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