Handle non-exclusive features when mapping OpenType tags to AAT feature type/selector pairs.
Fixes #2290.
This commit is contained in:
parent
0d5695983e
commit
573b6bf826
|
@ -129,6 +129,8 @@ struct FeatureName
|
||||||
|
|
||||||
hb_ot_name_id_t get_feature_name_id () const { return nameIndex; }
|
hb_ot_name_id_t get_feature_name_id () const { return nameIndex; }
|
||||||
|
|
||||||
|
bool is_exclusive () const { return featureFlags & Exclusive; }
|
||||||
|
|
||||||
/* A FeatureName with no settings is meaningless */
|
/* A FeatureName with no settings is meaningless */
|
||||||
bool has_data () const { return nSettings; }
|
bool has_data () const { return nSettings; }
|
||||||
|
|
||||||
|
|
|
@ -948,8 +948,10 @@ struct Chain
|
||||||
hb_aat_layout_feature_type_t type = (hb_aat_layout_feature_type_t) (unsigned int) feature.featureType;
|
hb_aat_layout_feature_type_t type = (hb_aat_layout_feature_type_t) (unsigned int) feature.featureType;
|
||||||
hb_aat_layout_feature_selector_t setting = (hb_aat_layout_feature_selector_t) (unsigned int) feature.featureSetting;
|
hb_aat_layout_feature_selector_t setting = (hb_aat_layout_feature_selector_t) (unsigned int) feature.featureSetting;
|
||||||
retry:
|
retry:
|
||||||
const hb_aat_map_builder_t::feature_info_t *info = map->features.bsearch (type);
|
// Check whether this type/setting pair was requested in the map, and if so, apply its flags.
|
||||||
if (info && info->setting == setting)
|
// (The search here only looks at the type and setting fields of feature_info_t.)
|
||||||
|
hb_aat_map_builder_t::feature_info_t info = { type, setting, false, 0 };
|
||||||
|
if (map->features.bsearch (info))
|
||||||
{
|
{
|
||||||
flags &= feature.disableFlags;
|
flags &= feature.disableFlags;
|
||||||
flags |= feature.enableFlags;
|
flags |= feature.enableFlags;
|
||||||
|
|
|
@ -48,12 +48,15 @@ void hb_aat_map_builder_t::add_feature (hb_tag_t tag, unsigned value)
|
||||||
info->type = HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES;
|
info->type = HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES;
|
||||||
info->setting = (hb_aat_layout_feature_selector_t) value;
|
info->setting = (hb_aat_layout_feature_selector_t) value;
|
||||||
info->seq = features.length;
|
info->seq = features.length;
|
||||||
|
info->is_exclusive = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const hb_aat_feature_mapping_t *mapping = hb_aat_layout_find_feature_mapping (tag);
|
const hb_aat_feature_mapping_t *mapping = hb_aat_layout_find_feature_mapping (tag);
|
||||||
if (!mapping) return;
|
if (!mapping) return;
|
||||||
if (!face->table.feat->exposes_feature (mapping->aatFeatureType))
|
|
||||||
|
const AAT::FeatureName* feature = &face->table.feat->get_feature (mapping->aatFeatureType);
|
||||||
|
if (!feature->has_data ())
|
||||||
{
|
{
|
||||||
/* Special case: Chain::compile_flags will fall back to the deprecated version of
|
/* Special case: Chain::compile_flags will fall back to the deprecated version of
|
||||||
* small-caps if necessary, so we need to check for that possibility.
|
* small-caps if necessary, so we need to check for that possibility.
|
||||||
|
@ -61,7 +64,8 @@ void hb_aat_map_builder_t::add_feature (hb_tag_t tag, unsigned value)
|
||||||
if (mapping->aatFeatureType == HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE &&
|
if (mapping->aatFeatureType == HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE &&
|
||||||
mapping->selectorToEnable == HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS)
|
mapping->selectorToEnable == HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS)
|
||||||
{
|
{
|
||||||
if (!face->table.feat->exposes_feature (HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE)) return;
|
feature = &face->table.feat->get_feature (HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE);
|
||||||
|
if (!feature->has_data ()) return;
|
||||||
}
|
}
|
||||||
else return;
|
else return;
|
||||||
}
|
}
|
||||||
|
@ -70,6 +74,7 @@ void hb_aat_map_builder_t::add_feature (hb_tag_t tag, unsigned value)
|
||||||
info->type = mapping->aatFeatureType;
|
info->type = mapping->aatFeatureType;
|
||||||
info->setting = value ? mapping->selectorToEnable : mapping->selectorToDisable;
|
info->setting = value ? mapping->selectorToEnable : mapping->selectorToDisable;
|
||||||
info->seq = features.length;
|
info->seq = features.length;
|
||||||
|
info->is_exclusive = feature->is_exclusive ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -81,7 +86,11 @@ hb_aat_map_builder_t::compile (hb_aat_map_t &m)
|
||||||
features.qsort ();
|
features.qsort ();
|
||||||
unsigned int j = 0;
|
unsigned int j = 0;
|
||||||
for (unsigned int i = 1; i < features.length; i++)
|
for (unsigned int i = 1; i < features.length; i++)
|
||||||
if (features[i].type != features[j].type)
|
if (features[i].type != features[j].type ||
|
||||||
|
/* Nonexclusive feature selectors come in even/odd pairs to turn a setting on/off
|
||||||
|
* respectively, so we mask out the low-order bit when checking for "duplicates"
|
||||||
|
* (selectors referring to the same feature setting) here. */
|
||||||
|
(!features[i].is_exclusive && ((features[i].setting & ~1) != (features[j].setting & ~1))))
|
||||||
features[++j] = features[i];
|
features[++j] = features[i];
|
||||||
features.shrink (j + 1);
|
features.shrink (j + 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,19 +64,24 @@ struct hb_aat_map_builder_t
|
||||||
{
|
{
|
||||||
hb_aat_layout_feature_type_t type;
|
hb_aat_layout_feature_type_t type;
|
||||||
hb_aat_layout_feature_selector_t setting;
|
hb_aat_layout_feature_selector_t setting;
|
||||||
|
bool is_exclusive;
|
||||||
unsigned seq; /* For stable sorting only. */
|
unsigned seq; /* For stable sorting only. */
|
||||||
|
|
||||||
HB_INTERNAL static int cmp (const void *pa, const void *pb)
|
HB_INTERNAL static int cmp (const void *pa, const void *pb)
|
||||||
{
|
{
|
||||||
const feature_info_t *a = (const feature_info_t *) pa;
|
const feature_info_t *a = (const feature_info_t *) pa;
|
||||||
const feature_info_t *b = (const feature_info_t *) pb;
|
const feature_info_t *b = (const feature_info_t *) pb;
|
||||||
return (a->type != b->type) ? (a->type < b->type ? -1 : 1) :
|
if (a->type != b->type) return (a->type < b->type ? -1 : 1);
|
||||||
(a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
|
if (!a->is_exclusive &&
|
||||||
|
(a->setting & ~1) != (b->setting & ~1)) return (a->setting < b->setting ? -1 : 1);
|
||||||
|
return (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cmp (hb_aat_layout_feature_type_t ty) const
|
/* compares type & setting only, not is_exclusive flag or seq number */
|
||||||
|
int cmp (const feature_info_t& f) const
|
||||||
{
|
{
|
||||||
return (ty != type) ? (ty < type ? -1 : 1) : 0;
|
return (f.type != type) ? (f.type < type ? -1 : 1) :
|
||||||
|
(f.setting != setting) ? (f.setting < setting ? -1 : 1) : 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue