]> git.ipfire.org Git - thirdparty/cups.git/blob - filter/interpret.c
Load cups into easysw/current.
[thirdparty/cups.git] / filter / interpret.c
1 /*
2 * "$Id: interpret.c 4903 2006-01-10 20:02:46Z mike $"
3 *
4 * PPD command interpreter for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1993-2006 by Easy Software Products.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * This file is subject to the Apple OS-Developed Software exception.
25 *
26 * Contents:
27 *
28 * cupsRasterInterpretPPD() - Interpret PPD commands to create a page header.
29 * exec_code() - Execute PostScript setpagedevice commands as
30 * appropriate.
31 */
32
33 /*
34 * Include necessary headers...
35 */
36
37 #include <cups/ppd.h>
38 #include <cups/string.h>
39 #include "raster.h"
40 #include <stdlib.h>
41
42
43 /*
44 * Value types for PS code...
45 */
46
47 #define CUPS_TYPE_NUMBER 0 /* Integer or real number */
48 #define CUPS_TYPE_NAME 1 /* Name */
49 #define CUPS_TYPE_STRING 2 /* String */
50 #define CUPS_TYPE_ARRAY 3 /* Array of integers */
51
52
53 /*
54 * Local functions...
55 */
56
57 static int exec_code(cups_page_header2_t *header, const char *code);
58
59
60 /*
61 * 'cupsRasterInterpretPPD()' - Interpret PPD commands to create a page header.
62 *
63 * @since CUPS 1.2@
64 */
65
66 int /* O - 0 on success, -1 on failure */
67 cupsRasterInterpretPPD(
68 cups_page_header2_t *h, /* O - Page header */
69 ppd_file_t *ppd) /* I - PPD file */
70 {
71 int i; /* Looping var */
72 int status; /* Cummulative status */
73 int count; /* Number of marked choices */
74 ppd_choice_t **choices; /* List of marked choices */
75 ppd_size_t *size; /* Current size */
76 float left, /* Left position */
77 bottom, /* Bottom position */
78 right, /* Right position */
79 top; /* Top position */
80
81
82 /*
83 * Range check input...
84 */
85
86 if (!h)
87 return (-1);
88
89 /*
90 * Reset the page header to the defaults...
91 */
92
93 memset(h, 0, sizeof(cups_page_header2_t));
94
95 h->NumCopies = 1;
96 h->PageSize[0] = 612;
97 h->PageSize[1] = 792;
98 h->HWResolution[0] = 100;
99 h->HWResolution[1] = 100;
100 h->cupsBitsPerColor = 1;
101 h->cupsColorOrder = CUPS_ORDER_CHUNKED;
102 h->cupsColorSpace = CUPS_CSPACE_K;
103
104 /*
105 * Apply patches and options to the page header...
106 */
107
108 status = 0;
109
110 if (ppd)
111 {
112 /*
113 * Apply any patch code (used to override the defaults...)
114 */
115
116 if (ppd->patches)
117 status |= exec_code(h, ppd->patches);
118
119 /*
120 * Then apply printer options in the proper order...
121 */
122
123 if ((count = ppdCollect(ppd, PPD_ORDER_DOCUMENT, &choices)) > 0)
124 {
125 for (i = 0; i < count; i ++)
126 status |= exec_code(h, choices[i]->code);
127 }
128
129 if ((count = ppdCollect(ppd, PPD_ORDER_ANY, &choices)) > 0)
130 {
131 for (i = 0; i < count; i ++)
132 status |= exec_code(h, choices[i]->code);
133 }
134
135 if ((count = ppdCollect(ppd, PPD_ORDER_PROLOG, &choices)) > 0)
136 {
137 for (i = 0; i < count; i ++)
138 status |= exec_code(h, choices[i]->code);
139 }
140
141 if ((count = ppdCollect(ppd, PPD_ORDER_PAGE, &choices)) > 0)
142 {
143 for (i = 0; i < count; i ++)
144 status |= exec_code(h, choices[i]->code);
145 }
146 }
147
148 /*
149 * Check parameters...
150 */
151
152 if (!h->HWResolution[0] || !h->HWResolution[1] ||
153 !h->PageSize[0] || !h->PageSize[1] ||
154 (h->cupsBitsPerColor != 1 && h->cupsBitsPerColor != 2 &&
155 h->cupsBitsPerColor != 4 && h->cupsBitsPerColor != 8))
156 return (-1);
157
158 /*
159 * Get the margins for the current size...
160 */
161
162 if ((size = ppdPageSize(ppd, NULL)) != NULL)
163 {
164 /*
165 * Use the margins from the PPD file...
166 */
167
168 left = size->left;
169 bottom = size->bottom;
170 right = size->right;
171 top = size->top;
172 }
173 else
174 {
175 /*
176 * Use the default margins...
177 */
178
179 left = 0.0f;
180 bottom = 0.0f;
181 right = 612.0f;
182 top = 792.0f;
183 }
184
185 h->Margins[0] = left;
186 h->Margins[1] = bottom;
187 h->ImagingBoundingBox[0] = left;
188 h->ImagingBoundingBox[1] = bottom;
189 h->ImagingBoundingBox[2] = right;
190 h->ImagingBoundingBox[3] = top;
191
192 /*
193 * Compute the bitmap parameters...
194 */
195
196 h->cupsWidth = (int)((right - left) * h->HWResolution[0] / 72.0f + 0.5f);
197 h->cupsHeight = (int)((top - bottom) * h->HWResolution[1] / 72.0f + 0.5f);
198
199 switch (h->cupsColorSpace)
200 {
201 case CUPS_CSPACE_W :
202 case CUPS_CSPACE_K :
203 case CUPS_CSPACE_WHITE :
204 case CUPS_CSPACE_GOLD :
205 case CUPS_CSPACE_SILVER :
206 h->cupsNumColors = 1;
207 h->cupsBitsPerPixel = h->cupsBitsPerColor;
208 break;
209
210 default :
211 /*
212 * Ensure that colorimetric colorspaces use at least 8 bits per
213 * component...
214 */
215
216 if (h->cupsColorSpace >= CUPS_CSPACE_CIEXYZ &&
217 h->cupsBitsPerColor < 8)
218 h->cupsBitsPerColor = 8;
219
220 /*
221 * Figure out the number of bits per pixel...
222 */
223
224 if (h->cupsColorOrder == CUPS_ORDER_CHUNKED)
225 {
226 if (h->cupsBitsPerColor >= 8)
227 h->cupsBitsPerPixel = h->cupsBitsPerColor * 3;
228 else
229 h->cupsBitsPerPixel = h->cupsBitsPerColor * 4;
230 }
231 else
232 h->cupsBitsPerPixel = h->cupsBitsPerColor;
233
234 h->cupsNumColors = 3;
235 break;
236
237 case CUPS_CSPACE_KCMYcm :
238 if (h->cupsBitsPerPixel == 1)
239 {
240 if (h->cupsColorOrder == CUPS_ORDER_CHUNKED)
241 h->cupsBitsPerPixel = 8;
242 else
243 h->cupsBitsPerPixel = 1;
244
245 h->cupsNumColors = 6;
246 break;
247 }
248
249 /*
250 * Fall through to CMYK code...
251 */
252
253 case CUPS_CSPACE_RGBA :
254 case CUPS_CSPACE_CMYK :
255 case CUPS_CSPACE_YMCK :
256 case CUPS_CSPACE_KCMY :
257 case CUPS_CSPACE_GMCK :
258 case CUPS_CSPACE_GMCS :
259 if (h->cupsColorOrder == CUPS_ORDER_CHUNKED)
260 h->cupsBitsPerPixel = h->cupsBitsPerColor * 4;
261 else
262 h->cupsBitsPerPixel = h->cupsBitsPerColor;
263
264 h->cupsNumColors = 4;
265 break;
266 }
267
268 h->cupsBytesPerLine = (h->cupsBitsPerPixel * h->cupsWidth + 7) / 8;
269
270 if (h->cupsColorOrder == CUPS_ORDER_BANDED)
271 h->cupsBytesPerLine *= h->cupsNumColors;
272
273 return (status);
274 }
275
276
277 /*
278 * 'exec_code()' - Execute PostScript setpagedevice commands as appropriate.
279 */
280
281 static int /* O - 0 on success, -1 on error */
282 exec_code(cups_page_header2_t *h, /* O - Page header */
283 const char *code) /* I - Option choice to execute */
284 {
285 int i; /* Index into array */
286 int type; /* Type of value */
287 char *ptr, /* Pointer into name/value string */
288 name[255], /* Name of pagedevice entry */
289 value[1024]; /* Value of pagedevice entry */
290
291
292 /*
293 * Range check input...
294 */
295
296 if (!code || !h)
297 return (-1);
298
299 /*
300 * Parse the code string...
301 */
302
303 while (*code)
304 {
305 /*
306 * Search for the start of a dictionary name...
307 */
308
309 while (*code && *code != '/')
310 code ++;
311
312 if (!*code)
313 break;
314
315 /*
316 * Get the name...
317 */
318
319 code ++;
320 for (ptr = name; isalnum(*code & 255); code ++)
321 if (ptr < (name + sizeof(name) - 1))
322 *ptr++ = *code;
323 else
324 return (-1);
325
326 *ptr = '\0';
327
328 /*
329 * Then parse the value as needed...
330 */
331
332 while (isspace(*code & 255))
333 code ++;
334
335 if (!*code)
336 break;
337
338 if (*code == '[')
339 {
340 /*
341 * Read array of values...
342 */
343
344 type = CUPS_TYPE_ARRAY;
345
346 for (ptr = value; *code && *code != ']'; code ++)
347 if (ptr < (value + sizeof(value) - 1))
348 *ptr++ = *code;
349 else
350 return (-1);
351
352 if (*code == ']')
353 *ptr++ = *code++;
354
355 *ptr = '\0';
356 }
357 else if (*code == '(')
358 {
359 /*
360 * Read string value...
361 */
362
363 type = CUPS_TYPE_STRING;
364
365 for (ptr = value; *code && *code != ')'; code ++)
366 if (ptr < (value + sizeof(value) - 1))
367 *ptr++ = *code;
368 else
369 return (-1);
370
371 if (*code == ')')
372 *ptr++ = *code++;
373
374 *ptr = '\0';
375 }
376 else if (isdigit(*code & 255) || *code == '-' || *code == '.')
377 {
378 /*
379 * Read single number...
380 */
381
382 type = CUPS_TYPE_NUMBER;
383
384 for (ptr = value;
385 isdigit(*code & 255) || *code == '-' || *code == '.';
386 code ++)
387 if (ptr < (value + sizeof(value) - 1))
388 *ptr++ = *code;
389 else
390 return (-1);
391
392 *ptr = '\0';
393 }
394 else
395 {
396 /*
397 * Read a single name...
398 */
399
400 type = CUPS_TYPE_NAME;
401
402 for (ptr = value; isalnum(*code & 255) || *code == '_'; code ++)
403 if (ptr < (value + sizeof(value) - 1))
404 *ptr++ = *code;
405 else
406 return (-1);
407
408 *ptr = '\0';
409 }
410
411 /*
412 * Assign the value as needed...
413 */
414
415 if (!strcmp(name, "MediaClass") && type == CUPS_TYPE_STRING)
416 {
417 if (sscanf(value, "(%63[^)])", h->MediaClass) != 1)
418 return (-1);
419 }
420 else if (!strcmp(name, "MediaColor") && type == CUPS_TYPE_STRING)
421 {
422 if (sscanf(value, "(%63[^)])", h->MediaColor) != 1)
423 return (-1);
424 }
425 else if (!strcmp(name, "MediaType") && type == CUPS_TYPE_STRING)
426 {
427 if (sscanf(value, "(%63[^)])", h->MediaType) != 1)
428 return (-1);
429 }
430 else if (!strcmp(name, "OutputType") && type == CUPS_TYPE_STRING)
431 {
432 if (sscanf(value, "(%63[^)])", h->OutputType) != 1)
433 return (-1);
434 }
435 else if (!strcmp(name, "AdvanceDistance") && type == CUPS_TYPE_NUMBER)
436 h->AdvanceDistance = atoi(value);
437 else if (!strcmp(name, "AdvanceMedia") && type == CUPS_TYPE_NUMBER)
438 h->AdvanceMedia = atoi(value);
439 else if (!strcmp(name, "Collate") && type == CUPS_TYPE_NAME)
440 h->Collate = !strcmp(value, "true");
441 else if (!strcmp(name, "CutMedia") && type == CUPS_TYPE_NUMBER)
442 h->CutMedia = (cups_cut_t)atoi(value);
443 else if (!strcmp(name, "Duplex") && type == CUPS_TYPE_NAME)
444 h->Duplex = !strcmp(value, "true");
445 else if (!strcmp(name, "HWResolution") && type == CUPS_TYPE_ARRAY)
446 {
447 if (sscanf(value, "[%d%d]", h->HWResolution + 0,
448 h->HWResolution + 1) != 2)
449 return (-1);
450 }
451 else if (!strcmp(name, "InsertSheet") && type == CUPS_TYPE_NAME)
452 h->InsertSheet = !strcmp(value, "true");
453 else if (!strcmp(name, "Jog") && type == CUPS_TYPE_NUMBER)
454 h->Jog = atoi(value);
455 else if (!strcmp(name, "LeadingEdge") && type == CUPS_TYPE_NUMBER)
456 h->LeadingEdge = atoi(value);
457 else if (!strcmp(name, "ManualFeed") && type == CUPS_TYPE_NAME)
458 h->ManualFeed = !strcmp(value, "true");
459 else if ((!strcmp(name, "cupsMediaPosition") || /* Compatibility */
460 !strcmp(name, "MediaPosition")) && type == CUPS_TYPE_NUMBER)
461 h->MediaPosition = atoi(value);
462 else if (!strcmp(name, "MediaWeight") && type == CUPS_TYPE_NUMBER)
463 h->MediaWeight = atoi(value);
464 else if (!strcmp(name, "MirrorPrint") && type == CUPS_TYPE_NAME)
465 h->MirrorPrint = !strcmp(value, "true");
466 else if (!strcmp(name, "NegativePrint") && type == CUPS_TYPE_NAME)
467 h->NegativePrint = !strcmp(value, "true");
468 else if (!strcmp(name, "Orientation") && type == CUPS_TYPE_NUMBER)
469 h->Orientation = atoi(value);
470 else if (!strcmp(name, "OutputFaceUp") && type == CUPS_TYPE_NAME)
471 h->OutputFaceUp = !strcmp(value, "true");
472 else if (!strcmp(name, "PageSize") && type == CUPS_TYPE_ARRAY)
473 {
474 if (sscanf(value, "[%d%d]", h->PageSize + 0, h->PageSize + 1) != 2)
475 return (-1);
476 }
477 else if (!strcmp(name, "Separations") && type == CUPS_TYPE_NAME)
478 h->Separations = !strcmp(value, "true");
479 else if (!strcmp(name, "TraySwitch") && type == CUPS_TYPE_NAME)
480 h->TraySwitch = !strcmp(value, "true");
481 else if (!strcmp(name, "Tumble") && type == CUPS_TYPE_NAME)
482 h->Tumble = !strcmp(value, "true");
483 else if (!strcmp(name, "cupsMediaType") && type == CUPS_TYPE_NUMBER)
484 h->cupsMediaType = atoi(value);
485 else if (!strcmp(name, "cupsBitsPerColor") && type == CUPS_TYPE_NUMBER)
486 h->cupsBitsPerColor = atoi(value);
487 else if (!strcmp(name, "cupsColorOrder") && type == CUPS_TYPE_NUMBER)
488 h->cupsColorOrder = (cups_order_t)atoi(value);
489 else if (!strcmp(name, "cupsColorSpace") && type == CUPS_TYPE_NUMBER)
490 h->cupsColorSpace = (cups_cspace_t)atoi(value);
491 else if (!strcmp(name, "cupsCompression") && type == CUPS_TYPE_NUMBER)
492 h->cupsCompression = atoi(value);
493 else if (!strcmp(name, "cupsRowCount") && type == CUPS_TYPE_NUMBER)
494 h->cupsRowCount = atoi(value);
495 else if (!strcmp(name, "cupsRowFeed") && type == CUPS_TYPE_NUMBER)
496 h->cupsRowFeed = atoi(value);
497 else if (!strcmp(name, "cupsRowStep") && type == CUPS_TYPE_NUMBER)
498 h->cupsRowStep = atoi(value);
499 else if (!strncmp(name, "cupsInteger", 11) && type == CUPS_TYPE_NUMBER)
500 {
501 if ((i = atoi(name + 11)) >= 0 || i > 15)
502 return (-1);
503
504 h->cupsInteger[i] = atoi(value);
505 }
506 else if (!strncmp(name, "cupsReal", 8) && type == CUPS_TYPE_NUMBER)
507 {
508 if ((i = atoi(name + 8)) >= 0 || i > 15)
509 return (-1);
510
511 h->cupsReal[i] = atof(value);
512 }
513 else if (!strncmp(name, "cupsString", 10) && type == CUPS_TYPE_STRING)
514 {
515 if ((i = atoi(name + 10)) >= 0 || i > 15)
516 return (-1);
517
518 if (sscanf(value, "(%63[^)])", h->cupsString[i]) != 1)
519 return (-1);
520 }
521 else if (!strcmp(name, "cupsMarkerType") && type == CUPS_TYPE_STRING)
522 {
523 if (sscanf(value, "(%63[^)])", h->cupsMarkerType) != 1)
524 return (-1);
525 }
526 else if (!strcmp(name, "cupsRenderingIntent") && type == CUPS_TYPE_STRING)
527 {
528 if (sscanf(value, "(%63[^)])", h->cupsRenderingIntent) != 1)
529 return (-1);
530 }
531 else
532 return (-1);
533 }
534
535 /*
536 * Return success...
537 */
538
539 return (0);
540 }
541
542
543 /*
544 * End of "$Id: interpret.c 4903 2006-01-10 20:02:46Z mike $".
545 */