Tue, 01 Jan 2002 05:02:44 +0000
create temporary TIFF file.
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_size;
14 page_size_t 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 bookmark_t *first_bookmark;
56 bookmark_t *last_bookmark;
58 boolean has_page_label;
59 page_label_t page_label;
60 } output_context_t;
63 typedef struct output_page_t
64 {
65 struct output_page_t *next;
66 output_context_t *output_context;
67 range_t range;
68 bookmark_t *bookmark_list;
69 } output_page_t;
72 #define SEMANTIC_DEBUG
73 #ifdef SEMANTIC_DEBUG
74 #define SDBG(x) printf x
75 #else
76 #define SDBG(x)
77 #endif
80 FILE *yyin;
81 int line; /* line number in spec file */
83 int bookmark_level;
85 input_context_t *first_input_context;
86 input_context_t *last_input_context;
88 input_modifier_type_t current_modifier_context;
90 input_image_t *first_input_image;
91 input_image_t *last_input_image;
93 output_context_t *first_output_context;
94 output_context_t *last_output_context;
96 output_page_t *first_output_page;
97 output_page_t *last_output_page;
100 void input_push_context (void)
101 {
102 input_context_t *new_input_context;
104 new_input_context = malloc (sizeof (input_context_t));
105 if (! new_input_context)
106 {
107 fprintf (stderr, "failed to malloc an input context\n");
108 return;
109 }
111 if (last_input_context)
112 {
113 memcpy (new_input_context, last_input_context, sizeof (input_context_t));
114 new_input_context->image_count = 0;
115 }
116 else
117 {
118 memset (new_input_context, 0, sizeof (input_context_t));
119 first_input_context = new_input_context;
120 }
122 new_input_context->parent = last_input_context;
123 last_input_context = new_input_context;
124 };
126 void input_pop_context (void)
127 {
128 if (! last_input_context)
129 {
130 fprintf (stderr, "failed to pop an input context\n");
131 return;
132 }
134 last_input_context = last_input_context->parent;
135 };
137 void input_set_modifier_context (input_modifier_type_t type)
138 {
139 current_modifier_context = type;
140 #ifdef SEMANTIC_DEBUG
141 SDBG(("modifier type "));
142 switch (type)
143 {
144 case INPUT_MODIFIER_ALL: SDBG(("all")); break;
145 case INPUT_MODIFIER_ODD: SDBG(("odd")); break;
146 case INPUT_MODIFIER_EVEN: SDBG(("even")); break;
147 default: SDBG(("unknown %d", type));
148 }
149 SDBG(("\n"));
150 #endif /* SEMANTIC_DEBUG */
151 }
153 static void input_clone (void)
154 {
155 input_context_t *new_input_context;
157 if (! last_input_context->image_count)
158 return;
160 new_input_context = malloc (sizeof (input_context_t));
161 if (! new_input_context)
162 {
163 fprintf (stderr, "failed to malloc an input context\n");
164 return;
165 }
167 memcpy (new_input_context, last_input_context, sizeof (input_context_t));
168 new_input_context->image_count = 0;
169 last_input_context->next = new_input_context;
170 }
172 void input_set_file (char *name)
173 {
174 input_clone ();
175 last_input_context->input_file = name;
176 };
178 void input_set_rotation (int rotation)
179 {
180 last_input_context->modifiers [current_modifier_context].has_rotation = 1;
181 last_input_context->modifiers [current_modifier_context].rotation = rotation;
182 SDBG(("rotation %d\n", rotation));
183 }
185 static void increment_input_image_count (int count)
186 {
187 input_context_t *context;
189 for (context = last_input_context; context; context = context->parent)
190 context->image_count += count;
191 }
193 void input_images (range_t range)
194 {
195 input_image_t *new_image;
196 int count = ((range.last - range.first) + 1);
198 #ifdef SEMANTIC_DEBUG
199 if (range.first == range.last)
200 SDBG(("image %d\n", range.first));
201 else
202 SDBG(("images %d..%d\n", range.first, range.last));
203 #endif /* SEMANTIC_DEBUG */
205 new_image = calloc (1, sizeof (input_image_t));
206 if (! new_image)
207 {
208 fprintf (stderr, "failed to malloc an input image struct\n");
209 return;
210 }
211 if (first_input_image)
212 {
213 last_input_image->next = new_image;
214 last_input_image = new_image;
215 }
216 else
217 {
218 first_input_image = last_input_image = new_image;
219 }
220 new_image->range = range;
221 new_image->input_context = last_input_context;
222 increment_input_image_count (count);
223 }
226 void output_push_context (void)
227 {
228 output_context_t *new_output_context;
230 new_output_context = malloc (sizeof (output_context_t));
231 if (! new_output_context)
232 {
233 fprintf (stderr, "failed to malloc an output context\n");
234 return;
235 }
237 if (last_output_context)
238 {
239 memcpy (new_output_context, last_output_context, sizeof (output_context_t));
240 new_output_context->page_count = 0;
241 new_output_context->first_bookmark = NULL;
242 new_output_context->last_bookmark = NULL;
243 }
244 else
245 {
246 memset (new_output_context, 0, sizeof (output_context_t));
247 first_output_context = new_output_context;
248 }
250 new_output_context->parent = last_output_context;
251 last_output_context = new_output_context;
252 };
254 void output_pop_context (void)
255 {
256 if (! last_output_context)
257 {
258 fprintf (stderr, "failed to pop an output context\n");
259 return;
260 }
262 last_output_context = last_output_context->parent;
263 };
265 static void output_clone (void)
266 {
267 output_context_t *new_output_context;
269 if (! last_output_context->page_count)
270 return;
272 new_output_context = malloc (sizeof (output_context_t));
273 if (! new_output_context)
274 {
275 fprintf (stderr, "failed to malloc an output context\n");
276 return;
277 }
279 memcpy (new_output_context, last_output_context, sizeof (output_context_t));
280 new_output_context->page_count = 0;
281 last_output_context->next = new_output_context;
282 }
284 void output_set_file (char *name)
285 {
286 output_clone ();
287 last_output_context->output_file = name;
288 };
290 void output_set_bookmark (char *name)
291 {
292 bookmark_t *new_bookmark;
294 /* As the language is defined (parser.y), a bookmark can only appear
295 at the beginning of a context! */
296 if (last_output_context->page_count)
297 {
298 fprintf (stderr, "internal error, bookmark not at beginning of context\n");
299 exit (2);
300 }
302 new_bookmark = calloc (1, sizeof (bookmark_t));
303 if (! new_bookmark)
304 {
305 fprintf (stderr, "failed to calloc a bookmark\n");
306 return;
307 }
309 new_bookmark->level = bookmark_level;
310 new_bookmark->name = name;
311 if (last_output_context->first_bookmark)
312 last_output_context->last_bookmark->next = new_bookmark;
313 else
314 last_output_context->first_bookmark = new_bookmark;
315 last_output_context->last_bookmark = new_bookmark;
316 }
318 void output_set_page_label (page_label_t label)
319 {
320 output_clone ();
321 last_output_context->has_page_label = 1;
322 last_output_context->page_label = label;
323 }
325 static void increment_output_page_count (int count)
326 {
327 output_context_t *context;
329 for (context = last_output_context; context; context = context->parent)
330 context->page_count += count;
331 }
334 void output_pages (range_t range)
335 {
336 output_page_t *new_page;
337 output_context_t *context;
338 int count = ((range.last - range.first) + 1);
340 #ifdef SEMANTIC_DEBUG
341 if (range.first == range.last)
342 SDBG(("page %d\n", range.first));
343 else
344 SDBG(("pages %d..%d\n", range.first, range.last));
345 #endif /* SEMANTIC_DEBUG */
347 new_page = calloc (1, sizeof (output_page_t));
348 if (! new_page)
349 {
350 fprintf (stderr, "failed to malloc an output page struct\n");
351 return;
352 }
353 if (first_output_page)
354 {
355 last_output_page->next = new_page;
356 last_output_page = new_page;
357 }
358 else
359 {
360 first_output_page = last_output_page = new_page;
361 }
362 new_page->range = range;
363 new_page->output_context = last_output_context;
365 /* transfer bookmarks from context(s) to page */
366 for (context = last_output_context; context; context = context->parent)
367 if (context->first_bookmark)
368 {
369 context->last_bookmark->next = new_page->bookmark_list;
370 new_page->bookmark_list = context->first_bookmark;
371 context->first_bookmark = NULL;
372 context->last_bookmark = NULL;
373 }
375 increment_output_page_count (count);
376 }
379 void yyerror (char *s)
380 {
381 fprintf (stderr, "%d: %s\n", line, s);
382 }
385 static char *get_input_file (input_context_t *context)
386 {
387 for (; context; context = context->parent)
388 if (context->input_file)
389 return (context->input_file);
390 fprintf (stderr, "no input file name found\n");
391 exit (2);
392 }
394 static int get_input_rotation (input_context_t *context, input_modifier_type_t type)
395 {
396 for (; context; context = context->parent)
397 {
398 if (context->modifiers [type].has_rotation)
399 return (context->modifiers [type].rotation);
400 if (context->modifiers [INPUT_MODIFIER_ALL].has_rotation)
401 return (context->modifiers [INPUT_MODIFIER_ALL].rotation);
402 }
403 return (0); /* default */
404 }
406 static char *get_output_file (output_context_t *context)
407 {
408 for (; context; context = context->parent)
409 if (context->output_file)
410 return (context->output_file);
411 fprintf (stderr, "no output file name found\n");
412 exit (2);
413 }
415 static page_label_t *get_output_page_label (output_context_t *context)
416 {
417 for (; context; context = context->parent)
418 if (context->has_page_label)
419 return (& context->page_label);
420 return (NULL); /* default */
421 }
424 #ifdef SEMANTIC_DEBUG
425 void dump_input_tree (void)
426 {
427 input_image_t *image;
428 int i;
430 printf ("input images:\n");
431 for (image = first_input_image; image; image = image->next)
432 for (i = image->range.first; i <= image->range.last; i++)
433 {
434 input_modifier_type_t parity = (i % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN;
435 printf ("file '%s' image %d, rotation %d\n",
436 get_input_file (image->input_context),
437 i,
438 get_input_rotation (image->input_context, parity));
439 }
440 }
442 void dump_output_tree (void)
443 {
444 int i;
445 output_page_t *page;
446 bookmark_t *bookmark;
448 printf ("output pages:\n");
449 for (page = first_output_page; page; page = page->next)
450 {
451 if (page->bookmark_list)
452 {
453 for (bookmark = page->bookmark_list; bookmark; bookmark = bookmark->next)
454 printf ("bookmark %d \"%s\"\n", bookmark->level, bookmark->name);
455 }
456 for (i = page->range.first; i <= page->range.last; i++)
457 {
458 page_label_t *label = get_output_page_label (page->output_context);
459 printf ("file \"%s\" ", get_output_file (page->output_context));
460 if (label)
461 {
462 printf ("label ");
463 if (label->prefix)
464 printf ("\"%s\" ", label->prefix);
465 if (label->style)
466 printf ("'%c' ", label->style);
467 }
468 printf ("page %d\n", i);
469 }
470 }
471 }
472 #endif /* SEMANTIC_DEBUG */
475 static inline int range_count (range_t range)
476 {
477 return ((range.last - range.first) + 1);
478 }
481 boolean parse_spec_file (char *fn)
482 {
483 boolean result = 0;
485 yyin = fopen (fn, "r");
486 if (! yyin)
487 {
488 fprintf (stderr, "can't open spec file '%s'\n", fn);
489 goto fail;
490 }
492 line = 1;
494 input_push_context (); /* create root input context */
495 input_push_context (); /* create inital input context */
497 output_push_context (); /* create root output context */
498 output_push_context (); /* create initial output context */
500 yyparse ();
502 if (first_input_context->image_count != first_output_context->page_count)
503 {
504 fprintf (stderr, "input image count %d != output page count %d\n",
505 first_input_context->image_count,
506 first_output_context->page_count);
507 goto fail;
508 }
510 fprintf (stderr, "%d pages specified\n", first_input_context->image_count);
512 result = 1;
514 #ifdef SEMANTIC_DEBUG
515 dump_input_tree ();
516 dump_output_tree ();
517 #endif /* SEMANTIC_DEBUG */
519 fail:
520 if (yyin)
521 fclose (yyin);
523 return (result);
524 }
527 boolean process_specs (void)
528 {
529 input_image_t *image = NULL;
530 output_page_t *page = NULL;
531 int i = 0;
532 int p = 0;
533 int page_index = 0;
534 input_attributes_t input_attributes;
535 input_modifier_type_t parity;
536 page_label_t *page_label;
538 for (;;)
539 {
540 if ((! image) || (i >= range_count (image->range)))
541 {
542 if (image)
543 image = image->next;
544 else
545 image = first_input_image;
546 if (! image)
547 return (0);
548 i = 0;
549 if (! open_tiff_input_file (get_input_file (image->input_context)))
550 return (0);
551 }
553 if ((! page) || (p >= range_count (page->range)))
554 {
555 if (page)
556 page = page->next;
557 else
558 page = first_output_page;
559 p = 0;
560 if (! open_pdf_output_file (get_output_file (page->output_context)))
561 return (0);
562 page_label = get_output_page_label (page->output_context);
563 process_page_numbers (page_index,
564 range_count (page->range),
565 page->range.first,
566 page_label);
567 }
569 parity = ((image->range.first + i) % 2) ? INPUT_MODIFIER_ODD : INPUT_MODIFIER_EVEN;
571 memset (& input_attributes, 0, sizeof (input_attributes));
572 input_attributes.rotation = get_input_rotation (image->input_context,
573 parity);;
575 process_page (image->range.first + i,
576 input_attributes,
577 page->bookmark_list);
578 i++;
579 p++;
580 page_index++;
581 }
583 return (1);
584 }