From 34f9aa582c3a03b578c7eae3d2e8860a0bd5cb00 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Wed, 20 Jul 2016 02:35:54 -0700 Subject: [PATCH] Implement symbol cmap in ft and ot fonts Fixes https://github.com/behdad/harfbuzz/issues/236 Fixes https://bugs.chromium.org/p/chromium/issues/detail?id=627953 --- src/hb-ft.cc | 27 +++++++++++++++++++++++---- src/hb-ot-font.cc | 50 ++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/src/hb-ft.cc b/src/hb-ft.cc index 6c6749c..eaa1311 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -70,11 +70,12 @@ struct hb_ft_font_t { FT_Face ft_face; int load_flags; + bool symbol; /* Whether selected cmap is symbol cmap. */ 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_create (FT_Face ft_face, bool symbol, bool unref) { hb_ft_font_t *ft_font = (hb_ft_font_t *) calloc (1, sizeof (hb_ft_font_t)); @@ -82,6 +83,7 @@ _hb_ft_font_create (FT_Face ft_face, bool unref) return NULL; ft_font->ft_face = ft_face; + ft_font->symbol = symbol; ft_font->unref = unref; ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING; @@ -171,7 +173,21 @@ hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED, unsigned int g = FT_Get_Char_Index (ft_font->ft_face, unicode); if (unlikely (!g)) - return false; + { + if (unlikely (ft_font->symbol) && unicode <= 0x00FFu) + { + /* For symbol-encoded OpenType fonts, we duplicate the + * U+F000..F0FF range at U+0000..U+00FF. That's what + * Windows seems to do, and that's hinted about at: + * http://www.microsoft.com/typography/otspec/recom.htm + * under "Non-Standard (Symbol) Fonts". */ + g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode); + if (!g) + return false; + } + else + return false; + } *glyph = g; return true; @@ -450,9 +466,11 @@ retry: #endif }; + bool symbol = ft_face->charmap && ft_face->charmap->encoding == FT_ENCODING_MS_SYMBOL; + hb_font_set_funcs (font, funcs, - _hb_ft_font_create (ft_face, unref), + _hb_ft_font_create (ft_face, symbol, unref), (hb_destroy_func_t) _hb_ft_font_destroy); } @@ -681,7 +699,8 @@ hb_ft_font_set_funcs (hb_font_t *font) return; } - FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE); + if (FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE)) + FT_Select_Charmap (ft_face, FT_ENCODING_MS_SYMBOL); FT_Set_Char_Size (ft_face, abs (font->x_scale), abs (font->y_scale), diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 39fc849..0b7e31b 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -215,6 +215,28 @@ static inline bool get_glyph_from (const void *obj, return typed_obj->get_glyph (codepoint, glyph); } +template +static inline bool get_glyph_from_symbol (const void *obj, + hb_codepoint_t codepoint, + hb_codepoint_t *glyph) +{ + const Type *typed_obj = (const Type *) obj; + if (likely (typed_obj->get_glyph (codepoint, glyph))) + return true; + + if (codepoint <= 0x00FFu) + { + /* For symbol-encoded OpenType fonts, we duplicate the + * U+F000..F0FF range at U+0000..U+00FF. That's what + * Windows seems to do, and that's hinted about at: + * http://www.microsoft.com/typography/otspec/recom.htm + * under "Non-Standard (Symbol) Fonts". */ + return typed_obj->get_glyph (0xF000u + codepoint, glyph); + } + + return false; +} + struct hb_ot_face_cmap_accelerator_t { hb_cmap_get_glyph_func_t get_glyph_func; @@ -231,6 +253,7 @@ struct hb_ot_face_cmap_accelerator_t const OT::CmapSubtable *subtable = NULL; const OT::CmapSubtableFormat14 *subtable_uvs = NULL; + bool symbol = false; /* 32-bit subtables. */ if (!subtable) subtable = cmap->find_subtable (3, 10); if (!subtable) subtable = cmap->find_subtable (0, 6); @@ -241,7 +264,7 @@ struct hb_ot_face_cmap_accelerator_t if (!subtable) subtable = cmap->find_subtable (0, 2); if (!subtable) subtable = cmap->find_subtable (0, 1); if (!subtable) subtable = cmap->find_subtable (0, 0); - if (!subtable) subtable = cmap->find_subtable (3, 0); + if (!subtable)(subtable = cmap->find_subtable (3, 0)) && (symbol = true); /* Meh. */ if (!subtable) subtable = &OT::Null(OT::CmapSubtable); @@ -258,18 +281,21 @@ struct hb_ot_face_cmap_accelerator_t this->uvs_table = subtable_uvs; this->get_glyph_data = subtable; - switch (subtable->u.format) { - /* Accelerate format 4 and format 12. */ - default: this->get_glyph_func = get_glyph_from; break; - case 12: this->get_glyph_func = get_glyph_from; break; - case 4: - { - this->format4_accel.init (&subtable->u.format4); - this->get_glyph_data = &this->format4_accel; - this->get_glyph_func = this->format4_accel.get_glyph_func; + if (unlikely (symbol)) + this->get_glyph_func = get_glyph_from_symbol; + else + switch (subtable->u.format) { + /* Accelerate format 4 and format 12. */ + default: this->get_glyph_func = get_glyph_from; break; + case 12: this->get_glyph_func = get_glyph_from; break; + case 4: + { + this->format4_accel.init (&subtable->u.format4); + this->get_glyph_data = &this->format4_accel; + this->get_glyph_func = this->format4_accel.get_glyph_func; + } + break; } - break; - } } inline void fini (void) -- 2.7.4