[cairo] [PATCH 2/2] stroke: Use round-joins near inflection points of splines
Martin Robinson
mrobinson at igalia.com
Tue Mar 12 15:17:19 PDT 2013
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 7d99f7f..180fce7 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,
--
1.7.10.4
More information about the cairo
mailing list