Bugzilla – Bug 691455
Stroking of sloppily authored paths goes wrong.
Last modified: 2011-02-06 01:08:50 UTC
Created attachment 6466 [details]
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.
Created attachment 6467 [details]
I'll look into this.
Created attachment 6471 [details]
The SVG rendered in firefox.
Created attachment 6472 [details]
The SVG rendered in IE.
Created attachment 6473 [details]
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.
Created attachment 6474 [details]
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.
(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.
Created attachment 6475 [details]
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.
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.
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?
Created attachment 6476 [details]
Added a postscript test that shows how strokes are rendered with the offending control handle moved around the end of the stroke.
Created attachment 6477 [details]
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.
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.
(In reply to comment #13)
> Created an attachment (id=6477) [details]
> 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
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).
Created attachment 6478 [details]
Harlequin output from lyd.eps
Created attachment 6479 [details]
Harlequin output from test-case.ps
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.
Created attachment 6480 [details]
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)
Created attachment 6481 [details]
Modified version of test-case.ps, overlaying the results with strokepath.
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.
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.
Created attachment 6578 [details]
A very simple example that shows the same problem.
Acrobat gets this right, ghostscript gets it wrong.
Created attachment 6615 [details]
Revised test case.
Created attachment 6616 [details]
Output for test-case3 from acrobat 9 pro (same result for PNG as TIFF, but PNG is easier to view on the web).
Created attachment 6617 [details]
72dpi output from gs using setaccuratecurves.
Created attachment 6618 [details]
test-case3.ps output from Jaws
Jaws output for test-case 3, RGB @72 dpi.
Created attachment 6619 [details]
GS in default mode, 72dpi.
Created attachment 6621 [details]
Harlequin output from test-case3.ps
Created attachment 6622 [details]
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.