diff options
author | Andrea Canciani <ranma42@gmail.com> | 2010-10-22 12:35:40 +0200 |
---|---|---|
committer | Andrea Canciani <ranma42@gmail.com> | 2010-10-29 17:31:23 +0200 |
commit | 89e1261dd0fdb6c6c0271f71dd84d72504969ab1 (patch) | |
tree | bd846d6dfe75d48a5972e10e183188f6f376b9f9 /src/cairo-path-bounds.c | |
parent | 958c56e2b4f5447cc5a1cc137a8d287aebabe5dc (diff) | |
download | cairo-89e1261dd0fdb6c6c0271f71dd84d72504969ab1.tar.gz |
path-bounder: Simplify code
If the path extents are tight, all the extents computations and
approximations become trivial except for the stroke extents.
Diffstat (limited to 'src/cairo-path-bounds.c')
-rw-r--r-- | src/cairo-path-bounds.c | 249 |
1 files changed, 56 insertions, 193 deletions
diff --git a/src/cairo-path-bounds.c b/src/cairo-path-bounds.c index 9cfc56d3b..d17d9a207 100644 --- a/src/cairo-path-bounds.c +++ b/src/cairo-path-bounds.c @@ -1,3 +1,4 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* cairo - a vector graphics library with display and print output * * Copyright © 2003 University of Southern California @@ -35,48 +36,16 @@ */ #include "cairoint.h" +#include "cairo-box-private.h" #include "cairo-path-fixed-private.h" -typedef struct cairo_path_bounder { - cairo_point_t current_point; - cairo_bool_t has_initial_point; - cairo_bool_t has_point; +typedef struct _cairo_path_bounder { + cairo_point_t current_point; + cairo_bool_t has_extents; cairo_box_t extents; } cairo_path_bounder_t; -static void -_cairo_path_bounder_init (cairo_path_bounder_t *bounder) -{ - bounder->has_initial_point = FALSE; - bounder->has_point = FALSE; -} - -static void -_cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, - const cairo_point_t *point) -{ - if (bounder->has_point) { - if (point->x < bounder->extents.p1.x) - bounder->extents.p1.x = point->x; - - if (point->y < bounder->extents.p1.y) - bounder->extents.p1.y = point->y; - - if (point->x > bounder->extents.p2.x) - bounder->extents.p2.x = point->x; - - if (point->y > bounder->extents.p2.y) - bounder->extents.p2.y = point->y; - } else { - bounder->extents.p1.x = point->x; - bounder->extents.p1.y = point->y; - bounder->extents.p2.x = point->x; - bounder->extents.p2.y = point->y; - bounder->has_point = TRUE; - } -} - static cairo_status_t _cairo_path_bounder_move_to (void *closure, const cairo_point_t *point) @@ -84,7 +53,13 @@ _cairo_path_bounder_move_to (void *closure, cairo_path_bounder_t *bounder = closure; bounder->current_point = *point; - bounder->has_initial_point = TRUE; + + if (likely (bounder->has_extents)) { + _cairo_box_add_point (&bounder->extents, point); + } else { + bounder->has_extents = TRUE; + _cairo_box_set (&bounder->extents, point, point); + } return CAIRO_STATUS_SUCCESS; } @@ -95,13 +70,8 @@ _cairo_path_bounder_line_to (void *closure, { cairo_path_bounder_t *bounder = closure; - if (bounder->has_initial_point) { - _cairo_path_bounder_add_point (bounder, &bounder->current_point); - bounder->has_initial_point = FALSE; - } - - _cairo_path_bounder_add_point (bounder, point); bounder->current_point = *point; + _cairo_box_add_point (&bounder->extents, point); return CAIRO_STATUS_SUCCESS; } @@ -114,25 +84,12 @@ _cairo_path_bounder_curve_to (void *closure, { cairo_path_bounder_t *bounder = closure; - /* If the bbox of the control points is entirely inside, then we - * do not need to further evaluate the spline. - */ - if (! bounder->has_point || - b->x < bounder->extents.p1.x || b->x > bounder->extents.p2.x || - b->y < bounder->extents.p1.y || b->y > bounder->extents.p2.y || - c->x < bounder->extents.p1.x || c->x > bounder->extents.p2.x || - c->y < bounder->extents.p1.y || c->y > bounder->extents.p2.y || - d->x < bounder->extents.p1.x || d->x > bounder->extents.p2.x || - d->y < bounder->extents.p1.y || d->y > bounder->extents.p2.y) - { - return _cairo_spline_bound (_cairo_path_bounder_line_to, bounder, - &bounder->current_point, b, c, d); - } - else - { - /* All control points are within the current extents. */ - return CAIRO_STATUS_SUCCESS; - } + _cairo_box_add_curve_to (&bounder->extents, + &bounder->current_point, + b, c, d); + bounder->current_point = *d; + + return CAIRO_STATUS_SUCCESS; } static cairo_status_t @@ -141,53 +98,40 @@ _cairo_path_bounder_close_path (void *closure) return CAIRO_STATUS_SUCCESS; } -/* This computes the extents of all the points in the path, not those of - * the damage area (i.e it does not consider winding and it only inspects - * the control points of the curves, not the flattened path). - */ +cairo_bool_t +_cairo_path_bounder_extents (const cairo_path_fixed_t *path, + cairo_box_t *extents) +{ + cairo_path_bounder_t bounder; + cairo_status_t status; + + bounder.has_extents = FALSE; + 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); + + if (bounder.has_extents) + *extents = bounder.extents; + + return bounder.has_extents; +} + void _cairo_path_fixed_approximate_clip_extents (const cairo_path_fixed_t *path, cairo_rectangle_int_t *extents) { - if (path->extents.p1.x < path->extents.p2.x) { - _cairo_box_round_to_rectangle (&path->extents, extents); - } else { - extents->x = extents->y = 0; - extents->width = extents->height = 0; - } + _cairo_path_fixed_approximate_fill_extents (path, extents); } -/* A slightly better approximation than above - we actually decompose the - * Bezier, but we continue to ignore winding. - */ void _cairo_path_fixed_approximate_fill_extents (const cairo_path_fixed_t *path, cairo_rectangle_int_t *extents) { - cairo_path_bounder_t bounder; - cairo_status_t status; - - if (! path->has_curve_to) { - bounder.extents = path->extents; - bounder.has_point = path->extents.p1.x < path->extents.p2.x; - } else { - _cairo_path_bounder_init (&bounder); - - 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->height = 0; - } + _cairo_path_fixed_fill_extents (path, CAIRO_FILL_RULE_WINDING, 0, extents); } void @@ -196,25 +140,9 @@ _cairo_path_fixed_fill_extents (const cairo_path_fixed_t *path, double tolerance, cairo_rectangle_int_t *extents) { - cairo_path_bounder_t bounder; - cairo_status_t status; - - if (! path->has_curve_to) { - bounder.extents = path->extents; - bounder.has_point = path->extents.p1.x < path->extents.p2.x; - } else { - _cairo_path_bounder_init (&bounder); - - status = _cairo_path_fixed_interpret_flat (path, CAIRO_DIRECTION_FORWARD, - _cairo_path_bounder_move_to, - _cairo_path_bounder_line_to, - _cairo_path_bounder_close_path, - &bounder, tolerance); - assert (status == CAIRO_STATUS_SUCCESS); - } - - if (bounder.has_point) { - _cairo_box_round_to_rectangle (&bounder.extents, extents); + if (path->extents.p1.x < path->extents.p2.x && + path->extents.p1.y < path->extents.p2.y) { + _cairo_box_round_to_rectangle (&path->extents, extents); } else { extents->x = extents->y = 0; extents->width = extents->height = 0; @@ -228,65 +156,18 @@ _cairo_path_fixed_approximate_stroke_extents (const cairo_path_fixed_t *path, const cairo_matrix_t *ctm, cairo_rectangle_int_t *extents) { - cairo_path_bounder_t bounder; - cairo_status_t status; - - if (! path->has_curve_to) { - bounder.extents = path->extents; - - /* include trailing move-to for degenerate segments */ - if (path->needs_move_to) { - const cairo_point_t *point = &path->current_point; - - if (point->x < bounder.extents.p1.x) - bounder.extents.p1.x = point->x; - if (point->y < bounder.extents.p1.y) - bounder.extents.p1.y = point->y; - - if (point->x > bounder.extents.p2.x) - bounder.extents.p2.x = point->x; - if (point->y > bounder.extents.p2.y) - bounder.extents.p2.y = point->y; - } - - bounder.has_point = bounder.extents.p1.x <= bounder.extents.p2.x; - bounder.has_initial_point = FALSE; - } else { - _cairo_path_bounder_init (&bounder); - - 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) { - 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 if (bounder.has_initial_point) { + if (path->has_extents) { + cairo_box_t box_extents; double dx, dy; - /* accommodate capping of degenerate paths */ - + box_extents = path->extents; _cairo_stroke_style_max_distance_from_path (style, ctm, &dx, &dy); + box_extents.p1.x -= _cairo_fixed_from_double (dx); + box_extents.p1.y -= _cairo_fixed_from_double (dy); + box_extents.p2.x += _cairo_fixed_from_double (dx); + box_extents.p2.y += _cairo_fixed_from_double (dy); - bounder.extents.p1.x = bounder.current_point.x - _cairo_fixed_from_double (dx); - bounder.extents.p2.x = bounder.current_point.x + _cairo_fixed_from_double (dx); - bounder.extents.p1.y = bounder.current_point.y - _cairo_fixed_from_double (dy); - bounder.extents.p2.y = bounder.current_point.y + _cairo_fixed_from_double (dy); - - _cairo_box_round_to_rectangle (&bounder.extents, extents); + _cairo_box_round_to_rectangle (&box_extents, extents); } else { extents->x = extents->y = 0; extents->width = extents->height = 0; @@ -326,24 +207,6 @@ cairo_bool_t _cairo_path_fixed_extents (const cairo_path_fixed_t *path, cairo_box_t *box) { - cairo_path_bounder_t bounder; - cairo_status_t status; - - if (! path->has_curve_to) { - *box = path->extents; - return path->has_extents; - } - - _cairo_path_bounder_init (&bounder); - - 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); - - *box = bounder.extents; - return bounder.has_point; + *box = path->extents; + return path->has_extents; } |