diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c index cb15ca437..bcc3cfab7 100644 --- a/src/cairo-user-font.c +++ b/src/cairo-user-font.c @@ -74,6 +74,28 @@ typedef struct _cairo_user_scaled_font { /* #cairo_user_scaled_font_t */ +static cairo_t * +_cairo_user_scaled_font_create_meta_context (cairo_user_scaled_font_t *scaled_font) +{ + cairo_content_t content; + cairo_surface_t *meta_surface; + cairo_t *cr; + + content = scaled_font->base.options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ? + CAIRO_CONTENT_COLOR_ALPHA : + CAIRO_CONTENT_ALPHA; + + meta_surface = _cairo_meta_surface_create (content, -1, -1); + cr = cairo_create (meta_surface); + cairo_surface_destroy (meta_surface); + + cairo_set_matrix (cr, &scaled_font->base.scale); + cairo_set_font_size (cr, 1.0); + cairo_set_font_options (cr, &scaled_font->base.options); + + return cr; +} + static const cairo_scaled_font_backend_t cairo_user_scaled_font_backend; static cairo_int_status_t @@ -89,17 +111,9 @@ _cairo_user_scaled_glyph_init (void *abstract_font, cairo_user_font_face_t *face = (cairo_user_font_face_t *) scaled_font->base.font_face; cairo_text_extents_t extents = scaled_font->default_glyph_extents; - cairo_content_t content = scaled_font->base.options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ? - CAIRO_CONTENT_COLOR_ALPHA : - CAIRO_CONTENT_ALPHA; cairo_t *cr; - meta_surface = _cairo_meta_surface_create (content, -1, -1); - cr = cairo_create (meta_surface); - - cairo_set_matrix (cr, &scaled_font->base.scale); - cairo_set_font_size (cr, 1.0); - cairo_set_font_options (cr, &scaled_font->base.options); + cr = _cairo_user_scaled_font_create_meta_context (scaled_font); if (face->scaled_font_methods.render_glyph) status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font, @@ -111,6 +125,8 @@ _cairo_user_scaled_glyph_init (void *abstract_font, if (status == CAIRO_STATUS_SUCCESS) status = cairo_status (cr); + meta_surface = cairo_surface_reference (cairo_get_target (cr)); + cairo_destroy (cr); if (status) { @@ -377,6 +393,8 @@ _cairo_user_font_face_scaled_font_create (void *abstract_ if (status == CAIRO_STATUS_SUCCESS && font_face->scaled_font_methods.init != NULL) { + cairo_t *cr; + /* Lock the scaled_font mutex such that user doesn't accidentally try * to use it just yet. */ CAIRO_MUTEX_LOCK (user_scaled_font->base.mutex); @@ -384,9 +402,17 @@ _cairo_user_font_face_scaled_font_create (void *abstract_ /* Give away fontmap lock such that user-font can use other fonts */ _cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base); + cr = _cairo_user_scaled_font_create_meta_context (user_scaled_font); + status = font_face->scaled_font_methods.init (&user_scaled_font->base, + cr, &font_extents); + if (status == CAIRO_STATUS_SUCCESS) + status = cairo_status (cr); + + cairo_destroy (cr); + _cairo_scaled_font_unregister_placeholder_and_lock_font_map (&user_scaled_font->base); CAIRO_MUTEX_UNLOCK (user_scaled_font->base.mutex); diff --git a/src/cairo.h b/src/cairo.h index 1be31ab9a..e26c25747 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -1365,11 +1365,18 @@ cairo_user_font_face_create (void); /** * cairo_user_scaled_font_init_func_t: * @scaled_font: the scaled-font being created + * @cr: a cairo context, in font space * @extents: font extents to fill in, in font space * * #cairo_user_scaled_font_init_func_t is the type of function which is * called when a scaled-font needs to be created for a user font-face. * + * The cairo context @cr is not used by the caller, but is prepared in font + * space, similar to what the cairo contexts passed to the render_glyph + * method will look like. The callback can use this context for extents + * computation for example. After the callback is called, @cr is checked + * for any error status. + * * The @extents argument is where the user font sets the font extents for * @scaled_font. It is in font space, which means that for most cases its * ascent and descent members should add to 1.0. @extents is preset to @@ -1391,6 +1398,7 @@ cairo_user_font_face_create (void); * Since: 1.8 **/ typedef cairo_status_t (*cairo_user_scaled_font_init_func_t) (cairo_scaled_font_t *scaled_font, + cairo_t *cr, cairo_font_extents_t *extents); /** diff --git a/test/user-font-proxy.c b/test/user-font-proxy.c index c7b29abdf..8684729a3 100644 --- a/test/user-font-proxy.c +++ b/test/user-font-proxy.c @@ -55,40 +55,16 @@ static cairo_user_data_key_t fallback_font_face_key; static cairo_status_t test_scaled_font_init (cairo_scaled_font_t *scaled_font, + cairo_t *cr, cairo_font_extents_t *extents) { - cairo_font_face_t *font_face; - cairo_matrix_t font_matrix, ctm; - cairo_font_options_t *font_options; - cairo_scaled_font_t *fallback_scaled_font; + cairo_set_font_face (cr, + cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font), + &fallback_font_face_key)); - font_face = cairo_toy_font_face_create ("", - CAIRO_FONT_SLANT_NORMAL, - CAIRO_FONT_WEIGHT_NORMAL); + cairo_font_extents (cr, extents); - cairo_matrix_init_identity (&font_matrix); - cairo_scaled_font_get_scale_matrix (scaled_font, &ctm); - - font_options = cairo_font_options_create (); - cairo_scaled_font_get_font_options (scaled_font, font_options); - - fallback_scaled_font = cairo_scaled_font_create (font_face, - &font_matrix, - &ctm, - font_options); - - cairo_font_options_destroy (font_options); - - cairo_scaled_font_extents (fallback_scaled_font, extents); - - cairo_scaled_font_destroy (fallback_scaled_font); - - cairo_scaled_font_set_user_data (scaled_font, - &fallback_font_face_key, - font_face, - cairo_font_face_destroy); - - return CAIRO_STATUS_SUCCESS; + return CAIRO_STATUS_SUCCESS; } static cairo_status_t @@ -103,23 +79,38 @@ test_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font, text[0] = glyph; cairo_set_font_face (cr, - cairo_scaled_font_get_user_data (scaled_font, - &fallback_font_face_key)); + cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font), + &fallback_font_face_key)); + cairo_show_text (cr, text); cairo_text_extents (cr, text, extents); return CAIRO_STATUS_SUCCESS; } +static cairo_font_face_t *user_font_face = NULL; + static cairo_font_face_t * get_user_font_face (void) { - static cairo_font_face_t *user_font_face = NULL; - if (!user_font_face) { + cairo_font_face_t *fallback_font_face; + user_font_face = cairo_user_font_face_create (); cairo_user_font_face_set_init_func (user_font_face, test_scaled_font_init); cairo_user_font_face_set_render_glyph_func (user_font_face, test_scaled_font_render_glyph); + + /* This also happens to be default font face on cairo_t, so does + * not make much sense here. For demonstration only. + */ + fallback_font_face = cairo_toy_font_face_create ("", + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_NORMAL); + + cairo_font_face_set_user_data (user_font_face, + &fallback_font_face_key, + fallback_font_face, + cairo_font_face_destroy); } return user_font_face; @@ -181,6 +172,11 @@ draw (cairo_t *cr, int width, int height) cairo_text_path (cr, text); cairo_fill (cr); + if (user_font_face) { + cairo_font_face_destroy (user_font_face); + user_font_face = NULL; + } + return CAIRO_TEST_SUCCESS; } diff --git a/test/user-font.c b/test/user-font.c index c414719df..406bd3aee 100644 --- a/test/user-font.c +++ b/test/user-font.c @@ -74,6 +74,7 @@ static cairo_user_data_key_t test_font_face_glyphs_key; static cairo_status_t test_scaled_font_init (cairo_scaled_font_t *scaled_font, + cairo_t *cr, cairo_font_extents_t *metrics) { metrics->ascent = .75;