diff options
author | Robin Watts <Robin.Watts@artifex.com> | 2022-02-07 16:30:23 +0000 |
---|---|---|
committer | Robin Watts <Robin.Watts@artifex.com> | 2022-02-07 19:55:23 +0000 |
commit | d3b0f42bba612880f65d7e1446ca6a8757340bf3 (patch) | |
tree | ed389a4202415a3bbdde3eaaa5aa7392f9a05355 /pdf | |
parent | 3ee68db403b270b0a6534233f0579af55d094d2d (diff) | |
download | ghostpdl-d3b0f42bba612880f65d7e1446ca6a8757340bf3.tar.gz |
PDFI: Optimise transparency setup/teardown.
For various operations (text/shadings/images), we currently find
a bbox (which involves a gsave/grestore pair) regardless of whether
we actually need the bbox.
Here we add some simple code to short circuit this work if transparency
in use. The big win here is with text.
Diffstat (limited to 'pdf')
-rw-r--r-- | pdf/pdf_image.c | 19 | ||||
-rw-r--r-- | pdf/pdf_shading.c | 9 | ||||
-rw-r--r-- | pdf/pdf_trans.c | 30 | ||||
-rw-r--r-- | pdf/pdf_trans.h | 3 |
4 files changed, 46 insertions, 15 deletions
diff --git a/pdf/pdf_image.c b/pdf/pdf_image.c index 19bc85e62..93651c5b1 100644 --- a/pdf/pdf_image.c +++ b/pdf/pdf_image.c @@ -1599,6 +1599,7 @@ pdfi_do_image(pdf_context *ctx, pdf_dict *page_dict, pdf_dict *stream_dict, pdf_ gs_offset_t stream_offset; float save_strokeconstantalpha = 0.0f, save_fillconstantalpha = 0.0f; pdf_string *EODString = NULL; + int trans_required; #if DEBUG_IMAGES dbgmprintf(ctx->memory, "pdfi_do_image BEGIN\n"); @@ -2034,9 +2035,13 @@ pdfi_do_image(pdf_context *ctx, pdf_dict *page_dict, pdf_dict *stream_dict, pdf_ } } - code = pdfi_image_setup_trans(ctx, &trans_state); - if (code < 0) - goto cleanupExit; + trans_required = pdfi_trans_required(ctx); + + if (trans_required) { + code = pdfi_image_setup_trans(ctx, &trans_state); + if (code < 0) + goto cleanupExit; + } /* Render the image */ code = pdfi_render_image(ctx, pim, new_stream, @@ -2047,9 +2052,11 @@ pdfi_do_image(pdf_context *ctx, pdf_dict *page_dict, pdf_dict *stream_dict, pdf_ dmprintf1(ctx->memory, "WARNING: pdfi_do_image: error %d from pdfi_render_image\n", code); } - code1 = pdfi_trans_teardown(ctx, &trans_state); - if (code == 0) - code = code1; + if (trans_required) { + code1 = pdfi_trans_teardown(ctx, &trans_state); + if (code == 0) + code = code1; + } cleanupExit: if (code < 0) diff --git a/pdf/pdf_shading.c b/pdf/pdf_shading.c index 845267784..c4e93e884 100644 --- a/pdf/pdf_shading.c +++ b/pdf/pdf_shading.c @@ -811,7 +811,7 @@ pdfi_shading_setup_trans(pdf_context *ctx, pdfi_trans_state_t *state, pdf_obj *S /* If we didn't get a BBox for the shading, then we need to create one, in order to * pass it to the transparency setup, which (potentially, at least, uses it to set * up a transparency group. - * In the basence of anything better, we take the currnet clip, turn that into a path + * In the absence of anything better, we take the current clip, turn that into a path * and then get the bounding box of that path. Obviously we don't want to disturb the * current path in the graphics state, so we do a gsave/grestore round it. */ @@ -853,6 +853,7 @@ int pdfi_shading(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict) gs_shading_t *psh = NULL; gs_offset_t savedoffset; pdfi_trans_state_t trans_state; + int trans_required; if (pdfi_count_stack(ctx) < 1) return_error(gs_error_stackunderflow); @@ -899,7 +900,9 @@ int pdfi_shading(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict) if (code < 0) goto exit2; - if (ctx->page.has_transparency) { + trans_required = pdfi_trans_required(ctx); + + if (trans_required) { code = pdfi_shading_setup_trans(ctx, &trans_state, Shading); if (code < 0) goto exit2; @@ -911,7 +914,7 @@ int pdfi_shading(pdf_context *ctx, pdf_dict *stream_dict, pdf_dict *page_dict) code = 0; } - if (ctx->page.has_transparency) { + if (trans_required) { code1 = pdfi_trans_teardown(ctx, &trans_state); if (code == 0) code = code1; diff --git a/pdf/pdf_trans.c b/pdf/pdf_trans.c index 608f1679f..46840f0f5 100644 --- a/pdf/pdf_trans.c +++ b/pdf/pdf_trans.c @@ -740,12 +740,33 @@ int pdfi_trans_setup(pdf_context *ctx, pdfi_trans_state_t *state, gs_rect *bbox, return code; } +int pdfi_trans_required(pdf_context *ctx) +{ + gs_blend_mode_t mode; + + if (!ctx->page.has_transparency) + return 0; + + mode = gs_currentblendmode(ctx->pgs); + if ((mode == BLEND_MODE_Normal || mode == BLEND_MODE_Compatible) && + ctx->pgs->fillconstantalpha == 1 && + ctx->pgs->strokeconstantalpha == 1 && + ((pdfi_int_gstate *)ctx->pgs->client_data)->SMask == NULL) + return 0; + + return 1; +} + int pdfi_trans_setup_text(pdf_context *ctx, pdfi_trans_state_t *state, bool is_show) { - int Trmode = gs_currenttextrenderingmode(ctx->pgs); + int Trmode; int code, code1; gs_rect bbox; + if (!pdfi_trans_required(ctx)) + return 0; + + Trmode = gs_currenttextrenderingmode(ctx->pgs); code = gs_gsave(ctx->pgs); if (code < 0) goto exit; @@ -781,11 +802,10 @@ int pdfi_trans_setup_text(pdf_context *ctx, pdfi_trans_state_t *state, bool is_s int pdfi_trans_teardown_text(pdf_context *ctx, pdfi_trans_state_t *state) { - int code = 0; - - code = pdfi_trans_teardown(ctx, state); + if (!pdfi_trans_required(ctx)) + return 0; - return code; + return pdfi_trans_teardown(ctx, state); } int pdfi_trans_teardown(pdf_context *ctx, pdfi_trans_state_t *state) diff --git a/pdf/pdf_trans.h b/pdf/pdf_trans.h index d6a33a889..3b71001de 100644 --- a/pdf/pdf_trans.h +++ b/pdf/pdf_trans.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019-2021 Artifex Software, Inc. +/* Copyright (C) 2019-2022 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or @@ -34,6 +34,7 @@ typedef enum { } pdfi_transparency_caller_t; bool pdfi_trans_okOPcs(pdf_context* ctx); +int pdfi_trans_required(pdf_context *ctx); int pdfi_trans_setup_text(pdf_context *ctx, pdfi_trans_state_t *state, bool is_show); int pdfi_trans_teardown_text(pdf_context *ctx, pdfi_trans_state_t *state); int pdfi_trans_setup(pdf_context *ctx, pdfi_trans_state_t *state, gs_rect *bbox, pdfi_transparency_caller_t caller); |