#include "mupdf/fitz.h" #include "mupdf/pdf.h" static fz_outline * pdf_load_outline_imp(fz_context *ctx, pdf_document *doc, pdf_obj *dict) { fz_outline *node, **prev, *first = NULL; pdf_obj *obj; pdf_obj *odict = dict; fz_var(dict); fz_var(first); fz_try(ctx) { 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 = fz_strdup(ctx, pdf_to_text_string(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, -1); else node->uri = NULL; if (node->uri && !fz_is_external_link(ctx, node->uri)) node->page = pdf_resolve_link(ctx, doc, node->uri, &node->x, &node->y); 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; } fz_outline * pdf_load_outline(fz_context *ctx, pdf_document *doc) { pdf_obj *root, *obj, *first; fz_outline *outline = NULL; pdf_load_page_tree(ctx, doc); /* cache page tree for fast link destination lookups */ fz_try(ctx) { root = pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME(Root)); obj = pdf_dict_get(ctx, root, PDF_NAME(Outlines)); first = pdf_dict_get(ctx, obj, PDF_NAME(First)); if (first) outline = pdf_load_outline_imp(ctx, doc, first); } fz_always(ctx) pdf_drop_page_tree(ctx, doc); fz_catch(ctx) fz_rethrow(ctx); return outline; }