Tolerances and Round Line Joins
Tavmjong Bah <[email protected]>
| Newsgroups | gmane.comp.lib.cairo |
|---|---|
| Message-ID | <[email protected]> |
Hi, I've been tracking down the source of a bug in Inkscape's rendering of paths with round line-joins where the join closing a path is rendered as a miter join.[1] I've found that the problem(s) are in the cairo code (probably introduced between 1.12.2 and 1.12.4) and would like some feedback on what a proper fix would be. Findings: 0. There is a tolerance condition applied to determine if a bevel join is good enough to use in place of a proper round line join. From the comments in "cairo-path-stroke-xxx.c": /* To test whether we need to join two segments of a spline using * a round-join or a bevel-join, we can inspect the angle between the * two segments. If the difference between the chord distance * (half-line -width times the cosine of the bisection angle) and the * half-line -width itself is greater than tolerance then we need to * inject a point. */ 1. A simple Cairo test program uses code in cairo-path-stroke-traps.c. This code applies the tolerance condition when constructing line joins, both in the middle of a path and when closing a path. 2. Inkscape uses code in cairo-path-stroke-polygon.c. This code applies the tolerance condition only when when constructing a line-join for closing a path. Joins in the middle of a path are always constructed as round line joins. When a path is being closed and the tolerance condition is not met, the path is closed with a miter (rather than a bevel as in cairo-path-stroke-traps.c). 3. The tolerance condition does not depend on the CTM matrix thus a path scaled up can have a visible defect (as we see in the SVG test case). 4. The tolerance condition is invalid if the 'tolerance' value is larger than the half the stroke width as this results in a negative number that is then squared. (For example, tolerance values of 5 and 0.05 result in rounded corners while a value of 0.1 results in beveled corners for right angles when the stroke width is 0.5, using the traps code.) Questions: 1. What triggers following the traps vs polygon code? 2. Why in the polygon code is the tolerance condition only applied on closing a path? 3. What is the best way to fix this problem? The simplest fix would be to remove the tolerance condition in cairo-path-stroke-polygon.c. Keeping the condition would mean: * Adding the condition for all joins in the path. * Fixing the fallback to 'bevel' rather than 'miter' * Making the condition dependent on the CTM. * Testing if the tolerance is greater than half the stroke width. Any feedback will be appreciated, Tav [1] https://bugs.launchpad.net/inkscape/+bug/1409520 -- cairo mailing list [email protected] http://lists.cairographics.org/mailman/listinfo/cairo