summaryrefslogtreecommitdiff
path: root/src/cairo-region.c
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <sandmann@redhat.com>2009-03-28 03:04:28 -0400
committerSøren Sandmann Pedersen <sandmann@daimi.au.dk>2009-03-28 18:02:58 -0400
commit980e9f0dbd4f21c0ccf4cc33b0b0f2f370667290 (patch)
treea4e5f58d17aa3eb93ebcfb1d0026738c3c069bd8 /src/cairo-region.c
parent64e490a464472cfe06d779503601d41972ed4518 (diff)
downloadcairo-980e9f0dbd4f21c0ccf4cc33b0b0f2f370667290.tar.gz
[region] Fix status propagation for regions
When an operation fails, store the status code in the destination region rather than leaving it unchanged.
Diffstat (limited to 'src/cairo-region.c')
-rw-r--r--src/cairo-region.c66
1 files changed, 52 insertions, 14 deletions
diff --git a/src/cairo-region.c b/src/cairo-region.c
index 55898d9c9..aec1bdf15 100644
--- a/src/cairo-region.c
+++ b/src/cairo-region.c
@@ -42,6 +42,40 @@ const cairo_region_t _cairo_region_nil = {
CAIRO_STATUS_NO_MEMORY, /* status */
};
+/**
+ * cairo_region_set_error:
+ * @region: a region
+ * @status: a status value indicating an error
+ *
+ * Atomically sets region->status to @status and calls _cairo_error;
+ * Does nothing if status is %CAIRO_STATUS_SUCCESS or any of the internal
+ * status values.
+ *
+ * All assignments of an error status to region->status should happen
+ * through cairo_region_set_error(). Note that due to the nature of
+ * the atomic operation, it is not safe to call this function on the
+ * nil objects.
+ *
+ * The purpose of this function is to allow the user to set a
+ * breakpoint in _cairo_error() to generate a stack trace for when the
+ * user causes cairo to detect an error.
+ *
+ * Return value: the error status.
+ **/
+static cairo_status_t
+cairo_region_set_error (cairo_region_t *region,
+ cairo_status_t status)
+{
+ if (status == CAIRO_STATUS_SUCCESS || status >= CAIRO_INT_STATUS_UNSUPPORTED)
+ return status;
+
+ /* Don't overwrite an existing error. This preserves the first
+ * error, which is the most significant. */
+ _cairo_status_set_error (&region->status, status);
+
+ return _cairo_error (status);
+}
+
cairo_region_t *
cairo_region_create (void)
{
@@ -172,7 +206,7 @@ cairo_region_subtract (cairo_region_t *dst, cairo_region_t *other)
return other->status;
if (!pixman_region32_subtract (&dst->rgn, &dst->rgn, &other->rgn))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_SUCCESS;
}
@@ -207,9 +241,9 @@ cairo_region_intersect (cairo_region_t *dst, cairo_region_t *other)
if (other->status)
return other->status;
-
+
if (!pixman_region32_intersect (&dst->rgn, &dst->rgn, &other->rgn))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_SUCCESS;
}
@@ -218,7 +252,7 @@ cairo_status_t
cairo_region_intersect_rectangle (cairo_region_t *dst,
const cairo_rectangle_int_t *rect)
{
- cairo_status_t result = CAIRO_STATUS_SUCCESS;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
pixman_region32_t region;
if (dst->status)
@@ -228,11 +262,11 @@ cairo_region_intersect_rectangle (cairo_region_t *dst,
rect->x, rect->y, rect->width, rect->height);
if (!pixman_region32_intersect (&dst->rgn, &dst->rgn, &region))
- result = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ status = cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY);
pixman_region32_fini (&region);
- return result;
+ return status;
}
cairo_status_t
@@ -246,7 +280,7 @@ cairo_region_union (cairo_region_t *dst,
return other->status;
if (!pixman_region32_union (&dst->rgn, &dst->rgn, &other->rgn))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_SUCCESS;
}
@@ -255,14 +289,18 @@ cairo_status_t
cairo_region_union_rectangle (cairo_region_t *dst,
const cairo_rectangle_int_t *rect)
{
- if (!pixman_region32_union_rect (&dst->rgn, &dst->rgn,
- rect->x, rect->y,
- rect->width, rect->height))
- {
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ pixman_region32_t region;
- return CAIRO_STATUS_SUCCESS;
+ pixman_region32_init_rect (&region,
+ rect->x, rect->y, rect->width, rect->height);
+
+ if (!pixman_region32_union (&dst->rgn, &dst->rgn, &region))
+ status = cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY);
+
+ pixman_region32_fini (&region);
+
+ return status;
}
cairo_bool_t