[user-font] Add a cairo_t argument to cairo_user_scaled_font_init_func_t

The init func does not actually need to draw anything, but having a cairo_t
similar to that passed to render_glyph is handy for computing font extents.
This is because cairo makes doing some things really hard (if not impossible)
without a cairo_t.

The user-font-proxy test case is a great example of how the added cairo_t
makes life much easier.
This commit is contained in:
Behdad Esfahbod 2008-08-07 15:44:11 -04:00
parent d6ae23478a
commit b01ad0835d
4 changed files with 74 additions and 43 deletions

View file

@ -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);

View file

@ -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);
/**

View file

@ -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;
}

View file

@ -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;