summaryrefslogtreecommitdiff
path: root/pdf
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2022-02-07 16:30:23 +0000
committerRobin Watts <Robin.Watts@artifex.com>2022-02-07 19:55:23 +0000
commitd3b0f42bba612880f65d7e1446ca6a8757340bf3 (patch)
treeed389a4202415a3bbdde3eaaa5aa7392f9a05355 /pdf
parent3ee68db403b270b0a6534233f0579af55d094d2d (diff)
downloadghostpdl-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.c19
-rw-r--r--pdf/pdf_shading.c9
-rw-r--r--pdf/pdf_trans.c30
-rw-r--r--pdf/pdf_trans.h3
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);