diff --git a/src/hb-ft.cc b/src/hb-ft.cc index edafff4e92bb9f5304ace0de2cac31d5b747d8a1..1acfecc4d322c089e5075f377954287f039e58ff 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -1,6 +1,7 @@ /* * Copyright © 2009 Red Hat, Inc. * Copyright © 2009 Keith Stribley + * Copyright © 2015 Google, Inc. * * This is part of HarfBuzz, a text shaping library. * @@ -23,6 +24,7 @@ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod */ #include "hb-private.hh" @@ -46,17 +48,15 @@ * In general, this file does a fine job of what it's supposed to do. * There are, however, things that need more work: * - * - We don't handle any load_flags. That definitely has API implications. :( - * I believe hb_ft_font_create() should take load_flags input. - * In particular, FT_Get_Advance() without the NO_HINTING flag seems to be - * buggy. + * - I remember seeing FT_Get_Advance() without the NO_HINTING flag to be buggy. + * Have not investigated. * - * FreeType works in 26.6 mode. Clients can decide to use that mode, and everything + * - FreeType works in 26.6 mode. Clients can decide to use that mode, and everything * would work fine. However, we also abuse this API for performing in font-space, * but don't pass the correct flags to FreeType. We just abuse the no-hinting mode * for that, such that no rounding etc happens. As such, we don't set ppem, and - * pass NO_HINTING around. This seems to work best, until we go ahead and add a full - * load_flags API. + * pass NO_HINTING as load_flags. Would be much better to use NO_SCALE, and scale + * ourselves, like we do in uniscribe, etc. * * - We don't handle / allow for emboldening / obliqueing. * @@ -66,6 +66,76 @@ */ +struct hb_ft_font_t +{ + FT_Face ft_face; + int load_flags; + bool unref; /* Whether to destroy ft_face when done. */ +}; + +static hb_ft_font_t * +_hb_ft_font_create (FT_Face ft_face, bool unref) +{ + hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t)); + + if (unlikely (!ft_font)) + return NULL; + + ft_font->ft_face = ft_face; + ft_font->unref = unref; + + ft_font->load_flags = FT_LOAD_DEFAULT; + + return ft_font; +} + +static void +_hb_ft_font_destroy (hb_ft_font_t *ft_font) +{ + if (ft_font->unref) + FT_Done_Face (ft_font->ft_face); + + free (ft_font); +} + +void +hb_ft_font_set_load_flags (hb_font_t *font, int load_flags) +{ + if (font->immutable) + return; + + if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) + return; + + hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data; + + ft_font->load_flags = load_flags; +} + +int +hb_ft_font_get_load_flags (hb_font_t *font) +{ + if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) + return 0; + + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data; + + return ft_font->load_flags; +} + +FT_Face +hb_ft_font_get_face (hb_font_t *font) +{ + if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy) + return NULL; + + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font->user_data; + + return ft_font->ft_face; +} + + + static hb_bool_t hb_ft_get_glyph (hb_font_t *font HB_UNUSED, void *font_data, @@ -75,13 +145,13 @@ hb_ft_get_glyph (hb_font_t *font HB_UNUSED, void *user_data HB_UNUSED) { + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; unsigned int g; - FT_Face ft_face = (FT_Face) font_data; if (likely (!variation_selector)) - g = FT_Get_Char_Index (ft_face, unicode); + g = FT_Get_Char_Index (ft_font->ft_face, unicode); else - g = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector); + g = FT_Face_GetCharVariantIndex (ft_font->ft_face, unicode, variation_selector); if (unlikely (!g)) return false; @@ -96,11 +166,10 @@ hb_ft_get_glyph_h_advance (hb_font_t *font HB_UNUSED, hb_codepoint_t glyph, void *user_data HB_UNUSED) { - FT_Face ft_face = (FT_Face) font_data; - int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; FT_Fixed v; - if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v))) + if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags, &v))) return 0; if (font->x_scale < 0) @@ -115,11 +184,10 @@ hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED, hb_codepoint_t glyph, void *user_data HB_UNUSED) { - FT_Face ft_face = (FT_Face) font_data; - int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING | FT_LOAD_VERTICAL_LAYOUT; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; FT_Fixed v; - if (unlikely (FT_Get_Advance (ft_face, glyph, load_flags, &v))) + if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v))) return 0; if (font->y_scale < 0) @@ -150,10 +218,10 @@ hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED, hb_position_t *y, void *user_data HB_UNUSED) { - FT_Face ft_face = (FT_Face) font_data; - int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + FT_Face ft_face = ft_font->ft_face; - if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags))) + if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) return false; /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates @@ -176,11 +244,11 @@ hb_ft_get_glyph_h_kerning (hb_font_t *font, hb_codepoint_t right_glyph, void *user_data HB_UNUSED) { - FT_Face ft_face = (FT_Face) font_data; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; FT_Vector kerningv; FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED; - if (FT_Get_Kerning (ft_face, left_glyph, right_glyph, mode, &kerningv)) + if (FT_Get_Kerning (ft_font->ft_face, left_glyph, right_glyph, mode, &kerningv)) return 0; return kerningv.x; @@ -204,10 +272,10 @@ hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED, hb_glyph_extents_t *extents, void *user_data HB_UNUSED) { - FT_Face ft_face = (FT_Face) font_data; - int load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + FT_Face ft_face = ft_font->ft_face; - if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags))) + if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) return false; extents->x_bearing = ft_face->glyph->metrics.horiBearingX; @@ -226,10 +294,10 @@ hb_ft_get_glyph_contour_point (hb_font_t *font HB_UNUSED, hb_position_t *y, void *user_data HB_UNUSED) { - FT_Face ft_face = (FT_Face) font_data; - int load_flags = FT_LOAD_DEFAULT; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + FT_Face ft_face = ft_font->ft_face; - if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags))) + if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags))) return false; if (unlikely (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)) @@ -251,9 +319,9 @@ hb_ft_get_glyph_name (hb_font_t *font HB_UNUSED, char *name, unsigned int size, void *user_data HB_UNUSED) { - FT_Face ft_face = (FT_Face) font_data; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; - hb_bool_t ret = !FT_Get_Glyph_Name (ft_face, glyph, name, size); + hb_bool_t ret = !FT_Get_Glyph_Name (ft_font->ft_face, glyph, name, size); if (ret && (size && !*name)) ret = false; @@ -267,7 +335,8 @@ hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED, hb_codepoint_t *glyph, void *user_data HB_UNUSED) { - FT_Face ft_face = (FT_Face) font_data; + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + FT_Face ft_face = ft_font->ft_face; if (len < 0) *glyph = FT_Get_Name_Index (ft_face, (FT_String *) name); @@ -293,8 +362,8 @@ hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED, } -static hb_font_funcs_t * -_hb_ft_get_font_funcs (void) +static void +_hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref) { static const hb_font_funcs_t ft_ffuncs = { HB_OBJECT_HEADER_STATIC, @@ -308,7 +377,10 @@ _hb_ft_get_font_funcs (void) } }; - return const_cast (&ft_ffuncs); + hb_font_set_funcs (font, + const_cast (&ft_ffuncs), + _hb_ft_font_create (ft_face, unref), + (hb_destroy_func_t) _hb_ft_font_destroy); } @@ -420,11 +492,6 @@ hb_ft_face_create_cached (FT_Face ft_face) return hb_face_reference ((hb_face_t *) ft_face->generic.data); } -static void -_do_nothing (void) -{ -} - /** * hb_ft_font_create: @@ -446,9 +513,7 @@ hb_ft_font_create (FT_Face ft_face, face = hb_ft_face_create (ft_face, destroy); font = hb_font_create (face); hb_face_destroy (face); - hb_font_set_funcs (font, - _hb_ft_get_font_funcs (), - ft_face, (hb_destroy_func_t) _do_nothing); + _hb_ft_font_set_funcs (font, ft_face, false); hb_font_set_scale (font, (int) (((uint64_t) ft_face->size->metrics.x_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16), (int) (((uint64_t) ft_face->size->metrics.y_scale * (uint64_t) ft_face->units_per_EM + (1<<15)) >> 16)); @@ -562,18 +627,6 @@ hb_ft_font_set_funcs (hb_font_t *font) ft_face->generic.data = blob; ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob; - hb_font_set_funcs (font, - _hb_ft_get_font_funcs (), - ft_face, - (hb_destroy_func_t) FT_Done_Face); -} - -FT_Face -hb_ft_font_get_face (hb_font_t *font) -{ - if (font->destroy == (hb_destroy_func_t) FT_Done_Face || - font->destroy == (hb_destroy_func_t) _do_nothing) - return (FT_Face) font->user_data; - - return NULL; + _hb_ft_font_set_funcs (font, ft_face, true); + hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING); } diff --git a/src/hb-ft.h b/src/hb-ft.h index 92f4b3614415503a939da9409b3794d85e7d7b7b..4bbc8265807b0437ff9e787a6e253f2668621136 100644 --- a/src/hb-ft.h +++ b/src/hb-ft.h @@ -1,5 +1,6 @@ /* * Copyright © 2009 Red Hat, Inc. + * Copyright © 2015 Google, Inc. * * This is part of HarfBuzz, a text shaping library. * @@ -22,6 +23,7 @@ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * * Red Hat Author(s): Behdad Esfahbod + * Google Author(s): Behdad Esfahbod */ #ifndef HB_FT_H @@ -105,14 +107,19 @@ hb_ft_font_create (FT_Face ft_face, hb_font_t * hb_ft_font_create_referenced (FT_Face ft_face); +FT_Face +hb_ft_font_get_face (hb_font_t *font); + +void +hb_ft_font_set_load_flags (hb_font_t *font, int load_flags); + +int +hb_ft_font_get_load_flags (hb_font_t *font); /* Makes an hb_font_t use FreeType internally to implement font functions. */ void hb_ft_font_set_funcs (hb_font_t *font); -FT_Face -hb_ft_font_get_face (hb_font_t *font); - HB_END_DECLS