Fri, 21 Feb 2003 09:01:33 +0000
added image position and size arguments to pdf_write_g4_fax_image.
1 /*
2 * t2p: Create a PDF file from the contents of one or more TIFF
3 * bilevel image files. The images in the resulting PDF file
4 * will be compressed using ITU-T T.6 (G4) fax encoding.
5 *
6 * PDF routines
7 * $Id: pdf_prim.c,v 1.3 2003/02/20 04:44:17 eric Exp $
8 * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation. Note that permission is
13 * not granted to redistribute this program under the terms of any
14 * other version of the General Public License.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
24 */
27 #include <stdbool.h>
28 #include <stdint.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
33 #include "bitblt.h"
34 #include "pdf.h"
35 #include "pdf_util.h"
36 #include "pdf_prim.h"
37 #include "pdf_private.h"
40 struct pdf_array_elem
41 {
42 struct pdf_array_elem *next;
43 struct pdf_obj *val;
44 };
47 struct pdf_array
48 {
49 struct pdf_array_elem *first;
50 struct pdf_array_elem *last;
51 };
54 struct pdf_dict_entry
55 {
56 struct pdf_dict_entry *next;
57 char *key;
58 struct pdf_obj *val;
59 };
62 struct pdf_dict
63 {
64 struct pdf_dict_entry *first;
65 };
68 struct pdf_stream
69 {
70 struct pdf_obj *stream_dict;
71 struct pdf_obj *length;
72 pdf_stream_write_callback callback;
73 void *app_data; /* arg to pass to callback */
74 struct pdf_obj *filters; /* name or array of names */
75 struct pdf_obj *decode_parms;
76 };
79 struct pdf_obj
80 {
81 /* these fields only apply to indirectly referenced objects */
82 struct pdf_obj *prev;
83 struct pdf_obj *next;
84 unsigned long obj_num;
85 unsigned long obj_gen;
86 long int file_offset;
88 /* these fields apply to all objects */
89 unsigned long ref_count;
90 pdf_obj_type type;
91 union {
92 bool boolean;
93 char *name;
94 char *string;
95 unsigned long integer;
96 double real;
97 struct pdf_obj *ind_ref;
98 struct pdf_dict dict;
99 struct pdf_array array;
100 struct pdf_stream stream;
101 } val;
102 };
105 struct pdf_obj *ref (struct pdf_obj *obj)
106 {
107 obj->ref_count++;
108 return (obj);
109 }
112 void unref (struct pdf_obj *obj)
113 {
114 if ((--obj->ref_count) == 0)
115 {
116 /* $$$ free the object */
117 }
118 }
121 struct pdf_obj *pdf_deref_ind_obj (struct pdf_obj *ind_obj)
122 {
123 pdf_assert (ind_obj->type == PT_IND_REF);
124 return (ind_obj->val.ind_ref);
125 }
128 void pdf_set_dict_entry (struct pdf_obj *dict_obj, char *key, struct pdf_obj *val)
129 {
130 struct pdf_dict_entry *entry;
132 if (dict_obj->type == PT_IND_REF)
133 dict_obj = pdf_deref_ind_obj (dict_obj);
135 pdf_assert (dict_obj->type == PT_DICTIONARY);
137 /* replacing existing entry? */
138 for (entry = dict_obj->val.dict.first; entry; entry = entry->next)
139 if (strcmp (entry->key, key) == 0)
140 {
141 unref (entry->val);
142 entry->val = ref (val);
143 return;
144 }
146 /* new entry */
147 entry = pdf_calloc (sizeof (struct pdf_dict_entry));
149 entry->next = dict_obj->val.dict.first;
150 dict_obj->val.dict.first = entry;
152 entry->key = pdf_strdup (key);
153 entry->val = ref (val);
154 }
157 struct pdf_obj *pdf_get_dict_entry (struct pdf_obj *dict_obj, char *key)
158 {
159 struct pdf_dict_entry *entry;
161 if (dict_obj->type == PT_IND_REF)
162 dict_obj = pdf_deref_ind_obj (dict_obj);
164 pdf_assert (dict_obj->type == PT_DICTIONARY);
166 for (entry = dict_obj->val.dict.first; entry; entry = entry->next)
167 if (strcmp (entry->key, key) == 0)
168 return (entry->val);
170 return (NULL);
171 }
174 void pdf_add_array_elem (struct pdf_obj *array_obj, struct pdf_obj *val)
175 {
176 struct pdf_array_elem *elem = pdf_calloc (sizeof (struct pdf_array_elem));
178 if (array_obj->type == PT_IND_REF)
179 array_obj = pdf_deref_ind_obj (array_obj);
181 pdf_assert (array_obj->type == PT_ARRAY);
183 elem->val = ref (val);
185 if (! array_obj->val.array.first)
186 array_obj->val.array.first = elem;
187 else
188 array_obj->val.array.last->next = elem;
190 array_obj->val.array.last = elem;
191 }
194 struct pdf_obj *pdf_new_obj (pdf_obj_type type)
195 {
196 struct pdf_obj *obj = pdf_calloc (sizeof (struct pdf_obj));
197 obj->type = type;
198 return (obj);
199 }
202 struct pdf_obj *pdf_new_bool (bool val)
203 {
204 struct pdf_obj *obj = pdf_new_obj (PT_BOOL);
205 obj->val.boolean = val;
206 return (obj);
207 }
210 struct pdf_obj *pdf_new_name (char *name)
211 {
212 struct pdf_obj *obj = pdf_new_obj (PT_NAME);
213 obj->val.name = pdf_strdup (name);
214 return (obj);
215 }
218 struct pdf_obj *pdf_new_string (char *str)
219 {
220 struct pdf_obj *obj = pdf_new_obj (PT_STRING);
221 obj->val.string = pdf_strdup (str);
222 return (obj);
223 }
226 struct pdf_obj *pdf_new_integer (unsigned long val)
227 {
228 struct pdf_obj *obj = pdf_new_obj (PT_INTEGER);
229 obj->val.integer = val;
230 return (obj);
231 }
234 struct pdf_obj *pdf_new_real (double val)
235 {
236 struct pdf_obj *obj = pdf_new_obj (PT_REAL);
237 obj->val.real = val;
238 return (obj);
239 }
242 struct pdf_obj *pdf_new_stream (pdf_file_handle pdf_file,
243 struct pdf_obj *stream_dict,
244 pdf_stream_write_callback callback,
245 void *app_data)
246 {
247 struct pdf_obj *obj = pdf_new_obj (PT_STREAM);
249 obj->val.stream.stream_dict = stream_dict;
250 obj->val.stream.length = pdf_new_ind_ref (pdf_file, pdf_new_integer (0));
251 pdf_set_dict_entry (obj->val.stream.stream_dict, "Length", obj->val.stream.length);
253 obj->val.stream.callback = callback;
254 obj->val.stream.app_data = app_data;
255 return (obj);
256 }
259 /* $$$ currently limited to one filter per stream */
260 void pdf_stream_add_filter (struct pdf_obj *stream,
261 char *filter_name,
262 struct pdf_obj *decode_parms)
263 {
264 if (stream->type == PT_IND_REF)
265 stream = pdf_deref_ind_obj (stream);
267 pdf_assert (stream->type == PT_STREAM);
269 pdf_set_dict_entry (stream->val.stream.stream_dict, "Filter", pdf_new_name (filter_name));
270 if (decode_parms)
271 pdf_set_dict_entry (stream->val.stream.stream_dict, "DecodeParms", decode_parms);
272 }
275 struct pdf_obj *pdf_new_ind_ref (pdf_file_handle pdf_file, struct pdf_obj *obj)
276 {
277 struct pdf_obj *ind_obj;
279 pdf_assert (obj->type != PT_IND_REF);
281 ind_obj = pdf_new_obj (PT_IND_REF);
283 ind_obj->type = PT_IND_REF;
284 ind_obj->val.ind_ref = obj;
286 /* is there already an indirect reference to this object? */
287 if (! obj->obj_num)
288 {
289 /* no, assign object number/generation and add to linked list */
290 if (! pdf_file->first_ind_obj)
291 {
292 obj->obj_num = 1;
293 pdf_file->first_ind_obj = pdf_file->last_ind_obj = obj;
294 }
295 else
296 {
297 obj->obj_num = pdf_file->last_ind_obj->obj_num + 1;
298 pdf_file->last_ind_obj->next = obj;
299 obj->prev = pdf_file->last_ind_obj;
300 pdf_file->last_ind_obj = obj;
301 }
302 }
304 return (ind_obj);
305 }
308 unsigned long pdf_get_integer (struct pdf_obj *obj)
309 {
310 if (obj->type == PT_IND_REF)
311 obj = pdf_deref_ind_obj (obj);
313 pdf_assert (obj->type == PT_INTEGER);
315 return (obj->val.integer);
316 }
318 void pdf_set_integer (struct pdf_obj *obj, unsigned long val)
319 {
320 if (obj->type == PT_IND_REF)
321 obj = pdf_deref_ind_obj (obj);
323 pdf_assert (obj->type == PT_INTEGER);
325 obj->val.integer = val;
326 }
329 double pdf_get_real (struct pdf_obj *obj)
330 {
331 if (obj->type == PT_IND_REF)
332 obj = pdf_deref_ind_obj (obj);
334 pdf_assert (obj->type == PT_REAL);
336 return (obj->val.real);
337 }
339 void pdf_set_real (struct pdf_obj *obj, double val)
340 {
341 if (obj->type == PT_IND_REF)
342 obj = pdf_deref_ind_obj (obj);
344 pdf_assert (obj->type == PT_REAL);
346 obj->val.real = val;
347 }
350 static int name_char_needs_quoting (char c)
351 {
352 return ((c < '!') || (c > '~') || (c == '/') || (c == '\\') ||
353 (c == '(') || (c == ')') || (c == '<') || (c == '>') ||
354 (c == '[') || (c == ']') || (c == '{') || (c == '}') ||
355 (c == '%'));
356 }
359 void pdf_write_name (pdf_file_handle pdf_file, char *s)
360 {
361 fprintf (pdf_file->f, "/");
362 while (*s)
363 if (name_char_needs_quoting (*s))
364 fprintf (pdf_file->f, "#%02x", 0xff & *(s++));
365 else
366 fprintf (pdf_file->f, "%c", *(s++));
367 fprintf (pdf_file->f, " ");
368 }
371 static int string_char_needs_quoting (char c)
372 {
373 return ((c < ' ') || (c > '~') || (c == '\\') ||
374 (c == '(') || (c == ')'));
375 }
378 void pdf_write_string (pdf_file_handle pdf_file, char *s)
379 {
380 fprintf (pdf_file->f, "(");
381 while (*s)
382 if (string_char_needs_quoting (*s))
383 fprintf (pdf_file->f, "\\%03o", 0xff & *(s++));
384 else
385 fprintf (pdf_file->f, "%c", *(s++));
386 fprintf (pdf_file->f, ") ");
387 }
390 void pdf_write_real (pdf_file_handle pdf_file, double num)
391 {
392 /* $$$ not actually good enough, precision needs to be variable,
393 and no exponent is allowed */
394 fprintf (pdf_file->f, "%0f ", num);
395 }
398 void pdf_write_ind_ref (pdf_file_handle pdf_file, struct pdf_obj *ind_obj)
399 {
400 struct pdf_obj *obj = pdf_deref_ind_obj (ind_obj);
401 fprintf (pdf_file->f, "%ld %ld R ", obj->obj_num, obj->obj_gen);
402 }
405 void pdf_write_array (pdf_file_handle pdf_file, struct pdf_obj *array_obj)
406 {
407 struct pdf_array_elem *elem;
409 pdf_assert (array_obj->type == PT_ARRAY);
411 fprintf (pdf_file->f, "[ ");
412 for (elem = array_obj->val.array.first; elem; elem = elem->next)
413 {
414 pdf_write_obj (pdf_file, elem->val);
415 fprintf (pdf_file->f, " ");
416 }
417 fprintf (pdf_file->f, "] ");
418 }
421 void pdf_write_dict (pdf_file_handle pdf_file, struct pdf_obj *dict_obj)
422 {
423 struct pdf_dict_entry *entry;
425 pdf_assert (dict_obj->type == PT_DICTIONARY);
427 fprintf (pdf_file->f, "<<\r\n");
428 for (entry = dict_obj->val.dict.first; entry; entry = entry->next)
429 {
430 pdf_write_name (pdf_file, entry->key);
431 fprintf (pdf_file->f, " ");
432 pdf_write_obj (pdf_file, entry->val);
433 fprintf (pdf_file->f, "\r\n");
434 }
435 fprintf (pdf_file->f, ">>\r\n");
436 }
439 void pdf_stream_write_data (pdf_file_handle pdf_file,
440 struct pdf_obj *stream,
441 char *data,
442 unsigned long len)
443 {
444 while (len)
445 {
446 unsigned long l2 = fwrite (data, 1, len, pdf_file->f);
447 data += l2;
448 len -= l2;
449 if (ferror (pdf_file->f))
450 pdf_fatal ("error writing stream data\n");
451 }
452 }
455 void pdf_write_stream (pdf_file_handle pdf_file, struct pdf_obj *stream)
456 {
457 unsigned long begin_pos, end_pos;
459 pdf_assert (stream->type == PT_STREAM);
461 pdf_write_dict (pdf_file, stream->val.stream.stream_dict);
462 fprintf (pdf_file->f, "stream\r\n");
463 begin_pos = ftell (pdf_file->f);
464 stream->val.stream.callback (pdf_file,
465 stream,
466 stream->val.stream.app_data);
467 end_pos = ftell (pdf_file->f);
468 fprintf (pdf_file->f, "\r\nendstream\r\n");
470 pdf_set_integer (stream->val.stream.length, end_pos - begin_pos);
471 }
474 void pdf_write_obj (pdf_file_handle pdf_file, struct pdf_obj *obj)
475 {
476 switch (obj->type)
477 {
478 case PT_NULL:
479 fprintf (pdf_file->f, "null ");
480 break;
481 case PT_BOOL:
482 if (obj->val.boolean)
483 fprintf (pdf_file->f, "true ");
484 else
485 fprintf (pdf_file->f, "false ");
486 break;
487 case PT_NAME:
488 pdf_write_name (pdf_file, obj->val.name);
489 break;
490 case PT_STRING:
491 pdf_write_string (pdf_file, obj->val.string);
492 break;
493 case PT_INTEGER:
494 fprintf (pdf_file->f, "%ld ", obj->val.integer);
495 break;
496 case PT_REAL:
497 pdf_write_real (pdf_file, obj->val.real);
498 break;
499 case PT_IND_REF:
500 pdf_write_ind_ref (pdf_file, obj);
501 break;
502 case PT_DICTIONARY:
503 pdf_write_dict (pdf_file, obj);
504 break;
505 case PT_ARRAY:
506 pdf_write_array (pdf_file, obj);
507 break;
508 case PT_STREAM:
509 pdf_write_stream (pdf_file, obj);
510 break;
511 default:
512 pdf_fatal ("bad object type\n");
513 }
514 }
517 void pdf_write_ind_obj (pdf_file_handle pdf_file, struct pdf_obj *ind_obj)
518 {
519 struct pdf_obj *obj;
521 if (ind_obj->type == PT_IND_REF)
522 obj = pdf_deref_ind_obj (ind_obj);
523 else
524 obj = ind_obj;
526 obj->file_offset = ftell (pdf_file->f);
527 fprintf (pdf_file->f, "%ld %ld obj\r\n", obj->obj_num, obj->obj_gen);
528 pdf_write_obj (pdf_file, obj);
529 fprintf (pdf_file->f, "endobj\r\n");
530 }
533 void pdf_write_all_ind_obj (pdf_file_handle pdf_file)
534 {
535 struct pdf_obj *ind_obj;
536 for (ind_obj = pdf_file->first_ind_obj; ind_obj; ind_obj = ind_obj->next)
537 if (! ind_obj->file_offset)
538 pdf_write_ind_obj (pdf_file, ind_obj);
539 }
542 unsigned long pdf_write_xref (pdf_file_handle pdf_file)
543 {
544 struct pdf_obj *ind_obj;
545 pdf_file->xref_offset = ftell (pdf_file->f);
546 fprintf (pdf_file->f, "xref\r\n");
547 fprintf (pdf_file->f, "0 %ld\r\n", pdf_file->last_ind_obj->obj_num + 1);
548 fprintf (pdf_file->f, "0000000000 65535 f\r\n");
549 for (ind_obj = pdf_file->first_ind_obj; ind_obj; ind_obj = ind_obj->next)
550 fprintf (pdf_file->f, "%010ld 00000 n\r\n", ind_obj->file_offset);
551 return (pdf_file->last_ind_obj->obj_num + 1);
552 }