Thu, 20 Feb 2003 12:20:28 +0000
fix includes.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
5 #include "pdf.h"
6 #include "pdf_util.h"
7 #include "pdf_prim.h"
8 #include "pdf_private.h"
11 struct pdf_array_elem
12 {
13 struct pdf_array_elem *next;
14 struct pdf_obj *val;
15 };
18 struct pdf_array
19 {
20 struct pdf_array_elem *first;
21 struct pdf_array_elem *last;
22 };
25 struct pdf_dict_entry
26 {
27 struct pdf_dict_entry *next;
28 char *key;
29 struct pdf_obj *val;
30 };
33 struct pdf_dict
34 {
35 struct pdf_dict_entry *first;
36 };
39 struct pdf_stream
40 {
41 struct pdf_obj *stream_dict;
42 struct pdf_obj *length;
43 pdf_stream_write_callback callback;
44 void *app_data; /* arg to pass to callback */
45 struct pdf_obj *filters; /* name or array of names */
46 struct pdf_obj *decode_parms;
47 };
50 struct pdf_obj
51 {
52 /* these fields only apply to indirectly referenced objects */
53 struct pdf_obj *prev;
54 struct pdf_obj *next;
55 unsigned long obj_num;
56 unsigned long obj_gen;
57 long int file_offset;
59 /* these fields apply to all objects */
60 unsigned long ref_count;
61 pdf_obj_type type;
62 union {
63 int bool;
64 char *name;
65 char *string;
66 unsigned long integer;
67 double real;
68 struct pdf_obj *ind_ref;
69 struct pdf_dict dict;
70 struct pdf_array array;
71 struct pdf_stream stream;
72 } val;
73 };
76 struct pdf_obj *ref (struct pdf_obj *obj)
77 {
78 obj->ref_count++;
79 return (obj);
80 }
83 void unref (struct pdf_obj *obj)
84 {
85 if ((--obj->ref_count) == 0)
86 {
87 /* $$$ free the object */
88 }
89 }
92 struct pdf_obj *pdf_deref_ind_obj (struct pdf_obj *ind_obj)
93 {
94 pdf_assert (ind_obj->type == PT_IND_REF);
95 return (ind_obj->val.ind_ref);
96 }
99 void pdf_set_dict_entry (struct pdf_obj *dict_obj, char *key, struct pdf_obj *val)
100 {
101 struct pdf_dict_entry *entry;
103 if (dict_obj->type == PT_IND_REF)
104 dict_obj = pdf_deref_ind_obj (dict_obj);
106 pdf_assert (dict_obj->type == PT_DICTIONARY);
108 /* replacing existing entry? */
109 for (entry = dict_obj->val.dict.first; entry; entry = entry->next)
110 if (strcmp (entry->key, key) == 0)
111 {
112 unref (entry->val);
113 entry->val = ref (val);
114 return;
115 }
117 /* new entry */
118 entry = pdf_calloc (sizeof (struct pdf_dict_entry));
120 entry->next = dict_obj->val.dict.first;
121 dict_obj->val.dict.first = entry;
123 entry->key = pdf_strdup (key);
124 entry->val = ref (val);
125 }
128 struct pdf_obj *pdf_get_dict_entry (struct pdf_obj *dict_obj, char *key)
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 for (entry = dict_obj->val.dict.first; entry; entry = entry->next)
138 if (strcmp (entry->key, key) == 0)
139 return (entry->val);
141 return (NULL);
142 }
145 void pdf_add_array_elem (struct pdf_obj *array_obj, struct pdf_obj *val)
146 {
147 struct pdf_array_elem *elem = pdf_calloc (sizeof (struct pdf_array_elem));
149 if (array_obj->type == PT_IND_REF)
150 array_obj = pdf_deref_ind_obj (array_obj);
152 pdf_assert (array_obj->type == PT_ARRAY);
154 elem->val = ref (val);
156 if (! array_obj->val.array.first)
157 array_obj->val.array.first = elem;
158 else
159 array_obj->val.array.last->next = elem;
161 array_obj->val.array.last = elem;
162 }
165 struct pdf_obj *pdf_new_obj (pdf_obj_type type)
166 {
167 struct pdf_obj *obj = pdf_calloc (sizeof (struct pdf_obj));
168 obj->type = type;
169 return (obj);
170 }
173 struct pdf_obj *pdf_new_bool (int bool)
174 {
175 struct pdf_obj *obj = pdf_new_obj (PT_BOOL);
176 obj->val.bool = bool;
177 return (obj);
178 }
181 struct pdf_obj *pdf_new_name (char *name)
182 {
183 struct pdf_obj *obj = pdf_new_obj (PT_NAME);
184 obj->val.name = pdf_strdup (name);
185 return (obj);
186 }
189 struct pdf_obj *pdf_new_string (char *str)
190 {
191 struct pdf_obj *obj = pdf_new_obj (PT_STRING);
192 obj->val.string = pdf_strdup (str);
193 return (obj);
194 }
197 struct pdf_obj *pdf_new_integer (unsigned long val)
198 {
199 struct pdf_obj *obj = pdf_new_obj (PT_INTEGER);
200 obj->val.integer = val;
201 return (obj);
202 }
205 struct pdf_obj *pdf_new_real (double val)
206 {
207 struct pdf_obj *obj = pdf_new_obj (PT_REAL);
208 obj->val.real = val;
209 return (obj);
210 }
213 struct pdf_obj *pdf_new_stream (pdf_file_handle pdf_file,
214 struct pdf_obj *stream_dict,
215 pdf_stream_write_callback callback,
216 void *app_data)
217 {
218 struct pdf_obj *obj = pdf_new_obj (PT_STREAM);
220 obj->val.stream.stream_dict = stream_dict;
221 obj->val.stream.length = pdf_new_ind_ref (pdf_file, pdf_new_integer (0));
222 pdf_set_dict_entry (obj->val.stream.stream_dict, "Length", obj->val.stream.length);
224 obj->val.stream.callback = callback;
225 obj->val.stream.app_data = app_data;
226 return (obj);
227 }
230 /* $$$ currently limited to one filter per stream */
231 void pdf_stream_add_filter (struct pdf_obj *stream,
232 char *filter_name,
233 struct pdf_obj *decode_parms)
234 {
235 if (stream->type == PT_IND_REF)
236 stream = pdf_deref_ind_obj (stream);
238 pdf_assert (stream->type == PT_STREAM);
240 pdf_set_dict_entry (stream->val.stream.stream_dict, "Filter", pdf_new_name (filter_name));
241 if (decode_parms)
242 pdf_set_dict_entry (stream->val.stream.stream_dict, "DecodeParms", decode_parms);
243 }
246 struct pdf_obj *pdf_new_ind_ref (pdf_file_handle pdf_file, struct pdf_obj *obj)
247 {
248 struct pdf_obj *ind_obj;
250 pdf_assert (obj->type != PT_IND_REF);
252 ind_obj = pdf_new_obj (PT_IND_REF);
254 ind_obj->type = PT_IND_REF;
255 ind_obj->val.ind_ref = obj;
257 /* is there already an indirect reference to this object? */
258 if (! obj->obj_num)
259 {
260 /* no, assign object number/generation and add to linked list */
261 if (! pdf_file->first_ind_obj)
262 {
263 obj->obj_num = 1;
264 pdf_file->first_ind_obj = pdf_file->last_ind_obj = obj;
265 }
266 else
267 {
268 obj->obj_num = pdf_file->last_ind_obj->obj_num + 1;
269 pdf_file->last_ind_obj->next = obj;
270 obj->prev = pdf_file->last_ind_obj;
271 pdf_file->last_ind_obj = obj;
272 }
273 }
275 return (ind_obj);
276 }
279 unsigned long pdf_get_integer (struct pdf_obj *obj)
280 {
281 if (obj->type == PT_IND_REF)
282 obj = pdf_deref_ind_obj (obj);
284 pdf_assert (obj->type == PT_INTEGER);
286 return (obj->val.integer);
287 }
289 void pdf_set_integer (struct pdf_obj *obj, unsigned long val)
290 {
291 if (obj->type == PT_IND_REF)
292 obj = pdf_deref_ind_obj (obj);
294 pdf_assert (obj->type == PT_INTEGER);
296 obj->val.integer = val;
297 }
300 double pdf_get_real (struct pdf_obj *obj)
301 {
302 if (obj->type == PT_IND_REF)
303 obj = pdf_deref_ind_obj (obj);
305 pdf_assert (obj->type == PT_REAL);
307 return (obj->val.real);
308 }
310 void pdf_set_real (struct pdf_obj *obj, double val)
311 {
312 if (obj->type == PT_IND_REF)
313 obj = pdf_deref_ind_obj (obj);
315 pdf_assert (obj->type == PT_REAL);
317 obj->val.real = val;
318 }
321 static int name_char_needs_quoting (char c)
322 {
323 return ((c < '!') || (c > '~') || (c == '/') || (c == '\\') ||
324 (c == '(') || (c == ')') || (c == '<') || (c == '>') ||
325 (c == '[') || (c == ']') || (c == '{') || (c == '}') ||
326 (c == '%'));
327 }
330 void pdf_write_name (pdf_file_handle pdf_file, char *s)
331 {
332 fprintf (pdf_file->f, "/");
333 while (*s)
334 if (name_char_needs_quoting (*s))
335 fprintf (pdf_file->f, "#%02x", 0xff & *(s++));
336 else
337 fprintf (pdf_file->f, "%c", *(s++));
338 fprintf (pdf_file->f, " ");
339 }
342 static int string_char_needs_quoting (char c)
343 {
344 return ((c < ' ') || (c > '~') || (c == '\\') ||
345 (c == '(') || (c == ')'));
346 }
349 void pdf_write_string (pdf_file_handle pdf_file, char *s)
350 {
351 fprintf (pdf_file->f, "(");
352 while (*s)
353 if (string_char_needs_quoting (*s))
354 fprintf (pdf_file->f, "\\%03o", 0xff & *(s++));
355 else
356 fprintf (pdf_file->f, "%c", *(s++));
357 fprintf (pdf_file->f, ") ");
358 }
361 void pdf_write_real (pdf_file_handle pdf_file, double num)
362 {
363 /* $$$ not actually good enough, precision needs to be variable,
364 and no exponent is allowed */
365 fprintf (pdf_file->f, "%0f ", num);
366 }
369 void pdf_write_ind_ref (pdf_file_handle pdf_file, struct pdf_obj *ind_obj)
370 {
371 struct pdf_obj *obj = pdf_deref_ind_obj (ind_obj);
372 fprintf (pdf_file->f, "%ld %ld R ", obj->obj_num, obj->obj_gen);
373 }
376 void pdf_write_array (pdf_file_handle pdf_file, struct pdf_obj *array_obj)
377 {
378 struct pdf_array_elem *elem;
380 pdf_assert (array_obj->type == PT_ARRAY);
382 fprintf (pdf_file->f, "[ ");
383 for (elem = array_obj->val.array.first; elem; elem = elem->next)
384 {
385 pdf_write_obj (pdf_file, elem->val);
386 fprintf (pdf_file->f, " ");
387 }
388 fprintf (pdf_file->f, "] ");
389 }
392 void pdf_write_dict (pdf_file_handle pdf_file, struct pdf_obj *dict_obj)
393 {
394 struct pdf_dict_entry *entry;
396 pdf_assert (dict_obj->type == PT_DICTIONARY);
398 fprintf (pdf_file->f, "<<\r\n");
399 for (entry = dict_obj->val.dict.first; entry; entry = entry->next)
400 {
401 pdf_write_name (pdf_file, entry->key);
402 fprintf (pdf_file->f, " ");
403 pdf_write_obj (pdf_file, entry->val);
404 fprintf (pdf_file->f, "\r\n");
405 }
406 fprintf (pdf_file->f, ">>\r\n");
407 }
410 void pdf_stream_write_data (pdf_file_handle pdf_file,
411 struct pdf_obj *stream,
412 char *data,
413 unsigned long len)
414 {
415 while (len)
416 {
417 unsigned long l2 = fwrite (data, 1, len, pdf_file->f);
418 data += l2;
419 len -= l2;
420 if (ferror (pdf_file->f))
421 pdf_fatal ("error writing stream data\n");
422 }
423 }
426 void pdf_write_stream (pdf_file_handle pdf_file, struct pdf_obj *stream)
427 {
428 unsigned long begin_pos, end_pos;
430 pdf_assert (stream->type == PT_STREAM);
432 pdf_write_dict (pdf_file, stream->val.stream.stream_dict);
433 fprintf (pdf_file->f, "stream\r\n");
434 begin_pos = ftell (pdf_file->f);
435 stream->val.stream.callback (pdf_file,
436 stream,
437 stream->val.stream.app_data);
438 end_pos = ftell (pdf_file->f);
439 fprintf (pdf_file->f, "\r\nendstream\r\n");
441 pdf_set_integer (stream->val.stream.length, end_pos - begin_pos);
442 }
445 void pdf_write_obj (pdf_file_handle pdf_file, struct pdf_obj *obj)
446 {
447 switch (obj->type)
448 {
449 case PT_NULL:
450 fprintf (pdf_file->f, "null ");
451 break;
452 case PT_BOOL:
453 if (obj->val.bool)
454 fprintf (pdf_file->f, "true ");
455 else
456 fprintf (pdf_file->f, "false ");
457 break;
458 case PT_NAME:
459 pdf_write_name (pdf_file, obj->val.name);
460 break;
461 case PT_STRING:
462 pdf_write_string (pdf_file, obj->val.string);
463 break;
464 case PT_INTEGER:
465 fprintf (pdf_file->f, "%ld ", obj->val.integer);
466 break;
467 case PT_REAL:
468 pdf_write_real (pdf_file, obj->val.real);
469 break;
470 case PT_IND_REF:
471 pdf_write_ind_ref (pdf_file, obj);
472 break;
473 case PT_DICTIONARY:
474 pdf_write_dict (pdf_file, obj);
475 break;
476 case PT_ARRAY:
477 pdf_write_array (pdf_file, obj);
478 break;
479 case PT_STREAM:
480 pdf_write_stream (pdf_file, obj);
481 break;
482 default:
483 pdf_fatal ("bad object type\n");
484 }
485 }
488 void pdf_write_ind_obj (pdf_file_handle pdf_file, struct pdf_obj *ind_obj)
489 {
490 struct pdf_obj *obj;
492 if (ind_obj->type == PT_IND_REF)
493 obj = pdf_deref_ind_obj (ind_obj);
494 else
495 obj = ind_obj;
497 obj->file_offset = ftell (pdf_file->f);
498 fprintf (pdf_file->f, "%ld %ld obj\r\n", obj->obj_num, obj->obj_gen);
499 pdf_write_obj (pdf_file, obj);
500 fprintf (pdf_file->f, "endobj\r\n");
501 }
504 void pdf_write_all_ind_obj (pdf_file_handle pdf_file)
505 {
506 struct pdf_obj *ind_obj;
507 for (ind_obj = pdf_file->first_ind_obj; ind_obj; ind_obj = ind_obj->next)
508 if (! ind_obj->file_offset)
509 pdf_write_ind_obj (pdf_file, ind_obj);
510 }
513 unsigned long pdf_write_xref (pdf_file_handle pdf_file)
514 {
515 struct pdf_obj *ind_obj;
516 pdf_file->xref_offset = ftell (pdf_file->f);
517 fprintf (pdf_file->f, "xref\r\n");
518 fprintf (pdf_file->f, "0 %ld\r\n", pdf_file->last_ind_obj->obj_num + 1);
519 fprintf (pdf_file->f, "0000000000 65535 f\r\n");
520 for (ind_obj = pdf_file->first_ind_obj; ind_obj; ind_obj = ind_obj->next)
521 fprintf (pdf_file->f, "%010ld 00000 n\r\n", ind_obj->file_offset);
522 return (pdf_file->last_ind_obj->obj_num + 1);
523 }