Revert "[aat] Support feature ranges"

This reverts commit 1b7994cb3a.

Broke Zapfino with partial ligature disabling. Debugging.
This commit is contained in:
Behdad Esfahbod 2023-01-09 21:29:19 -07:00
parent adfd5dd7a9
commit 6a7a38521f
9 changed files with 130 additions and 239 deletions

View File

@ -28,7 +28,6 @@
#define HB_AAT_LAYOUT_COMMON_HH #define HB_AAT_LAYOUT_COMMON_HH
#include "hb-aat-layout.hh" #include "hb-aat-layout.hh"
#include "hb-aat-map.hh"
#include "hb-open-type.hh" #include "hb-open-type.hh"
namespace OT { namespace OT {
@ -40,43 +39,6 @@ namespace AAT {
using namespace OT; using namespace OT;
struct ankr;
struct hb_aat_apply_context_t :
hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
{
const char *get_name () { return "APPLY"; }
template <typename T>
return_t dispatch (const T &obj) { return obj.apply (this); }
static return_t default_return_value () { return false; }
bool stop_sublookup_iteration (return_t r) const { return r; }
const hb_ot_shape_plan_t *plan;
hb_font_t *font;
hb_face_t *face;
hb_buffer_t *buffer;
hb_sanitize_context_t sanitizer;
const ankr *ankr_table;
const OT::GDEF *gdef_table;
const hb_sorted_vector_t<hb_aat_map_t::range_flags_t> *range_flags = nullptr;
hb_mask_t subtable_flags = 0;
/* Unused. For debug tracing only. */
unsigned int lookup_index;
HB_INTERNAL hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
hb_font_t *font_,
hb_buffer_t *buffer_,
hb_blob_t *blob = const_cast<hb_blob_t *> (&Null (hb_blob_t)));
HB_INTERNAL ~hb_aat_apply_context_t ();
HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_);
void set_lookup_index (unsigned int i) { lookup_index = i; }
};
/* /*
* Lookup Table * Lookup Table
*/ */
@ -778,44 +740,16 @@ struct StateTableDriver
num_glyphs (face_->get_num_glyphs ()) {} num_glyphs (face_->get_num_glyphs ()) {}
template <typename context_t> template <typename context_t>
void drive (context_t *c, hb_aat_apply_context_t *ac) void drive (context_t *c)
{ {
if (!c->in_place) if (!c->in_place)
buffer->clear_output (); buffer->clear_output ();
int state = StateTableT::STATE_START_OF_TEXT; int state = StateTableT::STATE_START_OF_TEXT;
auto *last_range = ac->range_flags && (*ac->range_flags) ? &(*ac->range_flags)[0] : nullptr;
for (buffer->idx = 0; buffer->successful;) for (buffer->idx = 0; buffer->successful;)
{ {
if (last_range)
{
auto *range = last_range;
if (buffer->idx < buffer->len)
{
unsigned cluster = buffer->cur().cluster;
while (cluster < range->cluster_first)
range--;
while (cluster > range->cluster_last)
range++;
if (range != last_range)
state = StateTableT::STATE_START_OF_TEXT;
last_range = range;
}
if (!(range->flags & ac->subtable_flags))
{
if (buffer->idx == buffer->len || unlikely (!buffer->successful))
break;
(void) buffer->next_glyph ();
continue;
}
}
unsigned int klass = buffer->idx < buffer->len ? unsigned int klass = buffer->idx < buffer->len ?
machine.get_class (buffer->cur().codepoint, num_glyphs) : machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) :
(unsigned) StateTableT::CLASS_END_OF_TEXT; (unsigned) StateTableT::CLASS_END_OF_TEXT;
DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx); DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
const EntryT &entry = machine.get_entry (state, klass); const EntryT &entry = machine.get_entry (state, klass);
@ -911,6 +845,41 @@ struct StateTableDriver
}; };
struct ankr;
struct hb_aat_apply_context_t :
hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
{
const char *get_name () { return "APPLY"; }
template <typename T>
return_t dispatch (const T &obj) { return obj.apply (this); }
static return_t default_return_value () { return false; }
bool stop_sublookup_iteration (return_t r) const { return r; }
const hb_ot_shape_plan_t *plan;
hb_font_t *font;
hb_face_t *face;
hb_buffer_t *buffer;
hb_sanitize_context_t sanitizer;
const ankr *ankr_table;
const OT::GDEF *gdef_table;
/* Unused. For debug tracing only. */
unsigned int lookup_index;
HB_INTERNAL hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
hb_font_t *font_,
hb_buffer_t *buffer_,
hb_blob_t *blob = const_cast<hb_blob_t *> (&Null (hb_blob_t)));
HB_INTERNAL ~hb_aat_apply_context_t ();
HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_);
void set_lookup_index (unsigned int i) { lookup_index = i; }
};
} /* namespace AAT */ } /* namespace AAT */

View File

@ -350,7 +350,7 @@ struct KerxSubTableFormat1
driver_context_t dc (this, c); driver_context_t dc (this, c);
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->font->face); StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->font->face);
driver.drive (&dc, c); driver.drive (&dc);
return_trace (true); return_trace (true);
} }
@ -594,7 +594,7 @@ struct KerxSubTableFormat4
driver_context_t dc (this, c); driver_context_t dc (this, c);
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->font->face); StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->font->face);
driver.drive (&dc, c); driver.drive (&dc);
return_trace (true); return_trace (true);
} }

View File

@ -169,7 +169,7 @@ struct RearrangementSubtable
driver_context_t dc (this); driver_context_t dc (this);
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
driver.drive (&dc, c); driver.drive (&dc);
return_trace (dc.ret); return_trace (dc.ret);
} }
@ -325,7 +325,7 @@ struct ContextualSubtable
driver_context_t dc (this, c); driver_context_t dc (this, c);
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
driver.drive (&dc, c); driver.drive (&dc);
return_trace (dc.ret); return_trace (dc.ret);
} }
@ -577,7 +577,7 @@ struct LigatureSubtable
driver_context_t dc (this, c); driver_context_t dc (this, c);
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
driver.drive (&dc, c); driver.drive (&dc);
return_trace (dc.ret); return_trace (dc.ret);
} }
@ -820,7 +820,7 @@ struct InsertionSubtable
driver_context_t dc (this, c); driver_context_t dc (this, c);
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
driver.drive (&dc, c); driver.drive (&dc);
return_trace (dc.ret); return_trace (dc.ret);
} }
@ -968,7 +968,7 @@ struct Chain
// Check whether this type/setting pair was requested in the map, and if so, apply its flags. // Check whether this type/setting pair was requested in the map, and if so, apply its flags.
// (The search here only looks at the type and setting fields of feature_info_t.) // (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 }; hb_aat_map_builder_t::feature_info_t info = { type, setting, false, 0 };
if (map->current_features.bsearch (info)) if (map->features.bsearch (info))
{ {
flags &= feature.disableFlags; flags &= feature.disableFlags;
flags |= feature.enableFlags; flags |= feature.enableFlags;
@ -994,7 +994,8 @@ struct Chain
return flags; return flags;
} }
void apply (hb_aat_apply_context_t *c) const void apply (hb_aat_apply_context_t *c,
hb_mask_t flags) const
{ {
const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount)); const ChainSubtable<Types> *subtable = &StructAfter<ChainSubtable<Types>> (featureZ.as_array (featureCount));
unsigned int count = subtableCount; unsigned int count = subtableCount;
@ -1002,9 +1003,8 @@ struct Chain
{ {
bool reverse; bool reverse;
if (c->range_flags->length == 1 && !(subtable->subFeatureFlags & (*c->range_flags)[0].flags)) if (!(subtable->subFeatureFlags & flags))
goto skip; goto skip;
c->subtable_flags = subtable->subFeatureFlags;
if (!(subtable->get_coverage() & ChainSubtable<Types>::AllDirections) && if (!(subtable->get_coverage() & ChainSubtable<Types>::AllDirections) &&
HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) != HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
@ -1120,18 +1120,14 @@ struct mortmorx
{ {
const Chain<Types> *chain = &firstChain; const Chain<Types> *chain = &firstChain;
unsigned int count = chainCount; unsigned int count = chainCount;
map->chain_flags.resize (count);
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
{ {
map->chain_flags[i].push (hb_aat_map_t::range_flags_t {chain->compile_flags (mapper), map->chain_flags.push (chain->compile_flags (mapper));
mapper->range_first,
mapper->range_last});
chain = &StructAfter<Chain<Types>> (*chain); chain = &StructAfter<Chain<Types>> (*chain);
} }
} }
void apply (hb_aat_apply_context_t *c, void apply (hb_aat_apply_context_t *c) const
const hb_aat_map_t &map) const
{ {
if (unlikely (!c->buffer->successful)) return; if (unlikely (!c->buffer->successful)) return;
c->set_lookup_index (0); c->set_lookup_index (0);
@ -1139,8 +1135,7 @@ struct mortmorx
unsigned int count = chainCount; unsigned int count = chainCount;
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
{ {
c->range_flags = &map.chain_flags[i]; chain->apply (c, c->plan->aat_map.chain_flags[i]);
chain->apply (c);
if (unlikely (!c->buffer->successful)) return; if (unlikely (!c->buffer->successful)) return;
chain = &StructAfter<Chain<Types>> (*chain); chain = &StructAfter<Chain<Types>> (*chain);
} }

View File

@ -244,23 +244,15 @@ hb_aat_layout_has_substitution (hb_face_t *face)
void void
hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan, hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
hb_font_t *font, hb_font_t *font,
hb_buffer_t *buffer, hb_buffer_t *buffer)
const hb_feature_t *features,
unsigned num_features)
{ {
hb_aat_map_builder_t builder (font->face, plan->props);
for (unsigned i = 0; i < num_features; i++)
builder.add_feature (features[i]);
hb_aat_map_t map;
builder.compile (map);
hb_blob_t *morx_blob = font->face->table.morx.get_blob (); hb_blob_t *morx_blob = font->face->table.morx.get_blob ();
const AAT::morx& morx = *morx_blob->as<AAT::morx> (); const AAT::morx& morx = *morx_blob->as<AAT::morx> ();
if (morx.has_data ()) if (morx.has_data ())
{ {
AAT::hb_aat_apply_context_t c (plan, font, buffer, morx_blob); AAT::hb_aat_apply_context_t c (plan, font, buffer, morx_blob);
if (!buffer->message (font, "start table morx")) return; if (!buffer->message (font, "start table morx")) return;
morx.apply (&c, map); morx.apply (&c);
(void) buffer->message (font, "end table morx"); (void) buffer->message (font, "end table morx");
return; return;
} }
@ -271,7 +263,7 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
{ {
AAT::hb_aat_apply_context_t c (plan, font, buffer, mort_blob); AAT::hb_aat_apply_context_t c (plan, font, buffer, mort_blob);
if (!buffer->message (font, "start table mort")) return; if (!buffer->message (font, "start table mort")) return;
mort.apply (&c, map); mort.apply (&c);
(void) buffer->message (font, "end table mort"); (void) buffer->message (font, "end table mort");
return; return;
} }

View File

@ -53,9 +53,7 @@ hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
HB_INTERNAL void HB_INTERNAL void
hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan, hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan,
hb_font_t *font, hb_font_t *font,
hb_buffer_t *buffer, hb_buffer_t *buffer);
const hb_feature_t *features,
unsigned num_features);
HB_INTERNAL void HB_INTERNAL void
hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer); hb_aat_layout_zero_width_deleted_glyphs (hb_buffer_t *buffer);

View File

@ -36,29 +36,27 @@
#include "hb-aat-layout-feat-table.hh" #include "hb-aat-layout-feat-table.hh"
void hb_aat_map_builder_t::add_feature (const hb_feature_t &feature) void hb_aat_map_builder_t::add_feature (hb_tag_t tag, unsigned value)
{ {
if (!face->table.feat->has_data ()) return; if (!face->table.feat->has_data ()) return;
if (feature.tag == HB_TAG ('a','a','l','t')) if (tag == HB_TAG ('a','a','l','t'))
{ {
if (!face->table.feat->exposes_feature (HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES)) if (!face->table.feat->exposes_feature (HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES))
return; return;
feature_range_t *range = features.push(); feature_info_t *info = features.push();
range->start = feature.start; info->type = HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES;
range->end = feature.end; info->setting = (hb_aat_layout_feature_selector_t) value;
range->info.type = HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES; info->seq = features.length;
range->info.setting = (hb_aat_layout_feature_selector_t) feature.value; info->is_exclusive = true;
range->info.seq = features.length;
range->info.is_exclusive = true;
return; return;
} }
const hb_aat_feature_mapping_t *mapping = hb_aat_layout_find_feature_mapping (feature.tag); const hb_aat_feature_mapping_t *mapping = hb_aat_layout_find_feature_mapping (tag);
if (!mapping) return; if (!mapping) return;
const AAT::FeatureName* feature_name = &face->table.feat->get_feature (mapping->aatFeatureType); const AAT::FeatureName* feature = &face->table.feat->get_feature (mapping->aatFeatureType);
if (!feature_name->has_data ()) 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.
@ -66,101 +64,38 @@ void hb_aat_map_builder_t::add_feature (const hb_feature_t &feature)
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)
{ {
feature_name = &face->table.feat->get_feature (HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE); feature = &face->table.feat->get_feature (HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE);
if (!feature_name->has_data ()) return; if (!feature->has_data ()) return;
} }
else return; else return;
} }
feature_range_t *range = features.push(); feature_info_t *info = features.push();
range->start = feature.start; info->type = mapping->aatFeatureType;
range->end = feature.end; info->setting = value ? mapping->selectorToEnable : mapping->selectorToDisable;
range->info.type = mapping->aatFeatureType; info->seq = features.length;
range->info.setting = feature.value ? mapping->selectorToEnable : mapping->selectorToDisable; info->is_exclusive = feature->is_exclusive ();
range->info.seq = features.length;
range->info.is_exclusive = feature_name->is_exclusive ();
} }
void 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. */ /* Sort features and merge duplicates */
if (features.length) if (features.length)
{ {
/* Sort features by start/end events. */ features.qsort ();
hb_vector_t<feature_event_t> feature_events; unsigned int j = 0;
for (unsigned int i = 0; i < features.length; i++) for (unsigned int i = 1; i < features.length; i++)
{ if (features[i].type != features[j].type ||
auto &feature = features[i]; /* 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"
feature_event_t *event; * (selectors referring to the same feature setting) here. */
(!features[i].is_exclusive && ((features[i].setting & ~1) != (features[j].setting & ~1))))
event = feature_events.push (); features[++j] = features[i];
event->index = features[i].start; features.shrink (j + 1);
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 = 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. */
/* Sort features and merge duplicates */
current_features = active_features;
range_first = last_index;
range_last = event->index - 1;
if (current_features.length)
{
current_features.qsort ();
unsigned int j = 0;
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)
{
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);
}
}
} }
hb_aat_layout_compile_map (this, &m);
} }

View File

@ -35,15 +35,16 @@ struct hb_aat_map_t
friend struct hb_aat_map_builder_t; friend struct hb_aat_map_builder_t;
public: public:
struct range_flags_t
void init ()
{ {
hb_mask_t flags; hb_memset (this, 0, sizeof (*this));
unsigned cluster_first; chain_flags.init ();
unsigned cluster_last; // end - 1 }
}; void fini () { chain_flags.fini (); }
public: public:
hb_vector_t<hb_sorted_vector_t<range_flags_t>> chain_flags; hb_vector_t<hb_mask_t> chain_flags;
}; };
struct hb_aat_map_builder_t struct hb_aat_map_builder_t
@ -55,7 +56,7 @@ struct hb_aat_map_builder_t
face (face_), face (face_),
props (props_) {} props (props_) {}
HB_INTERNAL void add_feature (const hb_feature_t &feature); HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value=1);
HB_INTERNAL void compile (hb_aat_map_t &m); HB_INTERNAL void compile (hb_aat_map_t &m);
@ -77,7 +78,7 @@ struct hb_aat_map_builder_t
return (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0); return (a->seq < b->seq ? -1 : a->seq > b->seq ? 1 : 0);
} }
/* compares type & setting only */ /* compares type & setting only, not is_exclusive flag or seq number */
int cmp (const feature_info_t& f) const int cmp (const feature_info_t& f) const
{ {
return (f.type != type) ? (f.type < type ? -1 : 1) : return (f.type != type) ? (f.type < type ? -1 : 1) :
@ -85,38 +86,12 @@ struct hb_aat_map_builder_t
} }
}; };
struct feature_range_t
{
feature_info_t info;
unsigned start;
unsigned end;
};
private:
struct feature_event_t
{
unsigned int index;
bool start;
feature_info_t feature;
HB_INTERNAL static int cmp (const void *pa, const void *pb) {
const feature_event_t *a = (const feature_event_t *) pa;
const feature_event_t *b = (const feature_event_t *) pb;
return a->index < b->index ? -1 : a->index > b->index ? 1 :
a->start < b->start ? -1 : a->start > b->start ? 1 :
feature_info_t::cmp (&a->feature, &b->feature);
}
};
public: public:
hb_face_t *face; hb_face_t *face;
hb_segment_properties_t props; hb_segment_properties_t props;
public: public:
hb_sorted_vector_t<feature_range_t> features; hb_sorted_vector_t<feature_info_t> features;
hb_sorted_vector_t<feature_info_t> current_features;
unsigned range_first;
unsigned range_last;
}; };

View File

@ -80,7 +80,8 @@ hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *fac
const hb_segment_properties_t &props) : const hb_segment_properties_t &props) :
face (face), face (face),
props (props), props (props),
map (face, props) map (face, props),
aat_map (face, props)
#ifndef HB_NO_AAT_SHAPE #ifndef HB_NO_AAT_SHAPE
, apply_morx (_hb_apply_morx (face, props)) , apply_morx (_hb_apply_morx (face, props))
#endif #endif
@ -104,6 +105,10 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan,
plan.props = props; plan.props = props;
plan.shaper = shaper; plan.shaper = shaper;
map.compile (plan.map, key); map.compile (plan.map, key);
#ifndef HB_NO_AAT_SHAPE
if (apply_morx)
aat_map.compile (plan.aat_map);
#endif
#ifndef HB_NO_OT_SHAPE_FRACTIONS #ifndef HB_NO_OT_SHAPE_FRACTIONS
plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c')); plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
@ -217,6 +222,9 @@ hb_ot_shape_plan_t::init0 (hb_face_t *face,
const hb_shape_plan_key_t *key) const hb_shape_plan_key_t *key)
{ {
map.init (); map.init ();
#ifndef HB_NO_AAT_SHAPE
aat_map.init ();
#endif
hb_ot_shape_planner_t planner (face, hb_ot_shape_planner_t planner (face,
key->props); key->props);
@ -233,6 +241,9 @@ hb_ot_shape_plan_t::init0 (hb_face_t *face,
if (unlikely (!data)) if (unlikely (!data))
{ {
map.fini (); map.fini ();
#ifndef HB_NO_AAT_SHAPE
aat_map.fini ();
#endif
return false; return false;
} }
} }
@ -247,13 +258,21 @@ hb_ot_shape_plan_t::fini ()
shaper->data_destroy (const_cast<void *> (data)); shaper->data_destroy (const_cast<void *> (data));
map.fini (); map.fini ();
#ifndef HB_NO_AAT_SHAPE
aat_map.fini ();
#endif
} }
void void
hb_ot_shape_plan_t::substitute (hb_font_t *font, hb_ot_shape_plan_t::substitute (hb_font_t *font,
hb_buffer_t *buffer) const hb_buffer_t *buffer) const
{ {
map.substitute (this, font, buffer); #ifndef HB_NO_AAT_SHAPE
if (unlikely (apply_morx))
hb_aat_layout_substitute (this, font, buffer);
else
#endif
map.substitute (this, font, buffer);
} }
void void
@ -387,6 +406,18 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
feature->value); feature->value);
} }
#ifndef HB_NO_AAT_SHAPE
if (planner->apply_morx)
{
hb_aat_map_builder_t *aat_map = &planner->aat_map;
for (unsigned int i = 0; i < num_user_features; i++)
{
const hb_feature_t *feature = &user_features[i];
aat_map->add_feature (feature->tag, feature->value);
}
}
#endif
if (planner->shaper->override_features) if (planner->shaper->override_features)
planner->shaper->override_features (planner); planner->shaper->override_features (planner);
} }
@ -909,13 +940,7 @@ hb_ot_substitute_plan (const hb_ot_shape_context_t *c)
if (c->plan->fallback_glyph_classes) if (c->plan->fallback_glyph_classes)
hb_synthesize_glyph_classes (c->buffer); hb_synthesize_glyph_classes (c->buffer);
#ifndef HB_NO_AAT_SHAPE c->plan->substitute (c->font, buffer);
if (unlikely (c->plan->apply_morx))
hb_aat_layout_substitute (c->plan, c->font, c->buffer,
c->user_features, c->num_user_features);
else
#endif
c->plan->substitute (c->font, buffer);
} }
static inline void static inline void

View File

@ -65,6 +65,7 @@ struct hb_ot_shape_plan_t
hb_segment_properties_t props; hb_segment_properties_t props;
const struct hb_ot_shaper_t *shaper; const struct hb_ot_shaper_t *shaper;
hb_ot_map_t map; hb_ot_map_t map;
hb_aat_map_t aat_map;
const void *data; const void *data;
#ifndef HB_NO_OT_SHAPE_FRACTIONS #ifndef HB_NO_OT_SHAPE_FRACTIONS
hb_mask_t frac_mask, numr_mask, dnom_mask; hb_mask_t frac_mask, numr_mask, dnom_mask;
@ -151,6 +152,7 @@ struct hb_ot_shape_planner_t
hb_face_t *face; hb_face_t *face;
hb_segment_properties_t props; hb_segment_properties_t props;
hb_ot_map_builder_t map; hb_ot_map_builder_t map;
hb_aat_map_builder_t aat_map;
#ifndef HB_NO_AAT_SHAPE #ifndef HB_NO_AAT_SHAPE
bool apply_morx : 1; bool apply_morx : 1;
#else #else