summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-06-24 11:27:16 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2012-06-24 11:53:18 +0100
commitb7bd5ae4f3da44131261711bb236cd7aa24a3ae3 (patch)
tree750f0e85337c18b512926bd24bfe50ed55a5a5ed
parent3d482e266febcf7da75f5662e518380460068ce1 (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.c17
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;