]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/rastertopwg.c
Return error if we cannot allocate the compression buffer
[thirdparty/cups.git] / filter / rastertopwg.c
CommitLineData
07ed0e9a
MS
1/*
2 * "$Id$"
3 *
7e86f2f6 4 * CUPS raster to PWG raster format filter for CUPS.
07ed0e9a 5 *
94d5dc48 6 * Copyright 2011, 2014-2015 Apple Inc.
07ed0e9a 7 *
7e86f2f6
MS
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/".
07ed0e9a 13 *
7e86f2f6 14 * This file is subject to the Apple OS-Developed Software exception.
07ed0e9a
MS
15 */
16
17/*
18 * Include necessary headers...
19 */
20
10ddcf65 21#include <cups/cups-private.h>
07ed0e9a 22#include <cups/raster.h>
07ed0e9a
MS
23#include <unistd.h>
24#include <fcntl.h>
25
26
27/*
28 * 'main()' - Main entry for filter.
29 */
30
31int /* O - Exit status */
32main(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 */
7e86f2f6 40 unsigned y; /* Current line */
07ed0e9a 41 unsigned char *line; /* Line buffer */
7e86f2f6 42 unsigned page = 0, /* Current page */
07ed0e9a
MS
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 */
10ddcf65
MS
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 */
07ed0e9a
MS
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
10ddcf65
MS
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
07ed0e9a
MS
90 while (cupsRasterReadHeader2(inras, &inheader))
91 {
92 /*
93 * Compute the real raster size...
94 */
95
96 page ++;
97
98 fprintf(stderr, "PAGE: %d %d\n", page, inheader.NumCopies);
99
7e86f2f6
MS
100 page_width = (unsigned)(inheader.cupsPageSize[0] * inheader.HWResolution[0] / 72.0);
101 page_height = (unsigned)(inheader.cupsPageSize[1] * inheader.HWResolution[1] / 72.0);
102 page_left = (unsigned)(inheader.cupsImagingBBox[0] * inheader.HWResolution[0] / 72.0);
103 page_bottom = (unsigned)(inheader.cupsImagingBBox[1] * inheader.HWResolution[1] / 72.0);
07ed0e9a
MS
104 page_top = page_height - page_bottom - inheader.cupsHeight;
105 linesize = (page_width * inheader.cupsBitsPerPixel + 7) / 8;
106 lineoffset = page_left * inheader.cupsBitsPerPixel / 8; /* Round down */
107
f4332376
MS
108 if (page_left > page_width || page_top > page_height || page_bottom > page_height)
109 {
110 _cupsLangPrintFilter(stderr, "ERROR", _("Unsupported raster data."));
111 fprintf(stderr, "DEBUG: Bad bottom/left/top margin on page %d.\n", page);
112 return (1);
113 }
114
07ed0e9a
MS
115 switch (inheader.cupsColorSpace)
116 {
117 case CUPS_CSPACE_W :
118 case CUPS_CSPACE_RGB :
119 case CUPS_CSPACE_SW :
120 case CUPS_CSPACE_SRGB :
121 case CUPS_CSPACE_ADOBERGB :
122 white = 255;
123 break;
124
125 case CUPS_CSPACE_K :
126 case CUPS_CSPACE_CMYK :
127 case CUPS_CSPACE_DEVICE1 :
128 case CUPS_CSPACE_DEVICE2 :
129 case CUPS_CSPACE_DEVICE3 :
130 case CUPS_CSPACE_DEVICE4 :
131 case CUPS_CSPACE_DEVICE5 :
132 case CUPS_CSPACE_DEVICE6 :
133 case CUPS_CSPACE_DEVICE7 :
134 case CUPS_CSPACE_DEVICE8 :
135 case CUPS_CSPACE_DEVICE9 :
136 case CUPS_CSPACE_DEVICEA :
137 case CUPS_CSPACE_DEVICEB :
138 case CUPS_CSPACE_DEVICEC :
139 case CUPS_CSPACE_DEVICED :
140 case CUPS_CSPACE_DEVICEE :
141 case CUPS_CSPACE_DEVICEF :
142 white = 0;
143 break;
10ddcf65 144
07ed0e9a
MS
145 default :
146 _cupsLangPrintFilter(stderr, "ERROR", _("Unsupported raster data."));
147 fprintf(stderr, "DEBUG: Unsupported cupsColorSpace %d on page %d.\n",
148 inheader.cupsColorSpace, page);
149 return (1);
150 }
151
152 if (inheader.cupsColorOrder != CUPS_ORDER_CHUNKED)
153 {
154 _cupsLangPrintFilter(stderr, "ERROR", _("Unsupported raster data."));
155 fprintf(stderr, "DEBUG: Unsupported cupsColorOrder %d on page %d.\n",
156 inheader.cupsColorOrder, page);
157 return (1);
158 }
159
160 if (inheader.cupsBitsPerPixel != 1 &&
161 inheader.cupsBitsPerColor != 8 && inheader.cupsBitsPerColor != 16)
162 {
163 _cupsLangPrintFilter(stderr, "ERROR", _("Unsupported raster data."));
164 fprintf(stderr, "DEBUG: Unsupported cupsBitsPerColor %d on page %d.\n",
165 inheader.cupsBitsPerColor, page);
166 return (1);
167 }
168
169 memcpy(&outheader, &inheader, sizeof(outheader));
10ddcf65 170 outheader.cupsWidth = page_width;
07ed0e9a
MS
171 outheader.cupsHeight = page_height;
172 outheader.cupsBytesPerLine = linesize;
173
10ddcf65
MS
174 outheader.cupsInteger[14] = 0; /* VendorIdentifier */
175 outheader.cupsInteger[15] = 0; /* VendorLength */
176
177 if ((val = cupsGetOption("print-content-optimize", num_options,
178 options)) != NULL)
179 {
180 if (!strcmp(val, "automatic"))
181 strlcpy(outheader.OutputType, "Automatic",
182 sizeof(outheader.OutputType));
183 else if (!strcmp(val, "graphics"))
184 strlcpy(outheader.OutputType, "Graphics", sizeof(outheader.OutputType));
185 else if (!strcmp(val, "photo"))
186 strlcpy(outheader.OutputType, "Photo", sizeof(outheader.OutputType));
187 else if (!strcmp(val, "text"))
188 strlcpy(outheader.OutputType, "Text", sizeof(outheader.OutputType));
189 else if (!strcmp(val, "text-and-graphics"))
190 strlcpy(outheader.OutputType, "TextAndGraphics",
191 sizeof(outheader.OutputType));
192 else
193 {
194 fprintf(stderr, "DEBUG: Unsupported print-content-type \"%s\".\n", val);
195 outheader.OutputType[0] = '\0';
196 }
197 }
198
199 if ((val = cupsGetOption("print-quality", num_options, options)) != NULL)
200 {
7e86f2f6 201 unsigned quality = (unsigned)atoi(val); /* print-quality value */
10ddcf65
MS
202
203 if (quality >= IPP_QUALITY_DRAFT && quality <= IPP_QUALITY_HIGH)
204 outheader.cupsInteger[8] = quality;
205 else
206 {
207 fprintf(stderr, "DEBUG: Unsupported print-quality %d.\n", quality);
208 outheader.cupsInteger[8] = 0;
209 }
210 }
211
212 if ((val = cupsGetOption("print-rendering-intent", num_options,
213 options)) != NULL)
214 {
215 if (!strcmp(val, "absolute"))
216 strlcpy(outheader.cupsRenderingIntent, "Absolute",
217 sizeof(outheader.cupsRenderingIntent));
218 else if (!strcmp(val, "automatic"))
219 strlcpy(outheader.cupsRenderingIntent, "Automatic",
220 sizeof(outheader.cupsRenderingIntent));
221 else if (!strcmp(val, "perceptual"))
222 strlcpy(outheader.cupsRenderingIntent, "Perceptual",
223 sizeof(outheader.cupsRenderingIntent));
224 else if (!strcmp(val, "relative"))
225 strlcpy(outheader.cupsRenderingIntent, "Relative",
226 sizeof(outheader.cupsRenderingIntent));
227 else if (!strcmp(val, "relative-bpc"))
228 strlcpy(outheader.cupsRenderingIntent, "RelativeBpc",
229 sizeof(outheader.cupsRenderingIntent));
230 else if (!strcmp(val, "saturation"))
231 strlcpy(outheader.cupsRenderingIntent, "Saturation",
232 sizeof(outheader.cupsRenderingIntent));
233 else
234 {
235 fprintf(stderr, "DEBUG: Unsupported print-rendering-intent \"%s\".\n",
236 val);
237 outheader.cupsRenderingIntent[0] = '\0';
238 }
239 }
240
241 if (inheader.cupsPageSizeName[0] &&
242 (pwg_size = _ppdCacheGetSize(cache, inheader.cupsPageSizeName)) != NULL)
243 {
244 strlcpy(outheader.cupsPageSizeName, pwg_size->map.pwg,
245 sizeof(outheader.cupsPageSizeName));
246 }
247 else
248 {
249 pwg_media = _pwgMediaForSize((int)(2540.0 * inheader.cupsPageSize[0] /
250 72.0),
251 (int)(2540.0 * inheader.cupsPageSize[1] /
252 72.0));
253
254 if (pwg_media)
255 strlcpy(outheader.cupsPageSizeName, pwg_media->pwg,
256 sizeof(outheader.cupsPageSizeName));
257 else
258 {
259 fprintf(stderr, "DEBUG: Unsupported PageSize %.2fx%.2f.\n",
260 inheader.cupsPageSize[0], inheader.cupsPageSize[1]);
261 outheader.cupsPageSizeName[0] = '\0';
262 }
263 }
264
265 if (inheader.Duplex && !(page & 1) &&
266 back && _cups_strcasecmp(back->value, "Normal"))
267 {
268 if (_cups_strcasecmp(back->value, "Flipped"))
269 {
270 if (inheader.Tumble)
271 {
7e86f2f6 272 outheader.cupsInteger[1] = ~0U;/* CrossFeedTransform */
10ddcf65
MS
273 outheader.cupsInteger[2] = 1; /* FeedTransform */
274
275 outheader.cupsInteger[3] = page_width - page_left -
276 inheader.cupsWidth;
277 /* ImageBoxLeft */
278 outheader.cupsInteger[4] = page_top;
279 /* ImageBoxTop */
280 outheader.cupsInteger[5] = page_width - page_left;
281 /* ImageBoxRight */
282 outheader.cupsInteger[6] = page_height - page_bottom;
283 /* ImageBoxBottom */
284 }
285 else
286 {
287 outheader.cupsInteger[1] = 1; /* CrossFeedTransform */
7e86f2f6 288 outheader.cupsInteger[2] = ~0U;/* FeedTransform */
10ddcf65
MS
289
290 outheader.cupsInteger[3] = page_left;
291 /* ImageBoxLeft */
292 outheader.cupsInteger[4] = page_bottom;
293 /* ImageBoxTop */
294 outheader.cupsInteger[5] = page_left + inheader.cupsWidth;
295 /* ImageBoxRight */
296 outheader.cupsInteger[6] = page_height - page_top;
297 /* ImageBoxBottom */
298 }
299 }
300 else if (_cups_strcasecmp(back->value, "ManualTumble"))
301 {
302 if (inheader.Tumble)
303 {
7e86f2f6
MS
304 outheader.cupsInteger[1] = ~0U;/* CrossFeedTransform */
305 outheader.cupsInteger[2] = ~0U;/* FeedTransform */
10ddcf65
MS
306
307 outheader.cupsInteger[3] = page_width - page_left -
308 inheader.cupsWidth;
309 /* ImageBoxLeft */
310 outheader.cupsInteger[4] = page_bottom;
311 /* ImageBoxTop */
312 outheader.cupsInteger[5] = page_width - page_left;
313 /* ImageBoxRight */
314 outheader.cupsInteger[6] = page_height - page_top;
315 /* ImageBoxBottom */
316 }
317 else
318 {
319 outheader.cupsInteger[1] = 1; /* CrossFeedTransform */
320 outheader.cupsInteger[2] = 1; /* FeedTransform */
321
322 outheader.cupsInteger[3] = page_left;
323 /* ImageBoxLeft */
324 outheader.cupsInteger[4] = page_top;
325 /* ImageBoxTop */
326 outheader.cupsInteger[5] = page_left + inheader.cupsWidth;
327 /* ImageBoxRight */
328 outheader.cupsInteger[6] = page_height - page_bottom;
329 /* ImageBoxBottom */
330 }
331 }
332 else if (_cups_strcasecmp(back->value, "Rotated"))
333 {
334 if (inheader.Tumble)
335 {
7e86f2f6
MS
336 outheader.cupsInteger[1] = ~0U;/* CrossFeedTransform */
337 outheader.cupsInteger[2] = ~0U;/* FeedTransform */
10ddcf65
MS
338
339 outheader.cupsInteger[3] = page_width - page_left -
340 inheader.cupsWidth;
341 /* ImageBoxLeft */
342 outheader.cupsInteger[4] = page_bottom;
343 /* ImageBoxTop */
344 outheader.cupsInteger[5] = page_width - page_left;
345 /* ImageBoxRight */
346 outheader.cupsInteger[6] = page_height - page_top;
347 /* ImageBoxBottom */
348 }
349 else
350 {
351 outheader.cupsInteger[1] = 1; /* CrossFeedTransform */
352 outheader.cupsInteger[2] = 1; /* FeedTransform */
353
354 outheader.cupsInteger[3] = page_left;
355 /* ImageBoxLeft */
356 outheader.cupsInteger[4] = page_top;
357 /* ImageBoxTop */
358 outheader.cupsInteger[5] = page_left + inheader.cupsWidth;
359 /* ImageBoxRight */
360 outheader.cupsInteger[6] = page_height - page_bottom;
361 /* ImageBoxBottom */
362 }
363 }
364 else
365 {
366 /*
367 * Unsupported value...
368 */
369
370 fprintf(stderr, "DEBUG: Unsupported cupsBackSide \"%s\".\n", back->value);
371
372 outheader.cupsInteger[1] = 1; /* CrossFeedTransform */
373 outheader.cupsInteger[2] = 1; /* FeedTransform */
374
375 outheader.cupsInteger[3] = page_left;
376 /* ImageBoxLeft */
377 outheader.cupsInteger[4] = page_top;
378 /* ImageBoxTop */
379 outheader.cupsInteger[5] = page_left + inheader.cupsWidth;
380 /* ImageBoxRight */
381 outheader.cupsInteger[6] = page_height - page_bottom;
382 /* ImageBoxBottom */
383 }
384 }
385 else
386 {
387 outheader.cupsInteger[1] = 1; /* CrossFeedTransform */
388 outheader.cupsInteger[2] = 1; /* FeedTransform */
389
390 outheader.cupsInteger[3] = page_left;
391 /* ImageBoxLeft */
392 outheader.cupsInteger[4] = page_top;
393 /* ImageBoxTop */
394 outheader.cupsInteger[5] = page_left + inheader.cupsWidth;
395 /* ImageBoxRight */
396 outheader.cupsInteger[6] = page_height - page_bottom;
397 /* ImageBoxBottom */
398 }
399
07ed0e9a
MS
400 if (!cupsRasterWriteHeader2(outras, &outheader))
401 {
402 _cupsLangPrintFilter(stderr, "ERROR", _("Error sending raster data."));
403 fprintf(stderr, "DEBUG: Unable to write header for page %d.\n", page);
404 return (1);
405 }
406
407 /*
408 * Copy raster data...
409 */
410
94d5dc48
MS
411 if (linesize < inheader.cupsBytesPerLine)
412 linesize = inheader.cupsBytesPerLine;
413
07ed0e9a
MS
414 line = malloc(linesize);
415
416 memset(line, white, linesize);
417 for (y = page_top; y > 0; y --)
418 if (!cupsRasterWritePixels(outras, line, outheader.cupsBytesPerLine))
419 {
420 _cupsLangPrintFilter(stderr, "ERROR", _("Error sending raster data."));
421 fprintf(stderr, "DEBUG: Unable to write line %d for page %d.\n",
422 page_top - y + 1, page);
423 return (1);
424 }
425
426 for (y = inheader.cupsHeight; y > 0; y --)
427 {
c130ea1d
MS
428 if (cupsRasterReadPixels(inras, line + lineoffset, inheader.cupsBytesPerLine) != inheader.cupsBytesPerLine)
429 {
430 _cupsLangPrintFilter(stderr, "ERROR", _("Error reading raster data."));
431 fprintf(stderr, "DEBUG: Unable to read line %d for page %d.\n",
432 inheader.cupsHeight - y + page_top + 1, page);
433 return (1);
434 }
435
07ed0e9a
MS
436 if (!cupsRasterWritePixels(outras, line, outheader.cupsBytesPerLine))
437 {
438 _cupsLangPrintFilter(stderr, "ERROR", _("Error sending raster data."));
439 fprintf(stderr, "DEBUG: Unable to write line %d for page %d.\n",
440 inheader.cupsHeight - y + page_top + 1, page);
441 return (1);
442 }
443 }
444
445 memset(line, white, linesize);
771bd8cb 446 for (y = page_bottom; y > 0; y --)
07ed0e9a
MS
447 if (!cupsRasterWritePixels(outras, line, outheader.cupsBytesPerLine))
448 {
449 _cupsLangPrintFilter(stderr, "ERROR", _("Error sending raster data."));
450 fprintf(stderr, "DEBUG: Unable to write line %d for page %d.\n",
451 page_bottom - y + page_top + inheader.cupsHeight + 1, page);
452 return (1);
453 }
454
455 free(line);
456 }
457
458 cupsRasterClose(inras);
459 if (fd)
460 close(fd);
461
462 cupsRasterClose(outras);
463
464 return (0);
465}
466
467
468/*
469 * End of "$Id$".
470 */