summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2013-03-12 15:17:19 -0700
committerMartin Robinson <mrobinson@igalia.com>2013-03-14 10:32:43 -0700
commit2c2dccf5a4d298c866f7c0faed2e10c65252c168 (patch)
treebb40601bdd73cce0604e307b9725bb6fd976cd2c
parentaadece05fb1cf80f0a1138368f4664e878a59204 (diff)
stroke: Use round-joins near inflection points of splines
Similar to b7bd5ae4f3da44131261711bb236cd7aa24a3ae3, but applied to the fallback stroke shaper.
-rw-r--r--src/cairo-path-stroke.c36
1 files changed, 36 insertions, 0 deletions
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,