diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-06-24 11:27:16 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-06-24 11:53:18 +0100 |
commit | b7bd5ae4f3da44131261711bb236cd7aa24a3ae3 (patch) | |
tree | 750f0e85337c18b512926bd24bfe50ed55a5a5ed | |
parent | 3d482e266febcf7da75f5662e518380460068ce1 (diff) |
stroke: Use round-joins near inflection points of splines
Near an inflection, the angle between two segments of a spline increases
rapidly (as the radius of curvature decreases for the cusp). The angle
may increase so much that a simple line connecting the two outside
points of the spline is not within the user specified geometric
tolerance (with the result that you can generate severe ugliness around
a cusp). Extend the current detection of the exact inflection to cover
the sharp joins near the cusp by inspecting whether the bisection angle
is larger than acceptable.
Fixes bug-spline.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/cairo-path-stroke-polygon.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/src/cairo-path-stroke-polygon.c b/src/cairo-path-stroke-polygon.c index 88527f5b..e8e7bb23 100644 --- a/src/cairo-path-stroke-polygon.c +++ b/src/cairo-path-stroke-polygon.c @@ -67,6 +67,7 @@ struct stroker { const cairo_matrix_t *ctm; const cairo_matrix_t *ctm_inverse; double tolerance; + double spline_cusp_tolerance; cairo_bool_t ctm_det_positive; cairo_pen_t pen; @@ -1152,8 +1153,8 @@ spline_to (void *closure, } else { compute_face (point, tangent, stroker, &face); - if (face.dev_slope.x * stroker->current_face.dev_slope.x + - face.dev_slope.y * stroker->current_face.dev_slope.y < 0) + if ((face.dev_slope.x * stroker->current_face.dev_slope.x + + face.dev_slope.y * stroker->current_face.dev_slope.y) < stroker->spline_cusp_tolerance) { const cairo_point_t *inpt, *outpt; struct stroke_contour *outer; @@ -1304,7 +1305,17 @@ _cairo_path_fixed_stroke_to_polygon (const cairo_path_fixed_t *path, stroker.ctm = ctm; stroker.ctm_inverse = ctm_inverse; stroker.tolerance = tolerance; - + /* 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. + */ + stroker.spline_cusp_tolerance = 1 - 2 * tolerance / style->line_width; + stroker.spline_cusp_tolerance *= stroker.spline_cusp_tolerance; + stroker.spline_cusp_tolerance *= 2; + stroker.spline_cusp_tolerance -= 1; stroker.ctm_det_positive = _cairo_matrix_compute_determinant (ctm) >= 0.0; |