diff options
Diffstat (limited to 'src/cairo.c')
-rw-r--r-- | src/cairo.c | 778 |
1 files changed, 467 insertions, 311 deletions
diff --git a/src/cairo.c b/src/cairo.c index f825c733e..73dfc2cdd 100644 --- a/src/cairo.c +++ b/src/cairo.c @@ -43,37 +43,56 @@ #define CAIRO_TOLERANCE_MINIMUM 0.0002 /* We're limited by 16 bits of sub-pixel precision */ +static const cairo_t cairo_nil = { + (unsigned int)-1, /* ref_count */ + CAIRO_STATUS_NO_MEMORY, /* status */ + { /* path */ + NULL, NULL, /* op_buf_head, op_buf_tail */ + NULL, NULL, /* arg_buf_head, arg_buf_tail */ + { 0, 0 }, /* last_move_point */ + { 0, 0 }, /* current point */ + FALSE, /* has_current_point */ + }, + NULL /* gstate */ +}; + #include <assert.h> -#ifdef NDEBUG -#define CAIRO_CHECK_SANITY(cr) -#else -static int -cairo_sane_state (cairo_t *cr) -{ - if (cr == NULL) - return 0; - switch (cr->status) { - case CAIRO_STATUS_SUCCESS: - case CAIRO_STATUS_NO_MEMORY: - case CAIRO_STATUS_INVALID_RESTORE: - case CAIRO_STATUS_INVALID_POP_GROUP: - case CAIRO_STATUS_NO_CURRENT_POINT: - case CAIRO_STATUS_INVALID_MATRIX: - case CAIRO_STATUS_NO_TARGET_SURFACE: - case CAIRO_STATUS_NULL_POINTER: - case CAIRO_STATUS_INVALID_STRING: - case CAIRO_STATUS_INVALID_PATH_DATA: - break; - default: - return 0; - } - return 1; +/* This has to be updated whenever cairo_status_t is extended. That's + * a bit of a pain, but it should be easy to always catch as long as + * one adds a new test case to test a trigger of the new status value. + */ +#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_SURFACE_TYPE_MISMATCH + +/** + * _cairo_error: + * @cr: a cairo context + * @status: a status value indicating an error, (eg. not + * CAIRO_STATUS_SUCCESS) + * + * Sets cr->status to @status. + * + * All assignments of an error status to cr->status should happen + * either inside of _cairo_error(), or else _cairo_error() should be + * called immediately after the assignment. + * + * 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. + * + * _cairo_error also calls the error notify callback function that the + * user may have set with cairo_set_error_notify. + **/ +static void +_cairo_error (cairo_t *cr, cairo_status_t status) +{ + assert (status > CAIRO_STATUS_SUCCESS && + status <= CAIRO_STATUS_LAST_STATUS); + + cr->status = status; } -#define CAIRO_CHECK_SANITY(cr) assert(cairo_sane_state ((cr))) -#endif -/* +/** * cairo_create: * @target: target surface for the context * @@ -81,7 +100,7 @@ cairo_sane_state (cairo_t *cr) * default values and with @target as a target surface. The target * surface should be constructed with a backend-specific function such * as cairo_image_surface_create (or any other - * cairo_<backend>_surface_create variant). + * cairo_<backend>_surface_create variant). * * This function references @target, so you can immediately * call cairo_surface_destroy() on it if you don't need to @@ -100,7 +119,12 @@ cairo_sane_state (cairo_t *cr) * Return value: a newly allocated #cairo_t with a reference * count of 1. The initial reference count should be released * with cairo_destroy() when you are done using the #cairo_t. - */ + * This function never returns %NULL. If memory cannot be + * allocated, a special #cairo_t object will be returned on + * which cairo_status() returns %CAIRO_STATUS_NO_MEMORY. + * You can use this object normally, but no drawing will + * be done. + **/ cairo_t * cairo_create (cairo_surface_t *target) { @@ -108,24 +132,24 @@ cairo_create (cairo_surface_t *target) cr = malloc (sizeof (cairo_t)); if (cr == NULL) - return NULL; + return (cairo_t *) &cairo_nil; - cr->status = CAIRO_STATUS_SUCCESS; cr->ref_count = 1; + cr->status = CAIRO_STATUS_SUCCESS; + _cairo_path_fixed_init (&cr->path); if (target == NULL) { cr->gstate = NULL; - cr->status = CAIRO_STATUS_NULL_POINTER; + _cairo_error (cr, CAIRO_STATUS_NULL_POINTER); return cr; } cr->gstate = _cairo_gstate_create (target); if (cr->gstate == NULL) - cr->status = CAIRO_STATUS_NO_MEMORY; + _cairo_error (cr, CAIRO_STATUS_NO_MEMORY); - CAIRO_CHECK_SANITY (cr); return cr; } @@ -140,12 +164,10 @@ cairo_create (cairo_surface_t *target) void cairo_reference (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->ref_count == (unsigned int)-1) return; - + cr->ref_count++; - CAIRO_CHECK_SANITY (cr); } /** @@ -159,7 +181,9 @@ cairo_reference (cairo_t *cr) void cairo_destroy (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); + if (cr->ref_count == (unsigned int)-1) + return; + cr->ref_count--; if (cr->ref_count) return; @@ -197,21 +221,20 @@ cairo_save (cairo_t *cr) { cairo_gstate_t *top; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } top = _cairo_gstate_clone (cr->gstate); if (top == NULL) { - cr->status = CAIRO_STATUS_NO_MEMORY; - CAIRO_CHECK_SANITY (cr); + _cairo_error (cr, CAIRO_STATUS_NO_MEMORY); return; } top->next = cr->gstate; cr->gstate = top; - CAIRO_CHECK_SANITY (cr); } slim_hidden_def(cairo_save); @@ -228,9 +251,10 @@ cairo_restore (cairo_t *cr) { cairo_gstate_t *top; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } top = cr->gstate; cr->gstate = top->next; @@ -238,12 +262,7 @@ cairo_restore (cairo_t *cr) _cairo_gstate_destroy (top); if (cr->gstate == NULL) - cr->status = CAIRO_STATUS_INVALID_RESTORE; - - if (cr->status) - return; - - CAIRO_CHECK_SANITY (cr); + _cairo_error (cr, CAIRO_STATUS_INVALID_RESTORE); } slim_hidden_def(cairo_restore); @@ -291,12 +310,26 @@ cairo_pop_group (cairo_t *cr) void cairo_set_operator (cairo_t *cr, cairo_operator_t op) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_set_operator (cr->gstate, op); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); +} + +static void +_cairo_set_source_solid (cairo_t *cr, const cairo_color_t *color) +{ + cairo_pattern_t *source; + + source = _cairo_pattern_create_solid (color); + + cairo_set_source (cr, source); + + cairo_pattern_destroy (source); } /** @@ -319,9 +352,10 @@ cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue) { cairo_color_t color; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } _cairo_restrict_value (&red, 0.0, 1.0); _cairo_restrict_value (&green, 0.0, 1.0); @@ -329,9 +363,7 @@ cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue) _cairo_color_init_rgb (&color, red, green, blue); - cr->status = _cairo_gstate_set_source_solid (cr->gstate, &color); - - CAIRO_CHECK_SANITY (cr); + _cairo_set_source_solid (cr, &color); } /** @@ -357,9 +389,10 @@ cairo_set_source_rgba (cairo_t *cr, { cairo_color_t color; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } _cairo_restrict_value (&red, 0.0, 1.0); _cairo_restrict_value (&green, 0.0, 1.0); @@ -368,9 +401,7 @@ cairo_set_source_rgba (cairo_t *cr, _cairo_color_init_rgba (&color, red, green, blue, alpha); - cr->status = _cairo_gstate_set_source_solid (cr->gstate, &color); - - CAIRO_CHECK_SANITY (cr); + _cairo_set_source_solid (cr, &color); } void @@ -382,23 +413,18 @@ cairo_set_source_surface (cairo_t *cr, cairo_pattern_t *pattern; cairo_matrix_t matrix; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } pattern = cairo_pattern_create_for_surface (surface); - if (!pattern) { - cr->status = CAIRO_STATUS_NO_MEMORY; - return; - } cairo_matrix_init_translate (&matrix, -x, -y); cairo_pattern_set_matrix (pattern, &matrix); cairo_set_source (cr, pattern); cairo_pattern_destroy (pattern); - - CAIRO_CHECK_SANITY (cr); } /** @@ -418,12 +444,24 @@ cairo_set_source_surface (cairo_t *cr, void cairo_set_source (cairo_t *cr, cairo_pattern_t *source) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); + return; + } + + if (source == NULL) { + _cairo_error (cr, CAIRO_STATUS_NULL_POINTER); + return; + } + + if (source->status) { + _cairo_error (cr, source->status); return; + } cr->status = _cairo_gstate_set_source (cr->gstate, source); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -439,11 +477,12 @@ cairo_set_source (cairo_t *cr, cairo_pattern_t *source) cairo_pattern_t * cairo_get_source (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); - /* XXX: We'll want to do something like this: - if (cr->status) - return cairo_pattern_nil; - */ + if (cr->status) { + cairo_pattern_t *pattern; + pattern = _cairo_pattern_create_in_error (cr->status); + _cairo_error (cr, cr->status); + return pattern; + } return _cairo_gstate_get_source (cr->gstate); } @@ -464,14 +503,16 @@ cairo_get_source (cairo_t *cr) void cairo_set_tolerance (cairo_t *cr, double tolerance) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } _cairo_restrict_value (&tolerance, CAIRO_TOLERANCE_MINIMUM, tolerance); cr->status = _cairo_gstate_set_tolerance (cr->gstate, tolerance); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -488,12 +529,14 @@ cairo_set_tolerance (cairo_t *cr, double tolerance) void cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_set_fill_rule (cr->gstate, fill_rule); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -513,14 +556,16 @@ cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule) void cairo_set_line_width (cairo_t *cr, double width) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } _cairo_restrict_value (&width, 0.0, width); cr->status = _cairo_gstate_set_line_width (cr->gstate, width); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -540,12 +585,14 @@ cairo_set_line_width (cairo_t *cr, double width) void cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_set_line_cap (cr->gstate, line_cap); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -565,34 +612,40 @@ cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap) void cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_set_line_join (cr->gstate, line_join); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } void cairo_set_dash (cairo_t *cr, double *dashes, int ndash, double offset) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_set_dash (cr->gstate, dashes, ndash, offset); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } void cairo_set_miter_limit (cairo_t *cr, double limit) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_set_miter_limit (cr->gstate, limit); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } @@ -611,12 +664,14 @@ cairo_set_miter_limit (cairo_t *cr, double limit) void cairo_translate (cairo_t *cr, double tx, double ty) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_translate (cr->gstate, tx, ty); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -633,12 +688,14 @@ cairo_translate (cairo_t *cr, double tx, double ty) void cairo_scale (cairo_t *cr, double sx, double sy) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_scale (cr->gstate, sx, sy); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } @@ -657,12 +714,14 @@ cairo_scale (cairo_t *cr, double sx, double sy) void cairo_rotate (cairo_t *cr, double angle) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_rotate (cr->gstate, angle); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -678,12 +737,14 @@ void cairo_transform (cairo_t *cr, const cairo_matrix_t *matrix) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_transform (cr->gstate, matrix); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -698,12 +759,14 @@ void cairo_set_matrix (cairo_t *cr, const cairo_matrix_t *matrix) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_set_matrix (cr->gstate, matrix); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -718,12 +781,14 @@ cairo_set_matrix (cairo_t *cr, void cairo_identity_matrix (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_identity_matrix (cr->gstate); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -739,12 +804,14 @@ cairo_identity_matrix (cairo_t *cr) void cairo_user_to_device (cairo_t *cr, double *x, double *y) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_user_to_device (cr->gstate, x, y); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -761,12 +828,14 @@ cairo_user_to_device (cairo_t *cr, double *x, double *y) void cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_user_to_device_distance (cr->gstate, dx, dy); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -782,12 +851,14 @@ cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy) void cairo_device_to_user (cairo_t *cr, double *x, double *y) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_device_to_user (cr->gstate, x, y); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -804,24 +875,25 @@ cairo_device_to_user (cairo_t *cr, double *x, double *y) void cairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_device_to_user_distance (cr->gstate, dx, dy); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } void cairo_new_path (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } _cairo_path_fixed_fini (&cr->path); - - CAIRO_CHECK_SANITY (cr); } slim_hidden_def(cairo_new_path); @@ -830,17 +902,18 @@ cairo_move_to (cairo_t *cr, double x, double y) { cairo_fixed_t x_fixed, y_fixed; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } _cairo_gstate_user_to_backend (cr->gstate, &x, &y); x_fixed = _cairo_fixed_from_double (x); y_fixed = _cairo_fixed_from_double (y); cr->status = _cairo_path_fixed_move_to (&cr->path, x_fixed, y_fixed); - - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } slim_hidden_def(cairo_move_to); @@ -849,17 +922,18 @@ cairo_line_to (cairo_t *cr, double x, double y) { cairo_fixed_t x_fixed, y_fixed; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } _cairo_gstate_user_to_backend (cr->gstate, &x, &y); x_fixed = _cairo_fixed_from_double (x); y_fixed = _cairo_fixed_from_double (y); cr->status = _cairo_path_fixed_line_to (&cr->path, x_fixed, y_fixed); - - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } void @@ -872,9 +946,10 @@ cairo_curve_to (cairo_t *cr, cairo_fixed_t x2_fixed, y2_fixed; cairo_fixed_t x3_fixed, y3_fixed; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } _cairo_gstate_user_to_backend (cr->gstate, &x1, &y1); _cairo_gstate_user_to_backend (cr->gstate, &x2, &y2); @@ -893,8 +968,8 @@ cairo_curve_to (cairo_t *cr, x1_fixed, y1_fixed, x2_fixed, y2_fixed, x3_fixed, y3_fixed); - - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -936,9 +1011,10 @@ cairo_arc (cairo_t *cr, double radius, double angle1, double angle2) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } /* Do nothing, successfully, if radius is <= 0 */ if (radius <= 0.0) @@ -953,8 +1029,6 @@ cairo_arc (cairo_t *cr, _cairo_arc_path (cr, xc, yc, radius, angle1, angle2); - - CAIRO_CHECK_SANITY (cr); } /** @@ -977,9 +1051,10 @@ cairo_arc_negative (cairo_t *cr, double radius, double angle1, double angle2) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } /* Do nothing, successfully, if radius is <= 0 */ if (radius <= 0.0) @@ -994,8 +1069,6 @@ cairo_arc_negative (cairo_t *cr, _cairo_arc_path_negative (cr, xc, yc, radius, angle1, angle2); - - CAIRO_CHECK_SANITY (cr); } /* XXX: NYI @@ -1020,17 +1093,18 @@ cairo_rel_move_to (cairo_t *cr, double dx, double dy) { cairo_fixed_t dx_fixed, dy_fixed; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy); dx_fixed = _cairo_fixed_from_double (dx); dy_fixed = _cairo_fixed_from_double (dy); cr->status = _cairo_path_fixed_rel_move_to (&cr->path, dx_fixed, dy_fixed); - - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } void @@ -1038,17 +1112,18 @@ cairo_rel_line_to (cairo_t *cr, double dx, double dy) { cairo_fixed_t dx_fixed, dy_fixed; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy); dx_fixed = _cairo_fixed_from_double (dx); dy_fixed = _cairo_fixed_from_double (dy); cr->status = _cairo_path_fixed_rel_line_to (&cr->path, dx_fixed, dy_fixed); - - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } slim_hidden_def(cairo_rel_line_to); @@ -1062,9 +1137,10 @@ cairo_rel_curve_to (cairo_t *cr, cairo_fixed_t dx2_fixed, dy2_fixed; cairo_fixed_t dx3_fixed, dy3_fixed; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } _cairo_gstate_user_to_device_distance (cr->gstate, &dx1, &dy1); _cairo_gstate_user_to_device_distance (cr->gstate, &dx2, &dy2); @@ -1083,8 +1159,8 @@ cairo_rel_curve_to (cairo_t *cr, dx1_fixed, dy1_fixed, dx2_fixed, dy2_fixed, dx3_fixed, dy3_fixed); - - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } void @@ -1092,16 +1168,16 @@ cairo_rectangle (cairo_t *cr, double x, double y, double width, double height) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cairo_move_to (cr, x, y); cairo_rel_line_to (cr, width, 0); cairo_rel_line_to (cr, 0, height); cairo_rel_line_to (cr, -width, 0); cairo_close_path (cr); - CAIRO_CHECK_SANITY (cr); } /* XXX: NYI @@ -1112,19 +1188,22 @@ cairo_stroke_to_path (cairo_t *cr) return; cr->status = _cairo_gstate_stroke_path (cr->gstate); + if (cr->status) + _cairo_error (cr, cr->status); } */ void cairo_close_path (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_path_fixed_close_path (&cr->path); - - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } slim_hidden_def(cairo_close_path); @@ -1138,13 +1217,14 @@ slim_hidden_def(cairo_close_path); void cairo_paint (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_paint (cr->gstate); - - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -1164,18 +1244,24 @@ cairo_paint_with_alpha (cairo_t *cr, cairo_color_t color; cairo_pattern_union_t pattern; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } + + if (CAIRO_ALPHA_IS_OPAQUE (alpha)) { + cairo_paint (cr); + return; + } _cairo_color_init_rgba (&color, 1., 1., 1., alpha); _cairo_pattern_init_solid (&pattern.solid, &color); cr->status = _cairo_gstate_mask (cr->gstate, &pattern.base); + if (cr->status) + _cairo_error (cr, cr->status); _cairo_pattern_fini (&pattern.base); - - CAIRO_CHECK_SANITY (cr); } /** @@ -1192,13 +1278,24 @@ void cairo_mask (cairo_t *cr, cairo_pattern_t *pattern) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } - cr->status = _cairo_gstate_mask (cr->gstate, pattern); + if (pattern == NULL) { + _cairo_error (cr, CAIRO_STATUS_NULL_POINTER); + return; + } + + if (pattern->status) { + _cairo_error (cr, pattern->status); + return; + } - CAIRO_CHECK_SANITY (cr); + cr->status = _cairo_gstate_mask (cr->gstate, pattern); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -1222,15 +1319,12 @@ cairo_mask_surface (cairo_t *cr, cairo_pattern_t *pattern; cairo_matrix_t matrix; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } pattern = cairo_pattern_create_for_surface (surface); - if (!pattern) { - cr->status = CAIRO_STATUS_NO_MEMORY; - return; - } cairo_matrix_init_translate (&matrix, - surface_x, - surface_y); cairo_pattern_set_matrix (pattern, &matrix); @@ -1275,13 +1369,14 @@ cairo_stroke (cairo_t *cr) void cairo_stroke_preserve (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_stroke (cr->gstate, &cr->path); - - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } slim_hidden_def(cairo_stroke_preserve); @@ -1315,36 +1410,41 @@ cairo_fill (cairo_t *cr) void cairo_fill_preserve (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_fill (cr->gstate, &cr->path); - - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } slim_hidden_def(cairo_fill_preserve); void cairo_copy_page (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_copy_page (cr->gstate); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } void cairo_show_page (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_show_page (cr->gstate); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } cairo_bool_t @@ -1352,18 +1452,18 @@ cairo_in_stroke (cairo_t *cr, double x, double y) { int inside; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return 0; + } cr->status = _cairo_gstate_in_stroke (cr->gstate, &cr->path, x, y, &inside); - - CAIRO_CHECK_SANITY (cr); - - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return 0; + } return inside; } @@ -1373,18 +1473,18 @@ cairo_in_fill (cairo_t *cr, double x, double y) { int inside; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return 0; + } cr->status = _cairo_gstate_in_fill (cr->gstate, &cr->path, x, y, &inside); - - CAIRO_CHECK_SANITY (cr); - - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return 0; + } return inside; } @@ -1393,28 +1493,32 @@ void cairo_stroke_extents (cairo_t *cr, double *x1, double *y1, double *x2, double *y2) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_stroke_extents (cr->gstate, &cr->path, x1, y1, x2, y2); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } void cairo_fill_extents (cairo_t *cr, double *x1, double *y1, double *x2, double *y2) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_fill_extents (cr->gstate, &cr->path, x1, y1, x2, y2); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -1472,12 +1576,14 @@ cairo_clip (cairo_t *cr) void cairo_clip_preserve (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_clip (cr->gstate, &cr->path); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } slim_hidden_def(cairo_clip_preserve); @@ -1500,12 +1606,14 @@ slim_hidden_def(cairo_clip_preserve); void cairo_reset_clip (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_reset_clip (cr->gstate); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -1529,12 +1637,14 @@ cairo_select_font_face (cairo_t *cr, cairo_font_slant_t slant, cairo_font_weight_t weight) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_select_font_face (cr->gstate, family, slant, weight); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -1546,19 +1656,27 @@ cairo_select_font_face (cairo_t *cr, * Return value: the current font object. Can return %NULL * on out-of-memory or if the context is already in * an error state. This object is owned by cairo. To keep - * a reference to it, you must call cairo_font_reference(). + * a reference to it, you must call cairo_font_face_reference(). **/ cairo_font_face_t * cairo_get_font_face (cairo_t *cr) { cairo_font_face_t *font_face; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return NULL; + } cr->status = _cairo_gstate_get_font_face (cr->gstate, &font_face); - CAIRO_CHECK_SANITY (cr); + if (cr->status) { + _cairo_error (cr, cr->status); + /* XXX: When available: + return _cairo_font_face_create_in_error (cr->status); + */ + return NULL; + } + return font_face; } @@ -1574,12 +1692,14 @@ void cairo_font_extents (cairo_t *cr, cairo_font_extents_t *extents) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_get_font_extents (cr->gstate, extents); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -1595,12 +1715,14 @@ void cairo_set_font_face (cairo_t *cr, cairo_font_face_t *font_face) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_set_font_face (cr->gstate, font_face); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -1617,12 +1739,14 @@ cairo_set_font_face (cairo_t *cr, void cairo_set_font_size (cairo_t *cr, double size) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_set_font_size (cr->gstate, size); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -1642,12 +1766,14 @@ void cairo_set_font_matrix (cairo_t *cr, const cairo_matrix_t *matrix) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_set_font_matrix (cr->gstate, matrix); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -1661,7 +1787,6 @@ cairo_set_font_matrix (cairo_t *cr, void cairo_get_font_matrix (cairo_t *cr, cairo_matrix_t *matrix) { - CAIRO_CHECK_SANITY (cr); _cairo_gstate_get_font_matrix (cr->gstate, matrix); } @@ -1694,9 +1819,10 @@ cairo_text_extents (cairo_t *cr, int num_glyphs; double x, y; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } if (utf8 == NULL) { extents->x_bearing = 0.0; @@ -1713,19 +1839,20 @@ cairo_text_extents (cairo_t *cr, cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8, x, y, &glyphs, &num_glyphs); - CAIRO_CHECK_SANITY (cr); if (cr->status) { if (glyphs) free (glyphs); + _cairo_error (cr, cr->status); return; } cr->status = _cairo_gstate_glyph_extents (cr->gstate, glyphs, num_glyphs, extents); - CAIRO_CHECK_SANITY (cr); - if (glyphs) free (glyphs); + + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -1752,13 +1879,15 @@ cairo_glyph_extents (cairo_t *cr, int num_glyphs, cairo_text_extents_t *extents) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_glyph_extents (cr->gstate, glyphs, num_glyphs, extents); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } void @@ -1768,9 +1897,10 @@ cairo_show_text (cairo_t *cr, const char *utf8) int num_glyphs; double x, y; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } if (utf8 == NULL) return; @@ -1780,30 +1910,34 @@ cairo_show_text (cairo_t *cr, const char *utf8) cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8, x, y, &glyphs, &num_glyphs); - CAIRO_CHECK_SANITY (cr); if (cr->status) { if (glyphs) free (glyphs); + _cairo_error (cr, cr->status); return; } cr->status = _cairo_gstate_show_glyphs (cr->gstate, glyphs, num_glyphs); - CAIRO_CHECK_SANITY (cr); if (glyphs) free (glyphs); + + if (cr->status) + _cairo_error (cr, cr->status); } void cairo_show_glyphs (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_show_glyphs (cr->gstate, glyphs, num_glyphs); - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } void @@ -1813,44 +1947,48 @@ cairo_text_path (cairo_t *cr, const char *utf8) int num_glyphs; double x, y; - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cairo_get_current_point (cr, &x, &y); cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8, x, y, &glyphs, &num_glyphs); - CAIRO_CHECK_SANITY (cr); if (cr->status) { if (glyphs) free (glyphs); + _cairo_error (cr, cr->status); return; } cr->status = _cairo_gstate_glyph_path (cr->gstate, glyphs, num_glyphs, &cr->path); - CAIRO_CHECK_SANITY (cr); - if (glyphs) free (glyphs); + + if (cr->status) + _cairo_error (cr, cr->status); + } void cairo_glyph_path (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } cr->status = _cairo_gstate_glyph_path (cr->gstate, glyphs, num_glyphs, &cr->path); - - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } /** @@ -1864,7 +2002,6 @@ cairo_glyph_path (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs) cairo_operator_t cairo_get_operator (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); return _cairo_gstate_get_operator (cr->gstate); } @@ -1879,7 +2016,6 @@ cairo_get_operator (cairo_t *cr) double cairo_get_tolerance (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); return _cairo_gstate_get_tolerance (cr->gstate); } @@ -1911,8 +2047,6 @@ cairo_get_current_point (cairo_t *cr, double *x_ret, double *y_ret) cairo_fixed_t x_fixed, y_fixed; double x, y; - CAIRO_CHECK_SANITY (cr); - status = _cairo_path_fixed_get_current_point (&cr->path, &x_fixed, &y_fixed); if (status == CAIRO_STATUS_NO_CURRENT_POINT) { x = 0.0; @@ -1927,8 +2061,6 @@ cairo_get_current_point (cairo_t *cr, double *x_ret, double *y_ret) *x_ret = x; if (y_ret) *y_ret = y; - - CAIRO_CHECK_SANITY (cr); } slim_hidden_def(cairo_get_current_point); @@ -1943,7 +2075,6 @@ slim_hidden_def(cairo_get_current_point); cairo_fill_rule_t cairo_get_fill_rule (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); return _cairo_gstate_get_fill_rule (cr->gstate); } @@ -1958,7 +2089,6 @@ cairo_get_fill_rule (cairo_t *cr) double cairo_get_line_width (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); return _cairo_gstate_get_line_width (cr->gstate); } @@ -1973,7 +2103,6 @@ cairo_get_line_width (cairo_t *cr) cairo_line_cap_t cairo_get_line_cap (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); return _cairo_gstate_get_line_cap (cr->gstate); } @@ -1988,7 +2117,6 @@ cairo_get_line_cap (cairo_t *cr) cairo_line_join_t cairo_get_line_join (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); return _cairo_gstate_get_line_join (cr->gstate); } @@ -2003,7 +2131,6 @@ cairo_get_line_join (cairo_t *cr) double cairo_get_miter_limit (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); return _cairo_gstate_get_miter_limit (cr->gstate); } @@ -2017,7 +2144,6 @@ cairo_get_miter_limit (cairo_t *cr) void cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix) { - CAIRO_CHECK_SANITY (cr); _cairo_gstate_get_matrix (cr->gstate, matrix); } @@ -2030,14 +2156,18 @@ cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix) * * Return value: the target surface, (or NULL if @cr is in an error * state). This object is owned by cairo. To keep a reference to it, - * you must call cairo_pattern_reference(). + * you must call cairo_surface_reference(). **/ cairo_surface_t * cairo_get_target (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); + /* XXX: Should be as follows when available: + return _cairo_surface_create_in_error (); + */ return NULL; + } return _cairo_gstate_get_target (cr->gstate); } @@ -2053,13 +2183,25 @@ cairo_get_target (cairo_t *cr) * Return value: the copy of the current path. The caller owns the * returned object and should call cairo_path_destroy() when finished * with it. + * + * This function will always return a valid pointer, but the result + * will have no data, (data==NULL and num_data==0), if either of the + * following conditions hold: + * + * 1) If there is insufficient memory to copy the path. In this case + * path->status will be set to CAIRO_STATUS_NO_MEMORY. + * + * 2) If @cr is already in an error state. In this case path->status + * will contain the same status that would be returned by + * cairo_status(cr). **/ cairo_path_t * cairo_copy_path (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) - return &_cairo_path_nil; + if (cr->status) { + _cairo_error (cr, cr->status); + return _cairo_path_data_create_in_error (cr->status); + } return _cairo_path_data_create (&cr->path, cr->gstate); } @@ -2082,15 +2224,25 @@ cairo_copy_path (cairo_t *cr) * Return value: the copy of the current path. The caller owns the * returned object and should call cairo_path_destroy() when finished * with it. + * + * This function will always return a valid pointer, but the result + * will have no data, (data==NULL and num_data==0), if either of the + * following conditions hold: + * + * 1) If there is insufficient memory to copy the path. In this case + * path->status will be set to CAIRO_STATUS_NO_MEMORY. + * + * 2) If @cr is already in an error state. In this case path->status + * will contain the same status that would be returned by + * cairo_status(cr). **/ cairo_path_t * cairo_copy_path_flat (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); if (cr->status) - return &_cairo_path_nil; - - return _cairo_path_data_create_flat (&cr->path, cr->gstate); + return _cairo_path_data_create_in_error (cr->status); + else + return _cairo_path_data_create_flat (&cr->path, cr->gstate); } /** @@ -2098,43 +2250,47 @@ cairo_copy_path_flat (cairo_t *cr) * @cr: a cairo context * @path: path to be appended * - * Append the @path onto the current path. See #cairo_path_t - * for details on how the path data structure must be initialized. + * Append the @path onto the current path. The @path may be either the + * return value from one of cairo_copy_path() or + * cairo_copy_path_flat() or it may be constructed manually. See + * #cairo_path_t for details on how the path data structure should be + * initialized, and note that path->status must be initialized to + * CAIRO_STATUS_SUCCESS. **/ void cairo_append_path (cairo_t *cr, cairo_path_t *path) { - CAIRO_CHECK_SANITY (cr); - if (cr->status) + if (cr->status) { + _cairo_error (cr, cr->status); return; + } if (path == NULL || path->data == NULL) { - cr->status = CAIRO_STATUS_NULL_POINTER; + _cairo_error (cr, CAIRO_STATUS_NULL_POINTER); return; } - if (path == &_cairo_path_nil) { - cr->status = CAIRO_STATUS_NO_MEMORY; + if (path->status) { + _cairo_error (cr, path->status); return; } cr->status = _cairo_path_data_append_to_context (path, cr); - - CAIRO_CHECK_SANITY (cr); + if (cr->status) + _cairo_error (cr, cr->status); } cairo_status_t cairo_status (cairo_t *cr) { - CAIRO_CHECK_SANITY (cr); return cr->status; } const char * -cairo_status_string (cairo_t *cr) +cairo_status_to_string (cairo_status_t status) { - switch (cr->status) { + switch (status) { case CAIRO_STATUS_SUCCESS: return "success"; case CAIRO_STATUS_NO_MEMORY: @@ -2163,8 +2319,8 @@ cairo_status_string (cairo_t *cr) return "the target surface has been finished"; case CAIRO_STATUS_SURFACE_TYPE_MISMATCH: return "the surface type is not appropriate for the operation"; - case CAIRO_STATUS_BAD_NESTING: - return "drawing operations interleaved for two contexts for the same surface"; + case CAIRO_STATUS_PATTERN_TYPE_MISMATCH: + return "the pattern type is not appropriate for the operation"; } return "<unknown error status>"; |