diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 907fd4631..2589218de 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -1643,6 +1643,9 @@ struct GPOS : GSUBGPOS inline bool sanitize (hb_sanitize_context_t *c) const { return GSUBGPOS::sanitize (c); } + HB_INTERNAL bool is_blacklisted (hb_blob_t *blob, + hb_face_t *face) const; + typedef GSUBGPOS::accelerator_t accelerator_t; }; diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index 501f2308c..27bd440da 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -1486,6 +1486,9 @@ struct GSUB : GSUBGPOS inline bool sanitize (hb_sanitize_context_t *c) const { return GSUBGPOS::sanitize (c); } + HB_INTERNAL bool is_blacklisted (hb_blob_t *blob, + hb_face_t *face) const; + typedef GSUBGPOS::accelerator_t accelerator_t; }; diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh index 3d70c55c2..a9bfee155 100644 --- a/src/hb-ot-layout-gsubgpos.hh +++ b/src/hb-ot-layout-gsubgpos.hh @@ -2753,6 +2753,11 @@ struct GSUBGPOS inline void init (hb_face_t *face) { this->table = hb_sanitize_context_t().reference_table (face); + if (unlikely (this->table->is_blacklisted (this->table.get_blob (), face))) + { + hb_blob_destroy (this->table.get_blob ()); + this->table = hb_blob_get_empty (); + } this->lookup_count = table->get_lookup_count (); diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 6d6834fc7..d0b22efe3 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -34,15 +34,17 @@ #include "hb-ot-map.hh" #include "hb-map.hh" +#include "hb-ot-kern-table.hh" #include "hb-ot-layout-gdef-table.hh" #include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gpos-table.hh" #include "hb-ot-layout-base-table.hh" // Just so we compile it; unused otherwise #include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise -#include "hb-ot-kern-table.hh" #include "hb-ot-name-table.hh" +#include "hb-ot-os2-table.hh" #include "hb-aat-layout-lcar-table.hh" +#include "hb-aat-layout-morx-table.hh" /** @@ -284,6 +286,38 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font, * GSUB/GPOS */ +bool +OT::GSUB::is_blacklisted (hb_blob_t *blob HB_UNUSED, + hb_face_t *face) const +{ + /* Mac OS X prefers morx over GSUB. It also ships with various Indic fonts, + * all by 'MUTF' foundry (Tamil MN, Tamil Sangam MN, etc.), that have broken + * GSUB/GPOS tables. Some have GSUB with zero scripts, those are ignored by + * our morx/GSUB preference code. But if GSUB has non-zero scripts, we tend + * to prefer it over morx because we want to be consistent with other OpenType + * shapers. + * + * To work around broken Indic Mac system fonts, we ignore GSUB table if + * OS/2 VendorId is 'MUTF' and font has morx table as well. + * + * https://github.com/harfbuzz/harfbuzz/issues/1410 + * https://github.com/harfbuzz/harfbuzz/issues/1348 + * https://github.com/harfbuzz/harfbuzz/issues/1391 + */ + if (unlikely (face->table.OS2->achVendID == HB_TAG ('M','U','T','F') && + face->table.morx->has_data ())) + return true; + + return false; +} + +bool +OT::GPOS::is_blacklisted (hb_blob_t *blob HB_UNUSED, + hb_face_t *face HB_UNUSED) const +{ + return false; +} + static const OT::GSUBGPOS& get_gsubgpos_table (hb_face_t *face, hb_tag_t table_tag)