static void process_annot(pdf_csi *csi, void *state, pdf_obj *resources, pdf_annot *annot) { fz_context *ctx = csi->doc->ctx; pdf_xobject *xobj = annot->ap; /* Avoid infinite recursion */ if (xobj == NULL || pdf_mark_obj(xobj->me)) return; fz_try(ctx) { if (xobj->resources) resources = xobj->resources; pdf_process_contents_object(csi, resources, xobj->contents); } fz_always(ctx) { pdf_unmark_obj(xobj->me); } fz_catch(ctx) { fz_rethrow(ctx); } }
static int pdf_resources_use_blending(pdf_document *doc, pdf_obj *rdb) { fz_context *ctx = doc->ctx; pdf_obj *obj; int i, n, useBM = 0; if (!rdb) return 0; /* Have we been here before and remembered an answer? */ if (pdf_obj_memo(rdb, &useBM)) return useBM; /* stop on cyclic resource dependencies */ if (pdf_mark_obj(rdb)) return 0; fz_try(ctx) { obj = pdf_dict_gets(rdb, "ExtGState"); n = pdf_dict_len(obj); for (i = 0; i < n; i++) if (pdf_extgstate_uses_blending(doc, pdf_dict_get_val(obj, i))) goto found; obj = pdf_dict_gets(rdb, "Pattern"); n = pdf_dict_len(obj); for (i = 0; i < n; i++) if (pdf_pattern_uses_blending(doc, pdf_dict_get_val(obj, i))) goto found; obj = pdf_dict_gets(rdb, "XObject"); n = pdf_dict_len(obj); for (i = 0; i < n; i++) if (pdf_xobject_uses_blending(doc, pdf_dict_get_val(obj, i))) goto found; if (0) { found: useBM = 1; } } fz_always(ctx) { pdf_unmark_obj(rdb); } fz_catch(ctx) { fz_rethrow(ctx); } pdf_set_obj_memo(rdb, useBM); return useBM; }
static int do_name_tree_map(fz_context *ctx, pdf_obj *tree, pdf_name_tree_map_fn *fn, void *arg) { int i; int n = 0; int m = 0; fz_var(n); fz_var(m); if (pdf_mark_obj(ctx, tree)) fz_throw(ctx, FZ_ERROR_GENERIC, "Recursive name tree!"); fz_try(ctx) { pdf_obj *arr = pdf_dict_get(ctx, tree, PDF_NAME_Kids); n = pdf_array_len(ctx, arr); for (i = n; i > 0;) { i--; if (do_name_tree_map(ctx, pdf_array_get(ctx, arr, i), fn, arg)) { pdf_array_delete(ctx, arr, i); n--; } } arr = pdf_dict_get(ctx, tree, PDF_NAME_Names); m = pdf_array_len(ctx, arr); if (m & 1) fz_throw(ctx, FZ_ERROR_GENERIC, "Malformed Names array"); for (i = m; i > 0;) { i -= 2; if (fn(ctx, tree, pdf_array_get(ctx, arr, i), pdf_array_get(ctx, arr, i+1), arg)) { pdf_array_delete(ctx, arr, i+1); pdf_array_delete(ctx, arr, i); m -= 2; } } } fz_always(ctx) pdf_unmark_obj(ctx, tree); fz_catch(ctx) fz_rethrow(ctx); return n == 0 && m == 0; }
int pdf_lookup_page_number(pdf_document *doc, pdf_obj *node) { fz_context *ctx = doc->ctx; int needle = pdf_to_num(node); int total = 0; pdf_obj *parent, *parent2; /* SumatraPDF: don't return 0 for non-dict nodes (certainly not the first page) */ if (!pdf_is_dict(node)) fz_throw(ctx, FZ_ERROR_GENERIC, "invalid page object"); parent2 = parent = pdf_dict_gets(node, "Parent"); fz_var(parent); fz_try(ctx) { /* SumatraPDF: don't throw for non-dict parents */ while (parent && pdf_is_dict(parent)) { if (pdf_mark_obj(parent)) fz_throw(ctx, FZ_ERROR_GENERIC, "cycle in page tree (parents)"); total += pdf_count_pages_before_kid(doc, parent, needle); needle = pdf_to_num(parent); parent = pdf_dict_gets(parent, "Parent"); } } fz_always(ctx) { /* Run back and unmark */ while (parent2) { pdf_unmark_obj(parent2); if (parent2 == parent) break; parent2 = pdf_dict_gets(parent2, "Parent"); } } fz_catch(ctx) { fz_rethrow(ctx); } return total; }
int pdf_lookup_page_number(pdf_document *doc, pdf_obj *node) { fz_context *ctx = doc->ctx; int needle = pdf_to_num(node); int total = 0; pdf_obj *parent, *parent2; if (strcmp(pdf_to_name(pdf_dict_gets(node, "Type")), "Page") != 0) fz_throw(ctx, FZ_ERROR_GENERIC, "invalid page object"); parent2 = parent = pdf_dict_gets(node, "Parent"); fz_var(parent); fz_try(ctx) { while (pdf_is_dict(parent)) { if (pdf_mark_obj(parent)) fz_throw(ctx, FZ_ERROR_GENERIC, "cycle in page tree (parents)"); total += pdf_count_pages_before_kid(doc, parent, needle); needle = pdf_to_num(parent); parent = pdf_dict_gets(parent, "Parent"); } } fz_always(ctx) { /* Run back and unmark */ while (parent2) { pdf_unmark_obj(parent2); if (parent2 == parent) break; parent2 = pdf_dict_gets(parent2, "Parent"); } } fz_catch(ctx) { fz_rethrow(ctx); } return total; }
/* SumatraPDF: make pdf_lookup_inherited_page_item externally available */ pdf_obj * pdf_lookup_inherited_page_item(pdf_document *doc, pdf_obj *node, const char *key) { fz_context *ctx = doc->ctx; pdf_obj *node2 = node; pdf_obj *val; /* fz_var(node); Not required as node passed in */ fz_try(ctx) { do { val = pdf_dict_gets(node, key); if (val) break; if (pdf_mark_obj(node)) fz_throw(ctx, FZ_ERROR_GENERIC, "cycle in page tree (parents)"); node = pdf_dict_gets(node, "Parent"); } while (node); } fz_always(ctx) { do { pdf_unmark_obj(node2); if (node2 == node) break; node2 = pdf_dict_gets(node2, "Parent"); } while (node2); } fz_catch(ctx) { fz_rethrow(ctx); } return val; }
static pdf_obj * pdf_lookup_page_loc_imp(pdf_document *doc, pdf_obj *node, int *skip, pdf_obj **parentp, int *indexp) { fz_context *ctx = doc->ctx; pdf_obj *kids; pdf_obj *hit = NULL; int i, len; pdf_obj *local_stack[LOCAL_STACK_SIZE]; pdf_obj **stack = &local_stack[0]; int stack_max = LOCAL_STACK_SIZE; int stack_len = 0; fz_var(hit); fz_var(stack); fz_var(stack_len); fz_var(stack_max); fz_try(ctx) { do { kids = pdf_dict_gets(node, "Kids"); len = pdf_array_len(kids); if (len == 0) fz_throw(ctx, FZ_ERROR_GENERIC, "Malformed pages tree"); /* Every node we need to unmark goes into the stack */ if (stack_len == stack_max) { if (stack == &local_stack[0]) { stack = fz_malloc_array(ctx, stack_max * 2, sizeof(*stack)); memcpy(stack, &local_stack[0], stack_max * sizeof(*stack)); } else stack = fz_resize_array(ctx, stack, stack_max * 2, sizeof(*stack)); stack_max *= 2; } stack[stack_len++] = node; if (pdf_mark_obj(node)) fz_throw(ctx, FZ_ERROR_GENERIC, "cycle in page tree"); for (i = 0; i < len; i++) { pdf_obj *kid = pdf_array_get(kids, i); char *type = pdf_to_name(pdf_dict_gets(kid, "Type")); if (!strcmp(type, "Page") || (!*type && pdf_dict_gets(kid, "MediaBox"))) { if (*skip == 0) { if (parentp) *parentp = node; if (indexp) *indexp = i; hit = kid; break; } else { (*skip)--; } } else if (!strcmp(type, "Pages") || (!*type && pdf_dict_gets(kid, "Kids"))) { int count = pdf_to_int(pdf_dict_gets(kid, "Count")); if (*skip < count) { node = kid; break; } else { *skip -= count; } } else { fz_throw(ctx, FZ_ERROR_GENERIC, "non-page object in page tree (%s)", type); } } } while (hit == NULL); } fz_always(ctx) { for (i = stack_len; i > 0; i--) pdf_unmark_obj(stack[i-1]); if (stack != &local_stack[0]) fz_free(ctx, stack); } fz_catch(ctx) { fz_rethrow(ctx); } return hit; }
/* * Load CMap stream in PDF file */ pdf_cmap * pdf_load_embedded_cmap(pdf_document *doc, pdf_obj *stmobj) { fz_stream *file = NULL; pdf_cmap *cmap = NULL; pdf_cmap *usecmap; pdf_obj *wmode; pdf_obj *obj = NULL; fz_context *ctx = doc->ctx; int phase = 0; fz_var(phase); fz_var(obj); fz_var(file); fz_var(cmap); if (pdf_obj_marked(stmobj)) fz_throw(ctx, FZ_ERROR_GENERIC, "Recursion in embedded cmap"); if ((cmap = pdf_find_item(ctx, pdf_free_cmap_imp, stmobj)) != NULL) { return cmap; } fz_try(ctx) { file = pdf_open_stream(doc, pdf_to_num(stmobj), pdf_to_gen(stmobj)); phase = 1; cmap = pdf_load_cmap(ctx, file); phase = 2; fz_close(file); file = NULL; wmode = pdf_dict_gets(stmobj, "WMode"); if (pdf_is_int(wmode)) pdf_set_cmap_wmode(ctx, cmap, pdf_to_int(wmode)); obj = pdf_dict_gets(stmobj, "UseCMap"); if (pdf_is_name(obj)) { usecmap = pdf_load_system_cmap(ctx, pdf_to_name(obj)); pdf_set_usecmap(ctx, cmap, usecmap); pdf_drop_cmap(ctx, usecmap); } else if (pdf_is_indirect(obj)) { phase = 3; pdf_mark_obj(obj); usecmap = pdf_load_embedded_cmap(doc, obj); pdf_unmark_obj(obj); phase = 4; pdf_set_usecmap(ctx, cmap, usecmap); pdf_drop_cmap(ctx, usecmap); } pdf_store_item(ctx, stmobj, cmap, pdf_cmap_size(ctx, cmap)); } fz_catch(ctx) { if (file) fz_close(file); if (cmap) pdf_drop_cmap(ctx, cmap); if (phase < 1) fz_rethrow_message(ctx, "cannot open cmap stream (%d %d R)", pdf_to_num(stmobj), pdf_to_gen(stmobj)); else if (phase < 2) fz_rethrow_message(ctx, "cannot parse cmap stream (%d %d R)", pdf_to_num(stmobj), pdf_to_gen(stmobj)); else if (phase < 3) fz_rethrow_message(ctx, "cannot load system usecmap '%s'", pdf_to_name(obj)); else { if (phase == 3) pdf_unmark_obj(obj); fz_rethrow_message(ctx, "cannot load embedded usecmap (%d %d R)", pdf_to_num(obj), pdf_to_gen(obj)); } } return cmap; }
static pdf_obj * pdf_lookup_page_loc_imp(pdf_document *doc, pdf_obj *node, int *skip, pdf_obj **parentp, int *indexp) { fz_context *ctx = doc->ctx; pdf_obj *kids, *hit; int i, len; kids = pdf_dict_gets(node, "Kids"); len = pdf_array_len(kids); if (pdf_mark_obj(node)) fz_throw(ctx, FZ_ERROR_GENERIC, "cycle in page tree"); hit = NULL; fz_var(hit); fz_try(ctx) { for (i = 0; i < len; i++) { pdf_obj *kid = pdf_array_get(kids, i); char *type = pdf_to_name(pdf_dict_gets(kid, "Type")); if (!strcmp(type, "Page")) { if (*skip == 0) { if (parentp) *parentp = node; if (indexp) *indexp = i; hit = kid; break; } else { (*skip)--; } } else if (!strcmp(type, "Pages")) { int count = pdf_to_int(pdf_dict_gets(kid, "Count")); if (*skip < count) { hit = pdf_lookup_page_loc_imp(doc, kid, skip, parentp, indexp); if (hit) break; } else { *skip -= count; } } else { fz_throw(ctx, FZ_ERROR_GENERIC, "non-page object in page tree"); } } } fz_always(ctx) { pdf_unmark_obj(node); } fz_catch(ctx) { fz_rethrow(ctx); } return hit; }
/* * Load CMap stream in PDF file */ pdf_cmap * pdf_load_embedded_cmap(fz_context *ctx, pdf_document *doc, pdf_obj *stmobj) { fz_stream *file = NULL; pdf_cmap *cmap = NULL; pdf_cmap *usecmap = NULL; pdf_obj *obj; fz_var(file); fz_var(cmap); fz_var(usecmap); if (pdf_obj_marked(ctx, stmobj)) fz_throw(ctx, FZ_ERROR_GENERIC, "Recursion in embedded cmap"); if ((cmap = pdf_find_item(ctx, pdf_drop_cmap_imp, stmobj)) != NULL) return cmap; fz_try(ctx) { file = pdf_open_stream(ctx, stmobj); cmap = pdf_load_cmap(ctx, file); obj = pdf_dict_get(ctx, stmobj, PDF_NAME_WMode); if (pdf_is_int(ctx, obj)) pdf_set_cmap_wmode(ctx, cmap, pdf_to_int(ctx, obj)); obj = pdf_dict_get(ctx, stmobj, PDF_NAME_UseCMap); if (pdf_is_name(ctx, obj)) { usecmap = pdf_load_system_cmap(ctx, pdf_to_name(ctx, obj)); pdf_set_usecmap(ctx, cmap, usecmap); } else if (pdf_is_indirect(ctx, obj)) { if (pdf_mark_obj(ctx, obj)) fz_throw(ctx, FZ_ERROR_GENERIC, "recursive CMap"); fz_try(ctx) usecmap = pdf_load_embedded_cmap(ctx, doc, obj); fz_always(ctx) pdf_unmark_obj(ctx, obj); fz_catch(ctx) fz_rethrow(ctx); pdf_set_usecmap(ctx, cmap, usecmap); } pdf_store_item(ctx, stmobj, cmap, pdf_cmap_size(ctx, cmap)); } fz_always(ctx) { fz_drop_stream(ctx, file); pdf_drop_cmap(ctx, usecmap); } fz_catch(ctx) { pdf_drop_cmap(ctx, cmap); fz_rethrow(ctx); } return cmap; }
static fz_outline * pdf_load_outline_imp(fz_context *ctx, pdf_document *doc, pdf_obj *dict) { fz_outline *node, **prev, *first; pdf_obj *obj; pdf_obj *odict = dict; fz_var(dict); fz_var(first); fz_try(ctx) { first = NULL; prev = &first; while (dict && pdf_is_dict(ctx, dict)) { if (pdf_mark_obj(ctx, dict)) break; node = fz_new_outline(ctx); *prev = node; prev = &node->next; obj = pdf_dict_get(ctx, dict, PDF_NAME_Title); if (obj) node->title = pdf_to_utf8(ctx, obj); if ((obj = pdf_dict_get(ctx, dict, PDF_NAME_Dest)) != NULL) node->uri = pdf_parse_link_dest(ctx, doc, obj); else if ((obj = pdf_dict_get(ctx, dict, PDF_NAME_A)) != NULL) node->uri = pdf_parse_link_action(ctx, doc, obj); else node->uri = NULL; if (node->uri) node->page = pdf_resolve_link(ctx, doc, node->uri, NULL, NULL); else node->page = -1; obj = pdf_dict_get(ctx, dict, PDF_NAME_First); if (obj) { node->down = pdf_load_outline_imp(ctx, doc, obj); obj = pdf_dict_get(ctx, dict, PDF_NAME_Count); if (pdf_to_int(ctx, obj) > 0) node->is_open = 1; } dict = pdf_dict_get(ctx, dict, PDF_NAME_Next); } } fz_always(ctx) { for (dict = odict; dict && pdf_obj_marked(ctx, dict); dict = pdf_dict_get(ctx, dict, PDF_NAME_Next)) pdf_unmark_obj(ctx, dict); } fz_catch(ctx) { fz_drop_outline(ctx, first); fz_rethrow(ctx); } return first; }