From 0bfa2ce884eed8bef83fb23cf2e25dae81a2207e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20B=C3=BCnzli?= Date: Fri, 3 Jan 2014 12:15:09 +0100 Subject: reuse JBIG2Globals Certain optimized documents use a rather large common symbol dictionary for all JBIG2 images. Caching these JBIG2Globals speeds up loading and rendering of such documents. --- source/fitz/filter-jbig2.c | 56 +++++++++++++++++++++++++++++++++------------- source/pdf/pdf-stream.c | 38 ++++++++++++++++++++++++++++--- 2 files changed, 75 insertions(+), 19 deletions(-) (limited to 'source') diff --git a/source/fitz/filter-jbig2.c b/source/fitz/filter-jbig2.c index 2771d070..592f7ab6 100644 --- a/source/fitz/filter-jbig2.c +++ b/source/fitz/filter-jbig2.c @@ -4,15 +4,27 @@ typedef struct fz_jbig2d_s fz_jbig2d; +struct fz_jbig2_globals_s +{ + fz_storable storable; + Jbig2GlobalCtx *gctx; +}; + struct fz_jbig2d_s { fz_stream *chain; Jbig2Ctx *ctx; - Jbig2GlobalCtx *gctx; + fz_jbig2_globals *gctx; Jbig2Image *page; int idx; }; +static void +fz_drop_jbig2_globals(fz_context *ctx, fz_jbig2_globals *globals) +{ + fz_drop_storable(ctx, &globals->storable); +} + static void close_jbig2d(fz_context *ctx, void *state_) { @@ -20,7 +32,7 @@ close_jbig2d(fz_context *ctx, void *state_) if (state->page) jbig2_release_page(state->ctx, state->page); if (state->gctx) - jbig2_global_ctx_free(state->gctx); + fz_drop_jbig2_globals(ctx, state->gctx); jbig2_ctx_free(state->ctx); fz_close(state->chain); fz_free(ctx, state); @@ -81,8 +93,30 @@ error_callback(void *data, const char *msg, Jbig2Severity severity, int32_t seg_ return 0; } +fz_jbig2_globals * +fz_load_jbig2_globals(fz_context *ctx, unsigned char *data, int size) +{ + fz_jbig2_globals *globals = fz_malloc_struct(ctx, fz_jbig2_globals); + + Jbig2Ctx *jctx = jbig2_ctx_new(NULL, JBIG2_OPTIONS_EMBEDDED, NULL, error_callback, ctx); + jbig2_data_in(jctx, data, size); + + FZ_INIT_STORABLE(globals, 1, fz_free_jbig2_globals_imp); + globals->gctx = jbig2_make_global_ctx(jctx); + + return globals; +} + +void +fz_free_jbig2_globals_imp(fz_context *ctx, fz_storable *globals_) +{ + fz_jbig2_globals *globals = (fz_jbig2_globals *)globals_; + jbig2_global_ctx_free(globals->gctx); + fz_free(ctx, globals); +} + fz_stream * -fz_open_jbig2d(fz_stream *chain, fz_buffer *globals) +fz_open_jbig2d(fz_stream *chain, fz_jbig2_globals *globals) { fz_jbig2d *state = NULL; fz_context *ctx = chain->ctx; @@ -93,34 +127,24 @@ fz_open_jbig2d(fz_stream *chain, fz_buffer *globals) { state = fz_malloc_struct(chain->ctx, fz_jbig2d); state->ctx = NULL; - state->gctx = NULL; + state->gctx = globals; state->chain = chain; - state->ctx = jbig2_ctx_new(NULL, JBIG2_OPTIONS_EMBEDDED, NULL, error_callback, ctx); + state->ctx = jbig2_ctx_new(NULL, JBIG2_OPTIONS_EMBEDDED, globals ? globals->gctx : NULL, error_callback, ctx); state->page = NULL; state->idx = 0; - - if (globals) - { - jbig2_data_in(state->ctx, globals->data, globals->len); - state->gctx = jbig2_make_global_ctx(state->ctx); - state->ctx = jbig2_ctx_new(NULL, JBIG2_OPTIONS_EMBEDDED, state->gctx, error_callback, ctx); - } } fz_catch(ctx) { if (state) { - if (state->gctx) - jbig2_global_ctx_free(state->gctx); + fz_drop_jbig2_globals(ctx, state->gctx); if (state->ctx) jbig2_ctx_free(state->ctx); } - fz_drop_buffer(ctx, globals); fz_free(ctx, state); fz_close(chain); fz_rethrow(ctx); } - fz_drop_buffer(ctx, globals); return fz_new_stream(ctx, state, read_jbig2d, close_jbig2d, rebind_jbig2d); } diff --git a/source/pdf/pdf-stream.c b/source/pdf/pdf-stream.c index bf7f64f2..f747a54b 100644 --- a/source/pdf/pdf-stream.c +++ b/source/pdf/pdf-stream.c @@ -46,6 +46,38 @@ pdf_stream_has_crypt(fz_context *ctx, pdf_obj *stm) return 0; } +static fz_jbig2_globals * +pdf_load_jbig2_globals(pdf_document *doc, pdf_obj *dict) +{ + fz_jbig2_globals *globals; + fz_context *ctx = doc->ctx; + fz_buffer *buf = NULL; + + fz_var(buf); + + if ((globals = pdf_find_item(ctx, fz_free_jbig2_globals_imp, dict)) != NULL) + { + return globals; + } + + fz_try(ctx) + { + buf = pdf_load_stream(doc, pdf_to_num(dict), pdf_to_gen(dict)); + globals = fz_load_jbig2_globals(ctx, buf->data, buf->len); + pdf_store_item(ctx, dict, globals, buf->len); + } + fz_always(ctx) + { + fz_drop_buffer(ctx, buf); + } + fz_catch(ctx) + { + fz_rethrow(ctx); + } + + return globals; +} + /* * Create a filter given a name and param dictionary. */ @@ -161,10 +193,10 @@ build_filter(fz_stream *chain, pdf_document *doc, pdf_obj *f, pdf_obj *p, int nu else if (!strcmp(s, "JBIG2Decode")) { - fz_buffer *globals = NULL; + fz_jbig2_globals *globals = NULL; pdf_obj *obj = pdf_dict_gets(p, "JBIG2Globals"); - if (obj) - globals = pdf_load_stream(doc, pdf_to_num(obj), pdf_to_gen(obj)); + if (pdf_is_indirect(obj)) + globals = pdf_load_jbig2_globals(doc, obj); /* fz_open_jbig2d takes possession of globals */ return fz_open_jbig2d(chain, globals); } -- cgit v1.2.3