diff options
author | Andrea Canciani <ranma42@gmail.com> | 2010-06-29 09:58:54 +0200 |
---|---|---|
committer | Andrea Canciani <ranma42@gmail.com> | 2010-06-30 12:31:25 +0200 |
commit | d2d6c96c24501d888422ea42d3c90d3c8f3647a0 (patch) | |
tree | edf850fa25b6b3b7b8602c1ac2b175d774c2c2c3 | |
parent | 6db247e13c6fa61879029b335c6fa649d810c11b (diff) |
user-font: correct handling of size 0 text
Text with size 0 has a singular scale matrix, thus requires special
handling to avoid invalidating the context where it is used.
Fixes pthread-show-text and text-zero-len (they failed with assertion
when ran using the user font backend).
-rw-r--r-- | src/cairo-matrix.c | 9 | ||||
-rw-r--r-- | src/cairo-scaled-font.c | 5 | ||||
-rw-r--r-- | src/cairo-user-font.c | 60 | ||||
-rw-r--r-- | src/cairoint.h | 3 |
4 files changed, 50 insertions, 27 deletions
diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c index de1c6ed2..6ae8e62c 100644 --- a/src/cairo-matrix.c +++ b/src/cairo-matrix.c @@ -578,6 +578,15 @@ _cairo_matrix_is_invertible (const cairo_matrix_t *matrix) return ISFINITE (det) && det != 0.; } +cairo_bool_t +_cairo_matrix_is_scale_0 (const cairo_matrix_t *matrix) +{ + return matrix->xx == 0. && + matrix->xy == 0. && + matrix->yx == 0. && + matrix->yy == 0.; +} + double _cairo_matrix_compute_determinant (const cairo_matrix_t *matrix) { diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c index 418f90a7..8ad77f5f 100644 --- a/src/cairo-scaled-font.c +++ b/src/cairo-scaled-font.c @@ -704,13 +704,12 @@ _cairo_scaled_font_init (cairo_scaled_font_t *scaled_font, * * Also, the check for == 0. below may be too harsh... */ - if (scaled_font->scale.xx == 0. && scaled_font->scale.xy == 0. && - scaled_font->scale.yx == 0. && scaled_font->scale.yy == 0.) + if (_cairo_matrix_is_scale_0 (&scaled_font->scale)) { cairo_matrix_init (&scaled_font->scale_inverse, 0, 0, 0, 0, -scaled_font->scale.x0, -scaled_font->scale.y0); - else + } else return status; } diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c index c00146f0..34638add 100644 --- a/src/cairo-user-font.c +++ b/src/cairo-user-font.c @@ -75,26 +75,34 @@ typedef struct _cairo_user_scaled_font { /* #cairo_user_scaled_font_t */ -static cairo_t * -_cairo_user_scaled_font_create_recording_context (cairo_user_scaled_font_t *scaled_font) +static cairo_surface_t * +_cairo_user_scaled_font_create_recording_surface (const cairo_user_scaled_font_t *scaled_font) { cairo_content_t content; - cairo_surface_t *recording_surface; - cairo_matrix_t scale; - cairo_t *cr; content = scaled_font->base.options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_ALPHA; - recording_surface = cairo_recording_surface_create (content, NULL); + return cairo_recording_surface_create (content, NULL); +} + + +static cairo_t * +_cairo_user_scaled_font_create_recording_context (const cairo_user_scaled_font_t *scaled_font, + cairo_surface_t *recording_surface) +{ + cairo_t *cr; + cr = cairo_create (recording_surface); - cairo_surface_destroy (recording_surface); - scale = scaled_font->base.scale; - scale.x0 = scale.y0 = 0.; + if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) { + cairo_matrix_t scale; + scale = scaled_font->base.scale; + scale.x0 = scale.y0 = 0.; + cairo_set_matrix (cr, &scale); + } - cairo_set_matrix (cr, &scale); cairo_set_font_size (cr, 1.0); cairo_set_font_options (cr, &scaled_font->base.options); cairo_set_source_rgb (cr, 1., 1., 1.); @@ -117,25 +125,26 @@ _cairo_user_scaled_glyph_init (void *abstract_font, cairo_text_extents_t extents = scaled_font->default_glyph_extents; cairo_t *cr; - cr = _cairo_user_scaled_font_create_recording_context (scaled_font); + if (!face->scaled_font_methods.render_glyph) + return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED; - if (face->scaled_font_methods.render_glyph) { + recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font); + + /* special case for 0 rank matrix (as in _cairo_scaled_font_init): empty surface */ + if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) { + cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface); status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font, _cairo_scaled_glyph_index(scaled_glyph), cr, &extents); - } else - status = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED; - - if (status == CAIRO_STATUS_SUCCESS) - status = cairo_status (cr); - - recording_surface = cairo_surface_reference (cairo_get_target (cr)); + cairo_destroy (cr); - cairo_destroy (cr); + if (status == CAIRO_STATUS_SUCCESS) + status = cairo_status (cr); - if (unlikely (status)) { - cairo_surface_destroy (recording_surface); - return status; + if (unlikely (status)) { + cairo_surface_destroy (recording_surface); + return status; + } } _cairo_scaled_glyph_set_recording_surface (scaled_glyph, @@ -424,9 +433,12 @@ _cairo_user_font_face_scaled_font_create (void *abstract_ /* Give away fontmap lock such that user-font can use other fonts */ status = _cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base); if (status == CAIRO_STATUS_SUCCESS) { + cairo_surface_t *recording_surface; cairo_t *cr; - cr = _cairo_user_scaled_font_create_recording_context (user_scaled_font); + recording_surface = _cairo_user_scaled_font_create_recording_surface (user_scaled_font); + cr = _cairo_user_scaled_font_create_recording_context (user_scaled_font, recording_surface); + cairo_surface_destroy (recording_surface); status = font_face->scaled_font_methods.init (&user_scaled_font->base, cr, diff --git a/src/cairoint.h b/src/cairoint.h index 6ccc18f7..1a938ed3 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -2052,6 +2052,9 @@ _cairo_matrix_transform_bounding_box_fixed (const cairo_matrix_t *matrix, cairo_private cairo_bool_t _cairo_matrix_is_invertible (const cairo_matrix_t *matrix) cairo_pure; +cairo_private cairo_bool_t +_cairo_matrix_is_scale_0 (const cairo_matrix_t *matrix) cairo_pure; + cairo_private double _cairo_matrix_compute_determinant (const cairo_matrix_t *matrix) cairo_pure; |