diff options
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc')
-rw-r--r-- | src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc | 305 |
1 files changed, 239 insertions, 66 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc index 275a960d58..145ec76389 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc @@ -60,6 +60,92 @@ _hb_ot_layout_create (hb_face_t *face) layout->gpos_blob = OT::Sanitizer<OT::GPOS>::sanitize (face->reference_table (HB_OT_TAG_GPOS)); layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob); + /* The MATH table is rarely used, so only try and load it in _get_math. */ + layout->math_blob = NULL; + layout->math = NULL; + + { + /* + * The ugly business of blacklisting individual fonts' tables happen here! + * See this thread for why we finally had to bend in and do this: + * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html + */ + unsigned int gdef_len = hb_blob_get_length (layout->gdef_blob); + unsigned int gsub_len = hb_blob_get_length (layout->gsub_blob); + unsigned int gpos_len = hb_blob_get_length (layout->gpos_blob); + if (0 + /* sha1sum:c5ee92f0bca4bfb7d06c4d03e8cf9f9cf75d2e8a Windows 7? timesi.ttf */ + || (442 == gdef_len && 42038 == gpos_len && 2874 == gsub_len) + /* sha1sum:37fc8c16a0894ab7b749e35579856c73c840867b Windows 7? timesbi.ttf */ + || (430 == gdef_len && 40662 == gpos_len && 2874 == gsub_len) + /* sha1sum:19fc45110ea6cd3cdd0a5faca256a3797a069a80 Windows 7 timesi.ttf */ + || (442 == gdef_len && 39116 == gpos_len && 2874 == gsub_len) + /* sha1sum:6d2d3c9ed5b7de87bc84eae0df95ee5232ecde26 Windows 7 timesbi.ttf */ + || (430 == gdef_len && 39374 == gpos_len && 2874 == gsub_len) + /* sha1sum:8583225a8b49667c077b3525333f84af08c6bcd8 OS X 10.11.3 Times New Roman Italic.ttf */ + || (490 == gdef_len && 41638 == gpos_len && 3046 == gsub_len) + /* sha1sum:ec0f5a8751845355b7c3271d11f9918a966cb8c9 OS X 10.11.3 Times New Roman Bold Italic.ttf */ + || (478 == gdef_len && 41902 == gpos_len && 3046 == gsub_len) + ) + { + /* In certain versions of Times New Roman Italic and Bold Italic, + * ASCII double quotation mark U+0022, mapped to glyph 5, has wrong + * glyph class 3 (mark) in GDEF. Nuke the GDEF to avoid zero-width + * double-quote. See: + * https://lists.freedesktop.org/archives/harfbuzz/2016-February/005489.html + */ + if (3 == layout->gdef->get_glyph_class (5)) + layout->gdef = &OT::Null(OT::GDEF); + } + else if (0 + /* sha1sum:96eda93f7d33e79962451c6c39a6b51ee893ce8c tahoma.ttf from Windows 8 */ + || (898 == gdef_len && 46470 == gpos_len && 12554 == gsub_len) + /* sha1sum:20928dc06014e0cd120b6fc942d0c3b1a46ac2bc tahomabd.ttf from Windows 8 */ + || (910 == gdef_len && 47732 == gpos_len && 12566 == gsub_len) + /* sha1sum:4f95b7e4878f60fa3a39ca269618dfde9721a79e tahoma.ttf from Windows 8.1 */ + || (928 == gdef_len && 59332 == gpos_len && 23298 == gsub_len) + /* sha1sum:6d400781948517c3c0441ba42acb309584b73033 tahomabd.ttf from Windows 8.1 */ + || (940 == gdef_len && 60732 == gpos_len && 23310 == gsub_len) + /* sha1sum:e55fa2dfe957a9f7ec26be516a0e30b0c925f846 tahoma.ttf from Windows 10 */ + || (994 == gdef_len && 60336 == gpos_len && 24474 == gsub_len) + /* sha1sum:7199385abb4c2cc81c83a151a7599b6368e92343 tahomabd.ttf from Windows 10 */ + || (1006 == gdef_len && 61740 == gpos_len && 24470 == gsub_len) + /* sha1sum:b0d36cf5a2fbe746a3dd277bffc6756a820807a7 Tahoma.ttf from Mac OS X 10.9 */ + || (832 == gdef_len && 47162 == gpos_len && 7324 == gsub_len) + /* sha1sum:12fc4538e84d461771b30c18b5eb6bd434e30fba Tahoma Bold.ttf from Mac OS X 10.9 */ + || (844 == gdef_len && 45474 == gpos_len && 7302 == gsub_len) + /* sha1sum:73da7f025b238a3f737aa1fde22577a6370f77b0 himalaya.ttf from Windows 8 */ + || (192 == gdef_len && 7254 == gpos_len && 12638 == gsub_len) + /* sha1sum:6e80fd1c0b059bbee49272401583160dc1e6a427 himalaya.ttf from Windows 8.1 */ + || (192 == gdef_len && 7254 == gpos_len && 12690 == gsub_len) + /* 8d9267aea9cd2c852ecfb9f12a6e834bfaeafe44 cantarell-fonts-0.0.21/otf/Cantarell-Regular.otf */ + /* 983988ff7b47439ab79aeaf9a45bd4a2c5b9d371 cantarell-fonts-0.0.21/otf/Cantarell-Oblique.otf */ + || (188 == gdef_len && 3852 == gpos_len && 248 == gsub_len) + /* 2c0c90c6f6087ffbfea76589c93113a9cbb0e75f cantarell-fonts-0.0.21/otf/Cantarell-Bold.otf */ + /* 55461f5b853c6da88069ffcdf7f4dd3f8d7e3e6b cantarell-fonts-0.0.21/otf/Cantarell-Bold-Oblique.otf */ + || (188 == gdef_len && 3426 == gpos_len && 264 == gsub_len) + /* 6c93b63b64e8b2c93f5e824e78caca555dc887c7 padauk-2.80/Padauk-book.ttf */ + || (1046 == gdef_len && 17112 == gpos_len && 71788 == gsub_len) + /* d89b1664058359b8ec82e35d3531931125991fb9 padauk-2.80/Padauk-bookbold.ttf */ + || (1058 == gdef_len && 17514 == gpos_len && 71794 == gsub_len) + /* 824cfd193aaf6234b2b4dc0cf3c6ef576c0d00ef padauk-3.0/Padauk-book.ttf */ + || (1330 == gdef_len && 57938 == gpos_len && 109904 == gsub_len) + /* 91fcc10cf15e012d27571e075b3b4dfe31754a8a padauk-3.0/Padauk-bookbold.ttf */ + || (1330 == gdef_len && 58972 == gpos_len && 109904 == gsub_len) + ) + { + /* Many versions of Tahoma have bad GDEF tables that incorrectly classify some spacing marks + * such as certain IPA symbols as glyph class 3. So do older versions of Microsoft Himalaya, + * and the version of Cantarell shipped by Ubuntu 16.04. + * Nuke the GDEF tables of these fonts to avoid unwanted width-zeroing. + * See https://bugzilla.mozilla.org/show_bug.cgi?id=1279925 + * https://bugzilla.mozilla.org/show_bug.cgi?id=1279693 + * https://bugzilla.mozilla.org/show_bug.cgi?id=1279875 + */ + layout->gdef = &OT::Null(OT::GDEF); + } + } + layout->gsub_lookup_count = layout->gsub->get_lookup_count (); layout->gpos_lookup_count = layout->gpos->get_lookup_count (); @@ -95,6 +181,7 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout) hb_blob_destroy (layout->gdef_blob); hb_blob_destroy (layout->gsub_blob); hb_blob_destroy (layout->gpos_blob); + hb_blob_destroy (layout->math_blob); free (layout); } @@ -118,7 +205,6 @@ _get_gpos (hb_face_t *face) return *hb_ot_layout_from_face (face)->gpos; } - /* * GDEF */ @@ -130,6 +216,8 @@ hb_ot_layout_has_glyph_classes (hb_face_t *face) } /** + * hb_ot_layout_get_glyph_class: + * * Since: 0.9.7 **/ hb_ot_layout_glyph_class_t @@ -140,6 +228,8 @@ hb_ot_layout_get_glyph_class (hb_face_t *face, } /** + * hb_ot_layout_get_glyphs_in_class: + * * Since: 0.9.7 **/ void @@ -365,6 +455,8 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face, } /** + * hb_ot_layout_language_get_required_feature: + * * Since: 0.9.30 **/ hb_bool_t @@ -452,6 +544,8 @@ hb_ot_layout_language_find_feature (hb_face_t *face, } /** + * hb_ot_layout_feature_get_lookups: + * * Since: 0.9.7 **/ unsigned int @@ -462,13 +556,18 @@ hb_ot_layout_feature_get_lookups (hb_face_t *face, unsigned int *lookup_count /* IN/OUT */, unsigned int *lookup_indexes /* OUT */) { - const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); - const OT::Feature &f = g.get_feature (feature_index); - - return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes); + return hb_ot_layout_feature_with_variations_get_lookups (face, + table_tag, + feature_index, + HB_OT_LAYOUT_NO_VARIATIONS_INDEX, + start_offset, + lookup_count, + lookup_indexes); } /** + * hb_ot_layout_table_get_lookup_count: + * * Since: 0.9.22 **/ unsigned int @@ -629,6 +728,8 @@ _hb_ot_layout_collect_lookups_languages (hb_face_t *face, } /** + * hb_ot_layout_collect_lookups: + * * Since: 0.9.8 **/ void @@ -673,6 +774,8 @@ hb_ot_layout_collect_lookups (hb_face_t *face, } /** + * hb_ot_layout_lookup_collect_glyphs: + * * Since: 0.9.7 **/ void @@ -710,6 +813,38 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face, } +/* Variations support */ + +hb_bool_t +hb_ot_layout_table_find_feature_variations (hb_face_t *face, + hb_tag_t table_tag, + const int *coords, + unsigned int num_coords, + unsigned int *variations_index /* out */) +{ + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + + return g.find_variations_index (coords, num_coords, variations_index); +} + +unsigned int +hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face, + hb_tag_t table_tag, + unsigned int feature_index, + unsigned int variations_index, + unsigned int start_offset, + unsigned int *lookup_count /* IN/OUT */, + unsigned int *lookup_indexes /* OUT */) +{ + ASSERT_STATIC (OT::FeatureVariations::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_VARIATIONS_INDEX); + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + + const OT::Feature &f = g.get_feature_variation (feature_index, variations_index); + + return f.get_lookup_indexes (start_offset, lookup_count, lookup_indexes); +} + + /* * OT::GSUB */ @@ -721,6 +856,8 @@ hb_ot_layout_has_substitution (hb_face_t *face) } /** + * hb_ot_layout_lookup_would_substitute: + * * Since: 0.9.7 **/ hb_bool_t @@ -742,7 +879,7 @@ hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face, hb_bool_t zero_context) { if (unlikely (lookup_index >= hb_ot_layout_from_face (face)->gsub_lookup_count)) return false; - OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, zero_context); + OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context); const OT::SubstLookup& l = hb_ot_layout_from_face (face)->gsub->get_lookup (lookup_index); @@ -755,13 +892,9 @@ hb_ot_layout_substitute_start (hb_font_t *font, hb_buffer_t *buffer) OT::GSUB::substitute_start (font, buffer); } -void -hb_ot_layout_substitute_finish (hb_font_t *font, hb_buffer_t *buffer) -{ - OT::GSUB::substitute_finish (font, buffer); -} - /** + * hb_ot_layout_lookup_substitute_closure: + * * Since: 0.9.7 **/ void @@ -793,12 +926,20 @@ hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer) } void -hb_ot_layout_position_finish (hb_font_t *font, hb_buffer_t *buffer) +hb_ot_layout_position_finish_advances (hb_font_t *font, hb_buffer_t *buffer) +{ + OT::GPOS::position_finish_advances (font, buffer); +} + +void +hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer) { - OT::GPOS::position_finish (font, buffer); + OT::GPOS::position_finish_offsets (font, buffer); } /** + * hb_ot_layout_get_size_params: + * * Since: 0.9.10 **/ hb_bool_t @@ -882,20 +1023,79 @@ struct GPOSProxy }; -template <typename Obj> +struct hb_get_subtables_context_t : + OT::hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY> +{ + template <typename Type> + static inline bool apply_to (const void *obj, OT::hb_apply_context_t *c) + { + const Type *typed_obj = (const Type *) obj; + return typed_obj->apply (c); + } + + typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_apply_context_t *c); + + struct hb_applicable_t + { + inline void init (const void *obj_, hb_apply_func_t apply_func_) + { + obj = obj_; + apply_func = apply_func_; + } + + inline bool apply (OT::hb_apply_context_t *c) const { return apply_func (obj, c); } + + private: + const void *obj; + hb_apply_func_t apply_func; + }; + + typedef hb_auto_array_t<hb_applicable_t> array_t; + + /* Dispatch interface. */ + inline const char *get_name (void) { return "GET_SUBTABLES"; } + template <typename T> + inline return_t dispatch (const T &obj) + { + hb_applicable_t *entry = array.push(); + if (likely (entry)) + entry->init (&obj, apply_to<T>); + return HB_VOID; + } + static return_t default_return_value (void) { return HB_VOID; } + bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; } + + hb_get_subtables_context_t (array_t &array_) : + array (array_), + debug_depth (0) {} + + array_t &array; + unsigned int debug_depth; +}; + static inline bool apply_forward (OT::hb_apply_context_t *c, - const Obj &obj, - const hb_ot_layout_lookup_accelerator_t &accel) + const hb_ot_layout_lookup_accelerator_t &accel, + const hb_get_subtables_context_t::array_t &subtables) { bool ret = false; hb_buffer_t *buffer = c->buffer; - while (buffer->idx < buffer->len) + while (buffer->idx < buffer->len && !buffer->in_error) { + bool applied = false; if (accel.may_have (buffer->cur().codepoint) && (buffer->cur().mask & c->lookup_mask) && - c->check_glyph_property (&buffer->cur(), c->lookup_props) && - obj.apply (c)) + c->check_glyph_property (&buffer->cur(), c->lookup_props)) + { + for (unsigned int i = 0; i < subtables.len; i++) + if (subtables[i].apply (c)) + { + applied = true; + break; + } + } + + if (applied) ret = true; else buffer->next_glyph (); @@ -903,11 +1103,10 @@ apply_forward (OT::hb_apply_context_t *c, return ret; } -template <typename Obj> static inline bool apply_backward (OT::hb_apply_context_t *c, - const Obj &obj, - const hb_ot_layout_lookup_accelerator_t &accel) + const hb_ot_layout_lookup_accelerator_t &accel, + const hb_get_subtables_context_t::array_t &subtables) { bool ret = false; hb_buffer_t *buffer = c->buffer; @@ -915,9 +1114,15 @@ apply_backward (OT::hb_apply_context_t *c, { if (accel.may_have (buffer->cur().codepoint) && (buffer->cur().mask & c->lookup_mask) && - c->check_glyph_property (&buffer->cur(), c->lookup_props) && - obj.apply (c)) - ret = true; + c->check_glyph_property (&buffer->cur(), c->lookup_props)) + { + for (unsigned int i = 0; i < subtables.len; i++) + if (subtables[i].apply (c)) + { + ret = true; + break; + } + } /* The reverse lookup doesn't "advance" cursor (for good reason). */ buffer->idx--; @@ -926,26 +1131,6 @@ apply_backward (OT::hb_apply_context_t *c, return ret; } -struct hb_apply_forward_context_t : - OT::hb_dispatch_context_t<hb_apply_forward_context_t, bool, HB_DEBUG_APPLY> -{ - inline const char *get_name (void) { return "APPLY_FWD"; } - template <typename T> - inline return_t dispatch (const T &obj) { return apply_forward (c, obj, accel); } - static return_t default_return_value (void) { return false; } - bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return true; } - - hb_apply_forward_context_t (OT::hb_apply_context_t *c_, - const hb_ot_layout_lookup_accelerator_t &accel_) : - c (c_), - accel (accel_), - debug_depth (0) {} - - OT::hb_apply_context_t *c; - const hb_ot_layout_lookup_accelerator_t &accel; - unsigned int debug_depth; -}; - template <typename Proxy> static inline void apply_string (OT::hb_apply_context_t *c, @@ -959,6 +1144,10 @@ apply_string (OT::hb_apply_context_t *c, c->set_lookup_props (lookup.get_props ()); + hb_get_subtables_context_t::array_t subtables; + hb_get_subtables_context_t c_get_subtables (subtables); + lookup.dispatch (&c_get_subtables); + if (likely (!lookup.is_reverse ())) { /* in/out forward substitution/positioning */ @@ -967,13 +1156,7 @@ apply_string (OT::hb_apply_context_t *c, buffer->idx = 0; bool ret; - if (lookup.get_subtable_count () == 1) - { - hb_apply_forward_context_t c_forward (c, accel); - ret = lookup.dispatch (&c_forward); - } - else - ret = apply_forward (c, lookup, accel); + ret = apply_forward (c, accel, subtables); if (ret) { if (!Proxy::inplace) @@ -989,7 +1172,7 @@ apply_string (OT::hb_apply_context_t *c, buffer->remove_output (); buffer->idx = buffer->len - 1; - apply_backward (c, lookup, accel); + apply_backward (c, accel, subtables); } } @@ -1008,25 +1191,15 @@ inline void hb_ot_map_t::apply (const Proxy &proxy, const stage_map_t *stage = &stages[table_index][stage_index]; for (; i < stage->last_lookup; i++) { -#if 0 - char buf[4096]; - hb_buffer_serialize_glyphs (buffer, 0, buffer->len, - buf, sizeof (buf), NULL, - font, - HB_BUFFER_SERIALIZE_FORMAT_TEXT, - Proxy::table_index == 0 ? - HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS : - HB_BUFFER_SERIALIZE_FLAG_DEFAULT); - printf ("buf: [%s]\n", buf); -#endif - unsigned int lookup_index = lookups[table_index][i].index; + if (!buffer->message (font, "start lookup %d", lookup_index)) continue; c.set_lookup_index (lookup_index); c.set_lookup_mask (lookups[table_index][i].mask); c.set_auto_zwj (lookups[table_index][i].auto_zwj); apply_string<Proxy> (&c, proxy.table.get_lookup (lookup_index), proxy.accels[lookup_index]); + (void) buffer->message (font, "end lookup %d", lookup_index); } if (stage->pause_func) |