summaryrefslogtreecommitdiff
path: root/src/cairo-path-bounds.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2008-12-18 14:52:03 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2008-12-18 14:55:20 +0000
commit813cbf13ddbd3d4b708b3b362dd6c108966f44d5 (patch)
treedb9844d62b71295e5431e83da34c18304e67c1e3 /src/cairo-path-bounds.c
parentdea40e61babe608315b6d365094cf518814b134e (diff)
downloadcairo-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.c101
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);