diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2008-12-18 14:52:03 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2008-12-18 14:55:20 +0000 |
commit | 813cbf13ddbd3d4b708b3b362dd6c108966f44d5 (patch) | |
tree | db9844d62b71295e5431e83da34c18304e67c1e3 /src/cairo-path-bounds.c | |
parent | dea40e61babe608315b6d365094cf518814b134e (diff) | |
download | cairo-813cbf13ddbd3d4b708b3b362dd6c108966f44d5.tar.gz |
[path] Separate the approx. bounds into 3 distinct functions
Based on feedback from Jeff Muizelaar, there is a case for a very quick
and dirty extents approximation based solely on the curve control points
(for example when computing the clip intersect rectangle of a path) and
by moving the stroke extension into a core function we can clean up the
interface for all users, and centralise the logic of approximating the
stroke extents.
Diffstat (limited to 'src/cairo-path-bounds.c')
-rw-r--r-- | src/cairo-path-bounds.c | 101 |
1 files changed, 96 insertions, 5 deletions
diff --git a/src/cairo-path-bounds.c b/src/cairo-path-bounds.c index 25737e835..ec5bb2185 100644 --- a/src/cairo-path-bounds.c +++ b/src/cairo-path-bounds.c @@ -141,6 +141,27 @@ _cairo_path_bounder_curve_to (void *closure, } static cairo_status_t +_cairo_path_bounder_curve_to_cp (void *closure, + const cairo_point_t *b, + const cairo_point_t *c, + const cairo_point_t *d) +{ + cairo_path_bounder_t *bounder = closure; + + if (bounder->has_move_to_point) { + _cairo_path_bounder_add_point (bounder, + &bounder->move_to_point); + bounder->has_move_to_point = FALSE; + } + + _cairo_path_bounder_add_point (bounder, b); + _cairo_path_bounder_add_point (bounder, c); + _cairo_path_bounder_add_point (bounder, d); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t _cairo_path_bounder_close_path (void *closure) { return CAIRO_STATUS_SUCCESS; @@ -152,8 +173,69 @@ _cairo_path_bounder_close_path (void *closure) */ void _cairo_path_fixed_approximate_extents (cairo_path_fixed_t *path, - double tolerance, - cairo_box_t *extents) + cairo_rectangle_int_t *extents) +{ + cairo_path_bounder_t bounder; + cairo_status_t status; + + _cairo_path_bounder_init (&bounder, 0.); + + status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD, + _cairo_path_bounder_move_to, + _cairo_path_bounder_line_to, + _cairo_path_bounder_curve_to_cp, + _cairo_path_bounder_close_path, + &bounder); + assert (status == CAIRO_STATUS_SUCCESS); + + if (bounder.has_point) { + _cairo_box_round_to_rectangle (&bounder.extents, extents); + } else { + extents->x = extents->y = 0; + extents->width = extents->width = 0; + } + + _cairo_path_bounder_fini (&bounder); +} + +/* A slightly better approximation than above - we actually decompose the + * Bezier, but we continue to ignore winding. + */ +void +_cairo_path_fixed_approximate_fill_extents (cairo_path_fixed_t *path, + double tolerance, + cairo_rectangle_int_t *extents) +{ + cairo_path_bounder_t bounder; + cairo_status_t status; + + _cairo_path_bounder_init (&bounder, tolerance); + + status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD, + _cairo_path_bounder_move_to, + _cairo_path_bounder_line_to, + _cairo_path_bounder_curve_to, + _cairo_path_bounder_close_path, + &bounder); + assert (status == CAIRO_STATUS_SUCCESS); + + if (bounder.has_point) { + _cairo_box_round_to_rectangle (&bounder.extents, extents); + } else { + extents->x = extents->y = 0; + extents->width = extents->width = 0; + } + + _cairo_path_bounder_fini (&bounder); +} + +/* Adjusts the fill extents (above) by the device-space pen. */ +void +_cairo_path_fixed_approximate_stroke_extents (cairo_path_fixed_t *path, + cairo_stroke_style_t *style, + const cairo_matrix_t *ctm, + double tolerance, + cairo_rectangle_int_t *extents) { cairo_path_bounder_t bounder; cairo_status_t status; @@ -169,10 +251,19 @@ _cairo_path_fixed_approximate_extents (cairo_path_fixed_t *path, assert (status == CAIRO_STATUS_SUCCESS); if (bounder.has_point) { - *extents = bounder.extents; + double dx, dy; + + _cairo_stroke_style_max_distance_from_path (style, ctm, &dx, &dy); + + bounder.extents.p1.x -= _cairo_fixed_from_double (dx); + bounder.extents.p2.x += _cairo_fixed_from_double (dx); + bounder.extents.p1.y -= _cairo_fixed_from_double (dy); + bounder.extents.p2.y += _cairo_fixed_from_double (dy); + + _cairo_box_round_to_rectangle (&bounder.extents, extents); } else { - extents->p1.x = extents->p1.y = 0; - extents->p2.x = extents->p2.y = 0; + extents->x = extents->y = 0; + extents->width = extents->width = 0; } _cairo_path_bounder_fini (&bounder); |