summaryrefslogtreecommitdiff
path: root/src/cairo-path-bounds.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-01-22 15:54:45 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2010-01-22 23:01:52 +0000
commit6b77567b6ef28710c7707ab82c7fa95c810152d1 (patch)
treebdeedad0ec53e1984ed1f319eccddf2ab14141dd /src/cairo-path-bounds.c
parent6bfcf3ea55964fee1c9b73818c3bb7cdacbc4f82 (diff)
downloadcairo-6b77567b6ef28710c7707ab82c7fa95c810152d1.tar.gz
path: Compute coarse bounds upon construction.
Frequently we only need the coarse path bounds, so avoid walking over the list of points once more as we can cheaply track the extents during construction.
Diffstat (limited to 'src/cairo-path-bounds.c')
-rw-r--r--src/cairo-path-bounds.c159
1 files changed, 77 insertions, 82 deletions
diff --git a/src/cairo-path-bounds.c b/src/cairo-path-bounds.c
index 7b7ae6800..8f9bdc3f2 100644
--- a/src/cairo-path-bounds.c
+++ b/src/cairo-path-bounds.c
@@ -35,6 +35,7 @@
*/
#include "cairoint.h"
+#include "cairo-path-fixed-private.h"
typedef struct cairo_path_bounder {
cairo_point_t current_point;
@@ -135,26 +136,6 @@ _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_initial_point) {
- _cairo_path_bounder_add_point (bounder, &bounder->current_point);
- bounder->has_initial_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;
@@ -168,21 +149,8 @@ void
_cairo_path_fixed_approximate_clip_extents (const cairo_path_fixed_t *path,
cairo_rectangle_int_t *extents)
{
- cairo_path_bounder_t bounder;
- cairo_status_t status;
-
- _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_cp,
- _cairo_path_bounder_close_path,
- &bounder);
- 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) {
+ _cairo_box_round_to_rectangle (&path->extents, extents);
} else {
extents->x = extents->y = 0;
extents->width = extents->height = 0;
@@ -199,15 +167,20 @@ _cairo_path_fixed_approximate_fill_extents (const cairo_path_fixed_t *path,
cairo_path_bounder_t bounder;
cairo_status_t status;
- _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 (! 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);
@@ -226,14 +199,19 @@ _cairo_path_fixed_fill_extents (const cairo_path_fixed_t *path,
cairo_path_bounder_t bounder;
cairo_status_t status;
- _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 (! 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);
@@ -247,21 +225,43 @@ _cairo_path_fixed_fill_extents (const cairo_path_fixed_t *path,
void
_cairo_path_fixed_approximate_stroke_extents (const cairo_path_fixed_t *path,
const cairo_stroke_style_t *style,
- const const cairo_matrix_t *ctm,
+ const cairo_matrix_t *ctm,
cairo_rectangle_int_t *extents)
{
cairo_path_bounder_t bounder;
cairo_status_t status;
- _cairo_path_bounder_init (&bounder);
+ if (! path->has_curve_to) {
+ bounder.extents = path->extents;
- 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);
+ /* include trailing move-to for degenerate segments */
+ if (path->has_last_move_point) {
+ const cairo_point_t *point = &path->last_move_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;
@@ -294,12 +294,12 @@ _cairo_path_fixed_approximate_stroke_extents (const cairo_path_fixed_t *path,
}
cairo_status_t
-_cairo_path_fixed_stroke_extents (const cairo_path_fixed_t *path,
- const cairo_stroke_style_t *stroke_style,
- const cairo_matrix_t *ctm,
- const cairo_matrix_t *ctm_inverse,
- double tolerance,
- cairo_rectangle_int_t *extents)
+_cairo_path_fixed_stroke_extents (const cairo_path_fixed_t *path,
+ const cairo_stroke_style_t *stroke_style,
+ const cairo_matrix_t *ctm,
+ const cairo_matrix_t *ctm_inverse,
+ double tolerance,
+ cairo_rectangle_int_t *extents)
{
cairo_traps_t traps;
cairo_box_t bbox;
@@ -322,14 +322,18 @@ _cairo_path_fixed_stroke_extents (const cairo_path_fixed_t *path,
return status;
}
-void
-_cairo_path_fixed_bounds (const cairo_path_fixed_t *path,
- double *x1, double *y1,
- double *x2, double *y2)
+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->extents.p1.x < path->extents.p2.x;
+ }
+
_cairo_path_bounder_init (&bounder);
status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD,
@@ -340,15 +344,6 @@ _cairo_path_fixed_bounds (const cairo_path_fixed_t *path,
&bounder);
assert (status == CAIRO_STATUS_SUCCESS);
- if (bounder.has_point) {
- *x1 = _cairo_fixed_to_double (bounder.extents.p1.x);
- *y1 = _cairo_fixed_to_double (bounder.extents.p1.y);
- *x2 = _cairo_fixed_to_double (bounder.extents.p2.x);
- *y2 = _cairo_fixed_to_double (bounder.extents.p2.y);
- } else {
- *x1 = 0.0;
- *y1 = 0.0;
- *x2 = 0.0;
- *y2 = 0.0;
- }
+ *box = bounder.extents;
+ return bounder.has_point;
}