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