diff options
author | Chris Liddell <chris.liddell@artifex.com> | 2016-01-07 17:44:56 +0000 |
---|---|---|
committer | Chris Liddell <chris.liddell@artifex.com> | 2016-01-07 17:44:56 +0000 |
commit | d5fe73441042077ee8e76494a94b9fef5102c3d0 (patch) | |
tree | 1a1b277e00cea706b16f6c9b7834c83378e7f3d3 /psi/zpcolor.c | |
parent | 03456d0a01bfb2823261d200d40bf2975c947eb8 (diff) | |
download | ghostpdl-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.c | 18 |
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) { |