summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-06-19 11:15:30 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2009-06-19 11:20:48 +0100
commitd3330d7beba0e0d2543e40a0e0e4d81ea9a78b45 (patch)
tree01ebb085aa7d926b68209acc9fbdef9253f460d9 /src
parent6d8b353658da1ad973e3bda9e89799a7467d8182 (diff)
[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.)
Diffstat (limited to 'src')
-rw-r--r--src/cairo-font-face-twin.c75
-rw-r--r--src/cairo-ft-font.c6
-rw-r--r--src/cairoint.h3
3 files changed, 66 insertions, 18 deletions
diff --git a/src/cairo-font-face-twin.c b/src/cairo-font-face-twin.c
index 712ca0dcd..3f8273324 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 2150a4144..b62a92393 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 6b1259463..3d6acc194 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);