Closed Bug 649960 Opened 13 years ago Closed 6 years ago

SVG wrong calculation of stroke-linejoin or stroke-miterlimit for problematic paths

Categories

(Core :: SVG, defect)

x86
Linux
defect
Not set
normal

Tracking

()

RESOLVED WORKSFORME

People

(Reporter: dr.o.hoffmann, Unassigned)

References

()

Details

User-Agent:       Mozilla/5.0 (X11; Linux i686; rv:2.0) Gecko/20100101 Firefox/4.0
Build Identifier: Mozilla/5.0 (X11; Linux i686; rv:2.0) Gecko/20100101 Firefox/4.0

Problematic paths for stroke-miterlimit and stroke-linejoin. 
For comparison the correct result is given too. 
The blue paths cover always the red ones completely.
More details for the test cases are available within the related desc elements.

Reproducible: Always

Steps to Reproduce:
1. Try the sample given in the URI above
2. Compare with desc(ription) and specification of stroke-linejoin and stroke-miterlimit
Actual Results:  
Some linejoins are wrong (indicated in red).

Expected Results:  
Blue paths should cover always red paths completely. There should be no red remaining.

Note, that many viewers have problems to get this right, but this results in
different renderings.


The degenerate case on top is especially problematic, but may only appear in
highly symmetrical, hand written files. 

It is defined (SVG 1.1):
"‘stroke-linejoin’ specifies the shape to be used at the corners of paths or basic shapes when they are stroked."

Therefore the stroke-linejoin is not limted to the usual case with two segements creating a corner. It applies for all corners within the path. 

Because the corner here is within one path segment, this can be difficult to find.
Gecko seems to use a rounded corner here, what is surprising, because nothing is set to round at all, but looks already better in most cases than for example the behaviour of Opera or Batik/Squiggle using a finite miter. 
Even if it is assumed, that stroke-miterlimit does not apply for such
linejoins, only for segment-joins, the miterlength would be infinite,
therefore a finite miter is a bug as well and only stroke-miterlimit has the capability to solve the problem in this situation - surprisingly Batik/Squiggles seems to know, how to display an infintie miter, but not for
the degenerate case, only for one sample below, where bevel applies ;o).

WebKit seems to display everything with bevel, even if miter would be right,
no alternative either ...
I imagine this is a cairo issue. Drawing the lines with canvas and getting the same result would prove that.

http://flashcanvas.net/examples/developer.mozilla.org/samples/canvas-tutorial/4_8_canvas_miterlimit.html may help in producing a canvas testcase.

If so this bug probably should to be moved to core->graphics rather than core->svg
If Cairo is used to stroke path, this sounds reasonable.
Not sure, how this script sample could help here, one has to test the specific 
paths with stroke-linejoin and stroke-miterlimit values - especially for
the test on top one needs such cubic path segments with a cusp.

Within an animated test (generated with PHP, avoiding java/ecma-script inconveniences) I have seen accuracy problems for stroke-miterlimit within
the requirements of SVG tiny as well (should be even better for a full viewer
as tested in the tiny test).
Such accuracy/rounding problem is a good explanation for the red at the bottom
test case. Apart from accuracy problems the implemented formula for stroke-miterlimit seems to be ok in unproblematic cases (if the limit is much smaller
or larger than the miter). This animated test uses only affine path segments.
http://hoffmann.bplaced.net/svgtest/stroke-miterlimit01.svg

But typically most authors will not use affine path segments with a miter angle
of 0 anyway (corresponding to an infinite miterlength), therefore this will
typically occur with those nice quadratic or cubic curves. And because people
like symmetries, such samples can appear outside from tests as well - intended
by the author or not. 

I never cared about canvas-sripting, therefore maybe others have to create
the corresponding canvas-script to check this, if required.
Does canvas-scripting refer to the definition of SVG for stroke-linejoin and
stroke-miterlimit, or why do you think, it has to be the same? Looking for example into the WHATWG draft, I'm not sure, if it is really always the same...
Canvas and SVG both use cairo to draw shapes. They don't really share much common code in Gecko beyond that so a Canvas example show whether the bug was in cairo as I suspect or something in the gecko SVG code.

I think that canvas has the same definition of miter limit and linejoin as SVG.
Hmmm, for the general SVG definition of stroke-linejoin see above, else for detals it is unfortunately of poor design especially for miter/round/bevel it notes only: 'See drawing below.' However this seemed to be no real problem for implementors.
In the WHATWG draft 'lineJoin' is described in detail for miter/round/bevel.
However it notes:  'The lineJoin attribute defines the type of corners that UAs will place where two lines meet.' and 'A join exists at any point in a subpath shared by two consecutive lines.' - it is not obvious whether this applies for
quadratic, cubic or elliptical arc segments as well, if they meet. And it seems
not to apply, if a corner appears within one segment, as possible for cubic paths.
For such a situation, the behaviour seems to be undefined in the WHATWG draft.
The SVG definition applies for corners in general.

For stroke-miterlimit SVG provides a formula, the WHATWG draft for miterLimit
does not, but I think, it is typically the same. 
Of course, it matters only in the WHATWG draft for situations, where stroke-linejoins applies at all - where two lines meet.

Therefore these are different definitions, however for lines they provide the
same behaviour.
For canvas either all tested situations of the file are undefined (if the
attributes apply only for lines), of if we assume, that they apply in general
for the linejoin of two path segments, the example on top would be still
undefined, because it has a corner/cusp within one segment, not covered by canvas.

Therefore it could be useful, to add some descriptive text to the SVG definition
of stroke-linejoin (even if the current 'example-image-definition' seemed to
cause no problems) and to adjust the canvas draft from 'line meeting' to
'corners' to have it properly defined for both formats in the same way - 
or at all in the case of canvas.

Of course, if the WHATWG draft reflects the typical implementation quality of
viewers, which interprete this already, it can be no surprise, that we get quite different rendering results for the SVG example given above ;o)
See Also: → 1508028
per 1508028 comment 2
Status: UNCONFIRMED → RESOLVED
Closed: 6 years ago
Resolution: --- → WORKSFORME
sorry that should have been bug 1508028 comment 2
You need to log in before you can comment on or make changes to this bug.