diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cairo-clip-private.h | 8 | ||||
-rw-r--r-- | src/cairo-clip.c | 187 | ||||
-rw-r--r-- | src/cairo-gstate.c | 106 | ||||
-rw-r--r-- | src/cairo-path-fill.c | 3 | ||||
-rw-r--r-- | src/cairo-surface-fallback.c | 111 |
5 files changed, 309 insertions, 106 deletions
diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h index 8a3e867ab..d045d12e3 100644 --- a/src/cairo-clip-private.h +++ b/src/cairo-clip-private.h @@ -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, diff --git a/src/cairo-clip.c b/src/cairo-clip.c index 7aa4d5e5a..320051183 100644 --- a/src/cairo-clip.c +++ b/src/cairo-clip.c @@ -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; } diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c index 344c34cdc..e17df67a2 100644 --- a/src/cairo-gstate.c +++ b/src/cairo-gstate.c @@ -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); diff --git a/src/cairo-path-fill.c b/src/cairo-path-fill.c index b74bf0aa4..50cd2183a 100644 --- a/src/cairo-path-fill.c +++ b/src/cairo-path-fill.c @@ -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); diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c index bba26a7af..cca63846a 100644 --- a/src/cairo-surface-fallback.c +++ b/src/cairo-surface-fallback.c @@ -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,23 +352,26 @@ _clip_and_composite_source (cairo_clip_t *clip, cairo_region_t *clip_region = NULL; cairo_status_t status; - /* Create a surface that is mask IN clip */ - status = _create_composite_mask_pattern (&mask_pattern, - clip, - draw_func, draw_closure, - dst, extents); - if (unlikely (status)) - return 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, + draw_func, draw_closure, + dst, extents); + if (unlikely (status)) + return status; + /* 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; |