Bug 691455 - Stroking of sloppily authored paths goes wrong.
Stroking of sloppily authored paths goes wrong.
Status: CONFIRMED
Product: Ghostscript
Classification: Unclassified
Component: Vectors
8.71
PC Linux
: P4 normal
Assigned To: Robin Watts
Bug traffic
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2010-07-12 14:46 PDT by Øyvind Kolås
Modified: 2011-02-06 01:08 PST (History)
3 users (show)

See Also:
Customer:
Word Size: ---


Attachments
EPS file (3.22 KB, image/x-eps)
2010-07-12 14:46 PDT, Øyvind Kolås
Details
SVG file (15.62 KB, image/svg)
2010-07-12 14:47 PDT, Øyvind Kolås
Details
firefox.png (75.21 KB, image/png)
2010-07-13 11:15 PDT, Robin Watts
Details
ie.png (61.72 KB, image/png)
2010-07-13 11:16 PDT, Robin Watts
Details
chrome.png (61.96 KB, image/png)
2010-07-13 11:21 PDT, Robin Watts
Details
test.ps (148 bytes, application/postscript)
2010-07-13 13:14 PDT, Robin Watts
Details
test.ps (345 bytes, application/postscript)
2010-07-13 14:03 PDT, Robin Watts
Details
test-case.ps (2.17 KB, application/postscript)
2010-07-13 17:09 PDT, Øyvind Kolås
Details
correct-render.png (42.27 KB, image/png)
2010-07-13 17:47 PDT, Øyvind Kolås
Details
Harlequin output from lyd.eps (1.47 KB, image/png)
2010-07-14 10:47 PDT, Chris Liddell (chrisl)
Details
Harlequin output from test-case.ps (2.05 KB, image/png)
2010-07-14 10:48 PDT, Chris Liddell (chrisl)
Details
test-case2.ps (2.53 KB, application/postscript)
2010-07-14 11:02 PDT, Øyvind Kolås
Details
test-case2.ps (2.28 KB, application/postscript)
2010-07-14 11:04 PDT, Robin Watts
Details
simple.ps (158 bytes, application/postscript)
2010-07-29 19:02 PDT, Robin Watts
Details
test-case3.ps (3.12 KB, application/postscript)
2010-08-05 15:52 PDT, Robin Watts
Details
test-case3-acrobat9pro.png (26.30 KB, image/png)
2010-08-05 15:56 PDT, Robin Watts
Details
test-case3-gsaccurate.png (24.43 KB, image/png)
2010-08-05 16:00 PDT, Robin Watts
Details
test-case3.ps output from Jaws (1.39 MB, image/tiff)
2010-08-05 16:00 PDT, Ken Sharp
Details
test-case3-gsdefault.png (25.38 KB, image/png)
2010-08-05 16:03 PDT, Robin Watts
Details
Harlequin output from test-case3.ps (14.74 KB, image/png)
2010-08-05 17:14 PDT, Chris Liddell (chrisl)
Details
AdobeCPSI_output.pdf (653.29 KB, application/pdf)
2010-08-05 18:38 PDT, Ray Johnston
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Øyvind Kolås 2010-07-12 14:46:33 PDT
Created attachment 6466 [details]
EPS file

Rendering an EPS with square line caps and slightly offset bezier control handles results in unexpected rendering output. The cases are a straight line looping back on itself due to the positioning of a bezier handle in the continuation of the final line stroke. The other is a line that has a bezier control handle positioned perpendicular to the final line segment. See attached EPS and SVG.
The SVG renders correctly in chrome and firefox but exhibits similar issues to ghostscript in inkscape which was the authoring tool used.
Comment 1 Øyvind Kolås 2010-07-12 14:47:50 PDT
Created attachment 6467 [details]
SVG file
Comment 2 Robin Watts 2010-07-12 15:24:14 PDT
I'll look into this.
Comment 3 Robin Watts 2010-07-13 11:15:32 PDT
Created attachment 6471 [details]
firefox.png

The SVG rendered in firefox.
Comment 4 Robin Watts 2010-07-13 11:16:01 PDT
Created attachment 6472 [details]
ie.png

The SVG rendered in IE.
Comment 5 Robin Watts 2010-07-13 11:21:40 PDT
Created attachment 6473 [details]
chrome.png
Comment 6 Robin Watts 2010-07-13 13:12:43 PDT
Firefox and Chrome agree on the SVG rendering (modulo a stray pixel in chrome).
IE (Using Adobes SVG plugin) renders with square line caps rather than round/half round ones.

I think IE (well, Adobe really) is the only one that gets it right. Ghostscripts rendering of the EPS agrees with Adobes rendering of the SVG.

I am unable to test the .eps file in Acrobat Pro 9 as it won't import properly. 

From the bug report, it sounds like ghostscript and inkscape are agreeing and also getting it right.
Comment 7 Robin Watts 2010-07-13 13:14:51 PDT
Created attachment 6474 [details]
test.ps

Simple test postscript file intended to simulate the kind of problem we're seeing.

Adobe Acrobat Pro 9 renders the second line (the one which reverses on itself) with a circular end cap. Ghostscript does not.
Comment 8 Ken Sharp 2010-07-13 13:20:27 PDT
(In reply to comment #6)
> Firefox and Chrome agree on the SVG rendering (modulo a stray pixel in chrome).
> IE (Using Adobes SVG plugin) renders with square line caps rather than
> round/half round ones.
> 
> I think IE (well, Adobe really) is the only one that gets it right.
> Ghostscripts rendering of the EPS agrees with Adobes rendering of the SVG.
> 
> I am unable to test the .eps file in Acrobat Pro 9 as it won't import properly. 

I used Distiller to convert it into a PDF and it worked OK, the resulting PDF displays in Acrobat as per Firefox and Chrome.
Comment 9 Robin Watts 2010-07-13 14:03:41 PDT
Created attachment 6475 [details]
test.ps

Better test.ps that shows the problem more precisely. Acrobat Pro 9 renders this differently from ghostscript, and more in line with how firefox/chrome render the svg.
Comment 10 Robin Watts 2010-07-13 15:57:49 PDT
As a final test, I changed the code in test.ps to do:

strokepath 0.1 setlinewidth stroke

rather than just stroke. This, according to the PLRM should give the same outline as simply stroking it. Acrobat changes the outline of the path to match gs, thus revealing itself to be inconsistent.

I am therefore closing this as RESOLVED - INVALID, as it looks like we do 'the right thing' already.
Comment 11 Øyvind Kolås 2010-07-13 16:22:57 PDT
If the result of stroke / strokepath is to be the same as convolving the pen with the path then the firefox/chrome rendition should be expected. At which point should one behavior rather than the other be triggered?
Comment 12 Øyvind Kolås 2010-07-13 17:09:04 PDT
Created attachment 6476 [details]
test-case.ps

Added a postscript test that shows how strokes are rendered with the offending control handle moved around the end of the stroke.
Comment 13 Øyvind Kolås 2010-07-13 17:47:20 PDT
Created attachment 6477 [details]
correct-render.png

Added an attachment showing how the other render engines would render the previous postscript test. These renderings all have a final cap that is perpendicular to the line between the two last coordinates of the final curveto.
Comment 14 Øyvind Kolås 2010-07-13 18:11:42 PDT
Inkscape where the logo was initially drawn exhibits a similar buggy behavior. Based on these renderings it seems like GhostScript internally is using strokepath to implement stroke.

It seems likely that the buggy behavior arises from insufficient precision in the approximation of the last bit of the stroke to orient a line cap that is "pasted"/unioned into the final shape. If it is possible to change this computation to instead directly derive the incline from the curve coordinates it seems like the rendering should match the correct one.
Comment 15 Ken Sharp 2010-07-14 07:19:36 PDT
(In reply to comment #13)
> Created an attachment (id=6477) [details]
> correct-render.png
> 
> Added an attachment showing how the other render engines would render the
> previous postscript test. These renderings all have a final cap that is
> perpendicular to the line between the two last coordinates of the final
> curveto.

Which other engines? 

I used Jaws (a different PostScript rip) to render the test file and it agrees with Ghostscript. I also used Adobe Acrobat Distiller to convert to a PDF file and examined that in Acrobat. While the first two lines do match the .PNG file, the third line does not, the three leftmost and the rightmost verticals are shown with butt end caps.

According to Robin's comment #10 Acrobat does not draw the same path when using strokepath, and is therefore unreliable as it should do so. It also doesn't match the 'reference'.

Comparisons with SVG and SVG rendering engines are irrelevant, we are consuming PostScript. It is entirely possible that the PostScript generation is incorrect and does not match the correct result in SVG, that would be a bug in the PostScript generation.

It would be interesting to see the result from an Adobe CPSI rip, and also from a Harlequin rip to give a couple more data points. It would be important to also check the strokepath result to ensure the implementation is reliable (unlike Acrobat).
Comment 16 Chris Liddell (chrisl) 2010-07-14 10:47:34 PDT
Created attachment 6478 [details]
Harlequin output from lyd.eps
Comment 17 Chris Liddell (chrisl) 2010-07-14 10:48:30 PDT
Created attachment 6479 [details]
Harlequin output from test-case.ps
Comment 18 Chris Liddell (chrisl) 2010-07-14 10:50:01 PDT
The two outputs from the Harlequin rip were written to tiff and converted to PNG for uploading. 96dpi mono. The HQN version is about 18 months old.
Comment 19 Øyvind Kolås 2010-07-14 11:02:13 PDT
Created attachment 6480 [details]
test-case2.ps

I think the comparison with SVG is valid, unless PostScript has a different defintion for defining beziers and how beziers are stroked. In my interpretation of such stroking the end-line of butt and square endcaps should be tangential to the line defined by the last two coordinates in the curveto coordinate triplet.

Of course strokepath fill and stroke should produce the same results, I am arguing that the ghostscript output is just as inprecise in both cases.

Added a postscript file that illustrates another permutation of this corner case (swapping the last coordinates of the curve). The upper end point still has a vertical tangent, while the bottom end of the strokes no longer should have a horizontal tangent.

The same numerical precision issues of using the slope of an insufficiently precise piece-wise linear approximation causes the exact slope used for the caps to be wrong.

(An interesting variation of the bug can be seen by using 0 setlinecap instead of 2 setlinecap)
Comment 20 Robin Watts 2010-07-14 11:04:27 PDT
Created attachment 6481 [details]
test-case2.ps

Modified version of test-case.ps, overlaying the results with strokepath.
Comment 21 Robin Watts 2010-07-14 11:15:15 PDT
The PLRM says that the strokepath operator:

"replaces the current path with one enclosing the shape that would result if the stroke operator were applied to the current path. The path resulting from strokepath is suitable as the implicit operator to fill, clip or pathbbox."

So, in a conforming implementation, strokepath and stroke must always give the same results. Ghostscript is such a conforming implementation. Acrobat, it seems is not.

I take your point about the fact that end caps should be applied in line with the vector between the end point of the bezier and the previous control point though. As you say this is clearly not happening exactly as we might wish it to due to the limited precision involved in the subdivision of the bezier to line segments. I'll have to ponder if there is a better way for us to achieve this.
Comment 22 Øyvind Kolås 2010-07-14 12:04:13 PDT
Depending on the rasteriz(In reply to comment #21)
> So, in a conforming implementation, strokepath and stroke must always give the
> same results. Ghostscript is such a conforming implementation. Acrobat, it
> seems is not.

Your updated test with strokepath shows that even ghostscript isn't always conforming depending on the scale of the rasterization the strokepath and stroke versions differ due to issues of numeric precision. This is seen in the first few sub paths in the test.
Comment 23 Robin Watts 2010-07-29 19:02:07 PDT
Created attachment 6578 [details]
simple.ps

A very simple example that shows the same problem.

Acrobat gets this right, ghostscript gets it wrong.
Comment 24 Robin Watts 2010-08-05 15:52:04 PDT
Created attachment 6615 [details]
test-case3.ps

Revised test case.
Comment 25 Robin Watts 2010-08-05 15:56:50 PDT
Created attachment 6616 [details]
test-case3-acrobat9pro.png

Output for test-case3 from acrobat 9 pro (same result for PNG as TIFF, but PNG is easier to view on the web).
Comment 26 Robin Watts 2010-08-05 16:00:29 PDT
Created attachment 6617 [details]
test-case3-gsaccurate.png

72dpi output from gs using setaccuratecurves.
Comment 27 Ken Sharp 2010-08-05 16:00:47 PDT
Created attachment 6618 [details]
test-case3.ps output from Jaws

Jaws output for test-case 3, RGB @72 dpi.
Comment 28 Robin Watts 2010-08-05 16:03:33 PDT
Created attachment 6619 [details]
test-case3-gsdefault.png

GS in default mode, 72dpi.
Comment 29 Chris Liddell (chrisl) 2010-08-05 17:14:08 PDT
Created attachment 6621 [details]
Harlequin output from test-case3.ps
Comment 30 Ray Johnston 2010-08-05 18:38:33 PDT
Created attachment 6622 [details]
AdobeCPSI_output.pdf

This file was created from CPSI rendering to 600 dpi, sending the output image
to a NitroPDF driver to convert to a PDF (image) file. Even though this is a
PDF, the rendering was performed by CPSI.