summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrea Canciani <ranma42@gmail.com>2010-06-29 09:58:54 +0200
committerAndrea Canciani <ranma42@gmail.com>2010-06-30 12:31:25 +0200
commitd2d6c96c24501d888422ea42d3c90d3c8f3647a0 (patch)
treeedf850fa25b6b3b7b8602c1ac2b175d774c2c2c3
parent6db247e13c6fa61879029b335c6fa649d810c11b (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.c9
-rw-r--r--src/cairo-scaled-font.c5
-rw-r--r--src/cairo-user-font.c60
-rw-r--r--src/cairoint.h3
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;