summaryrefslogtreecommitdiff
path: root/psi/zpcolor.c
diff options
context:
space:
mode:
authorChris Liddell <chris.liddell@artifex.com>2016-01-07 17:44:56 +0000
committerChris Liddell <chris.liddell@artifex.com>2016-01-07 17:44:56 +0000
commitd5fe73441042077ee8e76494a94b9fef5102c3d0 (patch)
tree1a1b277e00cea706b16f6c9b7834c83378e7f3d3 /psi/zpcolor.c
parent03456d0a01bfb2823261d200d40bf2975c947eb8 (diff)
downloadghostpdl-d5fe73441042077ee8e76494a94b9fef5102c3d0.tar.gz
Bug 696502: cope with PaintProc with more gsaves than grestores
If a pattern PaintProc executes one or more gsave operations, and fails to execute a matching number of grestore operations, we can end up trying to complete any transparency operations and cache the pattern tile with the wrong gstate in force. pattern_paint_cleanup() already dealt with that, so add similar code to pattern_paint_finish() - as the information is already available on the stack.
Diffstat (limited to 'psi/zpcolor.c')
-rw-r--r--psi/zpcolor.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/psi/zpcolor.c b/psi/zpcolor.c
index 34e3ba7c6..5dccb6328 100644
--- a/psi/zpcolor.c
+++ b/psi/zpcolor.c
@@ -312,11 +312,29 @@ pattern_paint_finish(i_ctx_t *i_ctx_p)
gs_pattern1_instance_t *pinst =
(gs_pattern1_instance_t *)gs_currentcolor(igs->saved)->pattern;
gx_device_pattern_accum const *padev = (const gx_device_pattern_accum *) pdev;
+ gs_pattern1_instance_t *pinst2 = r_ptr(esp - 2, gs_pattern1_instance_t);
if (pdev != NULL) {
gx_color_tile *ctile;
int code;
gs_state *pgs = igs;
+ /* If the PaintProc does one or more gsaves, then fails to do an equal numer of
+ * grestores, we can get here with the graphics state stack not how we expect.
+ * Hence we stored a reference to the pattern instance on the exec stack, and that
+ * allows us to roll back the graphics states until we have the one we expect,
+ * and pattern instance we expect
+ */
+ if (pinst != pinst2) {
+ int i;
+ for (i = 0; pgs->saved && pinst != pinst2; i++, pgs = pgs->saved) {
+ pinst = (gs_pattern1_instance_t *)gs_currentcolor(pgs->saved)->pattern;
+ }
+ for (;i > 1; i--) {
+ gs_grestore(igs);
+ }
+ pinst = (gs_pattern1_instance_t *)gs_currentcolor(igs->saved)->pattern;
+ }
+ pgs = igs;
if (pinst->templat.uses_transparency) {
if (pinst->is_clist) {