[cairo-commit] src/cairo-ft-font.c
Behdad Esfahbod
behdad at kemper.freedesktop.org
Thu Jun 5 12:44:55 PDT 2008
src/cairo-ft-font.c | 117 ++++++++++++++++++++++++++++++++--------------------
1 file changed, 72 insertions(+), 45 deletions(-)
New commits:
commit 60cf2ef8449e1fd09fe0f2d8c8dc5fa2bb855e5a
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu Jun 5 15:44:37 2008 -0400
[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.
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 5824f49..5e8c581 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -88,7 +88,7 @@ typedef struct _cairo_ft_font_face cairo_ft_font_face_t;
struct _cairo_ft_unscaled_font {
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 */
/* only set if from_face is false */
@@ -280,16 +280,19 @@ _cairo_ft_unscaled_font_map_unlock (void)
static void
_cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,
char *filename,
- int id)
+ int id,
+ FT_Face face)
{
unsigned long hash;
key->filename = filename;
key->id = id;
+ key->face = face;
- /* 1607 is just an arbitrary prime. */
hash = _cairo_hash_string (filename);
+ /* the constants are just arbitrary primes */
hash += ((unsigned long) id) * 1607;
+ hash += ((unsigned long) face) * 2137;
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)
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;
@@ -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_b = key_b;
- return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0 &&
- unscaled_a->id == unscaled_b->id);
+ if (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
* pattern. Returns a new reference to the unscaled font.
*/
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_map_t *font_map;
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 ();
if (font_map == NULL)
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. */
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;
}
- status = _cairo_ft_unscaled_font_init (unscaled, filename, id, NULL);
+ status = _cairo_ft_unscaled_font_init (unscaled, filename, id, font_face);
if (status)
goto UNWIND_UNSCALED_MALLOC;
@@ -451,57 +454,66 @@ UNWIND:
return NULL;
}
+
static cairo_ft_unscaled_font_t *
-_cairo_ft_unscaled_font_create_from_face (FT_Face face)
+_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
{
- cairo_status_t status;
- cairo_ft_unscaled_font_t *unscaled;
+ FT_Face font_face = NULL;
+ char *filename = NULL;
+ int id = 0;
- unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
- if (unscaled == NULL) {
- _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
- return NULL;
- }
+ if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &font_face) != FcResultMatch) {
+ FcChar8 *fc_filename = NULL;
- status = _cairo_ft_unscaled_font_init (unscaled, NULL, 0, face);
- if (status) {
- free (unscaled);
- return 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 unscaled;
+ return _cairo_ft_unscaled_font_create_internal (filename, id, font_face);
+
+UNWIND:
+ return NULL;
+}
+
+static cairo_ft_unscaled_font_t *
+_cairo_ft_unscaled_font_create_from_face (FT_Face face)
+{
+ return _cairo_ft_unscaled_font_create_internal (NULL, 0, face);
}
static void
_cairo_ft_unscaled_font_destroy (void *abstract_font)
{
cairo_ft_unscaled_font_t *unscaled = abstract_font;
+ cairo_ft_unscaled_font_map_t *font_map;
if (unscaled == NULL)
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) {
/* See comments in _ft_font_face_destroy about the "zombie" state
* for a _ft_font_face.
*/
if (unscaled->faces && !unscaled->faces->unscaled)
cairo_font_face_destroy (&unscaled->faces->base);
-
- unscaled->face = NULL;
} 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);
-
- _cairo_ft_unscaled_font_map_unlock ();
}
+ unscaled->face = NULL;
+
+ _cairo_ft_unscaled_font_map_unlock ();
+
_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
* cairo_ft_font_options_substitute(), so *just* use those load
* 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;
@@ -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
* 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
* cairo_font_face_destroy() when you are done using it.
**/
More information about the cairo-commit
mailing list