[cairo] Cairo and layered application
Mathias Hasselmann
mathias.hasselmann at gmx.de
Sun Mar 11 16:44:07 PDT 2007
Last version of my patch still caused some segmentation faults.
Attached patch set lets "make check" and "make perf" run without any
crashes again.
-------------- next part --------------
>From 93115b53e151eaad0e476a23864fc3301cf0cf86 Mon Sep 17 00:00:00 2001
From: (null) <(null)>
Date: Fri, 9 Mar 2007 22:37:36 +0100
Subject: [PATCH] Avoid malloc in _cairo_pixman_region_create_simple.
---
pixman/src/pixman.h | 12 ++-
pixman/src/pixregion.c | 18 +--
pixman/src/pixregionint.h | 7 +-
src/cairo-clip-private.h | 3 +-
src/cairo-clip.c | 125 ++++++++++-----------
src/cairo-region.c | 34 +++---
src/cairo-surface-fallback.c | 255 ++++++++++++++++++++++--------------------
src/cairo-surface.c | 56 ++++++----
src/cairo-traps.c | 18 ++--
src/cairoint.h | 11 +-
10 files changed, 279 insertions(+), 260 deletions(-)
diff --git a/pixman/src/pixman.h b/pixman/src/pixman.h
index 7f0ef32..8428543 100644
--- a/pixman/src/pixman.h
+++ b/pixman/src/pixman.h
@@ -113,12 +113,17 @@ extern "C" {
/* pixregion.h */
-typedef struct pixman_region16 pixman_region16_t;
+typedef struct pixman_region16_data pixman_region16_data_t;
typedef struct pixman_box16 {
short x1, y1, x2, y2;
} pixman_box16_t;
+typedef struct pixman_region16 {
+ pixman_box16_t extents;
+ pixman_region16_data_t *data;
+} pixman_region16_t;
+
typedef enum {
PIXMAN_REGION_STATUS_FAILURE,
PIXMAN_REGION_STATUS_SUCCESS
@@ -133,6 +138,11 @@ pixman_private pixman_region16_t *
pixman_region_create_simple (pixman_box16_t *extents);
pixman_private void
+pixman_region_init(pixman_region16_t *region, pixman_box16_t *extents);
+pixman_private void
+pixman_region_uninit (pixman_region16_t *region);
+
+pixman_private void
pixman_region_destroy (pixman_region16_t *region);
/* manipulation */
diff --git a/pixman/src/pixregion.c b/pixman/src/pixregion.c
index 0404dff..f710294 100644
--- a/pixman/src/pixregion.c
+++ b/pixman/src/pixregion.c
@@ -82,12 +82,6 @@ static pixman_region16_t pixman_brokenregion = { { 0, 0, 0, 0 }, &pixman_broke
static pixman_region_status_t
pixman_break (pixman_region16_t *pReg);
-static void
-pixman_init (pixman_region16_t *region, pixman_box16_t *rect);
-
-static void
-pixman_uninit (pixman_region16_t *region);
-
/*
* The functions in this file implement the Region abstraction used extensively
* throughout the X11 sample server. A Region is simply a set of disjoint
@@ -318,7 +312,7 @@ pixman_region_create_simple (pixman_box16_t *extents)
if (region == NULL)
return &pixman_brokenregion;
- pixman_init (region, extents);
+ pixman_region_init (region, extents);
return region;
}
@@ -328,8 +322,8 @@ pixman_region_create_simple (pixman_box16_t *extents)
* Outer region rect is statically allocated.
*****************************************************************/
-static void
-pixman_init(pixman_region16_t *region, pixman_box16_t *extents)
+void
+pixman_region_init(pixman_region16_t *region, pixman_box16_t *extents)
{
if (extents)
{
@@ -343,8 +337,8 @@ pixman_init(pixman_region16_t *region, pixman_box16_t *extents)
}
}
-static void
-pixman_uninit (pixman_region16_t *region)
+void
+pixman_region_uninit (pixman_region16_t *region)
{
good (region);
freeData (region);
@@ -353,7 +347,7 @@ pixman_uninit (pixman_region16_t *region)
void
pixman_region_destroy (pixman_region16_t *region)
{
- pixman_uninit (region);
+ pixman_region_uninit (region);
if (region != &pixman_brokenregion)
free (region);
diff --git a/pixman/src/pixregionint.h b/pixman/src/pixregionint.h
index b5b53fd..385a7f2 100644
--- a/pixman/src/pixregionint.h
+++ b/pixman/src/pixregionint.h
@@ -48,16 +48,11 @@ SOFTWARE.
#include "pixman.h"
-typedef struct pixman_region16_data {
+struct pixman_region16_data {
long size;
long numRects;
/* XXX: And why, exactly, do we have this bogus struct definition? */
/* pixman_box16_t rects[size]; in memory but not explicitly declared */
-} pixman_region16_data_t;
-
-struct pixman_region16 {
- pixman_box16_t extents;
- pixman_region16_data_t *data;
};
typedef struct pixman_region16_point {
diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h
index 3c4ff0d..381c003 100644
--- a/src/cairo-clip-private.h
+++ b/src/cairo-clip-private.h
@@ -72,7 +72,8 @@ struct _cairo_clip {
/*
* A clip region that can be placed in the surface
*/
- pixman_region16_t *region;
+ pixman_region16_t region;
+ cairo_bool_t has_region;
/*
* If the surface supports path clipping, we store the list of
* clipping paths that has been set here as a linked list.
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 605589b..46179d9 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -58,7 +58,7 @@ _cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
clip->serial = 0;
- clip->region = NULL;
+ clip->has_region = FALSE;
clip->path = NULL;
}
@@ -71,9 +71,10 @@ _cairo_clip_fini (cairo_clip_t *clip)
clip->serial = 0;
- if (clip->region)
- pixman_region_destroy (clip->region);
- clip->region = NULL;
+ if (clip->has_region) {
+ pixman_region_uninit (&clip->region);
+ clip->has_region = FALSE;
+ }
_cairo_clip_path_destroy (clip->path);
clip->path = NULL;
@@ -89,11 +90,11 @@ _cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
clip->serial = other->serial;
- if (other->region == NULL) {
- clip->region = other->region;
+ if (other->has_region) {
+ pixman_region_copy (&clip->region, &other->region);
+ clip->has_region = TRUE;
} else {
- clip->region = pixman_region_create ();
- pixman_region_copy (clip->region, other->region);
+ clip->has_region = FALSE;
}
clip->path = _cairo_clip_path_reference (other->path);
@@ -108,9 +109,10 @@ _cairo_clip_reset (cairo_clip_t *clip)
clip->serial = 0;
- if (clip->region)
- pixman_region_destroy (clip->region);
- clip->region = NULL;
+ if (clip->has_region) {
+ pixman_region_uninit (&clip->region);
+ clip->has_region = FALSE;
+ }
_cairo_clip_path_destroy (clip->path);
clip->path = NULL;
@@ -167,27 +169,25 @@ _cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
return status;
}
- if (clip->region) {
- pixman_region16_t *intersection;
+ if (clip->has_region) {
cairo_status_t status = CAIRO_STATUS_SUCCESS;
- pixman_region_status_t pixman_status;
+ pixman_region16_t intersection;
- intersection = _cairo_region_create_from_rectangle (rectangle);
- if (intersection == NULL)
+ if (_cairo_region_init_from_rectangle (&intersection, rectangle))
return CAIRO_STATUS_NO_MEMORY;
- pixman_status = pixman_region_intersect (intersection,
- clip->region,
- intersection);
- if (pixman_status == PIXMAN_REGION_STATUS_SUCCESS)
- _cairo_region_extents_rectangle (intersection, rectangle);
- else
+ if (PIXMAN_REGION_STATUS_SUCCESS !=
+ pixman_region_intersect (&intersection, &clip->region,
+ &intersection)) {
status = CAIRO_STATUS_NO_MEMORY;
+ } else {
+ _cairo_region_extents_rectangle (&intersection, rectangle);
+ }
- pixman_region_destroy (intersection);
+ pixman_region_uninit (&intersection);
- if (status)
- return status;
+ if (status)
+ return status;
}
if (clip->surface)
@@ -207,28 +207,24 @@ _cairo_clip_intersect_to_region (cairo_clip_t *clip,
/* Intersect clip path into region. */
}
- if (clip->region)
- pixman_region_intersect (region, clip->region, region);
+ if (clip->has_region)
+ pixman_region_intersect (region, &clip->region, region);
if (clip->surface) {
- pixman_region16_t *clip_rect;
- pixman_region_status_t pixman_status;
cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ pixman_region16_t clip_rect;
- clip_rect = _cairo_region_create_from_rectangle (&clip->surface_rect);
- if (clip_rect == NULL)
+ if (_cairo_region_init_from_rectangle (&clip_rect, &clip->surface_rect))
return CAIRO_STATUS_NO_MEMORY;
- pixman_status = pixman_region_intersect (region,
- clip_rect,
- region);
- if (pixman_status != PIXMAN_REGION_STATUS_SUCCESS)
+ if (PIXMAN_REGION_STATUS_SUCCESS !=
+ pixman_region_intersect (region, &clip_rect, region))
status = CAIRO_STATUS_NO_MEMORY;
- pixman_region_destroy (clip_rect);
+ pixman_region_uninit (&clip_rect);
- if (status)
- return status;
+ if (status)
+ return status;
}
return CAIRO_STATUS_SUCCESS;
@@ -326,42 +322,43 @@ _cairo_clip_path_destroy (cairo_clip_path_t *clip_path)
free (clip_path);
}
-static cairo_status_t
+static cairo_int_status_t
_cairo_clip_intersect_region (cairo_clip_t *clip,
cairo_traps_t *traps,
cairo_surface_t *target)
{
- pixman_region16_t *region;
- cairo_status_t status;
+ pixman_region16_t region;
+ cairo_int_status_t status;
if (clip->mode != CAIRO_CLIP_MODE_REGION)
return CAIRO_INT_STATUS_UNSUPPORTED;
status = _cairo_traps_extract_region (traps, ®ion);
+
if (status)
return status;
- if (region == NULL)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
status = CAIRO_STATUS_SUCCESS;
- if (clip->region == NULL) {
- clip->region = region;
+
+ if (!clip->has_region) {
+ pixman_region_copy (&clip->region, ®ion);
+ clip->has_region = TRUE;
} else {
- pixman_region16_t *intersection = pixman_region_create();
+ pixman_region16_t intersection;
+ pixman_region_init (&intersection, NULL);
+
+ if (PIXMAN_REGION_STATUS_SUCCESS ==
+ pixman_region_intersect (&intersection, &clip->region, ®ion)) {
+ pixman_region_copy (&clip->region, &intersection);
+ } else {
+ status = CAIRO_STATUS_NO_MEMORY;
+ }
- if (pixman_region_intersect (intersection,
- clip->region, region)
- == PIXMAN_REGION_STATUS_SUCCESS) {
- pixman_region_destroy (clip->region);
- clip->region = intersection;
- } else {
- status = CAIRO_STATUS_NO_MEMORY;
- }
- pixman_region_destroy (region);
+ pixman_region_uninit (&intersection);
}
clip->serial = _cairo_surface_allocate_clip_serial (target);
+ pixman_region_uninit (®ion);
return status;
}
@@ -506,8 +503,8 @@ _cairo_clip_translate (cairo_clip_t *clip,
cairo_fixed_t tx,
cairo_fixed_t ty)
{
- if (clip->region) {
- pixman_region_translate (clip->region,
+ if (clip->has_region) {
+ pixman_region_translate (&clip->region,
_cairo_fixed_integer_part (tx),
_cairo_fixed_integer_part (ty));
}
@@ -557,9 +554,9 @@ _cairo_clip_init_deep_copy (cairo_clip_t *clip,
/* We should reapply the original clip path in this case, and let
* whatever the right handling is happen */
} else {
- if (other->region) {
- clip->region = pixman_region_create ();
- pixman_region_copy (clip->region, other->region);
+ if (other->has_region) {
+ pixman_region_copy (&clip->region, &other->region);
+ clip->has_region = TRUE;
}
if (other->surface) {
@@ -610,16 +607,16 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
if (clip->path || clip->surface)
return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
- n_boxes = clip->region ? pixman_region_num_rects (clip->region) : 1;
+ n_boxes = clip->has_region ? pixman_region_num_rects (&clip->region) : 1;
rectangles = malloc (sizeof (cairo_rectangle_t)*n_boxes);
if (rectangles == NULL)
return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
- if (clip->region) {
+ if (clip->has_region) {
pixman_box16_t *boxes;
int i;
- boxes = pixman_region_rects (clip->region);
+ boxes = pixman_region_rects (&clip->region);
for (i = 0; i < n_boxes; ++i) {
if (!_cairo_clip_rect_to_user(gstate, boxes[i].x1, boxes[i].y1,
boxes[i].x2 - boxes[i].x1,
diff --git a/src/cairo-region.c b/src/cairo-region.c
index 057f9fe..883e1fc 100644
--- a/src/cairo-region.c
+++ b/src/cairo-region.c
@@ -36,30 +36,28 @@
#include <cairoint.h>
/**
- * _cairo_region_create_from_rectangle:
+ * _cairo_region_init_from_rectangle:
+ * @region: a #pixman_region16_t
* @rect: a #cairo_rectangle_int16_t
*
- * Creates a region with extents initialized from the given
- * rectangle.
+ * Initializes a region with extents from the given rectangle.
*
- * Return value: a newly created #pixman_region16_t or %NULL if
- * memory couldn't a allocated.
+ * Return value: #CAIRO_STATUS_SUCCESS on success, or
+ * #CAIRO_STATUS_NO_MEMORY when pixman fails to initialize
+ * the region.
**/
-pixman_region16_t *
-_cairo_region_create_from_rectangle (cairo_rectangle_int16_t *rect)
+cairo_status_t
+_cairo_region_init_from_rectangle (pixman_region16_t *region,
+ cairo_rectangle_int16_t *rect)
{
- /* We can't use pixman_region_create_simple(), because it doesn't
- * have an error return
- */
- pixman_region16_t *region = pixman_region_create ();
- if (pixman_region_union_rect (region, region,
- rect->x, rect->y,
- rect->width, rect->height) != PIXMAN_REGION_STATUS_SUCCESS) {
- pixman_region_destroy (region);
- return NULL;
- }
+ pixman_region_init (region, NULL);
+
+ if (PIXMAN_REGION_STATUS_SUCCESS == pixman_region_union_rect (
+ region, region, rect->x, rect->y, rect->width, rect->height))
+ return CAIRO_STATUS_SUCCESS;
- return region;
+ pixman_region_uninit (region);
+ return CAIRO_STATUS_NO_MEMORY;
}
/**
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 1a7d666..24c9115 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -511,145 +511,158 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
cairo_antialias_t antialias)
{
cairo_status_t status;
- pixman_region16_t *trap_region = NULL;
- pixman_region16_t *clear_region = NULL;
+ pixman_region16_t trap_region;
+ pixman_region16_t clear_region;
+ cairo_bool_t has_trap_region = FALSE;
+ cairo_bool_t has_clear_region = FALSE;
cairo_rectangle_int16_t extents;
cairo_composite_traps_info_t traps_info;
if (traps->num_traps == 0)
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_STATUS_SUCCESS;
status = _cairo_surface_get_extents (dst, &extents);
- if (status)
- return status;
- status = _cairo_traps_extract_region (traps, &trap_region);
if (status)
- return status;
+ return status;
- if (_cairo_operator_bounded_by_mask (op))
- {
- cairo_rectangle_int16_t trap_extents;
- if (trap_region) {
- status = _cairo_clip_intersect_to_region (clip, trap_region);
- if (status)
- goto out;
-
- _cairo_region_extents_rectangle (trap_region, &trap_extents);
- } else {
- cairo_box_t trap_box;
- _cairo_traps_extents (traps, &trap_box);
- _cairo_box_round_to_rectangle (&trap_box, &trap_extents);
- }
+ status = _cairo_traps_extract_region (traps, &trap_region);
- _cairo_rectangle_intersect (&extents, &trap_extents);
- status = _cairo_clip_intersect_to_rectangle (clip, &extents);
- if (status)
- goto out;
- }
- else
- {
- cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
-
- if (trap_region && !clip_surface) {
- /* If we optimize drawing with an unbounded operator to
- * _cairo_surface_fill_rectangles() or to drawing with a
- * clip region, then we have an additional region to clear.
- */
- clear_region = _cairo_region_create_from_rectangle (&extents);
- if (clear_region == NULL)
- return CAIRO_STATUS_NO_MEMORY;
-
- status = _cairo_clip_intersect_to_region (clip, clear_region);
- if (status)
- return status;
-
- _cairo_region_extents_rectangle (clear_region, &extents);
-
- if (pixman_region_subtract (clear_region, clear_region, trap_region) != PIXMAN_REGION_STATUS_SUCCESS)
- return CAIRO_STATUS_NO_MEMORY;
-
- if (!pixman_region_not_empty (clear_region)) {
- pixman_region_destroy (clear_region);
- clear_region = NULL;
- }
- } else {
- status = _cairo_clip_intersect_to_rectangle (clip, &extents);
- if (status)
- return status;
- }
+ if (CAIRO_INT_STATUS_UNSUPPORTED == status) {
+ has_trap_region = FALSE;
+ } else if (status) {
+ return status;
+ } else {
+ has_trap_region = TRUE;
}
- if (status)
- goto out;
-
- if (trap_region)
- {
- cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
-
- if ((src->type == CAIRO_PATTERN_TYPE_SOLID || op == CAIRO_OPERATOR_CLEAR) &&
- !clip_surface)
- {
- const cairo_color_t *color;
-
- if (op == CAIRO_OPERATOR_CLEAR)
- color = CAIRO_COLOR_TRANSPARENT;
- else
- color = &((cairo_solid_pattern_t *)src)->color;
-
- /* Solid rectangles special case */
- status = _cairo_surface_fill_region (dst, op, color, trap_region);
- if (!status && clear_region)
- status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
- CAIRO_COLOR_TRANSPARENT,
- clear_region);
-
- goto out;
- }
-
- if ((_cairo_operator_bounded_by_mask (op) && op != CAIRO_OPERATOR_SOURCE) ||
- !clip_surface)
- {
- /* For a simple rectangle, we can just use composite(), for more
- * rectangles, we have to set a clip region. The cost of rasterizing
- * trapezoids is pretty high for most backends currently, so it's
- * worthwhile even if a region is needed.
- *
- * If we have a clip surface, we set it as the mask; this only works
- * for bounded operators other than SOURCE; for unbounded operators,
- * clip and mask cannot be interchanged. For SOURCE, the operator
- * as implemented by the backends is different in it's handling
- * of the mask then what we want.
- *
- * CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
- * more than rectangle and the destination doesn't support clip
- * regions. In that case, we fall through.
- */
- status = _composite_trap_region (clip, src, op, dst,
- trap_region, &extents);
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- {
- if (!status && clear_region)
- status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
- CAIRO_COLOR_TRANSPARENT,
- clear_region);
- goto out;
- }
- }
+ if (_cairo_operator_bounded_by_mask (op)) {
+ cairo_rectangle_int16_t trap_extents;
+
+ if (has_trap_region) {
+ status = _cairo_clip_intersect_to_region (clip, &trap_region);
+
+ if (status)
+ goto out;
+
+ _cairo_region_extents_rectangle (&trap_region, &trap_extents);
+ } else {
+ cairo_box_t trap_box;
+ _cairo_traps_extents (traps, &trap_box);
+ _cairo_box_round_to_rectangle (&trap_box, &trap_extents);
+ }
+
+ _cairo_rectangle_intersect (&extents, &trap_extents);
+ status = _cairo_clip_intersect_to_rectangle (clip, &extents);
+
+ if (status)
+ goto out;
+ } else {
+ cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
+
+ if (has_trap_region && !clip_surface) {
+ /* If we optimize drawing with an unbounded operator to
+ * _cairo_surface_fill_rectangles() or to drawing with a
+ * clip region, then we have an additional region to clear.
+ */
+ if (_cairo_region_init_from_rectangle (&clear_region, &extents)) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto out;
+ }
+
+ has_clear_region = TRUE;
+ status = _cairo_clip_intersect_to_region (clip, &clear_region);
+
+ if (status)
+ goto out;
+
+ _cairo_region_extents_rectangle (&clear_region, &extents);
+
+ if (PIXMAN_REGION_STATUS_SUCCESS !=
+ pixman_region_subtract (&clear_region, &clear_region, &trap_region)) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto out;
+ }
+
+ if (!pixman_region_not_empty (&clear_region)) {
+ pixman_region_uninit (&clear_region);
+ has_clear_region = FALSE;
+ }
+ } else {
+ status = _cairo_clip_intersect_to_rectangle (clip, &extents);
+ }
+
+ if (status)
+ goto out;
+
+ if (has_trap_region) {
+ cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
+
+ if ((src->type == CAIRO_PATTERN_TYPE_SOLID ||
+ op == CAIRO_OPERATOR_CLEAR) && !clip_surface) {
+ const cairo_color_t *color;
+
+ if (op == CAIRO_OPERATOR_CLEAR) {
+ color = CAIRO_COLOR_TRANSPARENT;
+ } else {
+ color = &((cairo_solid_pattern_t *)src)->color;
+ }
+
+ /* Solid rectangles special case */
+ status = _cairo_surface_fill_region (dst, op, color,
+ has_trap_region ? &trap_region : NULL);
+
+ if (!status && has_clear_region)
+ status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
+ CAIRO_COLOR_TRANSPARENT,
+ &clear_region);
+
+ goto out;
+ }
+
+ if ((_cairo_operator_bounded_by_mask (op) &&
+ op != CAIRO_OPERATOR_SOURCE) || !clip_surface) {
+ /* For a simple rectangle, we can just use composite(), for more
+ * rectangles, we have to set a clip region. The cost of rasterizing
+ * trapezoids is pretty high for most backends currently, so it's
+ * worthwhile even if a region is needed.
+ *
+ * If we have a clip surface, we set it as the mask; this only works
+ * for bounded operators other than SOURCE; for unbounded operators,
+ * clip and mask cannot be interchanged. For SOURCE, the operator
+ * as implemented by the backends is different in it's handling
+ * of the mask then what we want.
+ *
+ * CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
+ * more than rectangle and the destination doesn't support clip
+ * regions. In that case, we fall through.
+ */
+ status = _composite_trap_region (clip, src, op, dst,
+ has_trap_region ? &trap_region : NULL,
+ &extents);
+
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
+ if (!status && has_clear_region)
+ status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
+ CAIRO_COLOR_TRANSPARENT,
+ &clear_region);
+ goto out;
+ }
+ }
+ }
}
traps_info.traps = traps;
traps_info.antialias = antialias;
- status = _clip_and_composite (clip, op, src,
- _composite_traps_draw_func, &traps_info,
- dst, &extents);
+ status = _clip_and_composite (clip, op, src, _composite_traps_draw_func,
+ &traps_info, dst, &extents);
- out:
- if (trap_region)
- pixman_region_destroy (trap_region);
- if (clear_region)
- pixman_region_destroy (clear_region);
+out:
+ if (has_trap_region)
+ pixman_region_uninit (&trap_region);
+ if (has_clear_region)
+ pixman_region_uninit (&clear_region);
return status;
}
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 3162a01..67df039 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1694,9 +1694,9 @@ _cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip)
clip->path,
clip->serial);
- if (clip->region)
+ if (clip->has_region)
return _cairo_surface_set_clip_region (surface,
- clip->region,
+ &clip->region,
clip->serial);
}
@@ -1859,9 +1859,11 @@ _cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst,
{
cairo_rectangle_int16_t dst_rectangle;
cairo_rectangle_int16_t drawn_rectangle;
- pixman_region16_t *drawn_region;
- pixman_region16_t *clear_region;
- cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_bool_t has_drawn_region = FALSE;
+ cairo_bool_t has_clear_region = FALSE;
+ pixman_region16_t drawn_region;
+ pixman_region16_t clear_region;
+ cairo_status_t status;
/* The area that was drawn is the area in the destination rectangle but not within
* the source or the mask.
@@ -1874,34 +1876,42 @@ _cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t *dst,
drawn_rectangle = dst_rectangle;
if (src_rectangle)
- _cairo_rectangle_intersect (&drawn_rectangle, src_rectangle);
+ _cairo_rectangle_intersect (&drawn_rectangle, src_rectangle);
if (mask_rectangle)
- _cairo_rectangle_intersect (&drawn_rectangle, mask_rectangle);
+ _cairo_rectangle_intersect (&drawn_rectangle, mask_rectangle);
/* Now compute the area that is in dst_rectangle but not in drawn_rectangle
*/
- drawn_region = _cairo_region_create_from_rectangle (&drawn_rectangle);
- clear_region = _cairo_region_create_from_rectangle (&dst_rectangle);
- if (!drawn_region || !clear_region) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto CLEANUP_REGIONS;
+ if (_cairo_region_init_from_rectangle (&drawn_region, &drawn_rectangle)) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto CLEANUP_REGIONS;
}
- if (pixman_region_subtract (clear_region, clear_region, drawn_region) != PIXMAN_REGION_STATUS_SUCCESS) {
- status = CAIRO_STATUS_NO_MEMORY;
- goto CLEANUP_REGIONS;
+ has_drawn_region = TRUE;
+
+ if (_cairo_region_init_from_rectangle (&clear_region, &dst_rectangle)) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto CLEANUP_REGIONS;
+ }
+
+ has_clear_region = TRUE;
+
+ if (PIXMAN_REGION_STATUS_SUCCESS !=
+ pixman_region_subtract (&clear_region, &clear_region, &drawn_region)) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto CLEANUP_REGIONS;
}
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_SOURCE,
- CAIRO_COLOR_TRANSPARENT,
- clear_region);
-
- CLEANUP_REGIONS:
- if (drawn_region)
- pixman_region_destroy (drawn_region);
- if (clear_region)
- pixman_region_destroy (clear_region);
+ CAIRO_COLOR_TRANSPARENT,
+ &clear_region);
+
+CLEANUP_REGIONS:
+ if (has_drawn_region)
+ pixman_region_uninit (&drawn_region);
+ if (has_clear_region)
+ pixman_region_uninit (&clear_region);
return status;
}
diff --git a/src/cairo-traps.c b/src/cairo-traps.c
index 9b3931f..6acebf8 100644
--- a/src/cairo-traps.c
+++ b/src/cairo-traps.c
@@ -935,11 +935,12 @@ _cairo_traps_extents (cairo_traps_t *traps, cairo_box_t *extents)
* Determines if a set of trapezoids are exactly representable as a
* pixman region, and if so creates such a region.
*
- * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
+ * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED
+ * or %CAIRO_STATUS_NO_MEMORY
**/
-cairo_status_t
-_cairo_traps_extract_region (cairo_traps_t *traps,
- pixman_region16_t **region)
+cairo_int_status_t
+_cairo_traps_extract_region (cairo_traps_t *traps,
+ pixman_region16_t *region)
{
int i;
@@ -950,11 +951,10 @@ _cairo_traps_extract_region (cairo_traps_t *traps,
&& _cairo_fixed_is_integer(traps->traps[i].bottom)
&& _cairo_fixed_is_integer(traps->traps[i].left.p1.x)
&& _cairo_fixed_is_integer(traps->traps[i].right.p1.x))) {
- *region = NULL;
- return CAIRO_STATUS_SUCCESS;
+ return CAIRO_INT_STATUS_UNSUPPORTED;
}
- *region = pixman_region_create ();
+ pixman_region_init (region, NULL);
for (i = 0; i < traps->num_traps; i++) {
int x = _cairo_fixed_integer_part(traps->traps[i].left.p1.x);
@@ -969,9 +969,9 @@ _cairo_traps_extract_region (cairo_traps_t *traps,
if (width == 0 || height == 0)
continue;
- if (pixman_region_union_rect (*region, *region,
+ if (pixman_region_union_rect (region, region,
x, y, width, height) != PIXMAN_REGION_STATUS_SUCCESS) {
- pixman_region_destroy (*region);
+ pixman_region_uninit (region);
return CAIRO_STATUS_NO_MEMORY;
}
}
diff --git a/src/cairoint.h b/src/cairoint.h
index 3e54857..3494a92 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2374,9 +2374,9 @@ _cairo_traps_contain (cairo_traps_t *traps, double x, double y);
cairo_private void
_cairo_traps_extents (cairo_traps_t *traps, cairo_box_t *extents);
-cairo_private cairo_status_t
-_cairo_traps_extract_region (cairo_traps_t *tr,
- pixman_region16_t **region);
+cairo_private cairo_int_status_t
+_cairo_traps_extract_region (cairo_traps_t *tr,
+ pixman_region16_t *region);
cairo_private void
_cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
@@ -2480,8 +2480,9 @@ _cairo_gstate_get_antialias (cairo_gstate_t *gstate);
/* cairo-region.c */
-cairo_private pixman_region16_t *
-_cairo_region_create_from_rectangle (cairo_rectangle_int16_t *rect);
+cairo_private cairo_status_t
+_cairo_region_init_from_rectangle (pixman_region16_t *region,
+ cairo_rectangle_int16_t *rect);
cairo_private void
_cairo_region_extents_rectangle (pixman_region16_t *region,
--
1.4.4.2
-------------- next part --------------
>From 8105eb1471775b12cc692114458bd4d2c2b76f53 Mon Sep 17 00:00:00 2001
From: Mathias Hasselmann <mathias.hasselmann at gmx.de>
Date: Sun, 11 Mar 2007 21:03:58 +0100
Subject: [PATCH] Fix infinite recursion introduced by last patch
---
src/cairo-surface-fallback.c | 93 +++++++++++++++++++++---------------------
1 files changed, 46 insertions(+), 47 deletions(-)
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 24c9115..1a0180d 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -591,71 +591,70 @@ _clip_and_composite_trapezoids (cairo_pattern_t *src,
} else {
status = _cairo_clip_intersect_to_rectangle (clip, &extents);
}
+ }
- if (status)
- goto out;
+ if (status)
+ goto out;
- if (has_trap_region) {
- cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
+ if (has_trap_region) {
+ cairo_surface_t *clip_surface = clip ? clip->surface : NULL;
+
+ if ((src->type == CAIRO_PATTERN_TYPE_SOLID ||
+ op == CAIRO_OPERATOR_CLEAR) && !clip_surface) {
+ const cairo_color_t *color;
+
+ if (op == CAIRO_OPERATOR_CLEAR) {
+ color = CAIRO_COLOR_TRANSPARENT;
+ } else {
+ color = &((cairo_solid_pattern_t *)src)->color;
+ }
+
+ /* Solid rectangles special case */
+ status = _cairo_surface_fill_region (dst, op, color, &trap_region);
- if ((src->type == CAIRO_PATTERN_TYPE_SOLID ||
- op == CAIRO_OPERATOR_CLEAR) && !clip_surface) {
- const cairo_color_t *color;
+ if (!status && has_clear_region)
+ status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
+ CAIRO_COLOR_TRANSPARENT,
+ &clear_region);
- if (op == CAIRO_OPERATOR_CLEAR) {
- color = CAIRO_COLOR_TRANSPARENT;
- } else {
- color = &((cairo_solid_pattern_t *)src)->color;
- }
+ goto out;
+ }
- /* Solid rectangles special case */
- status = _cairo_surface_fill_region (dst, op, color,
- has_trap_region ? &trap_region : NULL);
+ if ((_cairo_operator_bounded_by_mask (op) &&
+ op != CAIRO_OPERATOR_SOURCE) || !clip_surface) {
+ /* For a simple rectangle, we can just use composite(), for more
+ * rectangles, we have to set a clip region. The cost of rasterizing
+ * trapezoids is pretty high for most backends currently, so it's
+ * worthwhile even if a region is needed.
+ *
+ * If we have a clip surface, we set it as the mask; this only works
+ * for bounded operators other than SOURCE; for unbounded operators,
+ * clip and mask cannot be interchanged. For SOURCE, the operator
+ * as implemented by the backends is different in it's handling
+ * of the mask then what we want.
+ *
+ * CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
+ * more than rectangle and the destination doesn't support clip
+ * regions. In that case, we fall through.
+ */
+ status = _composite_trap_region (clip, src, op, dst,
+ &trap_region, &extents);
+ if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
if (!status && has_clear_region)
status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
CAIRO_COLOR_TRANSPARENT,
&clear_region);
-
goto out;
}
-
- if ((_cairo_operator_bounded_by_mask (op) &&
- op != CAIRO_OPERATOR_SOURCE) || !clip_surface) {
- /* For a simple rectangle, we can just use composite(), for more
- * rectangles, we have to set a clip region. The cost of rasterizing
- * trapezoids is pretty high for most backends currently, so it's
- * worthwhile even if a region is needed.
- *
- * If we have a clip surface, we set it as the mask; this only works
- * for bounded operators other than SOURCE; for unbounded operators,
- * clip and mask cannot be interchanged. For SOURCE, the operator
- * as implemented by the backends is different in it's handling
- * of the mask then what we want.
- *
- * CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
- * more than rectangle and the destination doesn't support clip
- * regions. In that case, we fall through.
- */
- status = _composite_trap_region (clip, src, op, dst,
- has_trap_region ? &trap_region : NULL,
- &extents);
-
- if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
- if (!status && has_clear_region)
- status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
- CAIRO_COLOR_TRANSPARENT,
- &clear_region);
- goto out;
- }
- }
}
}
traps_info.traps = traps;
traps_info.antialias = antialias;
- status = _clip_and_composite (clip, op, src, _composite_traps_draw_func,
+ status = _clip_and_composite (clip, op, src,
+ _composite_traps_draw_func,
&traps_info, dst, &extents);
out:
--
1.4.4.2
-------------- next part --------------
>From c34922eb803fa55efd8a3a7190390710d09a8fe8 Mon Sep 17 00:00:00 2001
From: Mathias Hasselmann <mathias.hasselmann at gmx.de>
Date: Mon, 12 Mar 2007 00:08:40 +0100
Subject: [PATCH] Make sure clip->region is always initialized
---
src/cairo-clip.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 46179d9..f63fdbb 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -58,6 +58,7 @@ _cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
clip->serial = 0;
+ pixman_region_init (&clip->region, NULL);
clip->has_region = FALSE;
clip->path = NULL;
@@ -90,6 +91,8 @@ _cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
clip->serial = other->serial;
+ pixman_region_init (&clip->region, NULL);
+
if (other->has_region) {
pixman_region_copy (&clip->region, &other->region);
clip->has_region = TRUE;
@@ -110,7 +113,12 @@ _cairo_clip_reset (cairo_clip_t *clip)
clip->serial = 0;
if (clip->has_region) {
+ /* pixman_region_uninit just releases the resources used but
+ * doesn't bother with leaving the region in a valid state.
+ * So pixman_region_init has to be called afterwards. */
pixman_region_uninit (&clip->region);
+ pixman_region_init (&clip->region, NULL);
+
clip->has_region = FALSE;
}
--
1.4.4.2
-------------- next part --------------
>From 92ddab81ecc330a852c43e7e78b632517d73db64 Mon Sep 17 00:00:00 2001
From: Mathias Hasselmann <mathias.hasselmann at gmx.de>
Date: Mon, 12 Mar 2007 00:23:42 +0100
Subject: [PATCH] Remove redundant _cairo_clip_fini function
---
src/cairo-clip-private.h | 3 ---
src/cairo-clip.c | 19 +------------------
src/cairo-gstate.c | 4 ++--
src/cairo-meta-surface.c | 2 +-
4 files changed, 4 insertions(+), 24 deletions(-)
diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h
index 381c003..ee920ae 100644
--- a/src/cairo-clip-private.h
+++ b/src/cairo-clip-private.h
@@ -85,9 +85,6 @@ cairo_private void
_cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target);
cairo_private void
-_cairo_clip_fini (cairo_clip_t *clip);
-
-cairo_private void
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other);
cairo_private void
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index f63fdbb..3a3717e 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -65,23 +65,6 @@ _cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target)
}
void
-_cairo_clip_fini (cairo_clip_t *clip)
-{
- cairo_surface_destroy (clip->surface);
- clip->surface = NULL;
-
- clip->serial = 0;
-
- if (clip->has_region) {
- pixman_region_uninit (&clip->region);
- clip->has_region = FALSE;
- }
-
- _cairo_clip_path_destroy (clip->path);
- clip->path = NULL;
-}
-
-void
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
{
clip->mode = other->mode;
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index f2d9280..daca47a 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -200,7 +200,7 @@ _cairo_gstate_fini (cairo_gstate_t *gstate)
cairo_scaled_font_destroy (gstate->scaled_font);
gstate->scaled_font = NULL;
- _cairo_clip_fini (&gstate->clip);
+ _cairo_clip_reset (&gstate->clip);
cairo_surface_destroy (gstate->target);
gstate->target = NULL;
@@ -309,7 +309,7 @@ _cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
* since its ref is now owned by gstate->parent_target */
gstate->target = cairo_surface_reference (child);
- _cairo_clip_fini (&gstate->clip);
+ _cairo_clip_reset (&gstate->clip);
_cairo_clip_init_deep_copy (&gstate->clip, &gstate->next->clip, child);
/* The clip is in surface backend coordinates for the previous target;
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index e196df2..457bfe2 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -773,7 +773,7 @@ _cairo_meta_surface_replay (cairo_surface_t *surface,
break;
}
- _cairo_clip_fini (&clip);
+ _cairo_clip_reset (&clip);
return status;
}
--
1.4.4.2
More information about the cairo
mailing list