Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
srohatgi01
GitHub Repository: srohatgi01/cups
Path: blob/master/filter/rastertopwg.c
1090 views
1
/*
2
* CUPS raster to PWG raster format filter for CUPS.
3
*
4
* Copyright © 2011, 2014-2017 Apple Inc.
5
*
6
* Licensed under Apache License v2.0. See the file "LICENSE" for more
7
* information.
8
*/
9
10
/*
11
* Include necessary headers...
12
*/
13
14
#include <cups/cups-private.h>
15
#include <cups/ppd-private.h>
16
#include <cups/raster.h>
17
#include <unistd.h>
18
#include <fcntl.h>
19
20
21
/*
22
* 'main()' - Main entry for filter.
23
*/
24
25
int /* O - Exit status */
26
main(int argc, /* I - Number of command-line args */
27
char *argv[]) /* I - Command-line arguments */
28
{
29
const char *final_content_type;
30
/* FINAL_CONTENT_TYPE env var */
31
int fd; /* Raster file */
32
cups_raster_t *inras, /* Input raster stream */
33
*outras; /* Output raster stream */
34
cups_page_header2_t inheader, /* Input raster page header */
35
outheader; /* Output raster page header */
36
unsigned y; /* Current line */
37
unsigned char *line; /* Line buffer */
38
unsigned page = 0, /* Current page */
39
page_width, /* Actual page width */
40
page_height, /* Actual page height */
41
page_top, /* Top margin */
42
page_bottom, /* Bottom margin */
43
page_left, /* Left margin */
44
page_right, /* Right margin */
45
linesize, /* Bytes per line */
46
lineoffset; /* Offset into line */
47
int tmp;
48
unsigned char white; /* White pixel */
49
ppd_file_t *ppd; /* PPD file */
50
ppd_attr_t *back; /* cupsBackSide attribute */
51
_ppd_cache_t *cache; /* PPD cache */
52
pwg_size_t *pwg_size; /* PWG media size */
53
pwg_media_t *pwg_media; /* PWG media name */
54
int num_options; /* Number of options */
55
cups_option_t *options = NULL;/* Options */
56
const char *val; /* Option value */
57
58
59
if (argc < 6 || argc > 7)
60
{
61
puts("Usage: rastertopwg job user title copies options [filename]");
62
return (1);
63
}
64
else if (argc == 7)
65
{
66
if ((fd = open(argv[6], O_RDONLY)) < 0)
67
{
68
perror("ERROR: Unable to open print file");
69
return (1);
70
}
71
}
72
else
73
fd = 0;
74
75
if ((final_content_type = getenv("FINAL_CONTENT_TYPE")) == NULL)
76
final_content_type = "image/pwg-raster";
77
78
inras = cupsRasterOpen(fd, CUPS_RASTER_READ);
79
outras = cupsRasterOpen(1, !strcmp(final_content_type, "image/pwg-raster") ? CUPS_RASTER_WRITE_PWG : CUPS_RASTER_WRITE_APPLE);
80
81
ppd = ppdOpenFile(getenv("PPD"));
82
back = ppdFindAttr(ppd, "cupsBackSide", NULL);
83
84
num_options = cupsParseOptions(argv[5], 0, &options);
85
86
ppdMarkDefaults(ppd);
87
cupsMarkOptions(ppd, num_options, options);
88
89
cache = ppd ? ppd->cache : NULL;
90
91
while (cupsRasterReadHeader2(inras, &inheader))
92
{
93
/*
94
* Show page device dictionary...
95
*/
96
97
fprintf(stderr, "DEBUG: Duplex = %d\n", inheader.Duplex);
98
fprintf(stderr, "DEBUG: HWResolution = [ %d %d ]\n", inheader.HWResolution[0], inheader.HWResolution[1]);
99
fprintf(stderr, "DEBUG: ImagingBoundingBox = [ %d %d %d %d ]\n", inheader.ImagingBoundingBox[0], inheader.ImagingBoundingBox[1], inheader.ImagingBoundingBox[2], inheader.ImagingBoundingBox[3]);
100
fprintf(stderr, "DEBUG: Margins = [ %d %d ]\n", inheader.Margins[0], inheader.Margins[1]);
101
fprintf(stderr, "DEBUG: ManualFeed = %d\n", inheader.ManualFeed);
102
fprintf(stderr, "DEBUG: MediaPosition = %d\n", inheader.MediaPosition);
103
fprintf(stderr, "DEBUG: NumCopies = %d\n", inheader.NumCopies);
104
fprintf(stderr, "DEBUG: Orientation = %d\n", inheader.Orientation);
105
fprintf(stderr, "DEBUG: PageSize = [ %d %d ]\n", inheader.PageSize[0], inheader.PageSize[1]);
106
fprintf(stderr, "DEBUG: cupsWidth = %d\n", inheader.cupsWidth);
107
fprintf(stderr, "DEBUG: cupsHeight = %d\n", inheader.cupsHeight);
108
fprintf(stderr, "DEBUG: cupsMediaType = %d\n", inheader.cupsMediaType);
109
fprintf(stderr, "DEBUG: cupsBitsPerColor = %d\n", inheader.cupsBitsPerColor);
110
fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d\n", inheader.cupsBitsPerPixel);
111
fprintf(stderr, "DEBUG: cupsBytesPerLine = %d\n", inheader.cupsBytesPerLine);
112
fprintf(stderr, "DEBUG: cupsColorOrder = %d\n", inheader.cupsColorOrder);
113
fprintf(stderr, "DEBUG: cupsColorSpace = %d\n", inheader.cupsColorSpace);
114
fprintf(stderr, "DEBUG: cupsCompression = %d\n", inheader.cupsCompression);
115
116
/*
117
* Compute the real raster size...
118
*/
119
120
page ++;
121
122
fprintf(stderr, "PAGE: %d %d\n", page, inheader.NumCopies);
123
124
page_width = (unsigned)(inheader.cupsPageSize[0] * inheader.HWResolution[0] / 72.0);
125
if (page_width < inheader.cupsWidth &&
126
page_width >= inheader.cupsWidth - 1)
127
page_width = (unsigned)inheader.cupsWidth;
128
page_height = (unsigned)(inheader.cupsPageSize[1] * inheader.HWResolution[1] / 72.0);
129
if (page_height < inheader.cupsHeight &&
130
page_height >= inheader.cupsHeight - 1)
131
page_height = (unsigned)inheader.cupsHeight;
132
page_left = (unsigned)(inheader.cupsImagingBBox[0] * inheader.HWResolution[0] / 72.0);
133
page_bottom = (unsigned)(inheader.cupsImagingBBox[1] * inheader.HWResolution[1] / 72.0);
134
tmp = (int)(page_height - page_bottom - inheader.cupsHeight);
135
if (tmp < 0 && tmp >= -1) /* Rounding error */
136
page_top = 0;
137
else
138
page_top = (unsigned)tmp;
139
tmp = (int)(page_width - page_left - inheader.cupsWidth);
140
if (tmp < 0 && tmp >= -1) /* Rounding error */
141
page_right = 0;
142
else
143
page_right = (unsigned)tmp;
144
linesize = (page_width * inheader.cupsBitsPerPixel + 7) / 8;
145
lineoffset = page_left * inheader.cupsBitsPerPixel / 8; /* Round down */
146
147
fprintf(stderr, "DEBUG: In pixels: Width: %u Height: %u Left: %u Right: %u Top: %u Bottom: %u\n", page_width, page_height, page_left, page_right, page_top, page_bottom);
148
if (page_left > page_width || page_top > page_height || page_bottom > page_height || page_right > page_width)
149
{
150
_cupsLangPrintFilter(stderr, "ERROR", _("Unsupported raster data."));
151
fprintf(stderr, "DEBUG: Bad bottom/left/top margin on page %d.\n", page);
152
return (1);
153
}
154
155
switch (inheader.cupsColorSpace)
156
{
157
case CUPS_CSPACE_W :
158
case CUPS_CSPACE_RGB :
159
case CUPS_CSPACE_SW :
160
case CUPS_CSPACE_SRGB :
161
case CUPS_CSPACE_ADOBERGB :
162
white = 255;
163
break;
164
165
case CUPS_CSPACE_K :
166
case CUPS_CSPACE_CMYK :
167
case CUPS_CSPACE_DEVICE1 :
168
case CUPS_CSPACE_DEVICE2 :
169
case CUPS_CSPACE_DEVICE3 :
170
case CUPS_CSPACE_DEVICE4 :
171
case CUPS_CSPACE_DEVICE5 :
172
case CUPS_CSPACE_DEVICE6 :
173
case CUPS_CSPACE_DEVICE7 :
174
case CUPS_CSPACE_DEVICE8 :
175
case CUPS_CSPACE_DEVICE9 :
176
case CUPS_CSPACE_DEVICEA :
177
case CUPS_CSPACE_DEVICEB :
178
case CUPS_CSPACE_DEVICEC :
179
case CUPS_CSPACE_DEVICED :
180
case CUPS_CSPACE_DEVICEE :
181
case CUPS_CSPACE_DEVICEF :
182
white = 0;
183
break;
184
185
default :
186
_cupsLangPrintFilter(stderr, "ERROR", _("Unsupported raster data."));
187
fprintf(stderr, "DEBUG: Unsupported cupsColorSpace %d on page %d.\n",
188
inheader.cupsColorSpace, page);
189
return (1);
190
}
191
192
if (inheader.cupsColorOrder != CUPS_ORDER_CHUNKED)
193
{
194
_cupsLangPrintFilter(stderr, "ERROR", _("Unsupported raster data."));
195
fprintf(stderr, "DEBUG: Unsupported cupsColorOrder %d on page %d.\n",
196
inheader.cupsColorOrder, page);
197
return (1);
198
}
199
200
if (inheader.cupsBitsPerPixel != 1 &&
201
inheader.cupsBitsPerColor != 8 && inheader.cupsBitsPerColor != 16)
202
{
203
_cupsLangPrintFilter(stderr, "ERROR", _("Unsupported raster data."));
204
fprintf(stderr, "DEBUG: Unsupported cupsBitsPerColor %d on page %d.\n",
205
inheader.cupsBitsPerColor, page);
206
return (1);
207
}
208
209
memcpy(&outheader, &inheader, sizeof(outheader));
210
outheader.cupsWidth = page_width;
211
outheader.cupsHeight = page_height;
212
outheader.cupsBytesPerLine = linesize;
213
214
outheader.cupsInteger[14] = 0; /* VendorIdentifier */
215
outheader.cupsInteger[15] = 0; /* VendorLength */
216
217
if ((val = cupsGetOption("print-content-optimize", num_options,
218
options)) != NULL)
219
{
220
if (!strcmp(val, "automatic"))
221
strlcpy(outheader.OutputType, "Automatic",
222
sizeof(outheader.OutputType));
223
else if (!strcmp(val, "graphics"))
224
strlcpy(outheader.OutputType, "Graphics", sizeof(outheader.OutputType));
225
else if (!strcmp(val, "photo"))
226
strlcpy(outheader.OutputType, "Photo", sizeof(outheader.OutputType));
227
else if (!strcmp(val, "text"))
228
strlcpy(outheader.OutputType, "Text", sizeof(outheader.OutputType));
229
else if (!strcmp(val, "text-and-graphics"))
230
strlcpy(outheader.OutputType, "TextAndGraphics",
231
sizeof(outheader.OutputType));
232
else
233
{
234
fputs("DEBUG: Unsupported print-content-optimize value.\n", stderr);
235
outheader.OutputType[0] = '\0';
236
}
237
}
238
239
if ((val = cupsGetOption("print-quality", num_options, options)) != NULL)
240
{
241
unsigned quality = (unsigned)atoi(val); /* print-quality value */
242
243
if (quality >= IPP_QUALITY_DRAFT && quality <= IPP_QUALITY_HIGH)
244
outheader.cupsInteger[8] = quality;
245
else
246
{
247
fprintf(stderr, "DEBUG: Unsupported print-quality %d.\n", quality);
248
outheader.cupsInteger[8] = 0;
249
}
250
}
251
252
if ((val = cupsGetOption("print-rendering-intent", num_options,
253
options)) != NULL)
254
{
255
if (!strcmp(val, "absolute"))
256
strlcpy(outheader.cupsRenderingIntent, "Absolute",
257
sizeof(outheader.cupsRenderingIntent));
258
else if (!strcmp(val, "automatic"))
259
strlcpy(outheader.cupsRenderingIntent, "Automatic",
260
sizeof(outheader.cupsRenderingIntent));
261
else if (!strcmp(val, "perceptual"))
262
strlcpy(outheader.cupsRenderingIntent, "Perceptual",
263
sizeof(outheader.cupsRenderingIntent));
264
else if (!strcmp(val, "relative"))
265
strlcpy(outheader.cupsRenderingIntent, "Relative",
266
sizeof(outheader.cupsRenderingIntent));
267
else if (!strcmp(val, "relative-bpc"))
268
strlcpy(outheader.cupsRenderingIntent, "RelativeBpc",
269
sizeof(outheader.cupsRenderingIntent));
270
else if (!strcmp(val, "saturation"))
271
strlcpy(outheader.cupsRenderingIntent, "Saturation",
272
sizeof(outheader.cupsRenderingIntent));
273
else
274
{
275
fputs("DEBUG: Unsupported print-rendering-intent value.\n", stderr);
276
outheader.cupsRenderingIntent[0] = '\0';
277
}
278
}
279
280
if (inheader.cupsPageSizeName[0] && (pwg_size = _ppdCacheGetSize(cache, inheader.cupsPageSizeName)) != NULL && pwg_size->map.pwg)
281
{
282
strlcpy(outheader.cupsPageSizeName, pwg_size->map.pwg,
283
sizeof(outheader.cupsPageSizeName));
284
}
285
else
286
{
287
pwg_media = pwgMediaForSize((int)(2540.0 * inheader.cupsPageSize[0] / 72.0),
288
(int)(2540.0 * inheader.cupsPageSize[1] / 72.0));
289
290
if (pwg_media)
291
strlcpy(outheader.cupsPageSizeName, pwg_media->pwg,
292
sizeof(outheader.cupsPageSizeName));
293
else
294
{
295
fprintf(stderr, "DEBUG: Unsupported PageSize %.2fx%.2f.\n",
296
inheader.cupsPageSize[0], inheader.cupsPageSize[1]);
297
outheader.cupsPageSizeName[0] = '\0';
298
}
299
}
300
301
if (inheader.Duplex && !(page & 1) &&
302
back && _cups_strcasecmp(back->value, "Normal"))
303
{
304
if (_cups_strcasecmp(back->value, "Flipped"))
305
{
306
if (inheader.Tumble)
307
{
308
outheader.cupsInteger[1] = ~0U;/* CrossFeedTransform */
309
outheader.cupsInteger[2] = 1; /* FeedTransform */
310
311
outheader.cupsInteger[3] = page_right;
312
/* ImageBoxLeft */
313
outheader.cupsInteger[4] = page_top;
314
/* ImageBoxTop */
315
outheader.cupsInteger[5] = page_width - page_left;
316
/* ImageBoxRight */
317
outheader.cupsInteger[6] = page_height - page_bottom;
318
/* ImageBoxBottom */
319
}
320
else
321
{
322
outheader.cupsInteger[1] = 1; /* CrossFeedTransform */
323
outheader.cupsInteger[2] = ~0U;/* FeedTransform */
324
325
outheader.cupsInteger[3] = page_left;
326
/* ImageBoxLeft */
327
outheader.cupsInteger[4] = page_bottom;
328
/* ImageBoxTop */
329
outheader.cupsInteger[5] = page_left + inheader.cupsWidth;
330
/* ImageBoxRight */
331
outheader.cupsInteger[6] = page_height - page_top;
332
/* ImageBoxBottom */
333
}
334
}
335
else if (_cups_strcasecmp(back->value, "ManualTumble"))
336
{
337
if (inheader.Tumble)
338
{
339
outheader.cupsInteger[1] = ~0U;/* CrossFeedTransform */
340
outheader.cupsInteger[2] = ~0U;/* FeedTransform */
341
342
outheader.cupsInteger[3] = page_width - page_left -
343
inheader.cupsWidth;
344
/* ImageBoxLeft */
345
outheader.cupsInteger[4] = page_bottom;
346
/* ImageBoxTop */
347
outheader.cupsInteger[5] = page_width - page_left;
348
/* ImageBoxRight */
349
outheader.cupsInteger[6] = page_height - page_top;
350
/* ImageBoxBottom */
351
}
352
else
353
{
354
outheader.cupsInteger[1] = 1; /* CrossFeedTransform */
355
outheader.cupsInteger[2] = 1; /* FeedTransform */
356
357
outheader.cupsInteger[3] = page_left;
358
/* ImageBoxLeft */
359
outheader.cupsInteger[4] = page_top;
360
/* ImageBoxTop */
361
outheader.cupsInteger[5] = page_left + inheader.cupsWidth;
362
/* ImageBoxRight */
363
outheader.cupsInteger[6] = page_height - page_bottom;
364
/* ImageBoxBottom */
365
}
366
}
367
else if (_cups_strcasecmp(back->value, "Rotated"))
368
{
369
if (inheader.Tumble)
370
{
371
outheader.cupsInteger[1] = ~0U;/* CrossFeedTransform */
372
outheader.cupsInteger[2] = ~0U;/* FeedTransform */
373
374
outheader.cupsInteger[3] = page_right;
375
/* ImageBoxLeft */
376
outheader.cupsInteger[4] = page_bottom;
377
/* ImageBoxTop */
378
outheader.cupsInteger[5] = page_width - page_left;
379
/* ImageBoxRight */
380
outheader.cupsInteger[6] = page_height - page_top;
381
/* ImageBoxBottom */
382
}
383
else
384
{
385
outheader.cupsInteger[1] = 1; /* CrossFeedTransform */
386
outheader.cupsInteger[2] = 1; /* FeedTransform */
387
388
outheader.cupsInteger[3] = page_left;
389
/* ImageBoxLeft */
390
outheader.cupsInteger[4] = page_top;
391
/* ImageBoxTop */
392
outheader.cupsInteger[5] = page_left + inheader.cupsWidth;
393
/* ImageBoxRight */
394
outheader.cupsInteger[6] = page_height - page_bottom;
395
/* ImageBoxBottom */
396
}
397
}
398
else
399
{
400
/*
401
* Unsupported value...
402
*/
403
404
fputs("DEBUG: Unsupported cupsBackSide value.\n", stderr);
405
406
outheader.cupsInteger[1] = 1; /* CrossFeedTransform */
407
outheader.cupsInteger[2] = 1; /* FeedTransform */
408
409
outheader.cupsInteger[3] = page_left;
410
/* ImageBoxLeft */
411
outheader.cupsInteger[4] = page_top;
412
/* ImageBoxTop */
413
outheader.cupsInteger[5] = page_left + inheader.cupsWidth;
414
/* ImageBoxRight */
415
outheader.cupsInteger[6] = page_height - page_bottom;
416
/* ImageBoxBottom */
417
}
418
}
419
else
420
{
421
outheader.cupsInteger[1] = 1; /* CrossFeedTransform */
422
outheader.cupsInteger[2] = 1; /* FeedTransform */
423
424
outheader.cupsInteger[3] = page_left;
425
/* ImageBoxLeft */
426
outheader.cupsInteger[4] = page_top;
427
/* ImageBoxTop */
428
outheader.cupsInteger[5] = page_left + inheader.cupsWidth;
429
/* ImageBoxRight */
430
outheader.cupsInteger[6] = page_height - page_bottom;
431
/* ImageBoxBottom */
432
}
433
434
if (!cupsRasterWriteHeader2(outras, &outheader))
435
{
436
_cupsLangPrintFilter(stderr, "ERROR", _("Error sending raster data."));
437
fprintf(stderr, "DEBUG: Unable to write header for page %d.\n", page);
438
return (1);
439
}
440
441
/*
442
* Copy raster data...
443
*/
444
445
if (linesize < inheader.cupsBytesPerLine)
446
linesize = inheader.cupsBytesPerLine;
447
448
if ((lineoffset + inheader.cupsBytesPerLine) > linesize)
449
lineoffset = linesize - inheader.cupsBytesPerLine;
450
451
line = malloc(linesize);
452
453
memset(line, white, linesize);
454
for (y = page_top; y > 0; y --)
455
if (!cupsRasterWritePixels(outras, line, outheader.cupsBytesPerLine))
456
{
457
_cupsLangPrintFilter(stderr, "ERROR", _("Error sending raster data."));
458
fprintf(stderr, "DEBUG: Unable to write line %d for page %d.\n",
459
page_top - y + 1, page);
460
return (1);
461
}
462
463
for (y = inheader.cupsHeight; y > 0; y --)
464
{
465
if (cupsRasterReadPixels(inras, line + lineoffset, inheader.cupsBytesPerLine) != inheader.cupsBytesPerLine)
466
{
467
_cupsLangPrintFilter(stderr, "ERROR", _("Error reading raster data."));
468
fprintf(stderr, "DEBUG: Unable to read line %d for page %d.\n",
469
inheader.cupsHeight - y + page_top + 1, page);
470
return (1);
471
}
472
473
if (!cupsRasterWritePixels(outras, line, outheader.cupsBytesPerLine))
474
{
475
_cupsLangPrintFilter(stderr, "ERROR", _("Error sending raster data."));
476
fprintf(stderr, "DEBUG: Unable to write line %d for page %d.\n",
477
inheader.cupsHeight - y + page_top + 1, page);
478
return (1);
479
}
480
}
481
482
memset(line, white, linesize);
483
for (y = page_bottom; y > 0; y --)
484
if (!cupsRasterWritePixels(outras, line, outheader.cupsBytesPerLine))
485
{
486
_cupsLangPrintFilter(stderr, "ERROR", _("Error sending raster data."));
487
fprintf(stderr, "DEBUG: Unable to write line %d for page %d.\n",
488
page_bottom - y + page_top + inheader.cupsHeight + 1, page);
489
return (1);
490
}
491
492
free(line);
493
}
494
495
cupsRasterClose(inras);
496
if (fd)
497
close(fd);
498
499
cupsRasterClose(outras);
500
501
return (0);
502
}
503
504