stroke-miterlimit: Why not use partial miters when a stroke linejoin exceeds the limit?

[ General comment: If it would preferable to submit these feature request /
implementation discussions through an issue tracker, please let me know.
I'm not quite clear on the relationship between the two issue trackers, one
at http://www.w3.org/Graphics/SVG/WG/track/ and one as part of the W3
Bugzilla.

Sorry for dumping a lot of ideas all at once, but as I mentioned previously
I'm starting to figure out what's new in SVG2, and I know that the working
group has got a big meeting coming up at the end of the month, so might as
well mention sooner rather than later. ]

______________________

Background:
------------------
The stroke-miterlimit prevents mitered strokes on acute linejoins from
extending far beyond the dimensions of the shape.

However, the behaviour was not clearly defined in SVG1.1 [1].  The general
description seems to imply that `stroke-miterlimit` is a *limit* that the
miter reaches but does not surpass.  However, the specific rule is "When
the limit is exceeded, the join is converted from a miter to a bevel",
which has been interpretted by most browsers as meaning to convert the
linejoin to `stroke-linejoin:bevel`, which is a much tighter crop.

The detailed implementation notes in the current SVG2 draft would lock in
that interpretation. [2]


The Problem:
------------------
In my mind, this is contrary to the spirit of a "limit" attribute.
Furthermore, it results in unpleasant effects in animation.  See
http://codepen.io/AmeliaBR/pen/JACBu?editors=110

Current behaviour in all browsers tested except Firefox is as described
above.  The switch to the the extreme bevel when the miter exceeds the
limit results in sudden jumps during animation, and ends up bevelling acute
angles much more closely than the miter on more oblique angles.

(Batik 1.7 seems to be cutting the difference, removing the bevelled area
but keeping the point!  Oops!)

In contrast, in Firefox (v32/33 on Win7), the animation is smooth.  If you
had a shape with multiple mitered corners of similar angles on either side
of the limit, they would be rendered consistently.

The discrepancy has been noted on this list before in May of this year [3],
where it was determined that the Firefox behaviour was operating-system
dependant.  That thread ended with a link to the corresponding Mozilla bug
page about standardizing the rendering [5].

Standardizing is good, but why not standardize in the other direction, to
the more aesthetically pleasing result that allows for smooth animations?
Yes, this would somewhat sacrifice backwards-compatibility, but only for a
feature that is currently implemented in incompatible ways by different
agents.


Request:
------------
That SVG 2 define the behaviour of stroke-miterlimit so that it never crops
mitered corners shorter than the limit.

A similar rule could also be applied to the proposed arc/talon linejoin,
taking the shape defined in the talon and clipping it to the miter limit.

In order to make this the defined behaviour, the final points in the line
join shape implementation notes (after calculating the basic intersection
points) would be amended as follows:

8. Let *bevel* be the triangle formed from the three points P, P1 and P2.

9. If ‘stroke-linejoin’ is bevel, return *bevel*.

10. If ‘stroke-linejoin’ is round, then return the union of *bevel* and a
circular sector of radius ‘stroke-width’, centered on P, and which has P1
and P2 as the two endpoints of the arc.

10. If ‘stroke-linejoin’ is arcs, then find the circles that are tangent to
the stroke edges at P1 and P2 with the same curvature as the edges at those
points (see "Computing the circles for the arcs 'stroke-linejoin'"). If
both curvatures are zero fall through to miter. Extend the stroke edges
using these circles (or a line, in the case of zero curvature). If the two
circles (or circle and line) intersect, let *extension* be the area inside
the region defined by the lines that connect P with P1 and P2 and the arcs
defined by the circles (or arc and line) between the closest intersection
point to P, and P1 and P2. If the two circles (or circle and line) do not
intersect, fall through to miter. Note that the curvatures are calculated
in user-space before any transforms are applied.

12. If ‘stroke-linejoin’ is miter, or if *extension* could not be defined
using the arcs method, let *extension* be the triangle formed from the
three points P1, P2 and P3.

13. Let θ be the angle between A and B.  If 1 / sin(θ / 2) ≤
‘stroke-miterlimit’, then return the union of *extension* and *bevel*.

14. Construct a clipping rectangle, *limit*, centered on P that extends
(‘stroke-miterlimit’ * ‘stroke-width’) from P in the directions
perpendicular to the line between P and P3, and half that distance in the
directions parallel to that line.  In other words, if P is (x,y), P3 is
(x1,y1), and the computed distance is d, then the four vertexes of the
clipping polygon would be defined as (x,y) ± d/2*(x1-x, y1-y) ± d*(y1-1,
x-x1).

15. Return the the union of *bevel* with *extension*, clipped to *limit*.

Depending on implementations, user agents might skip 13 and just apply the
clipping region; it depends which is faster, a null-effect clipping
operation or trigonometry.

I'm fairly certain this reflects the current Firefox/Windows implementation
for miters, and I think it would result in acceptable appearance of
"clipped talons" when applied to the arc line joins, although I haven't
explored it carefully.  The use of a clipping rectangle centered on P is
intended to encompass any degree of curvature of the talons, including
curving back towards the other side of the join.  However, I'm not sure
whether the use of 1 / sin(θ / 2) will cover all cases of long talons; it
might be better to directly calculate the distance to the intersection
point of the two arcs.


[1]: http://www.w3.org/TR/SVG11/painting.html#StrokeMiterlimitProperty
[2]:
http://www.w3.org/TR/2014/WD-SVG2-20140211/painting.html#TermLineJoinShape
[3]: http://lists.w3.org/Archives/Public/www-svg/2013May/0020.html
[4]: https://bugzilla.mozilla.org/show_bug.cgi?id=854296

Received on Saturday, 18 October 2014 22:19:03 UTC