4 * CUPS raster to PWG raster format filter for CUPS.
6 * Copyright 2011 Apple Inc.
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/".
14 * This file is subject to the Apple OS-Developed Software exception.
18 * main() - Main entry for filter.
22 * Include necessary headers...
25 #include <cups/cups-private.h>
26 #include <cups/raster.h>
32 * 'main()' - Main entry for filter.
35 int /* O - Exit status */
36 main(int argc
, /* I - Number of command-line args */
37 char *argv
[]) /* I - Command-line arguments */
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 */
65 if (argc
< 6 || argc
> 7)
67 puts("Usage: rastertopwg job user title copies options [filename]");
72 if ((fd
= open(argv
[6], O_RDONLY
)) < 0)
74 perror("ERROR: Unable to open print file");
81 inras
= cupsRasterOpen(fd
, CUPS_RASTER_READ
);
82 outras
= cupsRasterOpen(1, CUPS_RASTER_WRITE_PWG
);
84 ppd
= ppdOpenFile(getenv("PPD"));
85 back
= ppdFindAttr(ppd
, "cupsBackSide", NULL
);
87 num_options
= cupsParseOptions(argv
[5], 0, &options
);
90 cupsMarkOptions(ppd
, num_options
, options
);
92 cache
= ppd
? ppd
->cache
: NULL
;
94 while (cupsRasterReadHeader2(inras
, &inheader
))
97 * Compute the real raster size...
102 fprintf(stderr
, "PAGE: %d %d\n", page
, inheader
.NumCopies
);
104 page_width
= (int)(inheader
.cupsPageSize
[0] * inheader
.HWResolution
[0] /
106 page_height
= (int)(inheader
.cupsPageSize
[1] * inheader
.HWResolution
[1] /
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 */
116 switch (inheader
.cupsColorSpace
)
119 case CUPS_CSPACE_RGB
:
120 case CUPS_CSPACE_SW
:
121 case CUPS_CSPACE_SRGB
:
122 case CUPS_CSPACE_ADOBERGB
:
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
:
147 _cupsLangPrintFilter(stderr
, "ERROR", _("Unsupported raster data."));
148 fprintf(stderr
, "DEBUG: Unsupported cupsColorSpace %d on page %d.\n",
149 inheader
.cupsColorSpace
, page
);
153 if (inheader
.cupsColorOrder
!= CUPS_ORDER_CHUNKED
)
155 _cupsLangPrintFilter(stderr
, "ERROR", _("Unsupported raster data."));
156 fprintf(stderr
, "DEBUG: Unsupported cupsColorOrder %d on page %d.\n",
157 inheader
.cupsColorOrder
, page
);
161 if (inheader
.cupsBitsPerPixel
!= 1 &&
162 inheader
.cupsBitsPerColor
!= 8 && inheader
.cupsBitsPerColor
!= 16)
164 _cupsLangPrintFilter(stderr
, "ERROR", _("Unsupported raster data."));
165 fprintf(stderr
, "DEBUG: Unsupported cupsBitsPerColor %d on page %d.\n",
166 inheader
.cupsBitsPerColor
, page
);
170 memcpy(&outheader
, &inheader
, sizeof(outheader
));
171 outheader
.cupsWidth
= page_width
;
172 outheader
.cupsHeight
= page_height
;
173 outheader
.cupsBytesPerLine
= linesize
;
175 outheader
.cupsInteger
[14] = 0; /* VendorIdentifier */
176 outheader
.cupsInteger
[15] = 0; /* VendorLength */
178 if ((val
= cupsGetOption("print-content-optimize", num_options
,
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
));
195 fprintf(stderr
, "DEBUG: Unsupported print-content-type \"%s\".\n", val
);
196 outheader
.OutputType
[0] = '\0';
200 if ((val
= cupsGetOption("print-quality", num_options
, options
)) != NULL
)
202 int quality
= atoi(val
); /* print-quality value */
204 if (quality
>= IPP_QUALITY_DRAFT
&& quality
<= IPP_QUALITY_HIGH
)
205 outheader
.cupsInteger
[8] = quality
;
208 fprintf(stderr
, "DEBUG: Unsupported print-quality %d.\n", quality
);
209 outheader
.cupsInteger
[8] = 0;
213 if ((val
= cupsGetOption("print-rendering-intent", num_options
,
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
));
236 fprintf(stderr
, "DEBUG: Unsupported print-rendering-intent \"%s\".\n",
238 outheader
.cupsRenderingIntent
[0] = '\0';
242 if (inheader
.cupsPageSizeName
[0] &&
243 (pwg_size
= _ppdCacheGetSize(cache
, inheader
.cupsPageSizeName
)) != NULL
)
245 strlcpy(outheader
.cupsPageSizeName
, pwg_size
->map
.pwg
,
246 sizeof(outheader
.cupsPageSizeName
));
250 pwg_media
= _pwgMediaForSize((int)(2540.0 * inheader
.cupsPageSize
[0] /
252 (int)(2540.0 * inheader
.cupsPageSize
[1] /
256 strlcpy(outheader
.cupsPageSizeName
, pwg_media
->pwg
,
257 sizeof(outheader
.cupsPageSizeName
));
260 fprintf(stderr
, "DEBUG: Unsupported PageSize %.2fx%.2f.\n",
261 inheader
.cupsPageSize
[0], inheader
.cupsPageSize
[1]);
262 outheader
.cupsPageSizeName
[0] = '\0';
266 if (inheader
.Duplex
&& !(page
& 1) &&
267 back
&& _cups_strcasecmp(back
->value
, "Normal"))
269 if (_cups_strcasecmp(back
->value
, "Flipped"))
273 outheader
.cupsInteger
[1] = -1;/* CrossFeedTransform */
274 outheader
.cupsInteger
[2] = 1; /* FeedTransform */
276 outheader
.cupsInteger
[3] = page_width
- page_left
-
279 outheader
.cupsInteger
[4] = page_top
;
281 outheader
.cupsInteger
[5] = page_width
- page_left
;
283 outheader
.cupsInteger
[6] = page_height
- page_bottom
;
288 outheader
.cupsInteger
[1] = 1; /* CrossFeedTransform */
289 outheader
.cupsInteger
[2] = -1;/* FeedTransform */
291 outheader
.cupsInteger
[3] = page_left
;
293 outheader
.cupsInteger
[4] = page_bottom
;
295 outheader
.cupsInteger
[5] = page_left
+ inheader
.cupsWidth
;
297 outheader
.cupsInteger
[6] = page_height
- page_top
;
301 else if (_cups_strcasecmp(back
->value
, "ManualTumble"))
305 outheader
.cupsInteger
[1] = -1;/* CrossFeedTransform */
306 outheader
.cupsInteger
[2] = -1;/* FeedTransform */
308 outheader
.cupsInteger
[3] = page_width
- page_left
-
311 outheader
.cupsInteger
[4] = page_bottom
;
313 outheader
.cupsInteger
[5] = page_width
- page_left
;
315 outheader
.cupsInteger
[6] = page_height
- page_top
;
320 outheader
.cupsInteger
[1] = 1; /* CrossFeedTransform */
321 outheader
.cupsInteger
[2] = 1; /* FeedTransform */
323 outheader
.cupsInteger
[3] = page_left
;
325 outheader
.cupsInteger
[4] = page_top
;
327 outheader
.cupsInteger
[5] = page_left
+ inheader
.cupsWidth
;
329 outheader
.cupsInteger
[6] = page_height
- page_bottom
;
333 else if (_cups_strcasecmp(back
->value
, "Rotated"))
337 outheader
.cupsInteger
[1] = -1;/* CrossFeedTransform */
338 outheader
.cupsInteger
[2] = -1;/* FeedTransform */
340 outheader
.cupsInteger
[3] = page_width
- page_left
-
343 outheader
.cupsInteger
[4] = page_bottom
;
345 outheader
.cupsInteger
[5] = page_width
- page_left
;
347 outheader
.cupsInteger
[6] = page_height
- page_top
;
352 outheader
.cupsInteger
[1] = 1; /* CrossFeedTransform */
353 outheader
.cupsInteger
[2] = 1; /* FeedTransform */
355 outheader
.cupsInteger
[3] = page_left
;
357 outheader
.cupsInteger
[4] = page_top
;
359 outheader
.cupsInteger
[5] = page_left
+ inheader
.cupsWidth
;
361 outheader
.cupsInteger
[6] = page_height
- page_bottom
;
368 * Unsupported value...
371 fprintf(stderr
, "DEBUG: Unsupported cupsBackSide \"%s\".\n", back
->value
);
373 outheader
.cupsInteger
[1] = 1; /* CrossFeedTransform */
374 outheader
.cupsInteger
[2] = 1; /* FeedTransform */
376 outheader
.cupsInteger
[3] = page_left
;
378 outheader
.cupsInteger
[4] = page_top
;
380 outheader
.cupsInteger
[5] = page_left
+ inheader
.cupsWidth
;
382 outheader
.cupsInteger
[6] = page_height
- page_bottom
;
388 outheader
.cupsInteger
[1] = 1; /* CrossFeedTransform */
389 outheader
.cupsInteger
[2] = 1; /* FeedTransform */
391 outheader
.cupsInteger
[3] = page_left
;
393 outheader
.cupsInteger
[4] = page_top
;
395 outheader
.cupsInteger
[5] = page_left
+ inheader
.cupsWidth
;
397 outheader
.cupsInteger
[6] = page_height
- page_bottom
;
401 if (!cupsRasterWriteHeader2(outras
, &outheader
))
403 _cupsLangPrintFilter(stderr
, "ERROR", _("Error sending raster data."));
404 fprintf(stderr
, "DEBUG: Unable to write header for page %d.\n", page
);
409 * Copy raster data...
412 line
= malloc(linesize
);
414 memset(line
, white
, linesize
);
415 for (y
= page_top
; y
> 0; y
--)
416 if (!cupsRasterWritePixels(outras
, line
, outheader
.cupsBytesPerLine
))
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
);
424 for (y
= inheader
.cupsHeight
; y
> 0; y
--)
426 cupsRasterReadPixels(inras
, line
+ lineoffset
, inheader
.cupsBytesPerLine
);
427 if (!cupsRasterWritePixels(outras
, line
, outheader
.cupsBytesPerLine
))
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
);
436 memset(line
, white
, linesize
);
437 for (y
= page_bottom
; y
> 0; y
--)
438 if (!cupsRasterWritePixels(outras
, line
, outheader
.cupsBytesPerLine
))
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
);
449 cupsRasterClose(inras
);
453 cupsRasterClose(outras
);