diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2009-06-19 11:15:30 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2009-06-19 11:20:48 +0100 |
commit | d3330d7beba0e0d2543e40a0e0e4d81ea9a78b45 (patch) | |
tree | 01ebb085aa7d926b68209acc9fbdef9253f460d9 /src | |
parent | 6d8b353658da1ad973e3bda9e89799a7467d8182 (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.c | 75 | ||||
-rw-r--r-- | src/cairo-ft-font.c | 6 | ||||
-rw-r--r-- | src/cairoint.h | 3 |
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); |