mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-01-08 15:20:24 +01:00
[path] Compute approximate extents.
When computing the bounds of the clip path, we care more for a fast result than absolute precision as the extents are only used as a guide to trim the future operations. So computing the extents of the path suffices.
This commit is contained in:
parent
b6bf047494
commit
59de6fb89e
7 changed files with 82 additions and 61 deletions
|
|
@ -283,9 +283,6 @@ _cairo_analysis_surface_intersect_clip_path (void *abstract_surface,
|
|||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_analysis_surface_t *surface = abstract_surface;
|
||||
double x1, y1, x2, y2;
|
||||
cairo_rectangle_int_t extent;
|
||||
cairo_bool_t is_empty;
|
||||
|
||||
if (path == NULL) {
|
||||
surface->current_clip.x = 0;
|
||||
|
|
@ -293,17 +290,10 @@ _cairo_analysis_surface_intersect_clip_path (void *abstract_surface,
|
|||
surface->current_clip.width = surface->width;
|
||||
surface->current_clip.height = surface->height;
|
||||
} else {
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_path_fixed_bounds (path, &x1, &y1, &x2, &y2, tolerance);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
extent.x = floor (x1);
|
||||
extent.y = floor (y1);
|
||||
extent.width = ceil (x2) - extent.x;
|
||||
extent.height = ceil (y2) - extent.y;
|
||||
cairo_rectangle_int_t extent;
|
||||
cairo_bool_t is_empty;
|
||||
|
||||
_cairo_path_fixed_approximate_extents (path, &extent);
|
||||
is_empty = _cairo_rectangle_intersect (&surface->current_clip, &extent);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -143,30 +143,11 @@ _cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t *clip_path,
|
|||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
while (clip_path) {
|
||||
cairo_status_t status;
|
||||
cairo_traps_t traps;
|
||||
cairo_box_t extents;
|
||||
cairo_rectangle_int_t extents_rect;
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
_cairo_box_from_rectangle (&extents, rectangle);
|
||||
_cairo_path_fixed_approximate_extents (&clip_path->path, &extents);
|
||||
|
||||
_cairo_traps_init (&traps);
|
||||
_cairo_traps_limit (&traps, &extents);
|
||||
|
||||
status = _cairo_path_fixed_fill_to_traps (&clip_path->path,
|
||||
clip_path->fill_rule,
|
||||
clip_path->tolerance,
|
||||
&traps);
|
||||
if (status) {
|
||||
_cairo_traps_fini (&traps);
|
||||
return status;
|
||||
}
|
||||
|
||||
_cairo_traps_extents (&traps, &extents);
|
||||
_cairo_traps_fini (&traps);
|
||||
|
||||
_cairo_box_round_to_rectangle (&extents, &extents_rect);
|
||||
if (! _cairo_rectangle_intersect (rectangle, &extents_rect))
|
||||
if (! _cairo_rectangle_intersect (rectangle, &extents))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
clip_path = clip_path->prev;
|
||||
|
|
|
|||
|
|
@ -783,20 +783,17 @@ _cairo_gstate_stroke_to_path (cairo_gstate_t *gstate)
|
|||
}
|
||||
*/
|
||||
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_gstate_path_extents (cairo_gstate_t *gstate,
|
||||
cairo_path_fixed_t *path,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2)
|
||||
{
|
||||
cairo_status_t status;
|
||||
double px1, py1, px2, py2;
|
||||
|
||||
status = _cairo_path_fixed_bounds (path,
|
||||
&px1, &py1, &px2, &py2,
|
||||
gstate->tolerance);
|
||||
if (status)
|
||||
return status;
|
||||
_cairo_path_fixed_bounds (path,
|
||||
&px1, &py1, &px2, &py2,
|
||||
gstate->tolerance);
|
||||
|
||||
_cairo_gstate_backend_to_user_rectangle (gstate,
|
||||
&px1, &py1, &px2, &py2,
|
||||
|
|
@ -809,8 +806,6 @@ _cairo_gstate_path_extents (cairo_gstate_t *gstate,
|
|||
*x2 = px2;
|
||||
if (y2)
|
||||
*y2 = py2;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
|
|||
|
|
@ -131,14 +131,68 @@ _cairo_path_bounder_line_to (void *closure, cairo_point_t *point)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_path_bounder_curve_to (void *closure,
|
||||
cairo_point_t *b,
|
||||
cairo_point_t *c,
|
||||
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;
|
||||
}
|
||||
|
||||
/* XXX: Perhaps this should compute a PixRegion rather than 4 doubles */
|
||||
cairo_status_t
|
||||
/* 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).
|
||||
*/
|
||||
void
|
||||
_cairo_path_fixed_approximate_extents (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,
|
||||
_cairo_path_bounder_close_path,
|
||||
&bounder);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
if (bounder.has_point) {
|
||||
extents->x = bounder.min_x;
|
||||
extents->y = bounder.min_y;
|
||||
extents->width = bounder.max_x - extents->x;
|
||||
extents->height = bounder.max_y - extents->y;
|
||||
} else {
|
||||
extents->x = extents->y = 0;
|
||||
extents->width = extents->height = 0;
|
||||
}
|
||||
|
||||
_cairo_path_bounder_fini (&bounder);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_path_fixed_bounds (cairo_path_fixed_t *path,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2,
|
||||
|
|
@ -155,8 +209,9 @@ _cairo_path_fixed_bounds (cairo_path_fixed_t *path,
|
|||
_cairo_path_bounder_close_path,
|
||||
&bounder,
|
||||
tolerance);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS && bounder.has_point) {
|
||||
if (bounder.has_point) {
|
||||
*x1 = _cairo_fixed_to_double (bounder.min_x);
|
||||
*y1 = _cairo_fixed_to_double (bounder.min_y);
|
||||
*x2 = _cairo_fixed_to_double (bounder.max_x);
|
||||
|
|
@ -169,6 +224,4 @@ _cairo_path_fixed_bounds (cairo_path_fixed_t *path,
|
|||
}
|
||||
|
||||
_cairo_path_bounder_fini (&bounder);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2132,11 +2132,13 @@ _cairo_surface_set_clip_region (cairo_surface_t *surface,
|
|||
|
||||
assert (surface->backend->set_clip_region != NULL);
|
||||
|
||||
status = surface->backend->set_clip_region (surface, region);
|
||||
if (unlikely (status))
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
|
||||
surface->current_clip_serial = serial;
|
||||
|
||||
status = surface->backend->set_clip_region (surface, region);
|
||||
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
|
|
|
|||
10
src/cairo.c
10
src/cairo.c
|
|
@ -1907,8 +1907,6 @@ void
|
|||
cairo_path_extents (cairo_t *cr,
|
||||
double *x1, double *y1, double *x2, double *y2)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (cr->status) {
|
||||
if (x1)
|
||||
*x1 = 0.0;
|
||||
|
|
@ -1922,11 +1920,9 @@ cairo_path_extents (cairo_t *cr,
|
|||
return;
|
||||
}
|
||||
|
||||
status = _cairo_gstate_path_extents (cr->gstate,
|
||||
cr->path,
|
||||
x1, y1, x2, y2);
|
||||
if (status)
|
||||
_cairo_set_error (cr, status);
|
||||
_cairo_gstate_path_extents (cr->gstate,
|
||||
cr->path,
|
||||
x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1139,7 +1139,7 @@ _cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate,
|
|||
double *x2, double *y2,
|
||||
cairo_bool_t *is_tight);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
cairo_private void
|
||||
_cairo_gstate_path_extents (cairo_gstate_t *gstate,
|
||||
cairo_path_fixed_t *path,
|
||||
double *x1, double *y1,
|
||||
|
|
@ -1511,7 +1511,11 @@ _cairo_path_fixed_append (cairo_path_fixed_t *path,
|
|||
const cairo_path_fixed_t *other,
|
||||
cairo_direction_t dir);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
cairo_private void
|
||||
_cairo_path_fixed_approximate_extents (cairo_path_fixed_t *path,
|
||||
cairo_rectangle_int_t *extents);
|
||||
|
||||
cairo_private void
|
||||
_cairo_path_fixed_bounds (cairo_path_fixed_t *path,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue