[cairo-commit] src/cairo-font-face-twin.c src/cairo-ft-font.c src/cairoint.h

Chris Wilson ickle at kemper.freedesktop.org
Fri Jun 19 03:23:56 PDT 2009


 src/cairo-font-face-twin.c |   75 ++++++++++++++++++++++++++++++++++-----------
 src/cairo-ft-font.c        |    6 +++
 src/cairoint.h             |    3 +
 3 files changed, 66 insertions(+), 18 deletions(-)

New commits:
commit d3330d7beba0e0d2543e40a0e0e4d81ea9a78b45
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Jun 19 11:15:30 2009 +0100

    [ft] Substitute twin if there are no fonts
    
    Fixes bug 22356 -- Spurious "out of memory" error on system without fonts
    https://bugs.freedesktop.org/show_bug.cgi?id=22356
    
    If FcFontMatch() fails, then it means that there are no fonts available on
    the system (or it may have been a malloc error, we have no way of telling).
    Instead of report NO_MEMORY and disabling all drawing, one of the
    rationales for including a builtin font was so that we could continue even
    in the face of this error and show *something* to the user. (This being a
    last resort (and especially important for demos!) and hopefully easier to
    diagnose than no output at all.)

diff --git a/src/cairo-font-face-twin.c b/src/cairo-font-face-twin.c
index 712ca0d..3f82733 100644
--- a/src/cairo-font-face-twin.c
+++ b/src/cairo-font-face-twin.c
@@ -283,11 +283,11 @@ face_props_parse (twin_face_properties_t *props,
 }
 
 static cairo_status_t
-twin_font_face_set_properties_from_toy (cairo_font_face_t *twin_face,
-					cairo_toy_font_face_t *toy_face)
+twin_font_face_create_properties (cairo_font_face_t *twin_face,
+				  twin_face_properties_t **props_out)
 {
-    cairo_status_t status;
     twin_face_properties_t *props;
+    cairo_status_t status;
 
     props = malloc (sizeof (twin_face_properties_t));
     if (unlikely (props == NULL))
@@ -297,22 +297,37 @@ twin_font_face_set_properties_from_toy (cairo_font_face_t *twin_face,
     props->monospace = FALSE;
     props->smallcaps = FALSE;
 
-    props->slant = toy_face->slant;
-    props->weight = toy_face->weight == CAIRO_FONT_WEIGHT_NORMAL ?
-		    TWIN_WEIGHT_NORMAL : TWIN_WEIGHT_BOLD;
-    face_props_parse (props, toy_face->family);
-
     status = cairo_font_face_set_user_data (twin_face,
 					    &twin_properties_key,
 					    props, free);
-    if (unlikely (status))
-	goto FREE_PROPS;
+    if (unlikely (status)) {
+	free (props);
+	return status;
+    }
+
+    if (props_out)
+	*props_out = props;
 
     return CAIRO_STATUS_SUCCESS;
+}
 
-FREE_PROPS:
-    free (props);
-    return status;
+static cairo_status_t
+twin_font_face_set_properties_from_toy (cairo_font_face_t *twin_face,
+					cairo_toy_font_face_t *toy_face)
+{
+    cairo_status_t status;
+    twin_face_properties_t *props;
+
+    status = twin_font_face_create_properties (twin_face, &props);
+    if (unlikely (status))
+	return status;
+
+    props->slant = toy_face->slant;
+    props->weight = toy_face->weight == CAIRO_FONT_WEIGHT_NORMAL ?
+		    TWIN_WEIGHT_NORMAL : TWIN_WEIGHT_BOLD;
+    face_props_parse (props, toy_face->family);
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 
@@ -694,17 +709,43 @@ twin_scaled_font_unicode_to_glyph (cairo_scaled_font_t *scaled_font,
  * Face constructor
  */
 
-cairo_status_t
-_cairo_font_face_twin_create_for_toy (cairo_toy_font_face_t   *toy_face,
-				      cairo_font_face_t      **font_face)
+static cairo_font_face_t *
+_cairo_font_face_twin_create_internal (void)
 {
-    cairo_status_t status;
     cairo_font_face_t *twin_font_face;
 
     twin_font_face = cairo_user_font_face_create ();
     cairo_user_font_face_set_init_func             (twin_font_face, twin_scaled_font_init);
     cairo_user_font_face_set_render_glyph_func     (twin_font_face, twin_scaled_font_render_glyph);
     cairo_user_font_face_set_unicode_to_glyph_func (twin_font_face, twin_scaled_font_unicode_to_glyph);
+
+    return twin_font_face;
+}
+
+cairo_font_face_t *
+_cairo_font_face_twin_create_fallback (void)
+{
+    cairo_font_face_t *twin_font_face;
+    cairo_status_t status;
+
+    twin_font_face = _cairo_font_face_twin_create_internal ();
+    status = twin_font_face_create_properties (twin_font_face, NULL);
+    if (status) {
+	cairo_font_face_destroy (twin_font_face);
+	return (cairo_font_face_t *) &_cairo_font_face_nil;
+    }
+
+    return twin_font_face;
+}
+
+cairo_status_t
+_cairo_font_face_twin_create_for_toy (cairo_toy_font_face_t   *toy_face,
+				      cairo_font_face_t      **font_face)
+{
+    cairo_status_t status;
+    cairo_font_face_t *twin_font_face;
+
+    twin_font_face = _cairo_font_face_twin_create_internal ();
     status = twin_font_face_set_properties_from_toy (twin_font_face, toy_face);
     if (status) {
 	cairo_font_face_destroy (twin_font_face);
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 2150a41..b62a923 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2601,7 +2601,11 @@ _cairo_ft_resolve_pattern (FcPattern		      *pattern,
 
     resolved = FcFontMatch (NULL, pattern, &result);
     if (!resolved) {
-	font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
+	/* We failed to find any font. Substitute twin so that the user can
+	 * see something (and hopefully recognise that the font is missing)
+	 * and not just receive a NO_MEMORY error during rendering.
+	 */
+	font_face = _cairo_font_face_twin_create_fallback ();
 	goto FREE_PATTERN;
     }
 
diff --git a/src/cairoint.h b/src/cairoint.h
index 6b12594..3d6acc1 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1435,6 +1435,9 @@ _cairo_unscaled_font_destroy (cairo_unscaled_font_t *font);
 
 /* cairo-font-face-twin.c */
 
+cairo_private cairo_font_face_t *
+_cairo_font_face_twin_create_fallback (void);
+
 cairo_private cairo_status_t
 _cairo_font_face_twin_create_for_toy (cairo_toy_font_face_t   *toy_face,
 				      cairo_font_face_t      **font_face);


More information about the cairo-commit mailing list