]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/interpret.c
Fix compile error.
[thirdparty/cups.git] / filter / interpret.c
CommitLineData
ef416fc2 1/*
f2d18633 2 * "$Id$"
ef416fc2 3 *
739a2093 4 * PPD command interpreter for CUPS.
ef416fc2 5 *
d9564ec7 6 * Copyright 2007-2015 by Apple Inc.
739a2093 7 * Copyright 1993-2007 by Easy Software Products.
ef416fc2 8 *
739a2093
MS
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 14 *
739a2093 15 * This file is subject to the Apple OS-Developed Software exception.
ef416fc2 16 */
17
18/*
19 * Include necessary headers...
20 */
21
a4845881 22#include <cups/raster-private.h>
ef416fc2 23
24
25/*
b86bc4cf 26 * Stack values for the PostScript mini-interpreter...
ef416fc2 27 */
28
b86bc4cf 29typedef enum
30{
31 CUPS_PS_NAME,
32 CUPS_PS_NUMBER,
33 CUPS_PS_STRING,
34 CUPS_PS_BOOLEAN,
35 CUPS_PS_NULL,
36 CUPS_PS_START_ARRAY,
37 CUPS_PS_END_ARRAY,
38 CUPS_PS_START_DICT,
39 CUPS_PS_END_DICT,
40 CUPS_PS_START_PROC,
41 CUPS_PS_END_PROC,
42 CUPS_PS_CLEARTOMARK,
43 CUPS_PS_COPY,
44 CUPS_PS_DUP,
45 CUPS_PS_INDEX,
46 CUPS_PS_POP,
47 CUPS_PS_ROLL,
48 CUPS_PS_SETPAGEDEVICE,
49 CUPS_PS_STOPPED,
50 CUPS_PS_OTHER
51} _cups_ps_type_t;
52
53typedef struct
54{
55 _cups_ps_type_t type; /* Object type */
56 union
57 {
58 int boolean; /* Boolean value */
59 char name[64]; /* Name value */
60 double number; /* Number value */
61 char other[64]; /* Other operator */
62 char string[64]; /* Sring value */
63 } value; /* Value */
64} _cups_ps_obj_t;
65
66typedef struct
67{
68 int num_objs, /* Number of objects on stack */
69 alloc_objs; /* Number of allocated objects */
70 _cups_ps_obj_t *objs; /* Objects in stack */
71} _cups_ps_stack_t;
ef416fc2 72
73
74/*
75 * Local functions...
76 */
77
b86bc4cf 78static int cleartomark_stack(_cups_ps_stack_t *st);
79static int copy_stack(_cups_ps_stack_t *st, int count);
80static void delete_stack(_cups_ps_stack_t *st);
f7deaa1a 81static void error_object(_cups_ps_obj_t *obj);
82static void error_stack(_cups_ps_stack_t *st, const char *title);
b86bc4cf 83static _cups_ps_obj_t *index_stack(_cups_ps_stack_t *st, int n);
84static _cups_ps_stack_t *new_stack(void);
85static _cups_ps_obj_t *pop_stack(_cups_ps_stack_t *st);
86static _cups_ps_obj_t *push_stack(_cups_ps_stack_t *st,
87 _cups_ps_obj_t *obj);
88static int roll_stack(_cups_ps_stack_t *st, int c, int s);
89static _cups_ps_obj_t *scan_ps(_cups_ps_stack_t *st, char **ptr);
90static int setpagedevice(_cups_ps_stack_t *st,
91 cups_page_header2_t *h,
92 int *preferred_bits);
93#ifdef DEBUG
d9564ec7
MS
94static void DEBUG_object(const char *prefix, _cups_ps_obj_t *obj);
95static void DEBUG_stack(const char *prefix, _cups_ps_stack_t *st);
b86bc4cf 96#endif /* DEBUG */
ef416fc2 97
98
99/*
100 * 'cupsRasterInterpretPPD()' - Interpret PPD commands to create a page header.
101 *
db0bd74a
MS
102 * This function is used by raster image processing (RIP) filters like
103 * cgpdftoraster and imagetoraster when writing CUPS raster data for a page.
104 * It is not used by raster printer driver filters which only read CUPS
105 * raster data.
106 *
107 *
108 * @code cupsRasterInterpretPPD@ does not mark the options in the PPD using
109 * the "num_options" and "options" arguments. Instead, mark the options with
110 * @code cupsMarkOptions@ and @code ppdMarkOption@ prior to calling it -
111 * this allows for per-page options without manipulating the options array.
923edb68 112 *
a74454a7 113 * The "func" argument specifies an optional callback function that is
114 * called prior to the computation of the final raster data. The function
5a738aea 115 * can make changes to the @link cups_page_header2_t@ data as needed to use a
a74454a7 116 * supported raster format and then returns 0 on success and -1 if the
117 * requested attributes cannot be supported.
118 *
db0bd74a 119 *
5a738aea
MS
120 * @code cupsRasterInterpretPPD@ supports a subset of the PostScript language.
121 * Currently only the @code [@, @code ]@, @code <<@, @code >>@, @code {@,
122 * @code }@, @code cleartomark@, @code copy@, @code dup@, @code index@,
123 * @code pop@, @code roll@, @code setpagedevice@, and @code stopped@ operators
124 * are supported.
b86bc4cf 125 *
f3c17241 126 * @since CUPS 1.2/OS X 10.5@
ef416fc2 127 */
128
129int /* O - 0 on success, -1 on failure */
130cupsRasterInterpretPPD(
db0bd74a 131 cups_page_header2_t *h, /* O - Page header to create */
923edb68 132 ppd_file_t *ppd, /* I - PPD file */
133 int num_options, /* I - Number of options */
a74454a7 134 cups_option_t *options, /* I - Options */
db0bd74a 135 cups_interpret_cb_t func) /* I - Optional page header callback (@code NULL@ for none) */
ef416fc2 136{
ef416fc2 137 int status; /* Cummulative status */
b86bc4cf 138 char *code; /* Code to run */
923edb68 139 const char *val; /* Option value */
ef416fc2 140 ppd_size_t *size; /* Current size */
141 float left, /* Left position */
142 bottom, /* Bottom position */
143 right, /* Right position */
739a2093
MS
144 top, /* Top position */
145 temp1, temp2; /* Temporary variables for swapping */
a74454a7 146 int preferred_bits; /* Preferred bits per color */
ef416fc2 147
148
149 /*
150 * Range check input...
151 */
152
f7deaa1a 153 _cupsRasterClearError();
154
ef416fc2 155 if (!h)
f7deaa1a 156 {
157 _cupsRasterAddError("Page header cannot be NULL!\n");
ef416fc2 158 return (-1);
f7deaa1a 159 }
ef416fc2 160
161 /*
162 * Reset the page header to the defaults...
163 */
164
165 memset(h, 0, sizeof(cups_page_header2_t));
166
923edb68 167 h->NumCopies = 1;
168 h->PageSize[0] = 612;
169 h->PageSize[1] = 792;
170 h->HWResolution[0] = 100;
171 h->HWResolution[1] = 100;
739a2093 172 h->cupsBitsPerColor = 1;
923edb68 173 h->cupsColorOrder = CUPS_ORDER_CHUNKED;
174 h->cupsColorSpace = CUPS_CSPACE_K;
175 h->cupsBorderlessScalingFactor = 1.0f;
176 h->cupsPageSize[0] = 612.0f;
177 h->cupsPageSize[1] = 792.0f;
178 h->cupsImagingBBox[0] = 0.0f;
179 h->cupsImagingBBox[1] = 0.0f;
180 h->cupsImagingBBox[2] = 612.0f;
181 h->cupsImagingBBox[3] = 792.0f;
fa73b229 182
5a9febac 183 strlcpy(h->cupsPageSizeName, "Letter", sizeof(h->cupsPageSizeName));
ef416fc2 184
e38f5e9c
MS
185#ifdef __APPLE__
186 /*
f3c17241 187 * cupsInteger0 is also used for the total page count on OS X; set an
e38f5e9c
MS
188 * uncommon default value so we can tell if the driver is using cupsInteger0.
189 */
190
191 h->cupsInteger[0] = 0x80000000;
192#endif /* __APPLE__ */
193
ef416fc2 194 /*
195 * Apply patches and options to the page header...
196 */
197
a74454a7 198 status = 0;
199 preferred_bits = 0;
ef416fc2 200
201 if (ppd)
202 {
203 /*
204 * Apply any patch code (used to override the defaults...)
205 */
206
207 if (ppd->patches)
b86bc4cf 208 status |= _cupsRasterExecPS(h, &preferred_bits, ppd->patches);
ef416fc2 209
210 /*
211 * Then apply printer options in the proper order...
212 */
213
b86bc4cf 214 if ((code = ppdEmitString(ppd, PPD_ORDER_DOCUMENT, 0.0)) != NULL)
ef416fc2 215 {
b86bc4cf 216 status |= _cupsRasterExecPS(h, &preferred_bits, code);
217 free(code);
ef416fc2 218 }
219
b86bc4cf 220 if ((code = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL)
ef416fc2 221 {
b86bc4cf 222 status |= _cupsRasterExecPS(h, &preferred_bits, code);
223 free(code);
ef416fc2 224 }
225
b86bc4cf 226 if ((code = ppdEmitString(ppd, PPD_ORDER_PROLOG, 0.0)) != NULL)
ef416fc2 227 {
b86bc4cf 228 status |= _cupsRasterExecPS(h, &preferred_bits, code);
229 free(code);
ef416fc2 230 }
231
b86bc4cf 232 if ((code = ppdEmitString(ppd, PPD_ORDER_PAGE, 0.0)) != NULL)
ef416fc2 233 {
b86bc4cf 234 status |= _cupsRasterExecPS(h, &preferred_bits, code);
235 free(code);
ef416fc2 236 }
237 }
238
923edb68 239 /*
240 * Allow option override for page scaling...
241 */
242
243 if ((val = cupsGetOption("cupsBorderlessScalingFactor", num_options,
244 options)) != NULL)
245 {
c8fef167 246 double sc = atof(val); /* Scale factor */
923edb68 247
06d4e77b 248 if (sc >= 0.1 && sc <= 2.0)
c8fef167 249 h->cupsBorderlessScalingFactor = (float)sc;
923edb68 250 }
251
ef416fc2 252 /*
253 * Get the margins for the current size...
254 */
255
256 if ((size = ppdPageSize(ppd, NULL)) != NULL)
257 {
258 /*
259 * Use the margins from the PPD file...
260 */
261
262 left = size->left;
263 bottom = size->bottom;
264 right = size->right;
265 top = size->top;
fa73b229 266
267 strlcpy(h->cupsPageSizeName, size->name, sizeof(h->cupsPageSizeName));
07725fee 268
269 h->cupsPageSize[0] = size->width;
270 h->cupsPageSize[1] = size->length;
ef416fc2 271 }
272 else
273 {
274 /*
275 * Use the default margins...
276 */
277
278 left = 0.0f;
279 bottom = 0.0f;
280 right = 612.0f;
281 top = 792.0f;
282 }
283
739a2093
MS
284 /*
285 * Handle orientation...
286 */
287
288 switch (h->Orientation)
289 {
290 case CUPS_ORIENT_0 :
291 default :
292 /* Do nothing */
293 break;
294
295 case CUPS_ORIENT_90 :
296 temp1 = h->cupsPageSize[0];
297 h->cupsPageSize[0] = h->cupsPageSize[1];
298 h->cupsPageSize[1] = temp1;
299
300 temp1 = left;
301 temp2 = right;
302 left = h->cupsPageSize[0] - top;
303 right = h->cupsPageSize[0] - bottom;
304 bottom = h->cupsPageSize[1] - temp1;
305 top = h->cupsPageSize[1] - temp2;
306 break;
307
308 case CUPS_ORIENT_180 :
309 temp1 = left;
310 temp2 = bottom;
311 left = h->cupsPageSize[0] - right;
312 right = h->cupsPageSize[0] - temp1;
313 bottom = h->cupsPageSize[1] - top;
314 top = h->cupsPageSize[1] - temp2;
315 break;
316
317 case CUPS_ORIENT_270 :
318 temp1 = h->cupsPageSize[0];
319 h->cupsPageSize[0] = h->cupsPageSize[1];
320 h->cupsPageSize[1] = temp1;
321
322 temp1 = left;
323 temp2 = right;
324 left = bottom;
325 right = top;
326 bottom = h->cupsPageSize[1] - temp2;
327 top = h->cupsPageSize[1] - temp1;
328 break;
329 }
330
355ddf41
MS
331 if (left > right)
332 {
333 temp1 = left;
334 left = right;
335 right = temp1;
336 }
337
338 if (bottom > top)
339 {
340 temp1 = bottom;
341 bottom = top;
342 top = temp1;
343 }
344
c8fef167
MS
345 h->PageSize[0] = (unsigned)(h->cupsPageSize[0] *
346 h->cupsBorderlessScalingFactor);
347 h->PageSize[1] = (unsigned)(h->cupsPageSize[1] *
348 h->cupsBorderlessScalingFactor);
349 h->Margins[0] = (unsigned)(left *
350 h->cupsBorderlessScalingFactor);
351 h->Margins[1] = (unsigned)(bottom *
352 h->cupsBorderlessScalingFactor);
353 h->ImagingBoundingBox[0] = (unsigned)(left *
354 h->cupsBorderlessScalingFactor);
355 h->ImagingBoundingBox[1] = (unsigned)(bottom *
356 h->cupsBorderlessScalingFactor);
357 h->ImagingBoundingBox[2] = (unsigned)(right *
358 h->cupsBorderlessScalingFactor);
359 h->ImagingBoundingBox[3] = (unsigned)(top *
360 h->cupsBorderlessScalingFactor);
361 h->cupsImagingBBox[0] = (float)left;
362 h->cupsImagingBBox[1] = (float)bottom;
363 h->cupsImagingBBox[2] = (float)right;
364 h->cupsImagingBBox[3] = (float)top;
ef416fc2 365
a74454a7 366 /*
367 * Use the callback to validate the page header...
368 */
369
370 if (func && (*func)(h, preferred_bits))
f7deaa1a 371 {
372 _cupsRasterAddError("Page header callback returned error.\n");
a74454a7 373 return (-1);
f7deaa1a 374 }
a74454a7 375
a9252913 376 /*
377 * Check parameters...
378 */
379
380 if (!h->HWResolution[0] || !h->HWResolution[1] ||
381 !h->PageSize[0] || !h->PageSize[1] ||
382 (h->cupsBitsPerColor != 1 && h->cupsBitsPerColor != 2 &&
383 h->cupsBitsPerColor != 4 && h->cupsBitsPerColor != 8 &&
384 h->cupsBitsPerColor != 16) ||
06d4e77b 385 h->cupsBorderlessScalingFactor < 0.1 ||
b86bc4cf 386 h->cupsBorderlessScalingFactor > 2.0)
f7deaa1a 387 {
388 _cupsRasterAddError("Page header uses unsupported values.\n");
a9252913 389 return (-1);
f7deaa1a 390 }
a9252913 391
ef416fc2 392 /*
393 * Compute the bitmap parameters...
394 */
395
7e86f2f6 396 h->cupsWidth = (unsigned)((right - left) * h->cupsBorderlessScalingFactor *
fa73b229 397 h->HWResolution[0] / 72.0f + 0.5f);
7e86f2f6 398 h->cupsHeight = (unsigned)((top - bottom) * h->cupsBorderlessScalingFactor *
fa73b229 399 h->HWResolution[1] / 72.0f + 0.5f);
ef416fc2 400
401 switch (h->cupsColorSpace)
402 {
403 case CUPS_CSPACE_W :
404 case CUPS_CSPACE_K :
405 case CUPS_CSPACE_WHITE :
406 case CUPS_CSPACE_GOLD :
407 case CUPS_CSPACE_SILVER :
88f9aafc 408 case CUPS_CSPACE_SW :
ef416fc2 409 h->cupsNumColors = 1;
410 h->cupsBitsPerPixel = h->cupsBitsPerColor;
411 break;
412
413 default :
414 /*
415 * Ensure that colorimetric colorspaces use at least 8 bits per
416 * component...
417 */
418
419 if (h->cupsColorSpace >= CUPS_CSPACE_CIEXYZ &&
420 h->cupsBitsPerColor < 8)
421 h->cupsBitsPerColor = 8;
422
423 /*
424 * Figure out the number of bits per pixel...
425 */
426
427 if (h->cupsColorOrder == CUPS_ORDER_CHUNKED)
428 {
429 if (h->cupsBitsPerColor >= 8)
430 h->cupsBitsPerPixel = h->cupsBitsPerColor * 3;
431 else
432 h->cupsBitsPerPixel = h->cupsBitsPerColor * 4;
433 }
434 else
435 h->cupsBitsPerPixel = h->cupsBitsPerColor;
436
437 h->cupsNumColors = 3;
438 break;
439
440 case CUPS_CSPACE_KCMYcm :
f301802f 441 if (h->cupsBitsPerColor == 1)
ef416fc2 442 {
443 if (h->cupsColorOrder == CUPS_ORDER_CHUNKED)
444 h->cupsBitsPerPixel = 8;
445 else
446 h->cupsBitsPerPixel = 1;
447
448 h->cupsNumColors = 6;
449 break;
450 }
451
452 /*
453 * Fall through to CMYK code...
454 */
455
456 case CUPS_CSPACE_RGBA :
a74454a7 457 case CUPS_CSPACE_RGBW :
ef416fc2 458 case CUPS_CSPACE_CMYK :
459 case CUPS_CSPACE_YMCK :
460 case CUPS_CSPACE_KCMY :
461 case CUPS_CSPACE_GMCK :
462 case CUPS_CSPACE_GMCS :
463 if (h->cupsColorOrder == CUPS_ORDER_CHUNKED)
464 h->cupsBitsPerPixel = h->cupsBitsPerColor * 4;
465 else
466 h->cupsBitsPerPixel = h->cupsBitsPerColor;
467
468 h->cupsNumColors = 4;
469 break;
88f9aafc
MS
470
471 case CUPS_CSPACE_DEVICE1 :
472 case CUPS_CSPACE_DEVICE2 :
473 case CUPS_CSPACE_DEVICE3 :
474 case CUPS_CSPACE_DEVICE4 :
475 case CUPS_CSPACE_DEVICE5 :
476 case CUPS_CSPACE_DEVICE6 :
477 case CUPS_CSPACE_DEVICE7 :
478 case CUPS_CSPACE_DEVICE8 :
479 case CUPS_CSPACE_DEVICE9 :
480 case CUPS_CSPACE_DEVICEA :
481 case CUPS_CSPACE_DEVICEB :
482 case CUPS_CSPACE_DEVICEC :
483 case CUPS_CSPACE_DEVICED :
484 case CUPS_CSPACE_DEVICEE :
485 case CUPS_CSPACE_DEVICEF :
486 h->cupsNumColors = h->cupsColorSpace - CUPS_CSPACE_DEVICE1 + 1;
487
488 if (h->cupsColorOrder == CUPS_ORDER_CHUNKED)
489 h->cupsBitsPerPixel = h->cupsBitsPerColor * h->cupsNumColors;
490 else
491 h->cupsBitsPerPixel = h->cupsBitsPerColor;
492 break;
ef416fc2 493 }
494
495 h->cupsBytesPerLine = (h->cupsBitsPerPixel * h->cupsWidth + 7) / 8;
496
497 if (h->cupsColorOrder == CUPS_ORDER_BANDED)
498 h->cupsBytesPerLine *= h->cupsNumColors;
499
500 return (status);
501}
502
503
504/*
b86bc4cf 505 * '_cupsRasterExecPS()' - Execute PostScript code to initialize a page header.
ef416fc2 506 */
507
b86bc4cf 508int /* O - 0 on success, -1 on error */
509_cupsRasterExecPS(
a74454a7 510 cups_page_header2_t *h, /* O - Page header */
511 int *preferred_bits,/* O - Preferred bits per color */
b86bc4cf 512 const char *code) /* I - PS code to execute */
ef416fc2 513{
b1564bae 514 int error = 0; /* Error condition? */
b86bc4cf 515 _cups_ps_stack_t *st; /* PostScript value stack */
516 _cups_ps_obj_t *obj; /* Object from top of stack */
517 char *codecopy, /* Copy of code */
518 *codeptr; /* Pointer into copy of code */
519
ef416fc2 520
b86bc4cf 521 DEBUG_printf(("_cupsRasterExecPS(h=%p, preferred_bits=%p, code=\"%s\")\n",
b1564bae 522 h, preferred_bits, code));
ef416fc2 523
524 /*
b86bc4cf 525 * Copy the PostScript code and create a stack...
ef416fc2 526 */
527
b86bc4cf 528 if ((codecopy = strdup(code)) == NULL)
f7deaa1a 529 {
530 _cupsRasterAddError("Unable to duplicate code string.\n");
b86bc4cf 531 return (-1);
f7deaa1a 532 }
b86bc4cf 533
534 if ((st = new_stack()) == NULL)
535 {
f7deaa1a 536 _cupsRasterAddError("Unable to create stack.\n");
b86bc4cf 537 free(codecopy);
ef416fc2 538 return (-1);
b86bc4cf 539 }
ef416fc2 540
541 /*
b86bc4cf 542 * Parse the PS string until we run out of data...
ef416fc2 543 */
544
b86bc4cf 545 codeptr = codecopy;
546
547 while ((obj = scan_ps(st, &codeptr)) != NULL)
ef416fc2 548 {
b86bc4cf 549#ifdef DEBUG
d9564ec7
MS
550 DEBUG_printf(("_cupsRasterExecPS: Stack (%d objects)", st->num_objs));
551 DEBUG_object("_cupsRasterExecPS", obj);
b86bc4cf 552#endif /* DEBUG */
553
554 switch (obj->type)
555 {
556 default :
557 /* Do nothing for regular values */
558 break;
559
560 case CUPS_PS_CLEARTOMARK :
561 pop_stack(st);
562
f7deaa1a 563 if (cleartomark_stack(st))
d9564ec7 564 _cupsRasterAddError("cleartomark: Stack underflow.\n");
b86bc4cf 565
566#ifdef DEBUG
d9564ec7
MS
567 DEBUG_puts("1_cupsRasterExecPS: dup");
568 DEBUG_stack("_cupsRasterExecPS", st);
b86bc4cf 569#endif /* DEBUG */
570 break;
571
572 case CUPS_PS_COPY :
573 pop_stack(st);
574 if ((obj = pop_stack(st)) != NULL)
575 {
576 copy_stack(st, (int)obj->value.number);
577
578#ifdef DEBUG
ae71f5de 579 DEBUG_puts("_cupsRasterExecPS: copy");
d9564ec7 580 DEBUG_stack("_cupsRasterExecPS", st);
b86bc4cf 581#endif /* DEBUG */
582 }
583 break;
584
585 case CUPS_PS_DUP :
586 pop_stack(st);
587 copy_stack(st, 1);
588
589#ifdef DEBUG
ae71f5de 590 DEBUG_puts("_cupsRasterExecPS: dup");
d9564ec7 591 DEBUG_stack("_cupsRasterExecPS", st);
b86bc4cf 592#endif /* DEBUG */
593 break;
594
595 case CUPS_PS_INDEX :
596 pop_stack(st);
597 if ((obj = pop_stack(st)) != NULL)
598 {
599 index_stack(st, (int)obj->value.number);
600
601#ifdef DEBUG
ae71f5de 602 DEBUG_puts("_cupsRasterExecPS: index");
d9564ec7 603 DEBUG_stack("_cupsRasterExecPS", st);
b86bc4cf 604#endif /* DEBUG */
605 }
606 break;
607
608 case CUPS_PS_POP :
609 pop_stack(st);
610 pop_stack(st);
611
612#ifdef DEBUG
ae71f5de 613 DEBUG_puts("_cupsRasterExecPS: pop");
d9564ec7 614 DEBUG_stack("_cupsRasterExecPS", st);
b86bc4cf 615#endif /* DEBUG */
616 break;
617
618 case CUPS_PS_ROLL :
619 pop_stack(st);
620 if ((obj = pop_stack(st)) != NULL)
621 {
622 int c; /* Count */
ef416fc2 623
ef416fc2 624
b86bc4cf 625 c = (int)obj->value.number;
626
627 if ((obj = pop_stack(st)) != NULL)
628 {
629 roll_stack(st, (int)obj->value.number, c);
630
631#ifdef DEBUG
ae71f5de 632 DEBUG_puts("_cupsRasterExecPS: roll");
d9564ec7 633 DEBUG_stack("_cupsRasterExecPS", st);
b86bc4cf 634#endif /* DEBUG */
635 }
636 }
637 break;
638
639 case CUPS_PS_SETPAGEDEVICE :
640 pop_stack(st);
641 setpagedevice(st, h, preferred_bits);
642
643#ifdef DEBUG
ae71f5de 644 DEBUG_puts("_cupsRasterExecPS: setpagedevice");
d9564ec7 645 DEBUG_stack("_cupsRasterExecPS", st);
b86bc4cf 646#endif /* DEBUG */
647 break;
648
649 case CUPS_PS_START_PROC :
650 case CUPS_PS_END_PROC :
651 case CUPS_PS_STOPPED :
652 pop_stack(st);
653 break;
654
655 case CUPS_PS_OTHER :
d9564ec7 656 _cupsRasterAddError("Unknown operator \"%s\".\n", obj->value.other);
b1564bae 657 error = 1;
d9564ec7 658 DEBUG_printf(("_cupsRasterExecPS: Unknown operator \"%s\".", obj->value.other));
b86bc4cf 659 break;
660 }
661
b1564bae 662 if (error)
ef416fc2 663 break;
b86bc4cf 664 }
665
666 /*
667 * Cleanup...
668 */
669
670 free(codecopy);
671
672 if (st->num_objs > 0)
673 {
f7deaa1a 674 error_stack(st, "Stack not empty:");
675
b86bc4cf 676#ifdef DEBUG
d9564ec7
MS
677 DEBUG_puts("_cupsRasterExecPS: Stack not empty");
678 DEBUG_stack("_cupsRasterExecPS", st);
b86bc4cf 679#endif /* DEBUG */
ef416fc2 680
b86bc4cf 681 delete_stack(st);
682
683 return (-1);
684 }
685
686 delete_stack(st);
687
688 /*
689 * Return success...
690 */
691
692 return (0);
693}
694
695
696/*
697 * 'cleartomark_stack()' - Clear to the last mark ([) on the stack.
698 */
699
700static int /* O - 0 on success, -1 on error */
701cleartomark_stack(_cups_ps_stack_t *st) /* I - Stack */
702{
703 _cups_ps_obj_t *obj; /* Current object on stack */
704
705
706 while ((obj = pop_stack(st)) != NULL)
707 if (obj->type == CUPS_PS_START_ARRAY)
708 break;
709
710 return (obj ? 0 : -1);
711}
712
713
714/*
715 * 'copy_stack()' - Copy the top N stack objects.
716 */
717
718static int /* O - 0 on success, -1 on error */
719copy_stack(_cups_ps_stack_t *st, /* I - Stack */
720 int c) /* I - Number of objects to copy */
721{
722 int n; /* Index */
723
724
725 if (c < 0)
726 return (-1);
727 else if (c == 0)
728 return (0);
729
730 if ((n = st->num_objs - c) < 0)
731 return (-1);
732
733 while (c > 0)
734 {
735 if (!push_stack(st, st->objs + n))
736 return (-1);
737
738 n ++;
739 c --;
740 }
741
742 return (0);
743}
744
745
746/*
747 * 'delete_stack()' - Free memory used by a stack.
748 */
749
750static void
751delete_stack(_cups_ps_stack_t *st) /* I - Stack */
752{
753 free(st->objs);
754 free(st);
755}
756
757
f7deaa1a 758/*
759 * 'error_object()' - Add an object's value to the current error message.
760 */
761
762static void
763error_object(_cups_ps_obj_t *obj) /* I - Object to add */
764{
765 switch (obj->type)
766 {
767 case CUPS_PS_NAME :
768 _cupsRasterAddError(" /%s", obj->value.name);
769 break;
770
771 case CUPS_PS_NUMBER :
772 _cupsRasterAddError(" %g", obj->value.number);
773 break;
774
775 case CUPS_PS_STRING :
776 _cupsRasterAddError(" (%s)", obj->value.string);
777 break;
778
779 case CUPS_PS_BOOLEAN :
780 if (obj->value.boolean)
781 _cupsRasterAddError(" true");
782 else
783 _cupsRasterAddError(" false");
784 break;
785
786 case CUPS_PS_NULL :
787 _cupsRasterAddError(" null");
788 break;
789
790 case CUPS_PS_START_ARRAY :
791 _cupsRasterAddError(" [");
792 break;
793
794 case CUPS_PS_END_ARRAY :
795 _cupsRasterAddError(" ]");
796 break;
797
798 case CUPS_PS_START_DICT :
799 _cupsRasterAddError(" <<");
800 break;
801
802 case CUPS_PS_END_DICT :
803 _cupsRasterAddError(" >>");
804 break;
805
806 case CUPS_PS_START_PROC :
807 _cupsRasterAddError(" {");
808 break;
809
810 case CUPS_PS_END_PROC :
811 _cupsRasterAddError(" }");
812 break;
813
814 case CUPS_PS_COPY :
815 _cupsRasterAddError(" --copy--");
816 break;
817
818 case CUPS_PS_CLEARTOMARK :
819 _cupsRasterAddError(" --cleartomark--");
820 break;
821
822 case CUPS_PS_DUP :
823 _cupsRasterAddError(" --dup--");
824 break;
825
826 case CUPS_PS_INDEX :
827 _cupsRasterAddError(" --index--");
828 break;
829
830 case CUPS_PS_POP :
831 _cupsRasterAddError(" --pop--");
832 break;
833
834 case CUPS_PS_ROLL :
835 _cupsRasterAddError(" --roll--");
836 break;
837
838 case CUPS_PS_SETPAGEDEVICE :
839 _cupsRasterAddError(" --setpagedevice--");
840 break;
841
842 case CUPS_PS_STOPPED :
843 _cupsRasterAddError(" --stopped--");
844 break;
845
846 case CUPS_PS_OTHER :
847 _cupsRasterAddError(" --%s--", obj->value.other);
848 break;
849 }
850}
851
852
853/*
854 * 'error_stack()' - Add a stack to the current error message...
855 */
856
857static void
858error_stack(_cups_ps_stack_t *st, /* I - Stack */
859 const char *title) /* I - Title string */
860{
861 int c; /* Looping var */
862 _cups_ps_obj_t *obj; /* Current object on stack */
863
864
85dda01c 865 _cupsRasterAddError("%s", title);
f7deaa1a 866
867 for (obj = st->objs, c = st->num_objs; c > 0; c --, obj ++)
868 error_object(obj);
869
870 _cupsRasterAddError("\n");
871}
872
873
b86bc4cf 874/*
875 * 'index_stack()' - Copy the Nth value on the stack.
876 */
877
878static _cups_ps_obj_t * /* O - New object */
879index_stack(_cups_ps_stack_t *st, /* I - Stack */
880 int n) /* I - Object index */
881{
882 if (n < 0 || (n = st->num_objs - n - 1) < 0)
883 return (NULL);
884
885 return (push_stack(st, st->objs + n));
886}
887
888
889/*
890 * 'new_stack()' - Create a new stack.
891 */
892
893static _cups_ps_stack_t * /* O - New stack */
894new_stack(void)
895{
896 _cups_ps_stack_t *st; /* New stack */
897
898
899 if ((st = calloc(1, sizeof(_cups_ps_stack_t))) == NULL)
900 return (NULL);
901
902 st->alloc_objs = 32;
903
904 if ((st->objs = calloc(32, sizeof(_cups_ps_obj_t))) == NULL)
905 {
906 free(st);
907 return (NULL);
908 }
909 else
910 return (st);
911}
912
913
914/*
915 * 'pop_stock()' - Pop the top object off the stack.
916 */
917
918static _cups_ps_obj_t * /* O - Object */
919pop_stack(_cups_ps_stack_t *st) /* I - Stack */
920{
921 if (st->num_objs > 0)
922 {
923 st->num_objs --;
924
925 return (st->objs + st->num_objs);
926 }
927 else
928 return (NULL);
929}
930
931
932/*
933 * 'push_stack()' - Push an object on the stack.
934 */
935
936static _cups_ps_obj_t * /* O - New object */
937push_stack(_cups_ps_stack_t *st, /* I - Stack */
938 _cups_ps_obj_t *obj) /* I - Object */
939{
940 _cups_ps_obj_t *temp; /* New object */
941
942
943 if (st->num_objs >= st->alloc_objs)
944 {
945
946
947 st->alloc_objs += 32;
948
7e86f2f6 949 if ((temp = realloc(st->objs, (size_t)st->alloc_objs *
b86bc4cf 950 sizeof(_cups_ps_obj_t))) == NULL)
951 return (NULL);
952
953 st->objs = temp;
954 memset(temp + st->num_objs, 0, 32 * sizeof(_cups_ps_obj_t));
955 }
956
957 temp = st->objs + st->num_objs;
958 st->num_objs ++;
959
960 memcpy(temp, obj, sizeof(_cups_ps_obj_t));
961
962 return (temp);
963}
964
965
966/*
967 * 'roll_stack()' - Rotate stack objects.
968 */
969
970static int /* O - 0 on success, -1 on error */
971roll_stack(_cups_ps_stack_t *st, /* I - Stack */
972 int c, /* I - Number of objects */
973 int s) /* I - Amount to shift */
974{
975 _cups_ps_obj_t *temp; /* Temporary array of objects */
976 int n; /* Index into array */
977
978
d9564ec7 979 DEBUG_printf(("3roll_stack(st=%p, s=%d, c=%d)", st, s, c));
b86bc4cf 980
981 /*
982 * Range check input...
983 */
984
985 if (c < 0)
986 return (-1);
987 else if (c == 0)
988 return (0);
989
990 if ((n = st->num_objs - c) < 0)
991 return (-1);
992
993 s %= c;
994
995 if (s == 0)
996 return (0);
997
998 /*
999 * Copy N objects and move things around...
1000 */
1001
1002 if (s < 0)
1003 {
ef416fc2 1004 /*
b86bc4cf 1005 * Shift down...
ef416fc2 1006 */
1007
b86bc4cf 1008 s = -s;
ef416fc2 1009
7e86f2f6 1010 if ((temp = calloc((size_t)s, sizeof(_cups_ps_obj_t))) == NULL)
b86bc4cf 1011 return (-1);
ef416fc2 1012
7e86f2f6
MS
1013 memcpy(temp, st->objs + n, (size_t)s * sizeof(_cups_ps_obj_t));
1014 memmove(st->objs + n, st->objs + n + s, (size_t)(c - s) * sizeof(_cups_ps_obj_t));
1015 memcpy(st->objs + n + c - s, temp, (size_t)s * sizeof(_cups_ps_obj_t));
b86bc4cf 1016 }
1017 else
1018 {
ef416fc2 1019 /*
b86bc4cf 1020 * Shift up...
ef416fc2 1021 */
1022
7e86f2f6 1023 if ((temp = calloc((size_t)s, sizeof(_cups_ps_obj_t))) == NULL)
b86bc4cf 1024 return (-1);
ef416fc2 1025
7e86f2f6
MS
1026 memcpy(temp, st->objs + n + c - s, (size_t)s * sizeof(_cups_ps_obj_t));
1027 memmove(st->objs + n + s, st->objs + n, (size_t)(c - s) * sizeof(_cups_ps_obj_t));
1028 memcpy(st->objs + n, temp, (size_t)s * sizeof(_cups_ps_obj_t));
b86bc4cf 1029 }
ef416fc2 1030
b86bc4cf 1031 free(temp);
1032
1033 return (0);
1034}
ef416fc2 1035
ef416fc2 1036
b86bc4cf 1037/*
1038 * 'scan_ps()' - Scan a string for the next PS object.
1039 */
1040
1041static _cups_ps_obj_t * /* O - New object or NULL on EOF */
1042scan_ps(_cups_ps_stack_t *st, /* I - Stack */
1043 char **ptr) /* IO - String pointer */
1044{
1045 _cups_ps_obj_t obj; /* Current object */
1046 char *start, /* Start of object */
1047 *cur, /* Current position */
1048 *valptr, /* Pointer into value string */
1049 *valend; /* End of value string */
1050 int parens; /* Parenthesis nesting level */
ef416fc2 1051
ef416fc2 1052
b86bc4cf 1053 /*
1054 * Skip leading whitespace...
1055 */
1056
1057 for (cur = *ptr; *cur; cur ++)
1058 {
1059 if (*cur == '%')
ef416fc2 1060 {
1061 /*
b86bc4cf 1062 * Comment, skip to end of line...
ef416fc2 1063 */
1064
b86bc4cf 1065 for (cur ++; *cur && *cur != '\n' && *cur != '\r'; cur ++);
b0f6947b
MS
1066
1067 if (!*cur)
1068 cur --;
b86bc4cf 1069 }
1070 else if (!isspace(*cur & 255))
1071 break;
1072 }
ef416fc2 1073
b86bc4cf 1074 if (!*cur)
1075 {
1076 *ptr = NULL;
ef416fc2 1077
b86bc4cf 1078 return (NULL);
1079 }
ef416fc2 1080
b86bc4cf 1081 /*
1082 * See what we have...
1083 */
ef416fc2 1084
b86bc4cf 1085 memset(&obj, 0, sizeof(obj));
ef416fc2 1086
b86bc4cf 1087 switch (*cur)
1088 {
1089 case '(' : /* (string) */
1090 obj.type = CUPS_PS_STRING;
1091 start = cur;
1092
1093 for (cur ++, parens = 1, valptr = obj.value.string,
1094 valend = obj.value.string + sizeof(obj.value.string) - 1;
1095 *cur;
1096 cur ++)
1097 {
1098 if (*cur == ')' && parens == 1)
1099 break;
1100
1101 if (*cur == '(')
1102 parens ++;
1103 else if (*cur == ')')
1104 parens --;
1105
1106 if (valptr >= valend)
1107 {
1108 *ptr = start;
1109
1110 return (NULL);
1111 }
1112
1113 if (*cur == '\\')
1114 {
1115 /*
1116 * Decode escaped character...
1117 */
1118
1119 cur ++;
1120
1121 if (*cur == 'b')
1122 *valptr++ = '\b';
1123 else if (*cur == 'f')
1124 *valptr++ = '\f';
1125 else if (*cur == 'n')
1126 *valptr++ = '\n';
1127 else if (*cur == 'r')
1128 *valptr++ = '\r';
1129 else if (*cur == 't')
1130 *valptr++ = '\t';
1131 else if (*cur >= '0' && *cur <= '7')
1132 {
1133 int ch = *cur - '0';
1134
1135 if (cur[1] >= '0' && cur[1] <= '7')
1136 {
1137 cur ++;
1138 ch = (ch << 3) + *cur - '0';
1139 }
1140
1141 if (cur[1] >= '0' && cur[1] <= '7')
1142 {
1143 cur ++;
1144 ch = (ch << 3) + *cur - '0';
1145 }
1146
7e86f2f6 1147 *valptr++ = (char)ch;
b86bc4cf 1148 }
1149 else if (*cur == '\r')
1150 {
1151 if (cur[1] == '\n')
1152 cur ++;
1153 }
1154 else if (*cur != '\n')
1155 *valptr++ = *cur;
1156 }
1157 else
1158 *valptr++ = *cur;
1159 }
1160
1161 if (*cur != ')')
1162 {
1163 *ptr = start;
1164
1165 return (NULL);
1166 }
1167
1168 cur ++;
1169 break;
1170
1171 case '[' : /* Start array */
1172 obj.type = CUPS_PS_START_ARRAY;
1173 cur ++;
1174 break;
1175
1176 case ']' : /* End array */
1177 obj.type = CUPS_PS_END_ARRAY;
1178 cur ++;
1179 break;
1180
1181 case '<' : /* Start dictionary or hex string */
1182 if (cur[1] == '<')
1183 {
1184 obj.type = CUPS_PS_START_DICT;
1185 cur += 2;
1186 }
ef416fc2 1187 else
b86bc4cf 1188 {
1189 obj.type = CUPS_PS_STRING;
1190 start = cur;
1191
1192 for (cur ++, valptr = obj.value.string,
1193 valend = obj.value.string + sizeof(obj.value.string) - 1;
1194 *cur;
1195 cur ++)
1196 {
1197 int ch; /* Current character */
1198
1199
1200
1201 if (*cur == '>')
1202 break;
1203 else if (valptr >= valend || !isxdigit(*cur & 255))
1204 {
1205 *ptr = start;
1206 return (NULL);
1207 }
1208
1209 if (*cur >= '0' && *cur <= '9')
1210 ch = (*cur - '0') << 4;
1211 else
1212 ch = (tolower(*cur) - 'a' + 10) << 4;
1213
1214 if (isxdigit(cur[1] & 255))
1215 {
1216 cur ++;
1217
1218 if (*cur >= '0' && *cur <= '9')
1219 ch |= *cur - '0';
1220 else
1221 ch |= tolower(*cur) - 'a' + 10;
1222 }
1223
7e86f2f6 1224 *valptr++ = (char)ch;
b86bc4cf 1225 }
1226
1227 if (*cur != '>')
1228 {
1229 *ptr = start;
1230 return (NULL);
1231 }
1232
1233 cur ++;
1234 }
1235 break;
ef416fc2 1236
b86bc4cf 1237 case '>' : /* End dictionary? */
1238 if (cur[1] == '>')
1239 {
1240 obj.type = CUPS_PS_END_DICT;
1241 cur += 2;
1242 }
1243 else
1244 {
1245 obj.type = CUPS_PS_OTHER;
1246 obj.value.other[0] = *cur;
1247
1248 cur ++;
1249 }
1250 break;
1251
1252 case '{' : /* Start procedure */
1253 obj.type = CUPS_PS_START_PROC;
1254 cur ++;
1255 break;
1256
1257 case '}' : /* End procedure */
1258 obj.type = CUPS_PS_END_PROC;
1259 cur ++;
1260 break;
1261
1262 case '-' : /* Possible number */
1263 case '+' :
1264 if (!isdigit(cur[1] & 255) && cur[1] != '.')
1265 {
1266 obj.type = CUPS_PS_OTHER;
1267 obj.value.other[0] = *cur;
1268
1269 cur ++;
1270 break;
1271 }
1272
1273 case '0' : /* Number */
1274 case '1' :
1275 case '2' :
1276 case '3' :
1277 case '4' :
1278 case '5' :
1279 case '6' :
1280 case '7' :
1281 case '8' :
1282 case '9' :
1283 case '.' :
1284 obj.type = CUPS_PS_NUMBER;
1285
1286 start = cur;
1287 for (cur ++; *cur; cur ++)
1288 if (!isdigit(*cur & 255))
1289 break;
1290
1291 if (*cur == '#')
1292 {
1293 /*
1294 * Integer with radix...
1295 */
1296
1297 obj.value.number = strtol(cur + 1, &cur, atoi(start));
1298 break;
1299 }
1300 else if (strchr(".Ee()<>[]{}/%", *cur) || isspace(*cur & 255))
1301 {
1302 /*
1303 * Integer or real number...
1304 */
ef416fc2 1305
b86bc4cf 1306 obj.value.number = _cupsStrScand(start, &cur, localeconv());
1307 break;
1308 }
1309 else
1310 cur = start;
ef416fc2 1311
b86bc4cf 1312 default : /* Operator/variable name */
1313 start = cur;
1314
1315 if (*cur == '/')
1316 {
1317 obj.type = CUPS_PS_NAME;
1318 valptr = obj.value.name;
1319 valend = obj.value.name + sizeof(obj.value.name) - 1;
1320 cur ++;
1321 }
ef416fc2 1322 else
b86bc4cf 1323 {
1324 obj.type = CUPS_PS_OTHER;
1325 valptr = obj.value.other;
1326 valend = obj.value.other + sizeof(obj.value.other) - 1;
1327 }
ef416fc2 1328
b86bc4cf 1329 while (*cur)
1330 {
1331 if (strchr("()<>[]{}/%", *cur) || isspace(*cur & 255))
1332 break;
1333 else if (valptr < valend)
1334 *valptr++ = *cur++;
1335 else
1336 {
1337 *ptr = start;
1338 return (NULL);
1339 }
1340 }
1341
1342 if (obj.type == CUPS_PS_OTHER)
1343 {
1344 if (!strcmp(obj.value.other, "true"))
1345 {
1346 obj.type = CUPS_PS_BOOLEAN;
1347 obj.value.boolean = 1;
1348 }
1349 else if (!strcmp(obj.value.other, "false"))
1350 {
1351 obj.type = CUPS_PS_BOOLEAN;
1352 obj.value.boolean = 0;
1353 }
1354 else if (!strcmp(obj.value.other, "null"))
1355 obj.type = CUPS_PS_NULL;
1356 else if (!strcmp(obj.value.other, "cleartomark"))
1357 obj.type = CUPS_PS_CLEARTOMARK;
1358 else if (!strcmp(obj.value.other, "copy"))
1359 obj.type = CUPS_PS_COPY;
1360 else if (!strcmp(obj.value.other, "dup"))
1361 obj.type = CUPS_PS_DUP;
1362 else if (!strcmp(obj.value.other, "index"))
1363 obj.type = CUPS_PS_INDEX;
1364 else if (!strcmp(obj.value.other, "pop"))
1365 obj.type = CUPS_PS_POP;
1366 else if (!strcmp(obj.value.other, "roll"))
1367 obj.type = CUPS_PS_ROLL;
1368 else if (!strcmp(obj.value.other, "setpagedevice"))
1369 obj.type = CUPS_PS_SETPAGEDEVICE;
1370 else if (!strcmp(obj.value.other, "stopped"))
1371 obj.type = CUPS_PS_STOPPED;
1372 }
1373 break;
1374 }
1375
1376 /*
1377 * Save the current position in the string and return the new object...
1378 */
1379
1380 *ptr = cur;
1381
1382 return (push_stack(st, &obj));
1383}
1384
1385
1386/*
1387 * 'setpagedevice()' - Simulate the PostScript setpagedevice operator.
1388 */
1389
1390static int /* O - 0 on success, -1 on error */
1391setpagedevice(
1392 _cups_ps_stack_t *st, /* I - Stack */
1393 cups_page_header2_t *h, /* O - Page header */
1394 int *preferred_bits)/* O - Preferred bits per color */
1395{
1396 int i; /* Index into array */
1397 _cups_ps_obj_t *obj, /* Current object */
1398 *end; /* End of dictionary */
1399 const char *name; /* Attribute name */
1400
1401
1402 /*
1403 * Make sure we have a dictionary on the stack...
1404 */
1405
1406 if (st->num_objs == 0)
1407 return (-1);
1408
1409 obj = end = st->objs + st->num_objs - 1;
1410
1411 if (obj->type != CUPS_PS_END_DICT)
1412 return (-1);
1413
1414 obj --;
1415
1416 while (obj > st->objs)
1417 {
1418 if (obj->type == CUPS_PS_START_DICT)
1419 break;
1420
1421 obj --;
1422 }
1423
1424 if (obj < st->objs)
1425 return (-1);
ef416fc2 1426
b86bc4cf 1427 /*
1428 * Found the start of the dictionary, empty the stack to this point...
1429 */
1430
a2326b5b 1431 st->num_objs = (int)(obj - st->objs);
b86bc4cf 1432
1433 /*
1434 * Now pull /name and value pairs from the dictionary...
1435 */
1436
d9564ec7 1437 DEBUG_puts("3setpagedevice: Dictionary:");
b86bc4cf 1438
1439 for (obj ++; obj < end; obj ++)
1440 {
ef416fc2 1441 /*
b86bc4cf 1442 * Grab the name...
ef416fc2 1443 */
1444
b86bc4cf 1445 if (obj->type != CUPS_PS_NAME)
1446 return (-1);
1447
1448 name = obj->value.name;
1449 obj ++;
1450
1451#ifdef DEBUG
d9564ec7
MS
1452 DEBUG_printf(("4setpagedevice: /%s ", name));
1453 DEBUG_object("setpagedevice", obj);
b86bc4cf 1454#endif /* DEBUG */
1455
1456 /*
1457 * Then grab the value...
1458 */
1459
1460 if (!strcmp(name, "MediaClass") && obj->type == CUPS_PS_STRING)
1461 strlcpy(h->MediaClass, obj->value.string, sizeof(h->MediaClass));
1462 else if (!strcmp(name, "MediaColor") && obj->type == CUPS_PS_STRING)
1463 strlcpy(h->MediaColor, obj->value.string, sizeof(h->MediaColor));
1464 else if (!strcmp(name, "MediaType") && obj->type == CUPS_PS_STRING)
1465 strlcpy(h->MediaType, obj->value.string, sizeof(h->MediaType));
1466 else if (!strcmp(name, "OutputType") && obj->type == CUPS_PS_STRING)
1467 strlcpy(h->OutputType, obj->value.string, sizeof(h->OutputType));
1468 else if (!strcmp(name, "AdvanceDistance") && obj->type == CUPS_PS_NUMBER)
1469 h->AdvanceDistance = (unsigned)obj->value.number;
1470 else if (!strcmp(name, "AdvanceMedia") && obj->type == CUPS_PS_NUMBER)
1471 h->AdvanceMedia = (unsigned)obj->value.number;
1472 else if (!strcmp(name, "Collate") && obj->type == CUPS_PS_BOOLEAN)
1473 h->Collate = (unsigned)obj->value.boolean;
1474 else if (!strcmp(name, "CutMedia") && obj->type == CUPS_PS_NUMBER)
1475 h->CutMedia = (cups_cut_t)(unsigned)obj->value.number;
1476 else if (!strcmp(name, "Duplex") && obj->type == CUPS_PS_BOOLEAN)
1477 h->Duplex = (unsigned)obj->value.boolean;
1478 else if (!strcmp(name, "HWResolution") && obj->type == CUPS_PS_START_ARRAY)
ef416fc2 1479 {
b86bc4cf 1480 if (obj[1].type == CUPS_PS_NUMBER && obj[2].type == CUPS_PS_NUMBER &&
1481 obj[3].type == CUPS_PS_END_ARRAY)
1482 {
1483 h->HWResolution[0] = (unsigned)obj[1].value.number;
1484 h->HWResolution[1] = (unsigned)obj[2].value.number;
1485 obj += 3;
1486 }
1487 else
ef416fc2 1488 return (-1);
1489 }
b86bc4cf 1490 else if (!strcmp(name, "InsertSheet") && obj->type == CUPS_PS_BOOLEAN)
1491 h->InsertSheet = (unsigned)obj->value.boolean;
1492 else if (!strcmp(name, "Jog") && obj->type == CUPS_PS_NUMBER)
1493 h->Jog = (unsigned)obj->value.number;
1494 else if (!strcmp(name, "LeadingEdge") && obj->type == CUPS_PS_NUMBER)
1495 h->LeadingEdge = (unsigned)obj->value.number;
1496 else if (!strcmp(name, "ManualFeed") && obj->type == CUPS_PS_BOOLEAN)
1497 h->ManualFeed = (unsigned)obj->value.boolean;
09a101d6 1498 else if ((!strcmp(name, "cupsMediaPosition") ||
b86bc4cf 1499 !strcmp(name, "MediaPosition")) && obj->type == CUPS_PS_NUMBER)
09a101d6 1500 {
1501 /*
1502 * cupsMediaPosition is supported for backwards compatibility only.
1503 * We added it back in the Ghostscript 5.50 days to work around a
1504 * bug in Ghostscript WRT handling of MediaPosition and setpagedevice.
1505 *
1506 * All new development should set MediaPosition...
1507 */
1508
b86bc4cf 1509 h->MediaPosition = (unsigned)obj->value.number;
09a101d6 1510 }
b86bc4cf 1511 else if (!strcmp(name, "MediaWeight") && obj->type == CUPS_PS_NUMBER)
1512 h->MediaWeight = (unsigned)obj->value.number;
1513 else if (!strcmp(name, "MirrorPrint") && obj->type == CUPS_PS_BOOLEAN)
1514 h->MirrorPrint = (unsigned)obj->value.boolean;
1515 else if (!strcmp(name, "NegativePrint") && obj->type == CUPS_PS_BOOLEAN)
1516 h->NegativePrint = (unsigned)obj->value.boolean;
1517 else if (!strcmp(name, "NumCopies") && obj->type == CUPS_PS_NUMBER)
1518 h->NumCopies = (unsigned)obj->value.number;
1519 else if (!strcmp(name, "Orientation") && obj->type == CUPS_PS_NUMBER)
1520 h->Orientation = (unsigned)obj->value.number;
1521 else if (!strcmp(name, "OutputFaceUp") && obj->type == CUPS_PS_BOOLEAN)
1522 h->OutputFaceUp = (unsigned)obj->value.boolean;
1523 else if (!strcmp(name, "PageSize") && obj->type == CUPS_PS_START_ARRAY)
ef416fc2 1524 {
b86bc4cf 1525 if (obj[1].type == CUPS_PS_NUMBER && obj[2].type == CUPS_PS_NUMBER &&
1526 obj[3].type == CUPS_PS_END_ARRAY)
1527 {
c8fef167
MS
1528 h->cupsPageSize[0] = (float)obj[1].value.number;
1529 h->cupsPageSize[1] = (float)obj[2].value.number;
b86bc4cf 1530
1531 h->PageSize[0] = (unsigned)obj[1].value.number;
1532 h->PageSize[1] = (unsigned)obj[2].value.number;
1533
1534 obj += 3;
1535 }
1536 else
fa73b229 1537 return (-1);
ef416fc2 1538 }
b86bc4cf 1539 else if (!strcmp(name, "Separations") && obj->type == CUPS_PS_BOOLEAN)
1540 h->Separations = (unsigned)obj->value.boolean;
1541 else if (!strcmp(name, "TraySwitch") && obj->type == CUPS_PS_BOOLEAN)
1542 h->TraySwitch = (unsigned)obj->value.boolean;
1543 else if (!strcmp(name, "Tumble") && obj->type == CUPS_PS_BOOLEAN)
1544 h->Tumble = (unsigned)obj->value.boolean;
1545 else if (!strcmp(name, "cupsMediaType") && obj->type == CUPS_PS_NUMBER)
1546 h->cupsMediaType = (unsigned)obj->value.number;
1547 else if (!strcmp(name, "cupsBitsPerColor") && obj->type == CUPS_PS_NUMBER)
1548 h->cupsBitsPerColor = (unsigned)obj->value.number;
1549 else if (!strcmp(name, "cupsPreferredBitsPerColor") &&
1550 obj->type == CUPS_PS_NUMBER)
1551 *preferred_bits = (int)obj->value.number;
1552 else if (!strcmp(name, "cupsColorOrder") && obj->type == CUPS_PS_NUMBER)
1553 h->cupsColorOrder = (cups_order_t)(unsigned)obj->value.number;
1554 else if (!strcmp(name, "cupsColorSpace") && obj->type == CUPS_PS_NUMBER)
1555 h->cupsColorSpace = (cups_cspace_t)(unsigned)obj->value.number;
1556 else if (!strcmp(name, "cupsCompression") && obj->type == CUPS_PS_NUMBER)
1557 h->cupsCompression = (unsigned)obj->value.number;
1558 else if (!strcmp(name, "cupsRowCount") && obj->type == CUPS_PS_NUMBER)
1559 h->cupsRowCount = (unsigned)obj->value.number;
1560 else if (!strcmp(name, "cupsRowFeed") && obj->type == CUPS_PS_NUMBER)
1561 h->cupsRowFeed = (unsigned)obj->value.number;
1562 else if (!strcmp(name, "cupsRowStep") && obj->type == CUPS_PS_NUMBER)
1563 h->cupsRowStep = (unsigned)obj->value.number;
923edb68 1564 else if (!strcmp(name, "cupsBorderlessScalingFactor") &&
b86bc4cf 1565 obj->type == CUPS_PS_NUMBER)
c8fef167 1566 h->cupsBorderlessScalingFactor = (float)obj->value.number;
b86bc4cf 1567 else if (!strncmp(name, "cupsInteger", 11) && obj->type == CUPS_PS_NUMBER)
ef416fc2 1568 {
b86bc4cf 1569 if ((i = atoi(name + 11)) < 0 || i > 15)
ef416fc2 1570 return (-1);
1571
b86bc4cf 1572 h->cupsInteger[i] = (unsigned)obj->value.number;
ef416fc2 1573 }
b86bc4cf 1574 else if (!strncmp(name, "cupsReal", 8) && obj->type == CUPS_PS_NUMBER)
ef416fc2 1575 {
b86bc4cf 1576 if ((i = atoi(name + 8)) < 0 || i > 15)
ef416fc2 1577 return (-1);
1578
c8fef167 1579 h->cupsReal[i] = (float)obj->value.number;
ef416fc2 1580 }
b86bc4cf 1581 else if (!strncmp(name, "cupsString", 10) && obj->type == CUPS_PS_STRING)
ef416fc2 1582 {
b86bc4cf 1583 if ((i = atoi(name + 10)) < 0 || i > 15)
ef416fc2 1584 return (-1);
1585
b86bc4cf 1586 strlcpy(h->cupsString[i], obj->value.string, sizeof(h->cupsString[i]));
ef416fc2 1587 }
b86bc4cf 1588 else if (!strcmp(name, "cupsMarkerType") && obj->type == CUPS_PS_STRING)
1589 strlcpy(h->cupsMarkerType, obj->value.string, sizeof(h->cupsMarkerType));
1590 else if (!strcmp(name, "cupsPageSizeName") && obj->type == CUPS_PS_STRING)
1591 strlcpy(h->cupsPageSizeName, obj->value.string,
1592 sizeof(h->cupsPageSizeName));
1593 else if (!strcmp(name, "cupsRenderingIntent") &&
1594 obj->type == CUPS_PS_STRING)
1595 strlcpy(h->cupsRenderingIntent, obj->value.string,
1596 sizeof(h->cupsRenderingIntent));
1597 else
ef416fc2 1598 {
b86bc4cf 1599 /*
1600 * Ignore unknown name+value...
1601 */
1602
d9564ec7 1603 DEBUG_printf(("4setpagedevice: Unknown name (\"%s\") or value...\n", name));
b86bc4cf 1604
1605 while (obj[1].type != CUPS_PS_NAME && obj < end)
1606 obj ++;
ef416fc2 1607 }
ef416fc2 1608 }
1609
ef416fc2 1610 return (0);
1611}
1612
1613
b86bc4cf 1614#ifdef DEBUG
1615/*
1616 * 'DEBUG_object()' - Print an object's value...
1617 */
1618
1619static void
d9564ec7
MS
1620DEBUG_object(const char *prefix, /* I - Prefix string */
1621 _cups_ps_obj_t *obj) /* I - Object to print */
b86bc4cf 1622{
1623 switch (obj->type)
1624 {
1625 case CUPS_PS_NAME :
d9564ec7 1626 DEBUG_printf(("4%s: /%s\n", prefix, obj->value.name));
b86bc4cf 1627 break;
1628
1629 case CUPS_PS_NUMBER :
d9564ec7 1630 DEBUG_printf(("4%s: %g\n", prefix, obj->value.number));
b86bc4cf 1631 break;
1632
1633 case CUPS_PS_STRING :
d9564ec7 1634 DEBUG_printf(("4%s: (%s)\n", prefix, obj->value.string));
b86bc4cf 1635 break;
1636
1637 case CUPS_PS_BOOLEAN :
1638 if (obj->value.boolean)
d9564ec7 1639 DEBUG_printf(("4%s: true", prefix));
b86bc4cf 1640 else
d9564ec7 1641 DEBUG_printf(("4%s: false", prefix));
b86bc4cf 1642 break;
1643
1644 case CUPS_PS_NULL :
d9564ec7 1645 DEBUG_printf(("4%s: null", prefix));
b86bc4cf 1646 break;
1647
1648 case CUPS_PS_START_ARRAY :
d9564ec7 1649 DEBUG_printf(("4%s: [", prefix));
b86bc4cf 1650 break;
1651
1652 case CUPS_PS_END_ARRAY :
d9564ec7 1653 DEBUG_printf(("4%s: ]", prefix));
b86bc4cf 1654 break;
1655
1656 case CUPS_PS_START_DICT :
d9564ec7 1657 DEBUG_printf(("4%s: <<", prefix));
b86bc4cf 1658 break;
1659
1660 case CUPS_PS_END_DICT :
d9564ec7 1661 DEBUG_printf(("4%s: >>", prefix));
b86bc4cf 1662 break;
1663
1664 case CUPS_PS_START_PROC :
d9564ec7 1665 DEBUG_printf(("4%s: {", prefix));
b86bc4cf 1666 break;
1667
1668 case CUPS_PS_END_PROC :
d9564ec7 1669 DEBUG_printf(("4%s: }", prefix));
b86bc4cf 1670 break;
1671
1672 case CUPS_PS_CLEARTOMARK :
d9564ec7 1673 DEBUG_printf(("4%s: --cleartomark--", prefix));
b86bc4cf 1674 break;
1675
1676 case CUPS_PS_COPY :
d9564ec7 1677 DEBUG_printf(("4%s: --copy--", prefix));
b86bc4cf 1678 break;
1679
1680 case CUPS_PS_DUP :
d9564ec7 1681 DEBUG_printf(("4%s: --dup--", prefix));
b86bc4cf 1682 break;
1683
1684 case CUPS_PS_INDEX :
d9564ec7 1685 DEBUG_printf(("4%s: --index--", prefix));
b86bc4cf 1686 break;
1687
1688 case CUPS_PS_POP :
d9564ec7 1689 DEBUG_printf(("4%s: --pop--", prefix));
b86bc4cf 1690 break;
1691
1692 case CUPS_PS_ROLL :
d9564ec7 1693 DEBUG_printf(("4%s: --roll--", prefix));
b86bc4cf 1694 break;
1695
1696 case CUPS_PS_SETPAGEDEVICE :
d9564ec7 1697 DEBUG_printf(("4%s: --setpagedevice--", prefix));
b86bc4cf 1698 break;
1699
1700 case CUPS_PS_STOPPED :
d9564ec7 1701 DEBUG_printf(("4%s: --stopped--", prefix));
b86bc4cf 1702 break;
1703
1704 case CUPS_PS_OTHER :
d9564ec7 1705 DEBUG_printf(("4%s: --%s--", prefix, obj->value.other));
b86bc4cf 1706 break;
1707 }
1708}
1709
1710
1711/*
1712 * 'DEBUG_stack()' - Print a stack...
1713 */
1714
1715static void
d9564ec7
MS
1716DEBUG_stack(const char *prefix, /* I - Prefix string */
1717 _cups_ps_stack_t *st) /* I - Stack */
b86bc4cf 1718{
1719 int c; /* Looping var */
1720 _cups_ps_obj_t *obj; /* Current object on stack */
1721
1722
1723 for (obj = st->objs, c = st->num_objs; c > 0; c --, obj ++)
d9564ec7 1724 DEBUG_object(prefix, obj);
b86bc4cf 1725}
1726#endif /* DEBUG */
1727
1728
ef416fc2 1729/*
f2d18633 1730 * End of "$Id$".
ef416fc2 1731 */