From 2c2dccf5a4d298c866f7c0faed2e10c65252c168 Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Tue, 12 Mar 2013 15:17:19 -0700 Subject: stroke: Use round-joins near inflection points of splines Similar to b7bd5ae4f3da44131261711bb236cd7aa24a3ae3, but applied to the fallback stroke shaper. --- src/cairo-path-stroke.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c index 6fae093d..4d4ede81 100644 --- a/src/cairo-path-stroke.c +++ b/src/cairo-path-stroke.c @@ -54,6 +54,7 @@ typedef struct cairo_stroker { const cairo_matrix_t *ctm_inverse; double half_line_width; double tolerance; + double spline_cusp_tolerance; double ctm_determinant; cairo_bool_t ctm_det_positive; @@ -137,6 +138,18 @@ _cairo_stroker_init (cairo_stroker_t *stroker, stroker->tolerance = tolerance; stroker->half_line_width = stroke_style->line_width / 2.0; + /* 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 - tolerance / stroker->half_line_width; + stroker->spline_cusp_tolerance *= stroker->spline_cusp_tolerance; + stroker->spline_cusp_tolerance *= 2; + stroker->spline_cusp_tolerance -= 1; + stroker->ctm_determinant = _cairo_matrix_compute_determinant (stroker->ctm); stroker->ctm_det_positive = stroker->ctm_determinant >= 0.0; @@ -1012,6 +1025,29 @@ _cairo_stroker_spline_to (void *closure, assert (stroker->has_current_face); + if ((new_face.dev_slope.x * stroker->current_face.dev_slope.x + + new_face.dev_slope.y * stroker->current_face.dev_slope.y) < stroker->spline_cusp_tolerance) { + + const cairo_point_t *inpt, *outpt; + int clockwise = _cairo_stroker_join_is_clockwise (&new_face, + &stroker->current_face); + + if (clockwise) { + inpt = &stroker->current_face.cw; + outpt = &new_face.cw; + } else { + inpt = &stroker->current_face.ccw; + outpt = &new_face.ccw; + } + + _tessellate_fan (stroker, + &stroker->current_face.dev_vector, + &new_face.dev_vector, + &stroker->current_face.point, + inpt, outpt, + clockwise); + } + if (_slow_segment_intersection (&stroker->current_face.cw, &stroker->current_face.ccw, &new_face.cw, -- cgit v1.2.3