Ejemplo n.º 1
0
void
_cairo_scaled_font_map_destroy (void)
{
    int i;
    cairo_scaled_font_map_t *font_map = cairo_scaled_font_map;
    cairo_scaled_font_t *scaled_font;

    if (font_map == NULL)
	return;

    CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex);

    for (i = 0; i < font_map->num_holdovers; i++) {
	scaled_font = font_map->holdovers[i];
	/* We should only get here through the reset_static_data path
	 * and there had better not be any active references at that
	 * point. */
	assert (scaled_font->ref_count == 0);
	_cairo_hash_table_remove (font_map->hash_table,
				  &scaled_font->hash_entry);
	_cairo_scaled_font_fini (scaled_font);
	free (scaled_font);
    }

    _cairo_hash_table_destroy (font_map->hash_table);

    free (cairo_scaled_font_map);
    cairo_scaled_font_map = NULL;
}
Ejemplo n.º 2
0
/**
 * cairo_scaled_font_create:
 * @font_face: a #cairo_font_face_t
 * @font_matrix: font space to user space transformation matrix for the
 *       font. In the simplest case of a N point font, this matrix is
 *       just a scale by N, but it can also be used to shear the font
 *       or stretch it unequally along the two axes. See
 *       cairo_set_font_matrix().
 * @ctm: user to device transformation matrix with which the font will
 *       be used.
 * @options: options to use when getting metrics for the font and
 *           rendering with it.
 * 
 * Creates a #cairo_scaled_font_t object from a font face and matrices that
 * describe the size of the font and the environment in which it will
 * be used.
 * 
 * Return value: a newly created #cairo_scaled_font_t. Destroy with
 *  cairo_scaled_font_destroy()
 **/
cairo_scaled_font_t *
cairo_scaled_font_create (cairo_font_face_t          *font_face,
			  const cairo_matrix_t       *font_matrix,
			  const cairo_matrix_t       *ctm,
			  const cairo_font_options_t *options)
{
    cairo_status_t status;
    cairo_scaled_font_map_t *font_map;
    cairo_scaled_font_t key, *scaled_font = NULL;

    if (font_face->status)
	return (cairo_scaled_font_t *)&_cairo_scaled_font_nil;

    font_map = _cairo_scaled_font_map_lock ();
    if (font_map == NULL)
	goto UNWIND;
    
    _cairo_scaled_font_init_key (&key, font_face,
				 font_matrix, ctm, options);

    /* Return existing scaled_font if it exists in the hash table. */
    if (_cairo_hash_table_lookup (font_map->hash_table, &key.hash_entry,
				  (cairo_hash_entry_t**) &scaled_font))
    {
	_cairo_scaled_font_map_unlock ();
	return cairo_scaled_font_reference (scaled_font);
    }

    /* Otherwise create it and insert it into the hash table. */
    status = font_face->backend->scaled_font_create (font_face, font_matrix,
						     ctm, options, &scaled_font);
    if (status)
	goto UNWIND_FONT_MAP_LOCK;

    status = _cairo_hash_table_insert (font_map->hash_table,
				       &scaled_font->hash_entry);
    if (status)
	goto UNWIND_SCALED_FONT_CREATE;

    _cairo_scaled_font_map_unlock ();

    return scaled_font;

UNWIND_SCALED_FONT_CREATE:
    /* We can't call _cairo_scaled_font_destroy here since it expects
     * that the font has already been successfully inserted into the
     * hash table. */
    _cairo_scaled_font_fini (scaled_font);
    free (scaled_font);
UNWIND_FONT_MAP_LOCK:
    _cairo_scaled_font_map_unlock ();
UNWIND:
    return NULL;
}
Ejemplo n.º 3
0
/**
 * cairo_scaled_font_destroy:
 * @scaled_font: a #cairo_scaled_font_t
 * 
 * Decreases the reference count on @font by one. If the result
 * is zero, then @font and all associated resources are freed.
 * See cairo_scaled_font_reference().
 **/
void
cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
{
    cairo_scaled_font_map_t *font_map;

    if (scaled_font == NULL)
	return;

    if (scaled_font->ref_count == (unsigned int)-1)
	return;

    /* cairo_scaled_font_t objects are cached and shared between
     * threads. This works because these objects are immutable. Except
     * that the reference count is mutable, so we have to do locking
     * around any modification of the reference count. */
    font_map = _cairo_scaled_font_map_lock ();
    {
	assert (font_map != NULL);

	assert (scaled_font->ref_count > 0);

	if (--(scaled_font->ref_count) == 0)
	{
	    /* Rather than immediately destroying this object, we put it into
	     * the font_map->holdovers array in case it will get used again
	     * soon. To make room for it, we do actually destroy the
	     * least-recently-used holdover.
	     */
	    if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS) {
		cairo_scaled_font_t *lru;

		lru = font_map->holdovers[0];
		assert (lru->ref_count == 0);
	
		_cairo_hash_table_remove (font_map->hash_table, &lru->hash_entry);

		_cairo_scaled_font_fini (lru);
		free (lru);
	
		font_map->num_holdovers--;
		memmove (&font_map->holdovers[0],
			 &font_map->holdovers[1],
			 font_map->num_holdovers * sizeof (cairo_scaled_font_t*));
	    }

	    font_map->holdovers[font_map->num_holdovers] = scaled_font;
	    font_map->num_holdovers++;
	}
    }
    _cairo_scaled_font_map_unlock ();
}
Ejemplo n.º 4
0
static cairo_status_t
_cairo_user_font_face_scaled_font_create (void                        *abstract_face,
					  const cairo_matrix_t        *font_matrix,
					  const cairo_matrix_t        *ctm,
					  const cairo_font_options_t  *options,
					  cairo_scaled_font_t        **scaled_font)
{
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
    cairo_user_font_face_t *font_face = abstract_face;
    cairo_user_scaled_font_t *user_scaled_font = NULL;
    cairo_font_extents_t font_extents = {1., 0., 1., 1., 0.};

    font_face->immutable = TRUE;

    user_scaled_font = malloc (sizeof (cairo_user_scaled_font_t));
    if (user_scaled_font == NULL)
	return CAIRO_STATUS_NO_MEMORY;

    status = _cairo_scaled_font_init (&user_scaled_font->base,
				      &font_face->base,
				      font_matrix, ctm, options,
				      &cairo_user_scaled_font_backend);

    if (status) {
	free (user_scaled_font);
	return status;
    }

    /* XXX metrics hinting? */

    /* compute a normalized version of font scale matrix to compute
     * extents in.  This is to minimize error caused by the cairo_fixed_t
     * representation. */
    {
	double fixed_scale, x_scale, y_scale;

	user_scaled_font->extent_scale = user_scaled_font->base.scale_inverse;
	status = _cairo_matrix_compute_basis_scale_factors (&user_scaled_font->extent_scale,
						      &x_scale, &y_scale,
						      1);
	if (status == CAIRO_STATUS_SUCCESS) {

	    if (x_scale == 0) x_scale = 1.;
	    if (y_scale == 0) y_scale = 1.;

	    user_scaled_font->snap_x_scale = x_scale;
	    user_scaled_font->snap_y_scale = y_scale;

	    /* since glyphs are pretty much 1.0x1.0, we can reduce error by
	     * scaling to a larger square.  say, 1024.x1024. */
	    fixed_scale = 1024.;
	    x_scale /= fixed_scale;
	    y_scale /= fixed_scale;

	    cairo_matrix_scale (&user_scaled_font->extent_scale, 1. / x_scale, 1. / y_scale);

	    user_scaled_font->extent_x_scale = x_scale;
	    user_scaled_font->extent_y_scale = y_scale;
	}
    }

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

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

    if (status == CAIRO_STATUS_SUCCESS)
	status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents);


    if (status != CAIRO_STATUS_SUCCESS) {
        _cairo_scaled_font_fini (&user_scaled_font->base);
	free (user_scaled_font);
    } else {
        user_scaled_font->default_glyph_extents.x_bearing = 0.;
        user_scaled_font->default_glyph_extents.y_bearing = -font_extents.ascent;
        user_scaled_font->default_glyph_extents.width = 0.;
        user_scaled_font->default_glyph_extents.height = font_extents.ascent + font_extents.descent;
        user_scaled_font->default_glyph_extents.x_advance = font_extents.max_x_advance;
        user_scaled_font->default_glyph_extents.y_advance = 0.;

	*scaled_font = &user_scaled_font->base;
    }

    return status;
}