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