diff options
Diffstat (limited to 'pdf/pdf_page.c')
-rw-r--r-- | pdf/pdf_page.c | 137 |
1 files changed, 88 insertions, 49 deletions
diff --git a/pdf/pdf_page.c b/pdf/pdf_page.c index bbc335bb..a5a25989 100644 --- a/pdf/pdf_page.c +++ b/pdf/pdf_page.c @@ -27,75 +27,114 @@ put_marker_bool(fz_context *ctx, pdf_obj *rdb, char *marker, int val) pdf_drop_obj(tmp); } +typedef struct pdf_page_load_s pdf_page_load; + +struct pdf_page_load_s +{ + int max; + int pos; + pdf_obj *node; + pdf_obj *kids; + struct info info; +}; + static void pdf_load_page_tree_node(pdf_document *xref, pdf_obj *node, struct info info) { pdf_obj *dict, *kids, *count; pdf_obj *obj; - int i, n; fz_context *ctx = xref->ctx; - - /* prevent infinite recursion */ - if (!node || pdf_dict_mark(node)) - return; + pdf_page_load *stack = NULL; + int stacklen = -1; + int stackmax = 0; fz_try(ctx) { - kids = pdf_dict_gets(node, "Kids"); - count = pdf_dict_gets(node, "Count"); - - if (pdf_is_array(kids) && pdf_is_int(count)) + do { - obj = pdf_dict_gets(node, "Resources"); - if (obj) - info.resources = obj; - obj = pdf_dict_gets(node, "MediaBox"); - if (obj) - info.mediabox = obj; - obj = pdf_dict_gets(node, "CropBox"); - if (obj) - info.cropbox = obj; - obj = pdf_dict_gets(node, "Rotate"); - if (obj) - info.rotate = obj; - - n = pdf_array_len(kids); - for (i = 0; i < n; i++) + if (!node || pdf_dict_mark(node)) { - obj = pdf_array_get(kids, i); - pdf_load_page_tree_node(xref, obj, info); + /* NULL node, or we've been here before. + * Nothing to do. */ } - } - else if ((dict = pdf_to_dict(node)) != NULL) - { - if (info.resources && !pdf_dict_gets(dict, "Resources")) - pdf_dict_puts(dict, "Resources", info.resources); - if (info.mediabox && !pdf_dict_gets(dict, "MediaBox")) - pdf_dict_puts(dict, "MediaBox", info.mediabox); - if (info.cropbox && !pdf_dict_gets(dict, "CropBox")) - pdf_dict_puts(dict, "CropBox", info.cropbox); - if (info.rotate && !pdf_dict_gets(dict, "Rotate")) - pdf_dict_puts(dict, "Rotate", info.rotate); - - if (xref->page_len == xref->page_cap) + else { - fz_warn(ctx, "found more pages than expected"); - xref->page_refs = fz_resize_array(ctx, xref->page_refs, xref->page_cap+1, sizeof(pdf_obj*)); - xref->page_objs = fz_resize_array(ctx, xref->page_objs, xref->page_cap+1, sizeof(pdf_obj*)); - xref->page_cap ++; + kids = pdf_dict_gets(node, "Kids"); + count = pdf_dict_gets(node, "Count"); + if (pdf_is_array(kids) && pdf_is_int(count)) + { + /* Push this onto the stack */ + obj = pdf_dict_gets(node, "Resources"); + if (obj) + info.resources = obj; + obj = pdf_dict_gets(node, "MediaBox"); + if (obj) + info.mediabox = obj; + obj = pdf_dict_gets(node, "CropBox"); + if (obj) + info.cropbox = obj; + obj = pdf_dict_gets(node, "Rotate"); + if (obj) + info.rotate = obj; + stacklen++; + if (stacklen == stackmax) + { + stack = fz_resize_array(ctx, stack, stackmax ? stackmax*2 : 10, sizeof(*stack)); + stackmax = stackmax ? stackmax*2 : 10; + } + stack[stacklen].kids = kids; + stack[stacklen].node = node; + stack[stacklen].pos = -1; + stack[stacklen].max = pdf_array_len(kids); + stack[stacklen].info = info; + } + else if ((dict = pdf_to_dict(node)) != NULL) + { + if (info.resources && !pdf_dict_gets(dict, "Resources")) + pdf_dict_puts(dict, "Resources", info.resources); + if (info.mediabox && !pdf_dict_gets(dict, "MediaBox")) + pdf_dict_puts(dict, "MediaBox", info.mediabox); + if (info.cropbox && !pdf_dict_gets(dict, "CropBox")) + pdf_dict_puts(dict, "CropBox", info.cropbox); + if (info.rotate && !pdf_dict_gets(dict, "Rotate")) + pdf_dict_puts(dict, "Rotate", info.rotate); + + if (xref->page_len == xref->page_cap) + { + fz_warn(ctx, "found more pages than expected"); + xref->page_refs = fz_resize_array(ctx, xref->page_refs, xref->page_cap+1, sizeof(pdf_obj*)); + xref->page_objs = fz_resize_array(ctx, xref->page_objs, xref->page_cap+1, sizeof(pdf_obj*)); + xref->page_cap ++; + } + + xref->page_refs[xref->page_len] = pdf_keep_obj(node); + xref->page_objs[xref->page_len] = pdf_keep_obj(dict); + xref->page_len ++; + pdf_dict_unmark(node); + } } - - xref->page_refs[xref->page_len] = pdf_keep_obj(node); - xref->page_objs[xref->page_len] = pdf_keep_obj(dict); - xref->page_len ++; + /* Get the next node */ + while (++stack[stacklen].pos == stack[stacklen].max) + { + pdf_dict_unmark(stack[stacklen].node); + stacklen--; + if (stacklen < 0) /* No more to pop! */ + break; + node = stack[stacklen].node; + info = stack[stacklen].info; + pdf_dict_unmark(node); /* Unmark it, cos we're about to mark it again */ + } + if (stacklen >= 0) + node = pdf_array_get(stack[stacklen].kids, stack[stacklen].pos); } + while (stacklen >= 0); } fz_catch(ctx) { - pdf_dict_unmark(node); + while (stacklen >= 0) + pdf_dict_unmark(stack[stacklen--].node); fz_rethrow(ctx); } - pdf_dict_unmark(node); } static void |