diff options
author | Carl Worth <cworth@cworth.org> | 2003-09-04 16:27:34 +0000 |
---|---|---|
committer | Carl Worth <cworth@cworth.org> | 2003-09-04 16:27:34 +0000 |
commit | c25eea6f10473fd1e2d61faf60289f58475b85fd (patch) | |
tree | 838ed604ccf6636c58e3431fafe08b9f825f4429 | |
parent | 6f731e27580870a5954ca21331b15746e371c8d3 (diff) |
Fixed bugs if cairo_stroke/fill called before cairo_set_rgb_color or cairo_set_target. Also fixed bug when cairo_set_rgb_color is called before cairo_set_target.
-rw-r--r-- | BUGS | 2 | ||||
-rw-r--r-- | ChangeLog | 23 | ||||
-rw-r--r-- | src/cairo-gstate.c | 136 | ||||
-rw-r--r-- | src/cairo.c | 8 | ||||
-rw-r--r-- | src/cairo.h | 3 | ||||
-rw-r--r-- | src/cairo_gstate.c | 136 | ||||
-rw-r--r-- | src/cairoint.h | 7 |
7 files changed, 198 insertions, 117 deletions
@@ -1,3 +1 @@ -SEGV if cairo_set_rgb_color is called before cairo_set_target_drawable -SEGV if cairo_fill is called before cairo_set_rgb_color @@ -1,3 +1,26 @@ +2003-09-04 Carl Worth <cworth@isi.edu> + + * src/cairo_gstate.c (_cairo_gstate_init): Combine gstate->pattern + and gstate->solid into a single gstate->source. + (_cairo_gstate_set_rgb_color): Defer creation of gstate->source + until the stroke or fill. + (_cairo_gstate_ensure_source): New function to combine duplicated + code. + (_cairo_gstate_stroke): + (_cairo_gstate_fill): Now must ensure that gstate->source has been + created. + + * src/cairo.c (cairo_set_target_surface): + (cairo_set_target_drawable): + (cairo_set_target_image): These functions can now clear + status==CAIRO_STATUS_NO_TARGET_SURFACE. This is a clean solution + to the bug of a SEGV if cairo_stroke/cairo_fill are called before + cairo_set_target. + + * BUGS: Removed two fixed bugs, (SEGV if cairo_set_rgb_color + called before cairo_set_target and SEGV if cairo_fill called + before cairo_set_rgb_color) + 2003-09-04 Keith Packard <keithp@keithp.com> * src/cairo_path_stroke.c: added comments describing miter diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c index 42b3ca2d..a1a38799 100644 --- a/src/cairo-gstate.c +++ b/src/cairo-gstate.c @@ -34,6 +34,9 @@ static void _cairo_gstate_set_current_pt (cairo_gstate_t *gstate, double x, double y); static cairo_status_t +_cairo_gstate_ensure_source (cairo_gstate_t *gstate); + +static cairo_status_t _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate, cairo_surface_t *src, cairo_operator_t operator, @@ -74,10 +77,10 @@ _cairo_gstate_init (cairo_gstate_t *gstate) _cairo_font_init (&gstate->font); gstate->surface = NULL; - gstate->solid = NULL; - gstate->pattern = NULL; - gstate->pattern_offset.x = 0.0; - gstate->pattern_offset.y = 0.0; + gstate->source = NULL; + gstate->source_offset.x = 0.0; + gstate->source_offset.y = 0.0; + gstate->source_is_solid = 1; gstate->clip.surface = NULL; @@ -115,8 +118,7 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other) goto CLEANUP_DASHES; _cairo_surface_reference (gstate->surface); - _cairo_surface_reference (gstate->solid); - _cairo_surface_reference (gstate->pattern); + _cairo_surface_reference (gstate->source); _cairo_surface_reference (gstate->clip.surface); status = _cairo_path_init_copy (&gstate->path, &other->path); @@ -148,11 +150,9 @@ _cairo_gstate_fini (cairo_gstate_t *gstate) cairo_surface_destroy (gstate->surface); gstate->surface = NULL; - cairo_surface_destroy (gstate->solid); - gstate->solid = NULL; - - cairo_surface_destroy (gstate->pattern); - gstate->pattern = NULL; + cairo_surface_destroy (gstate->source); + gstate->source = NULL; + gstate->source_is_solid = 1; cairo_surface_destroy (gstate->clip.surface); gstate->clip.surface = NULL; @@ -313,14 +313,16 @@ _cairo_gstate_current_target_surface (cairo_gstate_t *gstate) cairo_status_t _cairo_gstate_set_pattern (cairo_gstate_t *gstate, cairo_surface_t *pattern) { - cairo_surface_destroy (gstate->pattern); + cairo_surface_destroy (gstate->source); - gstate->pattern = pattern; - _cairo_surface_reference (gstate->pattern); + gstate->source = pattern; + gstate->source_is_solid = 0; + + _cairo_surface_reference (gstate->source); _cairo_gstate_current_point (gstate, - &gstate->pattern_offset.x, - &gstate->pattern_offset.y); + &gstate->source_offset.x, + &gstate->source_offset.y); return CAIRO_STATUS_SUCCESS; } @@ -344,15 +346,12 @@ _cairo_gstate_set_rgb_color (cairo_gstate_t *gstate, double red, double green, d { _cairo_color_set_rgb (&gstate->color, red, green, blue); - cairo_surface_destroy (gstate->pattern); - gstate->pattern = NULL; + cairo_surface_destroy (gstate->source); - cairo_surface_destroy (gstate->solid); - gstate->solid = cairo_surface_create_similar_solid (gstate->surface, CAIRO_FORMAT_ARGB32, - 1, 1, - red, green, blue, - gstate->alpha); - cairo_surface_set_repeat (gstate->solid, 1); + gstate->source = NULL; + gstate->source_offset.x = 0; + gstate->source_offset.y = 0; + gstate->source_is_solid = 1; return CAIRO_STATUS_SUCCESS; } @@ -379,6 +378,7 @@ _cairo_gstate_current_tolerance (cairo_gstate_t *gstate) return gstate->tolerance; } +/* XXX: Need to fix this so it does the right thing after set_pattern. */ cairo_status_t _cairo_gstate_set_alpha (cairo_gstate_t *gstate, double alpha) { @@ -386,15 +386,11 @@ _cairo_gstate_set_alpha (cairo_gstate_t *gstate, double alpha) _cairo_color_set_alpha (&gstate->color, alpha); - cairo_surface_destroy (gstate->solid); - gstate->solid = cairo_surface_create_similar_solid (gstate->surface, - CAIRO_FORMAT_ARGB32, - 1, 1, - gstate->color.red, - gstate->color.green, - gstate->color.blue, - gstate->color.alpha); - cairo_surface_set_repeat (gstate->solid, 1); + cairo_surface_destroy (gstate->source); + + gstate->source = NULL; + gstate->source_offset.x = 0; + gstate->source_offset.y = 0; return CAIRO_STATUS_SUCCESS; } @@ -806,12 +802,40 @@ _cairo_gstate_current_point (cairo_gstate_t *gstate, double *x, double *y) return CAIRO_STATUS_SUCCESS; } +static cairo_status_t +_cairo_gstate_ensure_source (cairo_gstate_t *gstate) +{ + if (gstate->source) + return CAIRO_STATUS_SUCCESS; + + if (gstate->surface == NULL) + return CAIRO_STATUS_NO_TARGET_SURFACE; + + gstate->source = cairo_surface_create_similar_solid (gstate->surface, + CAIRO_FORMAT_ARGB32, + 1, 1, + gstate->color.red, + gstate->color.green, + gstate->color.blue, + gstate->color.alpha); + if (gstate->source == NULL) + return CAIRO_STATUS_NO_MEMORY; + + cairo_surface_set_repeat (gstate->source, 1); + + return CAIRO_STATUS_SUCCESS; +} + cairo_status_t _cairo_gstate_stroke (cairo_gstate_t *gstate) { cairo_status_t status; cairo_traps_t traps; - cairo_matrix_t user_to_pattern, device_to_pattern; + cairo_matrix_t user_to_source, device_to_source; + + status = _cairo_gstate_ensure_source (gstate); + if (status) + return status; _cairo_pen_init (&gstate->pen_regular, gstate->line_width / 2.0, gstate); @@ -823,21 +847,21 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate) return status; } - if (gstate->pattern) { - cairo_surface_get_matrix (gstate->pattern, &user_to_pattern); - cairo_matrix_multiply (&device_to_pattern, &gstate->ctm_inverse, &user_to_pattern); - cairo_surface_set_matrix (gstate->pattern, &device_to_pattern); + if (! gstate->source_is_solid) { + cairo_surface_get_matrix (gstate->source, &user_to_source); + cairo_matrix_multiply (&device_to_source, &gstate->ctm_inverse, &user_to_source); + cairo_surface_set_matrix (gstate->source, &device_to_source); } _cairo_gstate_clip_and_composite_trapezoids (gstate, - gstate->pattern ? gstate->pattern : gstate->solid, + gstate->source, gstate->operator, gstate->surface, &traps); - /* restore the matrix originally in the pattern surface */ - if (gstate->pattern) - cairo_surface_set_matrix (gstate->pattern, &user_to_pattern); + /* restore the matrix originally in the source surface */ + if (! gstate->source_is_solid) + cairo_surface_set_matrix (gstate->source, &user_to_source); _cairo_traps_fini (&traps); @@ -929,8 +953,8 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate, _cairo_surface_composite_trapezoids (gstate->operator, src, dst, - XFixedToDouble (xoff) - gstate->pattern_offset.x, - XFixedToDouble (yoff) - gstate->pattern_offset.y, + XFixedToDouble (xoff) - gstate->source_offset.x, + XFixedToDouble (yoff) - gstate->source_offset.y, traps->traps, traps->num_traps); } @@ -943,7 +967,11 @@ _cairo_gstate_fill (cairo_gstate_t *gstate) { cairo_status_t status; cairo_traps_t traps; - cairo_matrix_t user_to_pattern, device_to_pattern; + cairo_matrix_t user_to_source, device_to_source; + + status = _cairo_gstate_ensure_source (gstate); + if (status) + return status; _cairo_traps_init (&traps); @@ -953,21 +981,21 @@ _cairo_gstate_fill (cairo_gstate_t *gstate) return status; } - if (gstate->pattern) { - cairo_surface_get_matrix (gstate->pattern, &user_to_pattern); - cairo_matrix_multiply (&device_to_pattern, &gstate->ctm_inverse, &user_to_pattern); - cairo_surface_set_matrix (gstate->pattern, &device_to_pattern); + if (! gstate->source_is_solid) { + cairo_surface_get_matrix (gstate->source, &user_to_source); + cairo_matrix_multiply (&device_to_source, &gstate->ctm_inverse, &user_to_source); + cairo_surface_set_matrix (gstate->source, &device_to_source); } _cairo_gstate_clip_and_composite_trapezoids (gstate, - gstate->pattern ? gstate->pattern : gstate->solid, + gstate->source, gstate->operator, gstate->surface, &traps); - /* restore the matrix originally in the pattern surface */ - if (gstate->pattern) - cairo_surface_set_matrix (gstate->pattern, &user_to_pattern); + /* restore the matrix originally in the source surface */ + if (! gstate->source_is_solid) + cairo_surface_set_matrix (gstate->source, &user_to_source); _cairo_traps_fini (&traps); @@ -1095,7 +1123,7 @@ _cairo_gstate_show_text (cairo_gstate_t *gstate, const unsigned char *utf8) /* XXX: Need to make a generic (non-Xft) backend for text. */ XftTextRenderUtf8 (gstate->surface->dpy, gstate->operator, - gstate->solid->picture, + gstate->source->picture, xft_font, gstate->surface->picture, 0, 0, diff --git a/src/cairo.c b/src/cairo.c index 6c62d3a3..e4006e63 100644 --- a/src/cairo.c +++ b/src/cairo.c @@ -156,7 +156,7 @@ cairo_pop_group (cairo_t *cr) void cairo_set_target_surface (cairo_t *cr, cairo_surface_t *surface) { - if (cr->status) + if (cr->status && cr->status != CAIRO_STATUS_NO_TARGET_SURFACE) return; cr->status = _cairo_gstate_set_target_surface (cr->gstate, surface); @@ -170,7 +170,7 @@ cairo_set_target_drawable (cairo_t *cr, { cairo_surface_t *surface; - if (cr->status) + if (cr->status && cr->status != CAIRO_STATUS_NO_TARGET_SURFACE) return; surface = cairo_surface_create_for_drawable (dpy, drawable, @@ -197,7 +197,7 @@ cairo_set_target_image (cairo_t *cr, { cairo_surface_t *surface; - if (cr->status) + if (cr->status && cr->status != CAIRO_STATUS_NO_TARGET_SURFACE) return; surface = cairo_surface_create_for_image (data, @@ -734,6 +734,8 @@ cairo_status_string (cairo_t *cr) return "no current point defined"; case CAIRO_STATUS_INVALID_MATRIX: return "invalid matrix (not invertible)"; + case CAIRO_STATUS_NO_TARGET_SURFACE: + return "no target surface has been set"; } return ""; diff --git a/src/cairo.h b/src/cairo.h index 18c434a5..3379a8a6 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -389,7 +389,8 @@ typedef enum cairo_status { CAIRO_STATUS_INVALID_RESTORE, CAIRO_STATUS_INVALID_POP_GROUP, CAIRO_STATUS_NO_CURRENT_POINT, - CAIRO_STATUS_INVALID_MATRIX + CAIRO_STATUS_INVALID_MATRIX, + CAIRO_STATUS_NO_TARGET_SURFACE } cairo_status_t; extern cairo_status_t __external_linkage diff --git a/src/cairo_gstate.c b/src/cairo_gstate.c index 42b3ca2d..a1a38799 100644 --- a/src/cairo_gstate.c +++ b/src/cairo_gstate.c @@ -34,6 +34,9 @@ static void _cairo_gstate_set_current_pt (cairo_gstate_t *gstate, double x, double y); static cairo_status_t +_cairo_gstate_ensure_source (cairo_gstate_t *gstate); + +static cairo_status_t _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate, cairo_surface_t *src, cairo_operator_t operator, @@ -74,10 +77,10 @@ _cairo_gstate_init (cairo_gstate_t *gstate) _cairo_font_init (&gstate->font); gstate->surface = NULL; - gstate->solid = NULL; - gstate->pattern = NULL; - gstate->pattern_offset.x = 0.0; - gstate->pattern_offset.y = 0.0; + gstate->source = NULL; + gstate->source_offset.x = 0.0; + gstate->source_offset.y = 0.0; + gstate->source_is_solid = 1; gstate->clip.surface = NULL; @@ -115,8 +118,7 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other) goto CLEANUP_DASHES; _cairo_surface_reference (gstate->surface); - _cairo_surface_reference (gstate->solid); - _cairo_surface_reference (gstate->pattern); + _cairo_surface_reference (gstate->source); _cairo_surface_reference (gstate->clip.surface); status = _cairo_path_init_copy (&gstate->path, &other->path); @@ -148,11 +150,9 @@ _cairo_gstate_fini (cairo_gstate_t *gstate) cairo_surface_destroy (gstate->surface); gstate->surface = NULL; - cairo_surface_destroy (gstate->solid); - gstate->solid = NULL; - - cairo_surface_destroy (gstate->pattern); - gstate->pattern = NULL; + cairo_surface_destroy (gstate->source); + gstate->source = NULL; + gstate->source_is_solid = 1; cairo_surface_destroy (gstate->clip.surface); gstate->clip.surface = NULL; @@ -313,14 +313,16 @@ _cairo_gstate_current_target_surface (cairo_gstate_t *gstate) cairo_status_t _cairo_gstate_set_pattern (cairo_gstate_t *gstate, cairo_surface_t *pattern) { - cairo_surface_destroy (gstate->pattern); + cairo_surface_destroy (gstate->source); - gstate->pattern = pattern; - _cairo_surface_reference (gstate->pattern); + gstate->source = pattern; + gstate->source_is_solid = 0; + + _cairo_surface_reference (gstate->source); _cairo_gstate_current_point (gstate, - &gstate->pattern_offset.x, - &gstate->pattern_offset.y); + &gstate->source_offset.x, + &gstate->source_offset.y); return CAIRO_STATUS_SUCCESS; } @@ -344,15 +346,12 @@ _cairo_gstate_set_rgb_color (cairo_gstate_t *gstate, double red, double green, d { _cairo_color_set_rgb (&gstate->color, red, green, blue); - cairo_surface_destroy (gstate->pattern); - gstate->pattern = NULL; + cairo_surface_destroy (gstate->source); - cairo_surface_destroy (gstate->solid); - gstate->solid = cairo_surface_create_similar_solid (gstate->surface, CAIRO_FORMAT_ARGB32, - 1, 1, - red, green, blue, - gstate->alpha); - cairo_surface_set_repeat (gstate->solid, 1); + gstate->source = NULL; + gstate->source_offset.x = 0; + gstate->source_offset.y = 0; + gstate->source_is_solid = 1; return CAIRO_STATUS_SUCCESS; } @@ -379,6 +378,7 @@ _cairo_gstate_current_tolerance (cairo_gstate_t *gstate) return gstate->tolerance; } +/* XXX: Need to fix this so it does the right thing after set_pattern. */ cairo_status_t _cairo_gstate_set_alpha (cairo_gstate_t *gstate, double alpha) { @@ -386,15 +386,11 @@ _cairo_gstate_set_alpha (cairo_gstate_t *gstate, double alpha) _cairo_color_set_alpha (&gstate->color, alpha); - cairo_surface_destroy (gstate->solid); - gstate->solid = cairo_surface_create_similar_solid (gstate->surface, - CAIRO_FORMAT_ARGB32, - 1, 1, - gstate->color.red, - gstate->color.green, - gstate->color.blue, - gstate->color.alpha); - cairo_surface_set_repeat (gstate->solid, 1); + cairo_surface_destroy (gstate->source); + + gstate->source = NULL; + gstate->source_offset.x = 0; + gstate->source_offset.y = 0; return CAIRO_STATUS_SUCCESS; } @@ -806,12 +802,40 @@ _cairo_gstate_current_point (cairo_gstate_t *gstate, double *x, double *y) return CAIRO_STATUS_SUCCESS; } +static cairo_status_t +_cairo_gstate_ensure_source (cairo_gstate_t *gstate) +{ + if (gstate->source) + return CAIRO_STATUS_SUCCESS; + + if (gstate->surface == NULL) + return CAIRO_STATUS_NO_TARGET_SURFACE; + + gstate->source = cairo_surface_create_similar_solid (gstate->surface, + CAIRO_FORMAT_ARGB32, + 1, 1, + gstate->color.red, + gstate->color.green, + gstate->color.blue, + gstate->color.alpha); + if (gstate->source == NULL) + return CAIRO_STATUS_NO_MEMORY; + + cairo_surface_set_repeat (gstate->source, 1); + + return CAIRO_STATUS_SUCCESS; +} + cairo_status_t _cairo_gstate_stroke (cairo_gstate_t *gstate) { cairo_status_t status; cairo_traps_t traps; - cairo_matrix_t user_to_pattern, device_to_pattern; + cairo_matrix_t user_to_source, device_to_source; + + status = _cairo_gstate_ensure_source (gstate); + if (status) + return status; _cairo_pen_init (&gstate->pen_regular, gstate->line_width / 2.0, gstate); @@ -823,21 +847,21 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate) return status; } - if (gstate->pattern) { - cairo_surface_get_matrix (gstate->pattern, &user_to_pattern); - cairo_matrix_multiply (&device_to_pattern, &gstate->ctm_inverse, &user_to_pattern); - cairo_surface_set_matrix (gstate->pattern, &device_to_pattern); + if (! gstate->source_is_solid) { + cairo_surface_get_matrix (gstate->source, &user_to_source); + cairo_matrix_multiply (&device_to_source, &gstate->ctm_inverse, &user_to_source); + cairo_surface_set_matrix (gstate->source, &device_to_source); } _cairo_gstate_clip_and_composite_trapezoids (gstate, - gstate->pattern ? gstate->pattern : gstate->solid, + gstate->source, gstate->operator, gstate->surface, &traps); - /* restore the matrix originally in the pattern surface */ - if (gstate->pattern) - cairo_surface_set_matrix (gstate->pattern, &user_to_pattern); + /* restore the matrix originally in the source surface */ + if (! gstate->source_is_solid) + cairo_surface_set_matrix (gstate->source, &user_to_source); _cairo_traps_fini (&traps); @@ -929,8 +953,8 @@ _cairo_gstate_clip_and_composite_trapezoids (cairo_gstate_t *gstate, _cairo_surface_composite_trapezoids (gstate->operator, src, dst, - XFixedToDouble (xoff) - gstate->pattern_offset.x, - XFixedToDouble (yoff) - gstate->pattern_offset.y, + XFixedToDouble (xoff) - gstate->source_offset.x, + XFixedToDouble (yoff) - gstate->source_offset.y, traps->traps, traps->num_traps); } @@ -943,7 +967,11 @@ _cairo_gstate_fill (cairo_gstate_t *gstate) { cairo_status_t status; cairo_traps_t traps; - cairo_matrix_t user_to_pattern, device_to_pattern; + cairo_matrix_t user_to_source, device_to_source; + + status = _cairo_gstate_ensure_source (gstate); + if (status) + return status; _cairo_traps_init (&traps); @@ -953,21 +981,21 @@ _cairo_gstate_fill (cairo_gstate_t *gstate) return status; } - if (gstate->pattern) { - cairo_surface_get_matrix (gstate->pattern, &user_to_pattern); - cairo_matrix_multiply (&device_to_pattern, &gstate->ctm_inverse, &user_to_pattern); - cairo_surface_set_matrix (gstate->pattern, &device_to_pattern); + if (! gstate->source_is_solid) { + cairo_surface_get_matrix (gstate->source, &user_to_source); + cairo_matrix_multiply (&device_to_source, &gstate->ctm_inverse, &user_to_source); + cairo_surface_set_matrix (gstate->source, &device_to_source); } _cairo_gstate_clip_and_composite_trapezoids (gstate, - gstate->pattern ? gstate->pattern : gstate->solid, + gstate->source, gstate->operator, gstate->surface, &traps); - /* restore the matrix originally in the pattern surface */ - if (gstate->pattern) - cairo_surface_set_matrix (gstate->pattern, &user_to_pattern); + /* restore the matrix originally in the source surface */ + if (! gstate->source_is_solid) + cairo_surface_set_matrix (gstate->source, &user_to_source); _cairo_traps_fini (&traps); @@ -1095,7 +1123,7 @@ _cairo_gstate_show_text (cairo_gstate_t *gstate, const unsigned char *utf8) /* XXX: Need to make a generic (non-Xft) backend for text. */ XftTextRenderUtf8 (gstate->surface->dpy, gstate->operator, - gstate->solid->picture, + gstate->source->picture, xft_font, gstate->surface->picture, 0, 0, diff --git a/src/cairoint.h b/src/cairoint.h index b2a115be..49da376f 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -341,9 +341,10 @@ typedef struct cairo_gstate { cairo_font_t font; cairo_surface_t *surface; - cairo_surface_t *solid; - cairo_surface_t *pattern; - cairo_point_double_t pattern_offset; + + cairo_surface_t *source; + cairo_point_double_t source_offset; + int source_is_solid; cairo_clip_rec_t clip; |