mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 08:48:00 +02:00
[cairo-ft] Respect FC_FT_FACE element of pattern
Based on patch from Stuart Parmenter. Now one can use cairo_ft_font_face_create_for_pattern() to create cairo-ft font faces using provided FT_Face but also requesting advanced options like emboldening and hinting.
This commit is contained in:
parent
4c5370dad8
commit
60cf2ef844
1 changed files with 75 additions and 48 deletions
|
|
@ -88,7 +88,7 @@ typedef struct _cairo_ft_font_face cairo_ft_font_face_t;
|
||||||
struct _cairo_ft_unscaled_font {
|
struct _cairo_ft_unscaled_font {
|
||||||
cairo_unscaled_font_t base;
|
cairo_unscaled_font_t base;
|
||||||
|
|
||||||
cairo_bool_t from_face; /* from cairo_ft_font_face_create_for_ft_face()? */
|
cairo_bool_t from_face; /* was the FT_Face provided by user? */
|
||||||
FT_Face face; /* provided or cached face */
|
FT_Face face; /* provided or cached face */
|
||||||
|
|
||||||
/* only set if from_face is false */
|
/* only set if from_face is false */
|
||||||
|
|
@ -280,16 +280,19 @@ _cairo_ft_unscaled_font_map_unlock (void)
|
||||||
static void
|
static void
|
||||||
_cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,
|
_cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,
|
||||||
char *filename,
|
char *filename,
|
||||||
int id)
|
int id,
|
||||||
|
FT_Face face)
|
||||||
{
|
{
|
||||||
unsigned long hash;
|
unsigned long hash;
|
||||||
|
|
||||||
key->filename = filename;
|
key->filename = filename;
|
||||||
key->id = id;
|
key->id = id;
|
||||||
|
key->face = face;
|
||||||
|
|
||||||
/* 1607 is just an arbitrary prime. */
|
|
||||||
hash = _cairo_hash_string (filename);
|
hash = _cairo_hash_string (filename);
|
||||||
|
/* the constants are just arbitrary primes */
|
||||||
hash += ((unsigned long) id) * 1607;
|
hash += ((unsigned long) id) * 1607;
|
||||||
|
hash += ((unsigned long) face) * 2137;
|
||||||
|
|
||||||
key->base.hash_entry.hash = hash;
|
key->base.hash_entry.hash = hash;
|
||||||
}
|
}
|
||||||
|
|
@ -339,7 +342,7 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
|
||||||
if (filename_copy == NULL)
|
if (filename_copy == NULL)
|
||||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||||
|
|
||||||
_cairo_ft_unscaled_font_init_key (unscaled, filename_copy, id);
|
_cairo_ft_unscaled_font_init_key (unscaled, filename_copy, id, face);
|
||||||
}
|
}
|
||||||
|
|
||||||
unscaled->have_scale = FALSE;
|
unscaled->have_scale = FALSE;
|
||||||
|
|
@ -382,35 +385,35 @@ _cairo_ft_unscaled_font_keys_equal (const void *key_a,
|
||||||
const cairo_ft_unscaled_font_t *unscaled_a = key_a;
|
const cairo_ft_unscaled_font_t *unscaled_a = key_a;
|
||||||
const cairo_ft_unscaled_font_t *unscaled_b = key_b;
|
const cairo_ft_unscaled_font_t *unscaled_b = key_b;
|
||||||
|
|
||||||
return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0 &&
|
if (unscaled_a->id == unscaled_b->id &&
|
||||||
unscaled_a->id == unscaled_b->id);
|
unscaled_a->face == unscaled_b->face)
|
||||||
|
{
|
||||||
|
if (unscaled_a->filename == NULL && unscaled_a->filename == NULL)
|
||||||
|
return TRUE;
|
||||||
|
else if (unscaled_a->filename == NULL || unscaled_a->filename == NULL)
|
||||||
|
return FALSE;
|
||||||
|
else
|
||||||
|
return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finds or creates a #cairo_ft_unscaled_font_t for the filename/id from
|
/* Finds or creates a #cairo_ft_unscaled_font_t for the filename/id from
|
||||||
* pattern. Returns a new reference to the unscaled font.
|
* pattern. Returns a new reference to the unscaled font.
|
||||||
*/
|
*/
|
||||||
static cairo_ft_unscaled_font_t *
|
static cairo_ft_unscaled_font_t *
|
||||||
_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
|
_cairo_ft_unscaled_font_create_internal (char *filename, int id, FT_Face font_face)
|
||||||
{
|
{
|
||||||
cairo_ft_unscaled_font_t key, *unscaled;
|
cairo_ft_unscaled_font_t key, *unscaled;
|
||||||
cairo_ft_unscaled_font_map_t *font_map;
|
cairo_ft_unscaled_font_map_t *font_map;
|
||||||
cairo_status_t status;
|
cairo_status_t status;
|
||||||
FcChar8 *fc_filename;
|
|
||||||
char *filename;
|
|
||||||
int id;
|
|
||||||
|
|
||||||
if (FcPatternGetString (pattern, FC_FILE, 0, &fc_filename) != FcResultMatch)
|
|
||||||
goto UNWIND;
|
|
||||||
filename = (char *) fc_filename;
|
|
||||||
|
|
||||||
if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch)
|
|
||||||
goto UNWIND;
|
|
||||||
|
|
||||||
font_map = _cairo_ft_unscaled_font_map_lock ();
|
font_map = _cairo_ft_unscaled_font_map_lock ();
|
||||||
if (font_map == NULL)
|
if (font_map == NULL)
|
||||||
goto UNWIND;
|
goto UNWIND;
|
||||||
|
|
||||||
_cairo_ft_unscaled_font_init_key (&key, filename, id);
|
_cairo_ft_unscaled_font_init_key (&key, filename, id, font_face);
|
||||||
|
|
||||||
/* Return existing unscaled font if it exists in the hash table. */
|
/* Return existing unscaled font if it exists in the hash table. */
|
||||||
if (_cairo_hash_table_lookup (font_map->hash_table, &key.base.hash_entry,
|
if (_cairo_hash_table_lookup (font_map->hash_table, &key.base.hash_entry,
|
||||||
|
|
@ -428,7 +431,7 @@ _cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
|
||||||
goto UNWIND_FONT_MAP_LOCK;
|
goto UNWIND_FONT_MAP_LOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = _cairo_ft_unscaled_font_init (unscaled, filename, id, NULL);
|
status = _cairo_ft_unscaled_font_init (unscaled, filename, id, font_face);
|
||||||
if (status)
|
if (status)
|
||||||
goto UNWIND_UNSCALED_MALLOC;
|
goto UNWIND_UNSCALED_MALLOC;
|
||||||
|
|
||||||
|
|
@ -451,57 +454,66 @@ UNWIND:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static cairo_ft_unscaled_font_t *
|
||||||
|
_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
|
||||||
|
{
|
||||||
|
FT_Face font_face = NULL;
|
||||||
|
char *filename = NULL;
|
||||||
|
int id = 0;
|
||||||
|
|
||||||
|
if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &font_face) != FcResultMatch) {
|
||||||
|
FcChar8 *fc_filename = NULL;
|
||||||
|
|
||||||
|
if (FcPatternGetString (pattern, FC_FILE, 0, &fc_filename) != FcResultMatch)
|
||||||
|
goto UNWIND;
|
||||||
|
filename = (char *) fc_filename;
|
||||||
|
|
||||||
|
if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch)
|
||||||
|
goto UNWIND;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _cairo_ft_unscaled_font_create_internal (filename, id, font_face);
|
||||||
|
|
||||||
|
UNWIND:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static cairo_ft_unscaled_font_t *
|
static cairo_ft_unscaled_font_t *
|
||||||
_cairo_ft_unscaled_font_create_from_face (FT_Face face)
|
_cairo_ft_unscaled_font_create_from_face (FT_Face face)
|
||||||
{
|
{
|
||||||
cairo_status_t status;
|
return _cairo_ft_unscaled_font_create_internal (NULL, 0, face);
|
||||||
cairo_ft_unscaled_font_t *unscaled;
|
|
||||||
|
|
||||||
unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
|
|
||||||
if (unscaled == NULL) {
|
|
||||||
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = _cairo_ft_unscaled_font_init (unscaled, NULL, 0, face);
|
|
||||||
if (status) {
|
|
||||||
free (unscaled);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return unscaled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cairo_ft_unscaled_font_destroy (void *abstract_font)
|
_cairo_ft_unscaled_font_destroy (void *abstract_font)
|
||||||
{
|
{
|
||||||
cairo_ft_unscaled_font_t *unscaled = abstract_font;
|
cairo_ft_unscaled_font_t *unscaled = abstract_font;
|
||||||
|
cairo_ft_unscaled_font_map_t *font_map;
|
||||||
|
|
||||||
if (unscaled == NULL)
|
if (unscaled == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
font_map = _cairo_ft_unscaled_font_map_lock ();
|
||||||
|
/* All created objects must have been mapped in the font map. */
|
||||||
|
assert (font_map != NULL);
|
||||||
|
|
||||||
|
_cairo_hash_table_remove (font_map->hash_table,
|
||||||
|
&unscaled->base.hash_entry);
|
||||||
|
|
||||||
if (unscaled->from_face) {
|
if (unscaled->from_face) {
|
||||||
/* See comments in _ft_font_face_destroy about the "zombie" state
|
/* See comments in _ft_font_face_destroy about the "zombie" state
|
||||||
* for a _ft_font_face.
|
* for a _ft_font_face.
|
||||||
*/
|
*/
|
||||||
if (unscaled->faces && !unscaled->faces->unscaled)
|
if (unscaled->faces && !unscaled->faces->unscaled)
|
||||||
cairo_font_face_destroy (&unscaled->faces->base);
|
cairo_font_face_destroy (&unscaled->faces->base);
|
||||||
|
|
||||||
unscaled->face = NULL;
|
|
||||||
} else {
|
} else {
|
||||||
cairo_ft_unscaled_font_map_t *font_map;
|
|
||||||
|
|
||||||
font_map = _cairo_ft_unscaled_font_map_lock ();
|
|
||||||
/* All created objects must have been mapped in the font map. */
|
|
||||||
assert (font_map != NULL);
|
|
||||||
|
|
||||||
_cairo_hash_table_remove (font_map->hash_table,
|
|
||||||
&unscaled->base.hash_entry);
|
|
||||||
|
|
||||||
_font_map_release_face_lock_held (font_map, unscaled);
|
_font_map_release_face_lock_held (font_map, unscaled);
|
||||||
|
|
||||||
_cairo_ft_unscaled_font_map_unlock ();
|
|
||||||
}
|
}
|
||||||
|
unscaled->face = NULL;
|
||||||
|
|
||||||
|
_cairo_ft_unscaled_font_map_unlock ();
|
||||||
|
|
||||||
_cairo_ft_unscaled_font_fini (unscaled);
|
_cairo_ft_unscaled_font_fini (unscaled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2281,6 +2293,10 @@ _cairo_ft_font_face_scaled_font_create (void *abstract_face,
|
||||||
* derived from a pattern where the user has called
|
* derived from a pattern where the user has called
|
||||||
* cairo_ft_font_options_substitute(), so *just* use those load
|
* cairo_ft_font_options_substitute(), so *just* use those load
|
||||||
* flags and ignore the options.
|
* flags and ignore the options.
|
||||||
|
*
|
||||||
|
* XXX two points about the above comment:
|
||||||
|
* 1. I don't see how the comment is relevant here,
|
||||||
|
* 2. What if the face is coming from FC_FT_FACE of a pattern?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ft_options = font_face->ft_options;
|
ft_options = font_face->ft_options;
|
||||||
|
|
@ -2484,6 +2500,17 @@ cairo_ft_font_options_substitute (const cairo_font_options_t *options,
|
||||||
* appropriately to reflect the options in a #cairo_font_options_t, call
|
* appropriately to reflect the options in a #cairo_font_options_t, call
|
||||||
* cairo_ft_font_options_substitute().
|
* cairo_ft_font_options_substitute().
|
||||||
*
|
*
|
||||||
|
* The pattern's FC_FT_FACE element is inspected first and if that is set,
|
||||||
|
* that will be the FreeType font face associated with the returned cairo
|
||||||
|
* font face. Otherwise the FC_FILE and FC_INDEX elements of @pattern are
|
||||||
|
* used to load a font face from file.
|
||||||
|
*
|
||||||
|
* If the FC_FT_FACE element of @pattern is set, the user is responsible
|
||||||
|
* for making sure that the referenced FT_Face remains valid for the life
|
||||||
|
* time of the returned #cairo_font_face_t. See
|
||||||
|
* cairo_ft_font_face_create_for_ft_face() for an exmaple of how to couple
|
||||||
|
* the life time of the FT_Face to that of the cairo font-face.
|
||||||
|
*
|
||||||
* Return value: a newly created #cairo_font_face_t. Free with
|
* Return value: a newly created #cairo_font_face_t. Free with
|
||||||
* cairo_font_face_destroy() when you are done using it.
|
* cairo_font_face_destroy() when you are done using it.
|
||||||
**/
|
**/
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue