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 <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2012-08-25 12:57:01 +01:00
parent bdf83008f4
commit aeb039b16d

View file

@ -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;