summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
-rw-r--r--src/cairo-private.h8
-rw-r--r--src/cairo.c39
-rw-r--r--src/cairo.h14
-rw-r--r--test/.cvsignore1
-rw-r--r--test/Makefile.am2
-rw-r--r--test/error-notify.c108
7 files changed, 184 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 5039628f..3947a73e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2005-06-16 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-private.h: Reorder fields of cairo_private_t to match
+ initialization order.
+
+ * src/cairo.c: (_cairo_error): Call error_notify callback if set.
+ (cairo_create): Initialize error_notify callback to NULL.
+ (cairo_set_error_notify): New function to allow the user to set
+ an error notify callback.
+
+ * src/cairo.h: New cairo_set_error_notify prototye.
+
+ * test/.cvsignore:
+ * test/Makefile.am:
+ * test/error-notify.c: (toggle_status), (do_test), (main): New
+ test for cairo_set_error_notify.
+
2005-06-15 Carl Worth <cworth@cworth.org>
* TODO: Add CAIRO_STATUS_DESTROYED to TODO list.
diff --git a/src/cairo-private.h b/src/cairo-private.h
index a43c8ef7..d63d98b7 100644
--- a/src/cairo-private.h
+++ b/src/cairo-private.h
@@ -42,10 +42,14 @@
struct _cairo {
unsigned int ref_count;
- cairo_gstate_t *gstate;
+ cairo_status_t status;
+
+ cairo_error_notify_func_t error_notify;
+ void *error_notify_closure;
+
cairo_path_fixed_t path;
- cairo_status_t status;
+ cairo_gstate_t *gstate;
};
#endif /* CAIRO_PRIVATE_H */
diff --git a/src/cairo.c b/src/cairo.c
index c1ee8994..072bc10d 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -45,7 +45,9 @@
static const cairo_t cairo_nil = {
(unsigned int)-1, /* ref_count */
- NULL, /* gstate */
+ CAIRO_STATUS_NO_MEMORY, /* status */
+ NULL, /* error_notify */
+ NULL, /* error_notify_closure */
{ /* path */
NULL, NULL, /* op_buf_head, op_buf_tail */
NULL, NULL, /* arg_buf_head, arg_buf_tail */
@@ -53,7 +55,7 @@ static const cairo_t cairo_nil = {
{ 0, 0 }, /* current point */
FALSE, /* has_current_point */
},
- CAIRO_STATUS_NO_MEMORY /* status */
+ NULL /* gstate */
};
#include <assert.h>
@@ -87,6 +89,9 @@ _cairo_error (cairo_t *cr, cairo_status_t status)
status <= CAIRO_STATUS_LAST_STATUS);
cr->status = status;
+
+ if (cr->error_notify)
+ (cr->error_notify) (cr->error_notify_closure, status);
}
/**
@@ -131,9 +136,13 @@ cairo_create (cairo_surface_t *target)
if (cr == NULL)
return (cairo_t *) &cairo_nil;
- cr->status = CAIRO_STATUS_SUCCESS;
cr->ref_count = 1;
+ cr->status = CAIRO_STATUS_SUCCESS;
+
+ cr->error_notify = NULL;
+ cr->error_notify_closure = NULL;
+
_cairo_path_fixed_init (&cr->path);
if (target == NULL) {
@@ -2321,6 +2330,30 @@ cairo_status_to_string (cairo_status_t status)
return "<unknown error status>";
}
+/**
+ * cairo_set_error_notify:
+ * @cr: a cairo context
+ * @error_notify: an function to be called when an error occurs
+ * @closure: a closure argument to be passed to @error_notify
+ *
+ * Installs an error notifier within @cr. If an error is set within
+ * @cr, (eg. such that cairo_status(@cr) would return something other
+ * than CAIRO_STATUS_SUCCESS), then @error_notify will be called with
+ * the given @closure value as well as the #cairo_status_t value of
+ * the error.
+ *
+ * An error notifier can be cleared by passing NULL for @error_notify
+ * and for @closure.
+ **/
+void
+cairo_set_error_notify (cairo_t *cr,
+ cairo_error_notify_func_t error_notify,
+ void *closure)
+{
+ cr->error_notify = error_notify;
+ cr->error_notify_closure = closure;
+}
+
void
_cairo_restrict_value (double *value, double min, double max)
{
diff --git a/src/cairo.h b/src/cairo.h
index 0fcd8560..fe9b2e7e 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -884,6 +884,20 @@ cairo_status (cairo_t *cr);
const char *
cairo_status_to_string (cairo_status_t status);
+/**
+ * cairo_error_notify_func_t
+ *
+ * #cairo_error_notify_func_t the type of function which is called
+ * when an error is detected by cairo. It is passed a closure and the
+ * #cairo_status_t value of the error.
+ */
+typedef void (*cairo_error_notify_func_t) (void *closure, cairo_status_t status);
+
+void
+cairo_set_error_notify (cairo_t *cr,
+ cairo_error_notify_func_t error_notify,
+ void *closure);
+
/* Surface manipulation */
/**
diff --git a/test/.cvsignore b/test/.cvsignore
index 0b4c1531..d8fbef68 100644
--- a/test/.cvsignore
+++ b/test/.cvsignore
@@ -6,6 +6,7 @@ clip-nesting
clip-twice
coverage
create-for-png
+error-notify
fill-and-stroke
fill-rule
filter-nearest-offset
diff --git a/test/Makefile.am b/test/Makefile.am
index 48204192..cdefac96 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -3,6 +3,7 @@ TESTS = \
clip-nesting \
clip-twice \
create-for-png \
+error-notify \
fill-and-stroke \
fill-rule \
filter-nearest-offset \
@@ -134,6 +135,7 @@ LDADDS = libcairotest.la $(top_builddir)/src/libcairo.la
clip_nesting_LDADD = $(LDADDS)
clip_twice_LDADD = $(LDADDS)
create_for_png_LDADD = $(LDADDS)
+error_notify_LDADD = $(LDADDS)
fill_and_stroke_LDADD = $(LDADDS)
fill_rule_LDADD = $(LDADDS)
filter_nearest_offset_LDADD = $(LDADDS)
diff --git a/test/error-notify.c b/test/error-notify.c
new file mode 100644
index 00000000..0086455c
--- /dev/null
+++ b/test/error-notify.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Carl D. Worth <cworth@cworth.org>
+ */
+
+#include <stdlib.h>
+
+#include "cairo-test.h"
+
+cairo_test_t test = {
+ "error-notify",
+ "Tests calls to cairo_error_notify",
+ 0, 0
+};
+
+typedef struct test_result {
+ cairo_test_status_t status;
+} test_result_t;
+
+static void
+toggle_status (void *closure, cairo_status_t status)
+{
+ test_result_t *result = closure;
+
+ if (result->status == CAIRO_TEST_SUCCESS)
+ result->status = CAIRO_TEST_FAILURE;
+ else
+ result->status = CAIRO_TEST_SUCCESS;
+}
+
+static cairo_test_status_t
+do_test (cairo_t *cr, int width, int height)
+{
+ cairo_t *cr2;
+ test_result_t result;
+
+ /* We do all our testing in an alternate cr so that we don't leave
+ * an error in the original. */
+
+ cr2 = cairo_create (cairo_get_target (cr));
+
+ cairo_set_error_notify (cr2, toggle_status, &result);
+
+ cairo_test_log (" Testing that error notify function is called:\t\t");
+ {
+ result.status = CAIRO_TEST_FAILURE;
+ /* Trigger an error by trying to set a NULL source. */
+ cairo_set_source (cr2, NULL);
+ if (result.status != CAIRO_TEST_SUCCESS) {
+ cairo_test_log ("FAIL\n");
+ return CAIRO_TEST_FAILURE;
+ } else {
+ cairo_test_log ("PASS\n");
+ }
+ }
+
+ cairo_test_log (" Testing that cr remains in an error state:\t\t");
+ {
+ result.status = CAIRO_TEST_FAILURE;
+ cairo_move_to (cr2, 0.0, 0.0);
+ if (result.status != CAIRO_TEST_SUCCESS) {
+ cairo_test_log ("FAIL\n");
+ return CAIRO_TEST_FAILURE;
+ } else {
+ cairo_test_log ("PASS\n");
+ }
+ }
+
+ cairo_test_log (" Testing that error notify function can be cleared:\t");
+ {
+ cairo_set_error_notify (cr2, NULL, NULL);
+ cairo_set_source (cr2, NULL);
+ if (result.status != CAIRO_TEST_SUCCESS) {
+ cairo_test_log ("FAIL\n");
+ return CAIRO_TEST_FAILURE;
+ } else {
+ cairo_test_log ("PASS\n");
+ }
+ }
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test (&test, do_test);
+}