From c4e78d06ca6aee5b6e9973c8cae6ba4749d93e1f Mon Sep 17 00:00:00 2001 From: Krzysztof Kowalczyk Date: Tue, 28 Feb 2023 13:29:07 -0500 Subject: [PATCH] update mupdf --- mupdf/Makerules | 12 +++ mupdf/include/mupdf/fitz/context.h | 20 ----- mupdf/include/mupdf/pdf/document.h | 2 +- mupdf/include/mupdf/pdf/page.h | 15 ++-- mupdf/platform/java/jni/pdfobject.c | 4 +- mupdf/source/fitz/error.c | 16 ---- mupdf/source/fitz/filter-dct.c | 6 ++ mupdf/source/fitz/load-jpeg.c | 6 ++ mupdf/source/fitz/outline.c | 6 +- mupdf/source/fitz/stext-device.c | 72 ++++++++++++++++++ mupdf/source/fitz/stext-search.c | 84 ++++++++++++++++++++- mupdf/source/pdf/pdf-object.c | 6 +- mupdf/source/pdf/pdf-page.c | 63 +++++++++++----- mupdf/source/pdf/pdf-repair.c | 2 + mupdf/source/pdf/pdf-xref.c | 2 +- mupdf/source/tools/murun.c | 6 ++ mupdf/source/tools/pdfmerge.c | 6 -- src/EngineMupdf.cpp | 112 ++++++---------------------- 18 files changed, 268 insertions(+), 172 deletions(-) diff --git a/mupdf/Makerules b/mupdf/Makerules index 7380b3dc65d0..3d255e980441 100644 --- a/mupdf/Makerules +++ b/mupdf/Makerules @@ -264,6 +264,18 @@ ifeq "$(OS)" "wasm" HAVE_LIBCRYPTO=no endif +ifeq "$(OS)" "wasm-mt" + build_prefix += wasm-mt/ + CC = emcc + CXX = em++ + AR = emar + HAVE_GLUT=no + HAVE_X11=no + HAVE_OBJCOPY=no + HAVE_LIBCRYPTO=no + CFLAGS += -pthread +endif + ifeq "$(OS)" "mingw32-cross" build_prefix += $(OS)/ SO := dll diff --git a/mupdf/include/mupdf/fitz/context.h b/mupdf/include/mupdf/fitz/context.h index 6bc77245ca05..a43a493391eb 100644 --- a/mupdf/include/mupdf/fitz/context.h +++ b/mupdf/include/mupdf/fitz/context.h @@ -819,24 +819,4 @@ fz_drop_imp16(fz_context *ctx, void *p, int16_t *refs) return 0; } - -#if WASM_SKIP_TRY_CATCH - -/** - Exception macro definitions for WASM_SKIP_TRY_CATCH. In this mode, we - throw JS exceptions directly, and we skip fz_catch and fz_always. - Useful for producing cleaner stack traces when debugging. - Should *never* be used in production. -*/ -#undef fz_var -#define fz_var(var) (void)(var) -#undef fz_try -#define fz_try(ctx) do -#undef fz_always -#define fz_always(ctx) while (0); if (0) do -#undef fz_catch -#define fz_catch(ctx) while (0); if (0) - -#endif - #endif diff --git a/mupdf/include/mupdf/pdf/document.h b/mupdf/include/mupdf/pdf/document.h index 14aa13c25b70..0e3f23048079 100644 --- a/mupdf/include/mupdf/pdf/document.h +++ b/mupdf/include/mupdf/pdf/document.h @@ -427,10 +427,10 @@ struct pdf_document int last_xref_was_old_style; int has_linearization_object; - int page_map_nesting; int map_page_count; pdf_rev_page_map *rev_page_map; int *fwd_page_map; + int page_tree_broken; int repair_attempted; int repair_in_progress; diff --git a/mupdf/include/mupdf/pdf/page.h b/mupdf/include/mupdf/pdf/page.h index 1289cbdd42d1..843b7e8aede6 100644 --- a/mupdf/include/mupdf/pdf/page.h +++ b/mupdf/include/mupdf/pdf/page.h @@ -33,23 +33,22 @@ pdf_obj *pdf_lookup_page_obj(fz_context *ctx, pdf_document *doc, int needle); /* Cache the page tree for fast forward/reverse page lookups. - It is the caller's responsibility to ensure that nothing alters - the page tree between this call and the matching pdf_drop_page_tree - or undefined behaviour may occur. - - Any successful call to pdf_load_page_tree MUST be matched with - a call to pdf_drop_page_tree. + No longer required. This is a No Op, now as page tree + maps are loaded automatically 'just in time'. */ void pdf_load_page_tree(fz_context *ctx, pdf_document *doc); /* Discard the page tree maps. - Calls to this should exactly match successful calls to - pdf_load_page_tree. + No longer required. This is a No Op, now as page tree + maps are discarded automatically 'just in time'. */ void pdf_drop_page_tree(fz_context *ctx, pdf_document *doc); +void pdf_drop_page_tree_internal(fz_context *ctx, pdf_document *doc); + + /* Find the page number of a named destination. diff --git a/mupdf/platform/java/jni/pdfobject.c b/mupdf/platform/java/jni/pdfobject.c index ea207098a980..97eea3940025 100644 --- a/mupdf/platform/java/jni/pdfobject.c +++ b/mupdf/platform/java/jni/pdfobject.c @@ -1239,10 +1239,8 @@ FUN(PDFObject_equals)(JNIEnv *env, jobject self, jobject jother) pdf_obj *other = NULL; int result = 0; - if (!ctx || !obj) return JNI_FALSE; + if (!ctx) return JNI_FALSE; - if (jother == NULL) - return JNI_FALSE; if (!(*env)->IsInstanceOf(env, jother, cls_PDFObject)) return JNI_FALSE; diff --git a/mupdf/source/fitz/error.c b/mupdf/source/fitz/error.c index 3a8d4f4c44bf..e7795df6cef9 100644 --- a/mupdf/source/fitz/error.c +++ b/mupdf/source/fitz/error.c @@ -35,10 +35,6 @@ #endif #endif -#if WASM_SKIP_TRY_CATCH -#include "emscripten.h" -#endif - #ifdef __ANDROID__ #define USE_ANDROID_LOG #include @@ -178,8 +174,6 @@ fz_error_cb *fz_error_callback(fz_context *ctx, void **user) FZ_NORETURN static void throw(fz_context *ctx, int code) { -#if !WASM_SKIP_TRY_CATCH - if (ctx->error.top > ctx->error.stack_base) { ctx->error.top->state += 2; @@ -204,16 +198,6 @@ FZ_NORETURN static void throw(fz_context *ctx, int code) *p = 0; exit(EXIT_FAILURE); } - -#else - EM_ASM({ - let message = UTF8ToString($0); - console.error("mupdf:", message); - throw new libmupdf.MupdfError(message); - }, ctx->error.message); - // Unreachable - exit(EXIT_FAILURE); -#endif } fz_jmp_buf *fz_push_try(fz_context *ctx) diff --git a/mupdf/source/fitz/filter-dct.c b/mupdf/source/fitz/filter-dct.c index e229c1c065a2..edc746f34889 100755 --- a/mupdf/source/fitz/filter-dct.c +++ b/mupdf/source/fitz/filter-dct.c @@ -118,6 +118,11 @@ static void error_exit_dct(j_common_ptr cinfo) fz_throw(ctx, FZ_ERROR_GENERIC, "jpeg error: %s", msg); } +static void output_message_dct(j_common_ptr cinfo) +{ + /* swallow message */ +} + static void init_source_dct(j_decompress_ptr cinfo) { /* nothing to do */ @@ -369,6 +374,7 @@ fz_open_dctd(fz_context *ctx, fz_stream *chain, int color_transform, int l2facto cinfo->src = NULL; cinfo->err = &state->errmgr; jpeg_std_error(cinfo->err); + cinfo->err->output_message = output_message_dct; cinfo->err->error_exit = error_exit_dct; return fz_new_stream(ctx, state, next_dctd, close_dctd); diff --git a/mupdf/source/fitz/load-jpeg.c b/mupdf/source/fitz/load-jpeg.c index b9eb509e922e..20a6f2d17e49 100644 --- a/mupdf/source/fitz/load-jpeg.c +++ b/mupdf/source/fitz/load-jpeg.c @@ -89,6 +89,11 @@ fz_jpg_mem_term(j_common_ptr cinfo) #endif /* SHARE_JPEG */ +static void output_message(j_common_ptr cinfo) +{ + /* swallow message */ +} + static void error_exit(j_common_ptr cinfo) { char msg[JMSG_LENGTH_MAX]; @@ -374,6 +379,7 @@ fz_load_jpeg(fz_context *ctx, const unsigned char *rbuf, size_t rlen) cinfo.mem = NULL; cinfo.global_state = 0; cinfo.err = jpeg_std_error(&err); + err.output_message = output_message; err.error_exit = error_exit; cinfo.client_data = NULL; diff --git a/mupdf/source/fitz/outline.c b/mupdf/source/fitz/outline.c index 6c5d60d9ad17..2ee1a00e1860 100644 --- a/mupdf/source/fitz/outline.c +++ b/mupdf/source/fitz/outline.c @@ -106,14 +106,17 @@ load_outline_sub(fz_context *ctx, fz_outline_iterator *iter, fz_outline **tail, node->refs = 1; node->title = *t; node->uri = *u; + node->page.chapter = -1; + node->page.page = -1; *t = NULL; *u = NULL; - node->page = fz_resolve_link(ctx, iter->doc, node->uri, &node->x, &node->y); *tail = node; tail = &node->next; onode = node; node = NULL; + onode->page = fz_resolve_link(ctx, iter->doc, onode->uri, &onode->x, &onode->y); + res = fz_outline_iterator_down(ctx, iter); if (res == 0) load_outline_sub(ctx, iter, &onode->down, t, u); @@ -140,6 +143,7 @@ fz_load_outline_from_iterator(fz_context *ctx, fz_outline_iterator *iter) fz_drop_outline_iterator(ctx, iter); fz_catch(ctx) { + fz_drop_outline(ctx, head); fz_free(ctx, title); fz_free(ctx, uri); fz_rethrow(ctx); diff --git a/mupdf/source/fitz/stext-device.c b/mupdf/source/fitz/stext-device.c index 09d1738ec24f..f719d7857c37 100644 --- a/mupdf/source/fitz/stext-device.c +++ b/mupdf/source/fitz/stext-device.c @@ -319,6 +319,59 @@ vec_dot(const fz_point *a, const fz_point *b) return a->x * b->x + a->y * b->y; } +static void +prepend_line_if_possible(fz_context *ctx, fz_stext_block *cur_block, fz_point q) +{ + fz_stext_line *cur_line; + fz_stext_line *line; + fz_point ndir; + float size; + fz_point p; + fz_point delta; + float spacing; + + if (cur_block == NULL || cur_block->type != FZ_STEXT_BLOCK_TEXT) + return; + + cur_line = cur_block->u.t.last_line; + if (cur_line == NULL) + return; + + line = cur_line->prev; + if (line == NULL) + return; + + if (line->wmode != cur_line->wmode) + return; + + ndir = cur_line->dir; + size = cur_line->last_char->size; + p = line->first_char->origin; + delta.x = p.x - q.x; + delta.y = p.y - q.y; + + spacing = ndir.x * delta.x + ndir.y * delta.y; + + if (fabsf(spacing) >= size * SPACE_MAX_DIST) + return; + + /* cur_line plausibly finishes at the start of line. */ + /* Move all the chars from cur_line onto the start of line */ + cur_line->last_char->next = line->first_char; + line->first_char = cur_line->first_char; + cur_line->first_char = NULL; + cur_line->last_char = NULL; + + /* Merge the bboxes */ + line->bbox = fz_union_rect(line->bbox, cur_line->bbox); + + /* Unlink cur_line from the block. */ + cur_block->u.t.last_line = cur_block->u.t.last_line->prev; + cur_block->u.t.last_line->next = NULL; + + /* Can't bin the line storage as it's from a pool. */ +} + static void fz_add_stext_char_imp(fz_context *ctx, fz_stext_device *dev, fz_font *font, int c, int glyph, fz_matrix trm, float adv, int wmode, int force_new_line) { @@ -497,6 +550,14 @@ fz_add_stext_char_imp(fz_context *ctx, fz_stext_device *dev, fz_font *font, int new_line = 0; } + if (new_line) + { + /* We are about to start a new line. This means we've finished with this + * one. Can this be prepended to a previous line in this block? */ + /* dev->pen records the previous stopping point - so where cur_line ends. */ + prepend_line_if_possible(ctx, cur_block, dev->pen); + } + /* Start a new line */ if (new_line || !cur_line || force_new_line) { @@ -516,6 +577,15 @@ fz_add_stext_char_imp(fz_context *ctx, fz_stext_device *dev, fz_font *font, int dev->trm = trm; } +static void +flush_text(fz_context *ctx, fz_stext_device *dev) +{ + fz_stext_page *page = dev->page; + + /* Find current position to enter new text. */ + prepend_line_if_possible(ctx, page->last_block, dev->pen); +} + static void fz_add_stext_char(fz_context *ctx, fz_stext_device *dev, fz_font *font, int c, int glyph, fz_matrix trm, float adv, int wmode, int force_new_line) { @@ -794,6 +864,8 @@ fz_stext_close_device(fz_context *ctx, fz_device *dev) fz_stext_line *line; fz_stext_char *ch; + flush_text(ctx, tdev); + for (block = page->first_block; block; block = block->next) { if (block->type != FZ_STEXT_BLOCK_TEXT) diff --git a/mupdf/source/fitz/stext-search.c b/mupdf/source/fitz/stext-search.c index 44b745ae1b3f..557a0e1472e5 100644 --- a/mupdf/source/fitz/stext-search.c +++ b/mupdf/source/fitz/stext-search.c @@ -21,6 +21,7 @@ // CA 94945, U.S.A., +1(415)492-9861, for further information. #include "mupdf/fitz.h" +#include "mupdf/ucdn.h" #include #include @@ -56,11 +57,45 @@ static int line_length(fz_stext_line *line) return n; } +static int +direction_from_bidi_class(int bidiclass, int curdir) +{ + switch (bidiclass) + { + /* strong */ + case UCDN_BIDI_CLASS_L: return 1; + case UCDN_BIDI_CLASS_R: return -1; + case UCDN_BIDI_CLASS_AL: return -1; + + /* weak */ + case UCDN_BIDI_CLASS_EN: + case UCDN_BIDI_CLASS_ES: + case UCDN_BIDI_CLASS_ET: + case UCDN_BIDI_CLASS_AN: + case UCDN_BIDI_CLASS_CS: + case UCDN_BIDI_CLASS_NSM: + case UCDN_BIDI_CLASS_BN: + return curdir; + + /* neutral */ + case UCDN_BIDI_CLASS_B: + case UCDN_BIDI_CLASS_S: + case UCDN_BIDI_CLASS_WS: + case UCDN_BIDI_CLASS_ON: + return curdir; + + /* embedding, override, pop ... we don't support them */ + default: + return 0; + } +} + static int find_closest_in_line(fz_stext_line *line, int idx, fz_point p) { fz_stext_char *ch; float closest_dist = 1e30f; int closest_idx = idx; + int dirn = 0; if (line->dir.x > line->dir.y) { @@ -82,14 +117,29 @@ static int find_closest_in_line(fz_stext_line *line, int idx, fz_point p) float mid_x = (ch->quad.ul.x + ch->quad.ur.x + ch->quad.ll.x + ch->quad.lr.x) / 4; float mid_y = (ch->quad.ul.y + ch->quad.ur.y + ch->quad.ll.y + ch->quad.lr.y) / 4; float this_dist = dist2(p.x - mid_x, p.y - mid_y); + + dirn = direction_from_bidi_class(ucdn_get_bidi_class(ch->c), dirn); + if (this_dist < closest_dist) { closest_dist = this_dist; + if (dirn == -1) + { + /* R2L */ + if (line->dir.x > line->dir.y) + closest_idx = (p.x < mid_x) ? idx+1 : idx; + else + closest_idx = (p.y < mid_y) ? idx+1 : idx; + } + else + { + /* Neutral or L2R */ if (line->dir.x > line->dir.y) closest_idx = (p.x < mid_x) ? idx : idx+1; else closest_idx = (p.y < mid_y) ? idx : idx+1; } + } ++idx; } return closest_idx; @@ -287,14 +337,40 @@ static void on_highlight_char(fz_context *ctx, void *arg, fz_stext_line *line, f if (hits->len > 0) { fz_quad *end = &hits->box[hits->len-1]; - if (hdist(&line->dir, &end->lr, &ch->quad.ll) < hfuzz - && vdist(&line->dir, &end->lr, &ch->quad.ll) < vfuzz - && hdist(&line->dir, &end->ur, &ch->quad.ul) < hfuzz - && vdist(&line->dir, &end->ur, &ch->quad.ul) < vfuzz) + float llh = hdist(&line->dir, &end->lr, &ch->quad.ll); + float llv = vdist(&line->dir, &end->lr, &ch->quad.ll); + float ulh = hdist(&line->dir, &end->ur, &ch->quad.ul); + float ulv = vdist(&line->dir, &end->ur, &ch->quad.ul); + float lrh = hdist(&line->dir, &end->ll, &ch->quad.lr); + float lrv = vdist(&line->dir, &end->ll, &ch->quad.lr); + float urh = hdist(&line->dir, &end->ul, &ch->quad.ur); + float urv = vdist(&line->dir, &end->ul, &ch->quad.ur); + + if (lrh + lrv + urh + urv < llh + llv + ulh + ulv) + { + /* Merge to the right, if at all. */ + if (lrh < hfuzz + && lrv < vfuzz + && urh < hfuzz + && urv < vfuzz) + { + end->ul = ch->quad.ul; + end->ll = ch->quad.ll; + return; + } + } + else + { + /* Merge to the left, if at all */ + if (llh < hfuzz + && llv < vfuzz + && ulh < hfuzz + && ulv < vfuzz) { end->ur = ch->quad.ur; end->lr = ch->quad.lr; return; + } } } diff --git a/mupdf/source/pdf/pdf-object.c b/mupdf/source/pdf/pdf-object.c index 0e0ba22b1c3a..638e77624c6f 100755 --- a/mupdf/source/pdf/pdf-object.c +++ b/mupdf/source/pdf/pdf-object.c @@ -1482,8 +1482,8 @@ static void prepare_object_for_alteration(fz_context *ctx, pdf_obj *obj, pdf_obj return; } - /* Do we need to drop the reverse page map? */ - if (doc && doc->rev_page_map) + /* Do we need to drop the page maps? */ + if (doc && (doc->rev_page_map || doc->fwd_page_map)) { if (doc->non_structural_change) { @@ -1500,7 +1500,7 @@ static void prepare_object_for_alteration(fz_context *ctx, pdf_obj *obj, pdf_obj * never do structural changes in local_xrefs. */ } else - pdf_drop_page_tree(ctx, doc); + pdf_drop_page_tree_internal(ctx, doc); } if (val) diff --git a/mupdf/source/pdf/pdf-page.c b/mupdf/source/pdf/pdf-page.c index 7fbf666815f4..41e8ed89500d 100755 --- a/mupdf/source/pdf/pdf-page.c +++ b/mupdf/source/pdf/pdf-page.c @@ -85,15 +85,14 @@ cmp_rev_page_map(const void *va, const void *vb) void pdf_load_page_tree(fz_context *ctx, pdf_document *doc) { - int refs; - - /* Atomically increment the number of times we've been told to load. */ - fz_lock(ctx, FZ_LOCK_ALLOC); - refs = doc->page_map_nesting++; - fz_unlock(ctx, FZ_LOCK_ALLOC); + /* Noop now. */ +} - /* If we were already non-zero, then we're already loaded. */ - if (refs != 0) +static void +pdf_load_page_tree_internal(fz_context *ctx, pdf_document *doc) +{ + /* Check we're not already loaded. */ + if (doc->fwd_page_map != NULL) return; /* At this point we're trusting that only 1 thread should be doing @@ -112,9 +111,6 @@ pdf_load_page_tree(fz_context *ctx, pdf_document *doc) doc->rev_page_map = NULL; fz_free(ctx, doc->fwd_page_map); doc->fwd_page_map = NULL; - fz_lock(ctx, FZ_LOCK_ALLOC); - doc->page_map_nesting--; - fz_unlock(ctx, FZ_LOCK_ALLOC); fz_rethrow(ctx); } } @@ -122,14 +118,12 @@ pdf_load_page_tree(fz_context *ctx, pdf_document *doc) void pdf_drop_page_tree(fz_context *ctx, pdf_document *doc) { - int refs; - - fz_lock(ctx, FZ_LOCK_ALLOC); - refs = --doc->page_map_nesting; - fz_unlock(ctx, FZ_LOCK_ALLOC); - if (refs != 0) - return; + /* Historical entry point. Now does nothing. We drop 'just in time'. */ +} +void +pdf_drop_page_tree_internal(fz_context *ctx, pdf_document *doc) +{ /* At this point we're trusting that only 1 thread should be doing * stuff that hits the document at a time. */ fz_free(ctx, doc->rev_page_map); @@ -237,11 +231,29 @@ pdf_lookup_page_loc(fz_context *ctx, pdf_document *doc, int needle, pdf_obj **pa pdf_obj * pdf_lookup_page_obj(fz_context *ctx, pdf_document *doc, int needle) { - if (doc->fwd_page_map) + if (doc->fwd_page_map == NULL && !doc->page_tree_broken) { + fz_try(ctx) + pdf_load_page_tree_internal(ctx, doc); + fz_catch(ctx) + { + doc->page_tree_broken = 1; + fz_warn(ctx, "Page tree load failed. Falling back to slow lookup"); + } + } + + /* If we have a fwd_page_map then look it up. If the index in that map is 0 then + * maybe it was direct page object rather than a reference. This is illegal, but + * we've seen it in tests_private/pdf/sumatra/page_no_indirect_reference.pdf so + * we might as well cope. */ + if (doc->fwd_page_map && doc->fwd_page_map[needle] != 0) + { + pdf_obj *pageobj; if (needle < 0 || needle >= doc->map_page_count) fz_throw(ctx, FZ_ERROR_GENERIC, "cannot find page %d in page tree", needle+1); - return pdf_load_object(ctx, doc, doc->fwd_page_map[needle]); + pageobj = pdf_load_object(ctx, doc, doc->fwd_page_map[needle]); + pdf_drop_obj(ctx, pageobj); + return pageobj; } else return pdf_lookup_page_loc(ctx, doc, needle, NULL, NULL); } @@ -327,6 +339,17 @@ pdf_lookup_page_number_fast(fz_context *ctx, pdf_document *doc, int needle) int pdf_lookup_page_number(fz_context *ctx, pdf_document *doc, pdf_obj *page) { + if (doc->rev_page_map == NULL && !doc->page_tree_broken) + { + fz_try(ctx) + pdf_load_page_tree_internal(ctx, doc); + fz_catch(ctx) + { + doc->page_tree_broken = 1; + fz_warn(ctx, "Page tree load failed. Falling back to slow lookup."); + } + } + if (doc->rev_page_map) return pdf_lookup_page_number_fast(ctx, doc, pdf_to_num(ctx, page)); else diff --git a/mupdf/source/pdf/pdf-repair.c b/mupdf/source/pdf/pdf-repair.c index 9ec3e7aade78..3146d11787ed 100644 --- a/mupdf/source/pdf/pdf-repair.c +++ b/mupdf/source/pdf/pdf-repair.c @@ -367,6 +367,8 @@ pdf_repair_xref(fz_context *ctx, pdf_document *doc) doc->repair_attempted = 1; doc->repair_in_progress = 1; + pdf_drop_page_tree_internal(ctx, doc); + doc->page_tree_broken = 0; pdf_forget_xref(ctx, doc); fz_seek(ctx, doc->file, 0, 0); diff --git a/mupdf/source/pdf/pdf-xref.c b/mupdf/source/pdf/pdf-xref.c index 47ba5fd5b48d..b8462c342f01 100644 --- a/mupdf/source/pdf/pdf-xref.c +++ b/mupdf/source/pdf/pdf-xref.c @@ -1932,7 +1932,7 @@ pdf_drop_document_imp(fz_context *ctx, pdf_document *doc) fz_free(ctx, doc->orphans); - fz_free(ctx, doc->rev_page_map); + pdf_drop_page_tree_internal(ctx, doc); fz_defer_reap_end(ctx); diff --git a/mupdf/source/tools/murun.c b/mupdf/source/tools/murun.c index c179fb253ada..430c5d65c42b 100644 --- a/mupdf/source/tools/murun.c +++ b/mupdf/source/tools/murun.c @@ -3546,8 +3546,14 @@ static void ffi_Document_loadOutline(js_State *J) fz_catch(ctx) rethrow(J); + if (js_try(J)) { + fz_drop_outline(ctx, outline); + js_throw(J); + } + to_outline(J, outline); + js_endtry(J); fz_drop_outline(ctx, outline); } diff --git a/mupdf/source/tools/pdfmerge.c b/mupdf/source/tools/pdfmerge.c index 60b74f229e2f..9ddcfa9fe230 100644 --- a/mupdf/source/tools/pdfmerge.c +++ b/mupdf/source/tools/pdfmerge.c @@ -230,19 +230,15 @@ static void merge_range(fz_context *ctx, const char *range) fz_outline_iterator *it_src = NULL; fz_outline_iterator *it_dst = NULL; int pages_merged = 0; - int page_tree_loaded = 0; count = pdf_count_pages(ctx, doc_src); graft_map = pdf_new_graft_map(ctx, doc_des); fz_var(it_src); fz_var(it_dst); - fz_var(page_tree_loaded); fz_try(ctx) { - pdf_load_page_tree(ctx, doc_src); - page_tree_loaded = 1; r = range; while ((r = fz_parse_page_range(ctx, r, &start, &end, count))) { @@ -283,8 +279,6 @@ static void merge_range(fz_context *ctx, const char *range) fz_drop_outline_iterator(ctx, it_src); fz_drop_outline_iterator(ctx, it_dst); pdf_drop_graft_map(ctx, graft_map); - if (page_tree_loaded) - pdf_drop_page_tree(ctx, doc_src); } fz_catch(ctx) { diff --git a/src/EngineMupdf.cpp b/src/EngineMupdf.cpp index 30a7bb947c96..7c75439f3cc5 100644 --- a/src/EngineMupdf.cpp +++ b/src/EngineMupdf.cpp @@ -2033,97 +2033,31 @@ bool EngineMupdf::FinishLoading() { ScopedCritSec scope(ctxAccess); - bool loadPageTreeFailed = false; - - fz_try(ctx) { - pdf_load_page_tree(ctx, pdfdoc); - } - fz_catch(ctx) { - fz_warn(ctx, "pdf_load_page_tree() failed"); - loadPageTreeFailed = true; - } - - int nPages = pdfdoc->map_page_count; - if (loadPageTreeFailed) { - nPages = pageCount; - } else { - if (nPages != pageCount) { - logfa("pdfdoc->map_page_count: %d, pageCount: %d\n", pdfdoc->map_page_count, pageCount); - ReportIf(nPages != pageCount); - fz_warn(ctx, "mismatch between fz_count_pages() and doc->rev_page_count"); - return false; + for (int pageNo = 0; pageNo < pageCount; pageNo++) { + pdf_obj* pageref = nullptr; + fz_rect mbox{}; + fz_matrix page_ctm{}; + fz_var(pageref); + fz_var(mbox); + fz_try(ctx) { + // note: don't pdf_drop_obj() this + pageref = pdf_lookup_page_obj(ctx, pdfdoc, pageNo); + pdf_page_obj_transform(ctx, pageref, &mbox, &page_ctm); + mbox = fz_transform_rect(mbox, page_ctm); } - } - - if (!loadPageTreeFailed) { - // this does the job of pdf_bound_page but without doing pdf_load_page() - pdf_rev_page_map* map = pdfdoc->rev_page_map; - for (int i = 0; i < nPages && !loadPageTreeFailed; i++) { - int pageNo = map[i].page; - if (pageNo >= nPages) { - // corrupted file - loadPageTreeFailed = true; - continue; - } - int objNo = map[i].object; - fz_rect mbox{}; - fz_matrix page_ctm{}; - pdf_obj* pageref = nullptr; - fz_var(pageref); - fz_var(mbox); - fz_try(ctx) { - pageref = pdf_load_object(ctx, pdfdoc, objNo); - pdf_page_obj_transform(ctx, pageref, &mbox, &page_ctm); - mbox = fz_transform_rect(mbox, page_ctm); - pdf_drop_obj(ctx, pageref); - } - fz_catch(ctx) { - loadPageTreeFailed = true; - mbox = {}; - } - if (fz_is_empty_rect(mbox)) { - logfa("cannot find page size for page %d", i); - mbox.x0 = 0; - mbox.y0 = 0; - mbox.x1 = 612; - mbox.y1 = 792; - loadPageTreeFailed = true; - } - FzPageInfo* pageInfo = pages[pageNo]; - pageInfo->mediabox = ToRectF(mbox); - pageInfo->pageNo = pageNo + 1; - } - } - - if (loadPageTreeFailed) { - for (int pageNo = 0; pageNo < nPages; pageNo++) { - FzPageInfo* pageInfo = pages[pageNo]; - pageInfo->pageNo = pageNo + 1; - fz_rect mbox{}; - pdf_page* page = nullptr; - fz_var(page); - fz_var(mbox); - fz_try(ctx) { - page = pdf_load_page(ctx, pdfdoc, pageNo); - pageInfo->page = (fz_page*)page; - mbox = pdf_bound_page(ctx, page); - } - fz_catch(ctx) { - mbox = {}; - } - - if (fz_is_empty_rect(mbox)) { - logfa("cannot find page size (2) for page %d", pageNo); - mbox.x0 = 0; - mbox.y0 = 0; - mbox.x1 = 612; - mbox.y1 = 792; - } - pageInfo->mediabox = ToRectF(mbox); + fz_catch(ctx) { + mbox = {}; } - } - if (loadPageTreeFailed) { - logfa("Failed to load page tree for '%s'\n", FilePath()); + if (fz_is_empty_rect(mbox)) { + logfa("cannot find page size for page %d", pageNo); + mbox.x0 = 0; + mbox.y0 = 0; + mbox.x1 = 612; + mbox.y1 = 792; + } + FzPageInfo* pageInfo = pages[pageNo]; + pageInfo->mediabox = ToRectF(mbox); + pageInfo->pageNo = pageNo + 1; } fz_try(ctx) {