summaryrefslogtreecommitdiff
path: root/src/cairo-ft-font.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cairo-ft-font.c')
-rw-r--r--src/cairo-ft-font.c142
1 files changed, 91 insertions, 51 deletions
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index a0c7beb5d..74d43cc2d 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2209,6 +2209,55 @@ _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (void *abstract_font,
}
static cairo_int_status_t
+_cairo_ft_scaled_glyph_load_glyph (cairo_ft_scaled_font_t *scaled_font,
+ cairo_scaled_glyph_t *scaled_glyph,
+ FT_Face face,
+ int load_flags,
+ cairo_bool_t use_em_size,
+ cairo_bool_t vertical_layout)
+{
+ FT_Error error;
+ cairo_status_t status;
+
+ if (use_em_size) {
+ cairo_matrix_t em_size;
+ cairo_matrix_init_scale (&em_size, face->units_per_EM, face->units_per_EM);
+ status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled, &em_size);
+ } else {
+ status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
+ &scaled_font->base.scale);
+ }
+ if (unlikely (status))
+ return status;
+
+ error = FT_Load_Glyph (face,
+ _cairo_scaled_glyph_index(scaled_glyph),
+ load_flags);
+ /* XXX ignoring all other errors for now. They are not fatal, typically
+ * just a glyph-not-found. */
+ if (error == FT_Err_Out_Of_Memory)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ /*
+ * synthesize glyphs if requested
+ */
+#if HAVE_FT_GLYPHSLOT_EMBOLDEN
+ if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_BOLD)
+ FT_GlyphSlot_Embolden (face->glyph);
+#endif
+
+#if HAVE_FT_GLYPHSLOT_OBLIQUE
+ if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_OBLIQUE)
+ FT_GlyphSlot_Oblique (face->glyph);
+#endif
+
+ if (vertical_layout)
+ _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, face->glyph);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
_cairo_ft_scaled_glyph_init (void *abstract_font,
cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_glyph_info_t info)
@@ -2218,22 +2267,17 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
FT_GlyphSlot glyph;
FT_Face face;
- FT_Error error;
int load_flags = scaled_font->ft_options.load_flags;
FT_Glyph_Metrics *metrics;
double x_factor, y_factor;
cairo_bool_t vertical_layout = FALSE;
- cairo_status_t status;
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_bool_t scaled_glyph_loaded = FALSE;
face = _cairo_ft_unscaled_font_lock_face (unscaled);
if (!face)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
- &scaled_font->base.scale);
- if (unlikely (status))
- goto FAIL;
-
/* Ignore global advance unconditionally */
load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
@@ -2264,37 +2308,23 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
/* load_flags |= FT_LOAD_COLOR; */
#endif
- error = FT_Load_Glyph (face,
- _cairo_scaled_glyph_index(scaled_glyph),
- load_flags);
- /* XXX ignoring all other errors for now. They are not fatal, typically
- * just a glyph-not-found. */
- if (error == FT_Err_Out_Of_Memory) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto FAIL;
- }
-
- glyph = face->glyph;
- /*
- * synthesize glyphs if requested
- */
-#if HAVE_FT_GLYPHSLOT_EMBOLDEN
- if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_BOLD)
- FT_GlyphSlot_Embolden (glyph);
-#endif
+ if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) {
-#if HAVE_FT_GLYPHSLOT_OBLIQUE
- if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_OBLIQUE)
- FT_GlyphSlot_Oblique (glyph);
-#endif
+ cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF;
- if (vertical_layout)
- _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph);
+ status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
+ scaled_glyph,
+ face,
+ load_flags,
+ !hint_metrics,
+ vertical_layout);
+ if (unlikely (status))
+ goto FAIL;
- if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) {
+ glyph = face->glyph;
+ scaled_glyph_loaded = hint_metrics;
- cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF;
/*
* Compute font-space metrics
*/
@@ -2392,6 +2422,20 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) {
cairo_image_surface_t *surface;
+ if (!scaled_glyph_loaded) {
+ status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
+ scaled_glyph,
+ face,
+ load_flags,
+ FALSE,
+ vertical_layout);
+ if (unlikely (status))
+ goto FAIL;
+
+ glyph = face->glyph;
+ scaled_glyph_loaded = TRUE;
+ }
+
if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
status = _render_glyph_outline (face, &scaled_font->ft_options.base,
&surface);
@@ -2423,27 +2467,23 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
* so reload it. This will probably never occur though
*/
if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) {
- error = FT_Load_Glyph (face,
- _cairo_scaled_glyph_index(scaled_glyph),
- load_flags | FT_LOAD_NO_BITMAP);
- /* XXX ignoring all other errors for now. They are not fatal, typically
- * just a glyph-not-found. */
- if (error == FT_Err_Out_Of_Memory) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ scaled_glyph_loaded = FALSE;
+ load_flags |= FT_LOAD_NO_BITMAP;
+ }
+
+ if (!scaled_glyph_loaded) {
+ status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
+ scaled_glyph,
+ face,
+ load_flags,
+ FALSE,
+ vertical_layout);
+ if (unlikely (status))
goto FAIL;
- }
-#if HAVE_FT_GLYPHSLOT_EMBOLDEN
- if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_BOLD)
- FT_GlyphSlot_Embolden (glyph);
-#endif
-#if HAVE_FT_GLYPHSLOT_OBLIQUE
- if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_OBLIQUE)
- FT_GlyphSlot_Oblique (glyph);
-#endif
- if (vertical_layout)
- _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph);
+ glyph = face->glyph;
}
+
if (glyph->format == FT_GLYPH_FORMAT_OUTLINE)
status = _decompose_glyph_outline (face, &scaled_font->ft_options.base,
&path);