Mon, 26 Aug 2002 05:43:49 +0000
fixed 'middle-endian' output from TIFFReadScanline
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 "t2p.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 last_input_context = new_input_context;
174 }
176 void input_set_file (char *name)
177 {
178 input_clone ();
179 last_input_context->input_file = name;
180 };
182 void input_set_rotation (int rotation)
183 {
184 last_input_context->modifiers [current_modifier_context].has_rotation = 1;
185 last_input_context->modifiers [current_modifier_context].rotation = rotation;
186 SDBG(("rotation %d\n", rotation));
187 }
189 void input_set_page_size (page_size_t size)
190 {
191 last_input_context->modifiers [current_modifier_context].has_page_size = 1;
192 last_input_context->modifiers [current_modifier_context].page_size = size;
193 SDBG(("page size %f, %f\n", size.width, size.height));
194 }
196 static void increment_input_image_count (int count)
197 {
198 input_context_t *context;
200 for (context = last_input_context; context; context = context->parent)
201 context->image_count += count;
202 }
204 void input_images (range_t range)
205 {
206 input_image_t *new_image;
207 int count = ((range.last - range.first) + 1);
209 #ifdef SEMANTIC_DEBUG
210 if (range.first == range.last)
211 SDBG(("image %d\n", range.first));
212 else
213 SDBG(("images %d..%d\n", range.first, range.last));
214 #endif /* SEMANTIC_DEBUG */
216 new_image = calloc (1, sizeof (input_image_t));
217 if (! new_image)
218 {
219 fprintf (stderr, "failed to malloc an input image struct\n");
220 return;
221 }
222 if (first_input_image)
223 {
224 last_input_image->next = new_image;
225 last_input_image = new_image;
226 }
227 else
228 {
229 first_input_image = last_input_image = new_image;
230 }
231 new_image->range = range;
232 new_image->input_context = last_input_context;
233 increment_input_image_count (count);
234 }
237 void output_push_context (void)
238 {
239 output_context_t *new_output_context;
241 new_output_context = malloc (sizeof (output_context_t));
242 if (! new_output_context)
243 {
244 fprintf (stderr, "failed to malloc an output context\n");
245 return;
246 }
248 if (last_output_context)
249 {
250 memcpy (new_output_context, last_output_context, sizeof (output_context_t));
251 new_output_context->page_count = 0;
252 new_output_context->first_bookmark = NULL;
253 new_output_context->last_bookmark = NULL;
254 }
255 else
256 {
257 memset (new_output_context, 0, sizeof (output_context_t));
258 first_output_context = new_output_context;
259 }
261 new_output_context->parent = last_output_context;
262 last_output_context = new_output_context;
263 };
265 void output_pop_context (void)
266 {
267 if (! last_output_context)
268 {
269 fprintf (stderr, "failed to pop an output context\n");
270 return;
271 }
273 last_output_context = last_output_context->parent;
274 };
276 static void output_clone (void)
277 {
278 output_context_t *new_output_context;
280 if (! last_output_context->page_count)
281 return;
283 new_output_context = malloc (sizeof (output_context_t));
284 if (! new_output_context)
285 {
286 fprintf (stderr, "failed to malloc an output context\n");
287 return;
288 }
290 memcpy (new_output_context, last_output_context, sizeof (output_context_t));
291 new_output_context->page_count = 0;
292 last_output_context->next = new_output_context;
293 }
295 void output_set_file (char *name)
296 {
297 output_clone ();
298 last_output_context->output_file = name;
299 last_output_context->file_attributes.author = NULL;
300 last_output_context->file_attributes.creator = NULL;
301 last_output_context->file_attributes.title = NULL;
302 last_output_context->file_attributes.subject = NULL;
303 last_output_context->file_attributes.keywords = NULL;
304 };
306 void output_set_author (char *author)
307 {
308 last_output_context->file_attributes.author = author;
309 }
311 void output_set_creator (char *creator)
312 {
313 last_output_context->file_attributes.creator = creator;
314 }
316 void output_set_title (char *title)
317 {
318 last_output_context->file_attributes.title = title;
319 }
321 void output_set_subject (char *subject)
322 {
323 last_output_context->file_attributes.subject = subject;
324 }
326 void output_set_keywords (char *keywords)
327 {
328 last_output_context->file_attributes.keywords = keywords;
329 }
331 void output_set_bookmark (char *name)
332 {
333 bookmark_t *new_bookmark;
335 /* As the language is defined (parser.y), a bookmark can only appear
336 at the beginning of a context! */
337 if (last_output_context->page_count)
338 {
339 fprintf (stderr, "internal error, bookmark not at beginning of context\n");
340 exit (2);
341 }
343 new_bookmark = calloc (1, sizeof (bookmark_t));
344 if (! new_bookmark)
345 {
346 fprintf (stderr, "failed to calloc a bookmark\n");
347 return;
348 }
350 new_bookmark->level = bookmark_level;
351 new_bookmark->name = name;
352 if (last_output_context->first_bookmark)
353 last_output_context->last_bookmark->next = new_bookmark;
354 else
355 last_output_context->first_bookmark = new_bookmark;
356 last_output_context->last_bookmark = new_bookmark;
357 }
359 void output_set_page_label (page_label_t label)
360 {
361 output_clone ();
362 last_output_context->has_page_label = 1;
363 last_output_context->page_label = label;
364 }
366 static void increment_output_page_count (int count)
367 {
368 output_context_t *context;
370 for (context = last_output_context; context; context = context->parent)
371 context->page_count += count;
372 }
375 void output_pages (range_t range)
376 {
377 output_page_t *new_page;
378 output_context_t *context;
379 int count = ((range.last - range.first) + 1);
381 #ifdef SEMANTIC_DEBUG
382 if (range.first == range.last)
383 SDBG(("page %d\n", range.first));
384 else
385 SDBG(("pages %d..%d\n", range.first, range.last));
386 #endif /* SEMANTIC_DEBUG */
388 new_page = calloc (1, sizeof (output_page_t));
389 if (! new_page)
390 {
391 fprintf (stderr, "failed to malloc an output page struct\n");
392 return;
393 }
394 if (first_output_page)
395 {
396 last_output_page->next = new_page;
397 last_output_page = new_page;
398 }
399 else
400 {
401 first_output_page = last_output_page = new_page;
402 }
403 new_page->range = range;
404 new_page->output_context = last_output_context;
406 /* transfer bookmarks from context(s) to page */
407 for (context = last_output_context; context; context = context->parent)
408 if (context->first_bookmark)
409 {
410 context->last_bookmark->next = new_page->bookmark_list;
411 new_page->bookmark_list = context->first_bookmark;
412 context->first_bookmark = NULL;
413 context->last_bookmark = NULL;
414 }
416 increment_output_page_count (count);
417 }
420 void yyerror (char *s)
421 {
422 fprintf (stderr, "%d: %s\n", line, s);
423 }
426 static char *get_input_file (input_context_t *context)
427 {
428 for (; context; context = context->parent)
429 if (context->input_file)
430 return (context->input_file);
431 fprintf (stderr, "no input file name found\n");
432 exit (2);
433 }
435 static boolean get_input_rotation (input_context_t *context,
436 input_modifier_type_t type,
437 int *rotation)
438 {
439 for (; context; context = context->parent)
440 {
441 if (context->modifiers [type].has_rotation)
442 {
443 * rotation = context->modifiers [type].rotation;
444 return (1);
445 }
446 if (context->modifiers [INPUT_MODIFIER_ALL].has_rotation)
447 {
448 * rotation = context->modifiers [INPUT_MODIFIER_ALL].rotation;
449 return (1);
450 }
451 }
452 return (0); /* default */
453 }
455 static boolean get_input_page_size (input_context_t *context,
456 input_modifier_type_t type,
457 page_size_t *page_size)
458 {
459 for (; context; context = context->parent)
460 {
461 if (context->modifiers [type].has_page_size)
462 {
463 * page_size = context->modifiers [type].page_size;
464 return (1);
465 }
466 if (context->modifiers [INPUT_MODIFIER_ALL].has_page_size)
467 {
468 * page_size = context->modifiers [INPUT_MODIFIER_ALL].page_size;
469 return (1);
470 }
471 }
472 return (0); /* default */
473 }
475 static char *get_output_file (output_context_t *context)
476 {
477 for (; context; context = context->parent)
478 if (context->output_file)
479 return (context->output_file);
480 fprintf (stderr, "no output file found\n");
481 exit (2);
482 }
484 static pdf_file_attributes_t *get_output_file_attributes (output_context_t *context)
485 {
486 for (; context; context = context->parent)
487 if (context->output_file)
488 return (& context->file_attributes);
489 fprintf (stderr, "no output file found\n");
490 exit (2);
491 }
493 static page_label_t *get_output_page_label (output_context_t *context)
494 {
495 for (; context; context = context->parent)
496 if (context->has_page_label)
497 return (& context->page_label);
498 return (NULL); /* default */
499 }
502 #ifdef SEMANTIC_DEBUG
503 void dump_input_tree (void)
504 {
505 input_image_t *image;
506 int i;
508 printf ("input images:\n");
509 for (image = first_input_image; image; image = image->next)
510 for (i = image->range.first; i <= image->range.last; i++)
511 {
512 input_modifier_type_t parity = (i % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN;
513 boolean has_rotation, has_page_size;
514 int rotation;
515 page_size_t page_size;
517 has_rotation = get_input_rotation (image->input_context,
518 parity,
519 & rotation);
520 has_page_size = get_input_page_size (image->input_context,
521 parity,
522 & page_size);
523 printf ("file '%s' image %d",
524 get_input_file (image->input_context),
525 i);
526 if (has_rotation)
527 printf (" rotation %d", rotation);
528 if (has_page_size)
529 printf (" size %f, %f", page_size.width, page_size.height);
530 printf ("\n");
531 printf ("context: %08x\n", image->input_context);
532 }
533 }
535 void dump_output_tree (void)
536 {
537 int i;
538 output_page_t *page;
539 bookmark_t *bookmark;
541 printf ("output pages:\n");
542 for (page = first_output_page; page; page = page->next)
543 {
544 if (page->bookmark_list)
545 {
546 for (bookmark = page->bookmark_list; bookmark; bookmark = bookmark->next)
547 printf ("bookmark %d \"%s\"\n", bookmark->level, bookmark->name);
548 }
549 for (i = page->range.first; i <= page->range.last; i++)
550 {
551 page_label_t *label = get_output_page_label (page->output_context);
552 printf ("file \"%s\" ", get_output_file (page->output_context));
553 if (label)
554 {
555 printf ("label ");
556 if (label->prefix)
557 printf ("\"%s\" ", label->prefix);
558 if (label->style)
559 printf ("'%c' ", label->style);
560 }
561 printf ("page %d\n", i);
562 }
563 }
564 }
565 #endif /* SEMANTIC_DEBUG */
568 static inline int range_count (range_t range)
569 {
570 return ((range.last - range.first) + 1);
571 }
574 boolean parse_spec_file (char *fn)
575 {
576 boolean result = 0;
578 yyin = fopen (fn, "r");
579 if (! yyin)
580 {
581 fprintf (stderr, "can't open spec file '%s'\n", fn);
582 goto fail;
583 }
585 line = 1;
587 input_push_context (); /* create root input context */
588 input_push_context (); /* create inital input context */
590 output_push_context (); /* create root output context */
591 output_push_context (); /* create initial output context */
593 yyparse ();
595 if (first_input_context->image_count != first_output_context->page_count)
596 {
597 fprintf (stderr, "input image count %d != output page count %d\n",
598 first_input_context->image_count,
599 first_output_context->page_count);
600 goto fail;
601 }
603 fprintf (stderr, "%d pages specified\n", first_input_context->image_count);
605 result = 1;
607 #ifdef SEMANTIC_DEBUG
608 dump_input_tree ();
609 dump_output_tree ();
610 #endif /* SEMANTIC_DEBUG */
612 fail:
613 if (yyin)
614 fclose (yyin);
616 return (result);
617 }
620 boolean process_specs (void)
621 {
622 input_image_t *image = NULL;
623 output_page_t *page = NULL;
624 int i = 0;
625 int p = 0;
626 int page_index = 0;
627 input_attributes_t input_attributes;
628 input_modifier_type_t parity;
629 page_label_t *page_label;
631 for (;;)
632 {
633 if ((! image) || (i >= range_count (image->range)))
634 {
635 if (image)
636 image = image->next;
637 else
638 image = first_input_image;
639 if (! image)
640 return (0);
641 i = 0;
642 if (! open_tiff_input_file (get_input_file (image->input_context)))
643 return (0);
644 }
646 if ((! page) || (p >= range_count (page->range)))
647 {
648 if (page)
649 page = page->next;
650 else
651 page = first_output_page;
652 p = 0;
653 if (! open_pdf_output_file (get_output_file (page->output_context),
654 get_output_file_attributes (page->output_context)))
655 return (0);
656 page_label = get_output_page_label (page->output_context);
657 process_page_numbers (page_index,
658 range_count (page->range),
659 page->range.first,
660 page_label);
661 }
663 parity = ((image->range.first + i) % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN;
665 memset (& input_attributes, 0, sizeof (input_attributes));
667 input_attributes.rotation = 0;
668 input_attributes.has_rotation = get_input_rotation (image->input_context,
669 parity,
670 & input_attributes.rotation);
672 input_attributes.has_page_size = get_input_page_size (image->input_context,
673 parity,
674 & input_attributes.page_size);
676 process_page (image->range.first + i,
677 input_attributes,
678 page->bookmark_list);
679 i++;
680 p++;
681 page_index++;
682 }
684 return (1);
685 }