| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693 |
- // 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.
- /*
- * pdfshow -- the ultimate pdf debugging tool
- */
- #include "mupdf/fitz.h"
- #include "mupdf/pdf.h"
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- static pdf_document *doc = NULL;
- static fz_output *out = NULL;
- static pdf_object_labels *labels = NULL;
- static int showbinary = 0;
- static int showdecode = 1;
- static int do_tight = 0;
- static int do_repair = 0;
- static int do_label = 0;
- static int showcolumn;
- static int usage(void)
- {
- fprintf(stderr,
- "usage: mutool show [options] file.pdf ( trailer | xref | pages | grep | outline | js | form | <path> ) *\n"
- "\t-p -\tpassword\n"
- "\t-o -\toutput file\n"
- "\t-e\tleave stream contents in their original form\n"
- "\t-b\tprint only stream contents, as raw binary data\n"
- "\t-g\tprint only object, one line per object, suitable for grep\n"
- "\t-r\tforce repair before showing any objects\n"
- "\t-L\tshow object labels\n"
- "\tpath: path to an object, starting with either an object number,\n"
- "\t\t'pages', 'trailer', or a property in the trailer;\n"
- "\t\tpath elements separated by '.' or '/'. Path elements must be\n"
- "\t\tarray index numbers, dictionary property names, or '*'.\n"
- );
- return 1;
- }
- static void showtrailer(fz_context *ctx)
- {
- if (do_tight)
- fz_write_printf(ctx, out, "trailer ");
- else
- fz_write_printf(ctx, out, "trailer\n");
- pdf_print_obj(ctx, out, pdf_trailer(ctx, doc), do_tight, 1);
- fz_write_printf(ctx, out, "\n");
- }
- static void showxref(fz_context *ctx)
- {
- int i;
- int xref_len = pdf_xref_len(ctx, doc);
- fz_write_printf(ctx, out, "xref\n0 %d\n", xref_len);
- for (i = 0; i < xref_len; i++)
- {
- pdf_xref_entry *entry = pdf_get_xref_entry_no_null(ctx, doc, i);
- fz_write_printf(ctx, out, "%05d: %010d %05d %c \n",
- i,
- (int)entry->ofs,
- entry->gen,
- entry->type ? entry->type : '-');
- }
- }
- static void showpages(fz_context *ctx)
- {
- pdf_obj *ref;
- int i, n = pdf_count_pages(ctx, doc);
- for (i = 0; i < n; ++i)
- {
- ref = pdf_lookup_page_obj(ctx, doc, i);
- fz_write_printf(ctx, out, "page %d = %d 0 R\n", i + 1, pdf_to_num(ctx, ref));
- }
- }
- static void showsafe(unsigned char *buf, size_t n)
- {
- size_t i;
- for (i = 0; i < n; i++) {
- if (buf[i] == '\r' || buf[i] == '\n') {
- putchar('\n');
- showcolumn = 0;
- }
- else if (buf[i] < 32 || buf[i] > 126) {
- putchar('.');
- showcolumn ++;
- }
- else {
- putchar(buf[i]);
- showcolumn ++;
- }
- if (showcolumn == 79) {
- putchar('\n');
- showcolumn = 0;
- }
- }
- }
- static void showstream(fz_context *ctx, int num)
- {
- fz_stream *stm;
- unsigned char buf[2048];
- size_t n;
- showcolumn = 0;
- if (showdecode)
- stm = pdf_open_stream_number(ctx, doc, num);
- else
- stm = pdf_open_raw_stream_number(ctx, doc, num);
- while (1)
- {
- n = fz_read(ctx, stm, buf, sizeof buf);
- if (n == 0)
- break;
- if (showbinary)
- fz_write_data(ctx, out, buf, n);
- else
- showsafe(buf, n);
- }
- fz_drop_stream(ctx, stm);
- }
- static void showlabel(fz_context *ctx, void *arg, const char *label)
- {
- fz_write_printf(ctx, arg, "%% %s\n", label);
- }
- static void showobject(fz_context *ctx, pdf_obj *ref)
- {
- pdf_obj *obj = pdf_resolve_indirect(ctx, ref);
- int num = pdf_to_num(ctx, ref);
- if (pdf_is_stream(ctx, ref))
- {
- if (showbinary)
- {
- showstream(ctx, num);
- }
- else
- {
- if (do_label)
- pdf_label_object(ctx, labels, num, showlabel, out);
- if (do_tight)
- {
- fz_write_printf(ctx, out, "%d 0 obj ", num);
- pdf_print_obj(ctx, out, obj, 1, 1);
- fz_write_printf(ctx, out, " stream\n");
- }
- else
- {
- fz_write_printf(ctx, out, "%d 0 obj\n", num);
- pdf_print_obj(ctx, out, obj, 0, 1);
- fz_write_printf(ctx, out, "\nstream\n");
- showstream(ctx, num);
- fz_write_printf(ctx, out, "endstream\n");
- fz_write_printf(ctx, out, "endobj\n");
- }
- }
- }
- else
- {
- if (do_label)
- pdf_label_object(ctx, labels, num, showlabel, out);
- if (do_tight)
- {
- fz_write_printf(ctx, out, "%d 0 obj ", num);
- pdf_print_obj(ctx, out, obj, 1, 1);
- fz_write_printf(ctx, out, "\n");
- }
- else
- {
- fz_write_printf(ctx, out, "%d 0 obj\n", num);
- pdf_print_obj(ctx, out, obj, 0, 1);
- fz_write_printf(ctx, out, "\nendobj\n");
- }
- }
- }
- static void showgrep(fz_context *ctx)
- {
- pdf_obj *ref, *obj;
- int i, len;
- len = pdf_count_objects(ctx, doc);
- for (i = 0; i < len; i++)
- {
- pdf_xref_entry *entry = pdf_get_xref_entry_no_null(ctx, doc, i);
- if (entry->type == 'n' || entry->type == 'o')
- {
- fz_try(ctx)
- {
- ref = pdf_new_indirect(ctx, doc, i, 0);
- obj = pdf_resolve_indirect(ctx, ref);
- }
- fz_catch(ctx)
- {
- pdf_drop_obj(ctx, ref);
- fz_warn(ctx, "skipping object (%d 0 R)", i);
- continue;
- }
- pdf_sort_dict(ctx, obj);
- fz_write_printf(ctx, out, "%d 0 obj ", i);
- pdf_print_obj(ctx, out, obj, 1, 1);
- if (pdf_is_stream(ctx, ref))
- fz_write_printf(ctx, out, " stream");
- fz_write_printf(ctx, out, "\n");
- pdf_drop_obj(ctx, ref);
- }
- }
- fz_write_printf(ctx, out, "trailer ");
- pdf_print_obj(ctx, out, pdf_trailer(ctx, doc), 1, 1);
- fz_write_printf(ctx, out, "\n");
- }
- static void
- print_outline(fz_context *ctx, fz_outline *outline, int level)
- {
- int i;
- while (outline)
- {
- if (outline->down)
- fz_write_byte(ctx, out, outline->is_open ? '-' : '+');
- else
- fz_write_byte(ctx, out, '|');
- for (i = 0; i < level; i++)
- fz_write_byte(ctx, out, '\t');
- fz_write_printf(ctx, out, "%Q\t%s\n", outline->title, outline->uri);
- if (outline->down)
- print_outline(ctx, outline->down, level + 1);
- outline = outline->next;
- }
- }
- static void showoutline(fz_context *ctx)
- {
- fz_outline *outline = fz_load_outline(ctx, (fz_document*)doc);
- fz_try(ctx)
- print_outline(ctx, outline, 1);
- fz_always(ctx)
- fz_drop_outline(ctx, outline);
- fz_catch(ctx)
- fz_rethrow(ctx);
- }
- static void showtext(fz_context *ctx, char *buf, int indent)
- {
- int bol = 1;
- int c = *buf;
- while (*buf)
- {
- c = *buf++;
- if (c == '\r')
- {
- if (*buf == '\n')
- ++buf;
- c = '\n';
- }
- if (indent && bol)
- fz_write_byte(ctx, out, '\t');
- fz_write_byte(ctx, out, c);
- bol = (c == '\n');
- }
- if (!bol)
- fz_write_byte(ctx, out, '\n');
- }
- static void showjs(fz_context *ctx)
- {
- pdf_obj *tree;
- int i;
- tree = pdf_load_name_tree(ctx, doc, PDF_NAME(JavaScript));
- for (i = 0; i < pdf_dict_len(ctx, tree); ++i)
- {
- pdf_obj *name = pdf_dict_get_key(ctx, tree, i);
- pdf_obj *action = pdf_dict_get_val(ctx, tree, i);
- pdf_obj *js = pdf_dict_get(ctx, action, PDF_NAME(JS));
- char *src = pdf_load_stream_or_string_as_utf8(ctx, js);
- fz_write_printf(ctx, out, "// %s\n", pdf_to_name(ctx, name));
- showtext(ctx, src, 0);
- fz_free(ctx, src);
- }
- }
- static void showaction(fz_context *ctx, pdf_obj *action, const char *name)
- {
- if (action)
- {
- pdf_obj *js = pdf_dict_get(ctx, action, PDF_NAME(JS));
- if (js)
- {
- char *src = pdf_load_stream_or_string_as_utf8(ctx, js);
- fz_write_printf(ctx, out, " %s: {\n", name);
- showtext(ctx, src, 1);
- fz_write_printf(ctx, out, " }\n", name);
- fz_free(ctx, src);
- }
- else
- {
- fz_write_printf(ctx, out, " %s: ", name);
- if (pdf_is_indirect(ctx, action))
- action = pdf_resolve_indirect(ctx, action);
- pdf_print_obj(ctx, out, action, 1, 1);
- fz_write_printf(ctx, out, "\n");
- }
- }
- }
- static void showfield(fz_context *ctx, pdf_obj *field)
- {
- pdf_obj *kids, *ft, *parent;
- const char *tu;
- char *t;
- int ff;
- int i, n;
- t = pdf_load_field_name(ctx, field);
- tu = pdf_dict_get_text_string(ctx, field, PDF_NAME(TU));
- ft = pdf_dict_get_inheritable(ctx, field, PDF_NAME(FT));
- ff = pdf_field_flags(ctx, field);
- parent = pdf_dict_get(ctx, field, PDF_NAME(Parent));
- fz_write_printf(ctx, out, "field %d\n", pdf_to_num(ctx, field));
- fz_write_printf(ctx, out, " Type: %s\n", pdf_to_name(ctx, ft));
- if (ff)
- {
- fz_write_printf(ctx, out, " Flags:");
- if (ff & PDF_FIELD_IS_READ_ONLY) fz_write_string(ctx, out, " readonly");
- if (ff & PDF_FIELD_IS_REQUIRED) fz_write_string(ctx, out, " required");
- if (ff & PDF_FIELD_IS_NO_EXPORT) fz_write_string(ctx, out, " noExport");
- if (ft == PDF_NAME(Btn))
- {
- if (ff & PDF_BTN_FIELD_IS_NO_TOGGLE_TO_OFF) fz_write_string(ctx, out, " noToggleToOff");
- if (ff & PDF_BTN_FIELD_IS_RADIO) fz_write_string(ctx, out, " radio");
- if (ff & PDF_BTN_FIELD_IS_PUSHBUTTON) fz_write_string(ctx, out, " pushButton");
- if (ff & PDF_BTN_FIELD_IS_RADIOS_IN_UNISON) fz_write_string(ctx, out, " radiosInUnison");
- }
- if (ft == PDF_NAME(Tx))
- {
- if (ff & PDF_TX_FIELD_IS_MULTILINE) fz_write_string(ctx, out, " multiline");
- if (ff & PDF_TX_FIELD_IS_PASSWORD) fz_write_string(ctx, out, " password");
- if (ff & PDF_TX_FIELD_IS_FILE_SELECT) fz_write_string(ctx, out, " fileSelect");
- if (ff & PDF_TX_FIELD_IS_DO_NOT_SPELL_CHECK) fz_write_string(ctx, out, " dontSpellCheck");
- if (ff & PDF_TX_FIELD_IS_DO_NOT_SCROLL) fz_write_string(ctx, out, " dontScroll");
- if (ff & PDF_TX_FIELD_IS_COMB) fz_write_string(ctx, out, " comb");
- if (ff & PDF_TX_FIELD_IS_RICH_TEXT) fz_write_string(ctx, out, " richText");
- }
- if (ft == PDF_NAME(Ch))
- {
- if (ff & PDF_CH_FIELD_IS_COMBO) fz_write_string(ctx, out, " combo");
- if (ff & PDF_CH_FIELD_IS_EDIT) fz_write_string(ctx, out, " edit");
- if (ff & PDF_CH_FIELD_IS_SORT) fz_write_string(ctx, out, " sort");
- if (ff & PDF_CH_FIELD_IS_MULTI_SELECT) fz_write_string(ctx, out, " multiSelect");
- if (ff & PDF_CH_FIELD_IS_DO_NOT_SPELL_CHECK) fz_write_string(ctx, out, " dontSpellCheck");
- if (ff & PDF_CH_FIELD_IS_COMMIT_ON_SEL_CHANGE) fz_write_string(ctx, out, " commitOnSelChange");
- }
- fz_write_string(ctx, out, "\n");
- }
- fz_write_printf(ctx, out, " Name: %(\n", t);
- fz_free(ctx, t);
- if (*tu)
- fz_write_printf(ctx, out, " Label: %q\n", tu);
- if (parent)
- fz_write_printf(ctx, out, " Parent: %d\n", pdf_to_num(ctx, parent));
- showaction(ctx, pdf_dict_getp(ctx, field, "A"), "Action");
- showaction(ctx, pdf_dict_getp_inheritable(ctx, field, "AA/K"), "Keystroke");
- showaction(ctx, pdf_dict_getp_inheritable(ctx, field, "AA/V"), "Validate");
- showaction(ctx, pdf_dict_getp_inheritable(ctx, field, "AA/F"), "Format");
- showaction(ctx, pdf_dict_getp_inheritable(ctx, field, "AA/C"), "Calculate");
- showaction(ctx, pdf_dict_getp_inheritable(ctx, field, "AA/E"), "Enter");
- showaction(ctx, pdf_dict_getp_inheritable(ctx, field, "AA/X"), "Exit");
- showaction(ctx, pdf_dict_getp_inheritable(ctx, field, "AA/D"), "Down");
- showaction(ctx, pdf_dict_getp_inheritable(ctx, field, "AA/U"), "Up");
- showaction(ctx, pdf_dict_getp_inheritable(ctx, field, "AA/Fo"), "Focus");
- showaction(ctx, pdf_dict_getp_inheritable(ctx, field, "AA/Bl"), "Blur");
- fz_write_string(ctx, out, "\n");
- kids = pdf_dict_get(ctx, field, PDF_NAME(Kids));
- n = pdf_array_len(ctx, kids);
- for (i = 0; i < n; ++i)
- showfield(ctx, pdf_array_get(ctx, kids, i));
- }
- static void showform(fz_context *ctx)
- {
- pdf_obj *fields;
- int i, n;
- fields = pdf_dict_getp(ctx, pdf_trailer(ctx, doc), "Root/AcroForm/Fields");
- n = pdf_array_len(ctx, fields);
- for (i = 0; i < n; ++i)
- showfield(ctx, pdf_array_get(ctx, fields, i));
- }
- #define SEP ".[]/"
- static int isnumber(char *s)
- {
- if (*s == '-')
- s++;
- while (*s)
- {
- if (*s < '0' || *s > '9')
- return 0;
- ++s;
- }
- return 1;
- }
- static void showpath(fz_context *ctx, char *path, pdf_obj *obj)
- {
- if (path && path[0])
- {
- char *part = fz_strsep(&path, SEP);
- if (part && part[0])
- {
- if (!strcmp(part, "*"))
- {
- int i, n;
- char buf[1000];
- if (pdf_is_array(ctx, obj))
- {
- n = pdf_array_len(ctx, obj);
- for (i = 0; i < n; ++i)
- {
- if (path)
- {
- fz_strlcpy(buf, path, sizeof buf);
- showpath(ctx, buf, pdf_array_get(ctx, obj, i));
- }
- else
- showpath(ctx, NULL, pdf_array_get(ctx, obj, i));
- }
- }
- else if (pdf_is_dict(ctx, obj))
- {
- n = pdf_dict_len(ctx, obj);
- for (i = 0; i < n; ++i)
- {
- if (path)
- {
- fz_strlcpy(buf, path, sizeof buf);
- showpath(ctx, buf, pdf_dict_get_val(ctx, obj, i));
- }
- else
- showpath(ctx, NULL, pdf_dict_get_val(ctx, obj, i));
- }
- }
- else
- {
- fz_write_string(ctx, out, "null\n");
- }
- }
- else if (isnumber(part) && pdf_is_array(ctx, obj))
- {
- int num = atoi(part);
- num = num < 0 ? pdf_array_len(ctx, obj) + num : num - 1;
- showpath(ctx, path, pdf_array_get(ctx, obj, num));
- }
- else
- showpath(ctx, path, pdf_dict_gets(ctx, obj, part));
- }
- else
- fz_write_string(ctx, out, "null\n");
- }
- else
- {
- if (pdf_is_indirect(ctx, obj))
- showobject(ctx, obj);
- else
- {
- pdf_print_obj(ctx, out, obj, do_tight, 0);
- fz_write_string(ctx, out, "\n");
- }
- }
- }
- static void showpathpage(fz_context *ctx, char *path)
- {
- if (path)
- {
- char *part = fz_strsep(&path, SEP);
- if (part && part[0])
- {
- if (!strcmp(part, "*"))
- {
- int i, n;
- char buf[1000];
- n = pdf_count_pages(ctx, doc);
- for (i = 0; i < n; ++i)
- {
- if (path)
- {
- fz_strlcpy(buf, path, sizeof buf);
- showpath(ctx, buf, pdf_lookup_page_obj(ctx, doc, i));
- }
- else
- showpath(ctx, NULL, pdf_lookup_page_obj(ctx, doc, i));
- }
- }
- else if (isnumber(part))
- {
- int num = atoi(part);
- num = num < 0 ? pdf_count_pages(ctx, doc) + num : num - 1;
- showpath(ctx, path, pdf_lookup_page_obj(ctx, doc, num));
- }
- else
- fz_write_string(ctx, out, "null\n");
- }
- else
- fz_write_string(ctx, out, "null\n");
- }
- else
- {
- showpages(ctx);
- }
- }
- static void showpathroot(fz_context *ctx, char *path)
- {
- char buf[2000], *list = buf, *part;
- fz_strlcpy(buf, path, sizeof buf);
- part = fz_strsep(&list, SEP);
- if (part && part[0])
- {
- if (!strcmp(part, "trailer"))
- showpath(ctx, list, pdf_trailer(ctx, doc));
- else if (!strcmp(part, "pages"))
- showpathpage(ctx, list);
- else if (isnumber(part))
- {
- pdf_obj *obj;
- int num = atoi(part);
- num = num < 0 ? pdf_xref_len(ctx, doc) + num : num;
- obj = pdf_new_indirect(ctx, doc, num, 0);
- fz_try(ctx)
- showpath(ctx, list, obj);
- fz_always(ctx)
- pdf_drop_obj(ctx, obj);
- fz_catch(ctx)
- ;
- }
- else
- showpath(ctx, list, pdf_dict_gets(ctx, pdf_trailer(ctx, doc), part));
- }
- else
- fz_write_string(ctx, out, "null\n");
- }
- static void show(fz_context *ctx, char *sel)
- {
- if (!strcmp(sel, "trailer"))
- showtrailer(ctx);
- else if (!strcmp(sel, "xref"))
- showxref(ctx);
- else if (!strcmp(sel, "pages"))
- showpages(ctx);
- else if (!strcmp(sel, "grep"))
- showgrep(ctx);
- else if (!strcmp(sel, "outline"))
- showoutline(ctx);
- else if (!strcmp(sel, "js"))
- showjs(ctx);
- else if (!strcmp(sel, "form"))
- showform(ctx);
- else
- showpathroot(ctx, sel);
- }
- int pdfshow_main(int argc, char **argv)
- {
- char *password = NULL; /* don't throw errors if encrypted */
- char *filename = NULL;
- char *output = NULL;
- int c;
- int errored = 0;
- fz_context *ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
- if (!ctx)
- {
- fprintf(stderr, "cannot initialise context\n");
- exit(1);
- }
- while ((c = fz_getopt(argc, argv, "p:o:begrL")) != -1)
- {
- switch (c)
- {
- case 'p': password = fz_optarg; break;
- case 'o': output = fz_optarg; break;
- case 'b': showbinary = 1; break;
- case 'e': showdecode = 0; break;
- case 'g': do_tight = 1; break;
- case 'r': do_repair = 1; break;
- case 'L': do_label = 1; break;
- default: return usage();
- }
- }
- if (fz_optind == argc)
- return usage();
- filename = argv[fz_optind++];
- if (output)
- out = fz_new_output_with_path(ctx, output, 0);
- else
- out = fz_stdout(ctx);
- fz_var(doc);
- fz_var(labels);
- fz_try(ctx)
- {
- doc = pdf_open_document(ctx, filename);
- if (pdf_needs_password(ctx, doc))
- if (!pdf_authenticate_password(ctx, doc, password))
- fz_warn(ctx, "cannot authenticate password: %s", filename);
- if (do_repair)
- {
- fz_try(ctx)
- {
- pdf_repair_xref(ctx, doc);
- }
- fz_catch(ctx)
- {
- fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
- fz_rethrow_if(ctx, FZ_ERROR_SYSTEM);
- fz_rethrow_if(ctx, FZ_ERROR_REPAIRED);
- fz_report_error(ctx);
- }
- }
- if (do_label)
- labels = pdf_load_object_labels(ctx, doc);
- if (fz_optind == argc)
- showtrailer(ctx);
- while (fz_optind < argc)
- show(ctx, argv[fz_optind++]);
- }
- fz_always(ctx)
- {
- fz_close_output(ctx, out);
- fz_drop_output(ctx, out);
- pdf_drop_object_labels(ctx, labels);
- pdf_drop_document(ctx, doc);
- }
- fz_catch(ctx)
- {
- fz_report_error(ctx);
- errored = 1;
- }
- fz_drop_context(ctx);
- return errored;
- }
|