From aeb039b16dc302192113a7f10c4b86e7d13eb221 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 25 Aug 2012 12:57:01 +0100 Subject: [PATCH] stroke: Skip spline evaluation when stroking to a polygon If the spline is wholly outside the clip region, accounting for the stroke width and additional rendering, then we can simplify that spline with a straight line. Signed-off-by: Chris Wilson --- src/cairo-path-stroke-polygon.c | 37 +++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/cairo-path-stroke-polygon.c b/src/cairo-path-stroke-polygon.c index b7c18b72e..242fb24a1 100644 --- a/src/cairo-path-stroke-polygon.c +++ b/src/cairo-path-stroke-polygon.c @@ -81,6 +81,9 @@ struct stroker { cairo_bool_t has_first_face; cairo_stroke_face_t first_face; + + cairo_bool_t has_bounds; + cairo_box_t bounds; }; static inline double @@ -165,6 +168,10 @@ add_fan (struct stroker *stroker, { int start, stop, step, i, npoints; + if (stroker->has_bounds && + ! _cairo_box_contains_point (&stroker->bounds, midpt)) + return; + assert (stroker->pen.num_vertices); if (clockwise) { @@ -1207,6 +1214,11 @@ curve_to (void *closure, cairo_spline_t spline; cairo_stroke_face_t face; + if (stroker->has_bounds && + ! _cairo_spline_intersects (&stroker->current_face.point, b, c, b, + &stroker->bounds)) + return line_to (closure, d); + if (! _cairo_spline_init (&spline, spline_to, stroker, &stroker->current_face.point, b, c, d)) return line_to (closure, d); @@ -1305,6 +1317,31 @@ _cairo_path_fixed_stroke_to_polygon (const cairo_path_fixed_t *path, polygon); } + stroker.has_bounds = polygon->num_limits; + if (stroker.has_bounds) { + /* Extend the bounds in each direction to account for the maximum area + * we might generate trapezoids, to capture line segments that are + * outside of the bounds but which might generate rendering that's + * within bounds. + */ + double dx, dy; + cairo_fixed_t fdx, fdy; + int i; + + stroker.bounds = polygon->limits[0]; + for (i = 1; i < polygon->num_limits; i++) + _cairo_box_add_box (&stroker.bounds, &polygon->limits[i]); + + _cairo_stroke_style_max_distance_from_path (style, path, ctm, &dx, &dy); + fdx = _cairo_fixed_from_double (dx); + fdy = _cairo_fixed_from_double (dy); + + stroker.bounds.p1.x -= fdx; + stroker.bounds.p2.x += fdx; + stroker.bounds.p1.y -= fdy; + stroker.bounds.p2.y += fdy; + } + stroker.style = *style; stroker.ctm = ctm; stroker.ctm_inverse = ctm_inverse;