[cairo-commit] src/cairo-analysis-surface.c src/cairo-clip.c src/cairoint.h src/cairo-path-bounds.c src/cairo-rectangle.c src/cairo-surface-fallback.c
Chris Wilson
ickle at kemper.freedesktop.org
Thu Dec 18 07:08:06 PST 2008
src/cairo-analysis-surface.c | 32 +++++--------
src/cairo-clip.c | 14 ++---
src/cairo-path-bounds.c | 101 ++++++++++++++++++++++++++++++++++++++++---
src/cairo-rectangle.c | 10 ----
src/cairo-surface-fallback.c | 10 ++--
src/cairoint.h | 19 +++++---
6 files changed, 134 insertions(+), 52 deletions(-)
New commits:
commit 813cbf13ddbd3d4b708b3b362dd6c108966f44d5
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Thu Dec 18 14:52:03 2008 +0000
[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.
diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index b8f2ab4..b3eab41 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -290,12 +290,12 @@ _cairo_analysis_surface_intersect_clip_path (void *abstract_surface,
surface->current_clip.width = surface->width;
surface->current_clip.height = surface->height;
} else {
- cairo_box_t extents;
+ cairo_rectangle_int_t extents;
cairo_bool_t is_empty;
- _cairo_path_fixed_approximate_extents (path, tolerance, &extents);
- is_empty = _cairo_rectangle_intersect_box (&surface->current_clip,
- &extents);
+ _cairo_path_fixed_approximate_extents (path, &extents);
+ is_empty = _cairo_rectangle_intersect (&surface->current_clip,
+ &extents);
}
return CAIRO_STATUS_SUCCESS;
@@ -478,19 +478,13 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
if (_cairo_operator_bounded_by_mask (op)) {
- cairo_box_t mask_extents;
- double dx, dy;
-
- _cairo_path_fixed_approximate_extents (path, tolerance, &mask_extents);
-
- _cairo_stroke_style_max_distance_from_path (style, ctm, &dx, &dy);
+ cairo_rectangle_int_t mask_extents;
- mask_extents.p1.x -= _cairo_fixed_from_double (dx);
- mask_extents.p2.x += _cairo_fixed_from_double (dx);
- mask_extents.p1.y -= _cairo_fixed_from_double (dy);
- mask_extents.p2.y += _cairo_fixed_from_double (dy);
+ _cairo_path_fixed_approximate_stroke_extents (path,
+ style, ctm, tolerance,
+ &mask_extents);
- is_empty = _cairo_rectangle_intersect_box (&extents, &mask_extents);
+ is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
}
if (stroke_extents)
*stroke_extents = extents;
@@ -542,11 +536,13 @@ _cairo_analysis_surface_fill (void *abstract_surface,
is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
if (_cairo_operator_bounded_by_mask (op)) {
- cairo_box_t mask_extents;
+ cairo_rectangle_int_t mask_extents;
- _cairo_path_fixed_approximate_extents (path, tolerance, &mask_extents);
+ _cairo_path_fixed_approximate_fill_extents (path,
+ tolerance,
+ &mask_extents);
- is_empty = _cairo_rectangle_intersect_box (&extents, &mask_extents);
+ is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
}
if (fill_extents)
*fill_extents = extents;
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index cd36924..f0f68a3 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -143,13 +143,11 @@ _cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t *clip_path,
cairo_rectangle_int_t *rectangle)
{
while (clip_path) {
- cairo_box_t extents;
+ cairo_rectangle_int_t extents;
- _cairo_path_fixed_approximate_extents (&clip_path->path,
- clip_path->tolerance,
- &extents);
+ _cairo_path_fixed_approximate_extents (&clip_path->path, &extents);
- if (! _cairo_rectangle_intersect_box (rectangle, &extents))
+ if (! _cairo_rectangle_intersect (rectangle, &extents))
return CAIRO_STATUS_SUCCESS;
clip_path = clip_path->prev;
@@ -577,10 +575,10 @@ _cairo_clip_intersect_mask_using_spans (cairo_clip_t *clip,
/* We'll create a new surface the size of the intersection of the
* old mask surface and the extents of the new clip path. */
{
- cairo_box_t extents;
+ cairo_rectangle_int_t extents;
- _cairo_path_fixed_approximate_extents (path, tolerance, &extents);
- if (! _cairo_rectangle_intersect_box (&surface_rect, &extents))
+ _cairo_path_fixed_approximate_extents (path, &extents);
+ if (! _cairo_rectangle_intersect (&surface_rect, &extents))
goto SUCCESS;
if (clip->surface != NULL &&
diff --git a/src/cairo-path-bounds.c b/src/cairo-path-bounds.c
index 25737e8..ec5bb21 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);
diff --git a/src/cairo-rectangle.c b/src/cairo-rectangle.c
index 31a530e..b139624 100644
--- a/src/cairo-rectangle.c
+++ b/src/cairo-rectangle.c
@@ -126,16 +126,6 @@ _cairo_rectangle_intersect (cairo_rectangle_int_t *dst,
}
}
-cairo_bool_t
-_cairo_rectangle_intersect_box (cairo_rectangle_int_t *dst,
- const cairo_box_t *src)
-{
- cairo_rectangle_int_t rect;
-
- _cairo_box_round_to_rectangle (src, &rect);
- return _cairo_rectangle_intersect (dst, &rect);
-}
-
#define P1x (line->p1.x)
#define P1y (line->p1.y)
#define P2x (line->p2.x)
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 0fd1dee..9cd59d4 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -955,12 +955,12 @@ _cairo_surface_fallback_fill (cairo_surface_t *surface,
info.antialias = antialias;
if (_cairo_operator_bounded_by_mask (op)) {
- cairo_box_t path_extents;
+ cairo_rectangle_int_t path_extents;
- _cairo_path_fixed_approximate_extents (path,
- tolerance,
- &path_extents);
- if (! _cairo_rectangle_intersect_box (&extents, &path_extents))
+ _cairo_path_fixed_approximate_fill_extents (path,
+ tolerance,
+ &path_extents);
+ if (! _cairo_rectangle_intersect (&extents, &path_extents))
return CAIRO_STATUS_SUCCESS;
}
diff --git a/src/cairoint.h b/src/cairoint.h
index 88945a3..e98bac0 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -259,10 +259,6 @@ _cairo_rectangle_intersect (cairo_rectangle_int_t *dst,
const cairo_rectangle_int_t *src);
cairo_private cairo_bool_t
-_cairo_rectangle_intersect_box (cairo_rectangle_int_t *dst,
- const cairo_box_t *src);
-
-cairo_private cairo_bool_t
_cairo_box_intersects_line_segment (cairo_box_t *box, cairo_line_t *line);
cairo_private cairo_bool_t
@@ -1545,8 +1541,19 @@ _cairo_path_fixed_append (cairo_path_fixed_t *path,
cairo_private void
_cairo_path_fixed_approximate_extents (cairo_path_fixed_t *path,
- double tolerance,
- cairo_box_t *extents);
+ cairo_rectangle_int_t *extents);
+
+cairo_private void
+_cairo_path_fixed_approximate_fill_extents (cairo_path_fixed_t *path,
+ double tolerance,
+ cairo_rectangle_int_t *extents);
+
+cairo_private 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_private void
_cairo_path_fixed_bounds (cairo_path_fixed_t *path,
More information about the cairo-commit
mailing list