summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cairo-clip-private.h8
-rw-r--r--src/cairo-clip.c187
-rw-r--r--src/cairo-gstate.c106
-rw-r--r--src/cairo-path-fill.c3
-rw-r--r--src/cairo-surface-fallback.c111
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;