[aat] Always generate a feature range

This commit is contained in:
Behdad Esfahbod 2023-01-09 21:42:19 -07:00
parent db4c874758
commit c08308a83c
1 changed files with 69 additions and 68 deletions

View File

@ -85,80 +85,81 @@ void
hb_aat_map_builder_t::compile (hb_aat_map_t &m) hb_aat_map_builder_t::compile (hb_aat_map_t &m)
{ {
/* Compute active features per range, and compile each. */ /* Compute active features per range, and compile each. */
if (features.length)
/* Sort features by start/end events. */
hb_vector_t<feature_event_t> feature_events;
for (unsigned int i = 0; i < features.length; i++)
{ {
/* Sort features by start/end events. */ auto &feature = features[i];
hb_vector_t<feature_event_t> feature_events;
for (unsigned int i = 0; i < features.length; i++) if (features[i].start == features[i].end)
continue;
feature_event_t *event;
event = feature_events.push ();
event->index = features[i].start;
event->start = true;
event->feature = feature.info;
event = feature_events.push ();
event->index = features[i].end;
event->start = false;
event->feature = feature.info;
}
feature_events.qsort ();
/* Add a strategic final event. */
{
feature_info_t feature;
feature.seq = features.length + 1;
feature_event_t *event = feature_events.push ();
event->index = -1; /* This value does magic. */
event->start = false;
event->feature = feature;
}
/* Scan events and save features for each range. */
hb_sorted_vector_t<feature_info_t> active_features;
unsigned int last_index = 0;
for (unsigned int i = 0; i < feature_events.length; i++)
{
feature_event_t *event = &feature_events[i];
if (event->index != last_index)
{ {
auto &feature = features[i]; /* Save a snapshot of active features and the range. */
feature_event_t *event; /* Sort features and merge duplicates */
current_features = active_features;
event = feature_events.push (); range_first = last_index;
event->index = features[i].start; range_last = event->index - 1;
event->start = true; if (current_features.length)
event->feature = feature.info;
event = feature_events.push ();
event->index = features[i].end;
event->start = false;
event->feature = feature.info;
}
feature_events.qsort ();
/* Add a strategic final event. */
{
feature_info_t feature;
feature.seq = features.length + 1;
feature_event_t *event = feature_events.push ();
event->index = 0; /* This value does magic. */
event->start = false;
event->feature = feature;
}
/* Scan events and save features for each range. */
hb_sorted_vector_t<feature_info_t> active_features;
unsigned int last_index = 0;
for (unsigned int i = 0; i < feature_events.length; i++)
{
feature_event_t *event = &feature_events[i];
if (event->index != last_index)
{ {
/* Save a snapshot of active features and the range. */ current_features.qsort ();
unsigned int j = 0;
/* Sort features and merge duplicates */ for (unsigned int i = 1; i < current_features.length; i++)
current_features = active_features; if (current_features[i].type != current_features[j].type ||
range_first = last_index; /* Nonexclusive feature selectors come in even/odd pairs to turn a setting on/off
range_last = event->index - 1; * respectively, so we mask out the low-order bit when checking for "duplicates"
if (current_features.length) * (selectors referring to the same feature setting) here. */
{ (!current_features[i].is_exclusive && ((current_features[i].setting & ~1) != (current_features[j].setting & ~1))))
current_features.qsort (); current_features[++j] = current_features[i];
unsigned int j = 0; current_features.shrink (j + 1);
for (unsigned int i = 1; i < current_features.length; i++)
if (current_features[i].type != current_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. */
(!current_features[i].is_exclusive && ((current_features[i].setting & ~1) != (current_features[j].setting & ~1))))
current_features[++j] = current_features[i];
current_features.shrink (j + 1);
}
hb_aat_layout_compile_map (this, &m);
last_index = event->index;
} }
if (event->start) hb_aat_layout_compile_map (this, &m);
{
active_features.push (event->feature); last_index = event->index;
} else { }
feature_info_t *feature = active_features.lsearch (event->feature);
if (feature) if (event->start)
active_features.remove_ordered (feature - active_features.arrayZ); {
} active_features.push (event->feature);
} else {
feature_info_t *feature = active_features.lsearch (event->feature);
if (feature)
active_features.remove_ordered (feature - active_features.arrayZ);
} }
} }
} }