| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694 |
- // Copyright (C) 2004-2025 Artifex Software, Inc.
- //
- // This file is part of MuPDF.
- //
- // MuPDF is free software: you can redistribute it and/or modify it under the
- // terms of the GNU Affero General Public License as published by the Free
- // Software Foundation, either version 3 of the License, or (at your option)
- // any later version.
- //
- // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
- // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
- // details.
- //
- // You should have received a copy of the GNU Affero General Public License
- // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
- //
- // Alternative licensing terms are available from the licensor.
- // For commercial licensing, see <https://www.artifex.com/> or contact
- // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
- // CA 94129, USA, for further information.
- #include "mupdf/fitz.h"
- #include "pdf-annot-imp.h"
- static void
- pdf_run_annot_with_usage(fz_context *ctx, pdf_document *doc, pdf_page *page, pdf_annot *annot, fz_device *dev, fz_matrix ctm, const char *usage, fz_cookie *cookie)
- {
- fz_matrix page_ctm;
- fz_rect mediabox;
- pdf_processor *proc = NULL;
- fz_default_colorspaces *default_cs = NULL;
- int flags;
- int resources_pushed = 0;
- int struct_parent_num;
- pdf_obj *struct_parent;
- fz_var(proc);
- fz_var(default_cs);
- fz_var(resources_pushed);
- if (cookie && page->super.incomplete)
- cookie->incomplete = 1;
- pdf_annot_push_local_xref(ctx, annot);
- /* Widgets only get displayed if they have both a T and a TF flag,
- * apparently */
- if (pdf_name_eq(ctx, pdf_dict_get(ctx, annot->obj, PDF_NAME(Subtype)), PDF_NAME(Widget)))
- {
- pdf_obj *ft = pdf_dict_get_inheritable(ctx, annot->obj, PDF_NAME(FT));
- pdf_obj *t = pdf_dict_get_inheritable(ctx, annot->obj, PDF_NAME(T));
- if (ft == NULL || t == NULL)
- {
- pdf_annot_pop_local_xref(ctx, annot);
- return;
- }
- }
- fz_try(ctx)
- {
- default_cs = pdf_load_default_colorspaces(ctx, doc, page);
- if (default_cs)
- fz_set_default_colorspaces(ctx, dev, default_cs);
- pdf_page_transform(ctx, page, &mediabox, &page_ctm);
- flags = pdf_dict_get_int(ctx, annot->obj, PDF_NAME(F));
- if (flags & PDF_ANNOT_IS_NO_ROTATE)
- {
- int rotate = pdf_dict_get_inheritable_int(ctx, page->obj, PDF_NAME(Rotate));
- fz_rect rect = pdf_dict_get_rect(ctx, annot->obj, PDF_NAME(Rect));
- fz_point tp = fz_transform_point_xy(rect.x0, rect.y1, page_ctm);
- page_ctm = fz_concat(page_ctm, fz_translate(-tp.x, -tp.y));
- page_ctm = fz_concat(page_ctm, fz_rotate(-rotate));
- page_ctm = fz_concat(page_ctm, fz_translate(tp.x, tp.y));
- }
- ctm = fz_concat(page_ctm, ctm);
- struct_parent = pdf_dict_getl(ctx, page->obj, PDF_NAME(StructParent), NULL);
- struct_parent_num = pdf_to_int_default(ctx, struct_parent, -1);
- proc = pdf_new_run_processor(ctx, page->doc, dev, ctm, struct_parent_num, usage, NULL, default_cs, cookie, NULL, NULL);
- pdf_processor_push_resources(ctx, proc, pdf_page_resources(ctx, annot->page));
- resources_pushed = 1;
- pdf_process_annot(ctx, proc, annot, cookie);
- pdf_close_processor(ctx, proc);
- }
- fz_always(ctx)
- {
- if (resources_pushed)
- pdf_processor_pop_resources(ctx, proc);
- pdf_drop_processor(ctx, proc);
- fz_drop_default_colorspaces(ctx, default_cs);
- pdf_annot_pop_local_xref(ctx, annot);
- }
- fz_catch(ctx)
- fz_rethrow(ctx);
- }
- static fz_rect pdf_page_cropbox(fz_context *ctx, pdf_page *page)
- {
- pdf_obj *obj = pdf_dict_get_inheritable(ctx, page->obj, PDF_NAME(CropBox));
- if (!obj)
- obj = pdf_dict_get_inheritable(ctx, page->obj, PDF_NAME(MediaBox));
- return pdf_to_rect(ctx, obj);
- }
- static fz_rect pdf_page_mediabox(fz_context *ctx, pdf_page *page)
- {
- return pdf_dict_get_inheritable_rect(ctx, page->obj, PDF_NAME(MediaBox));
- }
- static void
- pdf_run_page_contents_with_usage_imp(fz_context *ctx, pdf_document *doc, pdf_page *page, fz_device *dev, fz_matrix ctm, const char *usage, fz_cookie *cookie)
- {
- fz_matrix page_ctm;
- pdf_obj *resources;
- pdf_obj *contents;
- fz_rect fitzbox;
- fz_rect mediabox, cropbox;
- pdf_processor *proc = NULL;
- fz_default_colorspaces *default_cs = NULL;
- fz_colorspace *colorspace = NULL;
- fz_path *path = NULL;
- int struct_parent_num;
- pdf_obj *struct_parent;
- fz_var(proc);
- fz_var(colorspace);
- fz_var(default_cs);
- fz_var(path);
- if (cookie && page->super.incomplete)
- cookie->incomplete = 1;
- fz_try(ctx)
- {
- default_cs = pdf_load_default_colorspaces(ctx, doc, page);
- if (default_cs)
- fz_set_default_colorspaces(ctx, dev, default_cs);
- pdf_page_transform(ctx, page, &fitzbox, &page_ctm);
- ctm = fz_concat(page_ctm, ctm);
- fitzbox = fz_transform_rect(fitzbox, ctm);
- resources = pdf_page_resources(ctx, page);
- contents = pdf_page_contents(ctx, page);
- mediabox = pdf_page_mediabox(ctx, page);
- cropbox = pdf_page_cropbox(ctx, page);
- if (page->transparency)
- {
- pdf_obj *group = pdf_page_group(ctx, page);
- if (group)
- {
- pdf_obj *cs = pdf_dict_get(ctx, group, PDF_NAME(CS));
- if (cs)
- {
- fz_try(ctx)
- colorspace = pdf_load_colorspace(ctx, cs);
- fz_catch(ctx)
- {
- fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
- fz_rethrow_if(ctx, FZ_ERROR_SYSTEM);
- fz_report_error(ctx);
- fz_warn(ctx, "Ignoring Page blending colorspace.");
- }
- if (!fz_is_valid_blend_colorspace(ctx, colorspace))
- {
- fz_warn(ctx, "Ignoring invalid Page blending colorspace: %s.", colorspace->name);
- fz_drop_colorspace(ctx, colorspace);
- colorspace = NULL;
- }
- }
- }
- else
- colorspace = fz_keep_colorspace(ctx, fz_default_output_intent(ctx, default_cs));
- fz_begin_group(ctx, dev, fitzbox, colorspace, 1, 0, 0, 1);
- }
- struct_parent = pdf_dict_get(ctx, page->obj, PDF_NAME(StructParents));
- struct_parent_num = pdf_to_int_default(ctx, struct_parent, -1);
- /* Clip content to CropBox if it is smaller than the MediaBox */
- if (cropbox.x0 > mediabox.x0 || cropbox.x1 < mediabox.x1 || cropbox.y0 > mediabox.y0 || cropbox.y1 < mediabox.y1)
- {
- path = fz_new_path(ctx);
- fz_rectto(ctx, path, cropbox.x0, cropbox.y0, cropbox.x1, cropbox.y1);
- fz_clip_path(ctx, dev, path, 1, ctm, fz_infinite_rect);
- }
- proc = pdf_new_run_processor(ctx, page->doc, dev, ctm, struct_parent_num, usage, NULL, default_cs, cookie, NULL, NULL);
- pdf_process_contents(ctx, proc, doc, resources, contents, cookie, NULL);
- pdf_close_processor(ctx, proc);
- if (cropbox.x0 > mediabox.x0 || cropbox.x1 < mediabox.x1 || cropbox.y0 > mediabox.y0 || cropbox.y1 < mediabox.y1)
- {
- fz_pop_clip(ctx, dev);
- }
- if (page->transparency)
- {
- fz_end_group(ctx, dev);
- }
- }
- fz_always(ctx)
- {
- fz_drop_path(ctx, path);
- pdf_drop_processor(ctx, proc);
- fz_drop_colorspace(ctx, colorspace);
- fz_drop_default_colorspaces(ctx, default_cs);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
- }
- void pdf_run_page_contents_with_usage(fz_context *ctx, pdf_page *page, fz_device *dev, fz_matrix ctm, const char *usage, fz_cookie *cookie)
- {
- pdf_document *doc = page->doc;
- int nocache;
- nocache = !!(dev->hints & FZ_NO_CACHE);
- if (nocache)
- pdf_mark_xref(ctx, doc);
- fz_try(ctx)
- {
- pdf_run_page_contents_with_usage_imp(ctx, doc, page, dev, ctm, usage, cookie);
- }
- fz_always(ctx)
- {
- if (nocache)
- pdf_clear_xref_to_mark(ctx, doc);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
- }
- void pdf_run_page_contents(fz_context *ctx, pdf_page *page, fz_device *dev, fz_matrix ctm, fz_cookie *cookie)
- {
- pdf_run_page_contents_with_usage(ctx, page, dev, ctm, "View", cookie);
- }
- void pdf_run_annot(fz_context *ctx, pdf_annot *annot, fz_device *dev, fz_matrix ctm, fz_cookie *cookie)
- {
- pdf_page *page = annot->page;
- pdf_document *doc;
- int nocache;
- if (!page)
- fz_throw(ctx, FZ_ERROR_ARGUMENT, "annotation not bound to any page");
- doc = page->doc;
- nocache = !!(dev->hints & FZ_NO_CACHE);
- if (nocache)
- pdf_mark_xref(ctx, doc);
- fz_try(ctx)
- {
- pdf_run_annot_with_usage(ctx, doc, page, annot, dev, ctm, "View", cookie);
- }
- fz_always(ctx)
- {
- if (nocache)
- pdf_clear_xref_to_mark(ctx, doc);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
- }
- static void
- pdf_run_page_widgets_with_usage_imp(fz_context *ctx, pdf_document *doc, pdf_page *page, fz_device *dev, fz_matrix ctm, const char *usage, fz_cookie *cookie)
- {
- pdf_annot *widget;
- if (cookie && cookie->progress_max != (size_t)-1)
- {
- int count = 1;
- for (widget = page->widgets; widget; widget = widget->next)
- count++;
- cookie->progress_max += count;
- }
- for (widget = page->widgets; widget; widget = widget->next)
- {
- /* Check the cookie for aborting */
- if (cookie)
- {
- if (cookie->abort)
- break;
- cookie->progress++;
- }
- pdf_run_annot_with_usage(ctx, doc, page, widget, dev, ctm, usage, cookie);
- }
- }
- static void
- pdf_run_page_annots_with_usage_imp(fz_context *ctx, pdf_document *doc, pdf_page *page, fz_device *dev, fz_matrix ctm, const char *usage, fz_cookie *cookie)
- {
- pdf_annot *annot;
- if (cookie && cookie->progress_max != (size_t)-1)
- {
- int count = 1;
- for (annot = page->annots; annot; annot = annot->next)
- count++;
- cookie->progress_max += count;
- }
- for (annot = page->annots; annot; annot = annot->next)
- {
- /* Check the cookie for aborting */
- if (cookie)
- {
- if (cookie->abort)
- break;
- cookie->progress++;
- }
- pdf_run_annot_with_usage(ctx, doc, page, annot, dev, ctm, usage, cookie);
- }
- }
- void pdf_run_page_annots_with_usage(fz_context *ctx, pdf_page *page, fz_device *dev, fz_matrix ctm, const char *usage, fz_cookie *cookie)
- {
- pdf_document *doc = page->doc;
- int nocache;
- nocache = !!(dev->hints & FZ_NO_CACHE);
- if (nocache)
- pdf_mark_xref(ctx, doc);
- fz_try(ctx)
- {
- pdf_run_page_annots_with_usage_imp(ctx, doc, page, dev, ctm, usage, cookie);
- }
- fz_always(ctx)
- {
- if (nocache)
- pdf_clear_xref_to_mark(ctx, doc);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
- }
- void pdf_run_page_annots(fz_context *ctx, pdf_page *page, fz_device *dev, fz_matrix ctm, fz_cookie *cookie)
- {
- pdf_run_page_annots_with_usage(ctx, page, dev, ctm, "View", cookie);
- }
- void pdf_run_page_widgets_with_usage(fz_context *ctx, pdf_page *page, fz_device *dev, fz_matrix ctm, const char *usage, fz_cookie *cookie)
- {
- pdf_document *doc = page->doc;
- int nocache;
- nocache = !!(dev->hints & FZ_NO_CACHE);
- if (nocache)
- pdf_mark_xref(ctx, doc);
- fz_try(ctx)
- {
- pdf_run_page_widgets_with_usage_imp(ctx, doc, page, dev, ctm, usage, cookie);
- }
- fz_always(ctx)
- {
- if (nocache)
- pdf_clear_xref_to_mark(ctx, doc);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
- }
- void pdf_run_page_widgets(fz_context *ctx, pdf_page *page, fz_device *dev, fz_matrix ctm, fz_cookie *cookie)
- {
- pdf_run_page_widgets_with_usage(ctx, page, dev, ctm, "View", cookie);
- }
- void
- pdf_run_page_with_usage(fz_context *ctx, pdf_page *page, fz_device *dev, fz_matrix ctm, const char *usage, fz_cookie *cookie)
- {
- pdf_document *doc = page->doc;
- int nocache = !!(dev->hints & FZ_NO_CACHE);
- if (nocache)
- pdf_mark_xref(ctx, doc);
- fz_try(ctx)
- {
- pdf_run_page_contents_with_usage_imp(ctx, doc, page, dev, ctm, usage, cookie);
- pdf_run_page_annots_with_usage_imp(ctx, doc, page, dev, ctm, usage, cookie);
- pdf_run_page_widgets_with_usage_imp(ctx, doc, page, dev, ctm, usage, cookie);
- }
- fz_always(ctx)
- {
- if (nocache)
- pdf_clear_xref_to_mark(ctx, doc);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
- }
- void
- pdf_run_page(fz_context *ctx, pdf_page *page, fz_device *dev, fz_matrix ctm, fz_cookie *cookie)
- {
- pdf_run_page_with_usage(ctx, page, dev, ctm, "View", cookie);
- }
- void
- pdf_run_glyph(fz_context *ctx, pdf_document *doc, pdf_obj *resources, fz_buffer *contents, fz_device *dev, fz_matrix ctm, void *gstate, fz_default_colorspaces *default_cs, void *fill_gstate, void *stroke_gstate)
- {
- pdf_processor *proc;
- proc = pdf_new_run_processor(ctx, doc, dev, ctm, -1, "View", gstate, default_cs, NULL, fill_gstate, stroke_gstate);
- fz_try(ctx)
- {
- pdf_process_glyph(ctx, proc, doc, resources, contents);
- pdf_close_processor(ctx, proc);
- }
- fz_always(ctx)
- pdf_drop_processor(ctx, proc);
- fz_catch(ctx)
- fz_rethrow(ctx);
- }
- fz_structure
- pdf_structure_type(fz_context *ctx, pdf_obj *role_map, pdf_obj *tag)
- {
- /* Perform Structure mapping to go from tag to standard. */
- if (role_map)
- {
- pdf_obj *o = pdf_dict_get(ctx, role_map, tag);
- if (o)
- tag = o;
- }
- if (pdf_name_eq(ctx, tag, PDF_NAME(Document)))
- return FZ_STRUCTURE_DOCUMENT;
- if (pdf_name_eq(ctx, tag, PDF_NAME(Part)))
- return FZ_STRUCTURE_PART;
- if (pdf_name_eq(ctx, tag, PDF_NAME(Art)))
- return FZ_STRUCTURE_ART;
- if (pdf_name_eq(ctx, tag, PDF_NAME(Sect)))
- return FZ_STRUCTURE_SECT;
- if (pdf_name_eq(ctx, tag, PDF_NAME(Div)))
- return FZ_STRUCTURE_DIV;
- if (pdf_name_eq(ctx, tag, PDF_NAME(BlockQuote)))
- return FZ_STRUCTURE_BLOCKQUOTE;
- if (pdf_name_eq(ctx, tag, PDF_NAME(Caption)))
- return FZ_STRUCTURE_CAPTION;
- if (pdf_name_eq(ctx, tag, PDF_NAME(TOC)))
- return FZ_STRUCTURE_TOC;
- if (pdf_name_eq(ctx, tag, PDF_NAME(TOCI)))
- return FZ_STRUCTURE_TOCI;
- if (pdf_name_eq(ctx, tag, PDF_NAME(Index)))
- return FZ_STRUCTURE_INDEX;
- if (pdf_name_eq(ctx, tag, PDF_NAME(NonStruct)))
- return FZ_STRUCTURE_NONSTRUCT;
- if (pdf_name_eq(ctx, tag, PDF_NAME(Private)))
- return FZ_STRUCTURE_PRIVATE;
- /* Grouping elements (PDF 2.0 - Table 364) */
- if (pdf_name_eq(ctx, tag, PDF_NAME(DocumentFragment)))
- return FZ_STRUCTURE_DOCUMENTFRAGMENT;
- /* Grouping elements (PDF 2.0 - Table 365) */
- if (pdf_name_eq(ctx, tag, PDF_NAME(Aside)))
- return FZ_STRUCTURE_ASIDE;
- /* Grouping elements (PDF 2.0 - Table 366) */
- if (pdf_name_eq(ctx, tag, PDF_NAME(Title)))
- return FZ_STRUCTURE_TITLE;
- if (pdf_name_eq(ctx, tag, PDF_NAME(FENote)))
- return FZ_STRUCTURE_FENOTE;
- /* Grouping elements (PDF 2.0 - Table 367) */
- if (pdf_name_eq(ctx, tag, PDF_NAME(Sub)))
- return FZ_STRUCTURE_SUB;
- /* Paragraphlike elements (PDF 1.7 - Table 10.21) */
- if (pdf_name_eq(ctx, tag, PDF_NAME(P)))
- return FZ_STRUCTURE_P;
- if (pdf_name_eq(ctx, tag, PDF_NAME(H)))
- return FZ_STRUCTURE_H;
- if (pdf_name_eq(ctx, tag, PDF_NAME(H1)))
- return FZ_STRUCTURE_H1;
- if (pdf_name_eq(ctx, tag, PDF_NAME(H2)))
- return FZ_STRUCTURE_H2;
- if (pdf_name_eq(ctx, tag, PDF_NAME(H3)))
- return FZ_STRUCTURE_H3;
- if (pdf_name_eq(ctx, tag, PDF_NAME(H4)))
- return FZ_STRUCTURE_H4;
- if (pdf_name_eq(ctx, tag, PDF_NAME(H5)))
- return FZ_STRUCTURE_H5;
- if (pdf_name_eq(ctx, tag, PDF_NAME(H6)))
- return FZ_STRUCTURE_H6;
- /* List elements (PDF 1.7 - Table 10.23) */
- if (pdf_name_eq(ctx, tag, PDF_NAME(L)))
- return FZ_STRUCTURE_LIST;
- if (pdf_name_eq(ctx, tag, PDF_NAME(LI)))
- return FZ_STRUCTURE_LISTITEM;
- if (pdf_name_eq(ctx, tag, PDF_NAME(Lbl)))
- return FZ_STRUCTURE_LABEL;
- if (pdf_name_eq(ctx, tag, PDF_NAME(LBody)))
- return FZ_STRUCTURE_LISTBODY;
- /* Table elements (PDF 1.7 - Table 10.24) */
- if (pdf_name_eq(ctx, tag, PDF_NAME(Table)))
- return FZ_STRUCTURE_TABLE;
- if (pdf_name_eq(ctx, tag, PDF_NAME(TR)))
- return FZ_STRUCTURE_TR;
- if (pdf_name_eq(ctx, tag, PDF_NAME(TH)))
- return FZ_STRUCTURE_TH;
- if (pdf_name_eq(ctx, tag, PDF_NAME(TD)))
- return FZ_STRUCTURE_TD;
- if (pdf_name_eq(ctx, tag, PDF_NAME(THead)))
- return FZ_STRUCTURE_THEAD;
- if (pdf_name_eq(ctx, tag, PDF_NAME(TBody)))
- return FZ_STRUCTURE_TBODY;
- if (pdf_name_eq(ctx, tag, PDF_NAME(TFoot)))
- return FZ_STRUCTURE_TFOOT;
- /* Inline elements (PDF 1.7 - Table 10.25) */
- if (pdf_name_eq(ctx, tag, PDF_NAME(Span)))
- return FZ_STRUCTURE_SPAN;
- if (pdf_name_eq(ctx, tag, PDF_NAME(Quote)))
- return FZ_STRUCTURE_QUOTE;
- if (pdf_name_eq(ctx, tag, PDF_NAME(Note)))
- return FZ_STRUCTURE_NOTE;
- if (pdf_name_eq(ctx, tag, PDF_NAME(Reference)))
- return FZ_STRUCTURE_REFERENCE;
- if (pdf_name_eq(ctx, tag, PDF_NAME(BibEntry)))
- return FZ_STRUCTURE_BIBENTRY;
- if (pdf_name_eq(ctx, tag, PDF_NAME(Code)))
- return FZ_STRUCTURE_CODE;
- if (pdf_name_eq(ctx, tag, PDF_NAME(Link)))
- return FZ_STRUCTURE_LINK;
- if (pdf_name_eq(ctx, tag, PDF_NAME(Annot)))
- return FZ_STRUCTURE_ANNOT;
- /* Inline elements (PDF 2.0 - Table 368) */
- if (pdf_name_eq(ctx, tag, PDF_NAME(Em)))
- return FZ_STRUCTURE_EM;
- if (pdf_name_eq(ctx, tag, PDF_NAME(Strong)))
- return FZ_STRUCTURE_STRONG;
- /* Ruby inline element (PDF 1.7 - Table 10.26) */
- if (pdf_name_eq(ctx, tag, PDF_NAME(Ruby)))
- return FZ_STRUCTURE_RUBY;
- if (pdf_name_eq(ctx, tag, PDF_NAME(RB)))
- return FZ_STRUCTURE_RB;
- if (pdf_name_eq(ctx, tag, PDF_NAME(RT)))
- return FZ_STRUCTURE_RT;
- if (pdf_name_eq(ctx, tag, PDF_NAME(RP)))
- return FZ_STRUCTURE_RP;
- /* Warichu inline element (PDF 1.7 - Table 10.26) */
- if (pdf_name_eq(ctx, tag, PDF_NAME(Warichu)))
- return FZ_STRUCTURE_WARICHU;
- if (pdf_name_eq(ctx, tag, PDF_NAME(WT)))
- return FZ_STRUCTURE_WT;
- if (pdf_name_eq(ctx, tag, PDF_NAME(WP)))
- return FZ_STRUCTURE_WP;
- /* Illustration elements (PDF 1.7 - Table 10.27) */
- if (pdf_name_eq(ctx, tag, PDF_NAME(Figure)))
- return FZ_STRUCTURE_FIGURE;
- if (pdf_name_eq(ctx, tag, PDF_NAME(Formula)))
- return FZ_STRUCTURE_FORMULA;
- if (pdf_name_eq(ctx, tag, PDF_NAME(Form)))
- return FZ_STRUCTURE_FORM;
- /* Artifact structure type (PDF 2.0 - Table 375) */
- if (pdf_name_eq(ctx, tag, PDF_NAME(Artifact)))
- return FZ_STRUCTURE_ARTIFACT;
- return FZ_STRUCTURE_INVALID;
- }
- /* The recursive descent of the structure tree uses an fz_try at each level.
- * At the risk of creating a foot cannon... "no one will need more than ~64
- * levels of structure tree". */
- static void
- run_ds(fz_context *ctx, fz_device *dev, pdf_obj *role_map, pdf_obj *obj, int idx, fz_cookie *cookie)
- {
- pdf_obj *k;
- int i, n;
- /* Check the cookie for aborting */
- if (cookie)
- {
- if (cookie->abort)
- return;
- cookie->progress++;
- }
- if (pdf_is_number(ctx, obj))
- {
- /* A marked-content identifier denoting a marked content sequence. WHAT? */
- return;
- }
- if (pdf_mark_obj(ctx, obj))
- return;
- fz_try(ctx)
- {
- fz_structure standard;
- pdf_obj *tag = pdf_dict_get(ctx, obj, PDF_NAME(S));
- if (!tag)
- break;
- standard = pdf_structure_type(ctx, role_map, tag);
- if (standard == FZ_STRUCTURE_INVALID)
- break;
- fz_begin_structure(ctx, dev, standard, pdf_to_name(ctx, tag), idx);
- k = pdf_dict_get(ctx, obj, PDF_NAME(K));
- if (k)
- {
- n = pdf_array_len(ctx, k);
- if (n == 0)
- run_ds(ctx, dev, role_map, k, 0, cookie);
- else
- {
- for (i = 0; i < n; i++)
- run_ds(ctx, dev, role_map, pdf_array_get(ctx, k, i), i, cookie);
- }
- }
- fz_end_structure(ctx, dev);
- }
- fz_always(ctx)
- pdf_unmark_obj(ctx, obj);
- fz_catch(ctx)
- fz_rethrow(ctx);
- }
- void pdf_run_document_structure(fz_context *ctx, pdf_document *doc, fz_device *dev, fz_cookie *cookie)
- {
- int nocache;
- int marked = 0;
- pdf_obj *st, *rm, *k;
- fz_var(marked);
- nocache = !!(dev->hints & FZ_NO_CACHE);
- if (nocache)
- pdf_mark_xref(ctx, doc);
- fz_try(ctx)
- {
- st = pdf_dict_get(ctx, pdf_dict_get(ctx, pdf_trailer(ctx, doc), PDF_NAME(Root)), PDF_NAME(StructTreeRoot));
- rm = pdf_dict_get(ctx, st, PDF_NAME(RoleMap));
- if (pdf_mark_obj(ctx, st))
- break;
- marked = 1;
- k = pdf_dict_get(ctx, st, PDF_NAME(K));
- if (k)
- {
- int n = pdf_array_len(ctx, k);
- if (n == 0)
- run_ds(ctx, dev, rm, k, 0, cookie);
- else
- {
- int i;
- for (i = 0; i < n; i++)
- run_ds(ctx, dev, rm, pdf_array_get(ctx, k, i), i, cookie);
- }
- }
- }
- fz_always(ctx)
- {
- if (marked)
- pdf_unmark_obj(ctx, st);
- if (nocache)
- pdf_clear_xref_to_mark(ctx, doc);
- }
- fz_catch(ctx)
- fz_rethrow(ctx);
- }
|