1 /*
2 * Function to apply IPP options to a CUPS/PWG Raster header.
3 *
4 * Copyright 2013 by Till Kamppeter.
5 *
6 * Distribution and use rights are outlined in the file "COPYING"
7 * which should have been included with this file.
8 *
9 * Contents:
10 *
11 * cupsRasterParseIPPOptions() - Parse IPP options from the command line
12 * and apply them to the CUPS Raster header.
13 */
14
15 #include <config.h>
16 #include <cups/cups.h>
17 #include <cups/ppd.h>
18 #if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 6)
19 #define HAVE_CUPS_1_7 1
20 #endif
21
22 /*
23 * Include necessary headers.
24 */
25
26 #include "driver.h"
27 #include <string.h>
28 #include <ctype.h>
29 #ifdef HAVE_CUPS_1_7
30 #include <cups/pwg.h>
31 #endif /* HAVE_CUPS_1_7 */
32
33 /*
34 * '_strlcpy()' - Safely copy two strings.
35 */
36
37 size_t /* O - Length of string */
_strlcpy(char * dst,const char * src,size_t size)38 _strlcpy(char *dst, /* O - Destination string */
39 const char *src, /* I - Source string */
40 size_t size) /* I - Size of destination string buffer */
41 {
42 size_t srclen; /* Length of source string */
43
44
45 /*
46 * Figure out how much room is needed...
47 */
48
49 size --;
50
51 srclen = strlen(src);
52
53 /*
54 * Copy the appropriate amount...
55 */
56
57 if (srclen > size)
58 srclen = size;
59
60 memcpy(dst, src, srclen);
61 dst[srclen] = '\0';
62
63 return (srclen);
64 }
65
66 /*
67 * 'cupsRasterParseIPPOptions()' - Parse IPP options from the command line
68 * and apply them to the CUPS Raster header.
69 */
70
71 int /* O - -1 on error, 0 on success */
cupsRasterParseIPPOptions(cups_page_header2_t * h,int num_options,cups_option_t * options,int pwg_raster,int set_defaults)72 cupsRasterParseIPPOptions(cups_page_header2_t *h, /* I - Raster header */
73 int num_options, /* I - Number of options */
74 cups_option_t *options, /* I - Options */
75 int pwg_raster, /* I - 1 if PWG Raster */
76 int set_defaults) /* I - If 1, se default values
77 for all fields for which
78 we did not get an option */
79 {
80 #ifdef HAVE_CUPS_1_7
81 int i; /* Looping var */
82 char *ptr, /* Pointer into string */
83 s[255]; /* Temporary string */
84 const char *val, /* Pointer into value */
85 *media; /* media option */
86 char *page_size, /* PageSize option */
87 *media_source, /* Media source */
88 *media_type; /* Media type */
89 pwg_media_t *size_found; /* page size found for given name */
90 float size; /* page size dimension */
91 int num_non_ppd_options = 0;/* Number of options which are not
92 in the PPD */
93 cups_option_t *non_ppd_options = NULL;/* Options not in the PPD */
94 ppd_file_t *ppd = NULL;
95
96 /*
97 * Range check input...
98 */
99
100 if (!h)
101 return (-1);
102
103 /*
104 * If we have a PPD file (PPD environment variable), take it into
105 * account, by not parsing options which are in the PPD file here.
106 *
107 * They should get parsed and applied separately via the
108 * ppdRasterInterpretPPD() as that function parses the embedded
109 * PostScript code. This way weird things like Gutenprint's
110 * "Resolution" option (choice name is something odd, like
111 * 301x300dpi, and actual resolution can be completely different)
112 * will get treated correctly.
113 *
114 * We mark the option settings in the PPD and call
115 * ppdRasterInterpretPPD() only when we are called with set_defaults
116 * = 1. In any case we replace the option list we parse by a copy
117 * without the options of the PPD file.
118 */
119
120 ptr = getenv("PPD");
121 if (ptr && ptr[0] != '\0' && (ppd = ppdOpenFile(ptr)) != NULL)
122 {
123 if (set_defaults)
124 {
125 cupsMarkOptions(ppd, num_options, options);
126 cupsRasterInterpretPPD(h, ppd, num_options, options, NULL);
127 }
128 for (i = 0; i < num_options; i ++)
129 if (ppdFindOption(ppd, options[i].name) == NULL)
130 num_non_ppd_options =
131 cupsAddOption(options[i].name, options[i].value,
132 num_non_ppd_options, &non_ppd_options);
133 num_options = num_non_ppd_options;
134 options = non_ppd_options;
135 }
136
137 /*
138 * Check if the supplied "media" option is a comma-separated list of any
139 * combination of page size ("media"), media source ("media-position"),
140 * and media type ("media-type") and if so, put these list elements into
141 * their dedicated options.
142 */
143
144 page_size = NULL;
145 media_source = NULL;
146 media_type = NULL;
147 if ((media = cupsGetOption("media", num_options, options)) != NULL)
148 {
149 /*
150 * Loop through the option string, separating it at commas and marking each
151 * individual option as long as the corresponding PPD option (PageSize,
152 * InputSlot, etc.) is not also set.
153 *
154 * For PageSize, we also check for an empty option value since some versions
155 * of MacOS X use it to specify auto-selection of the media based solely on
156 * the size.
157 */
158
159 for (val = media; *val;)
160 {
161 /*
162 * Extract the sub-option from the string...
163 */
164
165 for (ptr = s; *val && *val != ',' && (ptr - s) < (sizeof(s) - 1);)
166 *ptr++ = *val++;
167 *ptr++ = '\0';
168
169 if (*val == ',')
170 val ++;
171
172 /*
173 * Identify it...
174 */
175
176 size_found = NULL;
177 if ((size_found = pwgMediaForPWG(s)) == NULL)
178 if ((size_found = pwgMediaForPPD(s)) == NULL)
179 if ((size_found = pwgMediaForPPD(s)) == NULL)
180 {
181 if (strcasestr(s, "tray") ||
182 strcasestr(s, "feed") ||
183 strcasestr(s, "capacity") ||
184 strcasestr(s, "upper") ||
185 strcasestr(s, "top") ||
186 strcasestr(s, "middle") ||
187 strcasestr(s, "lower") ||
188 strcasestr(s, "bottom") ||
189 strcasestr(s, "left") ||
190 strcasestr(s, "right") ||
191 strcasestr(s, "side") ||
192 strcasestr(s, "main"))
193 {
194 if (media_source == NULL)
195 media_source = strdup(s);
196 }
197 else
198 media_type = strdup(s);
199 }
200 if (page_size == NULL && size_found)
201 page_size = strdup(size_found->pwg);
202 }
203 }
204
205 if (pwg_raster)
206 strcpy(h->MediaClass, "PwgRaster");
207 else if ((val = cupsGetOption("media-class", num_options, options)) != NULL ||
208 (val = cupsGetOption("MediaClass", num_options, options)) != NULL)
209 _strlcpy(h->MediaClass, val, sizeof(h->MediaClass));
210 else if (set_defaults)
211 strcpy(h->MediaClass, "");
212
213 if ((val = cupsGetOption("media-color", num_options, options)) != NULL ||
214 (val = cupsGetOption("MediaColor", num_options, options)) != NULL)
215 _strlcpy(h->MediaColor, val, sizeof(h->MediaColor));
216 else if (set_defaults)
217 h->MediaColor[0] = '\0';
218
219 if ((val = cupsGetOption("media-type", num_options, options)) != NULL ||
220 (val = cupsGetOption("MediaType", num_options, options)) != NULL ||
221 (val = media_type) != NULL)
222 _strlcpy(h->MediaType, val, sizeof(h->MediaType));
223 else if (set_defaults)
224 h->MediaType[0] = '\0';
225
226 if ((val = cupsGetOption("print-content-optimize", num_options,
227 options)) != NULL ||
228 (val = cupsGetOption("output-type", num_options, options)) != NULL ||
229 (val = cupsGetOption("OutputType", num_options, options)) != NULL)
230 {
231 if (!strcasecmp(val, "automatic"))
232 _strlcpy(h->OutputType, "Automatic",
233 sizeof(h->OutputType));
234 else if (!strcasecmp(val, "graphics"))
235 _strlcpy(h->OutputType, "Graphics", sizeof(h->OutputType));
236 else if (!strcasecmp(val, "photo"))
237 _strlcpy(h->OutputType, "Photo", sizeof(h->OutputType));
238 else if (!strcasecmp(val, "text"))
239 _strlcpy(h->OutputType, "Text", sizeof(h->OutputType));
240 else if (!strcasecmp(val, "text-and-graphics") ||
241 !strcasecmp(val, "TextAndGraphics"))
242 _strlcpy(h->OutputType, "TextAndGraphics",
243 sizeof(h->OutputType));
244 else if (pwg_raster)
245 fprintf(stderr, "DEBUG: Unsupported print-content-type \"%s\".\n", val);
246 else
247 _strlcpy(h->OutputType, val, sizeof(h->OutputType));
248 }
249 else if (set_defaults)
250 _strlcpy(h->OutputType, "Automatic", sizeof(h->OutputType));
251
252 if (pwg_raster)
253 {
254 /* Set "reserved" fields to 0 */
255 h->AdvanceDistance = 0;
256 h->AdvanceMedia = CUPS_ADVANCE_NONE;
257 h->Collate = CUPS_FALSE;
258 }
259 else
260 {
261 /* TODO - Support for advance distance and advance media */
262 if (set_defaults)
263 {
264 h->AdvanceDistance = 0;
265 h->AdvanceMedia = CUPS_ADVANCE_NONE;
266 }
267 if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
268 (!strcasecmp(val, "true") || !strcasecmp(val, "on") ||
269 !strcasecmp(val, "yes")))
270 h->Collate = CUPS_TRUE;
271 else if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
272 (!strcasecmp(val, "false") || !strcasecmp(val, "off") ||
273 !strcasecmp(val, "no")))
274 h->Collate = CUPS_FALSE;
275 else if (set_defaults)
276 h->Collate = CUPS_FALSE;
277 }
278
279 if (set_defaults)
280 h->CutMedia = CUPS_CUT_NONE;
281
282 if (set_defaults)
283 h->Tumble = CUPS_FALSE;
284 if ((val = cupsGetOption("sides", num_options, options)) != NULL ||
285 (val = cupsGetOption("Duplex", num_options, options)) != NULL)
286 {
287 if (!strcasecmp(val, "None") || !strcasecmp(val, "Off") ||
288 !strcasecmp(val, "False") || !strcasecmp(val, "No") ||
289 !strcasecmp(val, "one-sided") || !strcasecmp(val, "OneSided"))
290 h->Duplex = CUPS_FALSE;
291 else if (!strcasecmp(val, "On") ||
292 !strcasecmp(val, "True") || !strcasecmp(val, "Yes") ||
293 !strncasecmp(val, "two-sided", 9) ||
294 !strncasecmp(val, "TwoSided", 8) ||
295 !strncasecmp(val, "Duplex", 6))
296 {
297 h->Duplex = CUPS_TRUE;
298 if (!strncasecmp(val, "DuplexTumble", 12))
299 h->Tumble = CUPS_TRUE;
300 if (!strncasecmp(val, "DuplexNoTumble", 12))
301 h->Tumble = CUPS_FALSE;
302 }
303 else if (set_defaults)
304 h->Duplex = CUPS_FALSE;
305 }
306 else if (set_defaults)
307 h->Duplex = CUPS_FALSE;
308
309 if ((val = cupsGetOption("printer-resolution", num_options,
310 options)) != NULL ||
311 (val = cupsGetOption("Resolution", num_options, options)) != NULL)
312 {
313 int xres, /* X resolution */
314 yres; /* Y resolution */
315 char *ptr; /* Pointer into value */
316
317 xres = yres = strtol(val, (char **)&ptr, 10);
318 if (ptr > val && xres > 0)
319 {
320 if (*ptr == 'x')
321 yres = strtol(ptr + 1, (char **)&ptr, 10);
322 }
323
324 if (ptr <= val || xres <= 0 || yres <= 0 || !ptr ||
325 (*ptr != '\0' &&
326 strcasecmp(ptr, "dpi") &&
327 strcasecmp(ptr, "dpc") &&
328 strcasecmp(ptr, "dpcm")))
329 {
330 fprintf(stderr, "DEBUG: Bad resolution value \"%s\".\n", val);
331 if (set_defaults)
332 {
333 h->HWResolution[0] = 600;
334 h->HWResolution[1] = 600;
335 }
336 }
337 else
338 {
339 if (!strcasecmp(ptr, "dpc") ||
340 !strcasecmp(ptr, "dpcm"))
341 {
342 xres = xres * 254 / 100;
343 yres = yres * 254 / 100;
344 }
345 h->HWResolution[0] = xres;
346 h->HWResolution[1] = yres;
347 }
348 }
349 else if (set_defaults)
350 {
351 h->HWResolution[0] = 600;
352 h->HWResolution[1] = 600;
353 }
354
355 if (set_defaults)
356 {
357 /* TODO - Support for insert sheets */
358 h->InsertSheet = CUPS_FALSE;
359 }
360
361 if (set_defaults)
362 {
363 /* TODO - Support for jog */
364 h->Jog = CUPS_JOG_NONE;
365 }
366
367 if ((val = cupsGetOption("feed-orientation", num_options,
368 options)) != NULL ||
369 (val = cupsGetOption("feed-direction", num_options, options)) != NULL ||
370 (val = cupsGetOption("LeadingEdge", num_options, options)) != NULL)
371 {
372 if (!strcasecmp(val, "ShortEdgeFirst"))
373 h->LeadingEdge = CUPS_EDGE_TOP;
374 else if (!strcasecmp(val, "LongEdgeFirst"))
375 h->LeadingEdge = CUPS_EDGE_RIGHT;
376 else
377 fprintf(stderr, "DEBUG: Unsupported feed-orientation \"%s\".\n", val);
378 }
379 else if (set_defaults)
380 h->LeadingEdge = CUPS_EDGE_TOP;
381
382 if (pwg_raster || set_defaults)
383 {
384 /* TODO - Support for manual feed */
385 h->ManualFeed = CUPS_FALSE;
386 }
387
388 if ((val = cupsGetOption("media-position", num_options, options)) != NULL ||
389 (val = cupsGetOption("MediaPosition", num_options, options)) != NULL ||
390 (val = cupsGetOption("media-source", num_options, options)) != NULL ||
391 (val = cupsGetOption("MediaSource", num_options, options)) != NULL ||
392 (val = cupsGetOption("InputSlot", num_options, options)) != NULL ||
393 (val = media_source) != NULL)
394 {
395 if (!strncasecmp(val, "Auto", 4) ||
396 !strncasecmp(val, "Default", 7))
397 h->MediaPosition = 0;
398 else if (!strcasecmp(val, "Main"))
399 h->MediaPosition = 1;
400 else if (!strcasecmp(val, "Alternate"))
401 h->MediaPosition = 2;
402 else if (!strcasecmp(val, "LargeCapacity"))
403 h->MediaPosition = 3;
404 else if (!strcasecmp(val, "Manual"))
405 h->MediaPosition = 4;
406 else if (!strcasecmp(val, "Envelope"))
407 h->MediaPosition = 5;
408 else if (!strcasecmp(val, "Disc"))
409 h->MediaPosition = 6;
410 else if (!strcasecmp(val, "Photo"))
411 h->MediaPosition = 7;
412 else if (!strcasecmp(val, "Hagaki"))
413 h->MediaPosition = 8;
414 else if (!strcasecmp(val, "MainRoll"))
415 h->MediaPosition = 9;
416 else if (!strcasecmp(val, "AlternateRoll"))
417 h->MediaPosition = 10;
418 else if (!strcasecmp(val, "Top"))
419 h->MediaPosition = 11;
420 else if (!strcasecmp(val, "Middle"))
421 h->MediaPosition = 12;
422 else if (!strcasecmp(val, "Bottom"))
423 h->MediaPosition = 13;
424 else if (!strcasecmp(val, "Side"))
425 h->MediaPosition = 14;
426 else if (!strcasecmp(val, "Left"))
427 h->MediaPosition = 15;
428 else if (!strcasecmp(val, "Right"))
429 h->MediaPosition = 16;
430 else if (!strcasecmp(val, "Center"))
431 h->MediaPosition = 17;
432 else if (!strcasecmp(val, "Rear"))
433 h->MediaPosition = 18;
434 else if (!strcasecmp(val, "ByPassTray"))
435 h->MediaPosition = 19;
436 else if (!strcasecmp(val, "Tray1"))
437 h->MediaPosition = 20;
438 else if (!strcasecmp(val, "Tray2"))
439 h->MediaPosition = 21;
440 else if (!strcasecmp(val, "Tray3"))
441 h->MediaPosition = 22;
442 else if (!strcasecmp(val, "Tray4"))
443 h->MediaPosition = 23;
444 else if (!strcasecmp(val, "Tray5"))
445 h->MediaPosition = 24;
446 else if (!strcasecmp(val, "Tray6"))
447 h->MediaPosition = 25;
448 else if (!strcasecmp(val, "Tray7"))
449 h->MediaPosition = 26;
450 else if (!strcasecmp(val, "Tray8"))
451 h->MediaPosition = 27;
452 else if (!strcasecmp(val, "Tray9"))
453 h->MediaPosition = 28;
454 else if (!strcasecmp(val, "Tray10"))
455 h->MediaPosition = 29;
456 else if (!strcasecmp(val, "Tray11"))
457 h->MediaPosition = 30;
458 else if (!strcasecmp(val, "Tray12"))
459 h->MediaPosition = 31;
460 else if (!strcasecmp(val, "Tray13"))
461 h->MediaPosition = 32;
462 else if (!strcasecmp(val, "Tray14"))
463 h->MediaPosition = 33;
464 else if (!strcasecmp(val, "Tray15"))
465 h->MediaPosition = 34;
466 else if (!strcasecmp(val, "Tray16"))
467 h->MediaPosition = 35;
468 else if (!strcasecmp(val, "Tray17"))
469 h->MediaPosition = 36;
470 else if (!strcasecmp(val, "Tray18"))
471 h->MediaPosition = 37;
472 else if (!strcasecmp(val, "Tray19"))
473 h->MediaPosition = 38;
474 else if (!strcasecmp(val, "Tray20"))
475 h->MediaPosition = 39;
476 else if (!strcasecmp(val, "Roll1"))
477 h->MediaPosition = 40;
478 else if (!strcasecmp(val, "Roll2"))
479 h->MediaPosition = 41;
480 else if (!strcasecmp(val, "Roll3"))
481 h->MediaPosition = 42;
482 else if (!strcasecmp(val, "Roll4"))
483 h->MediaPosition = 43;
484 else if (!strcasecmp(val, "Roll5"))
485 h->MediaPosition = 44;
486 else if (!strcasecmp(val, "Roll6"))
487 h->MediaPosition = 45;
488 else if (!strcasecmp(val, "Roll7"))
489 h->MediaPosition = 46;
490 else if (!strcasecmp(val, "Roll8"))
491 h->MediaPosition = 47;
492 else if (!strcasecmp(val, "Roll9"))
493 h->MediaPosition = 48;
494 else if (!strcasecmp(val, "Roll10"))
495 h->MediaPosition = 49;
496 else
497 fprintf(stderr, "DEBUG: Unsupported media source \"%s\".\n", val);
498 }
499 else if (set_defaults)
500 h->MediaPosition = 0; /* Auto */
501
502 if ((val = cupsGetOption("media-weight", num_options, options)) != NULL ||
503 (val = cupsGetOption("MediaWeight", num_options, options)) != NULL ||
504 (val = cupsGetOption("media-weight-metric", num_options,
505 options)) != NULL ||
506 (val = cupsGetOption("MediaWeightMetric", num_options, options)) != NULL)
507 h->MediaWeight = atol(val);
508 else if (set_defaults)
509 h->MediaWeight = 0;
510
511 if (pwg_raster)
512 {
513 /* Set "reserved" fields to 0 */
514 h->MirrorPrint = CUPS_FALSE;
515 h->NegativePrint = CUPS_FALSE;
516 }
517 else
518 {
519 if ((val = cupsGetOption("mirror-print", num_options, options)) != NULL ||
520 (val = cupsGetOption("MirrorPrint", num_options, options)) != NULL)
521 {
522 if (!strcasecmp(val, "true") || !strcasecmp(val, "on") ||
523 !strcasecmp(val, "yes"))
524 h->MirrorPrint = CUPS_TRUE;
525 else if (!strcasecmp(val, "false") ||
526 !strcasecmp(val, "off") ||
527 !strcasecmp(val, "no"))
528 h->MirrorPrint = CUPS_FALSE;
529 else if (set_defaults)
530 h->MirrorPrint = CUPS_FALSE;
531 }
532 if ((val = cupsGetOption("negative-print", num_options, options)) != NULL ||
533 (val = cupsGetOption("NegativePrint", num_options, options)) != NULL)
534 {
535 if (!strcasecmp(val, "true") || !strcasecmp(val, "on") ||
536 !strcasecmp(val, "yes"))
537 h->NegativePrint = CUPS_TRUE;
538 else if (!strcasecmp(val, "false") ||
539 !strcasecmp(val, "off") ||
540 !strcasecmp(val, "no"))
541 h->NegativePrint = CUPS_FALSE;
542 else if (set_defaults)
543 h->NegativePrint = CUPS_FALSE;
544 }
545 }
546
547 if ((val = cupsGetOption("copies", num_options, options)) != NULL ||
548 (val = cupsGetOption("Copies", num_options, options)) != NULL ||
549 (val = cupsGetOption("num-copies", num_options, options)) != NULL ||
550 (val = cupsGetOption("NumCopies", num_options, options)) != NULL)
551 h->NumCopies = atol(val);
552 else if (set_defaults)
553 h->NumCopies = 1; /* 0 = Printer default */
554
555 if ((val = cupsGetOption("orientation-requested", num_options,
556 options)) != NULL ||
557 (val = cupsGetOption("OrientationRequested", num_options,
558 options)) != NULL ||
559 (val = cupsGetOption("Orientation", num_options, options)) != NULL)
560 {
561 if (!strcasecmp(val, "Portrait") ||
562 !strcasecmp(val, "3"))
563 h->Orientation = CUPS_ORIENT_0;
564 else if (!strcasecmp(val, "Landscape") ||
565 !strcasecmp(val, "4"))
566 h->Orientation = CUPS_ORIENT_90;
567 else if (!strcasecmp(val, "reverse-portrait") ||
568 !strcasecmp(val, "ReversePortrait") ||
569 !strcasecmp(val, "5"))
570 h->Orientation = CUPS_ORIENT_180;
571 else if (!strcasecmp(val, "reverse-landscape") ||
572 !strcasecmp(val, "ReverseLandscape") ||
573 !strcasecmp(val, "6"))
574 h->Orientation = CUPS_ORIENT_270;
575 else
576 fprintf(stderr, "DEBUG: Unsupported Orientation \"%s\".\n", val);
577 }
578 else if (set_defaults)
579 h->Orientation = CUPS_ORIENT_0;
580
581 if (pwg_raster)
582 {
583 /* Set "reserved" fields to 0 */
584 h->OutputFaceUp = CUPS_FALSE;
585 }
586 else
587 {
588 if ((val = cupsGetOption("OutputFaceUp", num_options, options)) != NULL ||
589 (val = cupsGetOption("output-face-up", num_options, options)) != NULL)
590 {
591 if (!strcasecmp(val, "true") || !strcasecmp(val, "on") ||
592 !strcasecmp(val, "yes"))
593 h->OutputFaceUp = CUPS_TRUE;
594 else if (!strcasecmp(val, "false") ||
595 !strcasecmp(val, "off") ||
596 !strcasecmp(val, "no"))
597 h->OutputFaceUp = CUPS_FALSE;
598 else if (set_defaults)
599 h->OutputFaceUp = CUPS_FALSE;
600 }
601 }
602
603 if ((val = cupsGetOption("media-size", num_options, options)) != NULL ||
604 (val = cupsGetOption("MediaSize", num_options, options)) != NULL ||
605 (val = cupsGetOption("page-size", num_options, options)) != NULL ||
606 (val = cupsGetOption("PageSize", num_options, options)) != NULL ||
607 (val = page_size) != NULL)
608 {
609 size_found = NULL;
610 if ((size_found = pwgMediaForPWG(val)) == NULL)
611 if ((size_found = pwgMediaForPPD(val)) == NULL)
612 size_found = pwgMediaForLegacy(val);
613 if (size_found != NULL)
614 {
615 h->PageSize[0] = size_found->width * 72 / 2540;
616 h->PageSize[1] = size_found->length * 72 / 2540;
617 _strlcpy(h->cupsPageSizeName, size_found->pwg,
618 sizeof(h->cupsPageSizeName));
619 if (pwg_raster)
620 {
621 h->cupsPageSize[0] = 0.0;
622 h->cupsPageSize[1] = 0.0;
623 }
624 else
625 {
626 h->cupsPageSize[0] = size_found->width * 72.0 / 2540.0;
627 h->cupsPageSize[1] = size_found->length * 72.0 / 2540.0;
628 }
629 }
630 else
631 fprintf(stderr, "DEBUG: Unsupported page size %s.\n", val);
632 }
633 else if (set_defaults)
634 {
635 /* TODO: Automatic A4/Letter, like in scheduler/conf.c in CUPS. */
636 h->cupsPageSize[0] = 612.0f;
637 h->cupsPageSize[1] = 792.0f;
638
639 h->PageSize[0] = 612;
640 h->PageSize[1] = 792;
641 _strlcpy(h->cupsPageSizeName, "na_letter_8.5x11in",
642 sizeof(h->cupsPageSizeName));
643 if (pwg_raster)
644 {
645 h->cupsPageSize[0] = 0.0;
646 h->cupsPageSize[1] = 0.0;
647 }
648 }
649 else if (pwg_raster)
650 {
651 h->cupsPageSize[0] = 0.0;
652 h->cupsPageSize[1] = 0.0;
653 }
654
655 if (pwg_raster)
656 {
657 /* Set "reserved" fields to 0 */
658 h->Margins[0] = 0;
659 h->Margins[1] = 0;
660 h->ImagingBoundingBox[0] = 0;
661 h->ImagingBoundingBox[1] = 0;
662 h->ImagingBoundingBox[2] = 0;
663 h->ImagingBoundingBox[3] = 0;
664 h->cupsImagingBBox[0] = 0.0;
665 h->cupsImagingBBox[1] = 0.0;
666 h->cupsImagingBBox[2] = 0.0;
667 h->cupsImagingBBox[3] = 0.0;
668 }
669 else
670 {
671 if ((val = cupsGetOption("media-left-margin", num_options, options))
672 != NULL)
673 {
674 size = atol(val) * 72.0 / 2540.0;
675 h->Margins[0] = (int)size;
676 h->ImagingBoundingBox[0] = (int)size;
677 h->cupsImagingBBox[0] = size;
678 }
679 else if (set_defaults)
680 {
681 h->Margins[0] = 0;
682 h->ImagingBoundingBox[0] = 0;
683 h->cupsImagingBBox[0] = 18.0f;
684 }
685 if ((val = cupsGetOption("media-bottom-margin", num_options, options))
686 != NULL)
687 {
688 size = atol(val) * 72.0 / 2540.0;
689 h->Margins[1] = (int)size;
690 h->ImagingBoundingBox[1] = (int)size;
691 h->cupsImagingBBox[1] = size;
692 }
693 else if (set_defaults)
694 {
695 h->Margins[1] = 0;
696 h->ImagingBoundingBox[1] = 0;
697 h->cupsImagingBBox[1] = 36.0f;
698 }
699 if ((val = cupsGetOption("media-right-margin", num_options, options))
700 != NULL)
701 {
702 size = atol(val) * 72.0 / 2540.0;
703 h->ImagingBoundingBox[2] = h->PageSize[0] - (int)size;
704 h->cupsImagingBBox[2] = h->cupsPageSize[0] - size;
705 }
706 else if (set_defaults)
707 {
708 h->ImagingBoundingBox[2] = h->PageSize[0];
709 h->cupsImagingBBox[2] = 594.0f;
710 }
711 if ((val = cupsGetOption("media-top-margin", num_options, options))
712 != NULL)
713 {
714 size = atol(val) * 72.0 / 2540.0;
715 h->ImagingBoundingBox[3] = h->PageSize[1] - (int)size;
716 h->cupsImagingBBox[3] = h->cupsPageSize[1] - size;
717 }
718 else if (set_defaults)
719 {
720 h->ImagingBoundingBox[3] = h->PageSize[1];
721 h->cupsImagingBBox[3] = 756.0f;
722 }
723 }
724
725 if (pwg_raster)
726 {
727 /* Set "reserved" fields to 0 */
728 h->Separations = CUPS_FALSE;
729 h->TraySwitch = CUPS_FALSE;
730 }
731 else
732 {
733 if ((val = cupsGetOption("separations", num_options, options)) != NULL ||
734 (val = cupsGetOption("Separations", num_options, options)) != NULL)
735 {
736 if (!strcasecmp(val, "true") || !strcasecmp(val, "on") ||
737 !strcasecmp(val, "yes"))
738 h->Separations = CUPS_TRUE;
739 else if (!strcasecmp(val, "false") ||
740 !strcasecmp(val, "off") ||
741 !strcasecmp(val, "no"))
742 h->Separations = CUPS_FALSE;
743 else if (set_defaults)
744 h->Separations = CUPS_FALSE;
745 }
746 if ((val = cupsGetOption("tray-switch", num_options, options)) != NULL ||
747 (val = cupsGetOption("TraySwitch", num_options, options)) != NULL)
748 {
749 if (!strcasecmp(val, "true") || !strcasecmp(val, "on") ||
750 !strcasecmp(val, "yes"))
751 h->TraySwitch = CUPS_TRUE;
752 else if (!strcasecmp(val, "false") ||
753 !strcasecmp(val, "off") ||
754 !strcasecmp(val, "no"))
755 h->TraySwitch = CUPS_FALSE;
756 else if (set_defaults)
757 h->TraySwitch = CUPS_FALSE;
758 }
759 }
760
761 if ((val = cupsGetOption("sides", num_options, options)) != NULL ||
762 (val = cupsGetOption("Tumble", num_options, options)) != NULL)
763 {
764 if (!strcasecmp(val, "None") || !strcasecmp(val, "Off") ||
765 !strcasecmp(val, "False") || !strcasecmp(val, "No") ||
766 !strcasecmp(val, "one-sided") || !strcasecmp(val, "OneSided") ||
767 !strcasecmp(val, "two-sided-long-edge") ||
768 !strcasecmp(val, "TwoSidedLongEdge") ||
769 !strcasecmp(val, "DuplexNoTumble"))
770 h->Tumble = CUPS_FALSE;
771 else if (!strcasecmp(val, "On") ||
772 !strcasecmp(val, "True") || !strcasecmp(val, "Yes") ||
773 !strcasecmp(val, "two-sided-short-edge") ||
774 !strcasecmp(val, "TwoSidedShortEdge") ||
775 !strcasecmp(val, "DuplexTumble"))
776 h->Tumble = CUPS_TRUE;
777 }
778
779 h->cupsWidth = h->HWResolution[0] * h->PageSize[0] / 72;
780 h->cupsHeight = h->HWResolution[1] * h->PageSize[1] / 72;
781
782 if (pwg_raster || set_defaults)
783 {
784 /* TODO - Support for MediaType number */
785 h->cupsMediaType = 0;
786 }
787
788 if ((val = cupsGetOption("pwg-raster-document-type", num_options,
789 options)) != NULL ||
790 (val = cupsGetOption("PwgRasterDocumentType", num_options,
791 options)) != NULL ||
792 (val = cupsGetOption("print-color-mode", num_options,
793 options)) != NULL ||
794 (val = cupsGetOption("PrintColorMode", num_options, options)) != NULL ||
795 (val = cupsGetOption("color-space", num_options, options)) != NULL ||
796 (val = cupsGetOption("ColorSpace", num_options, options)) != NULL ||
797 (val = cupsGetOption("color-model", num_options, options)) != NULL ||
798 (val = cupsGetOption("ColorModel", num_options, options)) != NULL)
799 {
800 int bitspercolor, /* Bits per color */
801 bitsperpixel, /* Bits per pixel */
802 colorspace, /* CUPS/PWG raster color space */
803 numcolors; /* Number of colorants */
804 const char *ptr; /* Pointer into value */
805
806 ptr = NULL;
807 numcolors = 0;
808 bitspercolor = 8;
809 if (!strncasecmp(val, "AdobeRgb", 8))
810 {
811 if (*(val + 8) == '_' || *(val + 8) == '-')
812 ptr = val + 9;
813 colorspace = 20;
814 numcolors = 3;
815 }
816 else if (!strncasecmp(val, "adobe-rgb", 9))
817 {
818 if (*(val + 9) == '_' || *(val + 9) == '-')
819 ptr = val + 10;
820 colorspace = 20;
821 numcolors = 3;
822 }
823 else if (!strcasecmp(val, "auto-monochrome"))
824 {
825 colorspace = 18;
826 numcolors = 1;
827 }
828 else if (!strcasecmp(val, "bi-level") ||
829 !strcasecmp(val, "process-bi-level"))
830 {
831 bitspercolor = 1;
832 colorspace = 3;
833 numcolors = 1;
834 }
835 else if (!strncasecmp(val, "Black", 5))
836 {
837 if (*(val + 5) == '_' || *(val + 5) == '-')
838 ptr = val + 6;
839 bitspercolor = 1;
840 colorspace = 3;
841 numcolors = 1;
842 }
843 else if (!strcasecmp(val, "process-monochrome"))
844 {
845 colorspace = 18;
846 numcolors = 1;
847 }
848 else if (!strncasecmp(val, "Monochrome", 10))
849 {
850 if (*(val + 10) == '_' || *(val + 10) == '-')
851 ptr = val + 11;
852 colorspace = 18;
853 numcolors = 1;
854 }
855 else if (!strncasecmp(val, "Mono", 4))
856 {
857 if (*(val + 4) == '_' || *(val + 4) == '-')
858 ptr = val + 5;
859 colorspace = 18;
860 numcolors = 1;
861 }
862 else if (!strcasecmp(val, "color"))
863 {
864 colorspace = 19;
865 numcolors = 3;
866 }
867 else if (!strncasecmp(val, "Cmyk", 4))
868 {
869 if (*(val + 4) == '_' || *(val + 4) == '-')
870 ptr = val + 5;
871 colorspace = 6;
872 numcolors = 4;
873 }
874 else if (!strncasecmp(val, "Cmy", 3))
875 {
876 if (*(val + 3) == '_' || *(val + 3) == '-')
877 ptr = val + 4;
878 colorspace = 4;
879 numcolors = 3;
880 }
881 else if (!strncasecmp(val, "Device", 6))
882 {
883 ptr = val + 6;
884 numcolors = strtol(ptr, (char **)&ptr, 10);
885 if (*ptr == '_' || *ptr == '-')
886 {
887 ptr ++;
888 colorspace = 47 + numcolors;
889 }
890 else
891 {
892 numcolors = 0;
893 ptr = NULL;
894 }
895 }
896 else if (!strncasecmp(val, "Sgray", 5))
897 {
898 if (*(val + 5) == '_' || *(val + 5) == '-')
899 ptr = val + 6;
900 colorspace = 18;
901 numcolors = 1;
902 }
903 else if (!strncasecmp(val, "Gray", 4))
904 {
905 if (*(val + 4) == '_' || *(val + 4) == '-')
906 ptr = val + 5;
907 colorspace = 18;
908 numcolors = 1;
909 }
910 else if (!strncasecmp(val, "Srgb", 4))
911 {
912 if (*(val + 4) == '_' || *(val + 4) == '-')
913 ptr = val + 5;
914 colorspace = 19;
915 numcolors = 3;
916 }
917 else if (!strncasecmp(val, "Rgbw", 4))
918 {
919 if (*(val + 4) == '_' || *(val + 4) == '-')
920 ptr = val + 5;
921 colorspace = 17;
922 numcolors = 4;
923 }
924 else if (!strncasecmp(val, "Rgb", 3))
925 {
926 if (*(val + 3) == '_' || *(val + 3) == '-')
927 ptr = val + 4;
928 colorspace = 1;
929 numcolors = 3;
930 }
931 else if (!strcasecmp(val, "auto"))
932 {
933 /* Let "auto" not look like an error */
934 if (set_defaults)
935 {
936 fprintf(stderr,
937 "DEBUG: \"Auto\" mode, using default RGB color space.\n");
938 colorspace = 19;
939 numcolors = 3;
940 }
941 }
942 if (numcolors > 0)
943 {
944 if (ptr)
945 bitspercolor = strtol(ptr, (char **)&ptr, 10);
946 bitsperpixel = bitspercolor * numcolors;
947 /* In 1-bit-per-color RGB modes we add a forth bit to each pixel
948 to align the pixels with bytes */
949 if (bitsperpixel == 3 &&
950 strcasestr(val, "Rgb"))
951 bitsperpixel = 4;
952 h->cupsBitsPerColor = bitspercolor;
953 h->cupsBitsPerPixel = bitsperpixel;
954 h->cupsColorSpace = colorspace;
955 h->cupsNumColors = numcolors;
956 }
957 else
958 {
959 fprintf(stderr, "DEBUG: Bad color space value \"%s\".\n", val);
960 if (set_defaults)
961 {
962 h->cupsBitsPerColor = 8;
963 h->cupsBitsPerPixel = 24;
964 h->cupsColorSpace = 19;
965 h->cupsNumColors = 3;
966 }
967 }
968 }
969 else if (set_defaults)
970 {
971 h->cupsBitsPerColor = 8;
972 h->cupsBitsPerPixel = 24;
973 h->cupsColorSpace = 19;
974 h->cupsNumColors = 3;
975 }
976
977 h->cupsBytesPerLine = (h->cupsWidth * h->cupsBitsPerPixel + 7) / 8;
978
979 if (pwg_raster || set_defaults)
980 {
981 /* TODO - Support for color orders 1 (banded) and 2 (planar) */
982 h->cupsColorOrder = 0;
983 }
984
985 if (pwg_raster || set_defaults)
986 {
987 /* TODO - Support for these parameters */
988 h->cupsCompression = 0;
989 h->cupsRowCount = 0;
990 h->cupsRowFeed = 0;
991 h->cupsRowStep = 0;
992 }
993
994 if (pwg_raster || set_defaults)
995 {
996 /* TODO - Support for cupsBorderlessScalingFactor */
997 h->cupsBorderlessScalingFactor = 0.0;
998 }
999
1000 if (pwg_raster || set_defaults)
1001 {
1002 /* TODO - Support for custom values in CUPS Raster mode */
1003 for (i = 0; i < 16; i ++)
1004 {
1005 h->cupsInteger[i] = 0;
1006 h->cupsReal[i] = 0.0;
1007 memset(h->cupsString[i], 0, 64);
1008 }
1009 }
1010
1011 if (pwg_raster)
1012 {
1013
1014 if ((val = cupsGetOption("job-impressions", num_options,
1015 options)) != NULL ||
1016 (val = cupsGetOption("JobImpressions", num_options, options)) != NULL ||
1017 (val = cupsGetOption("Impressions", num_options, options)) != NULL)
1018 {
1019 int impressions = atoi(val);
1020 if (impressions >= 0)
1021 h->cupsInteger[0] = impressions;
1022 }
1023
1024 if ((val = cupsGetOption("pwg-raster-document-sheet-back", num_options,
1025 options)) != NULL ||
1026 (val = cupsGetOption("PwgRasterDocumentSheetBack", num_options,
1027 options)) != NULL)
1028 {
1029 /* Set CrossFeedTransform and FeedTransform */
1030 if (h->Duplex == CUPS_FALSE)
1031 {
1032 h->cupsInteger[1] = 1;
1033 h->cupsInteger[2] = 1;
1034 }
1035 else if (h->Duplex == CUPS_TRUE)
1036 {
1037 if (h->Tumble == CUPS_FALSE)
1038 {
1039 if (!strcasecmp(val, "Flipped"))
1040 {
1041 h->cupsInteger[1] = 1;
1042 h->cupsInteger[2] = -1;
1043 }
1044 else if (!strncasecmp(val, "Manual", 6))
1045 {
1046 h->cupsInteger[1] = 1;
1047 h->cupsInteger[2] = 1;
1048 }
1049 else if (!strcasecmp(val, "Normal"))
1050 {
1051 h->cupsInteger[1] = 1;
1052 h->cupsInteger[2] = 1;
1053 }
1054 else if (!strcasecmp(val, "Rotated"))
1055 {
1056 h->cupsInteger[1] = -1;
1057 h->cupsInteger[2] = -1;
1058 }
1059 else
1060 {
1061 h->cupsInteger[1] = 1;
1062 h->cupsInteger[2] = 1;
1063 }
1064 }
1065 else
1066 {
1067 if (!strcasecmp(val, "Flipped"))
1068 {
1069 h->cupsInteger[1] = -1;
1070 h->cupsInteger[2] = 1;
1071 }
1072 else if (!strncasecmp(val, "Manual", 6))
1073 {
1074 h->cupsInteger[1] = -1;
1075 h->cupsInteger[2] = -1;
1076 }
1077 else if (!strcasecmp(val, "Normal"))
1078 {
1079 h->cupsInteger[1] = 1;
1080 h->cupsInteger[2] = 1;
1081 }
1082 else if (!strcasecmp(val, "Rotated"))
1083 {
1084 h->cupsInteger[1] = 1;
1085 h->cupsInteger[2] = 1;
1086 }
1087 else
1088 {
1089 h->cupsInteger[1] = 1;
1090 h->cupsInteger[2] = 1;
1091 }
1092 }
1093 }
1094 else
1095 {
1096 h->cupsInteger[1] = 1;
1097 h->cupsInteger[2] = 1;
1098 }
1099 }
1100 else
1101 {
1102 h->cupsInteger[1] = 1;
1103 h->cupsInteger[2] = 1;
1104 }
1105
1106 /* TODO - Support for ImageBoxLeft, ImageBoxTop, ImageBoxRight, and
1107 ImageBoxBottom (h->cupsInteger[3..6]), leave on 0 for now */
1108
1109 if ((val = cupsGetOption("alternate-primary", num_options,
1110 options)) != NULL ||
1111 (val = cupsGetOption("AlternatePrimary", num_options,
1112 options)) != NULL)
1113 {
1114 int alternateprimary = atoi(val); /* SRGB value for black
1115 pixels */
1116 h->cupsInteger[7] = alternateprimary;
1117 }
1118
1119 if ((val = cupsGetOption("print-quality", num_options, options)) != NULL ||
1120 (val = cupsGetOption("PrintQuality", num_options, options)) != NULL ||
1121 (val = cupsGetOption("Quality", num_options, options)) != NULL)
1122 {
1123 int quality = atoi(val); /* print-quality value */
1124
1125 if (!quality ||
1126 (quality >= IPP_QUALITY_DRAFT && quality <= IPP_QUALITY_HIGH))
1127 h->cupsInteger[8] = quality;
1128 else
1129 fprintf(stderr, "DEBUG: Unsupported print-quality %d.\n", quality);
1130 }
1131
1132 /* Leave "reserved" fields (h->cupsInteger[9..13]) on 0 */
1133
1134 if ((val = cupsGetOption("vendor-identifier", num_options,
1135 options)) != NULL ||
1136 (val = cupsGetOption("VendorIdentifier", num_options,
1137 options)) != NULL)
1138 {
1139 int vendorid = atoi(val); /* USB ID of manufacturer */
1140 h->cupsInteger[14] = vendorid;
1141 }
1142
1143 if ((val = cupsGetOption("vendor-length", num_options,
1144 options)) != NULL ||
1145 (val = cupsGetOption("VendorLength", num_options,
1146 options)) != NULL)
1147 {
1148 int vendorlength = atoi(val); /* How many bytes of vendor
1149 data? */
1150 if (vendorlength <= 1088)
1151 {
1152 h->cupsInteger[15] = vendorlength;
1153 if ((val = cupsGetOption("vendor-data", num_options,
1154 options)) != NULL ||
1155 (val = cupsGetOption("VendorData", num_options,
1156 options)) != NULL)
1157 /* TODO - How to enter binary data here? */
1158 _strlcpy((char *)&(h->cupsReal[0]), val, 1088);
1159 }
1160 }
1161 }
1162
1163 if (pwg_raster || set_defaults)
1164 {
1165 /* Set "reserved" fields to 0 */
1166 memset(h->cupsMarkerType, 0, 64);
1167 }
1168
1169 if ((val = cupsGetOption("print-rendering-intent", num_options,
1170 options)) != NULL ||
1171 (val = cupsGetOption("PrintRenderingIntent", num_options,
1172 options)) != NULL ||
1173 (val = cupsGetOption("RenderingIntent", num_options,
1174 options)) != NULL)
1175 {
1176 if (!strcmp(val, "absolute"))
1177 _strlcpy(h->cupsRenderingIntent, "Absolute",
1178 sizeof(h->cupsRenderingIntent));
1179 else if (!strcmp(val, "automatic"))
1180 _strlcpy(h->cupsRenderingIntent, "Automatic",
1181 sizeof(h->cupsRenderingIntent));
1182 else if (!strcmp(val, "perceptual"))
1183 _strlcpy(h->cupsRenderingIntent, "Perceptual",
1184 sizeof(h->cupsRenderingIntent));
1185 else if (!strcmp(val, "relative"))
1186 _strlcpy(h->cupsRenderingIntent, "Relative",
1187 sizeof(h->cupsRenderingIntent));
1188 else if (!strcmp(val, "relative-bpc"))
1189 _strlcpy(h->cupsRenderingIntent, "RelativeBpc",
1190 sizeof(h->cupsRenderingIntent));
1191 else if (!strcmp(val, "saturation"))
1192 _strlcpy(h->cupsRenderingIntent, "Saturation",
1193 sizeof(h->cupsRenderingIntent));
1194 else
1195 fprintf(stderr, "DEBUG: Unsupported print-rendering-intent \"%s\".\n",
1196 val);
1197 }
1198 else if (set_defaults)
1199 h->cupsRenderingIntent[0] = '\0';
1200
1201 if (media_source != NULL)
1202 free(media_source);
1203 if (media_type != NULL)
1204 free(media_type);
1205 if (page_size != NULL)
1206 free(page_size);
1207 if (num_non_ppd_options)
1208 cupsFreeOptions(num_non_ppd_options, non_ppd_options);
1209 #endif /* HAVE_CUPS_1_7 */
1210
1211 return (0);
1212 }
1213
1214
1215 /*
1216 * End
1217 */
1218