Index: third_party/harfbuzz-ng/src/hb-ft.cc |
diff --git a/third_party/harfbuzz-ng/src/hb-ft.cc b/third_party/harfbuzz-ng/src/hb-ft.cc |
index 468742cfd05fef35dd256b6a264ea9ca8a21973d..b695f81ab08475d4fa00ab63dd18c50af863ec4c 100644 |
--- a/third_party/harfbuzz-ng/src/hb-ft.cc |
+++ b/third_party/harfbuzz-ng/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,94 @@ |
*/ |
+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); |
+} |
+ |
+/** |
+ * hb_ft_font_set_load_flags: |
+ * @font: |
+ * @load_flags: |
+ * |
+ * |
+ * |
+ * Since: 1.0.5 |
+ **/ |
+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; |
+} |
+ |
+/** |
+ * hb_ft_font_get_load_flags: |
+ * @font: |
+ * |
+ * |
+ * |
+ * Return value: |
+ * Since: 1.0.5 |
+ **/ |
+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 +163,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 +184,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 +202,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 +236,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 +262,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 +290,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 +312,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 +337,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 +353,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 +380,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 +395,10 @@ _hb_ft_get_font_funcs (void) |
} |
}; |
- return const_cast<hb_font_funcs_t *> (&ft_ffuncs); |
+ hb_font_set_funcs (font, |
+ const_cast<hb_font_funcs_t *> (&ft_ffuncs), |
+ _hb_ft_font_create (ft_face, unref), |
+ (hb_destroy_func_t) _hb_ft_font_destroy); |
} |
@@ -347,7 +437,7 @@ reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) |
* |
* |
* Return value: (transfer full): |
- * Since: 1.0 |
+ * Since: 0.9.2 |
**/ |
hb_face_t * |
hb_ft_face_create (FT_Face ft_face, |
@@ -403,7 +493,7 @@ hb_ft_face_finalize (FT_Face ft_face) |
* |
* |
* Return value: (transfer full): |
- * Since: 1.0 |
+ * Since: 0.9.2 |
**/ |
hb_face_t * |
hb_ft_face_create_cached (FT_Face ft_face) |
@@ -420,11 +510,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: |
@@ -434,7 +519,7 @@ _do_nothing (void) |
* |
* |
* Return value: (transfer full): |
- * Since: 1.0 |
+ * Since: 0.9.2 |
**/ |
hb_font_t * |
hb_ft_font_create (FT_Face ft_face, |
@@ -446,9 +531,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 +645,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); |
} |