[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