summaryrefslogtreecommitdiff
path: root/pdf/pdf_path.c
diff options
context:
space:
mode:
authorKen Sharp <ken.sharp@artifex.com>2021-09-30 10:55:55 +0100
committerKen Sharp <ken.sharp@artifex.com>2021-09-30 10:55:55 +0100
commit04dafeae8b425cc823c2e58fe45d871943eb8ecf (patch)
tree5e4168bcd3c24f307fdfd2fb707a0f60eacb6920 /pdf/pdf_path.c
parent01e9f272831309c7db83cbe12a30c9b2ed6b37b7 (diff)
downloadghostpdl-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.c46
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;