diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index d85456375..a98734a06 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -36,6 +36,15 @@ #include "hb-set-private.hh" +/* Private API corresponding to hb-ot-layout.h: */ + +HB_INTERNAL hb_bool_t +hb_ot_layout_table_find_feature (hb_face_t *face, + hb_tag_t table_tag, + hb_tag_t feature_tag, + unsigned int *feature_index); + + /* * GDEF */ diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 5570a819c..6fe7b6ca0 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -291,6 +291,28 @@ hb_ot_layout_table_get_feature_tags (hb_face_t *face, return g.get_feature_tags (start_offset, feature_count, feature_tags); } +hb_bool_t +hb_ot_layout_table_find_feature (hb_face_t *face, + hb_tag_t table_tag, + hb_tag_t feature_tag, + unsigned int *feature_index) +{ + ASSERT_STATIC (OT::Index::NOT_FOUND_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX); + const OT::GSUBGPOS &g = get_gsubgpos_table (face, table_tag); + + unsigned int num_features = g.get_feature_count (); + for (unsigned int i = 0; i < num_features; i++) + { + if (feature_tag == g.get_feature_tag (i)) { + if (feature_index) *feature_index = i; + return true; + } + } + + if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX; + return false; +} + unsigned int hb_ot_layout_script_get_language_tags (hb_face_t *face, diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh index 86b7e9faf..f9538af18 100644 --- a/src/hb-ot-map-private.hh +++ b/src/hb-ot-map-private.hh @@ -154,9 +154,10 @@ struct hb_ot_map_t enum hb_ot_map_feature_flags_t { F_NONE = 0x0000u, - F_GLOBAL = 0x0001u, - F_HAS_FALLBACK = 0x0002u, - F_MANUAL_ZWJ = 0x0004u + F_GLOBAL = 0x0001u, /* Feature applies to all characters; results in no mask allocated for it. */ + F_HAS_FALLBACK = 0x0002u, /* Has fallback implementation, so include mask bit even if feature not found. */ + F_MANUAL_ZWJ = 0x0004u, /* Don't skip over ZWJ when matching. */ + F_GLOBAL_SEARCH = 0x0008u /* If feature not found in LangSys, look for it in global feature list and pick one. */ }; /* Macro version for where const is desired. */ #define F_COMBINE(l,r) (hb_ot_map_feature_flags_t ((unsigned int) (l) | (unsigned int) (r))) diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index 4985eb22b..95bd04ee8 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -216,6 +216,16 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) info->tag, &feature_index[table_index]); } + if (!found && (info->flags & F_GLOBAL_SEARCH)) + { + for (unsigned int table_index = 0; table_index < 2; table_index++) + { + found |= hb_ot_layout_table_find_feature (face, + table_tags[table_index], + info->tag, + &feature_index[table_index]); + } + } if (!found && !(info->flags & F_HAS_FALLBACK)) continue; diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 00a212192..f20be2aac 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -102,7 +102,11 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, F_HAS_FALLBACK : F_NONE)); else { - map->add_global_bool_feature (HB_TAG('v','e','r','t')); + /* We really want to find a 'vert' feature if there's any in the font, no + * matter which script/langsys it is listed (or not) under. + * See various bugs referenced from: + * https://github.com/behdad/harfbuzz/issues/63 */ + map->add_feature (HB_TAG ('v','e','r','t'), 1, F_GLOBAL | F_GLOBAL_SEARCH); } if (planner->shaper->override_features)