diff options
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | src/cairo-private.h | 8 | ||||
-rw-r--r-- | src/cairo.c | 39 | ||||
-rw-r--r-- | src/cairo.h | 14 | ||||
-rw-r--r-- | test/.cvsignore | 1 | ||||
-rw-r--r-- | test/Makefile.am | 2 | ||||
-rw-r--r-- | test/error-notify.c | 108 |
7 files changed, 184 insertions, 5 deletions
@@ -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); +} |