diff options
Diffstat (limited to 'source/pdf/pdf-xref.c')
-rw-r--r-- | source/pdf/pdf-xref.c | 1072 |
1 files changed, 552 insertions, 520 deletions
diff --git a/source/pdf/pdf-xref.c b/source/pdf/pdf-xref.c index 5308a272..586aab2d 100644 --- a/source/pdf/pdf-xref.c +++ b/source/pdf/pdf-xref.c @@ -20,9 +20,8 @@ static inline int iswhite(int ch) * xref tables */ -static void pdf_free_xref_sections(pdf_document *doc) +static void pdf_drop_xref_sections(fz_context *ctx, pdf_document *doc) { - fz_context *ctx = doc->ctx; int x, e; for (x = 0; x < doc->num_xref_sections; x++) @@ -39,7 +38,7 @@ static void pdf_free_xref_sections(pdf_document *doc) if (entry->obj) { - pdf_drop_obj(entry->obj); + pdf_drop_obj(ctx, entry->obj); fz_drop_buffer(ctx, entry->stm_buf); } } @@ -48,8 +47,8 @@ static void pdf_free_xref_sections(pdf_document *doc) sub = next_sub; } - pdf_drop_obj(xref->pre_repair_trailer); - pdf_drop_obj(xref->trailer); + pdf_drop_obj(ctx, xref->pre_repair_trailer); + pdf_drop_obj(ctx, xref->trailer); } fz_free(ctx, doc->xref_sections); @@ -57,6 +56,19 @@ static void pdf_free_xref_sections(pdf_document *doc) doc->num_xref_sections = 0; } +static void +extend_xref_index(fz_context *ctx, pdf_document *doc, int newlen) +{ + int i; + + doc->xref_index = fz_resize_array(ctx, doc->xref_index, newlen, sizeof(int)); + for (i = doc->max_xref_len; i < newlen; i++) + { + doc->xref_index[i] = 0; + } + doc->max_xref_len = newlen; +} + /* This is only ever called when we already have an incremental * xref. This means there will only be 1 subsec, and it will be * a complete subsec. */ @@ -84,13 +96,13 @@ static void pdf_resize_xref(fz_context *ctx, pdf_document *doc, int newlen) xref->num_objects = newlen; sub->len = newlen; if (doc->max_xref_len < newlen) - doc->max_xref_len = newlen; + extend_xref_index(ctx, doc, newlen); } -static void pdf_populate_next_xref_level(pdf_document *doc) +static void pdf_populate_next_xref_level(fz_context *ctx, pdf_document *doc) { pdf_xref *xref; - doc->xref_sections = fz_resize_array(doc->ctx, doc->xref_sections, doc->num_xref_sections + 1, sizeof(pdf_xref)); + doc->xref_sections = fz_resize_array(ctx, doc->xref_sections, doc->num_xref_sections + 1, sizeof(pdf_xref)); doc->num_xref_sections++; xref = &doc->xref_sections[doc->num_xref_sections - 1]; @@ -100,7 +112,7 @@ static void pdf_populate_next_xref_level(pdf_document *doc) xref->pre_repair_trailer = NULL; } -pdf_obj *pdf_trailer(pdf_document *doc) +pdf_obj *pdf_trailer(fz_context *ctx, pdf_document *doc) { /* Return the document's final trailer */ pdf_xref *xref = &doc->xref_sections[0]; @@ -108,19 +120,19 @@ pdf_obj *pdf_trailer(pdf_document *doc) return xref->trailer; } -void pdf_set_populating_xref_trailer(pdf_document *doc, pdf_obj *trailer) +void pdf_set_populating_xref_trailer(fz_context *ctx, pdf_document *doc, pdf_obj *trailer) { /* Update the trailer of the xref section being populated */ pdf_xref *xref = &doc->xref_sections[doc->num_xref_sections - 1]; if (xref->trailer) { - pdf_drop_obj(xref->pre_repair_trailer); + pdf_drop_obj(ctx, xref->pre_repair_trailer); xref->pre_repair_trailer = xref->trailer; } - xref->trailer = pdf_keep_obj(trailer); + xref->trailer = pdf_keep_obj(ctx, trailer); } -int pdf_xref_len(pdf_document *doc) +int pdf_xref_len(fz_context *ctx, pdf_document *doc) { return doc->max_xref_len; } @@ -128,9 +140,8 @@ int pdf_xref_len(pdf_document *doc) /* Ensure that the given xref has a single subsection * that covers the entire range. */ static void -ensure_solid_xref(pdf_document *doc, int num, int which) +ensure_solid_xref(fz_context *ctx, pdf_document *doc, int num, int which) { - fz_context *ctx = doc->ctx; pdf_xref *xref = &doc->xref_sections[which]; pdf_xref_subsec *sub = xref->subsec; pdf_xref_subsec *new_sub; @@ -174,11 +185,11 @@ ensure_solid_xref(pdf_document *doc, int num, int which) xref->num_objects = num; xref->subsec = new_sub; if (doc->max_xref_len < num) - doc->max_xref_len = num; + extend_xref_index(ctx, doc, num); } /* Used while reading the individual xref sections from a file */ -pdf_xref_entry *pdf_get_populating_xref_entry(pdf_document *doc, int num) +pdf_xref_entry *pdf_get_populating_xref_entry(fz_context *ctx, pdf_document *doc, int num) { /* Return an entry within the xref currently being populated */ pdf_xref *xref; @@ -186,13 +197,13 @@ pdf_xref_entry *pdf_get_populating_xref_entry(pdf_document *doc, int num) if (doc->num_xref_sections == 0) { - doc->xref_sections = fz_calloc(doc->ctx, 1, sizeof(pdf_xref)); + doc->xref_sections = fz_calloc(ctx, 1, sizeof(pdf_xref)); doc->num_xref_sections = 1; } /* Prevent accidental heap underflow */ if (num < 0) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "object number must not be negative (%d)", num); + fz_throw(ctx, FZ_ERROR_GENERIC, "object number must not be negative (%d)", num); /* Return the pointer to the entry in the last section. */ xref = &doc->xref_sections[doc->num_xref_sections-1]; @@ -204,7 +215,7 @@ pdf_xref_entry *pdf_get_populating_xref_entry(pdf_document *doc, int num) } /* We've been asked for an object that's not in a subsec. */ - ensure_solid_xref(doc, num+1, doc->num_xref_sections-1); + ensure_solid_xref(ctx, doc, num+1, doc->num_xref_sections-1); xref = &doc->xref_sections[doc->num_xref_sections-1]; sub = xref->subsec; @@ -215,9 +226,8 @@ pdf_xref_entry *pdf_get_populating_xref_entry(pdf_document *doc, int num) /* This will never throw anything, or return NULL if it is * only asked to return objects in range within a 'solid' * xref. */ -pdf_xref_entry *pdf_get_xref_entry(pdf_document *doc, int i) +pdf_xref_entry *pdf_get_xref_entry(fz_context *ctx, pdf_document *doc, int i) { - fz_context *ctx = doc->ctx; pdf_xref *xref; pdf_xref_subsec *sub; int j; @@ -225,12 +235,17 @@ pdf_xref_entry *pdf_get_xref_entry(pdf_document *doc, int i) if (i < 0) fz_throw(ctx, FZ_ERROR_GENERIC, "Negative object number requested"); + if (i <= doc->max_xref_len) + j = doc->xref_index[i]; + else + j = 0; + /* Find the first xref section where the entry is defined. */ - for (j = 0; j < doc->num_xref_sections; j++) + for (; j < doc->num_xref_sections; j++) { xref = &doc->xref_sections[j]; - if (i >= 0 && i < xref->num_objects) + if (i < xref->num_objects) { for (sub = xref->subsec; sub != NULL; sub = sub->next) { @@ -241,13 +256,17 @@ pdf_xref_entry *pdf_get_xref_entry(pdf_document *doc, int i) entry = &sub->table[i - sub->start]; if (entry->type) + { + doc->xref_index[i] = j; return entry; + } } } } /* Didn't find the entry in any section. Return the entry from * the final section. */ + doc->xref_index[i] = 0; if (i < xref->num_objects) { xref = &doc->xref_sections[0]; @@ -262,7 +281,7 @@ pdf_xref_entry *pdf_get_xref_entry(pdf_document *doc, int i) * can return a pointer. This is the only case where this function * might throw an exception, and it will never happen when we are * working within a 'solid' xref. */ - ensure_solid_xref(doc, i+1, 0); + ensure_solid_xref(ctx, doc, i+1, 0); xref = &doc->xref_sections[0]; sub = xref->subsec; return &sub->table[i - sub->start]; @@ -273,9 +292,8 @@ pdf_xref_entry *pdf_get_xref_entry(pdf_document *doc, int i) updated versions of indirect objects. This is a new xref section consisting of a single xref subsection. */ -static void ensure_incremental_xref(pdf_document *doc) +static void ensure_incremental_xref(fz_context *ctx, pdf_document *doc) { - fz_context *ctx = doc->ctx; if (!doc->xref_altered) { @@ -284,12 +302,13 @@ static void ensure_incremental_xref(pdf_document *doc) pdf_xref_entry *new_table = fz_calloc(ctx, xref->num_objects, sizeof(pdf_xref_entry)); pdf_xref_subsec *sub; pdf_obj *trailer = NULL; + int i; fz_var(trailer); fz_try(ctx) { sub = fz_malloc_struct(ctx, pdf_xref_subsec); - trailer = pdf_copy_dict(xref->trailer); + trailer = pdf_copy_dict(ctx, xref->trailer); doc->xref_sections = fz_resize_array(ctx, doc->xref_sections, doc->num_xref_sections + 1, sizeof(pdf_xref)); xref = &doc->xref_sections[0]; pxref = &doc->xref_sections[1]; @@ -308,21 +327,26 @@ static void ensure_incremental_xref(pdf_document *doc) fz_catch(ctx) { fz_free(ctx, new_table); - pdf_drop_obj(trailer); + pdf_drop_obj(ctx, trailer); fz_rethrow(ctx); } + + /* Update the xref_index */ + for (i = 0; i < doc->max_xref_len; i++) + { + doc->xref_index[i]++; + } } } /* Used when altering a document */ -static pdf_xref_entry *pdf_get_incremental_xref_entry(pdf_document *doc, int i) +static pdf_xref_entry *pdf_get_incremental_xref_entry(fz_context *ctx, pdf_document *doc, int i) { - fz_context *ctx = doc->ctx; pdf_xref *xref; pdf_xref_subsec *sub; /* Make a new final xref section if we haven't already */ - ensure_incremental_xref(doc); + ensure_incremental_xref(ctx, doc); xref = &doc->xref_sections[0]; if (i >= xref->num_objects) @@ -331,10 +355,11 @@ static pdf_xref_entry *pdf_get_incremental_xref_entry(pdf_document *doc, int i) sub = xref->subsec; assert(sub != NULL && sub->next == NULL); assert(i >= sub->start && i < sub->start + sub->len); + doc->xref_index[i] = 0; return &sub->table[i - sub->start]; } -int pdf_xref_is_incremental(pdf_document *doc, int num) +int pdf_xref_is_incremental(fz_context *ctx, pdf_document *doc, int num) { pdf_xref *xref = &doc->xref_sections[0]; pdf_xref_subsec *sub = xref->subsec; @@ -346,26 +371,26 @@ int pdf_xref_is_incremental(pdf_document *doc, int num) /* Ensure that the current populating xref has a single subsection * that covers the entire range. */ -void pdf_ensure_solid_xref(pdf_document *doc, int num) +void pdf_ensure_solid_xref(fz_context *ctx, pdf_document *doc, int num) { if (doc->num_xref_sections == 0) - pdf_populate_next_xref_level(doc); + pdf_populate_next_xref_level(ctx, doc); - ensure_solid_xref(doc, num, doc->num_xref_sections-1); + ensure_solid_xref(ctx, doc, num, doc->num_xref_sections-1); } /* Ensure that an object has been cloned into the incremental xref section */ -void pdf_xref_ensure_incremental_object(pdf_document *doc, int num) +void pdf_xref_ensure_incremental_object(fz_context *ctx, pdf_document *doc, int num) { pdf_xref_entry *new_entry, *old_entry; pdf_xref_subsec *sub = NULL; int i; /* Make sure we have created an xref section for incremental updates */ - ensure_incremental_xref(doc); + ensure_incremental_xref(ctx, doc); /* Search for the section that contains this object */ - for (i = 0; i < doc->num_xref_sections; i++) + for (i = doc->xref_index[num]; i < doc->num_xref_sections; i++) { pdf_xref *xref = &doc->xref_sections[i]; @@ -386,28 +411,29 @@ void pdf_xref_ensure_incremental_object(pdf_document *doc, int num) return; /* Move the object to the incremental section */ + doc->xref_index[num] = 0; old_entry = &sub->table[num - sub->start]; - new_entry = pdf_get_incremental_xref_entry(doc, num); + new_entry = pdf_get_incremental_xref_entry(ctx, doc, num); *new_entry = *old_entry; old_entry->obj = NULL; old_entry->stm_buf = NULL; } -void pdf_replace_xref(pdf_document *doc, pdf_xref_entry *entries, int n) +void pdf_replace_xref(fz_context *ctx, pdf_document *doc, pdf_xref_entry *entries, int n) { - fz_context *ctx = doc->ctx; - pdf_xref *xref; + pdf_xref *xref = NULL; pdf_xref_subsec *sub; - pdf_obj *trailer = pdf_keep_obj(pdf_trailer(doc)); + pdf_obj *trailer = pdf_keep_obj(ctx, pdf_trailer(ctx, doc)); fz_var(xref); fz_try(ctx) { + doc->xref_index = fz_calloc(ctx, n, sizeof(int)); xref = fz_malloc_struct(ctx, pdf_xref); sub = fz_malloc_struct(ctx, pdf_xref_subsec); /* The new table completely replaces the previous separate sections */ - pdf_free_xref_sections(doc); + pdf_drop_xref_sections(ctx, doc); sub->table = entries; sub->start = 0; @@ -420,11 +446,13 @@ void pdf_replace_xref(pdf_document *doc, pdf_xref_entry *entries, int n) doc->xref_sections = xref; doc->num_xref_sections = 1; doc->max_xref_len = n; + + memset(doc->xref_index, 0, sizeof(int)*doc->max_xref_len); } fz_catch(ctx) { fz_free(ctx, xref); - pdf_drop_obj(trailer); + pdf_drop_obj(ctx, trailer); fz_rethrow(ctx); } } @@ -434,33 +462,33 @@ void pdf_replace_xref(pdf_document *doc, pdf_xref_entry *entries, int n) */ static void -pdf_load_version(pdf_document *doc) +pdf_load_version(fz_context *ctx, pdf_document *doc) { char buf[20]; - fz_seek(doc->file, 0, SEEK_SET); - fz_read_line(doc->file, buf, sizeof buf); + fz_seek(ctx, doc->file, 0, SEEK_SET); + fz_read_line(ctx, doc->file, buf, sizeof buf); if (memcmp(buf, "%PDF-", 5) != 0) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "cannot recognize version marker"); + fz_throw(ctx, FZ_ERROR_GENERIC, "cannot recognize version marker"); doc->version = 10 * (fz_atof(buf+5) + 0.05); } static void -pdf_read_start_xref(pdf_document *doc) +pdf_read_start_xref(fz_context *ctx, pdf_document *doc) { unsigned char buf[1024]; int t, n; int i; - fz_seek(doc->file, 0, SEEK_END); + fz_seek(ctx, doc->file, 0, SEEK_END); - doc->file_size = fz_tell(doc->file); + doc->file_size = fz_tell(ctx, doc->file); t = fz_maxi(0, doc->file_size - (int)sizeof buf); - fz_seek(doc->file, t, SEEK_SET); + fz_seek(ctx, doc->file, t, SEEK_SET); - n = fz_read(doc->file, buf, sizeof buf); + n = fz_read(ctx, doc->file, buf, sizeof buf); for (i = n - 9; i >= 0; i--) { @@ -478,7 +506,7 @@ pdf_read_start_xref(pdf_document *doc) } } - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "cannot find startxref"); + fz_throw(ctx, FZ_ERROR_GENERIC, "cannot find startxref"); } /* @@ -486,7 +514,7 @@ pdf_read_start_xref(pdf_document *doc) */ static int -pdf_xref_size_from_old_trailer(pdf_document *doc, pdf_lexbuf *buf) +pdf_xref_size_from_old_trailer(fz_context *ctx, pdf_document *doc, pdf_lexbuf *buf) { int len; char *s; @@ -500,82 +528,81 @@ pdf_xref_size_from_old_trailer(pdf_document *doc, pdf_lexbuf *buf) fz_var(trailer); /* Record the current file read offset so that we can reinstate it */ - ofs = fz_tell(doc->file); + ofs = fz_tell(ctx, doc->file); - fz_read_line(doc->file, buf->scratch, buf->size); + fz_read_line(ctx, doc->file, buf->scratch, buf->size); if (strncmp(buf->scratch, "xref", 4) != 0) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "cannot find xref marker"); + fz_throw(ctx, FZ_ERROR_GENERIC, "cannot find xref marker"); while (1) { - c = fz_peek_byte(doc->file); + c = fz_peek_byte(ctx, doc->file); if (!(c >= '0' && c <= '9')) break; - fz_read_line(doc->file, buf->scratch, buf->size); + fz_read_line(ctx, doc->file, buf->scratch, buf->size); s = buf->scratch; fz_strsep(&s, " "); /* ignore ofs */ if (!s) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "invalid range marker in xref"); + fz_throw(ctx, FZ_ERROR_GENERIC, "invalid range marker in xref"); len = fz_atoi(fz_strsep(&s, " ")); if (len < 0) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "xref range marker must be positive"); + fz_throw(ctx, FZ_ERROR_GENERIC, "xref range marker must be positive"); /* broken pdfs where the section is not on a separate line */ if (s && *s != '\0') - fz_seek(doc->file, -(2 + (int)strlen(s)), SEEK_CUR); + fz_seek(ctx, doc->file, -(2 + (int)strlen(s)), SEEK_CUR); - t = fz_tell(doc->file); + t = fz_tell(ctx, doc->file); if (t < 0) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "cannot tell in file"); + fz_throw(ctx, FZ_ERROR_GENERIC, "cannot tell in file"); if (len > (INT_MAX - t) / 20) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "xref has too many entries"); + fz_throw(ctx, FZ_ERROR_GENERIC, "xref has too many entries"); - fz_seek(doc->file, t + 20 * len, SEEK_SET); + fz_seek(ctx, doc->file, t + 20 * len, SEEK_SET); } - fz_try(doc->ctx) + fz_try(ctx) { - tok = pdf_lex(doc->file, buf); + tok = pdf_lex(ctx, doc->file, buf); if (tok != PDF_TOK_TRAILER) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "expected trailer marker"); + fz_throw(ctx, FZ_ERROR_GENERIC, "expected trailer marker"); - tok = pdf_lex(doc->file, buf); + tok = pdf_lex(ctx, doc->file, buf); if (tok != PDF_TOK_OPEN_DICT) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "expected trailer dictionary"); + fz_throw(ctx, FZ_ERROR_GENERIC, "expected trailer dictionary"); - trailer = pdf_parse_dict(doc, doc->file, buf); + trailer = pdf_parse_dict(ctx, doc, doc->file, buf); - size = pdf_to_int(pdf_dict_gets(trailer, "Size")); + size = pdf_to_int(ctx, pdf_dict_gets(ctx, trailer, "Size")); if (!size) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "trailer missing Size entry"); + fz_throw(ctx, FZ_ERROR_GENERIC, "trailer missing Size entry"); } - fz_always(doc->ctx) + fz_always(ctx) { - pdf_drop_obj(trailer); + pdf_drop_obj(ctx, trailer); } - fz_catch(doc->ctx) + fz_catch(ctx) { - fz_rethrow_message(doc->ctx, "cannot parse trailer"); + fz_rethrow_message(ctx, "cannot parse trailer"); } - fz_seek(doc->file, ofs, SEEK_SET); + fz_seek(ctx, doc->file, ofs, SEEK_SET); return size; } pdf_obj * -pdf_new_ref(pdf_document *doc, pdf_obj *obj) +pdf_new_ref(fz_context *ctx, pdf_document *doc, pdf_obj *obj) { - int num = pdf_create_object(doc); - pdf_update_object(doc, num, obj); - return pdf_new_indirect(doc, num, 0); + int num = pdf_create_object(ctx, doc); + pdf_update_object(ctx, doc, num, obj); + return pdf_new_indirect(ctx, doc, num, 0); } static pdf_xref_entry * -pdf_xref_find_subsection(pdf_document *doc, int ofs, int len) +pdf_xref_find_subsection(fz_context *ctx, pdf_document *doc, int ofs, int len) { - fz_context *ctx = doc->ctx; pdf_xref *xref = &doc->xref_sections[doc->num_xref_sections-1]; pdf_xref_subsec *sub; int new_max; @@ -619,20 +646,23 @@ pdf_xref_find_subsection(pdf_document *doc, int ofs, int len) } xref->num_objects = new_max; if (doc->max_xref_len < new_max) - doc->max_xref_len = new_max; + extend_xref_index(ctx, doc, new_max); } else { /* Case 3 */ - ensure_solid_xref(doc, new_max, 0); + ensure_solid_xref(ctx, doc, new_max, doc->num_xref_sections-1); + xref = &doc->xref_sections[doc->num_xref_sections-1]; sub = xref->subsec; } return &sub->table[ofs-sub->start]; } static pdf_obj * -pdf_read_old_xref(pdf_document *doc, pdf_lexbuf *buf) +pdf_read_old_xref(fz_context *ctx, pdf_document *doc, pdf_lexbuf *buf) { + fz_stream *file = doc->file; + int ofs, len; char *s; int n; @@ -640,20 +670,20 @@ pdf_read_old_xref(pdf_document *doc, pdf_lexbuf *buf) int i; int c; pdf_obj *trailer; - int xref_len = pdf_xref_size_from_old_trailer(doc, buf); + int xref_len = pdf_xref_size_from_old_trailer(ctx, doc, buf); pdf_xref_entry *table; - fz_read_line(doc->file, buf->scratch, buf->size); + fz_read_line(ctx, file, buf->scratch, buf->size); if (strncmp(buf->scratch, "xref", 4) != 0) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "cannot find xref marker"); + fz_throw(ctx, FZ_ERROR_GENERIC, "cannot find xref marker"); while (1) { - c = fz_peek_byte(doc->file); + c = fz_peek_byte(ctx, file); if (!(c >= '0' && c <= '9')) break; - fz_read_line(doc->file, buf->scratch, buf->size); + fz_read_line(ctx, file, buf->scratch, buf->size); s = buf->scratch; ofs = fz_atoi(fz_strsep(&s, " ")); len = fz_atoi(fz_strsep(&s, " ")); @@ -661,27 +691,27 @@ pdf_read_old_xref(pdf_document *doc, pdf_lexbuf *buf) /* broken pdfs where the section is not on a separate line */ if (s && *s != '\0') { - fz_warn(doc->ctx, "broken xref section. proceeding anyway."); - fz_seek(doc->file, -(2 + (int)strlen(s)), SEEK_CUR); + fz_warn(ctx, "broken xref section. proceeding anyway."); + fz_seek(ctx, file, -(2 + (int)strlen(s)), SEEK_CUR); } if (ofs < 0) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "out of range object num in xref: %d", ofs); + fz_throw(ctx, FZ_ERROR_GENERIC, "out of range object num in xref: %d", ofs); /* broken pdfs where size in trailer undershoots entries in xref sections */ if (ofs + len > xref_len) { - fz_warn(doc->ctx, "broken xref section, proceeding anyway."); + fz_warn(ctx, "broken xref section, proceeding anyway."); } - table = pdf_xref_find_subsection(doc, ofs, len); + table = pdf_xref_find_subsection(ctx, doc, ofs, len); for (i = ofs; i < ofs + len; i++) { pdf_xref_entry *entry = &table[i-ofs]; - n = fz_read(doc->file, (unsigned char *) buf->scratch, 20); + n = fz_read(ctx, file, (unsigned char *) buf->scratch, 20); if (n != 20) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "unexpected EOF in xref table"); + fz_throw(ctx, FZ_ERROR_GENERIC, "unexpected EOF in xref table"); if (!entry->type) { s = buf->scratch; @@ -694,42 +724,42 @@ pdf_read_old_xref(pdf_document *doc, pdf_lexbuf *buf) entry->gen = atoi(s + 11); entry->type = s[17]; if (s[17] != 'f' && s[17] != 'n' && s[17] != 'o') - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "unexpected xref type: %#x (%d %d R)", s[17], i, entry->gen); + fz_throw(ctx, FZ_ERROR_GENERIC, "unexpected xref type: %#x (%d %d R)", s[17], i, entry->gen); } } } - fz_try(doc->ctx) + fz_try(ctx) { - tok = pdf_lex(doc->file, buf); + tok = pdf_lex(ctx, file, buf); if (tok != PDF_TOK_TRAILER) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "expected trailer marker"); + fz_throw(ctx, FZ_ERROR_GENERIC, "expected trailer marker"); - tok = pdf_lex(doc->file, buf); + tok = pdf_lex(ctx, file, buf); if (tok != PDF_TOK_OPEN_DICT) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "expected trailer dictionary"); + fz_throw(ctx, FZ_ERROR_GENERIC, "expected trailer dictionary"); - trailer = pdf_parse_dict(doc, doc->file, buf); + trailer = pdf_parse_dict(ctx, doc, file, buf); } - fz_catch(doc->ctx) + fz_catch(ctx) { - fz_rethrow_message(doc->ctx, "cannot parse trailer"); + fz_rethrow_message(ctx, "cannot parse trailer"); } return trailer; } static void -pdf_read_new_xref_section(pdf_document *doc, fz_stream *stm, int i0, int i1, int w0, int w1, int w2) +pdf_read_new_xref_section(fz_context *ctx, pdf_document *doc, fz_stream *stm, int i0, int i1, int w0, int w1, int w2) { - int i, n; pdf_xref_entry *table; + int i, n; if (i0 < 0 || i1 < 0) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "negative xref stream entry index"); - //if (i0 + i1 > pdf_xref_len(doc)) - // fz_throw(doc->ctx, FZ_ERROR_GENERIC, "xref stream has too many entries"); + fz_throw(ctx, FZ_ERROR_GENERIC, "negative xref stream entry index"); + //if (i0 + i1 > pdf_xref_len(ctx, doc)) + // fz_throw(ctx, FZ_ERROR_GENERIC, "xref stream has too many entries"); - table = pdf_xref_find_subsection(doc, i0, i1); + table = pdf_xref_find_subsection(ctx, doc, i0, i1); for (i = i0; i < i0 + i1; i++) { pdf_xref_entry *entry = &table[i-i0]; @@ -737,15 +767,15 @@ pdf_read_new_xref_section(pdf_document *doc, fz_stream *stm, int i0, int i1, int int b = 0; int c = 0; - if (fz_is_eof(stm)) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "truncated xref stream"); + if (fz_is_eof(ctx, stm)) + fz_throw(ctx, FZ_ERROR_GENERIC, "truncated xref stream"); for (n = 0; n < w0; n++) - a = (a << 8) + fz_read_byte(stm); + a = (a << 8) + fz_read_byte(ctx, stm); for (n = 0; n < w1; n++) - b = (b << 8) + fz_read_byte(stm); + b = (b << 8) + fz_read_byte(ctx, stm); for (n = 0; n < w2; n++) - c = (c << 8) + fz_read_byte(stm); + c = (c << 8) + fz_read_byte(ctx, stm); if (!entry->type) { @@ -761,7 +791,7 @@ pdf_read_new_xref_section(pdf_document *doc, fz_stream *stm, int i0, int i1, int /* Entered with file locked, remains locked throughout. */ static pdf_obj * -pdf_read_new_xref(pdf_document *doc, pdf_lexbuf *buf) +pdf_read_new_xref(fz_context *ctx, pdf_document *doc, pdf_lexbuf *buf) { fz_stream *stm = NULL; pdf_obj *trailer = NULL; @@ -770,19 +800,18 @@ pdf_read_new_xref(pdf_document *doc, pdf_lexbuf *buf) int num, gen, ofs, stm_ofs; int size, w0, w1, w2; int t; - fz_context *ctx = doc->ctx; fz_var(trailer); fz_var(stm); fz_try(ctx) { - ofs = fz_tell(doc->file); - trailer = pdf_parse_ind_obj(doc, doc->file, buf, &num, &gen, &stm_ofs, NULL); + ofs = fz_tell(ctx, doc->file); + trailer = pdf_parse_ind_obj(ctx, doc, doc->file, buf, &num, &gen, &stm_ofs, NULL); } fz_catch(ctx) { - pdf_drop_obj(trailer); + pdf_drop_obj(ctx, trailer); fz_rethrow_message(ctx, "cannot parse compressed xref stream object"); } @@ -790,18 +819,18 @@ pdf_read_new_xref(pdf_document *doc, pdf_lexbuf *buf) { pdf_xref_entry *entry; - obj = pdf_dict_gets(trailer, "Size"); + obj = pdf_dict_gets(ctx, trailer, "Size"); if (!obj) fz_throw(ctx, FZ_ERROR_GENERIC, "xref stream missing Size entry (%d %d R)", num, gen); - size = pdf_to_int(obj); + size = pdf_to_int(ctx, obj); - obj = pdf_dict_gets(trailer, "W"); + obj = pdf_dict_gets(ctx, trailer, "W"); if (!obj) fz_throw(ctx, FZ_ERROR_GENERIC, "xref stream missing W entry (%d %d R)", num, gen); - w0 = pdf_to_int(pdf_array_get(obj, 0)); - w1 = pdf_to_int(pdf_array_get(obj, 1)); - w2 = pdf_to_int(pdf_array_get(obj, 2)); + w0 = pdf_to_int(ctx, pdf_array_get(ctx, obj, 0)); + w1 = pdf_to_int(ctx, pdf_array_get(ctx, obj, 1)); + w2 = pdf_to_int(ctx, pdf_array_get(ctx, obj, 2)); if (w0 < 0) fz_warn(ctx, "xref stream objects have corrupt type"); @@ -814,39 +843,39 @@ pdf_read_new_xref(pdf_document *doc, pdf_lexbuf *buf) w1 = w1 < 0 ? 0 : w1; w2 = w2 < 0 ? 0 : w2; - index = pdf_dict_gets(trailer, "Index"); + index = pdf_dict_gets(ctx, trailer, "Index"); - stm = pdf_open_stream_with_offset(doc, num, gen, trailer, stm_ofs); + stm = pdf_open_stream_with_offset(ctx, doc, num, gen, trailer, stm_ofs); if (!index) { - pdf_read_new_xref_section(doc, stm, 0, size, w0, w1, w2); + pdf_read_new_xref_section(ctx, doc, stm, 0, size, w0, w1, w2); } else { - int n = pdf_array_len(index); + int n = pdf_array_len(ctx, index); for (t = 0; t < n; t += 2) { - int i0 = pdf_to_int(pdf_array_get(index, t + 0)); - int i1 = pdf_to_int(pdf_array_get(index, t + 1)); - pdf_read_new_xref_section(doc, stm, i0, i1, w0, w1, w2); + int i0 = pdf_to_int(ctx, pdf_array_get(ctx, index, t + 0)); + int i1 = pdf_to_int(ctx, pdf_array_get(ctx, index, t + 1)); + pdf_read_new_xref_section(ctx, doc, stm, i0, i1, w0, w1, w2); } } - entry = pdf_get_populating_xref_entry(doc, num); + entry = pdf_get_populating_xref_entry(ctx, doc, num); entry->ofs = ofs; entry->gen = gen; entry->stm_ofs = stm_ofs; - pdf_drop_obj(entry->obj); - entry->obj = pdf_keep_obj(trailer); + pdf_drop_obj(ctx, entry->obj); + entry->obj = pdf_keep_obj(ctx, trailer); entry->type = 'n'; } fz_always(ctx) { - fz_close(stm); + fz_drop_stream(ctx, stm); } fz_catch(ctx) { - pdf_drop_obj(trailer); + pdf_drop_obj(ctx, trailer); fz_rethrow(ctx); } @@ -854,24 +883,23 @@ pdf_read_new_xref(pdf_document *doc, pdf_lexbuf *buf) } static pdf_obj * -pdf_read_xref(pdf_document *doc, int ofs, pdf_lexbuf *buf) +pdf_read_xref(fz_context *ctx, pdf_document *doc, int ofs, pdf_lexbuf *buf) { - int c; - fz_context *ctx = doc->ctx; pdf_obj *trailer; + int c; - fz_seek(doc->file, ofs, SEEK_SET); + fz_seek(ctx, doc->file, ofs, SEEK_SET); - while (iswhite(fz_peek_byte(doc->file))) - fz_read_byte(doc->file); + while (iswhite(fz_peek_byte(ctx, doc->file))) + fz_read_byte(ctx, doc->file); fz_try(ctx) { - c = fz_peek_byte(doc->file); + c = fz_peek_byte(ctx, doc->file); if (c == 'x') - trailer = pdf_read_old_xref(doc, buf); + trailer = pdf_read_old_xref(ctx, doc, buf); else if (c >= '0' && c <= '9') - trailer = pdf_read_new_xref(doc, buf); + trailer = pdf_read_new_xref(ctx, doc, buf); else fz_throw(ctx, FZ_ERROR_GENERIC, "cannot recognize xref format"); } @@ -892,10 +920,9 @@ struct ofs_list_s }; static int -read_xref_section(pdf_document *doc, int ofs, pdf_lexbuf *buf, ofs_list *offsets) +read_xref_section(fz_context *ctx, pdf_document *doc, int ofs, pdf_lexbuf *buf, ofs_list *offsets) { pdf_obj *trailer = NULL; - fz_context *ctx = doc->ctx; int xrefstmofs = 0; int prevofs = 0; @@ -922,13 +949,13 @@ read_xref_section(pdf_document *doc, int ofs, pdf_lexbuf *buf, ofs_list *offsets } offsets->list[offsets->len++] = ofs; - trailer = pdf_read_xref(doc, ofs, buf); + trailer = pdf_read_xref(ctx, doc, ofs, buf); - pdf_set_populating_xref_trailer(doc, trailer); + pdf_set_populating_xref_trailer(ctx, doc, trailer); /* FIXME: do we overwrite free entries properly? */ /* FIXME: Does this work properly with progression? */ - xrefstmofs = pdf_to_int(pdf_dict_gets(trailer, "XRefStm")); + xrefstmofs = pdf_to_int(ctx, pdf_dict_gets(ctx, trailer, "XRefStm")); if (xrefstmofs) { if (xrefstmofs < 0) @@ -939,16 +966,16 @@ read_xref_section(pdf_document *doc, int ofs, pdf_lexbuf *buf, ofs_list *offsets follow any Prev tag therein, as specified on Page 108 of the PDF reference 1.7 */ - pdf_drop_obj(pdf_read_xref(doc, xrefstmofs, buf)); + pdf_drop_obj(ctx, pdf_read_xref(ctx, doc, xrefstmofs, buf)); } - prevofs = pdf_to_int(pdf_dict_gets(trailer, "Prev")); + prevofs = pdf_to_int(ctx, pdf_dict_gets(ctx, trailer, "Prev")); if (prevofs < 0) fz_throw(ctx, FZ_ERROR_GENERIC, "negative xref stream offset for previous xref stream"); } fz_always(ctx) { - pdf_drop_obj(trailer); + pdf_drop_obj(ctx, trailer); } fz_catch(ctx) { @@ -959,9 +986,8 @@ read_xref_section(pdf_document *doc, int ofs, pdf_lexbuf *buf, ofs_list *offsets } static void -pdf_read_xref_sections(pdf_document *doc, int ofs, pdf_lexbuf *buf, int read_previous) +pdf_read_xref_sections(fz_context *ctx, pdf_document *doc, int ofs, pdf_lexbuf *buf, int read_previous) { - fz_context *ctx = doc->ctx; ofs_list list; list.len = 0; @@ -971,8 +997,8 @@ pdf_read_xref_sections(pdf_document *doc, int ofs, pdf_lexbuf *buf, int read_pre { while(ofs) { - pdf_populate_next_xref_level(doc); - ofs = read_xref_section(doc, ofs, buf, &list); + pdf_populate_next_xref_level(ctx, doc); + ofs = read_xref_section(ctx, doc, ofs, buf, &list); if (!read_previous) break; } @@ -987,6 +1013,32 @@ pdf_read_xref_sections(pdf_document *doc, int ofs, pdf_lexbuf *buf, int read_pre } } +static void +pdf_prime_xref_index(fz_context *ctx, pdf_document *doc) +{ + int i, j; + int *idx = doc->xref_index; + + for (i = doc->num_xref_sections-1; i >= 0; i--) + { + pdf_xref *xref = &doc->xref_sections[i]; + pdf_xref_subsec *subsec = xref->subsec; + while (subsec != NULL) + { + int start = subsec->start; + int end = subsec->start + subsec->len; + for (j = start; j < end; j++) + { + char t = subsec->table[j-start].type; + if (t != 0 && t != 'f') + idx[j] = i; + } + + subsec = subsec->next; + } + } +} + /* * load xref tables from pdf * @@ -994,21 +1046,22 @@ pdf_read_xref_sections(pdf_document *doc, int ofs, pdf_lexbuf *buf, int read_pre */ static void -pdf_load_xref(pdf_document *doc, pdf_lexbuf *buf) +pdf_load_xref(fz_context *ctx, pdf_document *doc, pdf_lexbuf *buf) { int i; int xref_len; pdf_xref_entry *entry; - fz_context *ctx = doc->ctx; - pdf_read_start_xref(doc); + pdf_read_start_xref(ctx, doc); - pdf_read_xref_sections(doc, doc->startxref, buf, 1); + pdf_read_xref_sections(ctx, doc, doc->startxref, buf, 1); - if (pdf_xref_len(doc) == 0) + if (pdf_xref_len(ctx, doc) == 0) fz_throw(ctx, FZ_ERROR_GENERIC, "found xref was empty"); - entry = pdf_get_xref_entry(doc, 0); + pdf_prime_xref_index(ctx, doc); + + entry = pdf_get_xref_entry(ctx, doc, 0); /* broken pdfs where first object is missing */ if (!entry->type) { @@ -1020,10 +1073,10 @@ pdf_load_xref(pdf_document *doc, pdf_lexbuf *buf) fz_throw(ctx, FZ_ERROR_GENERIC, "first object in xref is not free"); /* broken pdfs where object offsets are out of range */ - xref_len = pdf_xref_len(doc); + xref_len = pdf_xref_len(ctx, doc); for (i = 0; i < xref_len; i++) { - pdf_xref_entry *entry = pdf_get_xref_entry(doc, i); + pdf_xref_entry *entry = pdf_get_xref_entry(ctx, doc, i); if (entry->type == 'n') { /* Special case code: "0000000000 * n" means free, @@ -1034,19 +1087,18 @@ pdf_load_xref(pdf_document *doc, pdf_lexbuf *buf) fz_throw(ctx, FZ_ERROR_GENERIC, "object offset out of range: %d (%d 0 R)", entry->ofs, i); } if (entry->type == 'o') - if (entry->ofs <= 0 || entry->ofs >= xref_len || pdf_get_xref_entry(doc, entry->ofs)->type != 'n') + if (entry->ofs <= 0 || entry->ofs >= xref_len || pdf_get_xref_entry(ctx, doc, entry->ofs)->type != 'n') fz_throw(ctx, FZ_ERROR_GENERIC, "invalid reference to an objstm that does not exist: %d (%d 0 R)", entry->ofs, i); } } static void -pdf_load_linear(pdf_document *doc) +pdf_load_linear(fz_context *ctx, pdf_document *doc) { pdf_obj *dict = NULL; pdf_obj *hint = NULL; pdf_obj *o; int num, gen, stmofs, lin, len; - fz_context *ctx = doc->ctx; fz_var(dict); fz_var(hint); @@ -1055,39 +1107,39 @@ pdf_load_linear(pdf_document *doc) { pdf_xref_entry *entry; - dict = pdf_parse_ind_obj(doc, doc->file, &doc->lexbuf.base, &num, &gen, &stmofs, NULL); - if (!pdf_is_dict(dict)) + dict = pdf_parse_ind_obj(ctx, doc, doc->file, &doc->lexbuf.base, &num, &gen, &stmofs, NULL); + if (!pdf_is_dict(ctx, dict)) fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to read linearized dictionary"); - o = pdf_dict_gets(dict, "Linearized"); + o = pdf_dict_gets(ctx, dict, "Linearized"); if (o == NULL) fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to read linearized dictionary"); - lin = pdf_to_int(o); + lin = pdf_to_int(ctx, o); if (lin != 1) fz_throw(ctx, FZ_ERROR_GENERIC, "Unexpected version of Linearized tag (%d)", lin); - len = pdf_to_int(pdf_dict_gets(dict, "L")); + len = pdf_to_int(ctx, pdf_dict_gets(ctx, dict, "L")); if (len != doc->file_length) fz_throw(ctx, FZ_ERROR_GENERIC, "File has been updated since linearization"); - pdf_read_xref_sections(doc, fz_tell(doc->file), &doc->lexbuf.base, 0); + pdf_read_xref_sections(ctx, doc, fz_tell(ctx, doc->file), &doc->lexbuf.base, 0); - doc->page_count = pdf_to_int(pdf_dict_gets(dict, "N")); + doc->page_count = pdf_to_int(ctx, pdf_dict_gets(ctx, dict, "N")); doc->linear_page_refs = fz_resize_array(ctx, doc->linear_page_refs, doc->page_count, sizeof(pdf_obj *)); memset(doc->linear_page_refs, 0, doc->page_count * sizeof(pdf_obj*)); doc->linear_obj = dict; - doc->linear_pos = fz_tell(doc->file); - doc->linear_page1_obj_num = pdf_to_int(pdf_dict_gets(dict, "O")); - doc->linear_page_refs[0] = pdf_new_indirect(doc, doc->linear_page1_obj_num, 0); + doc->linear_pos = fz_tell(ctx, doc->file); + doc->linear_page1_obj_num = pdf_to_int(ctx, pdf_dict_gets(ctx, dict, "O")); + doc->linear_page_refs[0] = pdf_new_indirect(ctx, doc, doc->linear_page1_obj_num, 0); doc->linear_page_num = 0; - hint = pdf_dict_gets(dict, "H"); - doc->hint_object_offset = pdf_to_int(pdf_array_get(hint, 0)); - doc->hint_object_length = pdf_to_int(pdf_array_get(hint, 1)); + hint = pdf_dict_gets(ctx, dict, "H"); + doc->hint_object_offset = pdf_to_int(ctx, pdf_array_get(ctx, hint, 0)); + doc->hint_object_length = pdf_to_int(ctx, pdf_array_get(ctx, hint, 1)); - entry = pdf_get_populating_xref_entry(doc, 0); + entry = pdf_get_populating_xref_entry(ctx, doc, 0); entry->type = 'f'; } fz_catch(ctx) { - pdf_drop_obj(dict); + pdf_drop_obj(ctx, dict); fz_rethrow_if(ctx, FZ_ERROR_TRYLATER); /* Drop back to non linearized reading mode */ doc->file_reading_linearly = 0; @@ -1095,41 +1147,41 @@ pdf_load_linear(pdf_document *doc) } void -pdf_ocg_set_config(pdf_document *doc, int config) +pdf_ocg_set_config(fz_context *ctx, pdf_document *doc, int config) { int i, j, len, len2; pdf_ocg_descriptor *desc = doc->ocg; pdf_obj *obj, *cobj; char *name; - obj = pdf_dict_gets(pdf_dict_gets(pdf_trailer(doc), "Root"), "OCProperties"); + obj = pdf_dict_gets(ctx, pdf_dict_gets(ctx, pdf_trailer(ctx, doc), "Root"), "OCProperties"); if (!obj) { if (config == 0) return; else - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "Unknown OCG config (None known!)"); + fz_throw(ctx, FZ_ERROR_GENERIC, "Unknown OCG config (None known!)"); } if (config == 0) { - cobj = pdf_dict_gets(obj, "D"); + cobj = pdf_dict_gets(ctx, obj, "D"); if (!cobj) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "No default OCG config"); + fz_throw(ctx, FZ_ERROR_GENERIC, "No default OCG config"); } else { - cobj = pdf_array_get(pdf_dict_gets(obj, "Configs"), config); + cobj = pdf_array_get(ctx, pdf_dict_gets(ctx, obj, "Configs"), config); if (!cobj) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "Illegal OCG config"); + fz_throw(ctx, FZ_ERROR_GENERIC, "Illegal OCG config"); } - pdf_drop_obj(desc->intent); - desc->intent = pdf_dict_gets(cobj, "Intent"); + pdf_drop_obj(ctx, desc->intent); + desc->intent = pdf_dict_gets(ctx, cobj, "Intent"); if (desc->intent) - pdf_keep_obj(desc->intent); + pdf_keep_obj(ctx, desc->intent); len = desc->len; - name = pdf_to_name(pdf_dict_gets(cobj, "BaseState")); + name = pdf_to_name(ctx, pdf_dict_gets(ctx, cobj, "BaseState")); if (strcmp(name, "Unchanged") == 0) { /* Do nothing */ @@ -1149,13 +1201,13 @@ pdf_ocg_set_config(pdf_document *doc, int config) } } - obj = pdf_dict_gets(cobj, "ON"); - len2 = pdf_array_len(obj); + obj = pdf_dict_gets(ctx, cobj, "ON"); + len2 = pdf_array_len(ctx, obj); for (i = 0; i < len2; i++) { - pdf_obj *o = pdf_array_get(obj, i); - int n = pdf_to_num(o); - int g = pdf_to_gen(o); + pdf_obj *o = pdf_array_get(ctx, obj, i); + int n = pdf_to_num(ctx, o); + int g = pdf_to_gen(ctx, o); for (j=0; j < len; j++) { if (desc->ocgs[j].num == n && desc->ocgs[j].gen == g) @@ -1166,13 +1218,13 @@ pdf_ocg_set_config(pdf_document *doc, int config) } } - obj = pdf_dict_gets(cobj, "OFF"); - len2 = pdf_array_len(obj); + obj = pdf_dict_gets(ctx, cobj, "OFF"); + len2 = pdf_array_len(ctx, obj); for (i = 0; i < len2; i++) { - pdf_obj *o = pdf_array_get(obj, i); - int n = pdf_to_num(o); - int g = pdf_to_gen(o); + pdf_obj *o = pdf_array_get(ctx, obj, i); + int n = pdf_to_num(ctx, o); + int g = pdf_to_gen(ctx, o); for (j=0; j < len; j++) { if (desc->ocgs[j].num == n && desc->ocgs[j].gen == g) @@ -1199,23 +1251,22 @@ pdf_ocg_set_config(pdf_document *doc, int config) } static void -pdf_read_ocg(pdf_document *doc) +pdf_read_ocg(fz_context *ctx, pdf_document *doc) { pdf_obj *obj, *ocg; int len, i; pdf_ocg_descriptor *desc; - fz_context *ctx = doc->ctx; fz_var(desc); - obj = pdf_dict_gets(pdf_dict_gets(pdf_trailer(doc), "Root"), "OCProperties"); + obj = pdf_dict_gets(ctx, pdf_dict_gets(ctx, pdf_trailer(ctx, doc), "Root"), "OCProperties"); if (!obj) return; - ocg = pdf_dict_gets(obj, "OCGs"); - if (!ocg || !pdf_is_array(ocg)) + ocg = pdf_dict_gets(ctx, obj, "OCGs"); + if (!ocg || !pdf_is_array(ctx, ocg)) /* Not ever supposed to happen, but live with it. */ return; - len = pdf_array_len(ocg); + len = pdf_array_len(ctx, ocg); fz_try(ctx) { desc = fz_calloc(ctx, 1, sizeof(*desc)); @@ -1224,9 +1275,9 @@ pdf_read_ocg(pdf_document *doc) desc->intent = NULL; for (i=0; i < len; i++) { - pdf_obj *o = pdf_array_get(ocg, i); - desc->ocgs[i].num = pdf_to_num(o); - desc->ocgs[i].gen = pdf_to_gen(o); + pdf_obj *o = pdf_array_get(ctx, ocg, i); + desc->ocgs[i].num = pdf_to_num(ctx, o); + desc->ocgs[i].gen = pdf_to_gen(ctx, o); desc->ocgs[i].state = 1; } doc->ocg = desc; @@ -1239,16 +1290,16 @@ pdf_read_ocg(pdf_document *doc) fz_rethrow(ctx); } - pdf_ocg_set_config(doc, 0); + pdf_ocg_set_config(ctx, doc, 0); } static void -pdf_free_ocg(fz_context *ctx, pdf_ocg_descriptor *desc) +pdf_drop_ocg(fz_context *ctx, pdf_ocg_descriptor *desc) { if (!desc) return; - pdf_drop_obj(desc->intent); + pdf_drop_obj(ctx, desc->intent); fz_free(ctx, desc->ocgs); fz_free(ctx, desc); } @@ -1259,9 +1310,8 @@ pdf_free_ocg(fz_context *ctx, pdf_ocg_descriptor *desc) */ static void -pdf_init_document(pdf_document *doc) +pdf_init_document(fz_context *ctx, pdf_document *doc) { - fz_context *ctx = doc->ctx; pdf_obj *encrypt, *id; pdf_obj *dict = NULL; pdf_obj *obj; @@ -1273,30 +1323,30 @@ pdf_init_document(pdf_document *doc) fz_try(ctx) { - pdf_load_version(doc); + pdf_load_version(ctx, doc); - doc->file_length = fz_stream_meta(doc->file, FZ_STREAM_META_LENGTH, 0, NULL); + doc->file_length = fz_stream_meta(ctx, doc->file, FZ_STREAM_META_LENGTH, 0, NULL); if (doc->file_length < 0) doc->file_length = 0; /* Check to see if we should work in progressive mode */ - if (fz_stream_meta(doc->file, FZ_STREAM_META_PROGRESSIVE, 0, NULL) > 0) + if (fz_stream_meta(ctx, doc->file, FZ_STREAM_META_PROGRESSIVE, 0, NULL) > 0) doc->file_reading_linearly = 1; /* Try to load the linearized file if we are in progressive * mode. */ if (doc->file_reading_linearly) - pdf_load_linear(doc); + pdf_load_linear(ctx, doc); /* If we aren't in progressive mode (or the linear load failed * and has set us back to non-progressive mode), load normally. */ if (!doc->file_reading_linearly) - pdf_load_xref(doc, &doc->lexbuf.base); + pdf_load_xref(ctx, doc, &doc->lexbuf.base); } fz_catch(ctx) { - pdf_free_xref_sections(doc); + pdf_drop_xref_sections(ctx, doc); fz_rethrow_if(ctx, FZ_ERROR_TRYLATER); fz_warn(ctx, "trying to repair broken xref"); repaired = 1; @@ -1307,33 +1357,38 @@ pdf_init_document(pdf_document *doc) int hasroot, hasinfo; if (repaired) - pdf_repair_xref(doc, &doc->lexbuf.base); + { + /* pdf_repair_xref may access xref_index, so reset it properly */ + memset(doc->xref_index, 0, sizeof(int) * doc->max_xref_len); + pdf_repair_xref(ctx, doc); + pdf_prime_xref_index(ctx, doc); + } - encrypt = pdf_dict_gets(pdf_trailer(doc), "Encrypt"); - id = pdf_dict_gets(pdf_trailer(doc), "ID"); - if (pdf_is_dict(encrypt)) + encrypt = pdf_dict_gets(ctx, pdf_trailer(ctx, doc), "Encrypt"); + id = pdf_dict_gets(ctx, pdf_trailer(ctx, doc), "ID"); + if (pdf_is_dict(ctx, encrypt)) doc->crypt = pdf_new_crypt(ctx, encrypt, id); /* Allow lazy clients to read encrypted files with a blank password */ - pdf_authenticate_password(doc, ""); + pdf_authenticate_password(ctx, doc, ""); if (repaired) { - int xref_len = pdf_xref_len(doc); - pdf_repair_obj_stms(doc); + int xref_len = pdf_xref_len(ctx, doc); + pdf_repair_obj_stms(ctx, doc); - hasroot = (pdf_dict_gets(pdf_trailer(doc), "Root") != NULL); - hasinfo = (pdf_dict_gets(pdf_trailer(doc), "Info") != NULL); + hasroot = (pdf_dict_gets(ctx, pdf_trailer(ctx, doc), "Root") != NULL); + hasinfo = (pdf_dict_gets(ctx, pdf_trailer(ctx, doc), "Info") != NULL); for (i = 1; i < xref_len; i++) { - pdf_xref_entry *entry = pdf_get_xref_entry(doc, i); + pdf_xref_entry *entry = pdf_get_xref_entry(ctx, doc, i); if (entry->type == 0 || entry->type == 'f') continue; fz_try(ctx) { - dict = pdf_load_object(doc, i, 0); + dict = pdf_load_object(ctx, doc, i, 0); } fz_catch(ctx) { @@ -1344,46 +1399,46 @@ pdf_init_document(pdf_document *doc) if (!hasroot) { - obj = pdf_dict_gets(dict, "Type"); - if (pdf_is_name(obj) && !strcmp(pdf_to_name(obj), "Catalog")) + obj = pdf_dict_gets(ctx, dict, "Type"); + if (pdf_is_name(ctx, obj) && !strcmp(pdf_to_name(ctx, obj), "Catalog")) { - nobj = pdf_new_indirect(doc, i, 0); - pdf_dict_puts(pdf_trailer(doc), "Root", nobj); - pdf_drop_obj(nobj); + nobj = pdf_new_indirect(ctx, doc, i, 0); + pdf_dict_puts(ctx, pdf_trailer(ctx, doc), "Root", nobj); + pdf_drop_obj(ctx, nobj); nobj = NULL; } } if (!hasinfo) { - if (pdf_dict_gets(dict, "Creator") || pdf_dict_gets(dict, "Producer")) + if (pdf_dict_gets(ctx, dict, "Creator") || pdf_dict_gets(ctx, dict, "Producer")) { - nobj = pdf_new_indirect(doc, i, 0); - pdf_dict_puts(pdf_trailer(doc), "Info", nobj); - pdf_drop_obj(nobj); + nobj = pdf_new_indirect(ctx, doc, i, 0); + pdf_dict_puts(ctx, pdf_trailer(ctx, doc), "Info", nobj); + pdf_drop_obj(ctx, nobj); nobj = NULL; } } - pdf_drop_obj(dict); + pdf_drop_obj(ctx, dict); dict = NULL; } /* ensure that strings are not used in their repaired, non-decrypted form */ if (doc->crypt) - pdf_clear_xref(doc); + pdf_clear_xref(ctx, doc); } } fz_catch(ctx) { - pdf_drop_obj(dict); - pdf_drop_obj(nobj); + pdf_drop_obj(ctx, dict); + pdf_drop_obj(ctx, nobj); fz_rethrow_message(ctx, "cannot open document"); } fz_try(ctx) { - pdf_read_ocg(doc); + pdf_read_ocg(ctx, doc); } fz_catch(ctx) { @@ -1393,8 +1448,8 @@ pdf_init_document(pdf_document *doc) fz_try(ctx) { char *version_str; - obj = pdf_dict_getp(pdf_trailer(doc), "Root/Version"); - version_str = pdf_to_name(obj); + obj = pdf_dict_getp(ctx, pdf_trailer(ctx, doc), "Root/Version"); + version_str = pdf_to_name(ctx, obj); if (*version_str) { int version = 10 * (fz_atof(version_str) + 0.05); @@ -1406,15 +1461,13 @@ pdf_init_document(pdf_document *doc) } void -pdf_close_document(pdf_document *doc) +pdf_close_document(fz_context *ctx, pdf_document *doc) { - fz_context *ctx; pdf_unsaved_sig *usig; int i; if (!doc) return; - ctx = doc->ctx; /* Type3 glyphs in the glyph cache can contain pdf_obj pointers * that we are about to destroy. Simplest solution is to bin the @@ -1424,21 +1477,22 @@ pdf_close_document(pdf_document *doc) if (doc->js) doc->drop_js(doc->js); - pdf_free_xref_sections(doc); + pdf_drop_xref_sections(ctx, doc); + fz_free(ctx, doc->xref_index); if (doc->focus_obj) - pdf_drop_obj(doc->focus_obj); + pdf_drop_obj(ctx, doc->focus_obj); if (doc->file) - fz_close(doc->file); + fz_drop_stream(ctx, doc->file); if (doc->crypt) - pdf_free_crypt(ctx, doc->crypt); + pdf_drop_crypt(ctx, doc->crypt); - pdf_drop_obj(doc->linear_obj); + pdf_drop_obj(ctx, doc->linear_obj); if (doc->linear_page_refs) { for (i=0; i < doc->page_count; i++) { - pdf_drop_obj(doc->linear_page_refs[i]); + pdf_drop_obj(ctx, doc->linear_page_refs[i]); } fz_free(ctx, doc->linear_page_refs); } @@ -1450,8 +1504,8 @@ pdf_close_document(pdf_document *doc) while ((usig = doc->unsaved_sigs) != NULL) { doc->unsaved_sigs = usig->next; - pdf_drop_obj(usig->field); - pdf_drop_signer(usig->signer); + pdf_drop_obj(ctx, usig->field); + pdf_drop_signer(ctx, usig->signer); fz_free(ctx, usig); } @@ -1462,24 +1516,24 @@ pdf_close_document(pdf_document *doc) } fz_free(ctx, doc->type3_fonts); - pdf_free_ocg(ctx, doc->ocg); + pdf_drop_ocg(ctx, doc->ocg); fz_empty_store(ctx); - pdf_lexbuf_fin(&doc->lexbuf.base); + pdf_lexbuf_fin(ctx, &doc->lexbuf.base); fz_free(ctx, doc); } void -pdf_print_xref(pdf_document *doc) +pdf_print_xref(fz_context *ctx, pdf_document *doc) { int i; - int xref_len = pdf_xref_len(doc); + int xref_len = pdf_xref_len(ctx, doc); printf("xref\n0 %d\n", xref_len); for (i = 0; i < xref_len; i++) { - pdf_xref_entry *entry = pdf_get_xref_entry(doc, i); + pdf_xref_entry *entry = pdf_get_xref_entry(ctx, doc, i); printf("%05d: %010d %05d %c (stm_ofs=%d; stm_buf=%p)\n", i, entry->ofs, entry->gen, @@ -1493,8 +1547,8 @@ pdf_print_xref(pdf_document *doc) * compressed object streams */ -static void -pdf_load_obj_stm(pdf_document *doc, int num, int gen, pdf_lexbuf *buf) +static pdf_xref_entry * +pdf_load_obj_stm(fz_context *ctx, pdf_document *doc, int num, int gen, pdf_lexbuf *buf, int target) { fz_stream *stm = NULL; pdf_obj *objstm = NULL; @@ -1506,7 +1560,7 @@ pdf_load_obj_stm(pdf_document *doc, int num, int gen, pdf_lexbuf *buf) int count; int i; pdf_token tok; - fz_context *ctx = doc->ctx; + pdf_xref_entry *ret_entry = NULL; fz_var(numbuf); fz_var(ofsbuf); @@ -1515,10 +1569,10 @@ pdf_load_obj_stm(pdf_document *doc, int num, int gen, pdf_lexbuf *buf) fz_try(ctx) { - objstm = pdf_load_object(doc, num, gen); + objstm = pdf_load_object(ctx, doc, num, gen); - count = pdf_to_int(pdf_dict_gets(objstm, "N")); - first = pdf_to_int(pdf_dict_gets(objstm, "First")); + count = pdf_to_int(ctx, pdf_dict_gets(ctx, objstm, "N")); + first = pdf_to_int(ctx, pdf_dict_gets(ctx, objstm, "First")); if (count < 0) fz_throw(ctx, FZ_ERROR_GENERIC, "negative number of objects in object stream"); @@ -1528,39 +1582,39 @@ pdf_load_obj_stm(pdf_document *doc, int num, int gen, pdf_lexbuf *buf) numbuf = fz_calloc(ctx, count, sizeof(int)); ofsbuf = fz_calloc(ctx, count, sizeof(int)); - stm = pdf_open_stream(doc, num, gen); + stm = pdf_open_stream(ctx, doc, num, gen); for (i = 0; i < count; i++) { - tok = pdf_lex(stm, buf); + tok = pdf_lex(ctx, stm, buf); if (tok != PDF_TOK_INT) fz_throw(ctx, FZ_ERROR_GENERIC, "corrupt object stream (%d %d R)", num, gen); numbuf[i] = buf->i; - tok = pdf_lex(stm, buf); + tok = pdf_lex(ctx, stm, buf); if (tok != PDF_TOK_INT) fz_throw(ctx, FZ_ERROR_GENERIC, "corrupt object stream (%d %d R)", num, gen); ofsbuf[i] = buf->i; } - fz_seek(stm, first, SEEK_SET); + fz_seek(ctx, stm, first, SEEK_SET); for (i = 0; i < count; i++) { - int xref_len = pdf_xref_len(doc); + int xref_len = pdf_xref_len(ctx, doc); pdf_xref_entry *entry; - fz_seek(stm, first + ofsbuf[i], SEEK_SET); + fz_seek(ctx, stm, first + ofsbuf[i], SEEK_SET); - obj = pdf_parse_stm_obj(doc, stm, buf); + obj = pdf_parse_stm_obj(ctx, doc, stm, buf); if (numbuf[i] <= 0 || numbuf[i] >= xref_len) { - pdf_drop_obj(obj); + pdf_drop_obj(ctx, obj); fz_throw(ctx, FZ_ERROR_GENERIC, "object id (%d 0 R) out of range (0..%d)", numbuf[i], xref_len - 1); } - entry = pdf_get_xref_entry(doc, numbuf[i]); + entry = pdf_get_xref_entry(ctx, doc, numbuf[i]); - pdf_set_obj_parent(obj, numbuf[i]); + pdf_set_obj_parent(ctx, obj, numbuf[i]); if (entry->type == 'o' && entry->ofs == num) { @@ -1570,51 +1624,55 @@ pdf_load_obj_stm(pdf_document *doc, int num, int gen, pdf_lexbuf *buf) * a pointer to the old one will be left with a * stale pointer. Instead, we drop the new one * and trust that the old one is correct. */ - if (entry->obj) { - if (pdf_objcmp(entry->obj, obj)) + if (entry->obj) + { + if (pdf_objcmp(ctx, entry->obj, obj)) fz_warn(ctx, "Encountered new definition for object %d - keeping the original one", numbuf[i]); - pdf_drop_obj(obj); - } else + pdf_drop_obj(ctx, obj); + } + else entry->obj = obj; + if (numbuf[i] == target) + ret_entry = entry; } else { - pdf_drop_obj(obj); + pdf_drop_obj(ctx, obj); } } } fz_always(ctx) { - fz_close(stm); + fz_drop_stream(ctx, stm); fz_free(ctx, ofsbuf); fz_free(ctx, numbuf); - pdf_drop_obj(objstm); + pdf_drop_obj(ctx, objstm); } fz_catch(ctx) { fz_rethrow_message(ctx, "cannot open object stream (%d %d R)", num, gen); } + return ret_entry; } /* * object loading */ static int -pdf_obj_read(pdf_document *doc, int *offset, int *nump, pdf_obj **page) +pdf_obj_read(fz_context *ctx, pdf_document *doc, int *offset, int *nump, pdf_obj **page) { - int num, numofs, gen, genofs, stmofs, tmpofs, tok; pdf_lexbuf *buf = &doc->lexbuf.base; - fz_context *ctx = doc->ctx; + int num, numofs, gen, genofs, stmofs, tmpofs, tok; int xref_len; pdf_xref_entry *entry; int newtmpofs; numofs = *offset; - fz_seek(doc->file, numofs, SEEK_SET); + fz_seek(ctx, doc->file, numofs, SEEK_SET); /* We expect to read 'num' here */ - tok = pdf_lex(doc->file, buf); - genofs = fz_tell(doc->file); + tok = pdf_lex(ctx, doc->file, buf); + genofs = fz_tell(ctx, doc->file); if (tok != PDF_TOK_INT) { /* Failed! */ @@ -1625,8 +1683,8 @@ pdf_obj_read(pdf_document *doc, int *offset, int *nump, pdf_obj **page) *nump = num = buf->i; /* We expect to read 'gen' here */ - tok = pdf_lex(doc->file, buf); - tmpofs = fz_tell(doc->file); + tok = pdf_lex(ctx, doc->file, buf); + tmpofs = fz_tell(ctx, doc->file); if (tok != PDF_TOK_INT) { /* Failed! */ @@ -1639,14 +1697,14 @@ pdf_obj_read(pdf_document *doc, int *offset, int *nump, pdf_obj **page) /* We expect to read 'obj' here */ do { - tmpofs = fz_tell(doc->file); - tok = pdf_lex(doc->file, buf); + tmpofs = fz_tell(ctx, doc->file); + tok = pdf_lex(ctx, doc->file, buf); if (tok == PDF_TOK_OBJ) break; if (tok != PDF_TOK_INT) { DEBUGMESS((ctx, "skipping unexpected data (tok=%d) at %d", tok, tmpofs)); - *offset = fz_tell(doc->file); + *offset = fz_tell(ctx, doc->file); return tok == PDF_TOK_EOF; } DEBUGMESS((ctx, "skipping unexpected int %d at %d", num, numofs)); @@ -1658,7 +1716,7 @@ pdf_obj_read(pdf_document *doc, int *offset, int *nump, pdf_obj **page) while (1); /* Now we read the actual object */ - xref_len = pdf_xref_len(doc); + xref_len = pdf_xref_len(ctx, doc); /* When we are reading a progressive file, we typically see: * File Header @@ -1676,7 +1734,7 @@ pdf_obj_read(pdf_document *doc, int *offset, int *nump, pdf_obj **page) * whenever we read an object it should just go into the * previous xref. */ - tok = pdf_repair_obj(doc, buf, &stmofs, NULL, NULL, NULL, page, &newtmpofs); + tok = pdf_repair_obj(ctx, doc, buf, &stmofs, NULL, NULL, NULL, page, &newtmpofs); do /* So we can break out of it */ { @@ -1689,7 +1747,7 @@ pdf_obj_read(pdf_document *doc, int *offset, int *nump, pdf_obj **page) { fz_warn(ctx, "Unexpected non zero generation number in linearized file"); } - entry = pdf_get_populating_xref_entry(doc, num); + entry = pdf_get_populating_xref_entry(ctx, doc, num); if (entry->type != 0) { DEBUGMESS((ctx, "Duplicate object found (%d %d obj)", num, gen)); @@ -1699,10 +1757,10 @@ pdf_obj_read(pdf_document *doc, int *offset, int *nump, pdf_obj **page) { DEBUGMESS((ctx, "Successfully read object %d @ %d - and found page %d!", num, numofs, doc->linear_page_num)); if (!entry->obj) - entry->obj = pdf_keep_obj(*page); + entry->obj = pdf_keep_obj(ctx, *page); if (doc->linear_page_refs[doc->linear_page_num] == NULL) - doc->linear_page_refs[doc->linear_page_num] = pdf_new_indirect(doc, num, gen); + doc->linear_page_refs[doc->linear_page_num] = pdf_new_indirect(ctx, doc, num, gen); } else { @@ -1719,7 +1777,7 @@ pdf_obj_read(pdf_document *doc, int *offset, int *nump, pdf_obj **page) if (tok == PDF_TOK_ENDOBJ) { - *offset = fz_tell(doc->file); + *offset = fz_tell(ctx, doc->file); } else { @@ -1729,9 +1787,8 @@ pdf_obj_read(pdf_document *doc, int *offset, int *nump, pdf_obj **page) } static void -pdf_load_hinted_page(pdf_document *doc, int pagenum) +pdf_load_hinted_page(fz_context *ctx, pdf_document *doc, int pagenum) { - fz_context *ctx = doc->ctx; if (!doc->hints_loaded || !doc->linear_page_refs) return; @@ -1742,14 +1799,14 @@ pdf_load_hinted_page(pdf_document *doc, int pagenum) fz_try(ctx) { int num = doc->hint_page[pagenum].number; - pdf_obj *page = pdf_load_object(doc, num, 0); - if (!strcmp("Page", pdf_to_name(pdf_dict_gets(page, "Type")))) + pdf_obj *page = pdf_load_object(ctx, doc, num, 0); + if (!strcmp("Page", pdf_to_name(ctx, pdf_dict_gets(ctx, page, "Type")))) { /* We have found the page object! */ DEBUGMESS((ctx, "LoadHintedPage pagenum=%d num=%d", pagenum, num)); - doc->linear_page_refs[pagenum] = pdf_new_indirect(doc, num, 0); + doc->linear_page_refs[pagenum] = pdf_new_indirect(ctx, doc, num, 0); } - pdf_drop_obj(page); + pdf_drop_obj(ctx, page); } fz_catch(ctx) { @@ -1760,12 +1817,11 @@ pdf_load_hinted_page(pdf_document *doc, int pagenum) } static int -read_hinted_object(pdf_document *doc, int num) +read_hinted_object(fz_context *ctx, pdf_document *doc, int num) { /* Try to find the object using our hint table. Find the closest * object <= the one we want that has a hint and read forward from * there. */ - fz_context *ctx = doc->ctx; int expected = num; int curr_pos; int start, offset; @@ -1777,7 +1833,7 @@ read_hinted_object(pdf_document *doc, int num) if (expected == 0) /* No hints found, just bale */ return 0; - curr_pos = fz_tell(doc->file); + curr_pos = fz_tell(ctx, doc->file); offset = doc->hint_obj_offsets[expected]; fz_var(expected); @@ -1791,7 +1847,7 @@ read_hinted_object(pdf_document *doc, int num) { start = offset; DEBUGMESS((ctx, "Searching for object %d @ %d", expected, offset)); - pdf_obj_read(doc, &offset, &found, 0); + pdf_obj_read(ctx, doc, &offset, &found, 0); DEBUGMESS((ctx, "Found object %d - next will be @ %d", found, offset)); if (found <= expected) { @@ -1819,7 +1875,7 @@ read_hinted_object(pdf_document *doc, int num) } fz_always(ctx) { - fz_seek(doc->file, curr_pos, SEEK_SET); + fz_seek(ctx, doc->file, curr_pos, SEEK_SET); } fz_catch(ctx) { @@ -1832,38 +1888,37 @@ read_hinted_object(pdf_document *doc, int num) return 1; } -void -pdf_cache_object(pdf_document *doc, int num, int gen) +pdf_xref_entry * +pdf_cache_object(fz_context *ctx, pdf_document *doc, int num, int gen) { pdf_xref_entry *x; int rnum, rgen, try_repair; - fz_context *ctx = doc->ctx; fz_var(try_repair); - if (num <= 0 || num >= pdf_xref_len(doc)) - fz_throw(ctx, FZ_ERROR_GENERIC, "object out of range (%d %d R); xref size %d", num, gen, pdf_xref_len(doc)); + if (num <= 0 || num >= pdf_xref_len(ctx, doc)) + fz_throw(ctx, FZ_ERROR_GENERIC, "object out of range (%d %d R); xref size %d", num, gen, pdf_xref_len(ctx, doc)); object_updated: try_repair = 0; rnum = num; - x = pdf_get_xref_entry(doc, num); + x = pdf_get_xref_entry(ctx, doc, num); - if (x->obj) - return; + if (x->obj != NULL) + return x; if (x->type == 'f') { - x->obj = pdf_new_null(doc); + x->obj = pdf_new_null(ctx, doc); } else if (x->type == 'n') { - fz_seek(doc->file, x->ofs, SEEK_SET); + fz_seek(ctx, doc->file, x->ofs, SEEK_SET); fz_try(ctx) { - x->obj = pdf_parse_ind_obj(doc, doc->file, &doc->lexbuf.base, + x->obj = pdf_parse_ind_obj(ctx, doc, doc->file, &doc->lexbuf.base, &rnum, &rgen, &x->stm_ofs, &try_repair); } fz_catch(ctx) @@ -1874,7 +1929,7 @@ object_updated: if (!try_repair && rnum != num) { - pdf_drop_obj(x->obj); + pdf_drop_obj(ctx, x->obj); x->obj = NULL; try_repair = 1; } @@ -1883,7 +1938,8 @@ object_updated: { fz_try(ctx) { - pdf_repair_xref(doc, &doc->lexbuf.base); + pdf_repair_xref(ctx, doc); + pdf_prime_xref_index(ctx, doc); } fz_catch(ctx) { @@ -1904,18 +1960,19 @@ object_updated: { fz_try(ctx) { - pdf_load_obj_stm(doc, x->ofs, 0, &doc->lexbuf.base); + x = pdf_load_obj_stm(ctx, doc, x->ofs, 0, &doc->lexbuf.base, num); } fz_catch(ctx) { fz_rethrow_message(ctx, "cannot load object stream containing object (%d %d R)", num, gen); } - x = pdf_get_xref_entry(doc, num); + if (x == NULL) + fz_throw(ctx, FZ_ERROR_GENERIC, "cannot load object stream containing object (%d %d R)", num, gen); if (!x->obj) fz_throw(ctx, FZ_ERROR_GENERIC, "object (%d %d R) was not found in its object stream", num, gen); } } - else if (doc->hint_obj_offsets && read_hinted_object(doc, num)) + else if (doc->hint_obj_offsets && read_hinted_object(ctx, doc, num)) { goto object_updated; } @@ -1928,54 +1985,52 @@ object_updated: fz_throw(ctx, FZ_ERROR_GENERIC, "cannot find object in xref (%d %d R)", num, gen); } - pdf_set_obj_parent(x->obj, num); + pdf_set_obj_parent(ctx, x->obj, num); + return x; } pdf_obj * -pdf_load_object(pdf_document *doc, int num, int gen) +pdf_load_object(fz_context *ctx, pdf_document *doc, int num, int gen) { - fz_context *ctx = doc->ctx; pdf_xref_entry *entry; fz_try(ctx) { - pdf_cache_object(doc, num, gen); + entry = pdf_cache_object(ctx, doc, num, gen); } fz_catch(ctx) { fz_rethrow_message(ctx, "cannot load object (%d %d R) into cache", num, gen); } - entry = pdf_get_xref_entry(doc, num); + assert(entry->obj != NULL); - assert(entry->obj); - - return pdf_keep_obj(entry->obj); + return pdf_keep_obj(ctx, entry->obj); } pdf_obj * -pdf_resolve_indirect(pdf_obj *ref) +pdf_resolve_indirect(fz_context *ctx, pdf_obj *ref) { int sanity = 10; int num; int gen; - fz_context *ctx = NULL; /* Avoid warning for stupid compilers */ - pdf_document *doc; pdf_xref_entry *entry; - while (pdf_is_indirect(ref)) + while (pdf_is_indirect(ctx, ref)) { + pdf_document *doc; + if (--sanity == 0) { fz_warn(ctx, "too many indirections (possible indirection cycle involving %d %d R)", num, gen); return NULL; } - doc = pdf_get_indirect_document(ref); + + doc = pdf_get_indirect_document(ctx, ref); if (!doc) return NULL; - ctx = doc->ctx; - num = pdf_to_num(ref); - gen = pdf_to_gen(ref); + num = pdf_to_num(ctx, ref); + gen = pdf_to_gen(ctx, ref); if (num <= 0 || gen < 0) { @@ -1985,7 +2040,7 @@ pdf_resolve_indirect(pdf_obj *ref) fz_try(ctx) { - pdf_cache_object(doc, num, gen); + entry = pdf_cache_object(ctx, doc, num, gen); } fz_catch(ctx) { @@ -1993,8 +2048,8 @@ pdf_resolve_indirect(pdf_obj *ref) fz_warn(ctx, "cannot load object (%d %d R) into cache", num, gen); return NULL; } - entry = pdf_get_xref_entry(doc, num); - if (!entry->obj) + + if (entry->obj == NULL) return NULL; ref = entry->obj; } @@ -2003,18 +2058,18 @@ pdf_resolve_indirect(pdf_obj *ref) } int -pdf_count_objects(pdf_document *doc) +pdf_count_objects(fz_context *ctx, pdf_document *doc) { - return pdf_xref_len(doc); + return pdf_xref_len(ctx, doc); } int -pdf_create_object(pdf_document *doc) +pdf_create_object(fz_context *ctx, pdf_document *doc) { /* TODO: reuse free object slots by properly linking free object chains in the ofs field */ pdf_xref_entry *entry; - int num = pdf_xref_len(doc); - entry = pdf_get_incremental_xref_entry(doc, num); + int num = pdf_xref_len(ctx, doc); + entry = pdf_get_incremental_xref_entry(ctx, doc, num); entry->type = 'f'; entry->ofs = -1; entry->gen = 0; @@ -2025,20 +2080,20 @@ pdf_create_object(pdf_document *doc) } void -pdf_delete_object(pdf_document *doc, int num) +pdf_delete_object(fz_context *ctx, pdf_document *doc, int num) { pdf_xref_entry *x; - if (num <= 0 || num >= pdf_xref_len(doc)) + if (num <= 0 || num >= pdf_xref_len(ctx, doc)) { - fz_warn(doc->ctx, "object out of range (%d 0 R); xref size %d", num, pdf_xref_len(doc)); + fz_warn(ctx, "object out of range (%d 0 R); xref size %d", num, pdf_xref_len(ctx, doc)); return; } - x = pdf_get_incremental_xref_entry(doc, num); + x = pdf_get_incremental_xref_entry(ctx, doc, num); - fz_drop_buffer(doc->ctx, x->stm_buf); - pdf_drop_obj(x->obj); + fz_drop_buffer(ctx, x->stm_buf); + pdf_drop_obj(ctx, x->obj); x->type = 'f'; x->ofs = 0; @@ -2049,46 +2104,46 @@ pdf_delete_object(pdf_document *doc, int num) } void -pdf_update_object(pdf_document *doc, int num, pdf_obj *newobj) +pdf_update_object(fz_context *ctx, pdf_document *doc, int num, pdf_obj *newobj) { pdf_xref_entry *x; - if (num <= 0 || num >= pdf_xref_len(doc)) + if (num <= 0 || num >= pdf_xref_len(ctx, doc)) { - fz_warn(doc->ctx, "object out of range (%d 0 R); xref size %d", num, pdf_xref_len(doc)); + fz_warn(ctx, "object out of range (%d 0 R); xref size %d", num, pdf_xref_len(ctx, doc)); return; } - x = pdf_get_incremental_xref_entry(doc, num); + x = pdf_get_incremental_xref_entry(ctx, doc, num); - pdf_drop_obj(x->obj); + pdf_drop_obj(ctx, x->obj); x->type = 'n'; x->ofs = 0; - x->obj = pdf_keep_obj(newobj); + x->obj = pdf_keep_obj(ctx, newobj); - pdf_set_obj_parent(newobj, num); + pdf_set_obj_parent(ctx, newobj, num); } void -pdf_update_stream(pdf_document *doc, int num, fz_buffer *newbuf) +pdf_update_stream(fz_context *ctx, pdf_document *doc, int num, fz_buffer *newbuf) { pdf_xref_entry *x; - if (num <= 0 || num >= pdf_xref_len(doc)) + if (num <= 0 || num >= pdf_xref_len(ctx, doc)) { - fz_warn(doc->ctx, "object out of range (%d 0 R); xref size %d", num, pdf_xref_len(doc)); + fz_warn(ctx, "object out of range (%d 0 R); xref size %d", num, pdf_xref_len(ctx, doc)); return; } - x = pdf_get_xref_entry(doc, num); + x = pdf_get_xref_entry(ctx, doc, num); - fz_drop_buffer(doc->ctx, x->stm_buf); - x->stm_buf = fz_keep_buffer(doc->ctx, newbuf); + fz_drop_buffer(ctx, x->stm_buf); + x->stm_buf = fz_keep_buffer(ctx, newbuf); } int -pdf_meta(pdf_document *doc, int key, void *ptr, int size) +pdf_meta(fz_context *ctx, pdf_document *doc, int key, void *ptr, int size) { switch (key) { @@ -2103,10 +2158,10 @@ pdf_meta(pdf_document *doc, int key, void *ptr, int size) case FZ_META_CRYPT_INFO: if (doc->crypt) sprintf((char *)ptr, "Standard V%d R%d %d-bit %s", - pdf_crypt_version(doc), - pdf_crypt_revision(doc), - pdf_crypt_length(doc), - pdf_crypt_method(doc)); + pdf_crypt_version(ctx, doc), + pdf_crypt_revision(ctx, doc), + pdf_crypt_length(ctx, doc), + pdf_crypt_method(ctx, doc)); else sprintf((char *)ptr, "None"); return FZ_META_OK; @@ -2130,18 +2185,18 @@ pdf_meta(pdf_document *doc, int key, void *ptr, int size) default: return 0; } - return pdf_has_permission(doc, i); + return pdf_has_permission(ctx, doc, i); } case FZ_META_INFO: { - pdf_obj *info = pdf_dict_gets(pdf_trailer(doc), "Info"); + pdf_obj *info = pdf_dict_gets(ctx, pdf_trailer(ctx, doc), "Info"); if (!info) { if (ptr) *(char *)ptr = 0; return 0; } - info = pdf_dict_gets(info, *(char **)ptr); + info = pdf_dict_gets(ctx, info, *(char **)ptr); if (!info) { if (ptr) @@ -2150,9 +2205,9 @@ pdf_meta(pdf_document *doc, int key, void *ptr, int size) } if (info && ptr && size) { - char *utf8 = pdf_to_utf8(doc, info); + char *utf8 = pdf_to_utf8(ctx, doc, info); fz_strlcpy(ptr, utf8, size); - fz_free(doc->ctx, utf8); + fz_free(ctx, utf8); } return 1; } @@ -2162,7 +2217,7 @@ pdf_meta(pdf_document *doc, int key, void *ptr, int size) } fz_transition * -pdf_page_presentation(pdf_document *doc, pdf_page *page, float *duration) +pdf_page_presentation(fz_context *ctx, pdf_page *page, float *duration) { *duration = page->duration; if (!page->transition_present) @@ -2170,13 +2225,6 @@ pdf_page_presentation(pdf_document *doc, pdf_page *page, float *duration) return &page->transition; } -static void -pdf_rebind(pdf_document *doc, fz_context *ctx) -{ - doc->ctx = ctx; - fz_rebind_stream(doc->file, ctx); -} - /* Initializers for the fz_document interface. @@ -2192,28 +2240,18 @@ pdf_new_document(fz_context *ctx, fz_stream *file) { pdf_document *doc = fz_malloc_struct(ctx, pdf_document); + doc->super.refs = 1; doc->super.close = (fz_document_close_fn *)pdf_close_document; doc->super.needs_password = (fz_document_needs_password_fn *)pdf_needs_password; doc->super.authenticate_password = (fz_document_authenticate_password_fn *)pdf_authenticate_password; doc->super.load_outline = (fz_document_load_outline_fn *)pdf_load_outline; doc->super.count_pages = (fz_document_count_pages_fn *)pdf_count_pages; doc->super.load_page = (fz_document_load_page_fn *)pdf_load_page; - doc->super.load_links = (fz_document_load_links_fn *)pdf_load_links; - doc->super.bound_page = (fz_document_bound_page_fn *)pdf_bound_page; - doc->super.first_annot = (fz_document_first_annot_fn *)pdf_first_annot; - doc->super.next_annot = (fz_document_next_annot_fn *)pdf_next_annot; - doc->super.bound_annot = (fz_document_bound_annot_fn *)pdf_bound_annot; - doc->super.run_page_contents = NULL; /* see pdf_xref_aux.c */ - doc->super.run_annot = NULL; /* see pdf_xref_aux.c */ - doc->super.free_page = (fz_document_free_page_fn *)pdf_free_page; doc->super.meta = (fz_document_meta_fn *)pdf_meta; - doc->super.page_presentation = (fz_document_page_presentation_fn *)pdf_page_presentation; doc->super.write = (fz_document_write_fn *)pdf_write_document; - doc->super.rebind = (fz_document_rebind_fn *)pdf_rebind; pdf_lexbuf_init(ctx, &doc->lexbuf.base, PDF_LEXBUF_LARGE); - doc->file = fz_keep_stream(file); - doc->ctx = ctx; + doc->file = fz_keep_stream(ctx, file); return doc; } @@ -2222,16 +2260,13 @@ pdf_document * pdf_open_document_no_run_with_stream(fz_context *ctx, fz_stream *file) { pdf_document *doc = pdf_new_document(ctx, file); - - fz_var(doc); - fz_try(ctx) { - pdf_init_document(doc); + pdf_init_document(ctx, doc); } fz_catch(ctx) { - pdf_close_document(doc); + pdf_close_document(ctx, doc); fz_rethrow_message(ctx, "cannot load document from stream"); } return doc; @@ -2250,26 +2285,25 @@ pdf_open_document_no_run(fz_context *ctx, const char *filename) { file = fz_open_file(ctx, filename); doc = pdf_new_document(ctx, file); - pdf_init_document(doc); + pdf_init_document(ctx, doc); } fz_always(ctx) { - fz_close(file); + fz_drop_stream(ctx, file); } fz_catch(ctx) { - pdf_close_document(doc); + pdf_close_document(ctx, doc); fz_rethrow_message(ctx, "cannot load document '%s'", filename); } return doc; } static void -pdf_load_hints(pdf_document *doc, int objnum, int gennum) +pdf_load_hints(fz_context *ctx, pdf_document *doc, int objnum, int gennum) { fz_stream *stream = NULL; pdf_obj *dict; - fz_context *ctx = doc->ctx; fz_var(stream); fz_var(dict); @@ -2286,14 +2320,14 @@ pdf_load_hints(pdf_document *doc, int objnum, int gennum) int shared_obj_num, shared_obj_offset, shared_obj_count_page1; int shared_obj_count_total; int least_shared_group_len, shared_group_len_num_bits; - int max_object_num = pdf_xref_len(doc); + int max_object_num = pdf_xref_len(ctx, doc); - stream = pdf_open_stream(doc, objnum, gennum); - dict = pdf_get_xref_entry(doc, objnum)->obj; - if (dict == NULL || !pdf_is_dict(dict)) + stream = pdf_open_stream(ctx, doc, objnum, gennum); + dict = pdf_get_xref_entry(ctx, doc, objnum)->obj; + if (dict == NULL || !pdf_is_dict(ctx, dict)) fz_throw(ctx, FZ_ERROR_GENERIC, "malformed hint object"); - shared_hint_offset = pdf_to_int(pdf_dict_gets(dict, "S")); + shared_hint_offset = pdf_to_int(ctx, pdf_dict_gets(ctx, dict, "S")); /* Malloc the structures (use realloc to cope with the fact we * may try this several times before enough data is loaded) */ @@ -2304,45 +2338,45 @@ pdf_load_hints(pdf_document *doc, int objnum, int gennum) doc->hint_obj_offsets_max = max_object_num; /* Read the page object hints table: Header first */ - least_num_page_objs = fz_read_bits(stream, 32); + least_num_page_objs = fz_read_bits(ctx, stream, 32); /* The following is sometimes a lie, but we read this version, * as other table values are built from it. In * pdf_reference17.pdf, this points to 2 objects before the * first pages page object. */ - doc->hint_page[0].offset = fz_read_bits(stream, 32); + doc->hint_page[0].offset = fz_read_bits(ctx, stream, 32); if (doc->hint_page[0].offset > doc->hint_object_offset) doc->hint_page[0].offset += doc->hint_object_length; - page_obj_num_bits = fz_read_bits(stream, 16); - least_page_len = fz_read_bits(stream, 32); - page_len_num_bits = fz_read_bits(stream, 16); - /* least_page_offset = */ (void) fz_read_bits(stream, 32); - /* page_offset_num_bits = */ (void) fz_read_bits(stream, 16); - /* least_content_stream_len = */ (void) fz_read_bits(stream, 32); - /* content_stream_len_num_bits = */ (void) fz_read_bits(stream, 16); - num_shared_obj_num_bits = fz_read_bits(stream, 16); - shared_obj_num_bits = fz_read_bits(stream, 16); - /* numerator_bits = */ (void) fz_read_bits(stream, 16); - /* denominator_bits = */ (void) fz_read_bits(stream, 16); + page_obj_num_bits = fz_read_bits(ctx, stream, 16); + least_page_len = fz_read_bits(ctx, stream, 32); + page_len_num_bits = fz_read_bits(ctx, stream, 16); + /* least_page_offset = */ (void) fz_read_bits(ctx, stream, 32); + /* page_offset_num_bits = */ (void) fz_read_bits(ctx, stream, 16); + /* least_content_stream_len = */ (void) fz_read_bits(ctx, stream, 32); + /* content_stream_len_num_bits = */ (void) fz_read_bits(ctx, stream, 16); + num_shared_obj_num_bits = fz_read_bits(ctx, stream, 16); + shared_obj_num_bits = fz_read_bits(ctx, stream, 16); + /* numerator_bits = */ (void) fz_read_bits(ctx, stream, 16); + /* denominator_bits = */ (void) fz_read_bits(ctx, stream, 16); /* Item 1: Page object numbers */ doc->hint_page[0].number = doc->linear_page1_obj_num; /* We don't care about the number of objects in the first page */ - (void)fz_read_bits(stream, page_obj_num_bits); + (void)fz_read_bits(ctx, stream, page_obj_num_bits); j = 1; for (i = 1; i < doc->page_count; i++) { - int delta_page_objs = fz_read_bits(stream, page_obj_num_bits); + int delta_page_objs = fz_read_bits(ctx, stream, page_obj_num_bits); doc->hint_page[i].number = j; j += least_num_page_objs + delta_page_objs; } doc->hint_page[i].number = j; /* Not a real page object */ - fz_sync_bits(stream); + fz_sync_bits(ctx, stream); /* Item 2: Page lengths */ j = doc->hint_page[0].offset; for (i = 0; i < doc->page_count; i++) { - int delta_page_len = fz_read_bits(stream, page_len_num_bits); + int delta_page_len = fz_read_bits(ctx, stream, page_len_num_bits); int old = j; doc->hint_page[i].offset = j; @@ -2351,39 +2385,39 @@ pdf_load_hints(pdf_document *doc, int objnum, int gennum) j += doc->hint_object_length; } doc->hint_page[i].offset = j; - fz_sync_bits(stream); + fz_sync_bits(ctx, stream); /* Item 3: Shared references */ shared = 0; for (i = 0; i < doc->page_count; i++) { - int num_shared_objs = fz_read_bits(stream, num_shared_obj_num_bits); + int num_shared_objs = fz_read_bits(ctx, stream, num_shared_obj_num_bits); doc->hint_page[i].index = shared; shared += num_shared_objs; } doc->hint_page[i].index = shared; doc->hint_shared_ref = fz_resize_array(ctx, doc->hint_shared_ref, shared, sizeof(*doc->hint_shared_ref)); memset(doc->hint_shared_ref, 0, sizeof(*doc->hint_shared_ref) * shared); - fz_sync_bits(stream); + fz_sync_bits(ctx, stream); /* Item 4: Shared references */ for (i = 0; i < shared; i++) { - int ref = fz_read_bits(stream, shared_obj_num_bits); + int ref = fz_read_bits(ctx, stream, shared_obj_num_bits); doc->hint_shared_ref[i] = ref; } /* Skip items 5,6,7 as we don't use them */ - fz_seek(stream, shared_hint_offset, SEEK_SET); + fz_seek(ctx, stream, shared_hint_offset, SEEK_SET); /* Read the shared object hints table: Header first */ - shared_obj_num = fz_read_bits(stream, 32); - shared_obj_offset = fz_read_bits(stream, 32); + shared_obj_num = fz_read_bits(ctx, stream, 32); + shared_obj_offset = fz_read_bits(ctx, stream, 32); if (shared_obj_offset > doc->hint_object_offset) shared_obj_offset += doc->hint_object_length; - shared_obj_count_page1 = fz_read_bits(stream, 32); - shared_obj_count_total = fz_read_bits(stream, 32); - shared_obj_num_bits = fz_read_bits(stream, 16); - least_shared_group_len = fz_read_bits(stream, 32); - shared_group_len_num_bits = fz_read_bits(stream, 16); + shared_obj_count_page1 = fz_read_bits(ctx, stream, 32); + shared_obj_count_total = fz_read_bits(ctx, stream, 32); + shared_obj_num_bits = fz_read_bits(ctx, stream, 16); + least_shared_group_len = fz_read_bits(ctx, stream, 32); + shared_group_len_num_bits = fz_read_bits(ctx, stream, 16); /* Sanity check the references in Item 4 above to ensure we * don't access out of range with malicious files. */ @@ -2402,7 +2436,7 @@ pdf_load_hints(pdf_document *doc, int objnum, int gennum) j = doc->hint_page[0].offset; for (i = 0; i < shared_obj_count_page1; i++) { - int off = fz_read_bits(stream, shared_group_len_num_bits); + int off = fz_read_bits(ctx, stream, shared_group_len_num_bits); int old = j; doc->hint_shared[i].offset = j; j += off + least_shared_group_len; @@ -2415,7 +2449,7 @@ pdf_load_hints(pdf_document *doc, int objnum, int gennum) j = shared_obj_offset; for (; i < shared_obj_count_total; i++) { - int off = fz_read_bits(stream, shared_group_len_num_bits); + int off = fz_read_bits(ctx, stream, shared_group_len_num_bits); int old = j; doc->hint_shared[i].offset = j; j += off + least_shared_group_len; @@ -2423,34 +2457,34 @@ pdf_load_hints(pdf_document *doc, int objnum, int gennum) j += doc->hint_object_length; } doc->hint_shared[i].offset = j; - fz_sync_bits(stream); + fz_sync_bits(ctx, stream); /* Item 2: Signature flags: read these just so we can skip */ for (i = 0; i < shared_obj_count_total; i++) { - doc->hint_shared[i].number = fz_read_bits(stream, 1); + doc->hint_shared[i].number = fz_read_bits(ctx, stream, 1); } - fz_sync_bits(stream); + fz_sync_bits(ctx, stream); /* Item 3: Signatures: just skip */ for (i = 0; i < shared_obj_count_total; i++) { if (doc->hint_shared[i].number) { - (void) fz_read_bits(stream, 128); + (void) fz_read_bits(ctx, stream, 128); } } - fz_sync_bits(stream); + fz_sync_bits(ctx, stream); /* Item 4: Shared object object numbers */ j = doc->linear_page1_obj_num; /* FIXME: This is a lie! */ for (i = 0; i < shared_obj_count_page1; i++) { doc->hint_shared[i].number = j; - j += fz_read_bits(stream, shared_obj_num_bits) + 1; + j += fz_read_bits(ctx, stream, shared_obj_num_bits) + 1; } j = shared_obj_num; for (; i < shared_obj_count_total; i++) { doc->hint_shared[i].number = j; - j += fz_read_bits(stream, shared_obj_num_bits) + 1; + j += fz_read_bits(ctx, stream, shared_obj_num_bits) + 1; } doc->hint_shared[i].number = j; @@ -2466,7 +2500,7 @@ pdf_load_hints(pdf_document *doc, int objnum, int gennum) } fz_always(ctx) { - fz_close(stream); + fz_drop_stream(ctx, stream); } fz_catch(ctx) { @@ -2482,14 +2516,13 @@ pdf_load_hints(pdf_document *doc, int objnum, int gennum) } static void -pdf_load_hint_object(pdf_document *doc) +pdf_load_hint_object(fz_context *ctx, pdf_document *doc) { - fz_context *ctx = doc->ctx; pdf_lexbuf *buf = &doc->lexbuf.base; int curr_pos; - curr_pos = fz_tell(doc->file); - fz_seek(doc->file, doc->hint_object_offset, SEEK_SET); + curr_pos = fz_tell(ctx, doc->file); + fz_seek(ctx, doc->file, doc->hint_object_offset, SEEK_SET); fz_try(ctx) { while (1) @@ -2497,24 +2530,24 @@ pdf_load_hint_object(pdf_document *doc) pdf_obj *page = NULL; int tmpofs, num, gen, tok; - tok = pdf_lex(doc->file, buf); + tok = pdf_lex(ctx, doc->file, buf); if (tok != PDF_TOK_INT) break; num = buf->i; - tok = pdf_lex(doc->file, buf); + tok = pdf_lex(ctx, doc->file, buf); if (tok != PDF_TOK_INT) break; gen = buf->i; - tok = pdf_lex(doc->file, buf); + tok = pdf_lex(ctx, doc->file, buf); if (tok != PDF_TOK_OBJ) break; - (void)pdf_repair_obj(doc, buf, &tmpofs, NULL, NULL, NULL, &page, &tmpofs); - pdf_load_hints(doc, num, gen); + (void)pdf_repair_obj(ctx, doc, buf, &tmpofs, NULL, NULL, NULL, &page, &tmpofs); + pdf_load_hints(ctx, doc, num, gen); } } fz_always(ctx) { - fz_seek(doc->file, curr_pos, SEEK_SET); + fz_seek(ctx, doc->file, curr_pos, SEEK_SET); } fz_catch(ctx) { @@ -2522,17 +2555,16 @@ pdf_load_hint_object(pdf_document *doc) } } -pdf_obj *pdf_progressive_advance(pdf_document *doc, int pagenum) +pdf_obj *pdf_progressive_advance(fz_context *ctx, pdf_document *doc, int pagenum) { - fz_context *ctx = doc->ctx; pdf_lexbuf *buf = &doc->lexbuf.base; int curr_pos; pdf_obj *page; - pdf_load_hinted_page(doc, pagenum); + pdf_load_hinted_page(ctx, doc, pagenum); if (pagenum < 0 || pagenum >= doc->page_count) - fz_throw(doc->ctx, FZ_ERROR_GENERIC, "page load out of range (%d of %d)", pagenum, doc->page_count); + fz_throw(ctx, FZ_ERROR_GENERIC, "page load out of range (%d of %d)", pagenum, doc->page_count); if (doc->linear_pos == doc->file_length) return doc->linear_page_refs[pagenum]; @@ -2541,11 +2573,11 @@ pdf_obj *pdf_progressive_advance(pdf_document *doc, int pagenum) if (pagenum > 0 && !doc->hints_loaded && doc->hint_object_offset > 0 && doc->linear_pos >= doc->hint_object_offset) { /* Found hint object */ - pdf_load_hint_object(doc); + pdf_load_hint_object(ctx, doc); } DEBUGMESS((ctx, "continuing to try to advance from %d", doc->linear_pos)); - curr_pos = fz_tell(doc->file); + curr_pos = fz_tell(ctx, doc->file); fz_var(page); @@ -2556,8 +2588,8 @@ pdf_obj *pdf_progressive_advance(pdf_document *doc, int pagenum) { int num; page = NULL; - eof = pdf_obj_read(doc, &doc->linear_pos, &num, &page); - pdf_drop_obj(page); + eof = pdf_obj_read(ctx, doc, &doc->linear_pos, &num, &page); + pdf_drop_obj(ctx, page); page = NULL; } while (!eof); @@ -2566,22 +2598,22 @@ pdf_obj *pdf_progressive_advance(pdf_document *doc, int pagenum) pdf_obj *catalog; pdf_obj *pages; doc->linear_pos = doc->file_length; - pdf_load_xref(doc, buf); - catalog = pdf_dict_gets(pdf_trailer(doc), "Root"); - pages = pdf_dict_gets(catalog, "Pages"); + pdf_load_xref(ctx, doc, buf); + catalog = pdf_dict_gets(ctx, pdf_trailer(ctx, doc), "Root"); + pages = pdf_dict_gets(ctx, catalog, "Pages"); - if (!pdf_is_dict(pages)) + if (!pdf_is_dict(ctx, pages)) fz_throw(ctx, FZ_ERROR_GENERIC, "missing page tree"); break; } } fz_always(ctx) { - fz_seek(doc->file, curr_pos, SEEK_SET); + fz_seek(ctx, doc->file, curr_pos, SEEK_SET); } fz_catch(ctx) { - pdf_drop_obj(page); + pdf_drop_obj(ctx, page); if (fz_caught(ctx) == FZ_ERROR_TRYLATER) { if (doc->linear_page_refs[pagenum] == NULL) @@ -2597,7 +2629,7 @@ pdf_obj *pdf_progressive_advance(pdf_document *doc, int pagenum) return doc->linear_page_refs[pagenum]; } -pdf_document *pdf_specifics(fz_document *doc) +pdf_document *pdf_specifics(fz_context *ctx, fz_document *doc) { return (pdf_document *)((doc && doc->close == (fz_document_close_fn *)pdf_close_document) ? doc : NULL); } @@ -2620,29 +2652,29 @@ pdf_document *pdf_create_document(fz_context *ctx) doc->file_size = 0; doc->startxref = 0; doc->num_xref_sections = 0; - pdf_get_populating_xref_entry(doc, 0); + pdf_get_populating_xref_entry(ctx, doc, 0); doc->xref_altered = 1; - trailer = pdf_new_dict(doc, 2); - pdf_dict_puts_drop(trailer, "Size", pdf_new_int(doc, 3)); - o = root = pdf_new_dict(doc, 2); - pdf_dict_puts_drop(trailer, "Root", pdf_new_ref(doc, o)); - pdf_drop_obj(o); + trailer = pdf_new_dict(ctx, doc, 2); + pdf_dict_puts_drop(ctx, trailer, "Size", pdf_new_int(ctx, doc, 3)); + o = root = pdf_new_dict(ctx, doc, 2); + pdf_dict_puts_drop(ctx, trailer, "Root", pdf_new_ref(ctx, doc, o)); + pdf_drop_obj(ctx, o); o = NULL; - pdf_dict_puts_drop(root, "Type", pdf_new_name(doc, "Catalog")); - o = pages = pdf_new_dict(doc, 3); - pdf_dict_puts_drop(root, "Pages", pdf_new_ref(doc, o)); - pdf_drop_obj(o); + pdf_dict_puts_drop(ctx, root, "Type", pdf_new_name(ctx, doc, "Catalog")); + o = pages = pdf_new_dict(ctx, doc, 3); + pdf_dict_puts_drop(ctx, root, "Pages", pdf_new_ref(ctx, doc, o)); + pdf_drop_obj(ctx, o); o = NULL; - pdf_dict_puts_drop(pages, "Type", pdf_new_name(doc, "Pages")); - pdf_dict_puts_drop(pages, "Count", pdf_new_int(doc, 0)); - pdf_dict_puts_drop(pages, "Kids", pdf_new_array(doc, 1)); - pdf_set_populating_xref_trailer(doc, trailer); - pdf_drop_obj(trailer); + pdf_dict_puts_drop(ctx, pages, "Type", pdf_new_name(ctx, doc, "Pages")); + pdf_dict_puts_drop(ctx, pages, "Count", pdf_new_int(ctx, doc, 0)); + pdf_dict_puts_drop(ctx, pages, "Kids", pdf_new_array(ctx, doc, 1)); + pdf_set_populating_xref_trailer(ctx, doc, trailer); + pdf_drop_obj(ctx, trailer); } fz_catch(ctx) { - pdf_drop_obj(trailer); - pdf_drop_obj(o); + pdf_drop_obj(ctx, trailer); + pdf_drop_obj(ctx, o); fz_rethrow_message(ctx, "Failed to create empty document"); } return doc; @@ -2671,7 +2703,7 @@ fz_document_handler pdf_no_run_document_handler = (fz_document_open_with_stream_fn *)&pdf_open_document_no_run_with_stream }; -void pdf_mark_xref(pdf_document *doc) +void pdf_mark_xref(fz_context *ctx, pdf_document *doc) { int x, e; @@ -2694,7 +2726,7 @@ void pdf_mark_xref(pdf_document *doc) } } -void pdf_clear_xref(pdf_document *doc) +void pdf_clear_xref(fz_context *ctx, pdf_document *doc) { int x, e; @@ -2712,9 +2744,9 @@ void pdf_clear_xref(pdf_document *doc) * buffer has been updated */ if (entry->obj != NULL && entry->stm_buf == NULL) { - if (pdf_obj_refs(entry->obj) == 1) + if (pdf_obj_refs(ctx, entry->obj) == 1) { - pdf_drop_obj(entry->obj); + pdf_drop_obj(ctx, entry->obj); entry->obj = NULL; } } @@ -2723,7 +2755,7 @@ void pdf_clear_xref(pdf_document *doc) } } -void pdf_clear_xref_to_mark(pdf_document *doc) +void pdf_clear_xref_to_mark(fz_context *ctx, pdf_document *doc) { int x, e; @@ -2742,9 +2774,9 @@ void pdf_clear_xref_to_mark(pdf_document *doc) * been updated */ if (entry->obj != NULL && entry->stm_buf == NULL) { - if ((entry->flags & PDF_OBJ_FLAG_MARK) == 0 && pdf_obj_refs(entry->obj) == 1) + if ((entry->flags & PDF_OBJ_FLAG_MARK) == 0 && pdf_obj_refs(ctx, entry->obj) == 1) { - pdf_drop_obj(entry->obj); + pdf_drop_obj(ctx, entry->obj); entry->obj = NULL; } } |