Tue, 22 Jan 2002 09:42:42 +0000
*** empty log message ***
1 #include <stdlib.h>
2 #include <string.h>
3 #include <stdio.h>
5 #include "type.h"
6 #include "semantics.h"
7 #include "parser.tab.h"
8 #include "tiff2pdf.h"
11 typedef struct
12 {
13 boolean has_page_size;
14 page_size_t page_size;
16 boolean has_rotation;
17 int rotation;
19 boolean has_crop;
20 crop_t crop;
21 } input_modifiers_t;
24 typedef struct input_context_t
25 {
26 struct input_context_t *parent;
27 struct input_context_t *next;
29 int image_count; /* how many pages reference this context,
30 including those from subcontexts */
32 char *input_file;
34 input_modifiers_t modifiers [INPUT_MODIFIER_TYPE_COUNT];
35 } input_context_t;
38 typedef struct input_image_t
39 {
40 struct input_image_t *next;
41 input_context_t *input_context;
42 range_t range;
43 } input_image_t;
46 typedef struct output_context_t
47 {
48 struct output_context_t *parent;
49 struct output_context_t *next;
51 int page_count; /* how many pages reference this context,
52 including those from subcontexts */
54 char *output_file;
55 pdf_file_attributes_t file_attributes;
57 bookmark_t *first_bookmark;
58 bookmark_t *last_bookmark;
60 boolean has_page_label;
61 page_label_t page_label;
62 } output_context_t;
65 typedef struct output_page_t
66 {
67 struct output_page_t *next;
68 output_context_t *output_context;
69 range_t range;
70 bookmark_t *bookmark_list;
71 } output_page_t;
74 #undef SEMANTIC_DEBUG
76 #ifdef SEMANTIC_DEBUG
77 #define SDBG(x) printf x
78 #else
79 #define SDBG(x)
80 #endif
83 FILE *yyin;
84 int line; /* line number in spec file */
86 int bookmark_level;
88 input_context_t *first_input_context;
89 input_context_t *last_input_context;
91 input_modifier_type_t current_modifier_context;
93 input_image_t *first_input_image;
94 input_image_t *last_input_image;
96 output_context_t *first_output_context;
97 output_context_t *last_output_context;
99 output_page_t *first_output_page;
100 output_page_t *last_output_page;
103 void input_push_context (void)
104 {
105 input_context_t *new_input_context;
107 new_input_context = malloc (sizeof (input_context_t));
108 if (! new_input_context)
109 {
110 fprintf (stderr, "failed to malloc an input context\n");
111 return;
112 }
114 if (last_input_context)
115 {
116 memcpy (new_input_context, last_input_context, sizeof (input_context_t));
117 new_input_context->image_count = 0;
118 }
119 else
120 {
121 memset (new_input_context, 0, sizeof (input_context_t));
122 first_input_context = new_input_context;
123 }
125 new_input_context->parent = last_input_context;
126 last_input_context = new_input_context;
127 };
129 void input_pop_context (void)
130 {
131 if (! last_input_context)
132 {
133 fprintf (stderr, "failed to pop an input context\n");
134 return;
135 }
137 last_input_context = last_input_context->parent;
138 };
140 void input_set_modifier_context (input_modifier_type_t type)
141 {
142 current_modifier_context = type;
143 #ifdef SEMANTIC_DEBUG
144 SDBG(("modifier type "));
145 switch (type)
146 {
147 case INPUT_MODIFIER_ALL: SDBG(("all")); break;
148 case INPUT_MODIFIER_ODD: SDBG(("odd")); break;
149 case INPUT_MODIFIER_EVEN: SDBG(("even")); break;
150 default: SDBG(("unknown %d", type));
151 }
152 SDBG(("\n"));
153 #endif /* SEMANTIC_DEBUG */
154 }
156 static void input_clone (void)
157 {
158 input_context_t *new_input_context;
160 if (! last_input_context->image_count)
161 return;
163 new_input_context = malloc (sizeof (input_context_t));
164 if (! new_input_context)
165 {
166 fprintf (stderr, "failed to malloc an input context\n");
167 return;
168 }
170 memcpy (new_input_context, last_input_context, sizeof (input_context_t));
171 new_input_context->image_count = 0;
172 last_input_context->next = new_input_context;
173 }
175 void input_set_file (char *name)
176 {
177 input_clone ();
178 last_input_context->input_file = name;
179 };
181 void input_set_rotation (int rotation)
182 {
183 last_input_context->modifiers [current_modifier_context].has_rotation = 1;
184 last_input_context->modifiers [current_modifier_context].rotation = rotation;
185 SDBG(("rotation %d\n", rotation));
186 }
188 void input_set_page_size (page_size_t size)
189 {
190 last_input_context->modifiers [current_modifier_context].has_page_size = 1;
191 last_input_context->modifiers [current_modifier_context].page_size = size;
192 SDBG(("page size %f, %f\n", size.width, size.height));
193 }
195 static void increment_input_image_count (int count)
196 {
197 input_context_t *context;
199 for (context = last_input_context; context; context = context->parent)
200 context->image_count += count;
201 }
203 void input_images (range_t range)
204 {
205 input_image_t *new_image;
206 int count = ((range.last - range.first) + 1);
208 #ifdef SEMANTIC_DEBUG
209 if (range.first == range.last)
210 SDBG(("image %d\n", range.first));
211 else
212 SDBG(("images %d..%d\n", range.first, range.last));
213 #endif /* SEMANTIC_DEBUG */
215 new_image = calloc (1, sizeof (input_image_t));
216 if (! new_image)
217 {
218 fprintf (stderr, "failed to malloc an input image struct\n");
219 return;
220 }
221 if (first_input_image)
222 {
223 last_input_image->next = new_image;
224 last_input_image = new_image;
225 }
226 else
227 {
228 first_input_image = last_input_image = new_image;
229 }
230 new_image->range = range;
231 new_image->input_context = last_input_context;
232 increment_input_image_count (count);
233 }
236 void output_push_context (void)
237 {
238 output_context_t *new_output_context;
240 new_output_context = malloc (sizeof (output_context_t));
241 if (! new_output_context)
242 {
243 fprintf (stderr, "failed to malloc an output context\n");
244 return;
245 }
247 if (last_output_context)
248 {
249 memcpy (new_output_context, last_output_context, sizeof (output_context_t));
250 new_output_context->page_count = 0;
251 new_output_context->first_bookmark = NULL;
252 new_output_context->last_bookmark = NULL;
253 }
254 else
255 {
256 memset (new_output_context, 0, sizeof (output_context_t));
257 first_output_context = new_output_context;
258 }
260 new_output_context->parent = last_output_context;
261 last_output_context = new_output_context;
262 };
264 void output_pop_context (void)
265 {
266 if (! last_output_context)
267 {
268 fprintf (stderr, "failed to pop an output context\n");
269 return;
270 }
272 last_output_context = last_output_context->parent;
273 };
275 static void output_clone (void)
276 {
277 output_context_t *new_output_context;
279 if (! last_output_context->page_count)
280 return;
282 new_output_context = malloc (sizeof (output_context_t));
283 if (! new_output_context)
284 {
285 fprintf (stderr, "failed to malloc an output context\n");
286 return;
287 }
289 memcpy (new_output_context, last_output_context, sizeof (output_context_t));
290 new_output_context->page_count = 0;
291 last_output_context->next = new_output_context;
292 }
294 void output_set_file (char *name)
295 {
296 output_clone ();
297 last_output_context->output_file = name;
298 last_output_context->file_attributes.author = NULL;
299 last_output_context->file_attributes.creator = NULL;
300 last_output_context->file_attributes.title = NULL;
301 last_output_context->file_attributes.subject = NULL;
302 last_output_context->file_attributes.keywords = NULL;
303 };
305 void output_set_author (char *author)
306 {
307 last_output_context->file_attributes.author = author;
308 }
310 void output_set_creator (char *creator)
311 {
312 last_output_context->file_attributes.creator = creator;
313 }
315 void output_set_title (char *title)
316 {
317 last_output_context->file_attributes.title = title;
318 }
320 void output_set_subject (char *subject)
321 {
322 last_output_context->file_attributes.subject = subject;
323 }
325 void output_set_keywords (char *keywords)
326 {
327 last_output_context->file_attributes.keywords = keywords;
328 }
330 void output_set_bookmark (char *name)
331 {
332 bookmark_t *new_bookmark;
334 /* As the language is defined (parser.y), a bookmark can only appear
335 at the beginning of a context! */
336 if (last_output_context->page_count)
337 {
338 fprintf (stderr, "internal error, bookmark not at beginning of context\n");
339 exit (2);
340 }
342 new_bookmark = calloc (1, sizeof (bookmark_t));
343 if (! new_bookmark)
344 {
345 fprintf (stderr, "failed to calloc a bookmark\n");
346 return;
347 }
349 new_bookmark->level = bookmark_level;
350 new_bookmark->name = name;
351 if (last_output_context->first_bookmark)
352 last_output_context->last_bookmark->next = new_bookmark;
353 else
354 last_output_context->first_bookmark = new_bookmark;
355 last_output_context->last_bookmark = new_bookmark;
356 }
358 void output_set_page_label (page_label_t label)
359 {
360 output_clone ();
361 last_output_context->has_page_label = 1;
362 last_output_context->page_label = label;
363 }
365 static void increment_output_page_count (int count)
366 {
367 output_context_t *context;
369 for (context = last_output_context; context; context = context->parent)
370 context->page_count += count;
371 }
374 void output_pages (range_t range)
375 {
376 output_page_t *new_page;
377 output_context_t *context;
378 int count = ((range.last - range.first) + 1);
380 #ifdef SEMANTIC_DEBUG
381 if (range.first == range.last)
382 SDBG(("page %d\n", range.first));
383 else
384 SDBG(("pages %d..%d\n", range.first, range.last));
385 #endif /* SEMANTIC_DEBUG */
387 new_page = calloc (1, sizeof (output_page_t));
388 if (! new_page)
389 {
390 fprintf (stderr, "failed to malloc an output page struct\n");
391 return;
392 }
393 if (first_output_page)
394 {
395 last_output_page->next = new_page;
396 last_output_page = new_page;
397 }
398 else
399 {
400 first_output_page = last_output_page = new_page;
401 }
402 new_page->range = range;
403 new_page->output_context = last_output_context;
405 /* transfer bookmarks from context(s) to page */
406 for (context = last_output_context; context; context = context->parent)
407 if (context->first_bookmark)
408 {
409 context->last_bookmark->next = new_page->bookmark_list;
410 new_page->bookmark_list = context->first_bookmark;
411 context->first_bookmark = NULL;
412 context->last_bookmark = NULL;
413 }
415 increment_output_page_count (count);
416 }
419 void yyerror (char *s)
420 {
421 fprintf (stderr, "%d: %s\n", line, s);
422 }
425 static char *get_input_file (input_context_t *context)
426 {
427 for (; context; context = context->parent)
428 if (context->input_file)
429 return (context->input_file);
430 fprintf (stderr, "no input file name found\n");
431 exit (2);
432 }
434 static boolean get_input_rotation (input_context_t *context,
435 input_modifier_type_t type,
436 int *rotation)
437 {
438 for (; context; context = context->parent)
439 {
440 if (context->modifiers [type].has_rotation)
441 {
442 * rotation = context->modifiers [type].rotation;
443 return (1);
444 }
445 if (context->modifiers [INPUT_MODIFIER_ALL].has_rotation)
446 {
447 * rotation = context->modifiers [INPUT_MODIFIER_ALL].rotation;
448 return (1);
449 }
450 }
451 return (0); /* default */
452 }
454 static boolean get_input_page_size (input_context_t *context,
455 input_modifier_type_t type,
456 page_size_t *page_size)
457 {
458 for (; context; context = context->parent)
459 {
460 if (context->modifiers [type].has_page_size)
461 {
462 * page_size = context->modifiers [type].page_size;
463 return (1);
464 }
465 if (context->modifiers [INPUT_MODIFIER_ALL].has_page_size)
466 {
467 * page_size = context->modifiers [INPUT_MODIFIER_ALL].page_size;
468 return (1);
469 }
470 }
471 return (0); /* default */
472 }
474 static char *get_output_file (output_context_t *context)
475 {
476 for (; context; context = context->parent)
477 if (context->output_file)
478 return (context->output_file);
479 fprintf (stderr, "no output file found\n");
480 exit (2);
481 }
483 static pdf_file_attributes_t *get_output_file_attributes (output_context_t *context)
484 {
485 for (; context; context = context->parent)
486 if (context->output_file)
487 return (& context->file_attributes);
488 fprintf (stderr, "no output file found\n");
489 exit (2);
490 }
492 static page_label_t *get_output_page_label (output_context_t *context)
493 {
494 for (; context; context = context->parent)
495 if (context->has_page_label)
496 return (& context->page_label);
497 return (NULL); /* default */
498 }
501 #ifdef SEMANTIC_DEBUG
502 void dump_input_tree (void)
503 {
504 input_image_t *image;
505 int i;
507 printf ("input images:\n");
508 for (image = first_input_image; image; image = image->next)
509 for (i = image->range.first; i <= image->range.last; i++)
510 {
511 input_modifier_type_t parity = (i % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN;
512 boolean has_rotation, has_page_size;
513 int rotation;
514 page_size_t page_size;
516 has_rotation = get_input_rotation (image->input_context,
517 parity,
518 & rotation);
519 has_page_size = get_input_page_size (image->input_context,
520 parity,
521 & page_size);
522 printf ("file '%s' image %d",
523 get_input_file (image->input_context),
524 i);
525 if (has_rotation)
526 printf (" rotation %d", rotation);
527 if (has_page_size)
528 printf (" size %f, %f", page_size.width, page_size.height);
529 printf ("\n");
530 }
531 }
533 void dump_output_tree (void)
534 {
535 int i;
536 output_page_t *page;
537 bookmark_t *bookmark;
539 printf ("output pages:\n");
540 for (page = first_output_page; page; page = page->next)
541 {
542 if (page->bookmark_list)
543 {
544 for (bookmark = page->bookmark_list; bookmark; bookmark = bookmark->next)
545 printf ("bookmark %d \"%s\"\n", bookmark->level, bookmark->name);
546 }
547 for (i = page->range.first; i <= page->range.last; i++)
548 {
549 page_label_t *label = get_output_page_label (page->output_context);
550 printf ("file \"%s\" ", get_output_file (page->output_context));
551 if (label)
552 {
553 printf ("label ");
554 if (label->prefix)
555 printf ("\"%s\" ", label->prefix);
556 if (label->style)
557 printf ("'%c' ", label->style);
558 }
559 printf ("page %d\n", i);
560 }
561 }
562 }
563 #endif /* SEMANTIC_DEBUG */
566 static inline int range_count (range_t range)
567 {
568 return ((range.last - range.first) + 1);
569 }
572 boolean parse_spec_file (char *fn)
573 {
574 boolean result = 0;
576 yyin = fopen (fn, "r");
577 if (! yyin)
578 {
579 fprintf (stderr, "can't open spec file '%s'\n", fn);
580 goto fail;
581 }
583 line = 1;
585 input_push_context (); /* create root input context */
586 input_push_context (); /* create inital input context */
588 output_push_context (); /* create root output context */
589 output_push_context (); /* create initial output context */
591 yyparse ();
593 if (first_input_context->image_count != first_output_context->page_count)
594 {
595 fprintf (stderr, "input image count %d != output page count %d\n",
596 first_input_context->image_count,
597 first_output_context->page_count);
598 goto fail;
599 }
601 fprintf (stderr, "%d pages specified\n", first_input_context->image_count);
603 result = 1;
605 #ifdef SEMANTIC_DEBUG
606 dump_input_tree ();
607 dump_output_tree ();
608 #endif /* SEMANTIC_DEBUG */
610 fail:
611 if (yyin)
612 fclose (yyin);
614 return (result);
615 }
618 boolean process_specs (void)
619 {
620 input_image_t *image = NULL;
621 output_page_t *page = NULL;
622 int i = 0;
623 int p = 0;
624 int page_index = 0;
625 input_attributes_t input_attributes;
626 input_modifier_type_t parity;
627 page_label_t *page_label;
629 for (;;)
630 {
631 if ((! image) || (i >= range_count (image->range)))
632 {
633 if (image)
634 image = image->next;
635 else
636 image = first_input_image;
637 if (! image)
638 return (0);
639 i = 0;
640 if (! open_tiff_input_file (get_input_file (image->input_context)))
641 return (0);
642 }
644 if ((! page) || (p >= range_count (page->range)))
645 {
646 if (page)
647 page = page->next;
648 else
649 page = first_output_page;
650 p = 0;
651 if (! open_pdf_output_file (get_output_file (page->output_context),
652 get_output_file_attributes (page->output_context)))
653 return (0);
654 page_label = get_output_page_label (page->output_context);
655 process_page_numbers (page_index,
656 range_count (page->range),
657 page->range.first,
658 page_label);
659 }
661 parity = ((image->range.first + i) % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN;
663 memset (& input_attributes, 0, sizeof (input_attributes));
665 input_attributes.rotation = 0;
666 input_attributes.has_rotation = get_input_rotation (image->input_context,
667 parity,
668 & input_attributes.rotation);
670 input_attributes.has_page_size = get_input_page_size (image->input_context,
671 parity,
672 & input_attributes.page_size);
674 process_page (image->range.first + i,
675 input_attributes,
676 page->bookmark_list);
677 i++;
678 p++;
679 page_index++;
680 }
682 return (1);
683 }