1 /* Copyright (C) 2000-2001, Ghostgum Software Pty Ltd. All rights reserved.
3 This file is part of GSview.
5 This file is distributed in the hope that it will be useful, but
6 WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
7 to anyone for the consequences of using it or for whether it serves any
8 particular purpose or works at all, unless he says so in writing. Refer
9 to the GNU General Public License for full details.
11 Everyone is granted permission to copy, modify and redistribute this
12 file, but only under the conditions described in the GNU General
13 Public License. A copy of this license is supposed to have been given
14 to you along with this file so you can know your rights and
15 responsibilities. It should be in a file named COPYING. Among other
16 things, the copyright notice and this notice must be preserved on all
22 /* dscparse.c - DSC parser */
25 * This is a DSC parser, based on the DSC 3.0 spec,
26 * with a few DSC 2.1 additions for page size.
28 * Current limitations:
29 * %%+ may be used after any comment in the comment or trailer,
30 * but is currently only supported by
33 * DSC 2.1 additions (discontinued in DSC 3.0):
34 * %%DocumentPaperColors:
35 * %%DocumentPaperForms:
36 * %%DocumentPaperSizes:
37 * %%DocumentPaperWeights:
38 * %%PaperColor: (ignored)
39 * %%PaperForm: (ignored)
41 * %%PaperWeight: (ignored)
43 * Other additions for defaults or page section
44 % %%ViewingOrientation: xx xy yx yy
47 #include <stdio.h> /* for sprintf(), not file I/O */
56 /* Macros for comparing string literals
57 * For maximum speed, the length of the second macro argument is
58 * computed at compile time.
59 * THE SECOND MACRO ARGUMENT MUST BE A STRING LITERAL.
61 #define COMPARE(p,str) (strncmp((const char *)(p), (str), sizeof(str)-1)==0)
62 #define IS_DSC(line, str) (COMPARE((line), (str)))
64 /* Macros for comparing the first one or two characters */
65 #define IS_WHITE(ch) (((ch)==' ') || ((ch)=='\t'))
66 #define IS_EOL(ch) (((ch)=='\r') || ((ch)=='\n'))
67 #define IS_WHITE_OR_EOL(ch) (IS_WHITE(ch) || IS_EOL(ch))
68 #define IS_BLANK(str) (IS_EOL(str[0]))
69 #define NOT_DSC_LINE(str) (((str)[0]!='%') || ((str)[1]!='%'))
71 /* Macros for document offset to start and end of line */
72 #define DSC_START(dsc) ((dsc)->data_offset + (dsc)->data_index - (dsc)->line_length)
73 #define DSC_END(dsc) ((dsc)->data_offset + (dsc)->data_index)
75 /* dsc_scan_SECTION() functions return one of
76 * CDSC_ERROR, CDSC_OK, CDSC_NOTDSC
77 * or one of the following
79 /* The line should be passed on to the next section parser. */
80 #define CDSC_PROPAGATE 10
82 /* If document is DOS EPS and we haven't read 30 bytes, ask for more. */
83 #define CDSC_NEEDMORE 11
85 /* local prototypes */
86 dsc_private
void * dsc_memalloc(P2(CDSC
*dsc
, size_t size
));
87 dsc_private
void dsc_memfree(P2(CDSC
*dsc
, void *ptr
));
88 dsc_private CDSC
* dsc_init2(P1(CDSC
*dsc
));
89 dsc_private
void dsc_reset(P1(CDSC
*dsc
));
90 dsc_private
void dsc_section_join(P3(unsigned long begin
, unsigned long *pend
, unsigned long **pplast
));
91 dsc_private
int dsc_read_line(P1(CDSC
*dsc
));
92 dsc_private
int dsc_read_doseps(P1(CDSC
*dsc
));
93 dsc_private
char * dsc_alloc_string(P3(CDSC
*dsc
, const char *str
, int len
));
94 dsc_private
char * dsc_add_line(P3(CDSC
*dsc
, const char *line
, unsigned int len
));
95 dsc_private
char * dsc_copy_string(P5(char *str
, unsigned int slen
,
96 char *line
, unsigned int len
, unsigned int *offset
));
97 dsc_private GSDWORD
dsc_get_dword(P1(const unsigned char *buf
));
98 dsc_private GSWORD
dsc_get_word(P1(const unsigned char *buf
));
99 dsc_private
int dsc_get_int(P3(const char *line
, unsigned int len
, unsigned int *offset
));
100 dsc_private
float dsc_get_real(P3(const char *line
, unsigned int len
,
101 unsigned int *offset
));
102 dsc_private
int dsc_stricmp(P2(const char *s
, const char *t
));
103 dsc_private
void dsc_unknown(P1(CDSC
*dsc
));
104 dsc_private GSBOOL
dsc_is_section(char *line
);
105 dsc_private
int dsc_parse_pages(P1(CDSC
*dsc
));
106 dsc_private
int dsc_parse_bounding_box(P3(CDSC
*dsc
, CDSCBBOX
** pbbox
, int offset
));
107 dsc_private
int dsc_parse_float_bounding_box(P3(CDSC
*dsc
, CDSCFBBOX
** pfbbox
, int offset
));
108 dsc_private
int dsc_parse_orientation(P3(CDSC
*dsc
, unsigned int *porientation
,
110 dsc_private
int dsc_parse_order(P1(CDSC
*dsc
));
111 dsc_private
int dsc_parse_media(P2(CDSC
*dsc
, const CDSCMEDIA
**page_media
));
112 dsc_private
int dsc_parse_document_media(P1(CDSC
*dsc
));
113 dsc_private
int dsc_parse_viewing_orientation(P2(CDSC
*dsc
, CDSCCTM
**pctm
));
114 dsc_private
int dsc_parse_page(P1(CDSC
*dsc
));
115 dsc_private
void dsc_save_line(P1(CDSC
*dsc
));
116 dsc_private
int dsc_scan_type(P1(CDSC
*dsc
));
117 dsc_private
int dsc_scan_comments(P1(CDSC
*dsc
));
118 dsc_private
int dsc_scan_preview(P1(CDSC
*dsc
));
119 dsc_private
int dsc_scan_defaults(P1(CDSC
*dsc
));
120 dsc_private
int dsc_scan_prolog(P1(CDSC
*dsc
));
121 dsc_private
int dsc_scan_setup(P1(CDSC
*dsc
));
122 dsc_private
int dsc_scan_page(P1(CDSC
*dsc
));
123 dsc_private
int dsc_scan_trailer(P1(CDSC
*dsc
));
124 dsc_private
int dsc_error(P4(CDSC
*dsc
, unsigned int explanation
,
125 char *line
, unsigned int line_len
));
127 /* DSC error reporting */
128 dsc_private
const int dsc_severity
[] = {
129 CDSC_ERROR_WARN
, /* CDSC_MESSAGE_BBOX */
130 CDSC_ERROR_WARN
, /* CDSC_MESSAGE_EARLY_TRAILER */
131 CDSC_ERROR_WARN
, /* CDSC_MESSAGE_EARLY_EOF */
132 CDSC_ERROR_ERROR
, /* CDSC_MESSAGE_PAGE_IN_TRAILER */
133 CDSC_ERROR_ERROR
, /* CDSC_MESSAGE_PAGE_ORDINAL */
134 CDSC_ERROR_ERROR
, /* CDSC_MESSAGE_PAGES_WRONG */
135 CDSC_ERROR_ERROR
, /* CDSC_MESSAGE_EPS_NO_BBOX */
136 CDSC_ERROR_ERROR
, /* CDSC_MESSAGE_EPS_PAGES */
137 CDSC_ERROR_WARN
, /* CDSC_MESSAGE_NO_MEDIA */
138 CDSC_ERROR_WARN
, /* CDSC_MESSAGE_ATEND */
139 CDSC_ERROR_INFORM
, /* CDSC_MESSAGE_DUP_COMMENT */
140 CDSC_ERROR_INFORM
, /* CDSC_MESSAGE_DUP_TRAILER */
141 CDSC_ERROR_WARN
, /* CDSC_MESSAGE_BEGIN_END */
142 CDSC_ERROR_INFORM
, /* CDSC_MESSAGE_BAD_SECTION */
143 CDSC_ERROR_INFORM
, /* CDSC_MESSAGE_LONG_LINE */
144 CDSC_ERROR_WARN
, /* CDSC_MESSAGE_INCORRECT_USAGE */
148 #define DSC_MAX_ERROR ((sizeof(dsc_severity) / sizeof(int))-2)
150 const CDSCMEDIA dsc_known_media
[CDSC_KNOWN_MEDIA
] = {
151 /* These sizes taken from Ghostscript gs_statd.ps */
152 {"11x17", 792, 1224, 0, NULL
, NULL
, NULL
},
153 {"A0", 2380, 3368, 0, NULL
, NULL
, NULL
},
154 {"A1", 1684, 2380, 0, NULL
, NULL
, NULL
},
155 {"A2", 1190, 1684, 0, NULL
, NULL
, NULL
},
156 {"A3", 842, 1190, 0, NULL
, NULL
, NULL
},
157 {"A4", 595, 842, 0, NULL
, NULL
, NULL
},
158 {"A5", 421, 595, 0, NULL
, NULL
, NULL
},
159 {"A6", 297, 421, 0, NULL
, NULL
, NULL
},
160 {"A7", 210, 297, 0, NULL
, NULL
, NULL
},
161 {"A8", 148, 210, 0, NULL
, NULL
, NULL
},
162 {"A9", 105, 148, 0, NULL
, NULL
, NULL
},
163 {"A10", 74, 105, 0, NULL
, NULL
, NULL
},
164 {"B0", 2836, 4008, 0, NULL
, NULL
, NULL
},
165 {"B1", 2004, 2836, 0, NULL
, NULL
, NULL
},
166 {"B2", 1418, 2004, 0, NULL
, NULL
, NULL
},
167 {"B3", 1002, 1418, 0, NULL
, NULL
, NULL
},
168 {"B4", 709, 1002, 0, NULL
, NULL
, NULL
}, /* ISO, but not Adobe standard */
169 {"B5", 501, 709, 0, NULL
, NULL
, NULL
}, /* ISO, but not Adobe standard */
170 {"B6", 354, 501, 0, NULL
, NULL
, NULL
},
171 {"C0", 2600, 3677, 0, NULL
, NULL
, NULL
},
172 {"C1", 1837, 2600, 0, NULL
, NULL
, NULL
},
173 {"C2", 1298, 1837, 0, NULL
, NULL
, NULL
},
174 {"C3", 918, 1298, 0, NULL
, NULL
, NULL
},
175 {"C4", 649, 918, 0, NULL
, NULL
, NULL
},
176 {"C5", 459, 649, 0, NULL
, NULL
, NULL
},
177 {"C6", 323, 459, 0, NULL
, NULL
, NULL
},
178 {"Ledger", 1224, 792, 0, NULL
, NULL
, NULL
},
179 {"Legal", 612, 1008, 0, NULL
, NULL
, NULL
},
180 {"Letter", 612, 792, 0, NULL
, NULL
, NULL
},
181 {"Note", 612, 792, 0, NULL
, NULL
, NULL
},
182 // ISO and JIS B sizes are different....
183 {"jisb0", 2916, 4128, 0, NULL
, NULL
, NULL
},
184 {"jisb1", 2064, 2916, 0, NULL
, NULL
, NULL
},
185 {"jisb2", 1458, 2064, 0, NULL
, NULL
, NULL
},
186 {"jisb3", 1032, 1458, 0, NULL
, NULL
, NULL
},
187 {"jisb4", 729, 1032, 0, NULL
, NULL
, NULL
},
188 {"jisb5", 516, 729, 0, NULL
, NULL
, NULL
},
189 {"jisb6", 363, 516, 0, NULL
, NULL
, NULL
},
190 // U.S. CAD standard paper sizes
191 {"archE", 2592, 3456, 0, NULL
, NULL
, NULL
},
192 {"archD", 1728, 2592, 0, NULL
, NULL
, NULL
},
193 {"archC", 1296, 1728, 0, NULL
, NULL
, NULL
},
194 {"archB", 864, 1296, 0, NULL
, NULL
, NULL
},
195 {"archA", 648, 864, 0, NULL
, NULL
, NULL
},
197 {"flsa", 612, 936, 0, NULL
, NULL
, NULL
}, /* U.S. foolscap */
198 {"flse", 612, 936, 0, NULL
, NULL
, NULL
}, /* European foolscap */
199 {"halfletter", 396, 612, 0, NULL
, NULL
, NULL
},
200 {NULL
, 0, 0, 0, NULL
, NULL
, NULL
}
204 enum CDSC_SCAN_SECTION
{
207 scan_pre_preview
= 2,
209 scan_pre_defaults
= 4,
217 scan_pre_trailer
= 12,
222 static const char * const dsc_scan_section_name
[15] = {
224 "pre-Preview", "Preview",
225 "pre-Defaults", "Defaults",
226 "pre-Prolog", "Prolog",
227 "pre-Setup", "Setup",
229 "pre-Trailer", "Trailer",
233 /******************************************************************/
234 /* Public functions */
235 /******************************************************************/
239 dsc_init(void *caller_data
)
241 CDSC
*dsc
= (CDSC
*)malloc(sizeof(CDSC
));
244 memset(dsc
, 0, sizeof(CDSC
));
245 dsc
->caller_data
= caller_data
;
247 return dsc_init2(dsc
);
250 /* constructor, with caller supplied memalloc */
254 void *(*memalloc
)(size_t size
, void *closure_data
),
255 void (*memfree
)(void *ptr
, void *closure_data
),
258 CDSC
*dsc
= (CDSC
*)memalloc(sizeof(CDSC
), closure_data
);
261 memset(dsc
, 0, sizeof(CDSC
));
262 dsc
->caller_data
= caller_data
;
264 dsc
->memalloc
= memalloc
;
265 dsc
->memfree
= memfree
;
266 dsc
->mem_closure_data
= closure_data
;
268 return dsc_init2(dsc
);
280 dsc_memfree(dsc
, dsc
);
284 /* Tell DSC parser how long document will be, to allow ignoring
285 * of early %%Trailer and %%EOF. This is optional.
288 dsc_set_length(CDSC
*dsc
, unsigned long len
)
290 dsc
->file_length
= len
;
293 /* Process a buffer containing DSC comments and PostScript */
294 /* Return value is < 0 for error, >=0 for OK.
297 * CDSC_NOTDSC (DSC will be ignored)
298 * other values indicate the last DSC comment read
301 dsc_scan_data(CDSC
*dsc
, const char *data
, int length
)
309 if (dsc
->id
== CDSC_NOTDSC
)
313 return CDSC_OK
; /* ignore */
316 /* EOF, so process what remains */
321 if (dsc
->id
== CDSC_NOTDSC
)
325 /* move existing data if needed */
326 if (dsc
->data_length
> CDSC_DATA_LENGTH
/2) {
327 memmove(dsc
->data
, dsc
->data
+ dsc
->data_index
,
328 dsc
->data_length
- dsc
->data_index
);
329 dsc
->data_offset
+= dsc
->data_index
;
330 dsc
->data_length
-= dsc
->data_index
;
333 /* append to buffer */
334 bytes_read
= min(length
, (int)(CDSC_DATA_LENGTH
- dsc
->data_length
));
335 memcpy(dsc
->data
+ dsc
->data_length
, data
, bytes_read
);
336 dsc
->data_length
+= bytes_read
;
338 length
-= bytes_read
;
340 if (dsc
->scan_section
== scan_none
) {
341 code
= dsc_scan_type(dsc
);
342 if (code
== CDSC_NEEDMORE
) {
343 /* need more characters before we can identify type */
350 if (code
== CDSC_NOTDSC
) {
351 dsc
->id
= CDSC_NOTDSC
;
355 while ((code
= dsc_read_line(dsc
)) > 0) {
356 if (dsc
->id
== CDSC_NOTDSC
)
358 if (dsc
->doseps_end
&&
359 (dsc
->data_offset
+ dsc
->data_index
> dsc
->doseps_end
)) {
360 /* have read past end of DOS EPS PostScript section */
361 return CDSC_OK
; /* ignore */
365 if (dsc
->skip_document
)
366 continue; /* embedded document */
368 continue; /* embedded lines */
369 if (IS_DSC(dsc
->line
, "%%BeginData:"))
371 if (IS_DSC(dsc
->line
, "%%BeginBinary:"))
373 if (IS_DSC(dsc
->line
, "%%EndDocument"))
375 if (IS_DSC(dsc
->line
, "%%EndData"))
377 if (IS_DSC(dsc
->line
, "%%EndBinary"))
381 switch (dsc
->scan_section
) {
383 code
= dsc_scan_comments(dsc
);
385 case scan_pre_preview
:
387 code
= dsc_scan_preview(dsc
);
389 case scan_pre_defaults
:
391 code
= dsc_scan_defaults(dsc
);
393 case scan_pre_prolog
:
395 code
= dsc_scan_prolog(dsc
);
399 code
= dsc_scan_setup(dsc
);
403 code
= dsc_scan_page(dsc
);
405 case scan_pre_trailer
:
407 code
= dsc_scan_trailer(dsc
);
416 /* repeat if line is start of next section */
417 } while (code
== CDSC_PROPAGATE
);
419 /* if DOS EPS header not complete, ask for more */
420 if (code
== CDSC_NEEDMORE
) {
424 if (code
== CDSC_NOTDSC
) {
425 dsc
->id
= CDSC_NOTDSC
;
429 } while (length
!= 0);
431 return (code
< 0) ? code
: dsc
->id
;
434 /* Tidy up from incorrect DSC comments */
442 if (dsc
->id
== CDSC_NOTDSC
)
445 /* flush last partial line */
446 dsc_scan_data(dsc
, NULL
, 0);
448 /* Fix DSC error: code between %%EndSetup and %%Page */
449 if (dsc
->page_count
&& (dsc
->page
[0].begin
!= dsc
->endsetup
)
450 && (dsc
->endsetup
!= dsc
->beginsetup
)) {
451 dsc
->endsetup
= dsc
->page
[0].begin
;
452 dsc_debug_print(dsc
, "Warning: code included between setup and first page\n");
455 /* Last page contained a false trailer, */
456 /* so extend last page to start of trailer */
457 if (dsc
->page_count
&& (dsc
->begintrailer
!= 0) &&
458 (dsc
->page
[dsc
->page_count
-1].end
!= dsc
->begintrailer
)) {
459 dsc_debug_print(dsc
, "Ignoring earlier misplaced trailer\n");
460 dsc_debug_print(dsc
, "and extending last page to start of trailer\n");
461 dsc
->page
[dsc
->page_count
-1].end
= dsc
->begintrailer
;
465 * Join up all sections.
466 * There might be extra code between them, or we might have
467 * missed including the \n which followed \r.
469 last
= &dsc
->endcomments
;
470 dsc_section_join(dsc
->beginpreview
, &dsc
->endpreview
, &last
);
471 dsc_section_join(dsc
->begindefaults
, &dsc
->enddefaults
, &last
);
472 dsc_section_join(dsc
->beginprolog
, &dsc
->endprolog
, &last
);
473 dsc_section_join(dsc
->beginsetup
, &dsc
->endsetup
, &last
);
474 for (i
=0; i
<dsc
->page_count
; i
++)
475 dsc_section_join(dsc
->page
[i
].begin
, &dsc
->page
[i
].end
, &last
);
476 if (dsc
->begintrailer
)
477 *last
= dsc
->begintrailer
;
479 if ((dsc
->page_pages
== 0) && (dsc
->page_count
== 1)) {
480 /* don't flag an error if %%Pages absent but one %%Page found */
481 /* adjust incorrect page count */
482 dsc
->page_pages
= dsc
->page_count
;
485 /* Warnings and Errors that we can now identify */
486 if ((dsc
->page_count
!= dsc
->page_pages
)) {
487 int rc
= dsc_error(dsc
, CDSC_MESSAGE_PAGES_WRONG
, NULL
, 0);
489 case CDSC_RESPONSE_OK
:
490 /* adjust incorrect page count */
491 dsc
->page_pages
= dsc
->page_count
;
493 case CDSC_RESPONSE_CANCEL
:
495 case CDSC_RESPONSE_IGNORE_ALL
:
500 if (dsc
->epsf
&& (dsc
->bbox
== (CDSCBBOX
*)NULL
)) {
501 /* EPS files MUST include a BoundingBox */
502 int rc
= dsc_error(dsc
, CDSC_MESSAGE_EPS_NO_BBOX
, NULL
, 0);
504 case CDSC_RESPONSE_OK
:
505 /* Assume that it is EPS */
507 case CDSC_RESPONSE_CANCEL
:
508 /* Is NOT an EPS file */
510 case CDSC_RESPONSE_IGNORE_ALL
:
515 if (dsc
->epsf
&& ((dsc
->page_count
> 1) || (dsc
->page_pages
> 1))) {
516 int rc
= dsc_error(dsc
, CDSC_MESSAGE_EPS_PAGES
, NULL
, 0);
518 case CDSC_RESPONSE_OK
:
521 case CDSC_RESPONSE_CANCEL
:
522 /* Is NOT an EPS file */
525 case CDSC_RESPONSE_IGNORE_ALL
:
530 if ((dsc
->media_count
== 1) && (dsc
->page_media
== NULL
)) {
531 /* if one only media was specified, and default page media */
532 /* was not specified, assume that default is the only media. */
533 dsc
->page_media
= dsc
->media
[0];
536 if ((dsc
->media_count
!= 0) && (dsc
->page_media
== NULL
)) {
537 int rc
= dsc_error(dsc
, CDSC_MESSAGE_NO_MEDIA
, NULL
, 0);
539 case CDSC_RESPONSE_OK
:
540 /* default media is first listed */
541 dsc
->page_media
= dsc
->media
[0];
543 case CDSC_RESPONSE_CANCEL
:
544 /* No default media */
546 case CDSC_RESPONSE_IGNORE_ALL
:
551 /* make sure all pages have a label */
552 for (i
=0; i
<dsc
->page_count
; i
++) {
553 if (strlen(dsc
->page
[i
].label
) == 0) {
554 sprintf(buf
, "%d", i
+1);
555 if ((dsc
->page
[i
].label
= dsc_alloc_string(dsc
, buf
, strlen(buf
)))
557 return CDSC_ERROR
; /* no memory */
563 /* Install a function to be used for displaying messages about
564 * DSC errors and warnings, and to request advice from user.
565 * Installing an error function is optional.
568 dsc_set_error_function(CDSC
*dsc
,
569 int (*fn
)(P5(void *caller_data
, CDSC
*dsc
,
570 unsigned int explanation
, const char *line
, unsigned int line_len
)))
572 dsc
->dsc_error_fn
= fn
;
576 /* Install a function for printing debug messages */
577 /* This is optional */
579 dsc_set_debug_function(CDSC
*dsc
,
580 void (*debug_fn
)(P2(void *caller_data
, const char *str
)))
582 dsc
->debug_print_fn
= debug_fn
;
585 /* Doesn't need to be public for PostScript documents */
586 /* Made public so GSview can add pages when processing PDF files */
588 dsc_add_page(CDSC
*dsc
, int ordinal
, char *label
)
590 dsc
->page
[dsc
->page_count
].ordinal
= ordinal
;
591 dsc
->page
[dsc
->page_count
].label
=
592 dsc_alloc_string(dsc
, label
, strlen(label
)+1);
593 dsc
->page
[dsc
->page_count
].begin
= 0;
594 dsc
->page
[dsc
->page_count
].end
= 0;
595 dsc
->page
[dsc
->page_count
].orientation
= CDSC_ORIENT_UNKNOWN
;
596 dsc
->page
[dsc
->page_count
].media
= NULL
;
597 dsc
->page
[dsc
->page_count
].bbox
= NULL
;
598 dsc
->page
[dsc
->page_count
].viewing_orientation
= NULL
;
601 if (dsc
->page_count
>= dsc
->page_chunk_length
) {
602 CDSCPAGE
*new_page
= (CDSCPAGE
*)dsc_memalloc(dsc
,
603 (CDSC_PAGE_CHUNK
+dsc
->page_count
) * sizeof(CDSCPAGE
));
604 if (new_page
== NULL
)
605 return CDSC_ERROR
; /* out of memory */
606 memcpy(new_page
, dsc
->page
,
607 dsc
->page_count
* sizeof(CDSCPAGE
));
608 dsc_memfree(dsc
, dsc
->page
);
610 dsc
->page_chunk_length
= CDSC_PAGE_CHUNK
+dsc
->page_count
;
615 /* Doesn't need to be public for PostScript documents */
616 /* Made public so GSview can store PDF MediaBox */
618 dsc_add_media(CDSC
*dsc
, CDSCMEDIA
*media
)
620 CDSCMEDIA
**newmedia_array
;
623 /* extend media array */
624 newmedia_array
= (CDSCMEDIA
**)dsc_memalloc(dsc
,
625 (dsc
->media_count
+ 1) * sizeof(CDSCMEDIA
*));
626 if (newmedia_array
== NULL
)
627 return CDSC_ERROR
; /* out of memory */
628 if (dsc
->media
!= NULL
) {
629 memcpy(newmedia_array
, dsc
->media
,
630 dsc
->media_count
* sizeof(CDSCMEDIA
*));
631 dsc_memfree(dsc
, dsc
->media
);
633 dsc
->media
= newmedia_array
;
635 /* allocate new media */
636 newmedia
= dsc
->media
[dsc
->media_count
] =
637 (CDSCMEDIA
*)dsc_memalloc(dsc
, sizeof(CDSCMEDIA
));
638 if (newmedia
== NULL
)
639 return CDSC_ERROR
; /* out of memory */
640 newmedia
->name
= NULL
;
641 newmedia
->width
= 595.0;
642 newmedia
->height
= 842.0;
643 newmedia
->weight
= 80.0;
644 newmedia
->colour
= NULL
;
645 newmedia
->type
= NULL
;
646 newmedia
->mediabox
= NULL
;
651 newmedia
->name
= dsc_alloc_string(dsc
, media
->name
,
652 strlen(media
->name
));
653 if (newmedia
->name
== NULL
)
654 return CDSC_ERROR
; /* no memory */
656 newmedia
->width
= media
->width
;
657 newmedia
->height
= media
->height
;
658 newmedia
->weight
= media
->weight
;
660 newmedia
->colour
= dsc_alloc_string(dsc
, media
->colour
,
661 strlen(media
->colour
));
662 if (newmedia
->colour
== NULL
)
663 return CDSC_ERROR
; /* no memory */
666 newmedia
->type
= dsc_alloc_string(dsc
, media
->type
,
667 strlen(media
->type
));
668 if (newmedia
->type
== NULL
)
669 return CDSC_ERROR
; /* no memory */
671 newmedia
->mediabox
= NULL
;
673 if (media
->mediabox
) {
674 newmedia
->mediabox
= (CDSCBBOX
*)dsc_memalloc(dsc
, sizeof(CDSCBBOX
));
675 if (newmedia
->mediabox
== NULL
)
676 return CDSC_ERROR
; /* no memory */
677 *newmedia
->mediabox
= *media
->mediabox
;
682 /* Doesn't need to be public for PostScript documents */
683 /* Made public so GSview can store PDF CropBox */
685 dsc_set_page_bbox(CDSC
*dsc
, unsigned int page_number
,
686 int llx
, int lly
, int urx
, int ury
)
689 if (page_number
>= dsc
->page_count
)
691 bbox
= dsc
->page
[page_number
].bbox
;
693 dsc
->page
[page_number
].bbox
= bbox
=
694 (CDSCBBOX
*)dsc_memalloc(dsc
, sizeof(CDSCBBOX
));
705 /******************************************************************/
706 /* Private functions below here. */
707 /******************************************************************/
710 dsc_memalloc(CDSC
*dsc
, size_t size
)
713 return dsc
->memalloc(size
, dsc
->mem_closure_data
);
718 dsc_memfree(CDSC
*dsc
, void *ptr
)
721 dsc
->memfree(ptr
, dsc
->mem_closure_data
);
726 /* private constructor */
732 dsc
->string_head
= (CDSCSTRING
*)dsc_memalloc(dsc
, sizeof(CDSCSTRING
));
733 if (dsc
->string_head
== NULL
) {
735 return NULL
; /* no memory */
737 dsc
->string
= dsc
->string_head
;
738 dsc
->string
->next
= NULL
;
739 dsc
->string
->data
= (char *)dsc_memalloc(dsc
, CDSC_STRING_CHUNK
);
740 if (dsc
->string
->data
== NULL
) {
742 return NULL
; /* no memory */
744 dsc
->string
->index
= 0;
745 dsc
->string
->length
= CDSC_STRING_CHUNK
;
747 dsc
->page
= (CDSCPAGE
*)dsc_memalloc(dsc
, CDSC_PAGE_CHUNK
* sizeof(CDSCPAGE
));
748 if (dsc
->page
== NULL
) {
750 return NULL
; /* no memory */
752 dsc
->page_chunk_length
= CDSC_PAGE_CHUNK
;
756 dsc
->data_length
= 0;
757 dsc
->data_index
= dsc
->data_length
;
767 /* Clear public members */
774 dsc
->preview
= CDSC_NOPREVIEW
;
775 dsc
->dsc_version
= NULL
; /* stored in dsc->string */
776 dsc
->language_level
= 0;
777 dsc
->document_data
= CDSC_DATA_UNKNOWN
;
778 dsc
->begincomments
= 0;
779 dsc
->endcomments
= 0;
780 dsc
->beginpreview
= 0;
782 dsc
->begindefaults
= 0;
783 dsc
->enddefaults
= 0;
784 dsc
->beginprolog
= 0;
788 dsc
->begintrailer
= 0;
791 for (i
=0; i
<dsc
->page_count
; i
++) {
792 /* page media is pointer to an element of media or dsc_known_media */
793 /* do not free it. */
795 if (dsc
->page
[i
].bbox
)
796 dsc_memfree(dsc
, dsc
->page
[i
].bbox
);
797 if (dsc
->page
[i
].viewing_orientation
)
798 dsc_memfree(dsc
, dsc
->page
[i
].viewing_orientation
);
801 dsc_memfree(dsc
, dsc
->page
);
806 dsc
->page_order
= CDSC_ORDER_UNKNOWN
;
807 dsc
->page_orientation
= CDSC_ORIENT_UNKNOWN
;
808 if (dsc
->viewing_orientation
)
809 dsc_memfree(dsc
, dsc
->viewing_orientation
);
810 dsc
->viewing_orientation
= NULL
;
813 for (i
=0; i
<dsc
->media_count
; i
++) {
815 if (dsc
->media
[i
]->mediabox
)
816 dsc_memfree(dsc
, dsc
->media
[i
]->mediabox
);
817 dsc_memfree(dsc
, dsc
->media
[i
]);
820 dsc_memfree(dsc
, dsc
->media
);
822 dsc
->media_count
= 0;
825 /* page_media is pointer to an element of media or dsc_known_media */
826 /* do not free it. */
827 dsc
->page_media
= NULL
;
830 dsc_memfree(dsc
, dsc
->bbox
);
833 dsc_memfree(dsc
, dsc
->page_bbox
);
834 dsc
->page_bbox
= NULL
;
836 dsc_memfree(dsc
, dsc
->doseps
);
839 dsc
->dsc_title
= NULL
;
840 dsc
->dsc_creator
= NULL
;
841 dsc
->dsc_date
= NULL
;
845 dsc
->max_error
= DSC_MAX_ERROR
;
846 dsc
->severity
= dsc_severity
;
848 /* Clear private members */
849 /* Don't touch dsc->caller_data */
851 dsc
->scan_section
= scan_none
;
853 dsc
->page_chunk_length
= 0;
854 dsc
->file_length
= 0;
855 dsc
->skip_document
= 0;
859 dsc
->begin_font_count
= 0;
860 dsc
->begin_feature_count
= 0;
861 dsc
->begin_resource_count
= 0;
862 dsc
->begin_procset_count
= 0;
864 dsc
->data_length
= 0;
866 dsc
->data_offset
= 0;
871 dsc
->line_length
= 0;
873 dsc
->last_cr
= FALSE
;
875 dsc
->long_line
= FALSE
;
876 memset(dsc
->last_line
, 0, sizeof(dsc
->last_line
));
878 dsc
->string
= dsc
->string_head
;
879 while (dsc
->string
!= (CDSCSTRING
*)NULL
) {
880 if (dsc
->string
->data
)
881 dsc_memfree(dsc
, dsc
->string
->data
);
882 dsc
->string_head
= dsc
->string
;
883 dsc
->string
= dsc
->string
->next
;
884 dsc_memfree(dsc
, dsc
->string_head
);
886 dsc
->string_head
= NULL
;
889 /* don't touch caller functions */
893 dsc_memfree(dsc
, dsc
->hires_bbox
);
894 dsc
->hires_bbox
= NULL
;
896 dsc_memfree(dsc
, dsc
->crop_box
);
897 dsc
->crop_box
= NULL
;
901 * Join up all sections.
902 * There might be extra code between them, or we might have
903 * missed including the \n which followed \r.
904 * begin is the start of this section
905 * pend is a pointer to the end of this section
906 * pplast is a pointer to a pointer of the end of the previous section
909 dsc_section_join(unsigned long begin
, unsigned long *pend
, unsigned long **pplast
)
918 /* return value is 0 if no line available, or length of line */
920 dsc_read_line(CDSC
*dsc
)
926 /* return all that remains, even if line incomplete */
927 dsc
->line
= dsc
->data
+ dsc
->data_index
;
928 dsc
->line_length
= dsc
->data_length
- dsc
->data_index
;
929 dsc
->data_index
= dsc
->data_length
;
930 return dsc
->line_length
;
933 /* ignore embedded bytes */
934 if (dsc
->skip_bytes
) {
935 int cnt
= min(dsc
->skip_bytes
,
936 (int)(dsc
->data_length
- dsc
->data_index
));
937 dsc
->skip_bytes
-= cnt
;
938 dsc
->data_index
+= cnt
;
939 if (dsc
->skip_bytes
!= 0)
944 dsc
->line
= dsc
->data
+ dsc
->data_index
;
945 last
= dsc
->data
+ dsc
->data_length
;
946 if (dsc
->data_index
== dsc
->data_length
) {
947 dsc
->line_length
= 0;
951 /* if previous line was complete, increment line count */
957 /* skip over \n which followed \r */
958 if (dsc
->last_cr
&& dsc
->line
[0] == '\n') {
962 dsc
->last_cr
= FALSE
;
966 for (p
= dsc
->line
; p
< last
; p
++) {
969 if ((p
<last
) && (*p
== '\n'))
970 p
++; /* include line feed also */
972 dsc
->last_cr
= TRUE
; /* we might need to skip \n */
973 dsc
->eol
= TRUE
; /* dsc->line is a complete line */
978 dsc
->eol
= TRUE
; /* dsc->line is a complete line */
981 if (*p
== '\032') { /* MS-DOS Ctrl+Z */
985 if (dsc
->eol
== FALSE
) {
986 /* we haven't got a complete line yet */
987 if (dsc
->data_length
- dsc
->data_index
< sizeof(dsc
->data
)/2) {
988 /* buffer is less than half full, ask for some more */
989 dsc
->line_length
= 0;
993 dsc
->data_index
+= dsc
->line_length
= (p
- dsc
->line
);
994 } while (dsc
->skip_lines
&& dsc
->line_length
);
996 if (dsc
->line_length
== 0)
999 if ((dsc
->line
[0]=='%') && (dsc
->line
[1]=='%')) {
1000 /* handle recursive %%BeginDocument */
1001 if ((dsc
->skip_document
) && dsc
->line_length
&&
1002 COMPARE(dsc
->line
, "%%EndDocument")) {
1003 dsc
->skip_document
--;
1006 /* handle embedded lines or binary data */
1007 if (COMPARE(dsc
->line
, "%%BeginData:")) {
1008 /* %%BeginData: <numberof>[ <type> [ <bytesorlines> ] ]
1009 * <numberof> ::= <uint> (Lines or physical bytes)
1010 * <type> ::= Hex | Binary | ASCII (Type of data)
1011 * <bytesorlines> ::= Bytes | Lines (Read in bytes or lines)
1013 char begindata
[MAXSTR
+1];
1016 const char *numberof
, *bytesorlines
;
1017 if ((num
= dsc
->line_length
) >= sizeof(begindata
)-1)
1018 num
= sizeof(begindata
)-1;
1020 memcpy(begindata
, dsc
->line
, num
);
1021 begindata
[num
] = '\0';
1022 numberof
= strtok(begindata
+12, " \r\n");
1023 strtok(NULL
, " \r\n"); /* dump type */
1024 bytesorlines
= strtok(NULL
, " \r\n");
1025 if (bytesorlines
== NULL
)
1026 bytesorlines
= "Bytes";
1028 if ( (numberof
== NULL
) || (bytesorlines
== NULL
) ) {
1029 /* invalid usage of %%BeginData */
1030 /* ignore that we ever saw it */
1031 int rc
= dsc_error(dsc
, CDSC_MESSAGE_INCORRECT_USAGE
,
1032 dsc
->line
, dsc
->line_length
);
1034 case CDSC_RESPONSE_OK
:
1035 case CDSC_RESPONSE_CANCEL
:
1037 case CDSC_RESPONSE_IGNORE_ALL
:
1042 cnt
= atoi(numberof
);
1044 if (bytesorlines
&& (dsc_stricmp(bytesorlines
, "Lines")==0)) {
1045 /* skip cnt lines */
1046 if (dsc
->skip_lines
== 0) {
1047 /* we are not already skipping lines */
1048 dsc
->skip_lines
= cnt
+1;
1052 /* byte count doesn't includes \n or \r\n */
1053 /* or \r of %%BeginData: */
1054 /* skip cnt bytes */
1055 if (dsc
->skip_bytes
== 0) {
1056 /* we are not already skipping lines */
1057 dsc
->skip_bytes
= cnt
;
1064 else if (COMPARE(dsc
->line
, "%%BeginBinary:")) {
1065 /* byte count doesn't includes \n or \r\n or \r of %%BeginBinary:*/
1066 unsigned long cnt
= atoi(dsc
->line
+ 14);
1067 if (dsc
->skip_bytes
== 0) {
1068 /* we are not already skipping lines */
1069 dsc
->skip_bytes
= cnt
;
1074 if ((dsc
->line
[0]=='%') && (dsc
->line
[1]=='%') &&
1075 COMPARE(dsc
->line
, "%%BeginDocument:") ) {
1076 /* Skip over embedded document, recursively */
1077 dsc
->skip_document
++;
1080 if (!dsc
->long_line
&& (dsc
->line_length
> DSC_LINE_LENGTH
)) {
1081 dsc_error(dsc
, CDSC_MESSAGE_LONG_LINE
, dsc
->line
, dsc
->line_length
);
1082 dsc
->long_line
= TRUE
;
1085 return dsc
->line_length
;
1089 /* Save last DSC line, for use with %%+ */
1091 dsc_save_line(CDSC
*dsc
)
1093 int len
= min(sizeof(dsc
->last_line
), dsc
->line_length
);
1094 memcpy(dsc
->last_line
, dsc
->line
, len
);
1097 /* display unknown DSC line */
1099 dsc_unknown(CDSC
*dsc
)
1101 if (dsc
->debug_print_fn
) {
1102 char line
[DSC_LINE_LENGTH
];
1103 unsigned int length
= min(DSC_LINE_LENGTH
-1, dsc
->line_length
);
1104 sprintf(line
, "Unknown in %s section at line %d:\n ",
1105 dsc_scan_section_name
[dsc
->scan_section
], dsc
->line_count
);
1106 dsc_debug_print(dsc
, line
);
1107 strncpy(line
, dsc
->line
, length
);
1108 line
[length
] = '\0';
1109 dsc_debug_print(dsc
, line
);
1115 dsc_is_section(char *line
)
1117 if ( !((line
[0]=='%') && (line
[1]=='%')) )
1119 if (IS_DSC(line
, "%%BeginPreview"))
1121 if (IS_DSC(line
, "%%BeginDefaults"))
1123 if (IS_DSC(line
, "%%BeginProlog"))
1125 if (IS_DSC(line
, "%%BeginSetup"))
1127 if (IS_DSC(line
, "%%Page:"))
1129 if (IS_DSC(line
, "%%Trailer"))
1131 if (IS_DSC(line
, "%%EOF"))
1138 dsc_get_dword(const unsigned char *buf
)
1141 dw
= (GSDWORD
)buf
[0];
1142 dw
+= ((GSDWORD
)buf
[1])<<8;
1143 dw
+= ((GSDWORD
)buf
[2])<<16;
1144 dw
+= ((GSDWORD
)buf
[3])<<24;
1149 dsc_get_word(const unsigned char *buf
)
1153 w
|= (GSWORD
)(buf
[1]<<8);
1158 dsc_read_doseps(CDSC
*dsc
)
1160 unsigned char *line
= (unsigned char *)dsc
->line
;
1161 if ((dsc
->doseps
= (CDSCDOSEPS
*)dsc_memalloc(dsc
, sizeof(CDSCDOSEPS
))) == NULL
)
1162 return CDSC_ERROR
; /* no memory */
1164 dsc
->doseps
->ps_begin
= dsc_get_dword(line
+4);
1165 dsc
->doseps
->ps_length
= dsc_get_dword(line
+8);
1166 dsc
->doseps
->wmf_begin
= dsc_get_dword(line
+12);
1167 dsc
->doseps
->wmf_length
= dsc_get_dword(line
+16);
1168 dsc
->doseps
->tiff_begin
= dsc_get_dword(line
+20);
1169 dsc
->doseps
->tiff_length
= dsc_get_dword(line
+24);
1170 dsc
->doseps
->checksum
= dsc_get_word(line
+28);
1172 dsc
->doseps_end
= dsc
->doseps
->ps_begin
+ dsc
->doseps
->ps_length
;
1174 /* move data_index backwards to byte after doseps header */
1175 dsc
->data_index
-= dsc
->line_length
- 30;
1176 /* we haven't read a line of PostScript code yet */
1177 dsc
->line_count
= 0;
1178 /* skip from current position to start of PostScript section */
1179 dsc
->skip_bytes
= dsc
->doseps
->ps_begin
- 30;
1181 if (dsc
->doseps
->tiff_begin
)
1182 dsc
->preview
= CDSC_TIFF
;
1183 if (dsc
->doseps
->wmf_begin
)
1184 dsc
->preview
= CDSC_WMF
;
1192 dsc_parse_pages(CDSC
*dsc
)
1198 if ((dsc
->page_pages
!= 0) && (dsc
->scan_section
== scan_comments
)) {
1199 int rc
= dsc_error(dsc
, CDSC_MESSAGE_DUP_COMMENT
, dsc
->line
,
1202 case CDSC_RESPONSE_OK
:
1203 case CDSC_RESPONSE_CANCEL
:
1204 return CDSC_OK
; /* ignore duplicate comments in header */
1205 case CDSC_RESPONSE_IGNORE_ALL
:
1209 if ((dsc
->page_pages
!= 0) && (dsc
->scan_section
== scan_trailer
)) {
1210 int rc
= dsc_error(dsc
, CDSC_MESSAGE_DUP_TRAILER
, dsc
->line
,
1213 case CDSC_RESPONSE_OK
:
1214 case CDSC_RESPONSE_CANCEL
:
1215 break; /* use duplicate comments in header */
1216 case CDSC_RESPONSE_IGNORE_ALL
:
1221 n
= IS_DSC(dsc
->line
, "%%+") ? 3 : 8;
1222 while (IS_WHITE(dsc
->line
[n
]))
1225 if (COMPARE(p
, "atend")) {
1226 int rc
= dsc_error(dsc
, CDSC_MESSAGE_ATEND
, dsc
->line
, dsc
->line_length
);
1228 case CDSC_RESPONSE_OK
:
1229 /* assume (atend) */
1230 /* we should mark it as deferred */
1232 case CDSC_RESPONSE_CANCEL
:
1235 case CDSC_RESPONSE_IGNORE_ALL
:
1239 else if (COMPARE(p
, "(atend)")) {
1241 /* we should mark it as deferred */
1244 ip
= dsc_get_int(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1247 dsc
->page_pages
= ip
;
1248 io
= dsc_get_int(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1250 /* DSC 2 uses extra integer to indicate page order */
1251 /* DSC 3 uses %%PageOrder: */
1252 if (dsc
->page_order
== CDSC_ORDER_UNKNOWN
)
1255 dsc
->page_order
= CDSC_DESCEND
;
1258 dsc
->page_order
= CDSC_SPECIAL
;
1261 dsc
->page_order
= CDSC_ASCEND
;
1267 int rc
= dsc_error(dsc
, CDSC_MESSAGE_INCORRECT_USAGE
, dsc
->line
,
1270 case CDSC_RESPONSE_OK
:
1271 case CDSC_RESPONSE_CANCEL
:
1274 case CDSC_RESPONSE_IGNORE_ALL
:
1283 dsc_parse_bounding_box(CDSC
*dsc
, CDSCBBOX
** pbbox
, int offset
)
1286 int llx
, lly
, urx
, ury
;
1287 float fllx
, flly
, furx
, fury
;
1289 /* Process first %%BoundingBox: in comments, and last in trailer */
1290 if ((*pbbox
!= NULL
) && (dsc
->scan_section
== scan_comments
)) {
1291 int rc
= dsc_error(dsc
, CDSC_MESSAGE_DUP_COMMENT
, dsc
->line
,
1294 case CDSC_RESPONSE_OK
:
1295 case CDSC_RESPONSE_CANCEL
:
1296 return CDSC_OK
; /* ignore duplicate comments in header */
1297 case CDSC_RESPONSE_IGNORE_ALL
:
1301 if ((*pbbox
!= NULL
) && (dsc
->scan_section
== scan_pages
)) {
1302 int rc
= dsc_error(dsc
, CDSC_MESSAGE_DUP_COMMENT
, dsc
->line
,
1305 case CDSC_RESPONSE_OK
:
1306 case CDSC_RESPONSE_CANCEL
:
1307 return CDSC_OK
; /* ignore duplicate comments in header */
1308 case CDSC_RESPONSE_IGNORE_ALL
:
1312 if ((*pbbox
!= NULL
) && (dsc
->scan_section
== scan_trailer
)) {
1313 int rc
= dsc_error(dsc
, CDSC_MESSAGE_DUP_TRAILER
, dsc
->line
,
1316 case CDSC_RESPONSE_OK
:
1317 case CDSC_RESPONSE_CANCEL
:
1318 break; /* use duplicate comments in trailer */
1319 case CDSC_RESPONSE_IGNORE_ALL
:
1323 if (*pbbox
!= NULL
) {
1324 dsc_memfree(dsc
, *pbbox
);
1328 /* should only process first %%BoundingBox: */
1330 while (IS_WHITE(dsc
->line
[offset
]))
1332 p
= dsc
->line
+ offset
;
1334 if (COMPARE(p
, "atend")) {
1335 int rc
= dsc_error(dsc
, CDSC_MESSAGE_ATEND
, dsc
->line
,
1338 case CDSC_RESPONSE_OK
:
1339 /* assume (atend) */
1340 /* we should mark it as deferred */
1342 case CDSC_RESPONSE_CANCEL
:
1345 case CDSC_RESPONSE_IGNORE_ALL
:
1349 else if (COMPARE(p
, "(atend)")) {
1351 /* we should mark it as deferred */
1354 /* llx = */ lly
= urx
= ury
= 0;
1356 llx
= dsc_get_int(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1359 lly
= dsc_get_int(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1362 urx
= dsc_get_int(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1365 ury
= dsc_get_int(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1367 *pbbox
= (CDSCBBOX
*)dsc_memalloc(dsc
, sizeof(CDSCBBOX
));
1369 return CDSC_ERROR
; /* no memory */
1370 (*pbbox
)->llx
= llx
;
1371 (*pbbox
)->lly
= lly
;
1372 (*pbbox
)->urx
= urx
;
1373 (*pbbox
)->ury
= ury
;
1376 int rc
= dsc_error(dsc
, CDSC_MESSAGE_BBOX
, dsc
->line
,
1379 case CDSC_RESPONSE_OK
:
1380 /* fllx = */ flly
= furx
= fury
= 0.0;
1383 fllx
= dsc_get_real(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1386 flly
= dsc_get_real(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1389 furx
= dsc_get_real(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1392 fury
= dsc_get_real(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1394 *pbbox
= (CDSCBBOX
*)dsc_memalloc(dsc
, sizeof(CDSCBBOX
));
1396 return CDSC_ERROR
; /* no memory */
1397 (*pbbox
)->llx
= (int)fllx
;
1398 (*pbbox
)->lly
= (int)flly
;
1399 (*pbbox
)->urx
= (int)(furx
+0.999);
1400 (*pbbox
)->ury
= (int)(fury
+0.999);
1403 case CDSC_RESPONSE_CANCEL
:
1405 case CDSC_RESPONSE_IGNORE_ALL
:
1414 dsc_parse_float_bounding_box(CDSC
*dsc
, CDSCFBBOX
** pbbox
, int offset
)
1417 float fllx
, flly
, furx
, fury
;
1419 /* Process first %%HiResBoundingBox: or %%CropBox: in comments,
1420 * and last in trailer.
1422 if ((*pbbox
!= NULL
) && (dsc
->scan_section
== scan_comments
)) {
1423 int rc
= dsc_error(dsc
, CDSC_MESSAGE_DUP_COMMENT
, dsc
->line
,
1426 case CDSC_RESPONSE_OK
:
1427 case CDSC_RESPONSE_CANCEL
:
1428 return CDSC_OK
; /* ignore duplicate comments in header */
1429 case CDSC_RESPONSE_IGNORE_ALL
:
1433 if ((*pbbox
!= NULL
) && (dsc
->scan_section
== scan_pages
)) {
1434 int rc
= dsc_error(dsc
, CDSC_MESSAGE_DUP_COMMENT
, dsc
->line
,
1437 case CDSC_RESPONSE_OK
:
1438 case CDSC_RESPONSE_CANCEL
:
1439 return CDSC_OK
; /* ignore duplicate comments in header */
1440 case CDSC_RESPONSE_IGNORE_ALL
:
1444 if ((*pbbox
!= NULL
) && (dsc
->scan_section
== scan_trailer
)) {
1445 int rc
= dsc_error(dsc
, CDSC_MESSAGE_DUP_TRAILER
, dsc
->line
,
1448 case CDSC_RESPONSE_OK
:
1449 case CDSC_RESPONSE_CANCEL
:
1450 break; /* use duplicate comments in trailer */
1451 case CDSC_RESPONSE_IGNORE_ALL
:
1455 if (*pbbox
!= NULL
) {
1456 dsc_memfree(dsc
, *pbbox
);
1460 /* should only process first %%BoundingBox: */
1462 while (IS_WHITE(dsc
->line
[offset
]))
1464 p
= dsc
->line
+ offset
;
1466 if (COMPARE(p
, "atend")) {
1467 int rc
= dsc_error(dsc
, CDSC_MESSAGE_ATEND
, dsc
->line
,
1470 case CDSC_RESPONSE_OK
:
1471 /* assume (atend) */
1472 /* we should mark it as deferred */
1474 case CDSC_RESPONSE_CANCEL
:
1477 case CDSC_RESPONSE_IGNORE_ALL
:
1481 else if (COMPARE(p
, "(atend)")) {
1483 /* we should mark it as deferred */
1486 /* fllx = */ flly
= furx
= fury
= 0.0;
1488 fllx
= dsc_get_real(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1491 flly
= dsc_get_real(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1494 furx
= dsc_get_real(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1497 fury
= dsc_get_real(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1499 *pbbox
= (CDSCFBBOX
*)dsc_memalloc(dsc
, sizeof(CDSCFBBOX
));
1501 return CDSC_ERROR
; /* no memory */
1502 (*pbbox
)->fllx
= fllx
;
1503 (*pbbox
)->flly
= flly
;
1504 (*pbbox
)->furx
= furx
;
1505 (*pbbox
)->fury
= fury
;
1512 dsc_parse_orientation(CDSC
*dsc
, unsigned int *porientation
, int offset
)
1515 if ((dsc
->page_orientation
!= CDSC_ORIENT_UNKNOWN
) &&
1516 (dsc
->scan_section
== scan_comments
)) {
1517 int rc
= dsc_error(dsc
, CDSC_MESSAGE_DUP_COMMENT
, dsc
->line
,
1520 case CDSC_RESPONSE_OK
:
1521 case CDSC_RESPONSE_CANCEL
:
1522 return CDSC_OK
; /* ignore duplicate comments in header */
1523 case CDSC_RESPONSE_IGNORE_ALL
:
1527 if ((dsc
->page_orientation
!= CDSC_ORIENT_UNKNOWN
) &&
1528 (dsc
->scan_section
== scan_trailer
)) {
1529 int rc
= dsc_error(dsc
, CDSC_MESSAGE_DUP_TRAILER
, dsc
->line
,
1532 case CDSC_RESPONSE_OK
:
1533 case CDSC_RESPONSE_CANCEL
:
1534 break; /* use duplicate comments in header; */
1535 case CDSC_RESPONSE_IGNORE_ALL
:
1539 p
= dsc
->line
+ offset
;
1540 while (IS_WHITE(*p
))
1542 if (COMPARE(p
, "atend")) {
1543 int rc
= dsc_error(dsc
, CDSC_MESSAGE_ATEND
, dsc
->line
, dsc
->line_length
);
1545 case CDSC_RESPONSE_OK
:
1546 /* assume (atend) */
1547 /* we should mark it as deferred */
1549 case CDSC_RESPONSE_CANCEL
:
1552 case CDSC_RESPONSE_IGNORE_ALL
:
1556 else if (COMPARE(p
, "(atend)")) {
1558 /* we should mark it as deferred */
1560 else if (COMPARE(p
, "Portrait")) {
1561 *porientation
= CDSC_PORTRAIT
;
1563 else if (COMPARE(p
, "Landscape")) {
1564 *porientation
= CDSC_LANDSCAPE
;
1573 dsc_parse_order(CDSC
*dsc
)
1576 if ((dsc
->page_order
!= CDSC_ORDER_UNKNOWN
) &&
1577 (dsc
->scan_section
== scan_comments
)) {
1578 int rc
= dsc_error(dsc
, CDSC_MESSAGE_DUP_COMMENT
, dsc
->line
,
1581 case CDSC_RESPONSE_OK
:
1582 case CDSC_RESPONSE_CANCEL
:
1583 return CDSC_OK
; /* ignore duplicate comments in header */
1584 case CDSC_RESPONSE_IGNORE_ALL
:
1588 if ((dsc
->page_order
!= CDSC_ORDER_UNKNOWN
) &&
1589 (dsc
->scan_section
== scan_trailer
)) {
1590 int rc
= dsc_error(dsc
, CDSC_MESSAGE_DUP_TRAILER
, dsc
->line
,
1593 case CDSC_RESPONSE_OK
:
1594 case CDSC_RESPONSE_CANCEL
:
1595 break; /* use duplicate comments in trailer */
1596 case CDSC_RESPONSE_IGNORE_ALL
:
1601 p
= dsc
->line
+ (IS_DSC(dsc
->line
, "%%+") ? 3 : 13);
1602 while (IS_WHITE(*p
))
1604 if (COMPARE(p
, "atend")) {
1605 int rc
= dsc_error(dsc
, CDSC_MESSAGE_ATEND
, dsc
->line
,
1608 case CDSC_RESPONSE_OK
:
1609 /* assume (atend) */
1610 /* we should mark it as deferred */
1612 case CDSC_RESPONSE_CANCEL
:
1615 case CDSC_RESPONSE_IGNORE_ALL
:
1619 else if (COMPARE(p
, "(atend)")) {
1621 /* we should mark it as deferred */
1623 else if (COMPARE(p
, "Ascend")) {
1624 dsc
->page_order
= CDSC_ASCEND
;
1626 else if (COMPARE(p
, "Descend")) {
1627 dsc
->page_order
= CDSC_DESCEND
;
1629 else if (COMPARE(p
, "Special")) {
1630 dsc
->page_order
= CDSC_SPECIAL
;
1640 dsc_parse_media(CDSC
*dsc
, const CDSCMEDIA
**page_media
)
1642 char media_name
[MAXSTR
];
1643 int n
= IS_DSC(dsc
->line
, "%%+") ? 3 : 12; /* %%PageMedia: */
1646 if (dsc_copy_string(media_name
, sizeof(media_name
)-1,
1647 dsc
->line
+n
, dsc
->line_length
-n
, NULL
)) {
1648 for (i
=0; i
<dsc
->media_count
; i
++) {
1649 if (dsc
->media
[i
]->name
&&
1650 (dsc_stricmp(media_name
, dsc
->media
[i
]->name
) == 0)) {
1651 *page_media
= dsc
->media
[i
];
1663 dsc_parse_document_media(CDSC
*dsc
)
1669 if (IS_DSC(dsc
->line
, "%%DocumentMedia:"))
1671 else if (IS_DSC(dsc
->line
, "%%+"))
1674 return CDSC_ERROR
; /* error */
1676 /* check for blank remainder of line */
1678 for (i
=n
; i
<dsc
->line_length
; i
++) {
1679 if (!IS_WHITE_OR_EOL(dsc
->line
[i
])) {
1687 char colour
[MAXSTR
];
1689 lmedia
.name
= lmedia
.colour
= lmedia
.type
= (char *)NULL
;
1690 lmedia
.width
= lmedia
.height
= lmedia
.weight
= 0;
1691 lmedia
.mediabox
= (CDSCBBOX
*)NULL
;
1692 lmedia
.name
= dsc_copy_string(name
, sizeof(name
)-1,
1693 dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1696 lmedia
.width
= dsc_get_real(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1699 lmedia
.height
= dsc_get_real(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1702 lmedia
.weight
= dsc_get_real(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1705 lmedia
.colour
= dsc_copy_string(colour
, sizeof(colour
)-1,
1706 dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1709 lmedia
.type
= dsc_copy_string(type
, sizeof(type
)-1,
1710 dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1713 dsc_unknown(dsc
); /* we didn't get all fields */
1715 if (dsc_add_media(dsc
, &lmedia
))
1716 return CDSC_ERROR
; /* out of memory */
1722 /* viewing orientation is believed to be the first four elements of
1726 dsc_parse_viewing_orientation(CDSC
*dsc
, CDSCCTM
**pctm
)
1731 if (*pctm
!= NULL
) {
1732 dsc_memfree(dsc
, *pctm
);
1736 n
= IS_DSC(dsc
->line
, "%%+") ? 3 : 21; /* %%ViewingOrientation: */
1737 while (IS_WHITE(dsc
->line
[n
]))
1740 /* ctm.xx = */ ctm
.xy
= ctm
.yx
= ctm
.yy
= 0.0;
1741 ctm
.xx
= dsc_get_real(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1744 ctm
.xy
= dsc_get_real(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1747 ctm
.yx
= dsc_get_real(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1750 ctm
.yy
= dsc_get_real(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
1752 dsc_unknown(dsc
); /* we didn't get all fields */
1755 *pctm
= (CDSCCTM
*)dsc_memalloc(dsc
, sizeof(CDSCCTM
));
1757 return CDSC_ERROR
; /* no memory */
1764 /* This is called before dsc_read_line(), since we may
1765 * need to skip a binary header which contains a new line
1769 dsc_scan_type(CDSC
*dsc
)
1772 unsigned char *line
= (unsigned char *)(dsc
->data
+ dsc
->data_index
);
1773 int length
= dsc
->data_length
- dsc
->data_index
;
1775 /* Types that should be known:
1778 * PJL + any of above
1785 /* First process any non PostScript headers */
1786 /* At this stage we do not have a complete line */
1789 return CDSC_NEEDMORE
;
1791 if (dsc
->skip_pjl
) {
1792 /* skip until first PostScript comment */
1793 while (length
>= 2) {
1794 while (length
&& !IS_EOL(line
[0])) {
1795 /* skip until EOL character */
1800 while ((length
>= 2) && IS_EOL(line
[0]) && IS_EOL(line
[1])) {
1801 /* skip until EOL followed by non-EOL */
1807 return CDSC_NEEDMORE
;
1809 if (IS_EOL(line
[0]) && line
[1]=='%') {
1813 dsc
->skip_pjl
= FALSE
;
1820 return CDSC_NEEDMORE
;
1824 return CDSC_NEEDMORE
;
1828 return CDSC_NEEDMORE
;
1830 if (line
[0] == '\004') {
1837 if (line
[0] == '\033') {
1840 return CDSC_NEEDMORE
;
1841 if (COMPARE(line
, "\033%-12345X")) {
1842 dsc
->skip_pjl
= TRUE
; /* skip until first PostScript comment */
1844 dsc
->data_index
+= 9;
1845 return dsc_scan_type(dsc
);
1849 if ((line
[0]==0xc5) && (length
< 4))
1850 return CDSC_NEEDMORE
;
1851 if ((line
[0]==0xc5) && (line
[1]==0xd0) &&
1852 (line
[2]==0xd3) && (line
[3]==0xc6) ) {
1853 /* id is "EPSF" with bit 7 set */
1854 /* read DOS EPS header, then ignore all bytes until the PS section */
1856 return CDSC_NEEDMORE
;
1857 dsc
->line
= (char *)line
;
1858 if (dsc_read_doseps(dsc
))
1863 return CDSC_NEEDMORE
;
1864 if ((line
[0] == '%') && (line
[1] == 'P')) {
1866 return CDSC_NEEDMORE
;
1867 if (COMPARE(line
, "%PDF-")) {
1869 dsc
->scan_section
= scan_comments
;
1875 /* Finally process PostScript headers */
1877 if (dsc_read_line(dsc
) <= 0)
1878 return CDSC_NEEDMORE
;
1880 dsc
->dsc_version
= dsc_add_line(dsc
, dsc
->line
, dsc
->line_length
);
1881 if (COMPARE(dsc
->line
, "%!PS-Adobe")) {
1883 dsc
->begincomments
= DSC_START(dsc
);
1884 if (dsc
->dsc_version
== NULL
)
1885 return CDSC_ERROR
; /* no memory */
1886 p
= (unsigned char *)dsc
->line
+ 14;
1887 while (IS_WHITE(*p
))
1889 if (COMPARE(p
, "EPSF-"))
1891 dsc
->scan_section
= scan_comments
;
1892 return CDSC_PSADOBE
;
1894 if (COMPARE(dsc
->line
, "%!")) {
1895 dsc
->scan_section
= scan_comments
;
1899 dsc
->scan_section
= scan_comments
;
1900 return CDSC_NOTDSC
; /* unrecognised */
1906 dsc_scan_comments(CDSC
*dsc
)
1908 /* Comments section ends at */
1910 /* another section */
1911 /* line that does not start with %% */
1912 /* Save a few important lines */
1914 char *line
= dsc
->line
;
1915 GSBOOL continued
= FALSE
;
1917 if (IS_DSC(line
, "%%EndComments")) {
1918 dsc
->id
= CDSC_ENDCOMMENTS
;
1919 dsc
->endcomments
= DSC_END(dsc
);
1920 dsc
->scan_section
= scan_pre_preview
;
1923 else if (IS_DSC(line
, "%%BeginComments")) {
1924 /* ignore because we are in this section */
1925 dsc
->id
= CDSC_BEGINCOMMENTS
;
1927 else if (dsc_is_section(line
)) {
1928 dsc
->endcomments
= DSC_START(dsc
);
1929 dsc
->scan_section
= scan_pre_preview
;
1930 return CDSC_PROPAGATE
;
1932 else if (line
[0] == '%' && IS_WHITE_OR_EOL(line
[1])) {
1933 dsc
->endcomments
= DSC_START(dsc
);
1934 dsc
->scan_section
= scan_pre_preview
;
1935 return CDSC_PROPAGATE
;
1937 else if (line
[0] != '%') {
1939 dsc
->endcomments
= DSC_START(dsc
);
1940 dsc
->scan_section
= scan_pre_preview
;
1941 return CDSC_PROPAGATE
;
1943 else if (IS_DSC(line
, "%%Begin")) {
1944 dsc
->endcomments
= DSC_START(dsc
);
1945 dsc
->scan_section
= scan_pre_preview
;
1946 return CDSC_PROPAGATE
;
1949 /* Handle continuation lines.
1950 * To simply processing, we assume that contination lines
1951 * will only occur if repeat parameters are allowed and that
1952 * a complete set of these parameters appears on each line.
1953 * This is more restrictive than the DSC specification, but
1954 * is valid for the DSC comments understood by this parser
1955 * for all documents that we have seen.
1957 if (IS_DSC(line
, "%%+")) {
1958 line
= dsc
->last_line
;
1964 if (IS_DSC(line
, "%%Pages:")) {
1965 dsc
->id
= CDSC_PAGES
;
1966 if (dsc_parse_pages(dsc
) != 0)
1969 else if (IS_DSC(line
, "%%Creator:")) {
1970 dsc
->id
= CDSC_CREATOR
;
1971 dsc
->dsc_creator
= dsc_add_line(dsc
, dsc
->line
+10, dsc
->line_length
-10);
1972 if (dsc
->dsc_creator
==NULL
)
1975 else if (IS_DSC(line
, "%%CreationDate:")) {
1976 dsc
->id
= CDSC_CREATIONDATE
;
1977 dsc
->dsc_date
= dsc_add_line(dsc
, dsc
->line
+15, dsc
->line_length
-15);
1978 if (dsc
->dsc_date
==NULL
)
1981 else if (IS_DSC(line
, "%%Title:")) {
1982 dsc
->id
= CDSC_TITLE
;
1983 dsc
->dsc_title
= dsc_add_line(dsc
, dsc
->line
+8, dsc
->line_length
-8);
1984 if (dsc
->dsc_title
==NULL
)
1987 else if (IS_DSC(line
, "%%For:")) {
1989 dsc
->dsc_for
= dsc_add_line(dsc
, dsc
->line
+6, dsc
->line_length
-6);
1990 if (dsc
->dsc_for
==NULL
)
1993 else if (IS_DSC(line
, "%%LanguageLevel:")) {
1994 unsigned int n
= continued
? 3 : 16;
1997 dsc
->id
= CDSC_LANGUAGELEVEL
;
1998 ll
= dsc_get_int(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
2000 if ( (ll
==1) || (ll
==2) || (ll
==3) )
2001 dsc
->language_level
= ll
;
2009 else if (IS_DSC(line
, "%%BoundingBox:")) {
2010 dsc
->id
= CDSC_BOUNDINGBOX
;
2011 if (dsc_parse_bounding_box(dsc
, &(dsc
->bbox
), continued
? 3 : 14))
2014 else if (IS_DSC(line
, "%%HiResBoundingBox:")) {
2015 dsc
->id
= CDSC_HIRESBOUNDINGBOX
;
2016 if (dsc_parse_float_bounding_box(dsc
, &(dsc
->hires_bbox
),
2017 continued
? 3 : 19))
2020 else if (IS_DSC(line
, "%%CropBox:")) {
2021 dsc
->id
= CDSC_CROPBOX
;
2022 if (dsc_parse_float_bounding_box(dsc
, &(dsc
->crop_box
),
2023 continued
? 3 : 10))
2026 else if (IS_DSC(line
, "%%Orientation:")) {
2027 dsc
->id
= CDSC_ORIENTATION
;
2028 if (dsc_parse_orientation(dsc
, &(dsc
->page_orientation
),
2029 continued
? 3 : 14))
2032 else if (IS_DSC(line
, "%%PageOrder:")) {
2033 dsc
->id
= CDSC_PAGEORDER
;
2034 if (dsc_parse_order(dsc
))
2037 else if (IS_DSC(line
, "%%DocumentMedia:")) {
2038 dsc
->id
= CDSC_DOCUMENTMEDIA
;
2039 if (dsc_parse_document_media(dsc
))
2042 else if (IS_DSC(line
, "%%DocumentPaperSizes:")) {
2044 unsigned int n
= continued
? 3 : 21;
2045 unsigned int count
= 0;
2049 dsc
->id
= CDSC_DOCUMENTPAPERSIZES
;
2050 while (i
&& (dsc
->line
[n
]!='\r') && (dsc
->line
[n
]!='\n')) {
2051 p
= dsc_copy_string(name
, sizeof(name
)-1,
2052 dsc
->line
+n
, dsc
->line_length
-n
, &i
);
2054 const CDSCMEDIA
*m
= dsc_known_media
;
2055 if (count
>= dsc
->media_count
) {
2056 /* set some default values */
2059 lmedia
.width
= 595.0;
2060 lmedia
.height
= 842.0;
2061 lmedia
.weight
= 80.0;
2062 lmedia
.colour
= NULL
;
2064 lmedia
.mediabox
= NULL
;
2065 if (dsc_add_media(dsc
, &lmedia
))
2069 dsc
->media
[count
]->name
=
2070 dsc_alloc_string(dsc
, p
, strlen(p
));
2071 /* find in list of known media */
2072 while (m
&& m
->name
) {
2073 if (dsc_stricmp(p
, m
->name
)==0) {
2074 dsc
->media
[count
]->width
= m
->width
;
2075 dsc
->media
[count
]->height
= m
->height
;
2085 else if (IS_DSC(line
, "%%DocumentPaperForms:")) {
2087 unsigned int n
= continued
? 3 : 21;
2088 unsigned int count
= 0;
2092 dsc
->id
= CDSC_DOCUMENTPAPERFORMS
;
2093 while (i
&& (dsc
->line
[n
]!='\r') && (dsc
->line
[n
]!='\n')) {
2094 p
= dsc_copy_string(type
, sizeof(type
)-1,
2095 dsc
->line
+n
, dsc
->line_length
-n
, &i
);
2097 if (count
>= dsc
->media_count
) {
2098 /* set some default values */
2101 lmedia
.width
= 595.0;
2102 lmedia
.height
= 842.0;
2103 lmedia
.weight
= 80.0;
2104 lmedia
.colour
= NULL
;
2106 lmedia
.mediabox
= NULL
;
2107 if (dsc_add_media(dsc
, &lmedia
))
2111 dsc
->media
[count
]->type
=
2112 dsc_alloc_string(dsc
, p
, strlen(p
));
2118 else if (IS_DSC(line
, "%%DocumentPaperColors:")) {
2120 unsigned int n
= continued
? 3 : 22;
2121 unsigned int count
= 0;
2123 char colour
[MAXSTR
];
2125 dsc
->id
= CDSC_DOCUMENTPAPERCOLORS
;
2126 while (i
&& (dsc
->line
[n
]!='\r') && (dsc
->line
[n
]!='\n')) {
2127 p
= dsc_copy_string(colour
, sizeof(colour
)-1,
2128 dsc
->line
+n
, dsc
->line_length
-n
, &i
);
2130 if (count
>= dsc
->media_count
) {
2131 /* set some default values */
2134 lmedia
.width
= 595.0;
2135 lmedia
.height
= 842.0;
2136 lmedia
.weight
= 80.0;
2139 lmedia
.mediabox
= NULL
;
2140 if (dsc_add_media(dsc
, &lmedia
))
2144 dsc
->media
[count
]->colour
=
2145 dsc_alloc_string(dsc
, p
, strlen(p
));
2151 else if (IS_DSC(line
, "%%DocumentPaperWeights:")) {
2153 unsigned int n
= continued
? 3 : 23;
2154 unsigned int count
= 0;
2157 dsc
->id
= CDSC_DOCUMENTPAPERWEIGHTS
;
2158 while (i
&& (dsc
->line
[n
]!='\r') && (dsc
->line
[n
]!='\n')) {
2159 w
= dsc_get_real(dsc
->line
+n
, dsc
->line_length
-n
, &i
);
2161 if (count
>= dsc
->media_count
) {
2162 /* set some default values */
2165 lmedia
.width
= 595.0;
2166 lmedia
.height
= 842.0;
2168 lmedia
.colour
= NULL
;
2170 lmedia
.mediabox
= NULL
;
2171 if (dsc_add_media(dsc
, &lmedia
))
2175 dsc
->media
[count
]->weight
= w
;
2181 else if (IS_DSC(line
, "%%DocumentData:")) {
2182 unsigned int n
= continued
? 3 : 15;
2183 char *p
= dsc
->line
+ n
;
2184 while (IS_WHITE(*p
))
2186 dsc
->id
= CDSC_DOCUMENTDATA
;
2187 if (COMPARE(p
, "Clean7Bit"))
2188 dsc
->document_data
= CDSC_CLEAN7BIT
;
2189 else if (COMPARE(p
, "Clean8Bit"))
2190 dsc
->document_data
= CDSC_CLEAN8BIT
;
2191 else if (COMPARE(p
, "Binary"))
2192 dsc
->document_data
= CDSC_BINARY
;
2196 else if (IS_DSC(line
, "%%Requirements:")) {
2197 dsc
->id
= CDSC_REQUIREMENTS
;
2200 else if (IS_DSC(line
, "%%DocumentNeededFonts:")) {
2201 dsc
->id
= CDSC_DOCUMENTNEEDEDFONTS
;
2204 else if (IS_DSC(line
, "%%DocumentSuppliedFonts:")) {
2205 dsc
->id
= CDSC_DOCUMENTSUPPLIEDFONTS
;
2208 else if (dsc
->line
[0] == '%' && IS_WHITE_OR_EOL(dsc
->line
[1])) {
2213 dsc
->id
= CDSC_UNKNOWNDSC
;
2217 dsc
->endcomments
= DSC_END(dsc
);
2223 dsc_scan_preview(CDSC
*dsc
)
2225 /* Preview section ends at */
2227 /* another section */
2228 /* Preview section must start with %%BeginPreview */
2229 char *line
= dsc
->line
;
2232 if (dsc
->scan_section
== scan_pre_preview
) {
2234 return CDSC_OK
; /* ignore blank lines before preview */
2235 else if (IS_DSC(line
, "%%BeginPreview")) {
2236 dsc
->id
= CDSC_BEGINPREVIEW
;
2237 dsc
->beginpreview
= DSC_START(dsc
);
2238 dsc
->endpreview
= DSC_END(dsc
);
2239 dsc
->scan_section
= scan_preview
;
2240 /* Don't mark the preview as EPSI if a DOS EPS header is present */
2241 if (dsc
->preview
== CDSC_NOPREVIEW
)
2242 dsc
->preview
= CDSC_EPSI
;
2246 dsc
->scan_section
= scan_pre_defaults
;
2247 return CDSC_PROPAGATE
;
2251 if (IS_DSC(line
, "%%BeginPreview")) {
2252 /* ignore because we are in this section */
2254 else if (dsc_is_section(line
)) {
2255 dsc
->endpreview
= DSC_START(dsc
);
2256 dsc
->scan_section
= scan_pre_defaults
;
2257 return CDSC_PROPAGATE
;
2259 else if (IS_DSC(line
, "%%EndPreview")) {
2260 dsc
->id
= CDSC_ENDPREVIEW
;
2261 dsc
->endpreview
= DSC_END(dsc
);
2262 dsc
->scan_section
= scan_pre_defaults
;
2265 else if (line
[0] == '%' && line
[1] != '%') {
2266 /* Ordinary comments are OK */
2269 dsc
->id
= CDSC_UNKNOWNDSC
;
2270 /* DSC comments should not occur in preview */
2274 dsc
->endpreview
= DSC_END(dsc
);
2279 dsc_scan_defaults(CDSC
*dsc
)
2281 /* Defaults section ends at */
2283 /* another section */
2284 /* Defaults section must start with %%BeginDefaults */
2285 char *line
= dsc
->line
;
2288 if (dsc
->scan_section
== scan_pre_defaults
) {
2290 return CDSC_OK
; /* ignore blank lines before defaults */
2291 else if (IS_DSC(line
, "%%BeginDefaults")) {
2292 dsc
->id
= CDSC_BEGINDEFAULTS
;
2293 dsc
->begindefaults
= DSC_START(dsc
);
2294 dsc
->enddefaults
= DSC_END(dsc
);
2295 dsc
->scan_section
= scan_defaults
;
2299 dsc
->scan_section
= scan_pre_prolog
;
2300 return CDSC_PROPAGATE
;
2304 if (NOT_DSC_LINE(line
)) {
2307 else if (IS_DSC(line
, "%%BeginPreview")) {
2308 /* ignore because we have already processed this section */
2310 else if (IS_DSC(line
, "%%BeginDefaults")) {
2311 /* ignore because we are in this section */
2313 else if (dsc_is_section(line
)) {
2314 dsc
->enddefaults
= DSC_START(dsc
);
2315 dsc
->scan_section
= scan_pre_prolog
;
2316 return CDSC_PROPAGATE
;
2318 else if (IS_DSC(line
, "%%EndDefaults")) {
2319 dsc
->id
= CDSC_ENDDEFAULTS
;
2320 dsc
->enddefaults
= DSC_END(dsc
);
2321 dsc
->scan_section
= scan_pre_prolog
;
2324 else if (IS_DSC(line
, "%%PageMedia:")) {
2325 dsc
->id
= CDSC_PAGEMEDIA
;
2326 dsc_parse_media(dsc
, &dsc
->page_media
);
2328 else if (IS_DSC(line
, "%%PageOrientation:")) {
2329 dsc
->id
= CDSC_PAGEORIENTATION
;
2330 /* This can override %%Orientation: */
2331 if (dsc_parse_orientation(dsc
, &(dsc
->page_orientation
), 18))
2334 else if (IS_DSC(line
, "%%PageBoundingBox:")) {
2335 dsc
->id
= CDSC_PAGEBOUNDINGBOX
;
2336 if (dsc_parse_bounding_box(dsc
, &(dsc
->page_bbox
), 18))
2339 else if (IS_DSC(line
, "%%ViewingOrientation:")) {
2340 dsc
->id
= CDSC_VIEWINGORIENTATION
;
2341 if (dsc_parse_viewing_orientation(dsc
, &dsc
->viewing_orientation
))
2345 dsc
->id
= CDSC_UNKNOWNDSC
;
2346 /* All other DSC comments are unknown, but not an error */
2349 dsc
->enddefaults
= DSC_END(dsc
);
2353 /* CDSC_RESPONSE_OK and CDSC_RESPONSE_CANCEL mean ignore the
2354 * mismatch (default) */
2356 dsc_check_match_prompt(CDSC
*dsc
, const char *str
, int count
)
2359 char buf
[MAXSTR
+MAXSTR
] = "";
2360 if (dsc
->line_length
< (unsigned int)(sizeof(buf
)/2-1)) {
2361 strncpy(buf
, dsc
->line
, dsc
->line_length
);
2362 buf
[dsc
->line_length
] = '\0';
2364 sprintf(buf
+strlen(buf
), "\n%%%%Begin%.40s: / %%%%End%.40s\n", str
, str
);
2365 return dsc_error(dsc
, CDSC_MESSAGE_BEGIN_END
, buf
, strlen(buf
));
2367 return CDSC_RESPONSE_CANCEL
;
2371 dsc_check_match_type(CDSC
*dsc
, const char *str
, int count
)
2373 if (dsc_check_match_prompt(dsc
, str
, count
) == CDSC_RESPONSE_IGNORE_ALL
)
2378 /* complain if Begin/End blocks didn't match */
2379 /* return non-zero if we should ignore all DSC */
2381 dsc_check_match(CDSC
*dsc
)
2384 const char *font
= "Font";
2385 const char *feature
= "Feature";
2386 const char *resource
= "Resource";
2387 const char *procset
= "ProcSet";
2390 rc
= dsc_check_match_type(dsc
, font
, dsc
->begin_font_count
);
2392 rc
= dsc_check_match_type(dsc
, feature
, dsc
->begin_feature_count
);
2394 rc
= dsc_check_match_type(dsc
, resource
, dsc
->begin_resource_count
);
2396 rc
= dsc_check_match_type(dsc
, procset
, dsc
->begin_procset_count
);
2398 dsc
->begin_font_count
= 0;
2399 dsc
->begin_feature_count
= 0;
2400 dsc
->begin_resource_count
= 0;
2401 dsc
->begin_procset_count
= 0;
2407 dsc_scan_prolog(CDSC
*dsc
)
2409 /* Prolog section ends at */
2411 /* another section */
2412 /* Prolog section may start with %%BeginProlog or non-dsc line */
2413 char *line
= dsc
->line
;
2416 if (dsc
->scan_section
== scan_pre_prolog
) {
2417 if (dsc_is_section(line
) && (!IS_DSC(line
, "%%BeginProlog"))) {
2418 dsc
->scan_section
= scan_pre_setup
;
2419 return CDSC_PROPAGATE
;
2421 dsc
->id
= CDSC_BEGINPROLOG
;
2422 dsc
->beginprolog
= DSC_START(dsc
);
2423 dsc
->endprolog
= DSC_END(dsc
);
2424 dsc
->scan_section
= scan_prolog
;
2425 if (IS_DSC(line
, "%%BeginProlog"))
2429 if (NOT_DSC_LINE(line
)) {
2432 else if (IS_DSC(line
, "%%BeginPreview")) {
2433 /* ignore because we have already processed this section */
2435 else if (IS_DSC(line
, "%%BeginDefaults")) {
2436 /* ignore because we have already processed this section */
2438 else if (IS_DSC(line
, "%%BeginProlog")) {
2439 /* ignore because we are in this section */
2441 else if (dsc_is_section(line
)) {
2442 dsc
->endprolog
= DSC_START(dsc
);
2443 dsc
->scan_section
= scan_pre_setup
;
2444 if (dsc_check_match(dsc
))
2446 return CDSC_PROPAGATE
;
2448 else if (IS_DSC(line
, "%%EndProlog")) {
2449 dsc
->id
= CDSC_ENDPROLOG
;
2450 dsc
->endprolog
= DSC_END(dsc
);
2451 dsc
->scan_section
= scan_pre_setup
;
2452 if (dsc_check_match(dsc
))
2456 else if (IS_DSC(line
, "%%BeginFont:")) {
2457 dsc
->id
= CDSC_BEGINFONT
;
2458 /* ignore Begin/EndFont, apart form making sure */
2459 /* that they are matched. */
2460 dsc
->begin_font_count
++;
2462 else if (IS_DSC(line
, "%%EndFont")) {
2463 dsc
->id
= CDSC_ENDFONT
;
2464 dsc
->begin_font_count
--;
2466 else if (IS_DSC(line
, "%%BeginFeature:")) {
2467 dsc
->id
= CDSC_BEGINFEATURE
;
2468 /* ignore Begin/EndFeature, apart form making sure */
2469 /* that they are matched. */
2470 dsc
->begin_feature_count
++;
2472 else if (IS_DSC(line
, "%%EndFeature")) {
2473 dsc
->id
= CDSC_ENDFEATURE
;
2474 dsc
->begin_feature_count
--;
2476 else if (IS_DSC(line
, "%%BeginResource:")) {
2477 dsc
->id
= CDSC_BEGINRESOURCE
;
2478 /* ignore Begin/EndResource, apart form making sure */
2479 /* that they are matched. */
2480 dsc
->begin_resource_count
++;
2482 else if (IS_DSC(line
, "%%EndResource")) {
2483 dsc
->id
= CDSC_ENDRESOURCE
;
2484 dsc
->begin_resource_count
--;
2486 else if (IS_DSC(line
, "%%BeginProcSet:")) {
2487 dsc
->id
= CDSC_BEGINPROCSET
;
2488 /* ignore Begin/EndProcSet, apart form making sure */
2489 /* that they are matched. */
2490 dsc
->begin_procset_count
++;
2492 else if (IS_DSC(line
, "%%EndProcSet")) {
2493 dsc
->id
= CDSC_ENDPROCSET
;
2494 dsc
->begin_procset_count
--;
2497 /* All other DSC comments are unknown, but not an error */
2498 dsc
->id
= CDSC_UNKNOWNDSC
;
2502 dsc
->endprolog
= DSC_END(dsc
);
2507 dsc_scan_setup(CDSC
*dsc
)
2509 /* Setup section ends at */
2511 /* another section */
2512 /* Setup section must start with %%BeginSetup */
2514 char *line
= dsc
->line
;
2517 if (dsc
->scan_section
== scan_pre_setup
) {
2519 return CDSC_OK
; /* ignore blank lines before setup */
2520 else if (IS_DSC(line
, "%%BeginSetup")) {
2521 dsc
->id
= CDSC_BEGINSETUP
;
2522 dsc
->beginsetup
= DSC_START(dsc
);
2523 dsc
->endsetup
= DSC_END(dsc
);
2524 dsc
->scan_section
= scan_setup
;
2528 dsc
->scan_section
= scan_pre_pages
;
2529 return CDSC_PROPAGATE
;
2533 if (NOT_DSC_LINE(line
)) {
2536 else if (IS_DSC(line
, "%%BeginPreview")) {
2537 /* ignore because we have already processed this section */
2539 else if (IS_DSC(line
, "%%BeginDefaults")) {
2540 /* ignore because we have already processed this section */
2542 else if (IS_DSC(line
, "%%BeginProlog")) {
2543 /* ignore because we have already processed this section */
2545 else if (IS_DSC(line
, "%%BeginSetup")) {
2546 /* ignore because we are in this section */
2548 else if (dsc_is_section(line
)) {
2549 dsc
->endsetup
= DSC_START(dsc
);
2550 dsc
->scan_section
= scan_pre_pages
;
2551 if (dsc_check_match(dsc
))
2553 return CDSC_PROPAGATE
;
2555 else if (IS_DSC(line
, "%%EndSetup")) {
2556 dsc
->id
= CDSC_ENDSETUP
;
2557 dsc
->endsetup
= DSC_END(dsc
);
2558 dsc
->scan_section
= scan_pre_pages
;
2559 if (dsc_check_match(dsc
))
2563 else if (IS_DSC(line
, "%%BeginFeature:")) {
2564 dsc
->id
= CDSC_BEGINFEATURE
;
2565 /* ignore Begin/EndFeature, apart form making sure */
2566 /* that they are matched. */
2567 dsc
->begin_feature_count
++;
2569 else if (IS_DSC(line
, "%%EndFeature")) {
2570 dsc
->id
= CDSC_ENDFEATURE
;
2571 dsc
->begin_feature_count
--;
2573 else if (IS_DSC(line
, "%%Feature:")) {
2574 dsc
->id
= CDSC_FEATURE
;
2577 else if (IS_DSC(line
, "%%BeginResource:")) {
2578 dsc
->id
= CDSC_BEGINRESOURCE
;
2579 /* ignore Begin/EndResource, apart form making sure */
2580 /* that they are matched. */
2581 dsc
->begin_resource_count
++;
2583 else if (IS_DSC(line
, "%%EndResource")) {
2584 dsc
->id
= CDSC_ENDRESOURCE
;
2585 dsc
->begin_resource_count
--;
2587 else if (IS_DSC(line
, "%%PaperColor:")) {
2588 dsc
->id
= CDSC_PAPERCOLOR
;
2591 else if (IS_DSC(line
, "%%PaperForm:")) {
2592 dsc
->id
= CDSC_PAPERFORM
;
2595 else if (IS_DSC(line
, "%%PaperWeight:")) {
2596 dsc
->id
= CDSC_PAPERWEIGHT
;
2599 else if (IS_DSC(line
, "%%PaperSize:")) {
2601 GSBOOL found_media
= FALSE
;
2606 dsc
->id
= CDSC_PAPERSIZE
;
2607 dsc_copy_string(buf
, sizeof(buf
)-1, dsc
->line
+n
, dsc
->line_length
-n
,
2609 for (i
=0; i
<(int)dsc
->media_count
; i
++) {
2610 if (dsc
->media
[i
] && dsc
->media
[i
]->name
&&
2611 (dsc_stricmp(buf
, dsc
->media
[i
]->name
)==0)) {
2612 dsc
->page_media
= dsc
->media
[i
];
2618 /* It didn't match %%DocumentPaperSizes: */
2619 /* Try our known media */
2620 const CDSCMEDIA
*m
= dsc_known_media
;
2622 if (dsc_stricmp(buf
, m
->name
)==0) {
2623 dsc
->page_media
= m
;
2628 if (m
->name
== NULL
)
2633 /* All other DSC comments are unknown, but not an error */
2634 dsc
->id
= CDSC_UNKNOWNDSC
;
2638 dsc
->endsetup
= DSC_END(dsc
);
2643 dsc_scan_page(CDSC
*dsc
)
2645 /* Page section ends at */
2649 char *line
= dsc
->line
;
2652 if (dsc
->scan_section
== scan_pre_pages
) {
2653 if (IS_DSC(line
, "%%Page:")) {
2654 dsc
->scan_section
= scan_pages
;
2658 /* %%Page: didn't follow %%EndSetup
2659 * Keep reading until reach %%Page or %%Trailer
2660 * and add it to previous section.
2662 unsigned long *last
;
2663 if (dsc
->endsetup
!= 0)
2664 last
= &dsc
->endsetup
;
2665 else if (dsc
->endprolog
!= 0)
2666 last
= &dsc
->endprolog
;
2667 else if (dsc
->enddefaults
!= 0)
2668 last
= &dsc
->enddefaults
;
2669 else if (dsc
->endpreview
!= 0)
2670 last
= &dsc
->endpreview
;
2671 else if (dsc
->endcomments
!= 0)
2672 last
= &dsc
->endcomments
;
2674 last
= &dsc
->begincomments
;
2675 *last
= DSC_START(dsc
);
2676 if (IS_DSC(line
, "%%Trailer") || IS_DSC(line
, "%%EOF")) {
2677 dsc
->scan_section
= scan_pre_trailer
;
2678 return CDSC_PROPAGATE
;
2684 if (NOT_DSC_LINE(line
)) {
2687 else if (IS_DSC(line
, "%%Page:")) {
2688 dsc
->id
= CDSC_PAGE
;
2689 if (dsc
->page_count
) {
2690 dsc
->page
[dsc
->page_count
-1].end
= DSC_START(dsc
);
2691 if (dsc_check_match(dsc
))
2695 if (dsc_parse_page(dsc
) != 0)
2700 else if (IS_DSC(line
, "%%BeginPreview")) {
2701 /* ignore because we have already processed this section */
2703 else if (IS_DSC(line
, "%%BeginDefaults")) {
2704 /* ignore because we have already processed this section */
2706 else if (IS_DSC(line
, "%%BeginProlog")) {
2707 /* ignore because we have already processed this section */
2709 else if (IS_DSC(line
, "%%BeginSetup")) {
2710 /* ignore because we have already processed this section */
2712 else if (dsc_is_section(line
)) {
2713 if (IS_DSC(line
, "%%Trailer")) {
2714 dsc
->page
[dsc
->page_count
-1].end
= DSC_START(dsc
);
2715 if (dsc
->file_length
) {
2716 if ((!dsc
->doseps
&&
2717 ((DSC_END(dsc
) + 32768) < dsc
->file_length
)) ||
2719 ((DSC_END(dsc
) + 32768) < dsc
->doseps_end
))) {
2720 int rc
= dsc_error(dsc
, CDSC_MESSAGE_EARLY_TRAILER
,
2721 dsc
->line
, dsc
->line_length
);
2723 case CDSC_RESPONSE_OK
:
2724 /* ignore early trailer */
2726 case CDSC_RESPONSE_CANCEL
:
2727 /* this is the trailer */
2728 dsc
->scan_section
= scan_pre_trailer
;
2729 if (dsc_check_match(dsc
))
2731 return CDSC_PROPAGATE
;
2732 case CDSC_RESPONSE_IGNORE_ALL
:
2737 dsc
->scan_section
= scan_pre_trailer
;
2738 if (dsc_check_match(dsc
))
2740 return CDSC_PROPAGATE
;
2744 dsc
->scan_section
= scan_pre_trailer
;
2745 if (dsc_check_match(dsc
))
2747 return CDSC_PROPAGATE
;
2750 else if (IS_DSC(line
, "%%EOF")) {
2751 dsc
->page
[dsc
->page_count
-1].end
= DSC_START(dsc
);
2752 if (dsc
->file_length
) {
2753 if ((DSC_END(dsc
)+100 < dsc
->file_length
) ||
2754 (dsc
->doseps
&& (DSC_END(dsc
) + 100 < dsc
->doseps_end
))) {
2755 int rc
= dsc_error(dsc
, CDSC_MESSAGE_EARLY_EOF
,
2756 dsc
->line
, dsc
->line_length
);
2758 case CDSC_RESPONSE_OK
:
2759 /* %%EOF is wrong, ignore it */
2761 case CDSC_RESPONSE_CANCEL
:
2762 /* %%EOF is correct */
2763 dsc
->scan_section
= scan_eof
;
2765 if (dsc_check_match(dsc
))
2767 return CDSC_PROPAGATE
;
2768 case CDSC_RESPONSE_IGNORE_ALL
:
2775 if (dsc_check_match(dsc
))
2781 /* Section comment, probably from a badly */
2782 /* encapsulated EPS file. */
2783 int rc
= dsc_error(dsc
, CDSC_MESSAGE_BAD_SECTION
,
2784 dsc
->line
, dsc
->line_length
);
2785 if (rc
== CDSC_RESPONSE_IGNORE_ALL
)
2789 else if (IS_DSC(line
, "%%PageTrailer")) {
2790 dsc
->id
= CDSC_PAGETRAILER
;
2793 else if (IS_DSC(line
, "%%BeginPageSetup")) {
2794 dsc
->id
= CDSC_BEGINPAGESETUP
;
2797 else if (IS_DSC(line
, "%%EndPageSetup")) {
2798 dsc
->id
= CDSC_ENDPAGESETUP
;
2801 else if (IS_DSC(line
, "%%PageMedia:")) {
2802 dsc
->id
= CDSC_PAGEMEDIA
;
2803 dsc_parse_media(dsc
, &(dsc
->page
[dsc
->page_count
-1].media
));
2805 else if (IS_DSC(line
, "%%PaperColor:")) {
2806 dsc
->id
= CDSC_PAPERCOLOR
;
2809 else if (IS_DSC(line
, "%%PaperForm:")) {
2810 dsc
->id
= CDSC_PAPERFORM
;
2813 else if (IS_DSC(line
, "%%PaperWeight:")) {
2814 dsc
->id
= CDSC_PAPERWEIGHT
;
2817 else if (IS_DSC(line
, "%%PaperSize:")) {
2819 GSBOOL found_media
= FALSE
;
2824 dsc_copy_string(buf
, sizeof(buf
)-1, dsc
->line
+n
,
2825 dsc
->line_length
-n
, NULL
);
2826 for (i
=0; i
<(int)dsc
->media_count
; i
++) {
2827 if (dsc
->media
[i
] && dsc
->media
[i
]->name
&&
2828 (dsc_stricmp(buf
, dsc
->media
[i
]->name
)==0)) {
2829 dsc
->page_media
= dsc
->media
[i
];
2835 /* It didn't match %%DocumentPaperSizes: */
2836 /* Try our known media */
2837 const CDSCMEDIA
*m
= dsc_known_media
;
2839 if (dsc_stricmp(buf
, m
->name
)==0) {
2840 dsc
->page
[dsc
->page_count
-1].media
= m
;
2845 if (m
->name
== NULL
)
2849 else if (IS_DSC(line
, "%%PageOrientation:")) {
2850 dsc
->id
= CDSC_PAGEORIENTATION
;
2851 if (dsc_parse_orientation(dsc
,
2852 &(dsc
->page
[dsc
->page_count
-1].orientation
) ,18))
2855 else if (IS_DSC(line
, "%%PageBoundingBox:")) {
2856 dsc
->id
= CDSC_PAGEBOUNDINGBOX
;
2857 if (dsc_parse_bounding_box(dsc
, &dsc
->page
[dsc
->page_count
-1].bbox
, 18))
2860 else if (IS_DSC(line
, "%%ViewingOrientation:")) {
2861 dsc
->id
= CDSC_VIEWINGORIENTATION
;
2862 if (dsc_parse_viewing_orientation(dsc
,
2863 &dsc
->page
[dsc
->page_count
-1].viewing_orientation
))
2866 else if (IS_DSC(line
, "%%BeginFont:")) {
2867 dsc
->id
= CDSC_BEGINFONT
;
2868 /* ignore Begin/EndFont, apart form making sure */
2869 /* that they are matched. */
2870 dsc
->begin_font_count
++;
2872 else if (IS_DSC(line
, "%%EndFont")) {
2873 dsc
->id
= CDSC_BEGINFONT
;
2874 dsc
->begin_font_count
--;
2876 else if (IS_DSC(line
, "%%BeginFeature:")) {
2877 dsc
->id
= CDSC_BEGINFEATURE
;
2878 /* ignore Begin/EndFeature, apart form making sure */
2879 /* that they are matched. */
2880 dsc
->begin_feature_count
++;
2882 else if (IS_DSC(line
, "%%EndFeature")) {
2883 dsc
->id
= CDSC_ENDFEATURE
;
2884 dsc
->begin_feature_count
--;
2886 else if (IS_DSC(line
, "%%BeginResource:")) {
2887 dsc
->id
= CDSC_BEGINRESOURCE
;
2888 /* ignore Begin/EndResource, apart form making sure */
2889 /* that they are matched. */
2890 dsc
->begin_resource_count
++;
2892 else if (IS_DSC(line
, "%%EndResource")) {
2893 dsc
->id
= CDSC_ENDRESOURCE
;
2894 dsc
->begin_resource_count
--;
2896 else if (IS_DSC(line
, "%%BeginProcSet:")) {
2897 dsc
->id
= CDSC_BEGINPROCSET
;
2898 /* ignore Begin/EndProcSet, apart form making sure */
2899 /* that they are matched. */
2900 dsc
->begin_procset_count
++;
2902 else if (IS_DSC(line
, "%%EndProcSet")) {
2903 dsc
->id
= CDSC_ENDPROCSET
;
2904 dsc
->begin_procset_count
--;
2906 else if (IS_DSC(line
, "%%IncludeFont:")) {
2907 dsc
->id
= CDSC_INCLUDEFONT
;
2911 /* All other DSC comments are unknown, but not an error */
2912 dsc
->id
= CDSC_UNKNOWNDSC
;
2916 dsc
->page
[dsc
->page_count
-1].end
= DSC_END(dsc
);
2920 /* Valid Trailer comments are
2923 * or the following deferred with (atend)
2925 * %%DocumentCustomColors:
2928 * %%DocumentNeededFiles:
2929 * %%DocumentNeededFonts:
2930 * %%DocumentNeededProcSets:
2931 * %%DocumentNeededResources:
2932 * %%DocumentProcSets:
2933 * %%DocumentProcessColors:
2934 * %%DocumentSuppliedFiles:
2935 * %%DocumentSuppliedFonts:
2936 * %%DocumentSuppliedProcSets:
2937 * %%DocumentSuppliedResources:
2942 * Our supported subset is
2949 * In addition to these, we support
2952 * A %%PageTrailer can have the following:
2953 * %%PageBoundingBox:
2954 * %%PageCustomColors:
2957 * %%PageOrientation:
2958 * %%PageProcessColors:
2963 dsc_scan_trailer(CDSC
*dsc
)
2965 /* Trailer section start at */
2969 char *line
= dsc
->line
;
2970 GSBOOL continued
= FALSE
;
2973 if (dsc
->scan_section
== scan_pre_trailer
) {
2974 if (IS_DSC(line
, "%%Trailer")) {
2975 dsc
->id
= CDSC_TRAILER
;
2976 dsc
->begintrailer
= DSC_START(dsc
);
2977 dsc
->endtrailer
= DSC_END(dsc
);
2978 dsc
->scan_section
= scan_trailer
;
2981 else if (IS_DSC(line
, "%%EOF")) {
2983 dsc
->begintrailer
= DSC_START(dsc
);
2984 dsc
->endtrailer
= DSC_END(dsc
);
2985 dsc
->scan_section
= scan_trailer
;
2986 /* Continue, in case we found %%EOF in an embedded document */
2990 /* %%Page: didn't follow %%EndSetup
2991 * Keep reading until reach %%Page or %%Trailer
2992 * and add it to setup section
2994 /* append to previous section */
2995 if (dsc
->beginsetup
)
2996 dsc
->endsetup
= DSC_END(dsc
);
2997 else if (dsc
->beginprolog
)
2998 dsc
->endprolog
= DSC_END(dsc
);
3000 /* horribly confused */
3006 /* Handle continuation lines.
3007 * See comment above about our restrictive processing of
3008 * continuation lines
3010 if (IS_DSC(line
, "%%+")) {
3011 line
= dsc
->last_line
;
3017 if (NOT_DSC_LINE(line
)) {
3020 else if (IS_DSC(dsc
->line
, "%%EOF")) {
3021 /* Keep scanning, in case we have a false trailer */
3024 else if (IS_DSC(dsc
->line
, "%%Trailer")) {
3025 /* Cope with no pages with code after setup and before trailer. */
3026 /* Last trailer is the correct one. */
3027 dsc
->id
= CDSC_TRAILER
;
3028 dsc
->begintrailer
= DSC_START(dsc
);
3030 else if (IS_DSC(line
, "%%Pages:")) {
3031 dsc
->id
= CDSC_PAGES
;
3032 if (dsc_parse_pages(dsc
) != 0)
3035 else if (IS_DSC(line
, "%%BoundingBox:")) {
3036 dsc
->id
= CDSC_BOUNDINGBOX
;
3037 if (dsc_parse_bounding_box(dsc
, &(dsc
->bbox
), continued
? 3 : 14))
3040 else if (IS_DSC(line
, "%%HiResBoundingBox:")) {
3041 dsc
->id
= CDSC_HIRESBOUNDINGBOX
;
3042 if (dsc_parse_float_bounding_box(dsc
, &(dsc
->hires_bbox
),
3043 continued
? 3 : 19))
3046 else if (IS_DSC(line
, "%%CropBox:")) {
3047 dsc
->id
= CDSC_CROPBOX
;
3048 if (dsc_parse_float_bounding_box(dsc
, &(dsc
->crop_box
),
3049 continued
? 3 : 10))
3052 else if (IS_DSC(line
, "%%Orientation:")) {
3053 dsc
->id
= CDSC_ORIENTATION
;
3054 if (dsc_parse_orientation(dsc
, &(dsc
->page_orientation
), continued
? 3 : 14))
3057 else if (IS_DSC(line
, "%%PageOrder:")) {
3058 dsc
->id
= CDSC_PAGEORDER
;
3059 if (dsc_parse_order(dsc
))
3062 else if (IS_DSC(line
, "%%DocumentMedia:")) {
3063 dsc
->id
= CDSC_DOCUMENTMEDIA
;
3064 if (dsc_parse_document_media(dsc
))
3067 else if (IS_DSC(dsc
->line
, "%%Page:")) {
3068 /* This should not occur in the trailer, but we might see
3069 * this if a document has been incorrectly embedded.
3071 int rc
= dsc_error(dsc
, CDSC_MESSAGE_PAGE_IN_TRAILER
,
3072 dsc
->line
, dsc
->line_length
);
3074 case CDSC_RESPONSE_OK
:
3075 /* Assume that we are really in the previous */
3076 /* page, not the trailer */
3077 dsc
->scan_section
= scan_pre_pages
;
3078 if (dsc
->page_count
)
3079 dsc
->page
[dsc
->page_count
-1].end
= DSC_START(dsc
);
3080 return CDSC_PROPAGATE
; /* try again */
3081 case CDSC_RESPONSE_CANCEL
:
3082 /* ignore pages in trailer */
3084 case CDSC_RESPONSE_IGNORE_ALL
:
3088 else if (IS_DSC(line
, "%%DocumentNeededFonts:")) {
3089 dsc
->id
= CDSC_DOCUMENTNEEDEDFONTS
;
3092 else if (IS_DSC(line
, "%%DocumentSuppliedFonts:")) {
3093 dsc
->id
= CDSC_DOCUMENTSUPPLIEDFONTS
;
3097 /* All other DSC comments are unknown, but not an error */
3098 dsc
->id
= CDSC_UNKNOWNDSC
;
3102 dsc
->endtrailer
= DSC_END(dsc
);
3108 dsc_alloc_string(CDSC
*dsc
, const char *str
, int len
)
3111 if (dsc
->string_head
== NULL
) {
3112 dsc
->string_head
= (CDSCSTRING
*)dsc_memalloc(dsc
, sizeof(CDSCSTRING
));
3113 if (dsc
->string_head
== NULL
)
3114 return NULL
; /* no memory */
3115 dsc
->string
= dsc
->string_head
;
3116 dsc
->string
->next
= NULL
;
3117 dsc
->string
->data
= (char *)dsc_memalloc(dsc
, CDSC_STRING_CHUNK
);
3118 if (dsc
->string
->data
== NULL
) {
3120 return NULL
; /* no memory */
3122 dsc
->string
->index
= 0;
3123 dsc
->string
->length
= CDSC_STRING_CHUNK
;
3125 if ( dsc
->string
->index
+ len
+ 1 > dsc
->string
->length
) {
3126 /* allocate another string block */
3127 CDSCSTRING
*newstring
= (CDSCSTRING
*)dsc_memalloc(dsc
, sizeof(CDSCSTRING
));
3128 if (newstring
== NULL
) {
3129 dsc_debug_print(dsc
, "Out of memory\n");
3132 newstring
->next
= NULL
;
3133 newstring
->length
= 0;
3134 newstring
->index
= 0;
3135 newstring
->data
= (char *)dsc_memalloc(dsc
, CDSC_STRING_CHUNK
);
3136 if (newstring
->data
== NULL
) {
3137 dsc_memfree(dsc
, newstring
);
3138 dsc_debug_print(dsc
, "Out of memory\n");
3139 return NULL
; /* no memory */
3141 newstring
->length
= CDSC_STRING_CHUNK
;
3142 dsc
->string
->next
= newstring
;
3143 dsc
->string
= newstring
;
3145 if ( dsc
->string
->index
+ len
+ 1 > dsc
->string
->length
)
3146 return NULL
; /* failed */
3147 p
= dsc
->string
->data
+ dsc
->string
->index
;
3148 memcpy(p
, str
, len
);
3150 dsc
->string
->index
+= len
+ 1;
3154 /* store line, ignoring leading spaces */
3156 dsc_add_line(CDSC
*dsc
, const char *line
, unsigned int len
)
3160 while (len
&& (IS_WHITE(*line
))) {
3164 newline
= dsc_alloc_string(dsc
, line
, len
);
3165 if (newline
== NULL
)
3168 for (i
=0; i
<len
; i
++) {
3169 if (newline
[i
] == '\r') {
3173 if (newline
[i
] == '\n') {
3182 /* Copy string on line to new allocated string str */
3183 /* String is always null terminated */
3184 /* String is no longer than len */
3185 /* Return pointer to string */
3186 /* Store number of used characters from line */
3187 /* Don't copy enclosing () */
3189 dsc_copy_string(char *str
, unsigned int slen
, char *line
,
3190 unsigned int len
, unsigned int *offset
)
3194 unsigned int newlength
= 0;
3199 while ( (i
<len
) && IS_WHITE(line
[i
]))
3200 i
++; /* skip leading spaces */
3204 i
++; /* don't copy outside () */
3207 str
[newlength
] = ch
= line
[i
];
3224 else if ( (ch
== '\\') && (i
+1 < len
) ) {
3226 if ((ch
>= '0') && (ch
<= '9')) {
3227 /* octal coded character */
3230 while (j
&& (i
< len
) && line
[i
]>='0' && line
[i
]<='7') {
3231 ch
= (unsigned char)((ch
<<3) + (line
[i
]-'0'));
3235 str
[newlength
] = ch
;
3237 else if (ch
== '(') {
3238 str
[newlength
] = ch
;
3241 else if (ch
== ')') {
3242 str
[newlength
] = ch
;
3245 else if (ch
== 'b') {
3246 str
[newlength
] = '\b';
3249 else if (ch
== 'f') {
3250 str
[newlength
] = '\b';
3253 else if (ch
== 'n') {
3254 str
[newlength
] = '\n';
3257 else if (ch
== 'r') {
3258 str
[newlength
] = '\r';
3261 else if (ch
== 't') {
3262 str
[newlength
] = '\t';
3265 else if (ch
== '\\') {
3266 str
[newlength
] = '\\';
3272 str
[newlength
] = '\0';
3273 if (offset
!= (unsigned int *)NULL
)
3279 dsc_get_int(const char *line
, unsigned int len
, unsigned int *offset
)
3281 char newline
[MAXSTR
];
3286 len
= min(len
, sizeof(newline
)-1);
3287 while ((i
<len
) && IS_WHITE(line
[i
]))
3288 i
++; /* skip leading spaces */
3290 newline
[newlength
] = ch
= line
[i
];
3291 if (!(isdigit(ch
) || (ch
=='-') || (ch
=='+')))
3292 break; /* not part of an integer number */
3296 while ((i
<len
) && IS_WHITE(line
[i
]))
3297 i
++; /* skip trailing spaces */
3298 newline
[newlength
] = '\0';
3299 if (offset
!= (unsigned int *)NULL
)
3301 return atoi(newline
);
3305 dsc_get_real(const char *line
, unsigned int len
, unsigned int *offset
)
3307 char newline
[MAXSTR
];
3312 len
= min(len
, sizeof(newline
)-1);
3313 while ((i
<len
) && IS_WHITE(line
[i
]))
3314 i
++; /* skip leading spaces */
3316 newline
[newlength
] = ch
= line
[i
];
3317 if (!(isdigit(ch
) || (ch
=='.') || (ch
=='-') || (ch
=='+')
3318 || (ch
=='e') || (ch
=='E')))
3319 break; /* not part of a real number */
3323 while ((i
<len
) && IS_WHITE(line
[i
]))
3324 i
++; /* skip trailing spaces */
3326 newline
[newlength
] = '\0';
3328 if (offset
!= (unsigned int *)NULL
)
3330 return (float)atof(newline
);
3334 dsc_stricmp(const char *s
, const char *t
)
3336 while (toupper(*s
) == toupper(*t
)) {
3342 return (toupper(*s
) - toupper(*t
));
3347 dsc_parse_page(CDSC
*dsc
)
3351 char page_label
[MAXSTR
];
3357 pl
= dsc_copy_string(page_label
, sizeof(page_label
)-1, p
, dsc
->line_length
-7, &i
);
3361 page_ordinal
= atoi(p
);
3363 if ( (page_ordinal
== 0) || (strlen(page_label
) == 0) ||
3365 (page_ordinal
!= dsc
->page
[dsc
->page_count
-1].ordinal
+1)) ) {
3366 int rc
= dsc_error(dsc
, CDSC_MESSAGE_PAGE_ORDINAL
, dsc
->line
,
3369 case CDSC_RESPONSE_OK
:
3370 /* ignore this page */
3372 case CDSC_RESPONSE_CANCEL
:
3373 /* accept the page */
3375 case CDSC_RESPONSE_IGNORE_ALL
:
3380 page_number
= dsc
->page_count
;
3381 dsc_add_page(dsc
, page_ordinal
, page_label
);
3382 dsc
->page
[page_number
].begin
= DSC_START(dsc
);
3383 dsc
->page
[page_number
].end
= DSC_START(dsc
);
3385 if (dsc
->page
[page_number
].label
== NULL
)
3386 return CDSC_ERROR
; /* no memory */
3393 /* DSC error reporting */
3396 dsc_debug_print(CDSC
*dsc
, const char *str
)
3398 if (dsc
->debug_print_fn
)
3399 dsc
->debug_print_fn(dsc
->caller_data
, str
);
3403 /* Display a message about a problem with the DSC comments.
3405 * explanation = an index to to a multiline explanation in dsc_message[]
3406 * line = pointer to the offending DSC line (if any)
3408 * CDSC_RESPONSE_OK DSC was wrong, make a guess about what
3410 * CDSC_RESPONSE_CANCEL Assume DSC was correct, ignore if it
3412 * CDSC_RESPONSE_IGNORE_ALL Ignore all DSC.
3414 /* Silent operation. Don't display errors. */
3416 dsc_error(CDSC
*dsc
, unsigned int explanation
,
3417 char *line
, unsigned int line_len
)
3419 /* if error function provided, use it */
3420 if (dsc
->dsc_error_fn
)
3421 return dsc
->dsc_error_fn(dsc
->caller_data
, dsc
,
3422 explanation
, line
, line_len
);
3424 /* treat DSC as being correct */
3425 return CDSC_RESPONSE_CANCEL
;
3429 // vim:sw=4:sts=4:ts=8:noet