[clip] Eliminate redundant clips

First perform a simple geometric clip to catch the majority of cases where
an unaligned clip has been set outside the operation extents that can be
discarded without having to use an image surface.

This causes a dramatic increase of over 13x for the poppler-bug-12266
trace and little impact elsewhere for more sensible clippers.
This commit is contained in:
Chris Wilson 2009-08-24 07:06:32 +01:00
parent ff0ca6d02a
commit 85094c4eee
5 changed files with 310 additions and 107 deletions

View file

@ -79,7 +79,7 @@ cairo_private cairo_status_t
_cairo_clip_init_rectangle (cairo_clip_t *clip,
const cairo_rectangle_int_t *rect);
cairo_private void
cairo_private_no_warn cairo_clip_t *
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other);
cairo_private cairo_status_t
@ -90,6 +90,12 @@ _cairo_clip_init_copy_transformed (cairo_clip_t *clip,
cairo_private void
_cairo_clip_reset (cairo_clip_t *clip);
#define _cairo_clip_fini(clip) _cairo_clip_reset (clip)
cairo_private cairo_status_t
_cairo_clip_rectangle (cairo_clip_t *clip,
const cairo_rectangle_int_t *rectangle);
cairo_private cairo_status_t
_cairo_clip_clip (cairo_clip_t *clip,
const cairo_path_fixed_t *path,

View file

@ -205,21 +205,25 @@ _cairo_clip_set_all_clipped (cairo_clip_t *clip)
}
}
/* XXX consider accepting a matrix, no users yet. */
cairo_status_t
_cairo_clip_init_rectangle (cairo_clip_t *clip,
const cairo_rectangle_int_t *rect)
static cairo_status_t
_cairo_clip_intersect_rectangle (cairo_clip_t *clip,
const cairo_rectangle_int_t *rect)
{
cairo_clip_path_t *clip_path;
cairo_status_t status;
_cairo_clip_init (clip);
if (rect == NULL)
return CAIRO_STATUS_SUCCESS;
if (clip->path != NULL) {
cairo_box_t box;
if (rect->width == 0 || rect->height == 0) {
_cairo_clip_set_all_clipped (clip);
return CAIRO_STATUS_SUCCESS;
if (_cairo_path_fixed_is_box (&clip->path->path, &box)) {
if (box.p1.x >= _cairo_fixed_from_int (rect->x) &&
box.p1.y >= _cairo_fixed_from_int (rect->y) &&
box.p2.x <= _cairo_fixed_from_int (rect->x + rect->width) &&
box.p2.y <= _cairo_fixed_from_int (rect->y + rect->height))
{
return CAIRO_STATUS_SUCCESS;
}
}
}
clip_path = _cairo_clip_path_create (clip);
@ -257,16 +261,40 @@ _cairo_clip_init_rectangle (cairo_clip_t *clip,
return CAIRO_STATUS_SUCCESS;
}
void
/* XXX consider accepting a matrix, no users yet. */
cairo_status_t
_cairo_clip_init_rectangle (cairo_clip_t *clip,
const cairo_rectangle_int_t *rect)
{
_cairo_clip_init (clip);
if (rect == NULL)
return CAIRO_STATUS_SUCCESS;
if (rect->width == 0 || rect->height == 0) {
_cairo_clip_set_all_clipped (clip);
return CAIRO_STATUS_SUCCESS;
}
return _cairo_clip_intersect_rectangle (clip, rect);
}
cairo_clip_t *
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
{
if (other != NULL) {
clip->all_clipped = other->all_clipped;
clip->path = _cairo_clip_path_reference (other->path);
if (other->path == NULL) {
_cairo_clip_init (clip);
clip = NULL;
} else {
clip->all_clipped = other->all_clipped;
clip->path = _cairo_clip_path_reference (other->path);
}
} else {
clip->all_clipped = FALSE;
clip->path = NULL;
_cairo_clip_init (clip);
}
return clip;
}
void
@ -291,15 +319,13 @@ _cairo_clip_intersect_path (cairo_clip_t *clip,
cairo_rectangle_int_t extents;
if (clip->path != NULL) {
if (_cairo_path_fixed_equal (&clip->path->path, path)) {
if (clip->path->fill_rule == fill_rule) {
if (path->is_rectilinear ||
(tolerance == clip->path->tolerance &&
antialias == clip->path->antialias))
{
return CAIRO_STATUS_SUCCESS;
}
}
if (clip->path->fill_rule == fill_rule &&
(path->is_rectilinear ||
(tolerance == clip->path->tolerance &&
antialias == clip->path->antialias)) &&
_cairo_path_fixed_equal (&clip->path->path, path))
{
return CAIRO_STATUS_SUCCESS;
}
}
@ -369,6 +395,32 @@ _cairo_clip_clip (cairo_clip_t *clip,
antialias);
}
cairo_status_t
_cairo_clip_rectangle (cairo_clip_t *clip,
const cairo_rectangle_int_t *rectangle)
{
if (clip->all_clipped)
return CAIRO_STATUS_SUCCESS;
if (rectangle->width == 0 || rectangle->height == 0) {
_cairo_clip_set_all_clipped (clip);
return CAIRO_STATUS_SUCCESS;
}
/* if a smaller clip has already been set, ignore the new path */
if (clip->path != NULL) {
if (rectangle->x <= clip->path->extents.x &&
rectangle->y <= clip->path->extents.x &&
rectangle->x + rectangle->width >= clip->path->extents.x + clip->path->extents.width &&
rectangle->y + rectangle->height >= clip->path->extents.y + clip->path->extents.height)
{
return CAIRO_STATUS_SUCCESS;
}
}
return _cairo_clip_intersect_rectangle (clip, rectangle);
}
static cairo_status_t
_cairo_clip_path_reapply_clip_path_transform (cairo_clip_t *clip,
cairo_clip_path_t *other_path,
@ -548,6 +600,65 @@ _cairo_clip_apply_clip (cairo_clip_t *clip,
return status;
}
#if 0
static inline cairo_bool_t
_clip_paths_are_rectilinear (cairo_clip_path_t *clip_path)
{
while (clip_path != NULL) {
if (! clip_path->path.is_rectilinear)
return FALSE;
clip_path = clip_path->prev;
}
return TRUE;
}
#endif
static cairo_int_status_t
_cairo_clip_path_to_region_geometric (cairo_clip_path_t *clip_path)
{
cairo_traps_t traps;
cairo_box_t box;
cairo_status_t status;
/* If we have nothing to intersect with this path, then it cannot
* magically be reduced into a region.
*/
if (clip_path->prev == NULL)
goto UNSUPPORTED;
/* start simple... */
if (! clip_path->path.maybe_fill_region)
goto UNSUPPORTED;
_cairo_traps_init (&traps);
_cairo_box_from_rectangle (&box, &clip_path->extents);
_cairo_traps_limit (&traps, &box);
status = _cairo_path_fixed_fill_to_traps (&clip_path->prev->path,
clip_path->prev->fill_rule,
clip_path->prev->tolerance,
&traps);
if (unlikely (status))
return status;
status = _cairo_traps_extract_region (&traps, &clip_path->region);
_cairo_traps_fini (&traps);
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
goto UNSUPPORTED;
if (unlikely (status))
return status;
clip_path->flags |= CAIRO_CLIP_PATH_HAS_REGION;
return CAIRO_STATUS_SUCCESS;
UNSUPPORTED:
clip_path->flags |= CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED;
return CAIRO_INT_STATUS_UNSUPPORTED;
}
static cairo_int_status_t
_cairo_clip_path_to_region (cairo_clip_path_t *clip_path)
{
@ -563,16 +674,16 @@ _cairo_clip_path_to_region (cairo_clip_path_t *clip_path)
CAIRO_STATUS_SUCCESS;
}
if (! clip_path->path.maybe_fill_region) {
clip_path->flags |= CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED;
return CAIRO_INT_STATUS_UNSUPPORTED;
}
if (! clip_path->path.maybe_fill_region)
return _cairo_clip_path_to_region_geometric (clip_path);
/* first retrieve the region for our antecedents */
if (clip_path->prev != NULL) {
status = _cairo_clip_path_to_region (clip_path->prev);
if (status) {
clip_path->flags |= CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED;
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
return _cairo_clip_path_to_region_geometric (clip_path);
return status;
}
@ -581,7 +692,6 @@ _cairo_clip_path_to_region (cairo_clip_path_t *clip_path)
/* now extract the region for ourselves */
/* XXX just use the cheap search for now */
clip_path->region =
_cairo_path_fixed_fill_rectilinear_to_region (&clip_path->path,
clip_path->fill_rule,
@ -647,7 +757,7 @@ _cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *target)
CAIRO_CONTENT_COLOR);
status = _cairo_clip_get_region (clip, &clip_region);
if (_cairo_status_is_error (status))
if (unlikely (_cairo_status_is_error (status)))
goto BAIL;
need_translate = clip_extents->x || clip_extents->y;
@ -693,18 +803,18 @@ _cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *target)
}
while ((clip_path = clip_path->prev) != NULL) {
status = _cairo_clip_get_region (clip, &clip_region);
if (_cairo_status_is_error (status))
status = _cairo_clip_path_to_region (clip_path);
if (unlikely (_cairo_status_is_error (status)))
goto BAIL;
if (status == CAIRO_STATUS_SUCCESS) {
cairo_region_translate (clip_region,
cairo_region_translate (clip_path->region,
-clip_extents->x, -clip_extents->y);
status = _cairo_surface_fill_region (surface,
CAIRO_OPERATOR_IN,
CAIRO_COLOR_WHITE,
clip_region);
cairo_region_translate (clip_region,
clip_path->region);
cairo_region_translate (clip_path->region,
clip_extents->x, clip_extents->y);
if (unlikely (status))
goto BAIL;
@ -844,6 +954,11 @@ _cairo_clip_get_region (cairo_clip_t *clip,
if (status)
return status;
if (cairo_region_is_empty (clip->path->region)) {
_cairo_clip_set_all_clipped (clip);
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
*region = clip->path->region;
return CAIRO_STATUS_SUCCESS;
}

View file

@ -860,7 +860,10 @@ _cairo_gstate_copy_transformed_mask (cairo_gstate_t *gstate,
&gstate->ctm_inverse);
}
#define _gstate_get_clip(g) ((g)->clip.path ? &(g)->clip : NULL)
/* We need to take a copy of the clip so that the lower layers may modify it
* by, perhaps, intersecting it with the operation extents and other paths.
*/
#define _gstate_get_clip(G, C) _cairo_clip_init_copy ((C), &(G)->clip)
static cairo_bool_t
_clipped (const cairo_gstate_t *gstate)
@ -870,11 +873,12 @@ _clipped (const cairo_gstate_t *gstate)
if (gstate->clip.all_clipped)
return TRUE;
if (gstate->clip.path == NULL)
return FALSE;
if (_cairo_surface_get_extents (gstate->target, &extents)) {
if (! _cairo_rectangle_intersect (&extents,
if (extents.width == 0 || extents.height == 0)
return TRUE;
if (gstate->clip.path != NULL &&
! _cairo_rectangle_intersect (&extents,
&gstate->clip.path->extents))
{
return TRUE;
@ -888,6 +892,8 @@ cairo_status_t
_cairo_gstate_paint (cairo_gstate_t *gstate)
{
cairo_pattern_union_t pattern;
cairo_clip_t clip;
cairo_status_t status;
if (unlikely (gstate->source->status))
return gstate->source->status;
@ -897,10 +903,13 @@ _cairo_gstate_paint (cairo_gstate_t *gstate)
_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
return _cairo_surface_paint (gstate->target,
gstate->op,
&pattern.base,
_gstate_get_clip (gstate));
status = _cairo_surface_paint (gstate->target,
gstate->op,
&pattern.base,
_gstate_get_clip (gstate, &clip));
_cairo_clip_fini (&clip);
return status;
}
cairo_status_t
@ -908,6 +917,8 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
cairo_pattern_t *mask)
{
cairo_pattern_union_t source_pattern, mask_pattern;
cairo_clip_t clip;
cairo_status_t status;
if (unlikely (mask->status))
return mask->status;
@ -921,17 +932,22 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
_cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
return _cairo_surface_mask (gstate->target,
gstate->op,
&source_pattern.base,
&mask_pattern.base,
_gstate_get_clip (gstate));
status = _cairo_surface_mask (gstate->target,
gstate->op,
&source_pattern.base,
&mask_pattern.base,
_gstate_get_clip (gstate, &clip));
_cairo_clip_fini (&clip);
return status;
}
cairo_status_t
_cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
cairo_pattern_union_t source_pattern;
cairo_clip_t clip;
cairo_status_t status;
if (unlikely (gstate->source->status))
return gstate->source->status;
@ -944,16 +960,19 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
return _cairo_surface_stroke (gstate->target,
gstate->op,
&source_pattern.base,
path,
&gstate->stroke_style,
&gstate->ctm,
&gstate->ctm_inverse,
gstate->tolerance,
gstate->antialias,
_gstate_get_clip (gstate));
status = _cairo_surface_stroke (gstate->target,
gstate->op,
&source_pattern.base,
path,
&gstate->stroke_style,
&gstate->ctm,
&gstate->ctm_inverse,
gstate->tolerance,
gstate->antialias,
_gstate_get_clip (gstate, &clip));
_cairo_clip_fini (&clip);
return status;
}
cairo_status_t
@ -1018,6 +1037,8 @@ cairo_status_t
_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
{
cairo_pattern_union_t pattern;
cairo_clip_t clip;
cairo_status_t status;
if (unlikely (gstate->source->status))
return gstate->source->status;
@ -1032,22 +1053,26 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
_cairo_pattern_init_solid (&pattern.solid,
CAIRO_COLOR_TRANSPARENT,
CAIRO_CONTENT_COLOR_ALPHA);
return _cairo_surface_paint (gstate->target,
CAIRO_OPERATOR_CLEAR,
&pattern.base,
_gstate_get_clip (gstate));
status = _cairo_surface_paint (gstate->target,
CAIRO_OPERATOR_CLEAR,
&pattern.base,
_gstate_get_clip (gstate, &clip));
} else {
_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
status = _cairo_surface_fill (gstate->target,
gstate->op,
&pattern.base,
path,
gstate->fill_rule,
gstate->tolerance,
gstate->antialias,
_gstate_get_clip (gstate, &clip));
}
_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
_cairo_clip_fini (&clip);
return _cairo_surface_fill (gstate->target,
gstate->op,
&pattern.base,
path,
gstate->fill_rule,
gstate->tolerance,
gstate->antialias,
_gstate_get_clip (gstate));
return status;
}
cairo_bool_t
@ -1642,6 +1667,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
cairo_text_cluster_t stack_transformed_clusters[CAIRO_STACK_ARRAY_LENGTH (cairo_text_cluster_t)];
cairo_text_cluster_t *transformed_clusters;
cairo_status_t status;
cairo_clip_t clip;
if (unlikely (gstate->source->status))
return gstate->source->status;
@ -1711,7 +1737,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
transformed_clusters, num_clusters,
cluster_flags,
gstate->scaled_font,
_gstate_get_clip (gstate));
_gstate_get_clip (gstate, &clip));
}
else
{
@ -1731,12 +1757,14 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
CAIRO_FILL_RULE_WINDING,
gstate->tolerance,
gstate->scaled_font->options.antialias,
_gstate_get_clip (gstate));
_gstate_get_clip (gstate, &clip));
}
_cairo_path_fixed_fini (&path);
}
_cairo_clip_fini (&clip);
CLEANUP_GLYPHS:
if (transformed_glyphs != stack_transformed_glyphs)
cairo_glyph_free (transformed_glyphs);

View file

@ -157,6 +157,9 @@ _cairo_path_fixed_fill_to_traps (const cairo_path_fixed_t *path,
cairo_status_t status;
_cairo_polygon_init (&polygon);
if (traps->has_limits)
_cairo_polygon_limit (&polygon, &traps->limits);
status = _cairo_path_fixed_fill_to_polygon (path,
tolerance,
&polygon);

View file

@ -133,6 +133,9 @@ _create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern,
status = _cairo_clip_get_region (clip, &clip_region);
assert (! _cairo_status_is_error (status));
/* The all-clipped state should never propagate this far. */
assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
if (clip_region && cairo_region_num_rectangles (clip_region) == 1)
@ -349,6 +352,18 @@ _clip_and_composite_source (cairo_clip_t *clip,
cairo_region_t *clip_region = NULL;
cairo_status_t status;
if (clip != NULL) {
status = _cairo_clip_get_region (clip, &clip_region);
assert (! _cairo_status_is_error (status));
if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
return CAIRO_STATUS_SUCCESS;
/* a solitary clip rectangle is already accommodated by extents */
if (clip_region && cairo_region_num_rectangles (clip_region) == 1)
clip_region = NULL;
}
/* Create a surface that is mask IN clip */
status = _create_composite_mask_pattern (&mask_pattern,
clip,
@ -357,15 +372,6 @@ _clip_and_composite_source (cairo_clip_t *clip,
if (unlikely (status))
return status;
if (clip != NULL) {
status = _cairo_clip_get_region (clip, &clip_region);
assert (! _cairo_status_is_error (status));
/* a solitary clip rectangle is already accommodated by extents */
if (clip_region && cairo_region_num_rectangles (clip_region) == 1)
clip_region = NULL;
}
/* Compute dest' = dest OUT (mask IN clip) */
status = _cairo_surface_composite (CAIRO_OPERATOR_DEST_OUT,
&mask_pattern.base, NULL, dst,
@ -454,6 +460,8 @@ _clip_and_composite (cairo_clip_t *clip,
if (clip != NULL) {
status = _cairo_clip_get_region (clip, &clip_region);
assert (! _cairo_status_is_error (status));
if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
return CAIRO_STATUS_SUCCESS;
clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -670,9 +678,9 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src,
status = _cairo_clip_get_region (clip, &clip_region);
if (unlikely (_cairo_status_is_error (status)))
return status;
if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
return CAIRO_STATUS_SUCCESS;
/* The all-clipped state should not have been propagated this far. */
assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -785,18 +793,21 @@ _composite_spans_draw_func (void *closure,
clip_region);
}
static cairo_bool_t
static cairo_status_t
_rectangle_intersect_clip (cairo_rectangle_int_t *extents, cairo_clip_t *clip)
{
if (clip != NULL) {
const cairo_rectangle_int_t *clip_extents;
if (! _cairo_rectangle_intersect (extents,
_cairo_clip_get_extents (clip)))
{
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
clip_extents = _cairo_clip_get_extents (clip);
if (clip_extents != NULL)
return _cairo_rectangle_intersect (extents, clip_extents);
}
return _cairo_clip_rectangle (clip, extents);
} else if (_cairo_rectangle_empty (extents))
return CAIRO_INT_STATUS_NOTHING_TO_DO;
return ! _cairo_rectangle_empty (extents);
return CAIRO_STATUS_SUCCESS;
}
cairo_status_t
@ -824,17 +835,21 @@ _cairo_surface_fallback_paint (cairo_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
if (! _rectangle_intersect_clip (&extents, clip))
return CAIRO_STATUS_SUCCESS;
status = _rectangle_intersect_clip (&extents, clip);
if (status) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
status = CAIRO_STATUS_SUCCESS;
return status;
}
/* avoid the palaver of constructing traps for a simple region */
if (clip != NULL) {
status = _cairo_clip_get_region (clip, &clip_region);
if (unlikely (_cairo_status_is_error (status)))
return status;
if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
return CAIRO_STATUS_SUCCESS;
/* The all-clipped state should not have been propagated this far. */
assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -929,6 +944,7 @@ _cairo_surface_fallback_mask (cairo_surface_t *surface,
{
cairo_rectangle_int_t extents;
cairo_bool_t is_bounded;
cairo_status_t status;
is_bounded = _cairo_surface_get_extents (surface, &extents);
assert (is_bounded || clip);
@ -949,8 +965,12 @@ _cairo_surface_fallback_mask (cairo_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
if (! _rectangle_intersect_clip (&extents, clip))
return CAIRO_STATUS_SUCCESS;
status = _rectangle_intersect_clip (&extents, clip);
if (status) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
status = CAIRO_STATUS_SUCCESS;
return status;
}
return _clip_and_composite (clip, op, source,
_cairo_surface_mask_draw_func,
@ -988,8 +1008,22 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
if (! _rectangle_intersect_clip (&extents, clip))
return CAIRO_STATUS_SUCCESS;
if (_cairo_operator_bounded_by_mask (op)) {
cairo_rectangle_int_t path_extents;
_cairo_path_fixed_approximate_stroke_extents (path,
stroke_style, ctm,
&path_extents);
if (! _cairo_rectangle_intersect (&extents, &path_extents))
return CAIRO_STATUS_SUCCESS;
}
status = _rectangle_intersect_clip (&extents, clip);
if (status) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
status = CAIRO_STATUS_SUCCESS;
return status;
}
_cairo_box_from_rectangle (&box, &extents);
@ -1092,8 +1126,20 @@ _cairo_surface_fallback_fill (cairo_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
if (! _rectangle_intersect_clip (&extents, clip))
return CAIRO_STATUS_SUCCESS;
if (_cairo_operator_bounded_by_mask (op)) {
cairo_rectangle_int_t path_extents;
_cairo_path_fixed_approximate_fill_extents (path, &path_extents);
if (! _cairo_rectangle_intersect (&extents, &path_extents))
return CAIRO_STATUS_SUCCESS;
}
status = _rectangle_intersect_clip (&extents, clip);
if (status) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
status = CAIRO_STATUS_SUCCESS;
return status;
}
/* avoid the palaver of constructing traps for a simple region */
if (path->maybe_fill_region) {
@ -1104,8 +1150,9 @@ _cairo_surface_fallback_fill (cairo_surface_t *surface,
status = _cairo_clip_get_region (clip, &clip_region);
if (unlikely (_cairo_status_is_error (status)))
return status;
if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
return CAIRO_STATUS_SUCCESS;
assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
}
@ -1310,8 +1357,12 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
if (! _rectangle_intersect_clip (&extents, clip))
return CAIRO_STATUS_SUCCESS;
status = _rectangle_intersect_clip (&extents, clip);
if (status) {
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
status = CAIRO_STATUS_SUCCESS;
return status;
}
glyph_info.font = scaled_font;
glyph_info.glyphs = glyphs;