Bug 691115 - PDF Pattern Render Error (Shading Pattern, Radial)
Summary: PDF Pattern Render Error (Shading Pattern, Radial)
Status: RESOLVED FIXED
Alias: None
Product: Ghostscript
Classification: Unclassified
Component: General (show other bugs)
Version: 8.70
Hardware: PC Windows XP
: P4 critical
Assignee: Robin Watts
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-02-17 09:32 UTC by Dietmar Müller
Modified: 2010-04-07 13:14 UTC (History)
1 user (show)

See Also:
Customer:
Word Size: ---


Attachments
Test-PDF (11.48 MB, application/pdf)
2010-02-17 09:40 UTC, Dietmar Müller
Details
h4i4h8.pdf (2.18 KB, application/pdf)
2010-02-17 19:30 UTC, Alex Cherepanov
Details
Patch (6.27 KB, patch)
2010-03-23 15:10 UTC, Robin Watts
Details | Diff
Final patch (7.17 KB, patch)
2010-03-24 12:50 UTC, Robin Watts
Details | Diff
Attachment of result, after supplying the patch (100.45 KB, image/jpeg)
2010-03-24 15:36 UTC, Dietmar Müller
Details
Second_Version (17.61 KB, patch)
2010-04-06 19:37 UTC, Robin Watts
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Dietmar Müller 2010-02-17 09:32:54 UTC
GhostScript renders pattern (Shading Pattern, radial shading) wrong.
Results in a geometric misbehaviour.

This is wrong for PDF and EPS converted from PDF
Comment 1 Dietmar Müller 2010-02-17 09:40:17 UTC
Created attachment 5961 [details]
Test-PDF

example pdf for wrong rendering
Comment 2 Alex Cherepanov 2010-02-17 19:30:19 UTC
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.
Comment 3 Alex Cherepanov 2010-02-18 13:27:25 UTC
This is a regression that happened between v. 8.57 and v.8.60.
Comment 4 Alex Cherepanov 2010-02-18 19:05:26 UTC
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.
Comment 5 Robin Watts 2010-02-24 08:52:14 UTC
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...
Comment 6 Robin Watts 2010-03-10 21:47:41 UTC
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;
Comment 7 Robin Watts 2010-03-11 00:43:47 UTC
The suggested patch fails local cluster testing. I'll investigate more.
Comment 8 Robin Watts 2010-03-23 15:10:56 UTC
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.
Comment 9 Robin Watts 2010-03-24 12:50:56 UTC
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.
Comment 10 Dietmar Müller 2010-03-24 15:36:01 UTC
Created attachment 6121 [details]
Attachment of result, after supplying the patch

See pdf/eps after applying the patch
Comment 11 Robin Watts 2010-04-01 14:28:18 UTC
I can confirm that I can reproduce this. Trying again.
Comment 12 Robin Watts 2010-04-06 19:37:01 UTC
Created attachment 6153 [details]
Second_Version

New patch, committed as revision 11025 that solves the bug.
Comment 13 Robin Watts 2010-04-06 19:37:57 UTC
Mr Muller, please feel free to try this version. It certainly seems to solve the problem locally, and passes our regression testing.
Comment 14 Dietmar Müller 2010-04-07 13:10:52 UTC
(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!