diff options
author | Ken Sharp <ken.sharp@artifex.com> | 2021-09-30 10:55:55 +0100 |
---|---|---|
committer | Ken Sharp <ken.sharp@artifex.com> | 2021-09-30 10:55:55 +0100 |
commit | 04dafeae8b425cc823c2e58fe45d871943eb8ecf (patch) | |
tree | 5e4168bcd3c24f307fdfd2fb707a0f60eacb6920 /pdf/pdf_path.c | |
parent | 01e9f272831309c7db83cbe12a30c9b2ed6b37b7 (diff) | |
download | ghostpdl-04dafeae8b425cc823c2e58fe45d871943eb8ecf.tar.gz |
GhostPDF - fix soft-masks with pdfwrite
The pdfwrite device, when encountering a soft mask, stores the ID of
the soft mask in the graphics state. It then uses this to determine
whether a soft mask is in operation, and whether it is the same soft
mask as the current one in the pdfwrite context. When the ID in the
graphics state does not match the current ID, we need to grestore.
The problem here is that we instantiate an ExtGState, which has a SMask
and then perform a pair of fill operations. Both of these are performed
while the soft mask is active.
The pdfi interpreter does a gsave/grestore round the transparency
setup and teardown, which causes the soft_mask_id in the graphics state
to be reset. This causes pdfwrite to emit a grestore before the second
fill with the result that only the first fill takes place inside the
soft mask.
This is actually a pretty poor way to operate, but I'm wary of trying
to fix it in pdfwrite currently. Instead, alter the pdfi code so that we
do the gsave/grestore round the fill/stroke/fillstroke operation but not
around the transparency setup and teardown.
I did try removing the gsave/grestore altogether because it seemed to
me we shouldn't need it, but that caused other files to fail.
This fixes tests_private/comparefiles/Bug689931.pdf and
tests_private/comparefiles/Bug689931a.pdf with pdfwrite
Diffstat (limited to 'pdf/pdf_path.c')
-rw-r--r-- | pdf/pdf_path.c | 46 |
1 files changed, 30 insertions, 16 deletions
diff --git a/pdf/pdf_path.c b/pdf/pdf_path.c index ef6f1328d..d35cf4424 100644 --- a/pdf/pdf_path.c +++ b/pdf/pdf_path.c @@ -120,22 +120,28 @@ static int pdfi_fill_inner(pdf_context *ctx, bool use_eofill) if (pdfi_oc_is_off(ctx)) goto exit; - code = pdfi_gsave(ctx); - if (code < 0) goto exit; - code = pdfi_trans_setup(ctx, &state, NULL, TRANSPARENCY_Caller_Fill); if (code == 0) { + /* If we don't gsave/grestore round the fill, then the file + * /tests_private/pdf/sumatra/954_-_dashed_lines_hardly_visible.pdf renders + * incorrectly. However we must not gsave/grestore round the trans_setup + * trans_teardown, because that might set pgs->soft_mask_id and if we restore + * back to a point where that is not set then pdfwrite doesn't work properly. + */ + code = pdfi_gsave(ctx); + if (code < 0) goto exit; + if (use_eofill) code = gs_eofill(ctx->pgs); else code = gs_fill(ctx->pgs); + code1 = pdfi_grestore(ctx); + if (code == 0) code = code1; + code1 = pdfi_trans_teardown(ctx, &state); if (code == 0) code = code1; } - code1 = pdfi_grestore(ctx); - if (code == 0) code = code1; - exit: code1 = pdfi_newpath(ctx); if (code == 0) code = code1; @@ -164,20 +170,27 @@ int pdfi_stroke(pdf_context *ctx) if (pdfi_oc_is_off(ctx)) goto exit; - code = pdfi_gsave(ctx); - if (code < 0) goto exit; +/* code = pdfi_gsave(ctx); + if (code < 0) goto exit;*/ gs_swapcolors_quick(ctx->pgs); code = pdfi_trans_setup(ctx, &state, NULL, TRANSPARENCY_Caller_Stroke); if (code == 0) { + code = pdfi_gsave(ctx); + if (code < 0) goto exit; + code = gs_stroke(ctx->pgs); + + code1 = pdfi_grestore(ctx); + if (code == 0) code = code1; + code1 = pdfi_trans_teardown(ctx, &state); if (code == 0) code = code1; } gs_swapcolors_quick(ctx->pgs); - code1 = pdfi_grestore(ctx); - if (code == 0) code = code1; +/* code1 = pdfi_grestore(ctx); + if (code == 0) code = code1;*/ exit: code1 = pdfi_newpath(ctx); @@ -378,22 +391,23 @@ static int pdfi_B_inner(pdf_context *ctx, bool use_eofill) if (pdfi_oc_is_off(ctx)) goto exit; - code = pdfi_gsave(ctx); - if (code < 0) goto exit; - code = pdfi_trans_setup(ctx, &state, NULL, TRANSPARENCY_Caller_FillStroke); if (code == 0) { + code = pdfi_gsave(ctx); + if (code < 0) goto exit; + if (use_eofill) code = gs_eofillstroke(ctx->pgs, &code1); else code = gs_fillstroke(ctx->pgs, &code1); + + code1 = pdfi_grestore(ctx); + if (code == 0) code = code1; + code1 = pdfi_trans_teardown(ctx, &state); if (code >= 0) code = code1; } - code1 = pdfi_grestore(ctx); - if (code == 0) code = code1; - exit: code1 = pdfi_newpath(ctx); if (code == 0) code = code1; |