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