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