diff options
Diffstat (limited to 'Build/source/texk/dvipdfm/pdfobj.c')
-rw-r--r-- | Build/source/texk/dvipdfm/pdfobj.c | 1743 |
1 files changed, 0 insertions, 1743 deletions
diff --git a/Build/source/texk/dvipdfm/pdfobj.c b/Build/source/texk/dvipdfm/pdfobj.c deleted file mode 100644 index ea0b6d0fead..00000000000 --- a/Build/source/texk/dvipdfm/pdfobj.c +++ /dev/null @@ -1,1743 +0,0 @@ -/* $Header$ - - This is dvipdfm, a DVI to PDF translator. - Copyright (C) 1998, 1999, 2008 by Mark A. Wicks - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - The author may be contacted via the e-mail address - - mwicks@kettering.edu -*/ - - -#include <ctype.h> -#include <string.h> -#include "system.h" -#include "config.h" -#include "mem.h" -#include "error.h" -#include "mfileio.h" -#include "pdflimits.h" -#include "pdfobj.h" -#include "pdfspecial.h" -#include "pdfparse.h" -#include "twiddle.h" - -#ifdef HAVE_ZLIB -#include <zlib.h> -#endif /* HAVE_ZLIB */ - -FILE *pdf_output_file = NULL; -FILE *pdf_input_file = NULL; -unsigned long pdf_output_file_position = 0, compression_saved = 0; -int pdf_output_line_position = 0; -#define FORMAT_BUF_SIZE 4096 -char format_buffer[FORMAT_BUF_SIZE]; - -static struct xref_entry -{ - unsigned long file_position; - pdf_obj *pdf_obj; -} *output_xref = NULL; -static unsigned long pdf_max_ind_objects = 0; -static unsigned long next_label = 1; - -static unsigned long startxref; - -static unsigned pdf_root_obj = 0, pdf_info_obj = 0; - -/* Internal static routines */ - -static void pdf_flush_obj (FILE *file, const pdf_obj *object); -static void pdf_label_obj (pdf_obj *object); - -static void pdf_out_char (FILE *file, char c); -static void pdf_out (FILE *file, void *buffer, int length); - -static void release_indirect (pdf_indirect *data); -static void write_indirect (FILE *file, const pdf_indirect *indirect); - -static void release_boolean (pdf_obj *data); -static void write_boolean (FILE *file, const pdf_boolean *data); - -static void write_null (FILE *file); -static void release_null (void *data); - -static void release_number (pdf_number *data); -static void write_number (FILE *file, const pdf_number - *number); - -static void write_string (FILE *file, const pdf_string *string); -static void release_string (pdf_string *data); - -static void write_name (FILE *file, const pdf_name *name); -static void release_name (pdf_name *data); - -static void write_array (FILE *file, const pdf_array *array); -static void release_array (pdf_array *data); - -static void write_dict (FILE *file, const pdf_dict *dict); -static void release_dict (pdf_dict *data); - -static void write_stream (FILE *file, pdf_stream *stream); -static void release_stream (pdf_stream *stream); -static int pdf_match_name (const pdf_obj *name_obj, const char *name); /* Name does not include the / */ - -static unsigned char debug = 0, verbose = 0; -static char compression_level = 9; - -void pdf_obj_set_compression (int level) -{ - if (level >= 0 && level <= 9) - compression_level = level; - else { - ERROR("set_compression: compression level"); - } -#ifndef HAVE_ZLIB_COMPRESS2 - if (level != 0) - fprintf (stderr, "Unable to set compression level--your zlib doesn't have compress2()\n"); -#endif - return; -} - -static unsigned pdf_version = 4; -void pdf_set_version (unsigned version) -{ - if (version >= 2 && version <= 7) { - pdf_version = version; - } -} - -void pdf_obj_set_debug(void) -{ - debug = 1; -} - -void pdf_obj_set_verbose(void) -{ - if (verbose < 255) - verbose += 1; -} - - -void pdf_out_init (const char *filename) -{ - char v; -#ifdef MEM_DEBUG -MEM_START -#endif - if (!(pdf_output_file = MFOPEN (filename, FOPEN_WBIN_MODE))) { - if (strlen(filename) < 128) { - sprintf (format_buffer, "Unable to open %s\n", filename); - } else - sprintf (format_buffer, "Unable to open file"); - ERROR (format_buffer); - } - pdf_out (pdf_output_file, "%PDF-1.", strlen("%PDF-1.")); - v = '0'+pdf_version; - pdf_out (pdf_output_file, &v, 1); - pdf_out (pdf_output_file, "\n", 1); - /* Adobe recommends writing % and four non-ASCII bytes in the second - line of a PDF, so that programs have a better chance of realizing - it is not a text file. The string here is "%" followed by "pdfm" - with the 8th bit set on each letter. */ - pdf_out (pdf_output_file, "\045\360\344\346\355\n", 6); -#ifdef MEM_DEBUG -MEM_END -#endif -} - -static void dump_xref(void) -{ - int length; - unsigned long i; - startxref = pdf_output_file_position; /* Record where this xref is for - trailer */ - pdf_out (pdf_output_file, "xref\n", 5); - sprintf (format_buffer, "%d %lu\n", 0, next_label); - length = strlen (format_buffer); - pdf_out (pdf_output_file, format_buffer, length); - sprintf (format_buffer, "%010ld %05ld f \n", 0L, 65535L); - length = strlen (format_buffer); - /* Every space counts. The space after the 'f' and 'n' is - *essential*. The PDF spec says the lines must be 20 characters - long including the end of line character. */ - pdf_out (pdf_output_file, format_buffer, length); - for (i=1; i<next_label; i++){ - sprintf (format_buffer, "%010ld %05ld n \n", - output_xref[i-1].file_position, 0L); - length = strlen (format_buffer); - pdf_out (pdf_output_file, format_buffer, length); - } - /* Done with xref table */ - RELEASE (output_xref); -} - -static void dump_trailer(void) -{ - int length; - unsigned long starttrailer; - starttrailer = pdf_output_file_position; - pdf_out (pdf_output_file, "trailer\n", 8); - pdf_out (pdf_output_file, "<<\n", 3); - sprintf (format_buffer, "/Size %lu\n", - next_label); - length = strlen (format_buffer); - pdf_out (pdf_output_file, format_buffer, length); - if (pdf_root_obj == 0) - ERROR ("dump_trailer: Invalid root object"); - sprintf (format_buffer, "/Root %u %u R\n", pdf_root_obj, 0); - length = strlen (format_buffer); - pdf_out (pdf_output_file, format_buffer, length); - if (pdf_info_obj != 0) { - sprintf (format_buffer, "/Info %u %u R\n", pdf_info_obj, 0); - length = strlen (format_buffer); - pdf_out (pdf_output_file, format_buffer, length); - } - pdf_out (pdf_output_file, ">>\n", 3); - pdf_out (pdf_output_file, "startxref\n", 10); - sprintf (format_buffer, "%lu\n", startxref); - length = strlen (format_buffer); - pdf_out (pdf_output_file, format_buffer, length); - pdf_out (pdf_output_file, "%%EOF\n", 6); -} - -void pdf_out_flush (void) -{ - if (pdf_output_file) { - if (debug) fprintf (stderr, "pdf_obj_out_flush: dumping xref\n"); - dump_xref(); - if (debug) fprintf (stderr, "pdf_obj_out_flush: dumping trailer\n"); - dump_trailer(); - if (verbose) { - if (compression_level>0) { - fprintf (stderr, "\nCompression eliminated approximately %lu bytes", - compression_saved); - } - } - fprintf (stderr, "\n%lu bytes written", - pdf_output_file_position); - MFCLOSE (pdf_output_file); - } -} - -void pdf_error_cleanup (void) -{ - /* This routine is the cleanup required for an abnormal exit. - For now, simply close the file. */ - if (pdf_output_file) - MFCLOSE (pdf_output_file); -} - - -void pdf_set_root (pdf_obj *object) -{ - if (pdf_root_obj != 0) { - ERROR ("pdf_set_root: root object already set"); - } - if (object -> label == 0) { /* Make sure this object has a label */ - pdf_label_obj (object); - } - pdf_root_obj = object -> label; -} - -void pdf_set_info (pdf_obj *object) -{ - if (pdf_info_obj != 0) { - ERROR ("pdf_set_info: info object already set"); - } - if (object -> label == 0) { /* Make sure this object has a label */ - pdf_label_obj (object); - } - pdf_info_obj = object -> label; -} - -static void pdf_out_char (FILE *file, char c) -{ - fputc (c, file); - /* Keep tallys for xref table *only* if writing a pdf file */ - if (file == pdf_output_file) { - pdf_output_file_position += 1; - pdf_output_line_position += 1; - } - if (file == pdf_output_file && c == '\n') - pdf_output_line_position = 0; -} - -static void pdf_out (FILE *file, void *buffer, int length) -{ - fwrite (buffer, 1, length, file); - /* Keep tallys for xref table *only* if writing a pdf file */ - if (file == pdf_output_file) { - pdf_output_file_position += length; - pdf_output_line_position += length; - if (length > 0 && ((char *)buffer)[length-1] == '\n') - pdf_output_line_position = 0; - } -} - -static void pdf_out_white (FILE *file) -{ - if (file == pdf_output_file && pdf_output_line_position >= 80) { - pdf_out_char (file, '\n'); - } else { - pdf_out_char (file, ' '); - } - return; -} - -pdf_obj *pdf_new_obj(pdf_obj_type type) -{ - pdf_obj *result; - result = NEW (1, pdf_obj); - result -> type = type; - result -> data = NULL; - result -> label = 0; - result -> generation = 0; - result -> refcount = 1; - return result; -} - -static void pdf_label_obj (pdf_obj *object) -{ - if (object == NULL) - return; - if (next_label > pdf_max_ind_objects) { - pdf_max_ind_objects += IND_OBJECTS_ALLOC_SIZE; - output_xref = RENEW (output_xref, pdf_max_ind_objects, - struct xref_entry); - } - if (object -> label == 0) { /* Don't change label on an already labeled - object. Ignore such calls */ - /* Save so we can lookup this object by its number */ - output_xref[next_label-1].pdf_obj = object; - object -> label = next_label++; - object -> generation = 0; - } -} - -/* This doesn't really copy the object, but allows - it to be used without fear that somebody else will free it */ - -pdf_obj *pdf_link_obj (pdf_obj *object) -{ - if (object == NULL) - ERROR ("pdf_link_obj passed null pointer"); - object -> refcount += 1; - return object; -} - - -pdf_obj *pdf_ref_obj(pdf_obj *object) -{ - pdf_obj *result; - pdf_indirect *indirect; - - if (object == NULL) - ERROR ("pdf_ref_obj passed null pointer"); - - if (object -> refcount == 0) { - fprintf (stderr, "\npdf_ref_obj: Called with already released object"); - pdf_write_obj (stderr, object); - ERROR ("Fatal Error\n"); - } - result = pdf_new_obj (PDF_INDIRECT); - indirect = NEW (1, pdf_indirect); - result -> data = indirect; - if (object -> type == PDF_INDIRECT) { /* If an object is already an indirect reference, - reference the original - object, not the indirect - one */ - indirect -> label = ((pdf_indirect *) (object -> data)) -> label; - indirect -> generation = ((pdf_indirect *) (object -> data)) -> generation; - indirect -> dirty = ((pdf_indirect *) (object -> data)) -> dirty; - indirect -> dirty_file = ((pdf_indirect *) (object -> data)) -> dirty_file; - } else { - if (object -> label == 0) { - pdf_label_obj (object); - } - indirect -> label = object -> label; - indirect -> generation = object -> generation; - indirect -> dirty = 0; - indirect -> dirty_file = NULL; - } - return result; -} - -static void release_indirect (pdf_indirect *data) -{ - RELEASE (data); -} - -static void write_indirect (FILE *file, const pdf_indirect *indirect) -{ - int length; -#ifdef MEM_DEBUG -MEM_START -#endif - if (indirect -> dirty) { - if (file == stderr) { - pdf_out (file, "{d}", 3); - sprintf (format_buffer, "%d %d R", indirect -> label, - indirect -> generation); - length = strlen (format_buffer); - pdf_out (file, format_buffer, length); - } - else { - pdf_obj *clean; - if (indirect -> dirty_file != pdf_input_file) { - fprintf (stderr, "\nwrite_indirect, label=%d, from_file=%p, current_file=%p\n", indirect -> label, indirect->dirty_file, pdf_input_file); - ERROR ("write_indirect: input PDF file doesn't match object"); - } - clean = pdf_ref_file_obj (indirect -> label); - pdf_write_obj (file, clean); - pdf_release_obj (clean); - } - } else { - sprintf (format_buffer, "%d %d R", indirect -> label, - indirect -> generation); - length = strlen (format_buffer); - pdf_out (file, format_buffer, length); - } -#ifdef MEM_DEBUG -MEM_END -#endif -} - -pdf_obj *pdf_new_null (void) -{ - pdf_obj *result; - result = pdf_new_obj (PDF_NULL); - result -> data = NULL; - return result; -} - -static void release_null (void *data) -{ - return; -} - -static void write_null (FILE *file) -{ - pdf_out (file, "null", 4); -} - -pdf_obj *pdf_new_boolean (char value) -{ - pdf_obj *result; - pdf_boolean *data; - result = pdf_new_obj (PDF_BOOLEAN); - data = NEW (1, pdf_boolean); - result -> data = data; - data -> value = value; - return result; -} - -static void release_boolean (pdf_obj *data) -{ - RELEASE (data); -} - -static void write_boolean (FILE *file, const pdf_boolean *data) -{ - if (data -> value) { - pdf_out (file, "true", 4); - } - else { - pdf_out (file, "false", 5); - } -} - -void pdf_set_boolean (pdf_obj *object, char value) -{ - if (object == NULL || object -> type != PDF_BOOLEAN) { - ERROR ("pdf_set_boolean: Passed non-boolean object"); - } - ((pdf_boolean *) (object -> data)) -> value = value; -} - -pdf_obj *pdf_new_number (double value) -{ - pdf_obj *result; - pdf_number *data; - result = pdf_new_obj (PDF_NUMBER); - data = NEW (1, pdf_number); - result -> data = data; - data -> value = value; - return result; -} - -static void release_number (pdf_number *data) -{ - RELEASE (data); -} - -static void write_number (FILE *file, const pdf_number *number) -{ - int count; - sprintf (format_buffer, "%.10g", number -> value); - count = strlen (format_buffer); - pdf_out (file, format_buffer, count); -} - - -void pdf_set_number (pdf_obj *object, double value) -{ - if (object == NULL || object -> type != PDF_NUMBER) { - ERROR ("pdf_set_number: Passed non-number object"); - } - ((pdf_number *) (object -> data)) -> value = value; -} - -double pdf_number_value (pdf_obj *object) -{ - if (object == NULL || object -> type != PDF_NUMBER) { - ERROR ("pdf_obj_number_value: Passed non-number object"); - } - return ((pdf_number *)(object -> data)) -> value; -} - -pdf_obj *pdf_new_string (const void *string, unsigned length) -{ - pdf_obj *result; - pdf_string *data; - result = pdf_new_obj (PDF_STRING); - data = NEW (1, pdf_string); - result -> data = data; - if (length != 0) { - data -> length = length; - data -> string = NEW (length+1, unsigned char); - memcpy (data -> string, string, length); - data -> string[length] = 0; - } else { - data -> length = 0; - data -> string = NULL; - } - return result; -} - -void *pdf_string_value (pdf_obj *a_pdf_string) -{ - pdf_string *data; - data = a_pdf_string -> data; - return data -> string; -} - -unsigned int pdf_string_length (pdf_obj *a_pdf_string) -{ - pdf_string *data; - data = a_pdf_string -> data; - return (data -> length); -} - -/* This routine escapes non printable characters and control - characters in an output string. It optionally remaps - the problem characters in the encoding */ - -int pdfobj_escape_str (char *buffer, int bufsize, unsigned char *s, - int len, int remap) -{ - int result = 0, i; - unsigned char ch; - for (i=0; i<len; i++) { - ch = remap? twiddle(s[i]): s[i]; - /* Exit as fast as possible for printable characters */ - if (result+4 > bufsize) - ERROR ("pdfobj_escape_str: Buffer overflow"); - if (ch < 32 || ch > 126) { - buffer[result++] = '\\'; - sprintf (buffer+result, "%03o", ch); - result += strlen (buffer+result); - continue; - } - switch (ch) { - case '(': - buffer[result++] = '\\'; - buffer[result++] = '('; - break; - case ')': - buffer[result++] = '\\'; - buffer[result++] = ')'; - break; - case '\\': - buffer[result++] = '\\'; - buffer[result++] = '\\'; - break; - default: - buffer[result++] = ch; - break; - } - } - return result; -} - - -static void write_string (FILE *file, const pdf_string *string) -{ - unsigned char *s = string -> string; - int count, i; - pdf_out_char (file, '('); - /* This section of code probably isn't speed critical. Escaping the - characters in the string one at a time may seem slow, but it's - safe if the formatted string length exceeds FORMAT_BUF_SIZE. - Occasionally you see some long strings in PDF. pdfobj_escape_str - is also used for strings of text with no kerning. These must be - handled as quickly as possible since there are so many of them. */ - for (i=0; i<string->length; i++) { - count = pdfobj_escape_str (format_buffer, FORMAT_BUF_SIZE, s+i, - 1, 0); - pdf_out (file, format_buffer, count); - } - pdf_out_char (file, ')'); -} - -static void release_string (pdf_string *data) -{ - if (data -> string != NULL) - RELEASE (data -> string); - RELEASE (data); -} - -void pdf_set_string (pdf_obj *object, unsigned char *string, unsigned length) -{ - pdf_string *data; - if (object == NULL || object -> type != PDF_STRING) { - ERROR ("pdf_set_string: Passed non-string object"); - } - data = object -> data; - if (data -> length != 0) { - RELEASE (data -> string); - } - if (length != 0) { - data -> length = length; - data -> string = NEW (length+1, unsigned char); - memcpy (data -> string, string, length); - (data->string)[length] = 0; - } else { - data -> length = 0; - data -> string = NULL; - } - return; -} - -int pdf_check_name(const char *name) -{ - static char *valid_chars = - "!\"$&'*+,-.0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\^_`abcdefghijklmnopqrstuvwxyz|~"; - if (strspn (name, valid_chars) == strlen (name)) - return 1; - else - return 0; -} - -pdf_obj *pdf_new_name (const char *name) /* name does *not* include the / */ -{ - pdf_obj *result; - unsigned length = strlen (name); - pdf_name *data; - if (!pdf_check_name (name)) { - fprintf (stderr, "Invalid PDF name \"%s\"\n", name); - ERROR ("pdf_new_name: invalid PDF name"); - } - result = pdf_new_obj (PDF_NAME); - data = NEW (1, pdf_name); - result -> data = data; - if (length != 0) { - data -> name = NEW (length+1, char); - memcpy (data -> name, name, length); - (data->name)[length] = 0; - } else - data -> name = NULL; - return result; -} - -static void write_name (FILE *file, const pdf_name *name) -{ - char *s = name -> name; - int i, length; - pdf_out_char (file, '/'); - if (name -> name == NULL) - length = 0; - else - length = strlen (name -> name); - for (i=0; i < length; i++) { - if (isprint (s[i]) && - s[i] != '/' && - s[i] != '%' && - s[i] != '(' && - s[i] != ')' && - s[i] != '[' && - s[i] != ']' && - s[i] != '#') - pdf_out_char (file, s[i]); - } -} - - -static void release_name (pdf_name *data) -{ - if (data -> name != NULL) - RELEASE (data -> name); - RELEASE (data); -} - -void pdf_set_name (pdf_obj *object, char *name) -{ - pdf_name *data; - unsigned length = strlen (name); - if (object == NULL || object -> type != PDF_NAME) { - ERROR ("pdf_set_name: Passed non-name object"); - } - data = object -> data; - if (data -> name != NULL) { - RELEASE (data -> name); - } - if (length != 0) { - data -> name = NEW (length+1, char); - memcpy (data -> name, name, length); - (data->name)[length] = 0; - } else { - data -> name = NULL; - } -} - -char *pdf_name_value (pdf_obj *object) -{ - pdf_name *data; - if (object == NULL || object -> type != PDF_NAME) { - ERROR ("pdf_name_value: Passed non-name object"); - } - data = object -> data; - if (data -> name == NULL) - return NULL; - return data -> name; -} - - -pdf_obj *pdf_new_array (void) -{ - pdf_obj *result; - pdf_array *data; - result = pdf_new_obj (PDF_ARRAY); - data = NEW (1, pdf_array); - data -> values = NULL; - data -> max = 0; - data -> size = 0; - result -> data = data; - return result; -} - -static void write_array (FILE *file, const pdf_array *array) -{ - if (array -> size > 0) { - unsigned long i; - pdf_out_char (file, '['); - for (i=0; i<array->size; i++) { - if (i != 0 && - ((array->values)[i]->type) != PDF_STRING && - ((array->values)[i]->type) != PDF_NAME && - ((array->values)[i]->type) != PDF_ARRAY) - pdf_out_white (file); - pdf_write_obj (file, (array->values)[i]); - } - pdf_out_char (file, ']'); - } else { - write_null (file); - } -} - -pdf_obj *pdf_get_array (pdf_obj *array, unsigned long index) -{ - pdf_array *data; - pdf_obj *result = NULL; - if (array == NULL) { - ERROR ("pdf_get_array: passed NULL object"); - } - if (array -> type != PDF_ARRAY) { - ERROR ("pdf_get_array: passed non array object"); - } - data = array -> data; - if (index < data -> size) { - result = (data->values)[index]; - } - return result; -} - -static void release_array (pdf_array *data) -{ - unsigned long i; - for (i=0; i<data->size; i++) { - pdf_release_obj ((data ->values)[i]); - } - if (data->size > 0) - RELEASE (data->values); - RELEASE (data); -} - -void pdf_add_array (pdf_obj *array, pdf_obj *object) /* Array is ended - by a node with NULL - this pointer */ -{ - pdf_array *data; - if (array == NULL || array -> type != PDF_ARRAY) { - ERROR ("pdf_add_array: Passed non-array object"); - } - data = array -> data; - if (data -> size >= data -> max) { - data->max += ARRAY_ALLOC_SIZE; - data->values = RENEW (data->values, data->max, pdf_obj *); - } - (data->values)[data->size++] = object; - return; -} - - -static void write_dict (FILE *file, const pdf_dict *dict) -{ - pdf_out (file, "<<\n", 3); - while (dict -> key != NULL) { - pdf_write_obj (file, dict -> key); - if (((dict -> value) -> type) == PDF_BOOLEAN || - ((dict -> value) -> type) == PDF_NUMBER || - ((dict -> value) -> type) == PDF_INDIRECT || - ((dict -> value) -> type) == PDF_NULL) - pdf_out_white (file); - pdf_write_obj (file, dict -> value); - dict = dict -> next; - pdf_out_char (file, '\n'); - } - pdf_out (file, ">>", 2); -} - -pdf_obj *pdf_new_dict (void) -{ - pdf_obj *result; - pdf_dict *data; - result = pdf_new_obj (PDF_DICT); - data = NEW (1, pdf_dict); - data -> key = NULL; - data -> value = NULL; - data -> next = NULL; - result -> data = data; - return result; -} - -static void release_dict (pdf_dict *data) -{ - pdf_dict *next; - while (data != NULL && data -> key != NULL) { - pdf_release_obj (data -> key); - pdf_release_obj (data -> value); - next = data -> next; - RELEASE (data); - data = next; - } - RELEASE (data); -} - -void pdf_add_dict (pdf_obj *dict, pdf_obj *key, pdf_obj *value) /* Array is ended - by a node with NULL - this pointer */ -{ - pdf_dict *data; - pdf_dict *new_node; - if (key == NULL || key -> type != PDF_NAME ) { - ERROR ("pdf_add_dict: Passed invalid key"); - } - if (value != NULL && - (value -> type == 0 || value -> type > PDF_INDIRECT )) { - ERROR ("pdf_add_dict: Passed invalid value"); - } - if (dict == NULL || dict -> type != PDF_DICT) { - fprintf (stderr, "key:"); - pdf_write_obj (stderr, key); - fprintf (stderr, "value:"); - pdf_write_obj (stderr, value); - ERROR ("pdf_add_dict: Passed non-dict object"); - } - data = dict -> data; - /* If this key already exists, simply replace the value */ - while (data -> key != NULL) { - if (!strcmp (pdf_name_value(key), pdf_name_value(data->key))) { - /* Release the old value */ - pdf_release_obj (data->value); - /* Release the new key (we don't need it) */ - pdf_release_obj (key); - data->value = value; - break; - } - data = data -> next; - } - /* If we didn't find the key, build a new "end" node and add - the new key just before the end */ - if (data -> key == NULL) { - new_node = NEW (1, pdf_dict); - new_node -> key = NULL; - new_node -> value = NULL; - new_node -> next = NULL; - data -> next = new_node; - data -> key = key; - data -> value = value; - } - return; -} - -/* pdf_merge_dict makes a link for each item in dict2 before - stealing it */ -void pdf_merge_dict (pdf_obj *dict1, pdf_obj *dict2) -{ - pdf_dict *data; - if (dict1 == NULL || dict1 -> type != PDF_DICT) - ERROR ("pdf_merge_dict: Passed invalid first dictionary"); - if (dict2 == NULL || dict2 -> type != PDF_DICT) - ERROR ("pdf_merge_dict: Passed invalid second dictionary"); - data = dict2 -> data; - while (data -> key != NULL) { - pdf_add_dict (dict1, pdf_link_obj(data -> key), - pdf_link_obj (data -> value)); - data = data -> next; - } -} - -static int pdf_match_name (const pdf_obj *name_obj, const char *name_string) -{ - pdf_name *data; - data = name_obj -> data; - return (!strcmp (data -> name, name_string)); -} - -pdf_obj *pdf_lookup_dict (const pdf_obj *dict, const char *name) -{ - pdf_dict *data; - if (dict == NULL || dict ->type != PDF_DICT) - ERROR ("pdf_lookup_dict: Passed invalid dictionary"); - data = dict -> data; - while (data -> key != NULL) { - if (pdf_match_name (data -> key, name)) - return data -> value; - data = data -> next; - } - return NULL; -} - -void pdf_remove_dict (pdf_obj *dict, const char *name) -{ - pdf_dict *data, **data_p; - if (dict == NULL || dict->type != PDF_DICT) - ERROR ("pdf_remove_dict: Passed invalid dictionary"); - data = (dict -> data); - data_p = (pdf_dict **) &(dict->data); - while (data->key != NULL) { - if (pdf_match_name (data -> key, name)) { - pdf_release_obj (data -> key); - pdf_release_obj (data -> value); - *data_p = data -> next; - RELEASE (data); - break; - } - data_p = &(data->next); - data = data -> next; - } - return; -} - -char *pdf_get_dict (const pdf_obj *dict, int index) -{ - pdf_dict *data; - char *result; - if (dict == NULL) { - ERROR ("pdf_get_dict: passed NULL object"); - } - if (dict -> type != PDF_DICT) { - ERROR ("pdf_get_dict: passed non array object"); - } - data = dict -> data; - while (index-- > 0 && data -> next != NULL) - data = data -> next; - if (data -> next == NULL) - return NULL; - result = pdf_name_value (data -> key); - return result; -} - -pdf_obj *pdf_new_stream (int flags) -{ - pdf_obj *result; -#ifdef HAVE_ZLIB - pdf_obj *filters = NULL; -#endif /* HAVE_ZLIB */ - pdf_stream *data; - result = pdf_new_obj (PDF_STREAM); - data = NEW (1, pdf_stream); - result -> data = data; - data -> dict = pdf_new_dict (); /* Although we are using an arbitrary - pdf_object here, it must have - type=PDF_DICT and cannot be an - indirect reference. This will - be checked by the output routine - */ - data -> _flags = flags; -#ifdef HAVE_ZLIB - if ((flags & STREAM_COMPRESS) && compression_level > 0) { - if (!filters) { - filters = pdf_new_array(); - pdf_add_dict (data -> dict, pdf_new_name ("Filter"), filters); - } - pdf_add_array (filters, pdf_new_name ("FlateDecode")); - } -#endif /* HAVE_ZLIB */ - - data -> stream_length = 0; - data -> max_length = 0; - data -> stream = NULL; - return result; -} - - -static void write_stream (FILE *file, pdf_stream *stream) -{ -#define COMPRESS_LEVEL 9 -#define THRESHOLD 100 - unsigned char *filtered; - unsigned long filtered_length; -#ifdef HAVE_ZLIB - unsigned long buffer_length; - unsigned char *buffer; -#endif /* HAVE_ZLIB */ - /* Always work from a copy of the stream */ - /* All filters read from "filtered" and leave their result in - "filtered" */ - filtered = NEW (stream->stream_length+1, unsigned char); - memcpy (filtered, stream->stream, stream->stream_length); - filtered_length = stream->stream_length; - -#ifdef HAVE_ZLIB - /* Apply compression filter if requested */ - if ((stream -> _flags & STREAM_COMPRESS) && compression_level > 0) { - buffer_length = filtered_length + filtered_length/1000 + 14; - buffer = NEW (buffer_length, unsigned char); -#ifdef HAVE_ZLIB_COMPRESS2 - if (compress2 (buffer, &buffer_length, filtered, - filtered_length, compression_level)) - ERROR ("Zlib error"); -#else - if (compress (buffer, &buffer_length, filtered, - filtered_length)) - ERROR ("Zlib error"); -#endif /* HAVE_ZLIB_COMPRESS2 */ - RELEASE (filtered); - filtered = buffer; - compression_saved += (filtered_length-buffer_length)-strlen("/Filter [/FlateDecode]\n"); - filtered_length = buffer_length; - } -#endif /* HAVE_ZLIB */ - /* Add a '\n' if the last character wasn't one */ - if (filtered_length > 0 && filtered[filtered_length-1] != '\n') { - filtered[filtered_length++] = '\n'; - } - pdf_add_dict (stream->dict, - pdf_new_name ("Length"), - pdf_new_number(filtered_length)); - pdf_write_obj (file, stream -> dict); - pdf_out (file, "\nstream\n", 8); - - if (filtered_length > 0) { - pdf_out (file, filtered, filtered_length); - } - - RELEASE (filtered); - /* This stream length "object" gets reset every time write_stream is - called for the stream object */ - /* If this stream gets written more than once with different - filters, this could be a problem */ - pdf_out (file, "endstream", 9); - return; -} - -static void release_stream (pdf_stream *stream) -{ - pdf_release_obj (stream -> dict); - if (stream -> stream_length > 0) - RELEASE (stream -> stream); - RELEASE (stream); -} - -pdf_obj *pdf_stream_dict (pdf_obj *stream) -{ - pdf_stream *data; - if (stream == NULL || stream -> type != PDF_STREAM) { - ERROR ("pdf_stream_dict: Passed non-stream object"); - } - data = stream -> data; - return data -> dict; -} - -void pdf_add_stream (pdf_obj *stream, char *stream_data, unsigned length) -{ - pdf_stream *data; - if (stream == NULL || stream -> type != PDF_STREAM) { - ERROR ("pdf_add_stream: Passed non-stream object"); - } - if (length == 0) - return; - data = stream -> data; - if (data -> stream_length + length > data -> max_length) { - data -> max_length += length + STREAM_ALLOC_SIZE; - data -> stream = RENEW (data -> stream, data->max_length, char); - } - memcpy ((data->stream)+(data->stream_length), stream_data, - length); - data->stream_length += length; -} - -void pdf_write_obj (FILE *file, const pdf_obj *object) -{ - if (object == NULL) { - write_null(file); - return; - } - if (object -> type > PDF_INDIRECT) { - fprintf (stderr, "Object type = %d\n", object -> type); - ERROR ("pdf_write_obj: Called with invalid object"); - } - if (file == stderr) - fprintf (stderr, "{%d}", object -> refcount); - switch (object -> type) { - case PDF_BOOLEAN: - write_boolean (file, object -> data); - break; - case PDF_NUMBER: - write_number (file, object -> data); - break; - case PDF_STRING: - write_string (file, object -> data); - break; - case PDF_NAME: - write_name (file, object -> data); - break; - case PDF_ARRAY: - write_array (file, object -> data); - break; - case PDF_DICT: - write_dict (file, object -> data); - break; - case PDF_STREAM: - write_stream (file, object -> data); - break; - case PDF_NULL: - write_null (file); - break; - case PDF_INDIRECT: - write_indirect (file, object -> data); - break; - } -} - -static void pdf_flush_obj (FILE *file, const pdf_obj *object) - /* Write the object to the file */ -{ - int length; - /* Record file position. No object is numbered 0, so subtract 1 - when using as an array index */ - output_xref[object->label-1].file_position = pdf_output_file_position; - sprintf (format_buffer, "%lu %d obj\n", object -> label , - object -> generation); - length = strlen (format_buffer); - pdf_out (file, format_buffer, length); - pdf_write_obj (file, object); - pdf_out (file, "\nendobj\n", 8); -} - - -void pdf_release_obj (pdf_obj *object) -{ - if (object == NULL) - return; - if (object -> type > PDF_INDIRECT || - object -> refcount <= 0) { - fprintf (stderr, "pdf_release_obj: object = %p, type = %d\n", object, object -> - type); - pdf_write_obj (stderr, object); - ERROR ("pdf_release_obj: Called with invalid object"); - } - object -> refcount -= 1; - if (object -> refcount == 0) { /* Nothing is using this object so it's okay to - remove it */ - /* Nonzero "label" means object needs to be written before it's destroyed*/ - if (object -> label && pdf_output_file != NULL) { - pdf_flush_obj (pdf_output_file, object); - } - switch (object -> type) { - case PDF_BOOLEAN: - release_boolean (object -> data); - break; - case PDF_NULL: - release_null (object -> data); - break; - case PDF_NUMBER: - release_number (object -> data); - break; - case PDF_STRING: - release_string (object -> data); - break; - case PDF_NAME: - release_name (object -> data); - break; - case PDF_ARRAY: - release_array (object -> data); - break; - case PDF_DICT: - release_dict (object -> data); - break; - case PDF_STREAM: - release_stream (object -> data); - break; - case PDF_INDIRECT: - release_indirect (object -> data); - break; - } - /* This might help detect freeing already freed objects */ - /* object -> type = -1;*/ - RELEASE (object); - } -} - -static int backup_line (void) -{ - int ch; - ch = -1; - if (debug) { - fprintf (stderr, "\nbackup_line:\n"); - } - /* Note: this code should work even if \r\n is eol. - It could fail on a machine where \n is eol and - there is a \r in the stream---Highly unlikely - in the last few bytes where this is likely to be used. - */ - if (tell_position (pdf_input_file) > 1) - do { - seek_relative (pdf_input_file, -2); - if (debug) - fprintf (stderr, "%c", ch); - } while (tell_position (pdf_input_file) > 0 && - (ch = fgetc (pdf_input_file)) >= 0 && - (ch != '\n' && ch != '\r' )); - if (debug) - fprintf (stderr, "<-\n"); - if (ch < 0) { - return 0; - } - return 1; -} - -static unsigned long pdf_file_size = 0; - -static long find_xref(void) -{ - long currentpos, xref_pos; - int tries = 10; - char *start, *end, *number; - if (debug) - fprintf (stderr, "(find_xref"); - seek_end (pdf_input_file); - pdf_file_size = tell_position (pdf_input_file); - do { - if (!backup_line()) { - tries = 0; - break; - } - currentpos = tell_position(pdf_input_file); - fread (work_buffer, sizeof(char), strlen("startxref"), - pdf_input_file); - if (debug) { - work_buffer[strlen("startxref")] = 0; - fprintf (stderr, "[%s]\n", work_buffer); - } - seek_absolute(pdf_input_file, currentpos); - tries--; - } while (tries > 0 && strncmp (work_buffer, "startxref", strlen ("startxref"))); - if (tries <= 0) - return 0; - /* Skip rest of this line */ - mfgets (work_buffer, WORK_BUFFER_SIZE, pdf_input_file); - /* Next line of input file should contain actual xref location */ - mfgets (work_buffer, WORK_BUFFER_SIZE, pdf_input_file); - if (debug) { - fprintf (stderr, "\n->[%s]<-\n", work_buffer); - } - start = work_buffer; - end = start+strlen(work_buffer); - skip_white(&start, end); - xref_pos = (long) atof (number = parse_number (&start, end)); - RELEASE (number); - if (debug) { - fprintf (stderr, ")\n"); - fprintf (stderr, "xref @ %lu\n", xref_pos); - } - return xref_pos; -} - -pdf_obj *parse_trailer (void) -{ - char *start; -#ifdef MEM_DEBUG -MEM_START -#endif - /* This routine must be called with the file pointer located at - the start of the trailer */ - /* Fill work_buffer and hope trailer fits. This should - be made a bit more robust sometime */ - if (fread (work_buffer, sizeof(char), WORK_BUFFER_SIZE, - pdf_input_file) == 0 || - strncmp (work_buffer, "trailer", strlen("trailer"))) { - fprintf (stderr, "No trailer. Are you sure this is a PDF file?\n"); - fprintf (stderr, "\nbuffer:\n->%s<-\n", work_buffer); - return NULL; - } - start = work_buffer + strlen("trailer"); - skip_white(&start, work_buffer+WORK_BUFFER_SIZE); -#ifdef MEM_DEBUG -MEM_END -#endif - return (parse_pdf_dict (&start, work_buffer+WORK_BUFFER_SIZE)); -} - -struct object -{ - unsigned long position; - unsigned generation; - /* Object numbers in original file and new file must have different - object numbers. - new_ref provides a reference for the object in the new file - object space. When it is first set, an object in the old file - is copied to the new file with a new number. new_ref remains set - until the file is closed so that future references can access the - object via new_ref instead of copying the object again */ - pdf_obj *direct; - pdf_obj *indirect; - int used; -} *xref_table = NULL; -long num_input_objects; - -long next_object (unsigned long obj) -{ - /* routine tries to estimate an upper bound for character position - of the end of the object, so it knows how big the buffer must be. - The parsing routines require that the entire object be read into - memory. It would be a major pain to rewrite them. The worst case - is that an object before an xref table will grab the whole table - :-( */ - unsigned long i; - long this_position, result = pdf_file_size; /* Worst case */ - this_position = xref_table[obj].position; - /* Check all other objects to find next one */ - for (i=0; i<num_input_objects; i++) { - if ((xref_table[i].used) && - xref_table[i].position > this_position && - xref_table[i].position < result) - result = xref_table[i].position; - } - return result; -} - -/* The following routine returns a reference to an object existing - only in the input file. It does this as follows. If the object - has never been referenced before, it reads the object - in and creates a reference to it. Then it writes - the object out, keeping the existing reference. If the - object has been read in (and written out) before, it simply - returns the retained existing reference to that object */ - -pdf_obj *pdf_ref_file_obj (unsigned long obj_no) -{ - pdf_obj *direct, *indirect; -#ifdef MEM_DEBUG -MEM_START -#endif - if (obj_no >= num_input_objects) { - fprintf (stderr, "\n\npdf_ref_file_obj: nonexistent object\n"); - return NULL; - } - if (xref_table[obj_no].indirect != NULL) { - return pdf_link_obj(xref_table[obj_no].indirect); - } - if ((direct = pdf_read_object (obj_no)) == NULL) { - fprintf (stderr, "\npdf_ref_file_obj: Could not read object\n"); - return NULL; - } - indirect = pdf_ref_obj (direct); - xref_table[obj_no].indirect = indirect; - xref_table[obj_no].direct = direct; - /* Make sure the caller can't doesn't free this object */ -#ifdef MEM_DEBUG -MEM_END -#endif - return pdf_link_obj(indirect); -} - - -pdf_obj *pdf_new_ref (unsigned long label, int generation) -{ - pdf_obj *result; - pdf_indirect *indirect; - if (label >= num_input_objects || label < 0) { - fprintf (stderr, "pdf_new_ref: Object doesn't exist\n"); - return NULL; - } - result = pdf_new_obj (PDF_INDIRECT); - indirect = NEW (1, pdf_indirect); - result -> data = indirect; - indirect -> label = label; - indirect -> generation = generation; - indirect -> dirty = 1; - indirect -> dirty_file = pdf_input_file; - return result; -} - -pdf_obj *pdf_read_object (unsigned long obj_no) -{ - long start_pos, end_pos; - char *buffer, *number, *parse_pointer, *end; - pdf_obj *result; -#ifdef MEM_DEBUG -MEM_START -#endif - if (debug) { - fprintf (stderr, "\nread_object: obj=%lu\n", obj_no); - } - if (obj_no < 0 || obj_no >= num_input_objects) { - fprintf (stderr, "\nTrying to read nonexistent object\n"); - return NULL; - } - if (!xref_table[obj_no].used) { - fprintf (stderr, "\nTrying to read deleted object\n"); - return NULL; - } - if (debug) { - fprintf (stderr, "\nobj@%lu\n", xref_table[obj_no].position); - } - seek_absolute (pdf_input_file, start_pos = - xref_table[obj_no].position); - end_pos = next_object (obj_no); - if (debug) { - fprintf (stderr, "\nendobj@%lu\n", end_pos); - } - buffer = NEW (end_pos - start_pos+1, char); - fread (buffer, sizeof(char), end_pos-start_pos, pdf_input_file); - buffer[end_pos-start_pos] = 0; - if (debug) { - fprintf (stderr, "\nobject:\n%s", buffer); - } - parse_pointer = buffer; - end = buffer+(end_pos-start_pos); - skip_white (&parse_pointer, end); - number = parse_number (&parse_pointer, end); - if ((int) atof(number) != obj_no) { - fprintf (stderr, "Object number doesn't match\n"); - RELEASE (buffer); - return NULL; - } - if (number != NULL) - RELEASE(number); - skip_white (&parse_pointer, end); - number = parse_number (&parse_pointer, end); - if (number != NULL) - RELEASE(number); - skip_white(&parse_pointer, end); - if (strncmp(parse_pointer, "obj", strlen("obj"))) { - fprintf (stderr, "Didn't find \"obj\"\n"); - RELEASE (buffer); - return (NULL); - } - parse_pointer += strlen("obj"); - result = parse_pdf_object (&parse_pointer, end); - skip_white (&parse_pointer, end); - if (strncmp(parse_pointer, "endobj", strlen("endobj"))) { - fprintf (stderr, "Didn't find \"endobj\"\n"); - if (result != NULL) - pdf_release_obj (result); - result = NULL; - } - RELEASE (buffer); - return (result); -#ifdef MEM_DEBUG -MEM_END -#endif -} -/* pdf_deref_obj always returns a link instead of the original */ -pdf_obj *pdf_deref_obj (pdf_obj *obj) -{ - pdf_obj *result, *tmp; - pdf_indirect *indirect; - if (obj == NULL) - return NULL; - if (obj -> type != PDF_INDIRECT) { - return pdf_link_obj (obj); - } - indirect = obj -> data; - if (!(indirect -> dirty)) { - ERROR ("Tried to deref a non-file object"); - } - result = pdf_read_object (indirect -> label); - - if (debug){ - fprintf (stderr, "\npdf_deref_obj: read_object returned\n"); - pdf_write_obj (stderr, result); - } - - while (result && result -> type == PDF_INDIRECT) { - tmp = pdf_read_object (result -> label); - pdf_release_obj (result); - result = tmp; - } - return result; -} - -/* extends the xref table if we get another segment - with higher object numbers than the current object */ -static void extend_xref (long new_size) -{ - unsigned long i; - xref_table = RENEW (xref_table, new_size, - struct object); - for (i=num_input_objects; i<new_size; i++) { - xref_table[i].direct = NULL; - xref_table[i].indirect = NULL; - xref_table[i].used = 0; - xref_table[i].position = 0; - } - num_input_objects = new_size; -} - - - -static int parse_xref (void) -{ - unsigned long first_obj, num_table_objects; - unsigned long i; - /* This routine reads one xref segment. It must be called - positioned at the beginning of an xref table. It may be called - multiple times on the same file. xref tables sometimes come in - pieces */ - mfgets (work_buffer, WORK_BUFFER_SIZE, pdf_input_file); - if (strncmp (work_buffer, "xref", strlen("xref"))) { - fprintf (stderr, "No xref. Are you sure this is a PDF file?\n"); - return 0; - } - /* Next line in file has first item and size of table */ - for (;;) { - unsigned long current_pos; - current_pos = tell_position (pdf_input_file); - if (mfgets (work_buffer, WORK_BUFFER_SIZE, pdf_input_file) == - NULL) - ERROR ("parse_xref: premature end of PDF file while parsing xref"); - if (!strncmp (work_buffer, "trailer", strlen ("trailer"))) { - /* Backup... This is ugly, but it seems like the safest thing to - do. It is possible the trailer dictionary starts on the same - logical line as the word trailer. In that case, the mfgets - call might have started to read the trailer dictionary and - parse_trailer would fail */ - seek_absolute (pdf_input_file, current_pos); - break; - } - sscanf (work_buffer, "%lu %lu", &first_obj, &num_table_objects); - if (num_input_objects < first_obj+num_table_objects) { - extend_xref (first_obj+num_table_objects); - } - if (debug) { - fprintf (stderr, "\nfirstobj=%lu,number=%lu\n", - first_obj,num_table_objects); - } - for (i=first_obj; i<first_obj+num_table_objects; i++) { - fread (work_buffer, sizeof(char), 20, pdf_input_file); - /* Don't overwrite positions that have already been set by a - modified xref table. We are working our way backwards - through the reference table, so we only set "position" - if it hasn't been set yet. */ - if (xref_table[i].position == 0) { - work_buffer[19] = 0; - sscanf (work_buffer, "%lu %u", &(xref_table[i].position), - &(xref_table[i].generation)); - } - if (debug) { - fprintf (stderr, "pos: %lu gen: %u\n", xref_table[i].position, - xref_table[i].generation); - } - if (work_buffer[17] != 'n' && work_buffer[17] != 'f') { - fprintf (stderr, "PDF file is corrupt\n"); - fprintf (stderr, "[%s]\n", work_buffer); - return 0; - } - if (work_buffer[17] == 'n') - xref_table[i].used = 1; - else - xref_table[i].used = 0; - xref_table[i].direct = NULL; - xref_table[i].indirect = NULL; - } - } - return 1; -} - -pdf_obj *read_xref (void) -{ - pdf_obj *main_trailer, *prev_trailer, *prev_xref, *xref_size; - long xref_pos; -#ifdef MEM_DEBUG -MEM_START -#endif - if ((xref_pos = find_xref()) == 0) { - fprintf (stderr, "Can't find xref table.\n"); - return NULL; - } - if (debug) { - fprintf(stderr, "xref@%lu\n", xref_pos); - } - /* Read primary xref table */ - seek_absolute (pdf_input_file, xref_pos); - if (!parse_xref()) { - fprintf (stderr, - "\nCouldn't read xref table. Is this a correct PDF file?\n"); - return NULL; - } - if ((main_trailer = parse_trailer()) == NULL) { - fprintf (stderr, - "\nCouldn't read xref trailer. Is this a correct PDF file?\n"); - return NULL; - } - if (pdf_lookup_dict (main_trailer, "Root") == NULL || - (xref_size = pdf_lookup_dict (main_trailer, "Size")) == NULL) { - fprintf (stderr, - "\nTrailer doesn't have catalog or a size. Is this a correct PDF file?\n"); - return NULL; - } - if (num_input_objects < pdf_number_value (xref_size)) { - extend_xref (pdf_number_value (xref_size)); - } - /* Read any additional xref tables */ - prev_trailer = pdf_link_obj (main_trailer); - while ((prev_xref = pdf_lookup_dict (prev_trailer, "Prev")) != NULL) { - xref_pos = pdf_number_value (prev_xref); - seek_absolute (pdf_input_file, xref_pos); - pdf_release_obj (prev_trailer); - if (!parse_xref()) { - fprintf (stderr, - "\nCouldn't read xref table. Is this a correct PDF file?\n"); - return NULL; - } - if ((prev_trailer = parse_trailer()) == NULL) { - fprintf (stderr, - "\nCouldn't read xref trailer. Is this a correct PDF file?\n"); - return NULL; - } - if (debug) { - fprintf (stderr, "\nprev_trailer:\n"); - pdf_write_obj (stderr, prev_trailer); - } - } -#ifdef MEM_DEBUG -MEM_END -#endif - pdf_release_obj (prev_trailer); - return main_trailer; -} - -static char any_open = 0; - -pdf_obj *pdf_open (FILE *file) -{ - pdf_obj *trailer; -#ifdef MEM_DEBUG -MEM_START -#endif - if (any_open) { - fprintf (stderr, "\nOnly one PDF file may be open at one time.\n"); - any_open = 1; - exit(1); - } - pdf_input_file = file; - if (!check_for_pdf (pdf_input_file)) { - fprintf (stderr, "pdf_open: Not a PDF 1.[1-3] file\n"); - return NULL; - } - if ((trailer = read_xref()) == NULL) { - fprintf (stderr, "No trailer.\n"); - pdf_close (); - return NULL; - } - if (debug) { - fprintf (stderr, "\nDone with xref:\n"); - } -#ifdef MEM_DEBUG - MEM_END -#endif - return trailer; -} - -void pdf_close (void) -{ - /* Following loop must be iterated because each write could trigger - an additional indirect reference of an object with a lower - number! */ - unsigned long i; - int done; - if (debug) { - fprintf (stderr, "\npdf_close:\n"); - fprintf (stderr, "pdf_input_file=%p\n", pdf_input_file); - } - do { - done = 1; - for (i=0; i<num_input_objects; i++) { - if (xref_table[i].direct != NULL) { - pdf_release_obj (xref_table[i].direct); - xref_table[i].direct = NULL; - done = 0; - } - } - } while (!done); - /* Now take care of the indirect objects - They had to be left around until all the direct - objects were flushed */ - for (i=0; i<num_input_objects; i++) { - if (xref_table[i].indirect != NULL) { - pdf_release_obj (xref_table[i].indirect); - } - } - RELEASE (xref_table); - xref_table = NULL; - num_input_objects = 0; - any_open = 0; - pdf_input_file = NULL; - if (debug) { - fprintf (stderr, "\nexiting pdf_close:\n"); - } -} - -int check_for_pdf (FILE *file) -{ - int result = 0; - rewind (file); - if (fread (work_buffer, sizeof(char), strlen("%PDF-1.x"), file) == - strlen("%PDF-1.x") && - !strncmp(work_buffer, "%PDF-1.", strlen("%PDF-1."))) { - if (work_buffer[7] >= '0' && work_buffer[7] <= '0'+pdf_version) - result = 1; - else { - fprintf (stderr, "\nVersion of PDF file (1.%c) is newer than version limit specification.\n", work_buffer[7]); - } - } - return result; -} |