1 /* Copyright (C) 2000-2003, Ghostgum Software Pty Ltd. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: dscparse.c,v 1.14 2003/09/13 02:04:15 ghostgum Exp $ */
18
19 /*
20 * This is a DSC parser, based on the DSC 3.0 spec,
21 * with a few DSC 2.1 additions for page size.
22 *
23 * Current limitations:
24 * %%+ may be used after any comment in the comment or trailer,
25 * but is currently only supported by
26 * %%DocumentMedia
27 *
28 * DSC 2.1 additions (discontinued in DSC 3.0):
29 * %%DocumentPaperColors:
30 * %%DocumentPaperForms:
31 * %%DocumentPaperSizes:
32 * %%DocumentPaperWeights:
33 * %%PaperColor: (ignored)
34 * %%PaperForm: (ignored)
35 * %%PaperSize:
36 * %%PaperWeight: (ignored)
37 *
38 * Other additions for defaults or page section
39 % %%ViewingOrientation: xx xy yx yy
40 */
41
42 #include <stdio.h> /* for sprintf(), not file I/O */
43 #include <stdlib.h>
44 #include <string.h>
45 #include <ctype.h>
46
47 #define MAXSTR 256
48
49 #include "dscparse.h"
50
51 /* Macros for comparing string literals
52 * For maximum speed, the length of the second macro argument is
53 * computed at compile time.
54 * THE SECOND MACRO ARGUMENT MUST BE A STRING LITERAL.
55 */
56 #define COMPARE(p,str) (strncmp((const char *)(p), (str), sizeof(str)-1)==0)
57 #define IS_DSC(line, str) (COMPARE((line), (str)))
58
59 /* Macros for comparing the first one or two characters */
60 #define IS_WHITE(ch) (((ch)==' ') || ((ch)=='\t'))
61 #define IS_EOL(ch) (((ch)=='\r') || ((ch)=='\n'))
62 #define IS_WHITE_OR_EOL(ch) (IS_WHITE(ch) || IS_EOL(ch))
63 #define IS_BLANK(str) (IS_EOL(str[0]))
64 #define NOT_DSC_LINE(str) (((str)[0]!='%') || ((str)[1]!='%'))
65
66 /* Macros for document offset to start and end of line */
67 #define DSC_START(dsc) ((dsc)->data_offset + (dsc)->data_index - (dsc)->line_length)
68 #define DSC_END(dsc) ((dsc)->data_offset + (dsc)->data_index)
69
70 /* dsc_scan_SECTION() functions return one of
71 * CDSC_ERROR, CDSC_OK, CDSC_NOTDSC
72 * or one of the following
73 */
74 /* The line should be passed on to the next section parser. */
75 #define CDSC_PROPAGATE 10
76
77 /* If document is DOS EPS and we haven't read 30 bytes, ask for more. */
78 #define CDSC_NEEDMORE 11
79
80 /* local prototypes */
81 dsc_private void * dsc_memalloc(CDSC *dsc, size_t size);
82 dsc_private void dsc_memfree(CDSC*dsc, void *ptr);
83 dsc_private CDSC * dsc_init2(CDSC *dsc);
84 dsc_private void dsc_reset(CDSC *dsc);
85 dsc_private void dsc_section_join(DSC_OFFSET begin, DSC_OFFSET *pend, DSC_OFFSET **pplast);
86 dsc_private int dsc_read_line(CDSC *dsc);
87 dsc_private int dsc_read_doseps(CDSC *dsc);
88 dsc_private int dsc_read_macbin(CDSC *dsc);
89 dsc_private int dsc_read_applesingle(CDSC *dsc);
90 dsc_private char * dsc_alloc_string(CDSC *dsc, const char *str, int len);
91 dsc_private char * dsc_add_line(CDSC *dsc, const char *line, unsigned int len);
92 dsc_private char * dsc_copy_string(char *str, unsigned int slen,
93 char *line, unsigned int len, unsigned int *offset);
94 dsc_private GSDWORD dsc_get_dword(const unsigned char *buf);
95 dsc_private GSWORD dsc_get_word(const unsigned char *buf);
96 dsc_private GSDWORD dsc_get_bigendian_dword(const unsigned char *buf);
97 dsc_private GSWORD dsc_get_bigendian_word(const unsigned char *buf);
98 dsc_private int dsc_get_int(const char *line, unsigned int len, unsigned int *offset);
99 dsc_private float dsc_get_real(const char *line, unsigned int len,
100 unsigned int *offset);
101 dsc_private void dsc_unknown(CDSC *dsc);
102 dsc_private GSBOOL dsc_is_section(char *line);
103 dsc_private int dsc_parse_pages(CDSC *dsc);
104 dsc_private int dsc_parse_bounding_box(CDSC *dsc, CDSCBBOX** pbbox, int offset);
105 dsc_private int dsc_parse_float_bounding_box(CDSC *dsc, CDSCFBBOX** pfbbox, int offset);
106 dsc_private int dsc_parse_orientation(CDSC *dsc, unsigned int *porientation,
107 int offset);
108 dsc_private int dsc_parse_order(CDSC *dsc);
109 dsc_private int dsc_parse_media(CDSC *dsc, const CDSCMEDIA **page_media);
110 dsc_private int dsc_parse_document_media(CDSC *dsc);
111 dsc_private int dsc_parse_viewing_orientation(CDSC *dsc, CDSCCTM **pctm);
112 dsc_private int dsc_parse_page(CDSC *dsc);
113 dsc_private void dsc_save_line(CDSC *dsc);
114 dsc_private int dsc_scan_type(CDSC *dsc);
115 dsc_private int dsc_scan_comments(CDSC *dsc);
116 dsc_private int dsc_scan_preview(CDSC *dsc);
117 dsc_private int dsc_scan_defaults(CDSC *dsc);
118 dsc_private int dsc_scan_prolog(CDSC *dsc);
119 dsc_private int dsc_scan_setup(CDSC *dsc);
120 dsc_private int dsc_scan_page(CDSC *dsc);
121 dsc_private int dsc_scan_trailer(CDSC *dsc);
122 dsc_private int dsc_error(CDSC *dsc, unsigned int explanation,
123 char *line, unsigned int line_len);
124 dsc_private int dsc_dcs2_fixup(CDSC *dsc);
125 dsc_private int dsc_parse_platefile(CDSC *dsc);
126 dsc_private int dsc_parse_dcs1plate(CDSC *dsc);
127 dsc_private CDSCCOLOUR * dsc_find_colour(CDSC *dsc, const char *colourname);
128 dsc_private int dsc_parse_process_colours(CDSC *dsc);
129 dsc_private int dsc_parse_custom_colours(CDSC *dsc);
130 dsc_private int dsc_parse_cmyk_custom_colour(CDSC *dsc);
131 dsc_private int dsc_parse_rgb_custom_colour(CDSC *dsc);
132
133 /* DSC error reporting */
134 dsc_private const int dsc_severity[] = {
135 CDSC_ERROR_WARN, /* CDSC_MESSAGE_BBOX */
136 CDSC_ERROR_WARN, /* CDSC_MESSAGE_EARLY_TRAILER */
137 CDSC_ERROR_WARN, /* CDSC_MESSAGE_EARLY_EOF */
138 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGE_IN_TRAILER */
139 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGE_ORDINAL */
140 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_PAGES_WRONG */
141 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_EPS_NO_BBOX */
142 CDSC_ERROR_ERROR, /* CDSC_MESSAGE_EPS_PAGES */
143 CDSC_ERROR_WARN, /* CDSC_MESSAGE_NO_MEDIA */
144 CDSC_ERROR_WARN, /* CDSC_MESSAGE_ATEND */
145 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_DUP_COMMENT */
146 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_DUP_TRAILER */
147 CDSC_ERROR_WARN, /* CDSC_MESSAGE_BEGIN_END */
148 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_BAD_SECTION */
149 CDSC_ERROR_INFORM, /* CDSC_MESSAGE_LONG_LINE */
150 CDSC_ERROR_WARN, /* CDSC_MESSAGE_INCORRECT_USAGE */
151 0
152 };
153
154 #define DSC_MAX_ERROR ((sizeof(dsc_severity) / sizeof(int))-2)
155
156 const CDSCMEDIA dsc_known_media[CDSC_KNOWN_MEDIA] = {
157 /* These sizes taken from Ghostscript gs_statd.ps */
158 {"11x17", 792, 1224, 0, NULL, NULL},
159 {"A3", 842, 1190, 0, NULL, NULL},
160 {"A4", 595, 842, 0, NULL, NULL},
161 {"A5", 421, 595, 0, NULL, NULL},
162 {"B4", 709, 1002, 0, NULL, NULL}, /* ISO, but not Adobe standard */
163 {"B5", 501, 709, 0, NULL, NULL}, /* ISO, but not Adobe standard */
164 {"Ledger", 1224, 792, 0, NULL, NULL},
165 {"Legal", 612, 1008, 0, NULL, NULL},
166 {"Letter", 612, 792, 0, NULL, NULL},
167 {"Note", 612, 792, 0, NULL, NULL},
168 {NULL, 0, 0, 0, NULL, NULL}
169 };
170
171 /* parser state */
172 enum CDSC_SCAN_SECTION {
173 scan_none = 0,
174 scan_comments = 1,
175 scan_pre_preview = 2,
176 scan_preview = 3,
177 scan_pre_defaults = 4,
178 scan_defaults = 5,
179 scan_pre_prolog = 6,
180 scan_prolog = 7,
181 scan_pre_setup = 8,
182 scan_setup = 9,
183 scan_pre_pages = 10,
184 scan_pages = 11,
185 scan_pre_trailer = 12,
186 scan_trailer = 13,
187 scan_eof = 14
188 };
189
190 static const char * const dsc_scan_section_name[15] = {
191 "Type", "Comments",
192 "pre-Preview", "Preview",
193 "pre-Defaults", "Defaults",
194 "pre-Prolog", "Prolog",
195 "pre-Setup", "Setup",
196 "pre-Page", "Page",
197 "pre-Trailer", "Trailer",
198 "EOF"
199 };
200
201
202 /******************************************************************/
203 /* Public functions */
204 /******************************************************************/
205
206 /* constructor */
207 CDSC *
dsc_init(void * caller_data)208 dsc_init(void *caller_data)
209 {
210 CDSC *dsc = (CDSC *)malloc(sizeof(CDSC));
211 if (dsc == NULL)
212 return NULL;
213 memset(dsc, 0, sizeof(CDSC));
214 dsc->caller_data = caller_data;
215 dsc->ref_count = 0;
216 dsc_ref(dsc);
217
218 return dsc_init2(dsc);
219 }
220
221 /* constructor, with caller supplied memalloc */
222 CDSC *
dsc_init_with_alloc(void * caller_data,void * (* memalloc)(size_t size,void * closure_data),void (* memfree)(void * ptr,void * closure_data),void * closure_data)223 dsc_init_with_alloc(
224 void *caller_data,
225 void *(*memalloc)(size_t size, void *closure_data),
226 void (*memfree)(void *ptr, void *closure_data),
227 void *closure_data)
228 {
229 CDSC *dsc = (CDSC *)memalloc(sizeof(CDSC), closure_data);
230 if (dsc == NULL)
231 return NULL;
232 memset(dsc, 0, sizeof(CDSC));
233 dsc->caller_data = caller_data;
234
235 dsc->memalloc = memalloc;
236 dsc->memfree = memfree;
237 dsc->mem_closure_data = closure_data;
238 dsc->ref_count = 0;
239 dsc_ref(dsc);
240
241 return dsc_init2(dsc);
242 }
243
244
245
246 /* destructor */
247 void
dsc_free(CDSC * dsc)248 dsc_free(CDSC *dsc)
249 {
250 if (dsc == NULL)
251 return;
252 dsc_reset(dsc);
253 dsc_memfree(dsc, dsc);
254 }
255
256
257 CDSC *
dsc_new(void * caller_data)258 dsc_new(void *caller_data)
259 {
260 return dsc_init(caller_data);
261 }
262
263 int
dsc_ref(CDSC * dsc)264 dsc_ref(CDSC *dsc)
265 {
266 return ++(dsc->ref_count);
267 }
268
269 int
dsc_unref(CDSC * dsc)270 dsc_unref(CDSC *dsc)
271 {
272 if (dsc->ref_count <= 0)
273 return -1;
274 dsc->ref_count--;
275 if (dsc->ref_count == 0) {
276 dsc_free(dsc);
277 return 0;
278 }
279 return dsc->ref_count;
280 }
281
282
283 /* Tell DSC parser how long document will be, to allow ignoring
284 * of early %%Trailer and %%EOF. This is optional.
285 */
286 void
dsc_set_length(CDSC * dsc,DSC_OFFSET len)287 dsc_set_length(CDSC *dsc, DSC_OFFSET len)
288 {
289 dsc->file_length = len;
290 }
291
292 /* Process a buffer containing DSC comments and PostScript */
293 /* Return value is < 0 for error, >=0 for OK.
294 * CDSC_ERROR
295 * CDSC_OK
296 * CDSC_NOTDSC (DSC will be ignored)
297 * other values indicate the last DSC comment read
298 */
299 int
dsc_scan_data(CDSC * dsc,const char * data,int length)300 dsc_scan_data(CDSC *dsc, const char *data, int length)
301 {
302 int bytes_read;
303 int code = 0;
304
305 if (dsc == NULL)
306 return CDSC_ERROR;
307
308 if (dsc->id == CDSC_NOTDSC)
309 return CDSC_NOTDSC;
310 dsc->id = CDSC_OK;
311 if (dsc->eof)
312 return CDSC_OK; /* ignore */
313
314 if (length == 0) {
315 /* EOF, so process what remains */
316 dsc->eof = TRUE;
317 }
318
319 do {
320 if (dsc->id == CDSC_NOTDSC)
321 break;
322
323 if (length != 0) {
324 /* move existing data if needed */
325 if (dsc->data_length > CDSC_DATA_LENGTH/2) {
326 memmove(dsc->data, dsc->data + dsc->data_index,
327 dsc->data_length - dsc->data_index);
328 dsc->data_offset += dsc->data_index;
329 dsc->data_length -= dsc->data_index;
330 dsc->data_index = 0;
331 }
332 /* append to buffer */
333 bytes_read = min(length, (int)(CDSC_DATA_LENGTH - dsc->data_length));
334 memcpy(dsc->data + dsc->data_length, data, bytes_read);
335 dsc->data_length += bytes_read;
336 data += bytes_read;
337 length -= bytes_read;
338 }
339 if (dsc->scan_section == scan_none) {
340 code = dsc_scan_type(dsc);
341 if (code == CDSC_NEEDMORE) {
342 /* need more characters before we can identify type */
343 code = CDSC_OK;
344 break;
345 }
346 dsc->id = code;
347 }
348
349 if (code == CDSC_NOTDSC) {
350 dsc->id = CDSC_NOTDSC;
351 break;
352 }
353
354 while ((code = dsc_read_line(dsc)) > 0) {
355 if (dsc->id == CDSC_NOTDSC)
356 break;
357 if (dsc->file_length &&
358 (dsc->data_offset + dsc->data_index > dsc->file_length)) {
359 /* have read past end of where we need to parse. */
360 return CDSC_OK; /* ignore */
361 }
362 if (dsc->doseps_end &&
363 (dsc->data_offset + dsc->data_index > dsc->doseps_end)) {
364 /* have read past end of DOS EPS or Mac Binary
365 * PostScript section
366 */
367 return CDSC_OK; /* ignore */
368 }
369 if (dsc->eof)
370 return CDSC_OK;
371 if (dsc->skip_document)
372 continue; /* embedded document */
373 if (dsc->skip_lines)
374 continue; /* embedded lines */
375 if (IS_DSC(dsc->line, "%%BeginData:"))
376 continue;
377 if (IS_DSC(dsc->line, "%%BeginBinary:"))
378 continue;
379 if (IS_DSC(dsc->line, "%%EndDocument"))
380 continue;
381 if (IS_DSC(dsc->line, "%%EndData"))
382 continue;
383 if (IS_DSC(dsc->line, "%%EndBinary"))
384 continue;
385
386 do {
387 switch (dsc->scan_section) {
388 case scan_comments:
389 code = dsc_scan_comments(dsc);
390 break;
391 case scan_pre_preview:
392 case scan_preview:
393 code = dsc_scan_preview(dsc);
394 break;
395 case scan_pre_defaults:
396 case scan_defaults:
397 code = dsc_scan_defaults(dsc);
398 break;
399 case scan_pre_prolog:
400 case scan_prolog:
401 code = dsc_scan_prolog(dsc);
402 break;
403 case scan_pre_setup:
404 case scan_setup:
405 code = dsc_scan_setup(dsc);
406 break;
407 case scan_pre_pages:
408 case scan_pages:
409 code = dsc_scan_page(dsc);
410 break;
411 case scan_pre_trailer:
412 case scan_trailer:
413 code = dsc_scan_trailer(dsc);
414 break;
415 case scan_eof:
416 code = CDSC_OK;
417 break;
418 default:
419 /* invalid state */
420 code = CDSC_ERROR;
421 }
422 /* repeat if line is start of next section */
423 } while (code == CDSC_PROPAGATE);
424
425 /* if DOS EPS header not complete, ask for more */
426 if (code == CDSC_NEEDMORE) {
427 code = CDSC_OK;
428 break;
429 }
430 if (code == CDSC_NOTDSC) {
431 dsc->id = CDSC_NOTDSC;
432 break;
433 }
434 }
435 } while (length != 0);
436
437 return (code < 0) ? code : dsc->id;
438 }
439
440 /* Tidy up from incorrect DSC comments */
441 int
dsc_fixup(CDSC * dsc)442 dsc_fixup(CDSC *dsc)
443 {
444 unsigned int i;
445 char buf[32];
446 DSC_OFFSET *last;
447
448 if (dsc->id == CDSC_NOTDSC)
449 return 0;
450
451 /* flush last partial line */
452 dsc_scan_data(dsc, NULL, 0);
453
454
455 /* Fix DSC error: EOF before end of %%BeginData */
456 if (dsc->eof &&
457 (dsc->skip_lines || dsc->skip_bytes || dsc->skip_document)) {
458 switch (dsc->scan_section) {
459 case scan_comments:
460 dsc->endcomments = DSC_END(dsc);
461 break;
462 case scan_preview:
463 dsc->endpreview = DSC_END(dsc);
464 break;
465 case scan_defaults:
466 dsc->enddefaults = DSC_END(dsc);
467 break;
468 case scan_prolog:
469 dsc->endprolog = DSC_END(dsc);
470 break;
471 case scan_setup:
472 dsc->endsetup = DSC_END(dsc);
473 break;
474 case scan_pages:
475 if (dsc->page_count)
476 dsc->page[dsc->page_count-1].end = DSC_END(dsc);
477 break;
478 case scan_trailer:
479 case scan_eof:
480 dsc->endtrailer = DSC_END(dsc);
481 break;
482 }
483 }
484
485 /* Fix DSC error: code between %%EndSetup and %%Page */
486 if (dsc->page_count && (dsc->page[0].begin != dsc->endsetup)
487 && (dsc->endsetup != dsc->beginsetup)) {
488 dsc->endsetup = dsc->page[0].begin;
489 dsc_debug_print(dsc, "Warning: code included between setup and first page\n");
490 }
491
492 /* Last page contained a false trailer, */
493 /* so extend last page to start of trailer */
494 if (dsc->page_count && (dsc->begintrailer != 0) &&
495 (dsc->page[dsc->page_count-1].end != dsc->begintrailer)) {
496 dsc_debug_print(dsc, "Ignoring earlier misplaced trailer\n");
497 dsc_debug_print(dsc, "and extending last page to start of trailer\n");
498 dsc->page[dsc->page_count-1].end = dsc->begintrailer;
499 }
500
501 /*
502 * Join up all sections.
503 * There might be extra code between them, or we might have
504 * missed including the \n which followed \r.
505 */
506 last = &dsc->endcomments;
507 dsc_section_join(dsc->beginpreview, &dsc->endpreview, &last);
508 dsc_section_join(dsc->begindefaults, &dsc->enddefaults, &last);
509 dsc_section_join(dsc->beginprolog, &dsc->endprolog, &last);
510 dsc_section_join(dsc->beginsetup, &dsc->endsetup, &last);
511 for (i=0; i<dsc->page_count; i++)
512 dsc_section_join(dsc->page[i].begin, &dsc->page[i].end, &last);
513 if (dsc->begintrailer)
514 *last = dsc->begintrailer;
515
516 if ((dsc->page_pages == 0) && (dsc->page_count == 1)) {
517 /* don't flag an error if %%Pages absent but one %%Page found */
518 /* adjust incorrect page count */
519 dsc->page_pages = dsc->page_count;
520 }
521
522 /* Warnings and Errors that we can now identify */
523 if ((dsc->page_count != dsc->page_pages)) {
524 int rc = dsc_error(dsc, CDSC_MESSAGE_PAGES_WRONG, NULL, 0);
525 switch (rc) {
526 case CDSC_RESPONSE_OK:
527 /* adjust incorrect page count */
528 dsc->page_pages = dsc->page_count;
529 break;
530 case CDSC_RESPONSE_CANCEL:
531 break;;
532 case CDSC_RESPONSE_IGNORE_ALL:
533 return CDSC_NOTDSC;
534 }
535 }
536
537 if (dsc->epsf && (dsc->bbox == (CDSCBBOX *)NULL)) {
538 /* EPS files MUST include a BoundingBox */
539 int rc = dsc_error(dsc, CDSC_MESSAGE_EPS_NO_BBOX, NULL, 0);
540 switch (rc) {
541 case CDSC_RESPONSE_OK:
542 /* Assume that it is EPS */
543 break;
544 case CDSC_RESPONSE_CANCEL:
545 /* Is NOT an EPS file */
546 dsc->epsf = FALSE;
547 case CDSC_RESPONSE_IGNORE_ALL:
548 return CDSC_NOTDSC;
549 }
550 }
551
552 if (dsc->epsf && ((dsc->page_count > 1) || (dsc->page_pages > 1))) {
553 int rc = dsc_error(dsc, CDSC_MESSAGE_EPS_PAGES, NULL, 0);
554 switch (rc) {
555 case CDSC_RESPONSE_OK:
556 /* Is an EPS file */
557 break;
558 case CDSC_RESPONSE_CANCEL:
559 /* Is NOT an EPS file */
560 dsc->epsf = FALSE;
561 break;
562 case CDSC_RESPONSE_IGNORE_ALL:
563 return CDSC_NOTDSC;
564 }
565 }
566
567 /* convert single file DSC 2.0 into multiple pages */
568 dsc_dcs2_fixup(dsc);
569
570 if ((dsc->media_count == 1) && (dsc->page_media == NULL)) {
571 /* if one only media was specified, and default page media */
572 /* was not specified, assume that default is the only media. */
573 dsc->page_media = dsc->media[0];
574 }
575
576 if ((dsc->media_count != 0) && (dsc->page_media == NULL)) {
577 int rc = dsc_error(dsc, CDSC_MESSAGE_NO_MEDIA, NULL, 0);
578 switch (rc) {
579 case CDSC_RESPONSE_OK:
580 /* default media is first listed */
581 dsc->page_media = dsc->media[0];
582 break;
583 case CDSC_RESPONSE_CANCEL:
584 /* No default media */
585 break;
586 case CDSC_RESPONSE_IGNORE_ALL:
587 return CDSC_NOTDSC;
588 }
589 }
590
591 /* make sure all pages have a label */
592 for (i=0; i<dsc->page_count; i++) {
593 if (strlen(dsc->page[i].label) == 0) {
594 sprintf(buf, "%d", i+1);
595 if ((dsc->page[i].label = dsc_alloc_string(dsc, buf, (int)strlen(buf)))
596 == (char *)NULL)
597 return CDSC_ERROR; /* no memory */
598 }
599 }
600 return CDSC_OK;
601 }
602
603 /* Install a function to be used for displaying messages about
604 * DSC errors and warnings, and to request advice from user.
605 * Installing an error function is optional.
606 */
607 void
dsc_set_error_function(CDSC * dsc,int (* fn)(void * caller_data,CDSC * dsc,unsigned int explanation,const char * line,unsigned int line_len))608 dsc_set_error_function(CDSC *dsc,
609 int (*fn)(void *caller_data, CDSC *dsc,
610 unsigned int explanation, const char *line, unsigned int line_len))
611 {
612 dsc->dsc_error_fn = fn;
613 }
614
615
616 /* Install a function for printing debug messages */
617 /* This is optional */
618 void
dsc_set_debug_function(CDSC * dsc,void (* debug_fn)(void * caller_data,const char * str))619 dsc_set_debug_function(CDSC *dsc,
620 void (*debug_fn)(void *caller_data, const char *str))
621 {
622 dsc->debug_print_fn = debug_fn;
623 }
624
625 /* Doesn't need to be public for PostScript documents */
626 /* Made public so GSview can add pages when processing PDF files */
627 int
dsc_add_page(CDSC * dsc,int ordinal,char * label)628 dsc_add_page(CDSC *dsc, int ordinal, char *label)
629 {
630 dsc->page[dsc->page_count].ordinal = ordinal;
631 dsc->page[dsc->page_count].label =
632 dsc_alloc_string(dsc, label, (int)strlen(label)+1);
633 dsc->page[dsc->page_count].begin = 0;
634 dsc->page[dsc->page_count].end = 0;
635 dsc->page[dsc->page_count].orientation = CDSC_ORIENT_UNKNOWN;
636 dsc->page[dsc->page_count].media = NULL;
637 dsc->page[dsc->page_count].bbox = NULL;
638 dsc->page[dsc->page_count].viewing_orientation = NULL;
639 dsc->page[dsc->page_count].crop_box = NULL;
640
641 dsc->page_count++;
642 if (dsc->page_count >= dsc->page_chunk_length) {
643 CDSCPAGE *new_page = (CDSCPAGE *)dsc_memalloc(dsc,
644 (CDSC_PAGE_CHUNK+dsc->page_count) * sizeof(CDSCPAGE));
645 if (new_page == NULL)
646 return CDSC_ERROR; /* out of memory */
647 memcpy(new_page, dsc->page,
648 dsc->page_count * sizeof(CDSCPAGE));
649 dsc_memfree(dsc, dsc->page);
650 dsc->page= new_page;
651 dsc->page_chunk_length = CDSC_PAGE_CHUNK+dsc->page_count;
652 }
653 return CDSC_OK;
654 }
655
656 /* Doesn't need to be public for PostScript documents */
657 /* Made public so GSview can store PDF MediaBox */
658 int
dsc_add_media(CDSC * dsc,CDSCMEDIA * media)659 dsc_add_media(CDSC *dsc, CDSCMEDIA *media)
660 {
661 CDSCMEDIA **newmedia_array;
662 CDSCMEDIA *newmedia;
663
664 /* extend media array */
665 newmedia_array = (CDSCMEDIA **)dsc_memalloc(dsc,
666 (dsc->media_count + 1) * sizeof(CDSCMEDIA *));
667 if (newmedia_array == NULL)
668 return CDSC_ERROR; /* out of memory */
669 if (dsc->media != NULL) {
670 memcpy(newmedia_array, dsc->media,
671 dsc->media_count * sizeof(CDSCMEDIA *));
672 dsc_memfree(dsc, dsc->media);
673 }
674 dsc->media = newmedia_array;
675
676 /* allocate new media */
677 newmedia = dsc->media[dsc->media_count] =
678 (CDSCMEDIA *)dsc_memalloc(dsc, sizeof(CDSCMEDIA));
679 if (newmedia == NULL)
680 return CDSC_ERROR; /* out of memory */
681 newmedia->name = NULL;
682 newmedia->width = 595.0;
683 newmedia->height = 842.0;
684 newmedia->weight = 80.0;
685 newmedia->colour = NULL;
686 newmedia->type = NULL;
687 newmedia->mediabox = NULL;
688
689 dsc->media_count++;
690
691 if (media->name) {
692 newmedia->name = dsc_alloc_string(dsc, media->name,
693 (int)strlen(media->name));
694 if (newmedia->name == NULL)
695 return CDSC_ERROR; /* no memory */
696 }
697 newmedia->width = media->width;
698 newmedia->height = media->height;
699 newmedia->weight = media->weight;
700 if (media->colour) {
701 newmedia->colour = dsc_alloc_string(dsc, media->colour,
702 (int)strlen(media->colour));
703 if (newmedia->colour == NULL)
704 return CDSC_ERROR; /* no memory */
705 }
706 if (media->type) {
707 newmedia->type = dsc_alloc_string(dsc, media->type,
708 (int)strlen(media->type));
709 if (newmedia->type == NULL)
710 return CDSC_ERROR; /* no memory */
711 }
712 newmedia->mediabox = NULL;
713
714 if (media->mediabox) {
715 newmedia->mediabox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
716 if (newmedia->mediabox == NULL)
717 return CDSC_ERROR; /* no memory */
718 *newmedia->mediabox = *media->mediabox;
719 }
720 return CDSC_OK;
721 }
722
723 /* Doesn't need to be public for PostScript documents */
724 /* Made public so GSview can store PDF CropBox */
725 int
dsc_set_page_bbox(CDSC * dsc,unsigned int page_number,int llx,int lly,int urx,int ury)726 dsc_set_page_bbox(CDSC *dsc, unsigned int page_number,
727 int llx, int lly, int urx, int ury)
728 {
729 CDSCBBOX *bbox;
730 if (page_number >= dsc->page_count)
731 return CDSC_ERROR;
732 bbox = dsc->page[page_number].bbox;
733 if (bbox == NULL)
734 dsc->page[page_number].bbox = bbox =
735 (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
736 if (bbox == NULL)
737 return CDSC_ERROR;
738 bbox->llx = llx;
739 bbox->lly = lly;
740 bbox->urx = urx;
741 bbox->ury = ury;
742 return CDSC_OK;
743 }
744
745
746 /******************************************************************/
747 /* Private functions below here. */
748 /******************************************************************/
749
750 dsc_private void *
dsc_memalloc(CDSC * dsc,size_t size)751 dsc_memalloc(CDSC *dsc, size_t size)
752 {
753 if (dsc->memalloc)
754 return dsc->memalloc(size, dsc->mem_closure_data);
755 return malloc(size);
756 }
757
758 dsc_private void
dsc_memfree(CDSC * dsc,void * ptr)759 dsc_memfree(CDSC*dsc, void *ptr)
760 {
761 if (dsc->memfree)
762 dsc->memfree(ptr, dsc->mem_closure_data);
763 else
764 free(ptr);
765 }
766
767 /* private constructor */
768 dsc_private CDSC *
dsc_init2(CDSC * dsc)769 dsc_init2(CDSC *dsc)
770 {
771 dsc_reset(dsc);
772
773 dsc->string_head = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
774 if (dsc->string_head == NULL) {
775 dsc_free(dsc);
776 return NULL; /* no memory */
777 }
778 dsc->string = dsc->string_head;
779 dsc->string->next = NULL;
780 dsc->string->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
781 if (dsc->string->data == NULL) {
782 dsc_free(dsc);
783 return NULL; /* no memory */
784 }
785 dsc->string->index = 0;
786 dsc->string->length = CDSC_STRING_CHUNK;
787
788 dsc->page = (CDSCPAGE *)dsc_memalloc(dsc, CDSC_PAGE_CHUNK * sizeof(CDSCPAGE));
789 if (dsc->page == NULL) {
790 dsc_free(dsc);
791 return NULL; /* no memory */
792 }
793 dsc->page_chunk_length = CDSC_PAGE_CHUNK;
794 dsc->page_count = 0;
795
796 dsc->line = NULL;
797 dsc->data_length = 0;
798 dsc->data_index = dsc->data_length;
799
800 return dsc;
801 }
802
803
804 dsc_private void
dsc_reset(CDSC * dsc)805 dsc_reset(CDSC *dsc)
806 {
807 unsigned int i;
808 /* Clear public members */
809 dsc->dsc = FALSE;
810 dsc->ctrld = FALSE;
811 dsc->pjl = FALSE;
812 dsc->epsf = FALSE;
813 dsc->pdf = FALSE;
814 dsc->epsf = FALSE;
815 dsc->preview = CDSC_NOPREVIEW;
816 dsc->dsc_version = NULL; /* stored in dsc->string */
817 dsc->language_level = 0;
818 dsc->document_data = CDSC_DATA_UNKNOWN;
819 dsc->begincomments = 0;
820 dsc->endcomments = 0;
821 dsc->beginpreview = 0;
822 dsc->endpreview = 0;
823 dsc->begindefaults = 0;
824 dsc->enddefaults = 0;
825 dsc->beginprolog = 0;
826 dsc->endprolog = 0;
827 dsc->beginsetup = 0;
828 dsc->endsetup = 0;
829 dsc->begintrailer = 0;
830 dsc->endtrailer = 0;
831
832 for (i=0; i<dsc->page_count; i++) {
833 /* page media is pointer to an element of media or dsc_known_media */
834 /* do not free it. */
835
836 if (dsc->page[i].bbox)
837 dsc_memfree(dsc, dsc->page[i].bbox);
838 if (dsc->page[i].viewing_orientation)
839 dsc_memfree(dsc, dsc->page[i].viewing_orientation);
840 if (dsc->page[i].crop_box)
841 dsc_memfree(dsc, dsc->page[i].crop_box);
842 }
843 if (dsc->page)
844 dsc_memfree(dsc, dsc->page);
845 dsc->page = NULL;
846
847 dsc->page_count = 0;
848 dsc->page_pages = 0;
849 dsc->page_order = CDSC_ORDER_UNKNOWN;
850 dsc->page_orientation = CDSC_ORIENT_UNKNOWN;
851 if (dsc->viewing_orientation)
852 dsc_memfree(dsc, dsc->viewing_orientation);
853 dsc->viewing_orientation = NULL;
854
855 if (dsc->media) {
856 for (i=0; i<dsc->media_count; i++) {
857 if (dsc->media[i]) {
858 if (dsc->media[i]->mediabox)
859 dsc_memfree(dsc, dsc->media[i]->mediabox);
860 dsc_memfree(dsc, dsc->media[i]);
861 }
862 }
863 dsc_memfree(dsc, dsc->media);
864 }
865 dsc->media_count = 0;
866 dsc->media = NULL;
867
868 /* page_media is pointer to an element of media or dsc_known_media */
869 /* do not free it. */
870 dsc->page_media = NULL;
871
872 if (dsc->bbox)
873 dsc_memfree(dsc, dsc->bbox);
874 dsc->bbox = NULL;
875 if (dsc->page_bbox)
876 dsc_memfree(dsc, dsc->page_bbox);
877 dsc->page_bbox = NULL;
878 if (dsc->doseps)
879 dsc_memfree(dsc, dsc->doseps);
880 dsc->doseps = NULL;
881
882 dsc->dsc_title = NULL;
883 dsc->dsc_creator = NULL;
884 dsc->dsc_date = NULL;
885 dsc->dsc_for = NULL;
886
887
888 dsc->max_error = DSC_MAX_ERROR;
889 dsc->severity = dsc_severity;
890
891 /* Clear private members */
892 /* Don't touch dsc->caller_data */
893 dsc->id = CDSC_OK;
894 dsc->scan_section = scan_none;
895 dsc->doseps_end = 0;
896 dsc->page_chunk_length = 0;
897 dsc->file_length = 0;
898 dsc->skip_document = 0;
899 dsc->skip_bytes = 0;
900 dsc->skip_lines = 0;
901 dsc->skip_pjl = 0;
902 dsc->begin_font_count = 0;
903 dsc->begin_feature_count = 0;
904 dsc->begin_resource_count = 0;
905 dsc->begin_procset_count = 0;
906
907 dsc->data_length = 0;
908 dsc->data_index = 0;
909 dsc->data_offset = 0;
910
911 dsc->eof = 0;
912
913 dsc->line = 0;
914 dsc->line_length = 0;
915 dsc->eol = 0;
916 dsc->last_cr = FALSE;
917 dsc->line_count = 1;
918 dsc->long_line = FALSE;
919 memset(dsc->last_line, 0, sizeof(dsc->last_line));
920
921 dsc->string = dsc->string_head;
922 while (dsc->string != (CDSCSTRING *)NULL) {
923 if (dsc->string->data)
924 dsc_memfree(dsc, dsc->string->data);
925 dsc->string_head = dsc->string;
926 dsc->string = dsc->string->next;
927 dsc_memfree(dsc, dsc->string_head);
928 }
929 dsc->string_head = NULL;
930 dsc->string = NULL;
931
932 /* don't touch caller functions */
933
934 /* public data */
935 if (dsc->hires_bbox)
936 dsc_memfree(dsc, dsc->hires_bbox);
937 dsc->hires_bbox = NULL;
938 if (dsc->crop_box)
939 dsc_memfree(dsc, dsc->crop_box);
940 dsc->crop_box = NULL;
941
942 if (dsc->dcs2) {
943 CDCS2 *this_dcs, *next_dcs;
944 this_dcs = dsc->dcs2;
945 while (this_dcs) {
946 next_dcs = this_dcs->next;
947 /* strings have already been freed */
948 dsc_memfree(dsc, this_dcs);
949 this_dcs = next_dcs;
950 }
951 dsc->dcs2 = NULL;
952 }
953 if (dsc->colours) {
954 CDSCCOLOUR *this_colour, *next_colour;
955 this_colour = dsc->colours;
956 while (this_colour) {
957 next_colour = this_colour->next;
958 /* strings have already been freed */
959 dsc_memfree(dsc, this_colour);
960 this_colour = next_colour;
961 }
962 dsc->colours = NULL;
963 }
964
965 if (dsc->macbin)
966 dsc_memfree(dsc, dsc->macbin);
967 dsc->macbin = NULL;
968 }
969
970 /*
971 * Join up all sections.
972 * There might be extra code between them, or we might have
973 * missed including the \n which followed \r.
974 * begin is the start of this section
975 * pend is a pointer to the end of this section
976 * pplast is a pointer to a pointer of the end of the previous section
977 */
978 dsc_private void
dsc_section_join(DSC_OFFSET begin,DSC_OFFSET * pend,DSC_OFFSET ** pplast)979 dsc_section_join(DSC_OFFSET begin, DSC_OFFSET *pend, DSC_OFFSET **pplast)
980 {
981 if (begin)
982 **pplast = begin;
983 if (*pend > begin)
984 *pplast = pend;
985 }
986
987
988 /* return value is 0 if no line available, or length of line */
989 dsc_private int
dsc_read_line(CDSC * dsc)990 dsc_read_line(CDSC *dsc)
991 {
992 char *p, *last;
993 dsc->line = NULL;
994
995 if (dsc->eof) {
996 /* return all that remains, even if line incomplete */
997 dsc->line = dsc->data + dsc->data_index;
998 dsc->line_length = dsc->data_length - dsc->data_index;
999 dsc->data_index = dsc->data_length;
1000 return dsc->line_length;
1001 }
1002
1003 if (dsc->file_length &&
1004 (dsc->data_offset + dsc->data_index >= dsc->file_length)) {
1005 /* Have read past where we need to parse. */
1006 /* Ignore all that remains. */
1007 dsc->line = dsc->data + dsc->data_index;
1008 dsc->line_length = dsc->data_length - dsc->data_index;
1009 dsc->data_index = dsc->data_length;
1010 return dsc->line_length;
1011
1012 }
1013 if (dsc->doseps_end &&
1014 (dsc->data_offset + dsc->data_index >= dsc->doseps_end)) {
1015 /* Have read past end of DOS EPS PostScript section. */
1016 /* Ignore all that remains. */
1017 dsc->line = dsc->data + dsc->data_index;
1018 dsc->line_length = dsc->data_length - dsc->data_index;
1019 dsc->data_index = dsc->data_length;
1020 return dsc->line_length;
1021 }
1022
1023 /* ignore embedded bytes */
1024 if (dsc->skip_bytes) {
1025 int cnt = min(dsc->skip_bytes,
1026 (int)(dsc->data_length - dsc->data_index));
1027 dsc->skip_bytes -= cnt;
1028 dsc->data_index += cnt;
1029 if (dsc->skip_bytes != 0)
1030 return 0;
1031 }
1032
1033 do {
1034 dsc->line = dsc->data + dsc->data_index;
1035 last = dsc->data + dsc->data_length;
1036 if (dsc->data_index == dsc->data_length) {
1037 dsc->line_length = 0;
1038 return 0;
1039 }
1040 if (dsc->eol) {
1041 /* if previous line was complete, increment line count */
1042 dsc->line_count++;
1043 if (dsc->skip_lines)
1044 dsc->skip_lines--;
1045 }
1046
1047 /* skip over \n which followed \r */
1048 if (dsc->last_cr && dsc->line[0] == '\n') {
1049 dsc->data_index++;
1050 dsc->line++;
1051 }
1052 dsc->last_cr = FALSE;
1053
1054 /* look for EOL */
1055 dsc->eol = FALSE;
1056 for (p = dsc->line; p < last; p++) {
1057 if (*p == '\r') {
1058 p++;
1059 if ((p<last) && (*p == '\n'))
1060 p++; /* include line feed also */
1061 else
1062 dsc->last_cr = TRUE; /* we might need to skip \n */
1063 dsc->eol = TRUE; /* dsc->line is a complete line */
1064 break;
1065 }
1066 if (*p == '\n') {
1067 p++;
1068 dsc->eol = TRUE; /* dsc->line is a complete line */
1069 break;
1070 }
1071 if (*p == '\032') { /* MS-DOS Ctrl+Z */
1072 dsc->eol = TRUE;
1073 }
1074 }
1075 if (dsc->eol == FALSE) {
1076 /* we haven't got a complete line yet */
1077 if (dsc->data_length - dsc->data_index < sizeof(dsc->data)/2) {
1078 /* buffer is less than half full, ask for some more */
1079 dsc->line_length = 0;
1080 return 0;
1081 }
1082 }
1083 dsc->data_index += dsc->line_length = (int)(p - dsc->line);
1084 } while (dsc->skip_lines && dsc->line_length);
1085
1086 if (dsc->line_length == 0)
1087 return 0;
1088
1089 if ((dsc->line[0]=='%') && (dsc->line[1]=='%')) {
1090 /* handle recursive %%BeginDocument */
1091 if ((dsc->skip_document) && dsc->line_length &&
1092 COMPARE(dsc->line, "%%EndDocument")) {
1093 dsc->skip_document--;
1094 }
1095
1096 /* handle embedded lines or binary data */
1097 if (COMPARE(dsc->line, "%%BeginData:")) {
1098 /* %%BeginData: <numberof>[ <type> [ <bytesorlines> ] ]
1099 * <numberof> ::= <uint> (Lines or physical bytes)
1100 * <type> ::= Hex | Binary | ASCII (Type of data)
1101 * <bytesorlines> ::= Bytes | Lines (Read in bytes or lines)
1102 */
1103 char begindata[MAXSTR+1];
1104 int cnt;
1105 const char *numberof, *bytesorlines;
1106 cnt = dsc->line_length;
1107 if (dsc->line_length > sizeof(begindata)-1)
1108 cnt = sizeof(begindata)-1;
1109 memcpy(begindata, dsc->line, cnt);
1110 begindata[cnt] = '\0';
1111 numberof = strtok(begindata+12, " \r\n");
1112 strtok(NULL, " \r\n"); /* dump type */
1113 bytesorlines = strtok(NULL, " \r\n");
1114 if (bytesorlines == NULL)
1115 bytesorlines = "Bytes";
1116
1117 if ( (numberof == NULL) || (bytesorlines == NULL) ) {
1118 /* invalid usage of %%BeginData */
1119 /* ignore that we ever saw it */
1120 int rc = dsc_error(dsc, CDSC_MESSAGE_INCORRECT_USAGE,
1121 dsc->line, dsc->line_length);
1122 switch (rc) {
1123 case CDSC_RESPONSE_OK:
1124 case CDSC_RESPONSE_CANCEL:
1125 break;
1126 case CDSC_RESPONSE_IGNORE_ALL:
1127 return 0;
1128 }
1129 }
1130 else {
1131 cnt = atoi(numberof);
1132 if (cnt) {
1133 if (bytesorlines && (dsc_stricmp(bytesorlines, "Lines")==0)) {
1134 /* skip cnt lines */
1135 if (dsc->skip_lines == 0) {
1136 /* we are not already skipping lines */
1137 dsc->skip_lines = cnt+1;
1138 }
1139 }
1140 else {
1141 /* byte count doesn't includes \n or \r\n */
1142 /* or \r of %%BeginData: */
1143 /* skip cnt bytes */
1144 if (dsc->skip_bytes == 0) {
1145 /* we are not already skipping lines */
1146 dsc->skip_bytes = cnt;
1147 }
1148
1149 }
1150 }
1151 }
1152 }
1153 else if (COMPARE(dsc->line, "%%BeginBinary:")) {
1154 /* byte count doesn't includes \n or \r\n or \r of %%BeginBinary:*/
1155 int cnt = dsc_get_int(dsc->line + 14,
1156 dsc->line_length - 14, NULL);
1157 if (dsc->skip_bytes == 0) {
1158 /* we are not already skipping lines */
1159 dsc->skip_bytes = cnt;
1160 }
1161 }
1162 }
1163
1164 if ((dsc->line[0]=='%') && (dsc->line[1]=='%') &&
1165 COMPARE(dsc->line, "%%BeginDocument:") ) {
1166 /* Skip over embedded document, recursively */
1167 dsc->skip_document++;
1168 }
1169
1170 if (!dsc->long_line && (dsc->line_length > DSC_LINE_LENGTH)) {
1171 dsc_error(dsc, CDSC_MESSAGE_LONG_LINE, dsc->line, dsc->line_length);
1172 dsc->long_line = TRUE;
1173 }
1174
1175 return dsc->line_length;
1176 }
1177
1178
1179 /* Save last DSC line, for use with %%+ */
1180 dsc_private void
dsc_save_line(CDSC * dsc)1181 dsc_save_line(CDSC *dsc)
1182 {
1183 int len = min(sizeof(dsc->last_line), dsc->line_length);
1184 memcpy(dsc->last_line, dsc->line, len);
1185 }
1186
1187 /* display unknown DSC line */
1188 dsc_private void
dsc_unknown(CDSC * dsc)1189 dsc_unknown(CDSC *dsc)
1190 {
1191 if (dsc->debug_print_fn) {
1192 char line[DSC_LINE_LENGTH];
1193 unsigned int length = min(DSC_LINE_LENGTH-1, dsc->line_length);
1194 sprintf(line, "Unknown in %s section at line %d:\n ",
1195 dsc_scan_section_name[dsc->scan_section], dsc->line_count);
1196 dsc_debug_print(dsc, line);
1197 strncpy(line, dsc->line, length);
1198 line[length] = '\0';
1199 dsc_debug_print(dsc, line);
1200 dsc_debug_print(dsc, "\n");
1201 }
1202 }
1203
1204
1205 dsc_private GSBOOL
dsc_is_section(char * line)1206 dsc_is_section(char *line)
1207 {
1208 if ( !((line[0]=='%') && (line[1]=='%')) )
1209 return FALSE;
1210 if (IS_DSC(line, "%%BeginPreview"))
1211 return TRUE;
1212 if (IS_DSC(line, "%%BeginDefaults"))
1213 return TRUE;
1214 if (IS_DSC(line, "%%BeginProlog"))
1215 return TRUE;
1216 if (IS_DSC(line, "%%BeginSetup"))
1217 return TRUE;
1218 if (IS_DSC(line, "%%Page:"))
1219 return TRUE;
1220 if (IS_DSC(line, "%%Trailer"))
1221 return TRUE;
1222 if (IS_DSC(line, "%%EOF"))
1223 return TRUE;
1224 return FALSE;
1225 }
1226
1227 /* Get little-endian DWORD, used for DOS EPS files */
1228 dsc_private GSDWORD
dsc_get_dword(const unsigned char * buf)1229 dsc_get_dword(const unsigned char *buf)
1230 {
1231 GSDWORD dw;
1232 dw = (GSDWORD)buf[0];
1233 dw += ((GSDWORD)buf[1])<<8;
1234 dw += ((GSDWORD)buf[2])<<16;
1235 dw += ((GSDWORD)buf[3])<<24;
1236 return dw;
1237 }
1238
1239 dsc_private GSWORD
dsc_get_word(const unsigned char * buf)1240 dsc_get_word(const unsigned char *buf)
1241 {
1242 GSWORD w;
1243 w = (GSWORD)buf[0];
1244 w |= (GSWORD)(buf[1]<<8);
1245 return w;
1246 }
1247
1248 /* Get big-endian DWORD, used for Mac Binary files */
1249 dsc_private GSDWORD
dsc_get_bigendian_dword(const unsigned char * buf)1250 dsc_get_bigendian_dword(const unsigned char *buf)
1251 {
1252 GSDWORD dw;
1253 dw = (GSDWORD)buf[3];
1254 dw += ((GSDWORD)buf[2])<<8;
1255 dw += ((GSDWORD)buf[1])<<16;
1256 dw += ((GSDWORD)buf[0])<<24;
1257 return dw;
1258 }
1259
1260 dsc_private GSWORD
dsc_get_bigendian_word(const unsigned char * buf)1261 dsc_get_bigendian_word(const unsigned char *buf)
1262 {
1263 GSWORD w;
1264 w = (GSWORD)buf[1];
1265 w |= (GSWORD)(buf[0]<<8);
1266 return w;
1267 }
1268
1269 dsc_private int
dsc_read_doseps(CDSC * dsc)1270 dsc_read_doseps(CDSC *dsc)
1271 {
1272 unsigned char *line = (unsigned char *)dsc->line;
1273 if ((dsc->doseps = (CDSCDOSEPS *)dsc_memalloc(dsc, sizeof(CDSCDOSEPS))) == NULL)
1274 return CDSC_ERROR; /* no memory */
1275
1276 dsc->doseps->ps_begin = dsc_get_dword(line+4);
1277 dsc->doseps->ps_length = dsc_get_dword(line+8);
1278 dsc->doseps->wmf_begin = dsc_get_dword(line+12);
1279 dsc->doseps->wmf_length = dsc_get_dword(line+16);
1280 dsc->doseps->tiff_begin = dsc_get_dword(line+20);
1281 dsc->doseps->tiff_length = dsc_get_dword(line+24);
1282 dsc->doseps->checksum = dsc_get_word(line+28);
1283
1284 if (dsc->file_length &&
1285 (dsc->doseps->ps_begin + dsc->doseps->ps_length > dsc->file_length)) {
1286 /* Error in DOS EPS header.
1287 * Some files have been seen with a fixed large value as
1288 * the length of the PostScript section.
1289 * Correct for these erroneous files.
1290 */
1291 dsc->doseps->ps_length =
1292 (GSDWORD)(dsc->file_length - dsc->doseps->ps_begin);
1293 }
1294
1295 dsc->doseps_end = dsc->doseps->ps_begin + dsc->doseps->ps_length;
1296
1297 /* move data_index backwards to byte after doseps header */
1298 dsc->data_index -= dsc->line_length - 30;
1299 /* we haven't read a line of PostScript code yet */
1300 dsc->line_count = 0;
1301 /* skip from current position to start of PostScript section */
1302 dsc->skip_bytes = dsc->doseps->ps_begin - 30;
1303
1304 if (dsc->doseps->tiff_begin)
1305 dsc->preview = CDSC_TIFF;
1306 if (dsc->doseps->wmf_begin)
1307 dsc->preview = CDSC_WMF;
1308
1309 return CDSC_OK;
1310 }
1311
1312
1313 dsc_private int
dsc_read_macbin(CDSC * dsc)1314 dsc_read_macbin(CDSC *dsc)
1315 {
1316 unsigned char *line = (unsigned char *)dsc->line;
1317 if ((dsc->macbin =
1318 (CDSCMACBIN *)dsc_memalloc(dsc, sizeof(CDSCMACBIN))) == NULL)
1319 return CDSC_ERROR; /* no memory */
1320
1321 dsc->macbin->data_begin = 128;
1322 dsc->macbin->data_length = dsc_get_bigendian_dword(line+83);
1323 dsc->macbin->resource_begin =
1324 (dsc->macbin->data_begin + dsc->macbin->data_length + 127 ) & ~127;
1325 dsc->macbin->resource_length = dsc_get_bigendian_dword(line+87);
1326
1327 if (dsc->file_length &&
1328 (((dsc->macbin->resource_begin + dsc->macbin->resource_length
1329 + 127) & ~127) > dsc->file_length)) {
1330 return CDSC_ERROR;
1331 }
1332
1333 dsc->doseps_end = dsc->macbin->data_begin + dsc->macbin->data_length;
1334
1335 /* move data_index to byte after Mac Binary header */
1336 dsc->data_index -= dsc->line_length - 128;
1337 /* we haven't read a line of PostScript code yet */
1338 dsc->line_count = 0;
1339
1340 dsc->preview = CDSC_PICT;
1341
1342 return CDSC_OK;
1343 }
1344
1345
1346 dsc_private int
dsc_read_applesingle(CDSC * dsc)1347 dsc_read_applesingle(CDSC *dsc)
1348 {
1349 GSDWORD EntryID;
1350 GSDWORD Offset;
1351 GSDWORD Length;
1352 GSWORD entries;
1353 int index;
1354 int header;
1355 int i;
1356
1357 unsigned char *line = (unsigned char *)dsc->line;
1358 if ((dsc->macbin =
1359 (CDSCMACBIN *)dsc_memalloc(dsc, sizeof(CDSCMACBIN))) == NULL)
1360 return CDSC_ERROR; /* no memory */
1361 entries = dsc_get_bigendian_word(line+24);
1362 for (i=0; i<(int)entries; i++) {
1363 index = 26 + i * 12;
1364 EntryID = dsc_get_bigendian_dword(line+index);
1365 Offset = dsc_get_bigendian_dword(line+index+4);
1366 Length = dsc_get_bigendian_dword(line+index+8);
1367 if (EntryID == 1) {
1368 /* data fork */
1369 dsc->macbin->data_begin = Offset;
1370 dsc->macbin->data_length = Length;
1371 }
1372 else if (EntryID == 2) {
1373 /* resource fork */
1374 dsc->macbin->resource_begin = Offset;
1375 dsc->macbin->resource_length = Length;
1376 }
1377 }
1378
1379 if (dsc->file_length &&
1380 (dsc->macbin->resource_begin + dsc->macbin->resource_length
1381 > dsc->file_length)) {
1382 return CDSC_ERROR;
1383 }
1384 if (dsc->file_length &&
1385 (dsc->macbin->data_begin + dsc->macbin->data_length
1386 > dsc->file_length)) {
1387 return CDSC_ERROR;
1388 }
1389
1390 dsc->doseps_end = dsc->macbin->data_begin + dsc->macbin->data_length;
1391
1392 header = 26 + entries * 12;
1393 /* move data_index to byte after AppleSingle/AppleDouble header */
1394 dsc->data_index -= dsc->line_length - header;
1395 /* we haven't read a line of PostScript code yet */
1396 dsc->line_count = 0;
1397 /* skip from current position to start of PostScript section */
1398 dsc->skip_bytes = dsc->macbin->data_begin - header;
1399
1400 dsc->preview = CDSC_PICT;
1401
1402 return CDSC_OK;
1403 }
1404
1405 dsc_private int
dsc_parse_pages(CDSC * dsc)1406 dsc_parse_pages(CDSC *dsc)
1407 {
1408 int ip, io;
1409 unsigned int i;
1410 char *p;
1411 int n;
1412 if ((dsc->page_pages != 0) && (dsc->scan_section == scan_comments)) {
1413 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1414 dsc->line_length);
1415 switch (rc) {
1416 case CDSC_RESPONSE_OK:
1417 case CDSC_RESPONSE_CANCEL:
1418 return CDSC_OK; /* ignore duplicate comments in header */
1419 case CDSC_RESPONSE_IGNORE_ALL:
1420 return CDSC_NOTDSC;
1421 }
1422 }
1423 if ((dsc->page_pages != 0) && (dsc->scan_section == scan_trailer)) {
1424 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1425 dsc->line_length);
1426 switch (rc) {
1427 case CDSC_RESPONSE_OK:
1428 case CDSC_RESPONSE_CANCEL:
1429 break; /* use duplicate comments in header */
1430 case CDSC_RESPONSE_IGNORE_ALL:
1431 return CDSC_NOTDSC;
1432 }
1433 }
1434
1435 n = IS_DSC(dsc->line, "%%+") ? 3 : 8;
1436 while (IS_WHITE(dsc->line[n]))
1437 n++;
1438 p = dsc->line + n;
1439 if (COMPARE(p, "atend")) {
1440 if (dsc->scan_section != scan_comments)
1441 dsc_unknown(dsc);
1442 else {
1443 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND,
1444 dsc->line, dsc->line_length);
1445 switch (rc) {
1446 case CDSC_RESPONSE_OK:
1447 /* assume (atend) */
1448 /* we should mark it as deferred */
1449 break;
1450 case CDSC_RESPONSE_CANCEL:
1451 /* ignore it */
1452 break;
1453 case CDSC_RESPONSE_IGNORE_ALL:
1454 return CDSC_NOTDSC;
1455 }
1456 }
1457 }
1458 else if (COMPARE(p, "(atend)")) {
1459 if (dsc->scan_section != scan_comments)
1460 dsc_unknown(dsc);
1461 /* do nothing */
1462 /* we should mark it as deferred */
1463 }
1464 else {
1465 ip = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1466 if (i) {
1467 n+=i;
1468 dsc->page_pages = ip;
1469 io = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1470 if (i) {
1471 /* DSC 2 uses extra integer to indicate page order */
1472 /* DSC 3 uses %%PageOrder: */
1473 if (dsc->page_order == CDSC_ORDER_UNKNOWN)
1474 switch (io) {
1475 case -1:
1476 dsc->page_order = CDSC_DESCEND;
1477 break;
1478 case 0:
1479 dsc->page_order = CDSC_SPECIAL;
1480 break;
1481 case 1:
1482 dsc->page_order = CDSC_ASCEND;
1483 break;
1484 }
1485 }
1486 }
1487 else {
1488 int rc = dsc_error(dsc, CDSC_MESSAGE_INCORRECT_USAGE, dsc->line,
1489 dsc->line_length);
1490 switch (rc) {
1491 case CDSC_RESPONSE_OK:
1492 case CDSC_RESPONSE_CANCEL:
1493 /* ignore it */
1494 break;
1495 case CDSC_RESPONSE_IGNORE_ALL:
1496 return CDSC_NOTDSC;
1497 }
1498 }
1499 }
1500 return CDSC_OK;
1501 }
1502
1503 dsc_private int
dsc_parse_bounding_box(CDSC * dsc,CDSCBBOX ** pbbox,int offset)1504 dsc_parse_bounding_box(CDSC *dsc, CDSCBBOX** pbbox, int offset)
1505 {
1506 unsigned int i, n;
1507 int llx, lly, urx, ury;
1508 float fllx, flly, furx, fury;
1509 char *p;
1510 /* Process first %%BoundingBox: in comments, and last in trailer */
1511 if ((*pbbox != NULL) && (dsc->scan_section == scan_comments)) {
1512 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1513 dsc->line_length);
1514 switch (rc) {
1515 case CDSC_RESPONSE_OK:
1516 case CDSC_RESPONSE_CANCEL:
1517 return CDSC_OK; /* ignore duplicate comments in header */
1518 case CDSC_RESPONSE_IGNORE_ALL:
1519 return CDSC_NOTDSC;
1520 }
1521 }
1522 if ((*pbbox != NULL) && (dsc->scan_section == scan_pages)) {
1523 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1524 dsc->line_length);
1525 switch (rc) {
1526 case CDSC_RESPONSE_OK:
1527 case CDSC_RESPONSE_CANCEL:
1528 return CDSC_OK; /* ignore duplicate comments in header */
1529 case CDSC_RESPONSE_IGNORE_ALL:
1530 return CDSC_NOTDSC;
1531 }
1532 }
1533 if ((*pbbox != NULL) && (dsc->scan_section == scan_trailer)) {
1534 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1535 dsc->line_length);
1536 switch (rc) {
1537 case CDSC_RESPONSE_OK:
1538 case CDSC_RESPONSE_CANCEL:
1539 break; /* use duplicate comments in trailer */
1540 case CDSC_RESPONSE_IGNORE_ALL:
1541 return CDSC_NOTDSC;
1542 }
1543 }
1544 if (*pbbox != NULL) {
1545 dsc_memfree(dsc, *pbbox);
1546 *pbbox = NULL;
1547 }
1548
1549 /* should only process first %%BoundingBox: */
1550
1551 while (IS_WHITE(dsc->line[offset]))
1552 offset++;
1553 p = dsc->line + offset;
1554
1555 if (COMPARE(p, "atend")) {
1556 if (dsc->scan_section == scan_trailer)
1557 dsc_unknown(dsc);
1558 else {
1559 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
1560 dsc->line_length);
1561 switch (rc) {
1562 case CDSC_RESPONSE_OK:
1563 /* assume (atend) */
1564 /* we should mark it as deferred */
1565 break;
1566 case CDSC_RESPONSE_CANCEL:
1567 /* ignore it */
1568 break;
1569 case CDSC_RESPONSE_IGNORE_ALL:
1570 return CDSC_NOTDSC;
1571 }
1572 }
1573 }
1574 else if (COMPARE(p, "(atend)")) {
1575 if (dsc->scan_section == scan_trailer)
1576 dsc_unknown(dsc);
1577 /* do nothing */
1578 /* we should mark it as deferred */
1579 }
1580 else {
1581 /* llx = */ lly = urx = ury = 0;
1582 n = offset;
1583 llx = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1584 n += i;
1585 if (i)
1586 lly = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1587 n += i;
1588 if (i)
1589 urx = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1590 n += i;
1591 if (i)
1592 ury = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
1593 if (i) {
1594 *pbbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
1595 if (*pbbox == NULL)
1596 return CDSC_ERROR; /* no memory */
1597 (*pbbox)->llx = llx;
1598 (*pbbox)->lly = lly;
1599 (*pbbox)->urx = urx;
1600 (*pbbox)->ury = ury;
1601 }
1602 else {
1603 int rc = dsc_error(dsc, CDSC_MESSAGE_BBOX, dsc->line,
1604 dsc->line_length);
1605 switch (rc) {
1606 case CDSC_RESPONSE_OK:
1607 /* fllx = */ flly = furx = fury = 0.0;
1608 n = offset;
1609 n += i;
1610 fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1611 n += i;
1612 if (i)
1613 flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1614 n += i;
1615 if (i)
1616 furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1617 n += i;
1618 if (i)
1619 fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1620 if (i) {
1621 *pbbox = (CDSCBBOX *)dsc_memalloc(dsc, sizeof(CDSCBBOX));
1622 if (*pbbox == NULL)
1623 return CDSC_ERROR; /* no memory */
1624 (*pbbox)->llx = (int)fllx;
1625 (*pbbox)->lly = (int)flly;
1626 (*pbbox)->urx = (int)(furx+0.999);
1627 (*pbbox)->ury = (int)(fury+0.999);
1628 }
1629 return CDSC_OK;
1630 case CDSC_RESPONSE_CANCEL:
1631 return CDSC_OK;
1632 case CDSC_RESPONSE_IGNORE_ALL:
1633 return CDSC_NOTDSC;
1634 }
1635 }
1636 }
1637 return CDSC_OK;
1638 }
1639
1640 dsc_private int
dsc_parse_float_bounding_box(CDSC * dsc,CDSCFBBOX ** pbbox,int offset)1641 dsc_parse_float_bounding_box(CDSC *dsc, CDSCFBBOX** pbbox, int offset)
1642 {
1643 unsigned int i, n;
1644 float fllx, flly, furx, fury;
1645 char *p;
1646 /* Process first %%HiResBoundingBox: or %%CropBox: in comments,
1647 * and last in trailer.
1648 */
1649 if ((*pbbox != NULL) && (dsc->scan_section == scan_comments)) {
1650 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1651 dsc->line_length);
1652 switch (rc) {
1653 case CDSC_RESPONSE_OK:
1654 case CDSC_RESPONSE_CANCEL:
1655 return CDSC_OK; /* ignore duplicate comments in header */
1656 case CDSC_RESPONSE_IGNORE_ALL:
1657 return CDSC_NOTDSC;
1658 }
1659 }
1660 if ((*pbbox != NULL) && (dsc->scan_section == scan_pages)) {
1661 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1662 dsc->line_length);
1663 switch (rc) {
1664 case CDSC_RESPONSE_OK:
1665 case CDSC_RESPONSE_CANCEL:
1666 return CDSC_OK; /* ignore duplicate comments in header */
1667 case CDSC_RESPONSE_IGNORE_ALL:
1668 return CDSC_NOTDSC;
1669 }
1670 }
1671 if ((*pbbox != NULL) && (dsc->scan_section == scan_trailer)) {
1672 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1673 dsc->line_length);
1674 switch (rc) {
1675 case CDSC_RESPONSE_OK:
1676 case CDSC_RESPONSE_CANCEL:
1677 break; /* use duplicate comments in trailer */
1678 case CDSC_RESPONSE_IGNORE_ALL:
1679 return CDSC_NOTDSC;
1680 }
1681 }
1682 if (*pbbox != NULL) {
1683 dsc_memfree(dsc, *pbbox);
1684 *pbbox = NULL;
1685 }
1686
1687 /* should only process first %%BoundingBox: */
1688
1689 while (IS_WHITE(dsc->line[offset]))
1690 offset++;
1691 p = dsc->line + offset;
1692
1693 if (COMPARE(p, "atend")) {
1694 if (dsc->scan_section == scan_trailer)
1695 dsc_unknown(dsc);
1696 else {
1697 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
1698 dsc->line_length);
1699 switch (rc) {
1700 case CDSC_RESPONSE_OK:
1701 /* assume (atend) */
1702 /* we should mark it as deferred */
1703 break;
1704 case CDSC_RESPONSE_CANCEL:
1705 /* ignore it */
1706 break;
1707 case CDSC_RESPONSE_IGNORE_ALL:
1708 return CDSC_NOTDSC;
1709 }
1710 }
1711 }
1712 else if (COMPARE(p, "(atend)")) {
1713 if (dsc->scan_section == scan_trailer)
1714 dsc_unknown(dsc);
1715 /* do nothing */
1716 /* we should mark it as deferred */
1717 }
1718 else {
1719 /* fllx = */ flly = furx = fury = 0.0;
1720 n = offset;
1721 fllx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1722 n += i;
1723 if (i)
1724 flly = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1725 n += i;
1726 if (i)
1727 furx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1728 n += i;
1729 if (i)
1730 fury = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1731 if (i) {
1732 *pbbox = (CDSCFBBOX *)dsc_memalloc(dsc, sizeof(CDSCFBBOX));
1733 if (*pbbox == NULL)
1734 return CDSC_ERROR; /* no memory */
1735 (*pbbox)->fllx = fllx;
1736 (*pbbox)->flly = flly;
1737 (*pbbox)->furx = furx;
1738 (*pbbox)->fury = fury;
1739 }
1740 }
1741 return CDSC_OK;
1742 }
1743
1744 dsc_private int
dsc_parse_orientation(CDSC * dsc,unsigned int * porientation,int offset)1745 dsc_parse_orientation(CDSC *dsc, unsigned int *porientation, int offset)
1746 {
1747 char *p;
1748 if ((dsc->page_orientation != CDSC_ORIENT_UNKNOWN) &&
1749 (dsc->scan_section == scan_comments)) {
1750 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1751 dsc->line_length);
1752 switch (rc) {
1753 case CDSC_RESPONSE_OK:
1754 case CDSC_RESPONSE_CANCEL:
1755 return CDSC_OK; /* ignore duplicate comments in header */
1756 case CDSC_RESPONSE_IGNORE_ALL:
1757 return CDSC_NOTDSC;
1758 }
1759 }
1760 if ((dsc->page_orientation != CDSC_ORIENT_UNKNOWN) &&
1761 (dsc->scan_section == scan_trailer)) {
1762 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1763 dsc->line_length);
1764 switch (rc) {
1765 case CDSC_RESPONSE_OK:
1766 case CDSC_RESPONSE_CANCEL:
1767 break; /* use duplicate comments in header; */
1768 case CDSC_RESPONSE_IGNORE_ALL:
1769 return CDSC_NOTDSC;
1770 }
1771 }
1772 p = dsc->line + offset;
1773 while (IS_WHITE(*p))
1774 p++;
1775 if (COMPARE(p, "atend")) {
1776 if (dsc->scan_section == scan_trailer)
1777 dsc_unknown(dsc);
1778 else {
1779 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND,
1780 dsc->line, dsc->line_length);
1781 switch (rc) {
1782 case CDSC_RESPONSE_OK:
1783 /* assume (atend) */
1784 /* we should mark it as deferred */
1785 break;
1786 case CDSC_RESPONSE_CANCEL:
1787 /* ignore it */
1788 break;
1789 case CDSC_RESPONSE_IGNORE_ALL:
1790 return CDSC_NOTDSC;
1791 }
1792 }
1793 }
1794 else if (COMPARE(p, "(atend)")) {
1795 if (dsc->scan_section == scan_trailer)
1796 dsc_unknown(dsc);
1797 /* do nothing */
1798 /* we should mark it as deferred */
1799 }
1800 else if (COMPARE(p, "Portrait")) {
1801 *porientation = CDSC_PORTRAIT;
1802 }
1803 else if (COMPARE(p, "Landscape")) {
1804 *porientation = CDSC_LANDSCAPE;
1805 }
1806 else {
1807 dsc_unknown(dsc);
1808 }
1809 return CDSC_OK;
1810 }
1811
1812 dsc_private int
dsc_parse_order(CDSC * dsc)1813 dsc_parse_order(CDSC *dsc)
1814 {
1815 char *p;
1816 if ((dsc->page_order != CDSC_ORDER_UNKNOWN) &&
1817 (dsc->scan_section == scan_comments)) {
1818 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_COMMENT, dsc->line,
1819 dsc->line_length);
1820 switch (rc) {
1821 case CDSC_RESPONSE_OK:
1822 case CDSC_RESPONSE_CANCEL:
1823 return CDSC_OK; /* ignore duplicate comments in header */
1824 case CDSC_RESPONSE_IGNORE_ALL:
1825 return CDSC_NOTDSC;
1826 }
1827 }
1828 if ((dsc->page_order != CDSC_ORDER_UNKNOWN) &&
1829 (dsc->scan_section == scan_trailer)) {
1830 int rc = dsc_error(dsc, CDSC_MESSAGE_DUP_TRAILER, dsc->line,
1831 dsc->line_length);
1832 switch (rc) {
1833 case CDSC_RESPONSE_OK:
1834 case CDSC_RESPONSE_CANCEL:
1835 break; /* use duplicate comments in trailer */
1836 case CDSC_RESPONSE_IGNORE_ALL:
1837 return CDSC_NOTDSC;
1838 }
1839 }
1840
1841 p = dsc->line + (IS_DSC(dsc->line, "%%+") ? 3 : 13);
1842 while (IS_WHITE(*p))
1843 p++;
1844 if (COMPARE(p, "atend")) {
1845 if (dsc->scan_section == scan_trailer)
1846 dsc_unknown(dsc);
1847 else {
1848 int rc = dsc_error(dsc, CDSC_MESSAGE_ATEND, dsc->line,
1849 dsc->line_length);
1850 switch (rc) {
1851 case CDSC_RESPONSE_OK:
1852 /* assume (atend) */
1853 /* we should mark it as deferred */
1854 break;
1855 case CDSC_RESPONSE_CANCEL:
1856 /* ignore it */
1857 break;
1858 case CDSC_RESPONSE_IGNORE_ALL:
1859 return CDSC_NOTDSC;
1860 }
1861 }
1862 }
1863 else if (COMPARE(p, "(atend)")) {
1864 if (dsc->scan_section == scan_trailer)
1865 dsc_unknown(dsc);
1866 /* do nothing */
1867 /* we should mark it as deferred */
1868 }
1869 else if (COMPARE(p, "Ascend")) {
1870 dsc->page_order = CDSC_ASCEND;
1871 }
1872 else if (COMPARE(p, "Descend")) {
1873 dsc->page_order = CDSC_DESCEND;
1874 }
1875 else if (COMPARE(p, "Special")) {
1876 dsc->page_order = CDSC_SPECIAL;
1877 }
1878 else {
1879 dsc_unknown(dsc);
1880 }
1881 return CDSC_OK;
1882 }
1883
1884
1885 dsc_private int
dsc_parse_media(CDSC * dsc,const CDSCMEDIA ** page_media)1886 dsc_parse_media(CDSC *dsc, const CDSCMEDIA **page_media)
1887 {
1888 char media_name[MAXSTR];
1889 int n = IS_DSC(dsc->line, "%%+") ? 3 : 12; /* %%PageMedia: */
1890 unsigned int i;
1891
1892 if (dsc_copy_string(media_name, sizeof(media_name)-1,
1893 dsc->line+n, dsc->line_length-n, NULL)) {
1894 for (i=0; i<dsc->media_count; i++) {
1895 if (dsc->media[i]->name &&
1896 (dsc_stricmp(media_name, dsc->media[i]->name) == 0)) {
1897 *page_media = dsc->media[i];
1898 return CDSC_OK;
1899 }
1900 }
1901 }
1902 dsc_unknown(dsc);
1903
1904 return CDSC_OK;
1905 }
1906
1907
1908 dsc_private int
dsc_parse_document_media(CDSC * dsc)1909 dsc_parse_document_media(CDSC *dsc)
1910 {
1911 unsigned int i, n;
1912 CDSCMEDIA lmedia;
1913 GSBOOL blank_line;
1914
1915 if (IS_DSC(dsc->line, "%%DocumentMedia:"))
1916 n = 16;
1917 else if (IS_DSC(dsc->line, "%%+"))
1918 n = 3;
1919 else
1920 return CDSC_ERROR; /* error */
1921
1922 /* check for blank remainder of line */
1923 blank_line = TRUE;
1924 for (i=n; i<dsc->line_length; i++) {
1925 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
1926 blank_line = FALSE;
1927 break;
1928 }
1929 }
1930
1931 if (!blank_line) {
1932 char name[MAXSTR];
1933 char colour[MAXSTR];
1934 char type[MAXSTR];
1935 lmedia.name = lmedia.colour = lmedia.type = (char *)NULL;
1936 lmedia.width = lmedia.height = lmedia.weight = 0;
1937 lmedia.mediabox = (CDSCBBOX *)NULL;
1938 lmedia.name = dsc_copy_string(name, sizeof(name),
1939 dsc->line+n, dsc->line_length-n, &i);
1940 n+=i;
1941 if (i)
1942 lmedia.width = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1943 n+=i;
1944 if (i)
1945 lmedia.height = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1946 n+=i;
1947 if (i)
1948 lmedia.weight = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1949 n+=i;
1950 if (i)
1951 lmedia.colour = dsc_copy_string(colour, sizeof(colour),
1952 dsc->line+n, dsc->line_length-n, &i);
1953 n+=i;
1954 if (i)
1955 lmedia.type = dsc_copy_string(type, sizeof(type),
1956 dsc->line+n, dsc->line_length-n, &i);
1957
1958 if (i==0)
1959 dsc_unknown(dsc); /* we didn't get all fields */
1960 else {
1961 if (dsc_add_media(dsc, &lmedia))
1962 return CDSC_ERROR; /* out of memory */
1963 }
1964 }
1965 return CDSC_OK;
1966 }
1967
1968 /* viewing orientation is believed to be the first four elements of
1969 * a CTM matrix
1970 */
1971 dsc_private int
dsc_parse_viewing_orientation(CDSC * dsc,CDSCCTM ** pctm)1972 dsc_parse_viewing_orientation(CDSC *dsc, CDSCCTM **pctm)
1973 {
1974 CDSCCTM ctm;
1975 unsigned int i, n;
1976
1977 if (*pctm != NULL) {
1978 dsc_memfree(dsc, *pctm);
1979 *pctm = NULL;
1980 }
1981
1982 n = IS_DSC(dsc->line, "%%+") ? 3 : 21; /* %%ViewingOrientation: */
1983 while (IS_WHITE(dsc->line[n]))
1984 n++;
1985
1986 /* ctm.xx = */ ctm.xy = ctm.yx = ctm.yy = 0.0;
1987 ctm.xx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1988 n += i;
1989 if (i)
1990 ctm.xy = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1991 n += i;
1992 if (i)
1993 ctm.yx = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1994 n += i;
1995 if (i)
1996 ctm.yy = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
1997 if (i==0) {
1998 dsc_unknown(dsc); /* we didn't get all fields */
1999 }
2000 else {
2001 *pctm = (CDSCCTM *)dsc_memalloc(dsc, sizeof(CDSCCTM));
2002 if (*pctm == NULL)
2003 return CDSC_ERROR; /* no memory */
2004 **pctm = ctm;
2005 }
2006 return CDSC_OK;
2007 }
2008
2009
2010 /* This is called before dsc_read_line(), since we may
2011 * need to skip a binary header which contains a new line
2012 * character
2013 */
2014 dsc_private int
dsc_scan_type(CDSC * dsc)2015 dsc_scan_type(CDSC *dsc)
2016 {
2017 unsigned char *p;
2018 unsigned char *line = (unsigned char *)(dsc->data + dsc->data_index);
2019 int length = dsc->data_length - dsc->data_index;
2020
2021 /* Types that should be known:
2022 * DSC
2023 * EPSF
2024 * PJL + any of above
2025 * ^D + any of above
2026 * DOS EPS
2027 * PDF
2028 * non-DSC
2029 */
2030
2031 /* First process any non PostScript headers */
2032 /* At this stage we do not have a complete line */
2033
2034 if (length == 0)
2035 return CDSC_NEEDMORE;
2036
2037 /* If we have already found a DOS EPS header, */
2038 /* ignore all until the PostScript section */
2039 if (dsc->skip_bytes) {
2040 int cnt = min(dsc->skip_bytes,
2041 (int)(dsc->data_length - dsc->data_index));
2042 dsc->skip_bytes -= cnt;
2043 dsc->data_index += cnt;
2044 length -= cnt;
2045 line += cnt;
2046 if (dsc->skip_bytes != 0)
2047 return CDSC_NEEDMORE;
2048 }
2049
2050 if (dsc->skip_pjl) {
2051 /* skip until first PostScript comment */
2052 while (length >= 2) {
2053 while (length && !IS_EOL(line[0])) {
2054 /* skip until EOL character */
2055 line++;
2056 dsc->data_index++;
2057 length--;
2058 }
2059 while ((length >= 2) && IS_EOL(line[0]) && IS_EOL(line[1])) {
2060 /* skip until EOL followed by non-EOL */
2061 line++;
2062 dsc->data_index++;
2063 length--;
2064 }
2065 if (length < 2)
2066 return CDSC_NEEDMORE;
2067
2068 if (IS_EOL(line[0]) && line[1]=='%') {
2069 line++;
2070 dsc->data_index++;
2071 length--;
2072 dsc->skip_pjl = FALSE;
2073 break;
2074 }
2075 else {
2076 line++;
2077 dsc->data_index++;
2078 length--;
2079 }
2080 }
2081 if (dsc->skip_pjl)
2082 return CDSC_NEEDMORE;
2083 }
2084
2085 if (length == 0)
2086 return CDSC_NEEDMORE;
2087
2088 if (line[0] == '\004') {
2089 line++;
2090 dsc->data_index++;
2091 length--;
2092 dsc->ctrld = TRUE;
2093 }
2094
2095 if (line[0] == '\033') {
2096 /* possibly PJL */
2097 if (length < 9)
2098 return CDSC_NEEDMORE;
2099 if (COMPARE(line, "\033%-12345X")) {
2100 dsc->skip_pjl = TRUE; /* skip until first PostScript comment */
2101 dsc->pjl = TRUE;
2102 dsc->data_index += 9;
2103 return dsc_scan_type(dsc);
2104 }
2105 }
2106
2107 if ((line[0]==0x0) && (length < 2))
2108 return CDSC_NEEDMORE; /* Could be Mac Binary EPSF */
2109 if ((line[0]==0x0) && (line[1] >= 1) && (line[1] <= 63) && (length < 128))
2110 return CDSC_NEEDMORE; /* Could be Mac Binary EPSF */
2111 if ((line[0]==0x0) && (line[1] == 0x5) && (length < 4))
2112 return CDSC_NEEDMORE; /* Could be Mac AppleSingle/AppleDouble */
2113 if ((line[0]==0xc5) && (length < 4))
2114 return CDSC_NEEDMORE; /* Could be DOS EPS */
2115
2116 if ((line[0]==0xc5) && (line[1]==0xd0) &&
2117 (line[2]==0xd3) && (line[3]==0xc6) ) {
2118 /* id is "EPSF" with bit 7 set */
2119 /* read DOS EPS header, then ignore all bytes until the PS section */
2120 if (length < 30)
2121 return CDSC_NEEDMORE;
2122 dsc->line = (char *)line;
2123 if (dsc_read_doseps(dsc))
2124 return CDSC_ERROR;
2125 }
2126 else if ((line[0]==0x0) && (line[1]==0x05) &&
2127 (line[2]==0x16) && ((line[3]==0x0) || (line[3] == 0x07))) {
2128 /* Mac AppleSingle or AppleDouble */
2129 GSDWORD version;
2130 GSWORD entries;
2131 if (length < 26)
2132 return CDSC_NEEDMORE;
2133 version = dsc_get_bigendian_dword(line+4);
2134 entries = dsc_get_bigendian_word(line+24);
2135 if ((version == 0x00010000) || (version == 0x00020000)) {
2136 if (length < (int)(26 + entries * 12))
2137 return CDSC_NEEDMORE;
2138 dsc->line = (char *)line;
2139 if (dsc_read_applesingle(dsc))
2140 return CDSC_ERROR;
2141 }
2142 }
2143 else if ((line[0]==0x0) &&
2144 (line[1] >= 1) && (line[1] <= 63) &&
2145 (line[74]==0x0) &&
2146 (line[65]=='E') && (line[66]=='P') &&
2147 (line[67]=='S') && (line[68]=='F')) {
2148 /* Mac Binary EPSF */
2149 dsc->line = (char *)line;
2150 if (dsc_read_macbin(dsc))
2151 return CDSC_ERROR;
2152 }
2153 else {
2154 if (length < 2)
2155 return CDSC_NEEDMORE;
2156 if ((line[0] == '%') && (line[1] == 'P')) {
2157 if (length < 5)
2158 return CDSC_NEEDMORE;
2159 if (COMPARE(line, "%PDF-")) {
2160 dsc->pdf = TRUE;
2161 dsc->scan_section = scan_comments;
2162 return CDSC_OK;
2163 }
2164 }
2165 }
2166
2167 /* Finally process PostScript headers */
2168
2169 if (dsc_read_line(dsc) <= 0)
2170 return CDSC_NEEDMORE;
2171
2172 dsc->dsc_version = dsc_add_line(dsc, dsc->line, dsc->line_length);
2173 if (COMPARE(dsc->line, "%!PS-Adobe")) {
2174 dsc->dsc = TRUE;
2175 dsc->begincomments = DSC_START(dsc);
2176 if (dsc->dsc_version == NULL)
2177 return CDSC_ERROR; /* no memory */
2178 p = (unsigned char *)dsc->line + 14;
2179 while (IS_WHITE(*p))
2180 p++;
2181 if (COMPARE(p, "EPSF-"))
2182 dsc->epsf = TRUE;
2183 dsc->scan_section = scan_comments;
2184 return CDSC_PSADOBE;
2185 }
2186 if (COMPARE(dsc->line, "%!")) {
2187 dsc->scan_section = scan_comments;
2188 return CDSC_NOTDSC;
2189 }
2190
2191 dsc->scan_section = scan_comments;
2192 return CDSC_NOTDSC; /* unrecognised */
2193 }
2194
2195
2196
2197 dsc_private int
dsc_scan_comments(CDSC * dsc)2198 dsc_scan_comments(CDSC *dsc)
2199 {
2200 /* Comments section ends at */
2201 /* %%EndComments */
2202 /* another section */
2203 /* line that does not start with %% */
2204 /* Save a few important lines */
2205
2206 char *line = dsc->line;
2207 GSBOOL continued = FALSE;
2208 dsc->id = CDSC_OK;
2209 if (IS_DSC(line, "%%EndComments")) {
2210 dsc->id = CDSC_ENDCOMMENTS;
2211 dsc->endcomments = DSC_END(dsc);
2212 dsc->scan_section = scan_pre_preview;
2213 return CDSC_OK;
2214 }
2215 else if (IS_DSC(line, "%%BeginComments")) {
2216 /* ignore because we are in this section */
2217 dsc->id = CDSC_BEGINCOMMENTS;
2218 }
2219 else if (dsc_is_section(line)) {
2220 dsc->endcomments = DSC_START(dsc);
2221 dsc->scan_section = scan_pre_preview;
2222 return CDSC_PROPAGATE;
2223 }
2224 else if (line[0] == '%' && IS_WHITE_OR_EOL(line[1])) {
2225 dsc->endcomments = DSC_START(dsc);
2226 dsc->scan_section = scan_pre_preview;
2227 return CDSC_PROPAGATE;
2228 }
2229 else if (line[0] != '%') {
2230 dsc->id = CDSC_OK;
2231 dsc->endcomments = DSC_START(dsc);
2232 dsc->scan_section = scan_pre_preview;
2233 return CDSC_PROPAGATE;
2234 }
2235 else if (IS_DSC(line, "%%Begin")) {
2236 dsc->endcomments = DSC_START(dsc);
2237 dsc->scan_section = scan_pre_preview;
2238 return CDSC_PROPAGATE;
2239 }
2240
2241 /* Handle continuation lines.
2242 * To simply processing, we assume that contination lines
2243 * will only occur if repeat parameters are allowed and that
2244 * a complete set of these parameters appears on each line.
2245 * This is more restrictive than the DSC specification, but
2246 * is valid for the DSC comments understood by this parser
2247 * for all documents that we have seen.
2248 */
2249 if (IS_DSC(line, "%%+")) {
2250 line = dsc->last_line;
2251 continued = TRUE;
2252 }
2253 else
2254 dsc_save_line(dsc);
2255
2256 if (IS_DSC(line, "%%Pages:")) {
2257 dsc->id = CDSC_PAGES;
2258 if (dsc_parse_pages(dsc) != 0)
2259 return CDSC_ERROR;
2260 }
2261 else if (IS_DSC(line, "%%Creator:")) {
2262 dsc->id = CDSC_CREATOR;
2263 dsc->dsc_creator = dsc_add_line(dsc, dsc->line+10, dsc->line_length-10);
2264 if (dsc->dsc_creator==NULL)
2265 return CDSC_ERROR;
2266 }
2267 else if (IS_DSC(line, "%%CreationDate:")) {
2268 dsc->id = CDSC_CREATIONDATE;
2269 dsc->dsc_date = dsc_add_line(dsc, dsc->line+15, dsc->line_length-15);
2270 if (dsc->dsc_date==NULL)
2271 return CDSC_ERROR;
2272 }
2273 else if (IS_DSC(line, "%%Title:")) {
2274 dsc->id = CDSC_TITLE;
2275 dsc->dsc_title = dsc_add_line(dsc, dsc->line+8, dsc->line_length-8);
2276 if (dsc->dsc_title==NULL)
2277 return CDSC_ERROR;
2278 }
2279 else if (IS_DSC(line, "%%For:")) {
2280 dsc->id = CDSC_FOR;
2281 dsc->dsc_for = dsc_add_line(dsc, dsc->line+6, dsc->line_length-6);
2282 if (dsc->dsc_for==NULL)
2283 return CDSC_ERROR;
2284 }
2285 else if (IS_DSC(line, "%%LanguageLevel:")) {
2286 unsigned int n = continued ? 3 : 16;
2287 unsigned int i;
2288 int ll;
2289 dsc->id = CDSC_LANGUAGELEVEL;
2290 ll = dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
2291 if (i) {
2292 if ( (ll==1) || (ll==2) || (ll==3) )
2293 dsc->language_level = ll;
2294 else {
2295 dsc_unknown(dsc);
2296 }
2297 }
2298 else
2299 dsc_unknown(dsc);
2300 }
2301 else if (IS_DSC(line, "%%BoundingBox:")) {
2302 dsc->id = CDSC_BOUNDINGBOX;
2303 if (dsc_parse_bounding_box(dsc, &(dsc->bbox), continued ? 3 : 14))
2304 return CDSC_ERROR;
2305 }
2306 else if (IS_DSC(line, "%%HiResBoundingBox:")) {
2307 dsc->id = CDSC_HIRESBOUNDINGBOX;
2308 if (dsc_parse_float_bounding_box(dsc, &(dsc->hires_bbox),
2309 continued ? 3 : 19))
2310 return CDSC_ERROR;
2311 }
2312 else if (IS_DSC(line, "%%CropBox:")) {
2313 dsc->id = CDSC_CROPBOX;
2314 if (dsc_parse_float_bounding_box(dsc, &(dsc->crop_box),
2315 continued ? 3 : 10))
2316 return CDSC_ERROR;
2317 }
2318 else if (IS_DSC(line, "%%Orientation:")) {
2319 dsc->id = CDSC_ORIENTATION;
2320 if (dsc_parse_orientation(dsc, &(dsc->page_orientation),
2321 continued ? 3 : 14))
2322 return CDSC_ERROR;
2323 }
2324 else if (IS_DSC(line, "%%PageOrder:")) {
2325 dsc->id = CDSC_PAGEORDER;
2326 if (dsc_parse_order(dsc))
2327 return CDSC_ERROR;
2328 }
2329 else if (IS_DSC(line, "%%DocumentMedia:")) {
2330 dsc->id = CDSC_DOCUMENTMEDIA;
2331 if (dsc_parse_document_media(dsc))
2332 return CDSC_ERROR;
2333 }
2334 else if (IS_DSC(line, "%%DocumentPaperSizes:")) {
2335 /* DSC 2.1 */
2336 unsigned int n = continued ? 3 : 21;
2337 unsigned int count = 0;
2338 unsigned int i = 1;
2339 char name[MAXSTR];
2340 char *p;
2341 dsc->id = CDSC_DOCUMENTPAPERSIZES;
2342 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2343 p = dsc_copy_string(name, sizeof(name)-1,
2344 dsc->line+n, dsc->line_length-n, &i);
2345 if (i && p) {
2346 const CDSCMEDIA *m = dsc_known_media;
2347 if (count >= dsc->media_count) {
2348 /* set some default values */
2349 CDSCMEDIA lmedia;
2350 lmedia.name = p;
2351 lmedia.width = 595.0;
2352 lmedia.height = 842.0;
2353 lmedia.weight = 80.0;
2354 lmedia.colour = NULL;
2355 lmedia.type = NULL;
2356 lmedia.mediabox = NULL;
2357 if (dsc_add_media(dsc, &lmedia))
2358 return CDSC_ERROR;
2359 }
2360 else
2361 dsc->media[count]->name =
2362 dsc_alloc_string(dsc, p, (int)strlen(p));
2363 /* find in list of known media */
2364 while (m && m->name) {
2365 if (dsc_stricmp(p, m->name)==0) {
2366 dsc->media[count]->width = m->width;
2367 dsc->media[count]->height = m->height;
2368 break;
2369 }
2370 m++;
2371 }
2372 }
2373 n+=i;
2374 count++;
2375 }
2376 }
2377 else if (IS_DSC(line, "%%DocumentPaperForms:")) {
2378 /* DSC 2.1 */
2379 unsigned int n = continued ? 3 : 21;
2380 unsigned int count = 0;
2381 unsigned int i = 1;
2382 char type[MAXSTR];
2383 char *p;
2384 dsc->id = CDSC_DOCUMENTPAPERFORMS;
2385 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2386 p = dsc_copy_string(type, sizeof(type)-1,
2387 dsc->line+n, dsc->line_length-n, &i);
2388 if (i && p) {
2389 if (count >= dsc->media_count) {
2390 /* set some default values */
2391 CDSCMEDIA lmedia;
2392 lmedia.name = NULL;
2393 lmedia.width = 595.0;
2394 lmedia.height = 842.0;
2395 lmedia.weight = 80.0;
2396 lmedia.colour = NULL;
2397 lmedia.type = p;
2398 lmedia.mediabox = NULL;
2399 if (dsc_add_media(dsc, &lmedia))
2400 return CDSC_ERROR;
2401 }
2402 else
2403 dsc->media[count]->type =
2404 dsc_alloc_string(dsc, p, (int)strlen(p));
2405 }
2406 n+=i;
2407 count++;
2408 }
2409 }
2410 else if (IS_DSC(line, "%%DocumentPaperColors:")) {
2411 /* DSC 2.1 */
2412 unsigned int n = continued ? 3 : 22;
2413 unsigned int count = 0;
2414 unsigned int i = 1;
2415 char colour[MAXSTR];
2416 char *p;
2417 dsc->id = CDSC_DOCUMENTPAPERCOLORS;
2418 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2419 p = dsc_copy_string(colour, sizeof(colour)-1,
2420 dsc->line+n, dsc->line_length-n, &i);
2421 if (i && p) {
2422 if (count >= dsc->media_count) {
2423 /* set some default values */
2424 CDSCMEDIA lmedia;
2425 lmedia.name = NULL;
2426 lmedia.width = 595.0;
2427 lmedia.height = 842.0;
2428 lmedia.weight = 80.0;
2429 lmedia.colour = p;
2430 lmedia.type = NULL;
2431 lmedia.mediabox = NULL;
2432 if (dsc_add_media(dsc, &lmedia))
2433 return CDSC_ERROR;
2434 }
2435 else
2436 dsc->media[count]->colour =
2437 dsc_alloc_string(dsc, p, (int)strlen(p));
2438 }
2439 n+=i;
2440 count++;
2441 }
2442 }
2443 else if (IS_DSC(line, "%%DocumentPaperWeights:")) {
2444 /* DSC 2.1 */
2445 unsigned int n = continued ? 3 : 23;
2446 unsigned int count = 0;
2447 unsigned int i = 1;
2448 float w;
2449 dsc->id = CDSC_DOCUMENTPAPERWEIGHTS;
2450 while (i && (dsc->line[n]!='\r') && (dsc->line[n]!='\n')) {
2451 w = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
2452 if (i) {
2453 if (count >= dsc->media_count) {
2454 /* set some default values */
2455 CDSCMEDIA lmedia;
2456 lmedia.name = NULL;
2457 lmedia.width = 595.0;
2458 lmedia.height = 842.0;
2459 lmedia.weight = w;
2460 lmedia.colour = NULL;
2461 lmedia.type = NULL;
2462 lmedia.mediabox = NULL;
2463 if (dsc_add_media(dsc, &lmedia))
2464 return CDSC_ERROR;
2465 }
2466 else
2467 dsc->media[count]->weight = w;
2468 }
2469 n+=i;
2470 count++;
2471 }
2472 }
2473 else if (IS_DSC(line, "%%DocumentData:")) {
2474 unsigned int n = continued ? 3 : 15;
2475 char *p = dsc->line + n;
2476 while (IS_WHITE(*p))
2477 p++;
2478 dsc->id = CDSC_DOCUMENTDATA;
2479 if (COMPARE(p, "Clean7Bit"))
2480 dsc->document_data = CDSC_CLEAN7BIT;
2481 else if (COMPARE(p, "Clean8Bit"))
2482 dsc->document_data = CDSC_CLEAN8BIT;
2483 else if (COMPARE(p, "Binary"))
2484 dsc->document_data = CDSC_BINARY;
2485 else
2486 dsc_unknown(dsc);
2487 }
2488 else if (IS_DSC(line, "%%Requirements:")) {
2489 dsc->id = CDSC_REQUIREMENTS;
2490 /* ignore */
2491 }
2492 else if (IS_DSC(line, "%%DocumentNeededFonts:")) {
2493 dsc->id = CDSC_DOCUMENTNEEDEDFONTS;
2494 /* ignore */
2495 }
2496 else if (IS_DSC(line, "%%DocumentSuppliedFonts:")) {
2497 dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS;
2498 /* ignore */
2499 }
2500 else if (IS_DSC(line, "%%PlateFile:")) {
2501 dsc->id = CDSC_PLATEFILE;
2502 if (dsc_parse_platefile(dsc) != CDSC_OK)
2503 dsc->id = CDSC_UNKNOWNDSC;
2504 }
2505 else if (IS_DSC(line, "%%CyanPlate:") ||
2506 IS_DSC(line, "%%MagentaPlate:") ||
2507 IS_DSC(line, "%%YellowPlate:") ||
2508 IS_DSC(line, "%%BlackPlate:")) {
2509 dsc->id = CDSC_PLATEFILE;
2510 if (dsc_parse_dcs1plate(dsc) != CDSC_OK)
2511 dsc->id = CDSC_UNKNOWNDSC;
2512 }
2513 else if (IS_DSC(line, "%%DocumentProcessColors:")) {
2514 dsc->id = CDSC_DOCUMENTPROCESSCOLORS;
2515 if (dsc_parse_process_colours(dsc) != CDSC_OK)
2516 dsc->id = CDSC_UNKNOWNDSC;
2517 }
2518 else if (IS_DSC(line, "%%DocumentCustomColors:")) {
2519 dsc->id = CDSC_DOCUMENTCUSTOMCOLORS;
2520 if (dsc_parse_custom_colours(dsc) != CDSC_OK)
2521 dsc->id = CDSC_UNKNOWNDSC;
2522 }
2523 else if (IS_DSC(line, "%%CMYKCustomColor:")) {
2524 dsc->id = CDSC_CMYKCUSTOMCOLOR;
2525 if (dsc_parse_cmyk_custom_colour(dsc) != CDSC_OK)
2526 dsc->id = CDSC_UNKNOWNDSC;
2527 }
2528 else if (IS_DSC(line, "%%RGBCustomColor:")) {
2529 dsc->id = CDSC_RGBCUSTOMCOLOR;
2530 if (dsc_parse_rgb_custom_colour(dsc) != CDSC_OK)
2531 dsc->id = CDSC_UNKNOWNDSC;
2532 }
2533 else if (dsc->line[0] == '%' && IS_WHITE_OR_EOL(dsc->line[1])) {
2534 dsc->id = CDSC_OK;
2535 /* ignore */
2536 }
2537 else {
2538 dsc->id = CDSC_UNKNOWNDSC;
2539 dsc_unknown(dsc);
2540 }
2541
2542 dsc->endcomments = DSC_END(dsc);
2543 return CDSC_OK;
2544 }
2545
2546
2547 dsc_private int
dsc_scan_preview(CDSC * dsc)2548 dsc_scan_preview(CDSC *dsc)
2549 {
2550 /* Preview section ends at */
2551 /* %%EndPreview */
2552 /* another section */
2553 /* Preview section must start with %%BeginPreview */
2554 char *line = dsc->line;
2555 dsc->id = CDSC_OK;
2556
2557 if (dsc->scan_section == scan_pre_preview) {
2558 if (IS_BLANK(line))
2559 return CDSC_OK; /* ignore blank lines before preview */
2560 else if (IS_DSC(line, "%%BeginPreview")) {
2561 dsc->id = CDSC_BEGINPREVIEW;
2562 dsc->beginpreview = DSC_START(dsc);
2563 dsc->endpreview = DSC_END(dsc);
2564 dsc->scan_section = scan_preview;
2565 /* Don't mark the preview as EPSI if a DOS EPS header is present */
2566 if (dsc->preview == CDSC_NOPREVIEW)
2567 dsc->preview = CDSC_EPSI;
2568 return CDSC_OK;
2569 }
2570 else {
2571 dsc->scan_section = scan_pre_defaults;
2572 return CDSC_PROPAGATE;
2573 }
2574 }
2575
2576 if (IS_DSC(line, "%%BeginPreview")) {
2577 /* ignore because we are in this section */
2578 }
2579 else if (dsc_is_section(line)) {
2580 dsc->endpreview = DSC_START(dsc);
2581 dsc->scan_section = scan_pre_defaults;
2582 return CDSC_PROPAGATE;
2583 }
2584 else if (IS_DSC(line, "%%EndPreview")) {
2585 dsc->id = CDSC_ENDPREVIEW;
2586 dsc->endpreview = DSC_END(dsc);
2587 dsc->scan_section = scan_pre_defaults;
2588 return CDSC_OK;
2589 }
2590 else if (line[0] == '%' && line[1] != '%') {
2591 /* Ordinary comments are OK */
2592 }
2593 else {
2594 dsc->id = CDSC_UNKNOWNDSC;
2595 /* DSC comments should not occur in preview */
2596 dsc_unknown(dsc);
2597 }
2598
2599 dsc->endpreview = DSC_END(dsc);
2600 return CDSC_OK;
2601 }
2602
2603 dsc_private int
dsc_scan_defaults(CDSC * dsc)2604 dsc_scan_defaults(CDSC *dsc)
2605 {
2606 /* Defaults section ends at */
2607 /* %%EndDefaults */
2608 /* another section */
2609 /* Defaults section must start with %%BeginDefaults */
2610 char *line = dsc->line;
2611 dsc->id = CDSC_OK;
2612
2613 if (dsc->scan_section == scan_pre_defaults) {
2614 if (IS_BLANK(line))
2615 return CDSC_OK; /* ignore blank lines before defaults */
2616 else if (IS_DSC(line, "%%BeginDefaults")) {
2617 dsc->id = CDSC_BEGINDEFAULTS;
2618 dsc->begindefaults = DSC_START(dsc);
2619 dsc->enddefaults = DSC_END(dsc);
2620 dsc->scan_section = scan_defaults;
2621 return CDSC_OK;
2622 }
2623 else {
2624 dsc->scan_section = scan_pre_prolog;
2625 return CDSC_PROPAGATE;
2626 }
2627 }
2628
2629 if (NOT_DSC_LINE(line)) {
2630 /* ignore */
2631 }
2632 else if (IS_DSC(line, "%%BeginPreview")) {
2633 /* ignore because we have already processed this section */
2634 }
2635 else if (IS_DSC(line, "%%BeginDefaults")) {
2636 /* ignore because we are in this section */
2637 }
2638 else if (dsc_is_section(line)) {
2639 dsc->enddefaults = DSC_START(dsc);
2640 dsc->scan_section = scan_pre_prolog;
2641 return CDSC_PROPAGATE;
2642 }
2643 else if (IS_DSC(line, "%%EndDefaults")) {
2644 dsc->id = CDSC_ENDDEFAULTS;
2645 dsc->enddefaults = DSC_END(dsc);
2646 dsc->scan_section = scan_pre_prolog;
2647 return CDSC_OK;
2648 }
2649 else if (IS_DSC(line, "%%PageMedia:")) {
2650 dsc->id = CDSC_PAGEMEDIA;
2651 dsc_parse_media(dsc, &dsc->page_media);
2652 }
2653 else if (IS_DSC(line, "%%PageOrientation:")) {
2654 dsc->id = CDSC_PAGEORIENTATION;
2655 /* This can override %%Orientation: */
2656 if (dsc_parse_orientation(dsc, &(dsc->page_orientation), 18))
2657 return CDSC_ERROR;
2658 }
2659 else if (IS_DSC(line, "%%PageBoundingBox:")) {
2660 dsc->id = CDSC_PAGEBOUNDINGBOX;
2661 if (dsc_parse_bounding_box(dsc, &(dsc->page_bbox), 18))
2662 return CDSC_ERROR;
2663 }
2664 else if (IS_DSC(line, "%%ViewingOrientation:")) {
2665 dsc->id = CDSC_VIEWINGORIENTATION;
2666 if (dsc_parse_viewing_orientation(dsc, &dsc->viewing_orientation))
2667 return CDSC_ERROR;
2668 }
2669 else if (IS_DSC(line, "%%PageCropBox:")) {
2670 dsc->id = CDSC_PAGECROPBOX;
2671 if (dsc_parse_float_bounding_box(dsc, &dsc->crop_box, 14))
2672 return CDSC_ERROR;
2673 }
2674 else {
2675 dsc->id = CDSC_UNKNOWNDSC;
2676 /* All other DSC comments are unknown, but not an error */
2677 dsc_unknown(dsc);
2678 }
2679 dsc->enddefaults = DSC_END(dsc);
2680 return CDSC_OK;
2681 }
2682
2683 /* CDSC_RESPONSE_OK and CDSC_RESPONSE_CANCEL mean ignore the
2684 * mismatch (default) */
2685 dsc_private int
dsc_check_match_prompt(CDSC * dsc,const char * str,int count)2686 dsc_check_match_prompt(CDSC *dsc, const char *str, int count)
2687 {
2688 if (count != 0) {
2689 char buf[MAXSTR+MAXSTR];
2690 if (dsc->line_length < (unsigned int)(sizeof(buf)/2-1)) {
2691 strncpy(buf, dsc->line, dsc->line_length);
2692 buf[dsc->line_length] = '\0';
2693 }
2694 sprintf(buf+strlen(buf), "\n%%%%Begin%.40s: / %%%%End%.40s\n", str, str);
2695 return dsc_error(dsc, CDSC_MESSAGE_BEGIN_END, buf, (int)strlen(buf));
2696 }
2697 return CDSC_RESPONSE_CANCEL;
2698 }
2699
2700 dsc_private int
dsc_check_match_type(CDSC * dsc,const char * str,int count)2701 dsc_check_match_type(CDSC *dsc, const char *str, int count)
2702 {
2703 if (dsc_check_match_prompt(dsc, str, count) == CDSC_RESPONSE_IGNORE_ALL)
2704 return CDSC_NOTDSC;
2705 return CDSC_OK;
2706 }
2707
2708 /* complain if Begin/End blocks didn't match */
2709 /* return non-zero if we should ignore all DSC */
2710 dsc_private int
dsc_check_match(CDSC * dsc)2711 dsc_check_match(CDSC *dsc)
2712 {
2713 int rc = 0;
2714 const char *font = "Font";
2715 const char *feature = "Feature";
2716 const char *resource = "Resource";
2717 const char *procset = "ProcSet";
2718
2719 if (!rc)
2720 rc = dsc_check_match_type(dsc, font, dsc->begin_font_count);
2721 if (!rc)
2722 rc = dsc_check_match_type(dsc, feature, dsc->begin_feature_count);
2723 if (!rc)
2724 rc = dsc_check_match_type(dsc, resource, dsc->begin_resource_count);
2725 if (!rc)
2726 rc = dsc_check_match_type(dsc, procset, dsc->begin_procset_count);
2727
2728 dsc->begin_font_count = 0;
2729 dsc->begin_feature_count = 0;
2730 dsc->begin_resource_count = 0;
2731 dsc->begin_procset_count = 0;
2732 return rc;
2733 }
2734
2735
2736 dsc_private int
dsc_scan_prolog(CDSC * dsc)2737 dsc_scan_prolog(CDSC *dsc)
2738 {
2739 /* Prolog section ends at */
2740 /* %%EndProlog */
2741 /* another section */
2742 /* Prolog section may start with %%BeginProlog or non-dsc line */
2743 char *line = dsc->line;
2744 dsc->id = CDSC_OK;
2745
2746 if (dsc->scan_section == scan_pre_prolog) {
2747 if (dsc_is_section(line) && (!IS_DSC(line, "%%BeginProlog"))) {
2748 dsc->scan_section = scan_pre_setup;
2749 return CDSC_PROPAGATE;
2750 }
2751 dsc->id = CDSC_BEGINPROLOG;
2752 dsc->beginprolog = DSC_START(dsc);
2753 dsc->endprolog = DSC_END(dsc);
2754 dsc->scan_section = scan_prolog;
2755 if (IS_DSC(line, "%%BeginProlog"))
2756 return CDSC_OK;
2757 }
2758
2759 if (NOT_DSC_LINE(line)) {
2760 /* ignore */
2761 }
2762 else if (IS_DSC(line, "%%BeginPreview")) {
2763 /* ignore because we have already processed this section */
2764 }
2765 else if (IS_DSC(line, "%%BeginDefaults")) {
2766 /* ignore because we have already processed this section */
2767 }
2768 else if (IS_DSC(line, "%%BeginProlog")) {
2769 /* ignore because we are in this section */
2770 }
2771 else if (dsc_is_section(line)) {
2772 dsc->endprolog = DSC_START(dsc);
2773 dsc->scan_section = scan_pre_setup;
2774 if (dsc_check_match(dsc))
2775 return CDSC_NOTDSC;
2776 return CDSC_PROPAGATE;
2777 }
2778 else if (IS_DSC(line, "%%EndProlog")) {
2779 dsc->id = CDSC_ENDPROLOG;
2780 dsc->endprolog = DSC_END(dsc);
2781 dsc->scan_section = scan_pre_setup;
2782 if (dsc_check_match(dsc))
2783 return CDSC_NOTDSC;
2784 return CDSC_OK;
2785 }
2786 else if (IS_DSC(line, "%%BeginFont:")) {
2787 dsc->id = CDSC_BEGINFONT;
2788 /* ignore Begin/EndFont, apart form making sure */
2789 /* that they are matched. */
2790 dsc->begin_font_count++;
2791 }
2792 else if (IS_DSC(line, "%%EndFont")) {
2793 dsc->id = CDSC_ENDFONT;
2794 dsc->begin_font_count--;
2795 }
2796 else if (IS_DSC(line, "%%BeginFeature:")) {
2797 dsc->id = CDSC_BEGINFEATURE;
2798 /* ignore Begin/EndFeature, apart form making sure */
2799 /* that they are matched. */
2800 dsc->begin_feature_count++;
2801 }
2802 else if (IS_DSC(line, "%%EndFeature")) {
2803 dsc->id = CDSC_ENDFEATURE;
2804 dsc->begin_feature_count--;
2805 }
2806 else if (IS_DSC(line, "%%BeginResource:")) {
2807 dsc->id = CDSC_BEGINRESOURCE;
2808 /* ignore Begin/EndResource, apart form making sure */
2809 /* that they are matched. */
2810 dsc->begin_resource_count++;
2811 }
2812 else if (IS_DSC(line, "%%EndResource")) {
2813 dsc->id = CDSC_ENDRESOURCE;
2814 dsc->begin_resource_count--;
2815 }
2816 else if (IS_DSC(line, "%%BeginProcSet:")) {
2817 dsc->id = CDSC_BEGINPROCSET;
2818 /* ignore Begin/EndProcSet, apart form making sure */
2819 /* that they are matched. */
2820 dsc->begin_procset_count++;
2821 }
2822 else if (IS_DSC(line, "%%EndProcSet")) {
2823 dsc->id = CDSC_ENDPROCSET;
2824 dsc->begin_procset_count--;
2825 }
2826 else {
2827 /* All other DSC comments are unknown, but not an error */
2828 dsc->id = CDSC_UNKNOWNDSC;
2829 dsc_unknown(dsc);
2830 }
2831
2832 dsc->endprolog = DSC_END(dsc);
2833 return CDSC_OK;
2834 }
2835
2836 dsc_private int
dsc_scan_setup(CDSC * dsc)2837 dsc_scan_setup(CDSC *dsc)
2838 {
2839 /* Setup section ends at */
2840 /* %%EndSetup */
2841 /* another section */
2842 /* Setup section must start with %%BeginSetup */
2843
2844 char *line = dsc->line;
2845 dsc->id = CDSC_OK;
2846
2847 if (dsc->scan_section == scan_pre_setup) {
2848 if (IS_BLANK(line))
2849 return CDSC_OK; /* ignore blank lines before setup */
2850 else if (IS_DSC(line, "%%BeginSetup")) {
2851 dsc->id = CDSC_BEGINSETUP;
2852 dsc->beginsetup = DSC_START(dsc);
2853 dsc->endsetup = DSC_END(dsc);
2854 dsc->scan_section = scan_setup;
2855 return CDSC_OK;
2856 }
2857 else {
2858 dsc->scan_section = scan_pre_pages;
2859 return CDSC_PROPAGATE;
2860 }
2861 }
2862
2863 if (NOT_DSC_LINE(line)) {
2864 /* ignore */
2865 }
2866 else if (IS_DSC(line, "%%BeginPreview")) {
2867 /* ignore because we have already processed this section */
2868 }
2869 else if (IS_DSC(line, "%%BeginDefaults")) {
2870 /* ignore because we have already processed this section */
2871 }
2872 else if (IS_DSC(line, "%%BeginProlog")) {
2873 /* ignore because we have already processed this section */
2874 }
2875 else if (IS_DSC(line, "%%BeginSetup")) {
2876 /* ignore because we are in this section */
2877 }
2878 else if (dsc_is_section(line)) {
2879 dsc->endsetup = DSC_START(dsc);
2880 dsc->scan_section = scan_pre_pages;
2881 if (dsc_check_match(dsc))
2882 return CDSC_NOTDSC;
2883 return CDSC_PROPAGATE;
2884 }
2885 else if (IS_DSC(line, "%%EndSetup")) {
2886 dsc->id = CDSC_ENDSETUP;
2887 dsc->endsetup = DSC_END(dsc);
2888 dsc->scan_section = scan_pre_pages;
2889 if (dsc_check_match(dsc))
2890 return CDSC_NOTDSC;
2891 return CDSC_OK;
2892 }
2893 else if (IS_DSC(line, "%%BeginFeature:")) {
2894 dsc->id = CDSC_BEGINFEATURE;
2895 /* ignore Begin/EndFeature, apart form making sure */
2896 /* that they are matched. */
2897 dsc->begin_feature_count++;
2898 }
2899 else if (IS_DSC(line, "%%EndFeature")) {
2900 dsc->id = CDSC_ENDFEATURE;
2901 dsc->begin_feature_count--;
2902 }
2903 else if (IS_DSC(line, "%%Feature:")) {
2904 dsc->id = CDSC_FEATURE;
2905 /* ignore */
2906 }
2907 else if (IS_DSC(line, "%%BeginResource:")) {
2908 dsc->id = CDSC_BEGINRESOURCE;
2909 /* ignore Begin/EndResource, apart form making sure */
2910 /* that they are matched. */
2911 dsc->begin_resource_count++;
2912 }
2913 else if (IS_DSC(line, "%%EndResource")) {
2914 dsc->id = CDSC_ENDRESOURCE;
2915 dsc->begin_resource_count--;
2916 }
2917 else if (IS_DSC(line, "%%PaperColor:")) {
2918 dsc->id = CDSC_PAPERCOLOR;
2919 /* ignore */
2920 }
2921 else if (IS_DSC(line, "%%PaperForm:")) {
2922 dsc->id = CDSC_PAPERFORM;
2923 /* ignore */
2924 }
2925 else if (IS_DSC(line, "%%PaperWeight:")) {
2926 dsc->id = CDSC_PAPERWEIGHT;
2927 /* ignore */
2928 }
2929 else if (IS_DSC(line, "%%PaperSize:")) {
2930 /* DSC 2.1 */
2931 GSBOOL found_media = FALSE;
2932 int i;
2933 int n = 12;
2934 char buf[MAXSTR];
2935 buf[0] = '\0';
2936 dsc->id = CDSC_PAPERSIZE;
2937 dsc_copy_string(buf, sizeof(buf)-1, dsc->line+n, dsc->line_length-n,
2938 NULL);
2939 for (i=0; i<(int)dsc->media_count; i++) {
2940 if (dsc->media[i] && dsc->media[i]->name &&
2941 (dsc_stricmp(buf, dsc->media[i]->name)==0)) {
2942 dsc->page_media = dsc->media[i];
2943 found_media = TRUE;
2944 break;
2945 }
2946 }
2947 if (!found_media) {
2948 /* It didn't match %%DocumentPaperSizes: */
2949 /* Try our known media */
2950 const CDSCMEDIA *m = dsc_known_media;
2951 while (m->name) {
2952 if (dsc_stricmp(buf, m->name)==0) {
2953 dsc->page_media = m;
2954 break;
2955 }
2956 m++;
2957 }
2958 if (m->name == NULL)
2959 dsc_unknown(dsc);
2960 }
2961 }
2962 else {
2963 /* All other DSC comments are unknown, but not an error */
2964 dsc->id = CDSC_UNKNOWNDSC;
2965 dsc_unknown(dsc);
2966 }
2967
2968 dsc->endsetup = DSC_END(dsc);
2969 return CDSC_OK;
2970 }
2971
2972 dsc_private int
dsc_scan_page(CDSC * dsc)2973 dsc_scan_page(CDSC *dsc)
2974 {
2975 /* Page section ends at */
2976 /* %%Page */
2977 /* %%Trailer */
2978 /* %%EOF */
2979 char *line = dsc->line;
2980 dsc->id = CDSC_OK;
2981
2982 if (dsc->scan_section == scan_pre_pages) {
2983 if (IS_DSC(line, "%%Page:")) {
2984 dsc->scan_section = scan_pages;
2985 /* fall through */
2986 }
2987 else {
2988 /* %%Page: didn't follow %%EndSetup
2989 * Keep reading until reach %%Page or %%Trailer
2990 * and add it to previous section.
2991 */
2992 DSC_OFFSET *last;
2993 if (dsc->endsetup != 0)
2994 last = &dsc->endsetup;
2995 else if (dsc->endprolog != 0)
2996 last = &dsc->endprolog;
2997 else if (dsc->enddefaults != 0)
2998 last = &dsc->enddefaults;
2999 else if (dsc->endpreview != 0)
3000 last = &dsc->endpreview;
3001 else if (dsc->endcomments != 0)
3002 last = &dsc->endcomments;
3003 else
3004 last = &dsc->begincomments;
3005 *last = DSC_START(dsc);
3006 if (IS_DSC(line, "%%Trailer") || IS_DSC(line, "%%EOF")) {
3007 dsc->scan_section = scan_pre_trailer;
3008 return CDSC_PROPAGATE;
3009 }
3010 *last = DSC_END(dsc);
3011 return CDSC_OK;
3012 }
3013 }
3014
3015 if (NOT_DSC_LINE(line)) {
3016 /* ignore */
3017 }
3018 else if (IS_DSC(line, "%%Page:")) {
3019 int code;
3020 dsc->id = CDSC_PAGE;
3021 if (dsc->page_count) {
3022 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
3023 if (dsc_check_match(dsc))
3024 return CDSC_NOTDSC;
3025 }
3026
3027 if ( (code = dsc_parse_page(dsc)) != CDSC_OK)
3028 return code;
3029 if (dsc->page_count == 0)
3030 dsc->scan_section = scan_pre_pages;
3031 }
3032 else if (IS_DSC(line, "%%BeginPreview")) {
3033 /* ignore because we have already processed this section */
3034 }
3035 else if (IS_DSC(line, "%%BeginDefaults")) {
3036 /* ignore because we have already processed this section */
3037 }
3038 else if (IS_DSC(line, "%%BeginProlog")) {
3039 /* ignore because we have already processed this section */
3040 }
3041 else if (IS_DSC(line, "%%BeginSetup")) {
3042 /* ignore because we have already processed this section */
3043 }
3044 else if (dsc_is_section(line)) {
3045 if (IS_DSC(line, "%%Trailer")) {
3046 if (dsc->page_count)
3047 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
3048 if (dsc->file_length) {
3049 if ((!dsc->doseps_end &&
3050 ((DSC_END(dsc) + 32768) < dsc->file_length)) ||
3051 ((dsc->doseps_end) &&
3052 ((DSC_END(dsc) + 32768) < dsc->doseps_end))) {
3053 int rc = dsc_error(dsc, CDSC_MESSAGE_EARLY_TRAILER,
3054 dsc->line, dsc->line_length);
3055 switch (rc) {
3056 case CDSC_RESPONSE_OK:
3057 /* ignore early trailer */
3058 break;
3059 case CDSC_RESPONSE_CANCEL:
3060 /* this is the trailer */
3061 dsc->scan_section = scan_pre_trailer;
3062 if (dsc_check_match(dsc))
3063 return CDSC_NOTDSC;
3064 return CDSC_PROPAGATE;
3065 case CDSC_RESPONSE_IGNORE_ALL:
3066 return CDSC_NOTDSC;
3067 }
3068 }
3069 else {
3070 dsc->scan_section = scan_pre_trailer;
3071 if (dsc_check_match(dsc))
3072 return CDSC_NOTDSC;
3073 return CDSC_PROPAGATE;
3074 }
3075 }
3076 else {
3077 dsc->scan_section = scan_pre_trailer;
3078 if (dsc_check_match(dsc))
3079 return CDSC_NOTDSC;
3080 return CDSC_PROPAGATE;
3081 }
3082 }
3083 else if (IS_DSC(line, "%%EOF")) {
3084 if (dsc->page_count)
3085 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
3086 if (dsc->file_length) {
3087 if ((!dsc->doseps_end &&
3088 ((DSC_END(dsc) + 100) < dsc->file_length)) ||
3089 ((dsc->doseps_end) &&
3090 ((DSC_END(dsc) + 100) < dsc->doseps_end))) {
3091 int rc = dsc_error(dsc, CDSC_MESSAGE_EARLY_EOF,
3092 dsc->line, dsc->line_length);
3093 switch (rc) {
3094 case CDSC_RESPONSE_OK:
3095 /* %%EOF is wrong, ignore it */
3096 break;
3097 case CDSC_RESPONSE_CANCEL:
3098 /* %%EOF is correct */
3099 dsc->scan_section = scan_eof;
3100 dsc->eof = TRUE;
3101 if (dsc_check_match(dsc))
3102 return CDSC_NOTDSC;
3103 return CDSC_PROPAGATE;
3104 case CDSC_RESPONSE_IGNORE_ALL:
3105 return CDSC_NOTDSC;
3106 }
3107 }
3108 }
3109 else {
3110 /* ignore it */
3111 if (dsc_check_match(dsc))
3112 return CDSC_NOTDSC;
3113 return CDSC_OK;
3114 }
3115 }
3116 else {
3117 /* Section comment, probably from a badly */
3118 /* encapsulated EPS file. */
3119 int rc = dsc_error(dsc, CDSC_MESSAGE_BAD_SECTION,
3120 dsc->line, dsc->line_length);
3121 if (rc == CDSC_RESPONSE_IGNORE_ALL)
3122 return CDSC_NOTDSC;
3123 }
3124 }
3125 else if (IS_DSC(line, "%%PageTrailer")) {
3126 dsc->id = CDSC_PAGETRAILER;
3127 /* ignore */
3128 }
3129 else if (IS_DSC(line, "%%BeginPageSetup")) {
3130 dsc->id = CDSC_BEGINPAGESETUP;
3131 /* ignore */
3132 }
3133 else if (IS_DSC(line, "%%EndPageSetup")) {
3134 dsc->id = CDSC_ENDPAGESETUP;
3135 /* ignore */
3136 }
3137 else if (IS_DSC(line, "%%PageMedia:")) {
3138 dsc->id = CDSC_PAGEMEDIA;
3139 if (dsc->page_count)
3140 dsc_parse_media(dsc, &(dsc->page[dsc->page_count-1].media));
3141 }
3142 else if (IS_DSC(line, "%%PaperColor:")) {
3143 dsc->id = CDSC_PAPERCOLOR;
3144 /* ignore */
3145 }
3146 else if (IS_DSC(line, "%%PaperForm:")) {
3147 dsc->id = CDSC_PAPERFORM;
3148 /* ignore */
3149 }
3150 else if (IS_DSC(line, "%%PaperWeight:")) {
3151 dsc->id = CDSC_PAPERWEIGHT;
3152 /* ignore */
3153 }
3154 else if (IS_DSC(line, "%%PaperSize:")) {
3155 /* DSC 2.1 */
3156 GSBOOL found_media = FALSE;
3157 int i;
3158 int n = 12;
3159 char buf[MAXSTR];
3160 buf[0] = '\0';
3161 dsc_copy_string(buf, sizeof(buf)-1, dsc->line+n,
3162 dsc->line_length-n, NULL);
3163 for (i=0; i<(int)dsc->media_count; i++) {
3164 if (dsc->media[i] && dsc->media[i]->name &&
3165 (dsc_stricmp(buf, dsc->media[i]->name)==0)) {
3166 if (dsc->page_count)
3167 dsc->page[dsc->page_count-1].media = dsc->media[i];
3168 found_media = TRUE;
3169 break;
3170 }
3171 }
3172 if (!found_media) {
3173 /* It didn't match %%DocumentPaperSizes: */
3174 /* Try our known media */
3175 const CDSCMEDIA *m = dsc_known_media;
3176 while (m->name) {
3177 if (dsc_stricmp(buf, m->name)==0) {
3178 if (dsc->page_count)
3179 dsc->page[dsc->page_count-1].media = m;
3180 break;
3181 }
3182 m++;
3183 }
3184 if (m->name == NULL)
3185 dsc_unknown(dsc);
3186 }
3187 }
3188 else if (IS_DSC(line, "%%PageOrientation:")) {
3189 if (dsc->page_count) {
3190 dsc->id = CDSC_PAGEORIENTATION;
3191 if (dsc_parse_orientation(dsc,
3192 &(dsc->page[dsc->page_count-1].orientation) ,18))
3193 return CDSC_NOTDSC;
3194 }
3195 }
3196 else if (IS_DSC(line, "%%PageBoundingBox:")) {
3197 if (dsc->page_count) {
3198 dsc->id = CDSC_PAGEBOUNDINGBOX;
3199 if (dsc_parse_bounding_box(dsc,
3200 &dsc->page[dsc->page_count-1].bbox, 18))
3201 return CDSC_NOTDSC;
3202 }
3203 }
3204 else if (IS_DSC(line, "%%ViewingOrientation:")) {
3205 if (dsc->page_count) {
3206 dsc->id = CDSC_VIEWINGORIENTATION;
3207 if (dsc_parse_viewing_orientation(dsc,
3208 &dsc->page[dsc->page_count-1].viewing_orientation))
3209 return CDSC_ERROR;
3210 }
3211 }
3212 else if (IS_DSC(line, "%%PageCropBox:")) {
3213 if (dsc->page_count) {
3214 dsc->id = CDSC_PAGECROPBOX;
3215 if (dsc_parse_float_bounding_box(dsc,
3216 &(dsc->page[dsc->page_count-1].crop_box), 14))
3217 return CDSC_ERROR;
3218 }
3219 }
3220 else if (IS_DSC(line, "%%BeginFont:")) {
3221 dsc->id = CDSC_BEGINFONT;
3222 /* ignore Begin/EndFont, apart form making sure */
3223 /* that they are matched. */
3224 dsc->begin_font_count++;
3225 }
3226 else if (IS_DSC(line, "%%EndFont")) {
3227 dsc->id = CDSC_BEGINFONT;
3228 dsc->begin_font_count--;
3229 }
3230 else if (IS_DSC(line, "%%BeginFeature:")) {
3231 dsc->id = CDSC_BEGINFEATURE;
3232 /* ignore Begin/EndFeature, apart form making sure */
3233 /* that they are matched. */
3234 dsc->begin_feature_count++;
3235 }
3236 else if (IS_DSC(line, "%%EndFeature")) {
3237 dsc->id = CDSC_ENDFEATURE;
3238 dsc->begin_feature_count--;
3239 }
3240 else if (IS_DSC(line, "%%BeginResource:")) {
3241 dsc->id = CDSC_BEGINRESOURCE;
3242 /* ignore Begin/EndResource, apart form making sure */
3243 /* that they are matched. */
3244 dsc->begin_resource_count++;
3245 }
3246 else if (IS_DSC(line, "%%EndResource")) {
3247 dsc->id = CDSC_ENDRESOURCE;
3248 dsc->begin_resource_count--;
3249 }
3250 else if (IS_DSC(line, "%%BeginProcSet:")) {
3251 dsc->id = CDSC_BEGINPROCSET;
3252 /* ignore Begin/EndProcSet, apart form making sure */
3253 /* that they are matched. */
3254 dsc->begin_procset_count++;
3255 }
3256 else if (IS_DSC(line, "%%EndProcSet")) {
3257 dsc->id = CDSC_ENDPROCSET;
3258 dsc->begin_procset_count--;
3259 }
3260 else if (IS_DSC(line, "%%IncludeFont:")) {
3261 dsc->id = CDSC_INCLUDEFONT;
3262 /* ignore */
3263 }
3264 else {
3265 /* All other DSC comments are unknown, but not an error */
3266 dsc->id = CDSC_UNKNOWNDSC;
3267 dsc_unknown(dsc);
3268 }
3269
3270 if (dsc->page_count)
3271 dsc->page[dsc->page_count-1].end = DSC_END(dsc);
3272 return CDSC_OK;
3273 }
3274
3275 /* Valid Trailer comments are
3276 * %%Trailer
3277 * %%EOF
3278 * or the following deferred with (atend)
3279 * %%BoundingBox:
3280 * %%DocumentCustomColors:
3281 * %%DocumentFiles:
3282 * %%DocumentFonts:
3283 * %%DocumentNeededFiles:
3284 * %%DocumentNeededFonts:
3285 * %%DocumentNeededProcSets:
3286 * %%DocumentNeededResources:
3287 * %%DocumentProcSets:
3288 * %%DocumentProcessColors:
3289 * %%DocumentSuppliedFiles:
3290 * %%DocumentSuppliedFonts:
3291 * %%DocumentSuppliedProcSets:
3292 * %%DocumentSuppliedResources:
3293 * %%Orientation:
3294 * %%Pages:
3295 * %%PageOrder:
3296 *
3297 * Our supported subset is
3298 * %%Trailer
3299 * %%EOF
3300 * %%BoundingBox:
3301 * %%CropBox:
3302 * %%HiResBoundingBox:
3303 * %%DocumentCustomColors:
3304 * %%DocumentProcessColors:
3305 * %%Orientation:
3306 * %%Pages:
3307 * %%PageOrder:
3308 * In addition to these, we support
3309 * %%DocumentMedia:
3310 *
3311 * A %%PageTrailer can have the following:
3312 * %%PageBoundingBox:
3313 * %%PageCustomColors:
3314 * %%PageFiles:
3315 * %%PageFonts:
3316 * %%PageOrientation:
3317 * %%PageProcessColors:
3318 * %%PageResources:
3319 */
3320
3321 dsc_private int
dsc_scan_trailer(CDSC * dsc)3322 dsc_scan_trailer(CDSC *dsc)
3323 {
3324 /* Trailer section start at */
3325 /* %%Trailer */
3326 /* and ends at */
3327 /* %%EOF */
3328 char *line = dsc->line;
3329 GSBOOL continued = FALSE;
3330 dsc->id = CDSC_OK;
3331
3332 if (dsc->scan_section == scan_pre_trailer) {
3333 if (IS_DSC(line, "%%Trailer")) {
3334 dsc->id = CDSC_TRAILER;
3335 dsc->begintrailer = DSC_START(dsc);
3336 dsc->endtrailer = DSC_END(dsc);
3337 dsc->scan_section = scan_trailer;
3338 return CDSC_OK;
3339 }
3340 else if (IS_DSC(line, "%%EOF")) {
3341 dsc->id = CDSC_EOF;
3342 dsc->begintrailer = DSC_START(dsc);
3343 dsc->endtrailer = DSC_END(dsc);
3344 dsc->scan_section = scan_trailer;
3345 /* Continue, in case we found %%EOF in an embedded document */
3346 return CDSC_OK;
3347 }
3348 else {
3349 /* %%Page: didn't follow %%EndSetup
3350 * Keep reading until reach %%Page or %%Trailer
3351 * and add it to setup section
3352 */
3353 /* append to previous section */
3354 if (dsc->beginsetup)
3355 dsc->endsetup = DSC_END(dsc);
3356 else if (dsc->beginprolog)
3357 dsc->endprolog = DSC_END(dsc);
3358 else {
3359 /* horribly confused */
3360 }
3361 return CDSC_OK;
3362 }
3363 }
3364
3365 /* Handle continuation lines.
3366 * See comment above about our restrictive processing of
3367 * continuation lines
3368 */
3369 if (IS_DSC(line, "%%+")) {
3370 line = dsc->last_line;
3371 continued = TRUE;
3372 }
3373 else
3374 dsc_save_line(dsc);
3375
3376 if (NOT_DSC_LINE(line)) {
3377 /* ignore */
3378 }
3379 else if (IS_DSC(dsc->line, "%%EOF")) {
3380 /* Keep scanning, in case we have a false trailer */
3381 dsc->id = CDSC_EOF;
3382 }
3383 else if (IS_DSC(dsc->line, "%%Trailer")) {
3384 /* Cope with no pages with code after setup and before trailer. */
3385 /* Last trailer is the correct one. */
3386 dsc->id = CDSC_TRAILER;
3387 dsc->begintrailer = DSC_START(dsc);
3388 }
3389 else if (IS_DSC(line, "%%Pages:")) {
3390 dsc->id = CDSC_PAGES;
3391 if (dsc_parse_pages(dsc) != 0)
3392 return CDSC_ERROR;
3393 }
3394 else if (IS_DSC(line, "%%BoundingBox:")) {
3395 dsc->id = CDSC_BOUNDINGBOX;
3396 if (dsc_parse_bounding_box(dsc, &(dsc->bbox), continued ? 3 : 14))
3397 return CDSC_ERROR;
3398 }
3399 else if (IS_DSC(line, "%%HiResBoundingBox:")) {
3400 dsc->id = CDSC_HIRESBOUNDINGBOX;
3401 if (dsc_parse_float_bounding_box(dsc, &(dsc->hires_bbox),
3402 continued ? 3 : 19))
3403 return CDSC_ERROR;
3404 }
3405 else if (IS_DSC(line, "%%CropBox:")) {
3406 dsc->id = CDSC_CROPBOX;
3407 if (dsc_parse_float_bounding_box(dsc, &(dsc->crop_box),
3408 continued ? 3 : 10))
3409 return CDSC_ERROR;
3410 }
3411 else if (IS_DSC(line, "%%Orientation:")) {
3412 dsc->id = CDSC_ORIENTATION;
3413 if (dsc_parse_orientation(dsc, &(dsc->page_orientation), continued ? 3 : 14))
3414 return CDSC_ERROR;
3415 }
3416 else if (IS_DSC(line, "%%PageOrder:")) {
3417 dsc->id = CDSC_PAGEORDER;
3418 if (dsc_parse_order(dsc))
3419 return CDSC_ERROR;
3420 }
3421 else if (IS_DSC(line, "%%DocumentMedia:")) {
3422 dsc->id = CDSC_DOCUMENTMEDIA;
3423 if (dsc_parse_document_media(dsc))
3424 return CDSC_ERROR;
3425 }
3426 else if (IS_DSC(dsc->line, "%%Page:")) {
3427 /* This should not occur in the trailer, but we might see
3428 * this if a document has been incorrectly embedded.
3429 */
3430 int rc = dsc_error(dsc, CDSC_MESSAGE_PAGE_IN_TRAILER,
3431 dsc->line, dsc->line_length);
3432 switch (rc) {
3433 case CDSC_RESPONSE_OK:
3434 /* Assume that we are really in the previous */
3435 /* page, not the trailer */
3436 dsc->scan_section = scan_pre_pages;
3437 if (dsc->page_count)
3438 dsc->page[dsc->page_count-1].end = DSC_START(dsc);
3439 return CDSC_PROPAGATE; /* try again */
3440 case CDSC_RESPONSE_CANCEL:
3441 /* ignore pages in trailer */
3442 break;
3443 case CDSC_RESPONSE_IGNORE_ALL:
3444 return CDSC_NOTDSC;
3445 }
3446 }
3447 else if (IS_DSC(line, "%%DocumentNeededFonts:")) {
3448 dsc->id = CDSC_DOCUMENTNEEDEDFONTS;
3449 /* ignore */
3450 }
3451 else if (IS_DSC(line, "%%DocumentSuppliedFonts:")) {
3452 dsc->id = CDSC_DOCUMENTSUPPLIEDFONTS;
3453 /* ignore */
3454 }
3455 else if (IS_DSC(line, "%%DocumentProcessColors:")) {
3456 dsc->id = CDSC_DOCUMENTPROCESSCOLORS;
3457 if (dsc_parse_process_colours(dsc) != CDSC_OK)
3458 dsc->id = CDSC_UNKNOWNDSC;
3459 }
3460 else if (IS_DSC(line, "%%DocumentCustomColors:")) {
3461 dsc->id = CDSC_DOCUMENTCUSTOMCOLORS;
3462 if (dsc_parse_custom_colours(dsc) != CDSC_OK)
3463 dsc->id = CDSC_UNKNOWNDSC;
3464 }
3465 else {
3466 /* All other DSC comments are unknown, but not an error */
3467 dsc->id = CDSC_UNKNOWNDSC;
3468 dsc_unknown(dsc);
3469 }
3470
3471 dsc->endtrailer = DSC_END(dsc);
3472 return CDSC_OK;
3473 }
3474
3475
3476 dsc_private char *
dsc_alloc_string(CDSC * dsc,const char * str,int len)3477 dsc_alloc_string(CDSC *dsc, const char *str, int len)
3478 {
3479 char *p;
3480 if (dsc->string_head == NULL) {
3481 dsc->string_head = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
3482 if (dsc->string_head == NULL)
3483 return NULL; /* no memory */
3484 dsc->string = dsc->string_head;
3485 dsc->string->next = NULL;
3486 dsc->string->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
3487 if (dsc->string->data == NULL) {
3488 dsc_reset(dsc);
3489 return NULL; /* no memory */
3490 }
3491 dsc->string->index = 0;
3492 dsc->string->length = CDSC_STRING_CHUNK;
3493 }
3494 if ( dsc->string->index + len + 1 > dsc->string->length) {
3495 /* allocate another string block */
3496 CDSCSTRING *newstring = (CDSCSTRING *)dsc_memalloc(dsc, sizeof(CDSCSTRING));
3497 if (newstring == NULL) {
3498 dsc_debug_print(dsc, "Out of memory\n");
3499 return NULL;
3500 }
3501 newstring->next = NULL;
3502 newstring->length = 0;
3503 newstring->index = 0;
3504 newstring->data = (char *)dsc_memalloc(dsc, CDSC_STRING_CHUNK);
3505 if (newstring->data == NULL) {
3506 dsc_memfree(dsc, newstring);
3507 dsc_debug_print(dsc, "Out of memory\n");
3508 return NULL; /* no memory */
3509 }
3510 newstring->length = CDSC_STRING_CHUNK;
3511 dsc->string->next = newstring;
3512 dsc->string = newstring;
3513 }
3514 if ( dsc->string->index + len + 1 > dsc->string->length)
3515 return NULL; /* failed */
3516 p = dsc->string->data + dsc->string->index;
3517 memcpy(p, str, len);
3518 *(p+len) = '\0';
3519 dsc->string->index += len + 1;
3520 return p;
3521 }
3522
3523 /* store line, ignoring leading spaces */
3524 dsc_private char *
dsc_add_line(CDSC * dsc,const char * line,unsigned int len)3525 dsc_add_line(CDSC *dsc, const char *line, unsigned int len)
3526 {
3527 char *newline;
3528 unsigned int i;
3529 while (len && (IS_WHITE(*line))) {
3530 len--;
3531 line++;
3532 }
3533 newline = dsc_alloc_string(dsc, line, len);
3534 if (newline == NULL)
3535 return NULL;
3536
3537 for (i=0; i<len; i++) {
3538 if (newline[i] == '\r') {
3539 newline[i]='\0';
3540 break;
3541 }
3542 if (newline[i] == '\n') {
3543 newline[i]='\0';
3544 break;
3545 }
3546 }
3547 return newline;
3548 }
3549
3550
3551 /* Copy string on line to new allocated string str */
3552 /* String is always null terminated */
3553 /* String is no longer than len */
3554 /* Return pointer to string */
3555 /* Store number of used characters from line */
3556 /* Don't copy enclosing () */
3557 dsc_private char *
dsc_copy_string(char * str,unsigned int slen,char * line,unsigned int len,unsigned int * offset)3558 dsc_copy_string(char *str, unsigned int slen, char *line,
3559 unsigned int len, unsigned int *offset)
3560 {
3561 int quoted = FALSE;
3562 int instring=0;
3563 unsigned int newlength = 0;
3564 unsigned int i = 0;
3565 unsigned char ch;
3566 if (len > slen)
3567 len = slen-1;
3568 while ( (i<len) && IS_WHITE(line[i]))
3569 i++; /* skip leading spaces */
3570 if ((i < len) && (line[i]=='(')) {
3571 quoted = TRUE;
3572 instring++;
3573 i++; /* don't copy outside () */
3574 }
3575 while (i < len) {
3576 str[newlength] = ch = line[i];
3577 i++;
3578 if (quoted) {
3579 if (ch == '(')
3580 instring++;
3581 if (ch == ')')
3582 instring--;
3583 if (instring==0)
3584 break;
3585 }
3586 else if (ch == ' ')
3587 break;
3588
3589 if (ch == '\r')
3590 break;
3591 if (ch == '\n')
3592 break;
3593 else if ( (ch == '\\') && (i+1 < len) ) {
3594 ch = line[i];
3595 if ((ch >= '0') && (ch <= '9')) {
3596 /* octal coded character */
3597 int j = 3;
3598 ch = 0;
3599 while (j && (i < len) && line[i]>='0' && line[i]<='7') {
3600 ch = (unsigned char)((ch<<3) + (line[i]-'0'));
3601 i++;
3602 j--;
3603 }
3604 str[newlength] = ch;
3605 }
3606 else if (ch == '(') {
3607 str[newlength] = ch;
3608 i++;
3609 }
3610 else if (ch == ')') {
3611 str[newlength] = ch;
3612 i++;
3613 }
3614 else if (ch == 'b') {
3615 str[newlength] = '\b';
3616 i++;
3617 }
3618 else if (ch == 'f') {
3619 str[newlength] = '\b';
3620 i++;
3621 }
3622 else if (ch == 'n') {
3623 str[newlength] = '\n';
3624 i++;
3625 }
3626 else if (ch == 'r') {
3627 str[newlength] = '\r';
3628 i++;
3629 }
3630 else if (ch == 't') {
3631 str[newlength] = '\t';
3632 i++;
3633 }
3634 else if (ch == '\\') {
3635 str[newlength] = '\\';
3636 i++;
3637 }
3638 }
3639 newlength++;
3640 }
3641 str[newlength] = '\0';
3642 if (offset != (unsigned int *)NULL)
3643 *offset = i;
3644 return str;
3645 }
3646
3647 dsc_private int
dsc_get_int(const char * line,unsigned int len,unsigned int * offset)3648 dsc_get_int(const char *line, unsigned int len, unsigned int *offset)
3649 {
3650 char newline[MAXSTR];
3651 int newlength = 0;
3652 unsigned int i = 0;
3653 unsigned char ch;
3654
3655 len = min(len, sizeof(newline)-1);
3656 while ((i<len) && IS_WHITE(line[i]))
3657 i++; /* skip leading spaces */
3658 while (i < len) {
3659 newline[newlength] = ch = line[i];
3660 if (!(isdigit(ch) || (ch=='-') || (ch=='+')))
3661 break; /* not part of an integer number */
3662 i++;
3663 newlength++;
3664 }
3665 while ((i<len) && IS_WHITE(line[i]))
3666 i++; /* skip trailing spaces */
3667 newline[newlength] = '\0';
3668 if (offset != (unsigned int *)NULL)
3669 *offset = i;
3670 return atoi(newline);
3671 }
3672
3673 dsc_private float
dsc_get_real(const char * line,unsigned int len,unsigned int * offset)3674 dsc_get_real(const char *line, unsigned int len, unsigned int *offset)
3675 {
3676 char newline[MAXSTR];
3677 int newlength = 0;
3678 unsigned int i = 0;
3679 unsigned char ch;
3680
3681 len = min(len, sizeof(newline)-1);
3682 while ((i<len) && IS_WHITE(line[i]))
3683 i++; /* skip leading spaces */
3684 while (i < len) {
3685 newline[newlength] = ch = line[i];
3686 if (!(isdigit(ch) || (ch=='.') || (ch=='-') || (ch=='+')
3687 || (ch=='e') || (ch=='E')))
3688 break; /* not part of a real number */
3689 i++;
3690 newlength++;
3691 }
3692 while ((i<len) && IS_WHITE(line[i]))
3693 i++; /* skip trailing spaces */
3694
3695 newline[newlength] = '\0';
3696
3697 if (offset != (unsigned int *)NULL)
3698 *offset = i;
3699 return (float)atof(newline);
3700 }
3701
3702 int
dsc_stricmp(const char * s,const char * t)3703 dsc_stricmp(const char *s, const char *t)
3704 {
3705 while (toupper(*s) == toupper(*t)) {
3706 if (*s == '\0')
3707 return 0;
3708 s++;
3709 t++;
3710 }
3711 return (toupper(*s) - toupper(*t));
3712 }
3713
3714
3715 dsc_private int
dsc_parse_page(CDSC * dsc)3716 dsc_parse_page(CDSC *dsc)
3717 {
3718 char *p;
3719 unsigned int i;
3720 char page_label[MAXSTR];
3721 char *pl;
3722 int page_ordinal;
3723 int page_number;
3724
3725 p = dsc->line + 7;
3726 pl = dsc_copy_string(page_label, sizeof(page_label), p, dsc->line_length-7, &i);
3727 if (pl == NULL)
3728 return CDSC_ERROR;
3729 p += i;
3730 if (dsc->line_length - 7 - i == 0) {
3731 /* Ordinal missing, or parentheses not matched in label */
3732 /* Try to find ordinal at end of line */
3733 while (i > 0) {
3734 if (!IS_WHITE_OR_EOL(p[-1]))
3735 break;
3736 p--;
3737 i--;
3738 }
3739 while (i > 0) {
3740 if (!isdigit((int)p[-1]))
3741 break;
3742 p--;
3743 i--;
3744 }
3745 }
3746 page_ordinal = dsc_get_int(p, dsc->line_length - 7 - i, NULL);
3747
3748 if ( (page_ordinal == 0) || (strlen(page_label) == 0) ||
3749 (dsc->page_count &&
3750 (page_ordinal != dsc->page[dsc->page_count-1].ordinal+1)) ) {
3751 int rc = dsc_error(dsc, CDSC_MESSAGE_PAGE_ORDINAL, dsc->line,
3752 dsc->line_length);
3753 switch (rc) {
3754 case CDSC_RESPONSE_OK:
3755 /* ignore this page */
3756 return CDSC_OK;
3757 case CDSC_RESPONSE_CANCEL:
3758 /* accept the page */
3759 break;
3760 case CDSC_RESPONSE_IGNORE_ALL:
3761 return CDSC_NOTDSC;
3762 }
3763 }
3764
3765 page_number = dsc->page_count;
3766 dsc_add_page(dsc, page_ordinal, page_label);
3767 dsc->page[page_number].begin = DSC_START(dsc);
3768 dsc->page[page_number].end = DSC_START(dsc);
3769
3770 if (dsc->page[page_number].label == NULL)
3771 return CDSC_ERROR; /* no memory */
3772
3773 return CDSC_OK;
3774 }
3775
3776
3777
3778 /* DSC error reporting */
3779
3780 void
dsc_debug_print(CDSC * dsc,const char * str)3781 dsc_debug_print(CDSC *dsc, const char *str)
3782 {
3783 if (dsc->debug_print_fn)
3784 dsc->debug_print_fn(dsc->caller_data, str);
3785 }
3786
3787
3788 /* Display a message about a problem with the DSC comments.
3789 *
3790 * explanation = an index to to a multiline explanation in dsc_message[]
3791 * line = pointer to the offending DSC line (if any)
3792 * return code =
3793 * CDSC_RESPONSE_OK DSC was wrong, make a guess about what
3794 * was really meant.
3795 * CDSC_RESPONSE_CANCEL Assume DSC was correct, ignore if it
3796 * is misplaced.
3797 * CDSC_RESPONSE_IGNORE_ALL Ignore all DSC.
3798 */
3799 /* Silent operation. Don't display errors. */
3800 dsc_private int
dsc_error(CDSC * dsc,unsigned int explanation,char * line,unsigned int line_len)3801 dsc_error(CDSC *dsc, unsigned int explanation,
3802 char *line, unsigned int line_len)
3803 {
3804 /* if error function provided, use it */
3805 if (dsc->dsc_error_fn)
3806 return dsc->dsc_error_fn(dsc->caller_data, dsc,
3807 explanation, line, line_len);
3808
3809 /* treat DSC as being correct */
3810 return CDSC_RESPONSE_CANCEL;
3811 }
3812
3813
3814 /* Fixup if DCS 2.0 was used */
3815 dsc_private int
dsc_dcs2_fixup(CDSC * dsc)3816 dsc_dcs2_fixup(CDSC *dsc)
3817 {
3818 char composite[] = "Composite";
3819 /* If DCS 2.0 single file format found, expose the separations
3820 * as multiple pages. Treat the initial EPS file as a single
3821 * page without comments, prolog or trailer.
3822 */
3823 if (dsc->dcs2) {
3824 int code = CDSC_OK;
3825 int page_number;
3826 DSC_OFFSET *pbegin;
3827 DSC_OFFSET *pend;
3828 DSC_OFFSET end;
3829 CDCS2 *pdcs = dsc->dcs2;
3830 /* Now treat the initial EPS file as a single page without
3831 * headers or trailer, so page extraction will fetch the
3832 * the correct separation. */
3833 if (dsc->page_count == 0)
3834 code = dsc_add_page(dsc, 1, composite);
3835 else if (dsc->page_count == 1)
3836 dsc->page[0].label =
3837 dsc_alloc_string(dsc, composite, (int)strlen(composite)+1);
3838 if (code != CDSC_OK)
3839 return code;
3840 page_number = dsc->page_count - 1;
3841 pbegin = &dsc->page[page_number].begin;
3842 pend = &dsc->page[page_number].end;
3843 if (*pbegin == *pend) {
3844 /* no page, so force it to conform to the following sections */
3845 *pbegin = 999999999;
3846 *pend = 0;
3847 }
3848
3849 if (dsc->begincomments != dsc->endcomments) {
3850 *pbegin = min(dsc->begincomments, *pbegin);
3851 dsc->begincomments = 0;
3852 *pend = max(dsc->endcomments, *pend);
3853 dsc->endcomments = 0;
3854 }
3855
3856 if (dsc->beginpreview != dsc->endpreview) {
3857 *pbegin = min(dsc->beginpreview, *pbegin);
3858 dsc->beginpreview = 0;
3859 *pend = max(dsc->endpreview, *pend);
3860 dsc->endpreview = 0;
3861 }
3862
3863 if (dsc->begindefaults != dsc->enddefaults) {
3864 *pbegin = min(dsc->begindefaults, *pbegin);
3865 dsc->begindefaults = 0;
3866 *pend = max(dsc->enddefaults, *pend);
3867 dsc->enddefaults = 0;
3868 }
3869
3870 if (dsc->beginprolog != dsc->endprolog) {
3871 *pbegin = min(dsc->beginprolog, *pbegin);
3872 dsc->beginprolog = 0;
3873 *pend = max(dsc->endprolog, *pend);
3874 dsc->endprolog = 0;
3875 }
3876
3877 if (dsc->beginsetup != dsc->endsetup) {
3878 *pbegin = min(dsc->beginsetup, *pbegin);
3879 dsc->beginsetup = 0;
3880 *pend = max(dsc->endsetup, *pend);
3881 dsc->endsetup = 0;
3882 }
3883
3884 if (dsc->begintrailer != dsc->endtrailer) {
3885 *pbegin = min(dsc->begintrailer, *pbegin);
3886 dsc->begintrailer = 0;
3887 *pend = max(dsc->endtrailer, *pend);
3888 dsc->endtrailer = 0;
3889 }
3890
3891 if (*pbegin == 999999999)
3892 *pbegin = *pend;
3893 end = 0; /* end of composite is start of first separation */
3894
3895 while (pdcs) {
3896 page_number = dsc->page_count;
3897 if ((pdcs->begin) && (pdcs->colourname != NULL)) {
3898 /* Single file DCS 2.0 */
3899 code = dsc_add_page(dsc, page_number+1, pdcs->colourname);
3900 if (code)
3901 return code;
3902 dsc->page[page_number].begin = pdcs->begin;
3903 dsc->page[page_number].end = pdcs->end;
3904 if (end != 0)
3905 end = min(end, pdcs->begin);
3906 else
3907 end = pdcs->begin; /* first separation */
3908 }
3909 else {
3910 /* Multiple file DCS 2.0 */
3911 if ((pdcs->location != NULL) &&
3912 (pdcs->filetype != NULL) &&
3913 (pdcs->colourname != NULL) &&
3914 (dsc_stricmp(pdcs->location, "Local") == 0) &&
3915 ((dsc_stricmp(pdcs->filetype, "EPS") == 0) ||
3916 (dsc_stricmp(pdcs->filetype, "EPSF") == 0))) {
3917 code = dsc_add_page(dsc, page_number+1, pdcs->colourname);
3918 if (code)
3919 return code;
3920 dsc->page[page_number].begin = 0;
3921 dsc->page[page_number].end = 0;
3922 }
3923 }
3924 pdcs = pdcs->next;
3925 }
3926 /* end of composite is start of first separation */
3927 if (end != 0)
3928 *pend = end;
3929 /* According to the DCS2 specification, the size of the composite
3930 * section can be determined by the smallest #offset.
3931 * Some incorrect DCS2 files don't put the separations inside
3932 * the DOS EPS PostScript section, and have a TIFF separation
3933 * between the composite and the first separation. This
3934 * contravenes the DCS2 specification. If we see one of these
3935 * files, bring the end of the composite back to the end of
3936 * the DOS EPS PostScript section.
3937 */
3938 if (dsc->doseps_end && (*pend > dsc->doseps_end))
3939 *pend = dsc->doseps_end;
3940 }
3941 return 0;
3942 }
3943
3944
3945 dsc_private int
dsc_parse_platefile(CDSC * dsc)3946 dsc_parse_platefile(CDSC *dsc)
3947 {
3948 unsigned int i, n;
3949 CDCS2 dcs2;
3950 CDCS2 *pdcs2;
3951 char colourname[MAXSTR];
3952 char filetype[MAXSTR];
3953 char location[MAXSTR];
3954 char *filename = NULL;
3955 int filename_length = 0;
3956 GSBOOL blank_line;
3957 GSBOOL single = FALSE;
3958 if (IS_DSC(dsc->line, "%%PlateFile:"))
3959 n = 12;
3960 else if (IS_DSC(dsc->line, "%%+"))
3961 n = 3;
3962 else
3963 return CDSC_ERROR; /* error */
3964
3965 memset(&dcs2, 0, sizeof(dcs2));
3966 memset(&colourname, 0, sizeof(colourname));
3967 memset(&filetype, 0, sizeof(filetype));
3968 memset(&location, 0, sizeof(location));
3969 memset(&filename, 0, sizeof(filename));
3970
3971 /* check for blank remainder of line */
3972 blank_line = TRUE;
3973 for (i=n; i<dsc->line_length; i++) {
3974 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
3975 blank_line = FALSE;
3976 break;
3977 }
3978 }
3979
3980 if (!blank_line) {
3981 dsc_copy_string(colourname, sizeof(colourname),
3982 dsc->line+n, dsc->line_length-n, &i);
3983 n+=i;
3984 if (i)
3985 dsc_copy_string(filetype, sizeof(filetype),
3986 dsc->line+n, dsc->line_length-n, &i);
3987 n+=i;
3988 while (IS_WHITE_OR_EOL(dsc->line[n]))
3989 n++;
3990 if (dsc->line[n] == '#') {
3991 /* single file DCS 2.0 */
3992 single = TRUE;
3993 n++;
3994 if (i)
3995 dcs2.begin= dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
3996 n+=i;
3997 if (i)
3998 dcs2.end= dcs2.begin +
3999 dsc_get_int(dsc->line+n, dsc->line_length-n, &i);
4000 }
4001 else {
4002 /* multiple file DCS 2.0 */
4003 if (i)
4004 dsc_copy_string(location, sizeof(location),
4005 dsc->line+n, dsc->line_length-n, &i);
4006 n+=i;
4007 if (i) {
4008 filename = dsc->line+n;
4009 filename_length = dsc->line_length-n;
4010 }
4011 }
4012 if (i==0)
4013 dsc_unknown(dsc); /* we didn't get all fields */
4014 else {
4015 /* Allocate strings */
4016 if (strlen(colourname))
4017 dcs2.colourname = dsc_alloc_string(dsc,
4018 colourname, (int)strlen(colourname));
4019 if (strlen(filetype))
4020 dcs2.filetype = dsc_alloc_string(dsc,
4021 filetype, (int)strlen(filetype));
4022 if (strlen(location))
4023 dcs2.location = dsc_alloc_string(dsc,
4024 location, (int)strlen(location));
4025 if (filename)
4026 dcs2.filename = dsc_add_line(dsc, filename, filename_length);
4027
4028 /* Prevent parser from reading separations */
4029 if (single)
4030 dsc->file_length = min(dsc->file_length, dcs2.begin);
4031 /* Allocate it */
4032 pdcs2 = (CDCS2 *)dsc_memalloc(dsc, sizeof(CDCS2));
4033 if (pdcs2 == NULL)
4034 return CDSC_ERROR; /* out of memory */
4035 memcpy(pdcs2, &dcs2, sizeof(CDCS2));
4036 /* Then add to list of separations */
4037 if (dsc->dcs2 == NULL)
4038 dsc->dcs2 = pdcs2;
4039 else {
4040 CDCS2 *this_dcs2 = dsc->dcs2;
4041 while (this_dcs2->next)
4042 this_dcs2 = this_dcs2->next;
4043 this_dcs2->next = pdcs2;
4044 }
4045 }
4046 }
4047 return CDSC_OK;
4048 }
4049
4050 /* Parse a DCS 1.0 plate comment, storing like a multi file DSC 2.0 */
4051 dsc_private int
dsc_parse_dcs1plate(CDSC * dsc)4052 dsc_parse_dcs1plate(CDSC *dsc)
4053 {
4054 unsigned int i, n = 0;
4055 CDCS2 dcs2;
4056 CDCS2 *pdcs2;
4057 const char *colourname;
4058 char filename[MAXSTR];
4059 GSBOOL blank_line;
4060 GSBOOL continued = FALSE;
4061 char *line = dsc->line;
4062
4063 memset(&dcs2, 0, sizeof(dcs2));
4064 memset(&filename, 0, sizeof(filename));
4065
4066 if (IS_DSC(line, "%%+")) {
4067 n = 3;
4068 line = dsc->last_line;
4069 continued = TRUE;
4070 }
4071
4072 if (IS_DSC(line, "%%CyanPlate:")) {
4073 colourname = "Cyan";
4074 if (!continued)
4075 n = 12;
4076 }
4077 else if (IS_DSC(line, "%%MagentaPlate:")) {
4078 colourname = "Magenta";
4079 if (!continued)
4080 n = 15;
4081 }
4082 else if (IS_DSC(line, "%%YellowPlate:")) {
4083 colourname = "Yellow";
4084 if (!continued)
4085 n = 14;
4086 }
4087 else if (IS_DSC(line, "%%BlackPlate:")) {
4088 colourname = "Black";
4089 if (!continued)
4090 n = 13;
4091 }
4092 else
4093 return CDSC_ERROR; /* error */
4094
4095 /* check for blank remainder of line */
4096 blank_line = TRUE;
4097 for (i=n; i<dsc->line_length; i++) {
4098 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4099 blank_line = FALSE;
4100 break;
4101 }
4102 }
4103
4104 if (!blank_line) {
4105 dsc_copy_string(filename, sizeof(filename),
4106 dsc->line+n, dsc->line_length-n, &i);
4107 if (i==0)
4108 dsc_unknown(dsc); /* we didn't get all fields */
4109 else {
4110 /* Allocate strings */
4111 dcs2.colourname = dsc_alloc_string(dsc,
4112 colourname, (int)strlen(colourname));
4113 dcs2.filetype = dsc_alloc_string(dsc, "EPS", 3);
4114 dcs2.location = dsc_alloc_string(dsc, "Local", 5);
4115 if (strlen(filename))
4116 dcs2.filename = dsc_alloc_string(dsc,
4117 filename, (int)strlen(filename));
4118 /* Allocate it */
4119 pdcs2 = (CDCS2 *)dsc_memalloc(dsc, sizeof(CDCS2));
4120 if (pdcs2 == NULL)
4121 return CDSC_ERROR; /* out of memory */
4122 memcpy(pdcs2, &dcs2, sizeof(CDCS2));
4123 /* Then add to list of separations */
4124 if (dsc->dcs2 == NULL)
4125 dsc->dcs2 = pdcs2;
4126 else {
4127 CDCS2 *this_dcs2 = dsc->dcs2;
4128 while (this_dcs2->next)
4129 this_dcs2 = this_dcs2->next;
4130 this_dcs2->next = pdcs2;
4131 }
4132 }
4133 }
4134 return CDSC_OK;
4135 }
4136
4137
4138 /* Find the filename which corresponds to this separation.
4139 * Used with multiple file DCS 2.0.
4140 * Returns NULL if there is no filename, or not DCS 2.0,
4141 * or single file DCS 2.0.
4142 * Caller will need to obtain the filesize from the file.
4143 */
4144 const char *
dsc_find_platefile(CDSC * dsc,int page)4145 dsc_find_platefile(CDSC *dsc, int page)
4146 {
4147 CDCS2 *pdcs = dsc->dcs2;
4148 int i = 1;
4149 while (pdcs) {
4150 if (pdcs->begin != pdcs->end)
4151 return NULL; /* Single file DCS 2.0 */
4152 if (pdcs->location && pdcs->filetype && pdcs->colourname
4153 && (dsc_stricmp(pdcs->location, "Local") == 0)
4154 && ((dsc_stricmp(pdcs->filetype, "EPS") == 0) ||
4155 (dsc_stricmp(pdcs->filetype, "EPSF") == 0))) {
4156 if (i == page)
4157 return pdcs->filename;
4158 i++;
4159 }
4160 pdcs = pdcs->next;
4161 }
4162 return NULL;
4163 }
4164
4165
4166 dsc_private CDSCCOLOUR *
dsc_find_colour(CDSC * dsc,const char * colourname)4167 dsc_find_colour(CDSC *dsc, const char *colourname)
4168 {
4169 CDSCCOLOUR *colour = dsc->colours;
4170 while (colour) {
4171 if (colour->name && (dsc_stricmp(colour->name, colourname)==0))
4172 return colour;
4173 colour = colour->next;
4174 }
4175 return 0;
4176 }
4177
4178 dsc_private int
dsc_parse_process_colours(CDSC * dsc)4179 dsc_parse_process_colours(CDSC *dsc)
4180 {
4181 unsigned int i, n;
4182 CDSCCOLOUR *pcolour;
4183 char colourname[MAXSTR];
4184 GSBOOL blank_line;
4185 if (IS_DSC(dsc->line, "%%DocumentProcessColors:"))
4186 n = 24;
4187 else if (IS_DSC(dsc->line, "%%+"))
4188 n = 3;
4189 else
4190 return CDSC_ERROR; /* error */
4191
4192 memset(&colourname, 0, sizeof(colourname));
4193
4194 /* check for blank remainder of line */
4195 blank_line = TRUE;
4196 for (i=n; i<dsc->line_length; i++) {
4197 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4198 blank_line = FALSE;
4199 break;
4200 }
4201 }
4202 while (IS_WHITE(dsc->line[n]))
4203 n++;
4204 if (COMPARE(dsc->line+n, "(atend)")) {
4205 if (dsc->scan_section == scan_comments)
4206 blank_line = TRUE;
4207 else {
4208 dsc_unknown(dsc);
4209 return CDSC_NOTDSC;
4210 }
4211 }
4212
4213 if (!blank_line) {
4214 do {
4215 dsc_copy_string(colourname, sizeof(colourname),
4216 dsc->line+n, dsc->line_length-n, &i);
4217 n+=i;
4218 if (i && strlen(colourname)) {
4219 if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
4220 pcolour = (CDSCCOLOUR *)
4221 dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
4222 if (pcolour == NULL)
4223 return CDSC_ERROR; /* out of memory */
4224 memset(pcolour, 0, sizeof(CDSCCOLOUR));
4225 pcolour->custom = CDSC_CUSTOM_COLOUR_UNKNOWN;
4226 pcolour->name = dsc_alloc_string(dsc,
4227 colourname, (int)strlen(colourname));
4228 if (dsc->colours == NULL)
4229 dsc->colours = pcolour;
4230 else {
4231 CDSCCOLOUR *this_colour = dsc->colours;
4232 while (this_colour->next)
4233 this_colour = this_colour->next;
4234 this_colour->next = pcolour;
4235 }
4236 }
4237 pcolour->type = CDSC_COLOUR_PROCESS;
4238 if (dsc_stricmp(colourname, "Cyan")==0) {
4239 pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4240 pcolour->cyan = 1.0;
4241 pcolour->magenta = pcolour->yellow = pcolour->black = 0.0;
4242 }
4243 else if (dsc_stricmp(colourname, "Magenta")==0) {
4244 pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4245 pcolour->magenta = 1.0;
4246 pcolour->cyan = pcolour->yellow = pcolour->black = 0.0;
4247 }
4248 else if (dsc_stricmp(colourname, "Yellow")==0) {
4249 pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4250 pcolour->yellow = 1.0;
4251 pcolour->cyan = pcolour->magenta = pcolour->black = 0.0;
4252 }
4253 else if (dsc_stricmp(colourname, "Black")==0) {
4254 pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4255 pcolour->black = 1.0;
4256 pcolour->cyan = pcolour->magenta = pcolour->yellow = 0.0;
4257 }
4258 else if (dsc_stricmp(colourname, "Red")==0) {
4259 pcolour->custom = CDSC_CUSTOM_COLOUR_RGB;
4260 pcolour->red = 1.0;
4261 pcolour->green = pcolour->blue = 0.0;
4262 }
4263 else if (dsc_stricmp(colourname, "Green")==0) {
4264 pcolour->custom = CDSC_CUSTOM_COLOUR_RGB;
4265 pcolour->green = 1.0;
4266 pcolour->red = pcolour->blue = 0.0;
4267 }
4268 else if (dsc_stricmp(colourname, "Blue")==0) {
4269 pcolour->custom = CDSC_CUSTOM_COLOUR_RGB;
4270 pcolour->blue = 1.0;
4271 pcolour->red = pcolour->green = 0.0;
4272 }
4273 }
4274 } while (i != 0);
4275 }
4276 return CDSC_OK;
4277 }
4278
4279 dsc_private int
dsc_parse_custom_colours(CDSC * dsc)4280 dsc_parse_custom_colours(CDSC *dsc)
4281 {
4282 unsigned int i, n;
4283 CDSCCOLOUR *pcolour;
4284 char colourname[MAXSTR];
4285 GSBOOL blank_line;
4286 if (IS_DSC(dsc->line, "%%DocumentCustomColors:"))
4287 n = 23;
4288 else if (IS_DSC(dsc->line, "%%+"))
4289 n = 3;
4290 else
4291 return CDSC_ERROR; /* error */
4292
4293 memset(&colourname, 0, sizeof(colourname));
4294
4295 /* check for blank remainder of line */
4296 blank_line = TRUE;
4297 for (i=n; i<dsc->line_length; i++) {
4298 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4299 blank_line = FALSE;
4300 break;
4301 }
4302 }
4303 while (IS_WHITE(dsc->line[n]))
4304 n++;
4305 if (COMPARE(dsc->line+n, "(atend)")) {
4306 if (dsc->scan_section == scan_comments)
4307 blank_line = TRUE;
4308 else {
4309 dsc_unknown(dsc);
4310 return CDSC_NOTDSC;
4311 }
4312 }
4313
4314 if (!blank_line) {
4315 do {
4316 dsc_copy_string(colourname, sizeof(colourname),
4317 dsc->line+n, dsc->line_length-n, &i);
4318 n+=i;
4319 if (i && strlen(colourname)) {
4320 if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
4321 pcolour = (CDSCCOLOUR *)
4322 dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
4323 if (pcolour == NULL)
4324 return CDSC_ERROR; /* out of memory */
4325 memset(pcolour, 0, sizeof(CDSCCOLOUR));
4326 pcolour->name = dsc_alloc_string(dsc,
4327 colourname, (int)strlen(colourname));
4328 pcolour->custom = CDSC_CUSTOM_COLOUR_UNKNOWN;
4329 if (dsc->colours == NULL)
4330 dsc->colours = pcolour;
4331 else {
4332 CDSCCOLOUR *this_colour = dsc->colours;
4333 while (this_colour->next)
4334 this_colour = this_colour->next;
4335 this_colour->next = pcolour;
4336 }
4337 }
4338 pcolour->type = CDSC_COLOUR_CUSTOM;
4339 }
4340 } while (i != 0);
4341 }
4342 return CDSC_OK;
4343 }
4344
4345
4346 dsc_private int
dsc_parse_cmyk_custom_colour(CDSC * dsc)4347 dsc_parse_cmyk_custom_colour(CDSC *dsc)
4348 {
4349 unsigned int i, n;
4350 CDSCCOLOUR *pcolour;
4351 char colourname[MAXSTR];
4352 float cyan, magenta, yellow, black;
4353 GSBOOL blank_line;
4354 if (IS_DSC(dsc->line, "%%CMYKCustomColor:"))
4355 n = 18;
4356 else if (IS_DSC(dsc->line, "%%+"))
4357 n = 3;
4358 else
4359 return CDSC_ERROR; /* error */
4360
4361 memset(&colourname, 0, sizeof(colourname));
4362
4363 /* check for blank remainder of line */
4364
4365 do {
4366 blank_line = TRUE;
4367 for (i=n; i<dsc->line_length; i++) {
4368 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4369 blank_line = FALSE;
4370 break;
4371 }
4372 }
4373 if (blank_line)
4374 break;
4375 else {
4376 cyan = magenta = yellow = black = 0.0;
4377 cyan = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4378 n += i;
4379 if (i)
4380 magenta = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4381 n += i;
4382 if (i)
4383 yellow = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4384 n += i;
4385 if (i)
4386 black = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4387 n += i;
4388 if (i)
4389 dsc_copy_string(colourname, sizeof(colourname),
4390 dsc->line+n, dsc->line_length-n, &i);
4391 n+=i;
4392 if (i && strlen(colourname)) {
4393 if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
4394 pcolour = (CDSCCOLOUR *)
4395 dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
4396 if (pcolour == NULL)
4397 return CDSC_ERROR; /* out of memory */
4398 memset(pcolour, 0, sizeof(CDSCCOLOUR));
4399 pcolour->name = dsc_alloc_string(dsc,
4400 colourname, (int)strlen(colourname));
4401 pcolour->type = CDSC_COLOUR_UNKNOWN;
4402 if (dsc->colours == NULL)
4403 dsc->colours = pcolour;
4404 else {
4405 CDSCCOLOUR *this_colour = dsc->colours;
4406 while (this_colour->next)
4407 this_colour = this_colour->next;
4408 this_colour->next = pcolour;
4409 }
4410 }
4411 pcolour->custom = CDSC_CUSTOM_COLOUR_CMYK;
4412 pcolour->cyan = cyan;
4413 pcolour->magenta = magenta;
4414 pcolour->yellow = yellow;
4415 pcolour->black = black;
4416 }
4417 }
4418 } while (i != 0);
4419 return CDSC_OK;
4420 }
4421
4422 dsc_private int
dsc_parse_rgb_custom_colour(CDSC * dsc)4423 dsc_parse_rgb_custom_colour(CDSC *dsc)
4424 {
4425 unsigned int i, n;
4426 CDSCCOLOUR *pcolour;
4427 char colourname[MAXSTR];
4428 float red, green, blue;
4429 GSBOOL blank_line;
4430 if (IS_DSC(dsc->line, "%%RGBCustomColor:"))
4431 n = 17;
4432 else if (IS_DSC(dsc->line, "%%+"))
4433 n = 3;
4434 else
4435 return CDSC_ERROR; /* error */
4436
4437 memset(&colourname, 0, sizeof(colourname));
4438
4439 /* check for blank remainder of line */
4440
4441 do {
4442 blank_line = TRUE;
4443 for (i=n; i<dsc->line_length; i++) {
4444 if (!IS_WHITE_OR_EOL(dsc->line[i])) {
4445 blank_line = FALSE;
4446 break;
4447 }
4448 }
4449 if (blank_line)
4450 break;
4451 else {
4452 red = green = blue = 0.0;
4453 red = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4454 n += i;
4455 if (i)
4456 green = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4457 n += i;
4458 if (i)
4459 blue = dsc_get_real(dsc->line+n, dsc->line_length-n, &i);
4460 n += i;
4461 if (i)
4462 dsc_copy_string(colourname, sizeof(colourname),
4463 dsc->line+n, dsc->line_length-n, &i);
4464 n+=i;
4465 if (i && strlen(colourname)) {
4466 if ((pcolour = dsc_find_colour(dsc, colourname)) == NULL) {
4467 pcolour = (CDSCCOLOUR *)
4468 dsc_memalloc(dsc, sizeof(CDSCCOLOUR));
4469 if (pcolour == NULL)
4470 return CDSC_ERROR; /* out of memory */
4471 memset(pcolour, 0, sizeof(CDSCCOLOUR));
4472 pcolour->name = dsc_alloc_string(dsc,
4473 colourname, (int)strlen(colourname));
4474 pcolour->type = CDSC_COLOUR_UNKNOWN;
4475 if (dsc->colours == NULL)
4476 dsc->colours = pcolour;
4477 else {
4478 CDSCCOLOUR *this_colour = dsc->colours;
4479 while (this_colour->next)
4480 this_colour = this_colour->next;
4481 this_colour->next = pcolour;
4482 }
4483 }
4484 pcolour->custom = CDSC_CUSTOM_COLOUR_RGB;
4485 pcolour->red = red;
4486 pcolour->green = green;
4487 pcolour->blue = blue;
4488 }
4489 }
4490 } while (i != 0);
4491 return CDSC_OK;
4492 }
4493