GhostScript renders pattern (Shading Pattern, radial shading) wrong. Results in a geometric misbehaviour. This is wrong for PDF and EPS converted from PDF
Created attachment 5961 [details] Test-PDF example pdf for wrong rendering
Created attachment 5963 [details] h4i4h8.pdf Simplified sample file. The problem appears to be a wring stroke width for a line stroked with a shading pattern.
This is a regression that happened between v. 8.57 and v.8.60.
The problem first appears in: r8017 | leonardo | 2007-05-31 13:25:52 -0400 (Thu, 31 May 2007) | 97 lines Fix (shadings) : Optimize path manipulations for shading fill.
The stroking side of things looks fine and we end up with a correct 1 pixel wide rectangle to be filled with the shading. The code maps this backwards to get a path to be filled (which looks plausible to me) and then tries to fill it. This results in a call to fill a rectangle with a shading, and the rectangle to be filled is correctly 1 pixel wide. The shading code however takes a path that manages to ignore this clipping rectangle: gs_shading_R_fill_rectangle gs_shading_R_fill_rectangle_aux R_extensions R_tensor_annulus patch_fill fill_patch fill_patch fill_stripe decompose_stripe (recursively 6 times) fill_quadrangle constant_color_quadrangle constant_color_quadrangle_aux gx_shade_trapezoid Presumably, somewhere in there we should have some clipping...
This patch seems to solve the problem. I am not hugely happy with it though as a) I'm sure there must be existing "clip point to a rectangle" calls within ghostscript already, and b) I'm not sure that this is the best place to be doing such clipping. It may be that this just patches one point at which the problem arises and a more general solution should be sought. This is a place to start discussion though. Index: gs/base/gxshade6.c =================================================================== --- gs/base/gxshade6.c (revision 10913) +++ gs/base/gxshade6.c (working copy) @@ -2208,6 +2208,20 @@ # endif wrap_vertices_by_y(q, qq); } + { +#define CLIP_TO_RECT(P,R) \ +do {\ + if((P).x < (R).p.x) (P).x = (R).p.x;\ + if((P).x > (R).q.x) (P).x = (R).q.x;\ + if((P).y < (R).p.y) (P).y = (R).p.y;\ + if((P).y > (R).q.y) (P).y = (R).q.y;\ +} while (0==1) + CLIP_TO_RECT(q[0], pfs->rect); + CLIP_TO_RECT(q[1], pfs->rect); + CLIP_TO_RECT(q[2], pfs->rect); + CLIP_TO_RECT(q[3], pfs->rect); +#undef CLIP_TO_RECT + } { fixed dx1 = q[1].x - q[0].x, dy1 = q[1].y - q[0].y; fixed dx3 = q[3].x - q[0].x, dy3 = q[3].y - q[0].y; int64_t g13 = (int64_t)dx1 * dy3, h13 = (int64_t)dy1 * dx3;
The suggested patch fails local cluster testing. I'll investigate more.
Created attachment 6113 [details] Patch Better patch. It is possible for the area to be filled to get all the way down to the fill trapezoid case without ever being clipped. In this case, we "draw outside the lines". The fix is to spot this and clip within the trapezoid code. This patch fixes the problem locally with this file - testing now with the localcluster.
Created attachment 6120 [details] Final patch Final patch, committed as revision 10963. Mr Muller: Please feel free to apply this to your copy and let us know if it solves your problem.
Created attachment 6121 [details] Attachment of result, after supplying the patch See pdf/eps after applying the patch
I can confirm that I can reproduce this. Trying again.
Created attachment 6153 [details] Second_Version New patch, committed as revision 11025 that solves the bug.
Mr Muller, please feel free to try this version. It certainly seems to solve the problem locally, and passes our regression testing.
(In reply to comment #13) > Mr Muller, please feel free to try this version. It certainly seems to solve > the problem locally, and passes our regression testing. This patch is solving the problem. Great!