src/hb-aat-layout-common.hh | 105 +++++++++++++---- src/hb-aat-layout-kerx-table.hh | 17 +- src/hb-aat-layout-morx-table.hh | 243 +++++++++++++++++++++++++--------------- src/hb-aat-layout.cc | 49 +++++++- src/hb-open-type.hh | 7 + src/hb-ot-face.hh | 1 src/hb-ot-maxp-table.hh | 2 7 files changed, 296 insertions(+), 128 deletions(-)
New commits: commit 28b68cffe4e5ebf82217ebf439f428431d672af3 Author: Behdad Esfahbod <[email protected]> Date: Tue Oct 30 23:33:30 2018 -0700 [mort] Implement / adjust Contextual substitution diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index dba352f9..c3a74835 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -213,10 +213,13 @@ struct ContextualSubtable Reserved = 0x3FFF, /* These bits are reserved and should be set to 0. */ }; - inline driver_context_t (const ContextualSubtable *table) : + inline driver_context_t (const ContextualSubtable *table_, + hb_aat_apply_context_t *c_) : ret (false), + c (c_), mark_set (false), mark (0), + table (table_), subs (table+table->substitutionTables) {} inline bool is_actionable (StateTableDriver<Types, EntryData> *driver, @@ -239,30 +242,57 @@ struct ContextualSubtable if (buffer->idx == buffer->len && !mark_set) return true; - if (entry->data.markIndex != 0xFFFF) + const GlyphID *replacement; + + replacement = nullptr; + if (Types::extended) { - const Lookup<GlyphID> &lookup = subs[entry->data.markIndex]; - hb_glyph_info_t *info = buffer->info; - const GlyphID *replacement = lookup.get_value (info[mark].codepoint, driver->num_glyphs); - if (replacement) + if (entry->data.markIndex != 0xFFFF) { - buffer->unsafe_to_break (mark, MIN (buffer->idx + 1, buffer->len)); - info[mark].codepoint = *replacement; - ret = true; + const Lookup<GlyphID> &lookup = subs[entry->data.markIndex]; + replacement = lookup.get_value (buffer->info[mark].codepoint, driver->num_glyphs); } } - if (entry->data.currentIndex != 0xFFFF) + else + { + unsigned int offset = 2 * (entry->data.markIndex + buffer->info[mark].codepoint); + replacement = &StructAtOffset<GlyphID> (table, offset); + if ((const void *) replacement < (const void *) subs || + !replacement->sanitize (&c->sanitizer) || + !*replacement) + replacement = nullptr; + } + if (replacement) + { + buffer->unsafe_to_break (mark, MIN (buffer->idx + 1, buffer->len)); + buffer->info[mark].codepoint = *replacement; + ret = true; + } + + replacement = nullptr; + unsigned int idx = MIN (buffer->idx, buffer->len - 1); + if (Types::extended) { - unsigned int idx = MIN (buffer->idx, buffer->len - 1); - const Lookup<GlyphID> &lookup = subs[entry->data.currentIndex]; - hb_glyph_info_t *info = buffer->info; - const GlyphID *replacement = lookup.get_value (info[idx].codepoint, driver->num_glyphs); - if (replacement) + if (entry->data.currentIndex != 0xFFFF) { - info[idx].codepoint = *replacement; - ret = true; + const Lookup<GlyphID> &lookup = subs[entry->data.currentIndex]; + replacement = lookup.get_value (buffer->info[idx].codepoint, driver->num_glyphs); } } + else + { + unsigned int offset = 2 * (entry->data.currentIndex + buffer->info[idx].codepoint); + replacement = &StructAtOffset<GlyphID> (table, offset); + if ((const void *) replacement < (const void *) subs || + !replacement->sanitize (&c->sanitizer) || + !*replacement) + replacement = nullptr; + } + if (replacement) + { + buffer->info[idx].codepoint = *replacement; + ret = true; + } if (entry->flags & SetMark) { @@ -276,8 +306,10 @@ struct ContextualSubtable public: bool ret; private: + hb_aat_apply_context_t *c; bool mark_set; unsigned int mark; + const ContextualSubtable *table; const UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT, false> &subs; }; @@ -285,7 +317,7 @@ struct ContextualSubtable { TRACE_APPLY (this); - driver_context_t dc (this); + driver_context_t dc (this, c); StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); driver.drive (&dc); @@ -300,6 +332,8 @@ struct ContextualSubtable unsigned int num_entries = 0; if (unlikely (!machine.sanitize (c, &num_entries))) return_trace (false); + if (!Types::extended) return_trace (true); + unsigned int num_lookups = 0; const Entry<EntryData> *entries = machine.get_entries (); diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index e9f99b10..00bd134d 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -340,6 +340,9 @@ struct UnsizedArrayOf inline const Type& operator [] (unsigned int i) const { return arrayZ[i]; } inline Type& operator [] (unsigned int i) { return arrayZ[i]; } + template <typename T> inline operator T * (void) { return arrayZ; } + template <typename T> inline operator const T * (void) const { return arrayZ; } + inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const { TRACE_SANITIZE (this); @@ -450,6 +453,10 @@ struct ArrayOf if (unlikely (i >= len)) return Crap(Type); return arrayZ[i]; } + + template <typename T> inline operator T * (void) { return arrayZ; } + template <typename T> inline operator const T * (void) const { return arrayZ; } + inline unsigned int get_size (void) const { return len.static_size + len * Type::static_size; } commit 11dbf0f12926b80d0c308c70a218342280045c23 Author: Behdad Esfahbod <[email protected]> Date: Tue Oct 30 21:49:59 2018 -0700 [mort] More fixes] diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index 65e7fd93..33d9e556 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -430,9 +430,8 @@ struct StateTable CLASS_END_OF_LINE = 3, }; - inline unsigned int row_stride (void) const { return nClasses * sizeof (HBUSHORT); } inline unsigned int new_state (unsigned int newState) const - { return newState / (Types::extended ? 1 : row_stride ()); } + { return Types::extended ? newState : (newState - stateArrayTable) / nClasses; } inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const { @@ -524,7 +523,7 @@ struct StateTable entryTable; /* Offset to the entry array. */ public: - DEFINE_SIZE_STATIC (16); + DEFINE_SIZE_STATIC (4 * sizeof (HBUINT)); }; struct ClassTable commit e1552af95b6c17571f7ee58ebac92f48d93c8f98 Author: Behdad Esfahbod <[email protected]> Date: Tue Oct 30 21:09:05 2018 -0700 [maxp] Minor diff --git a/src/hb-ot-maxp-table.hh b/src/hb-ot-maxp-table.hh index 648f232d..198dd251 100644 --- a/src/hb-ot-maxp-table.hh +++ b/src/hb-ot-maxp-table.hh @@ -92,7 +92,7 @@ struct maxp if (version.major == 1) { const maxpV1Tail &v1 = StructAfter<maxpV1Tail> (*this); - return v1.sanitize (c); + return_trace (v1.sanitize (c)); } return_trace (likely (version.major == 0 && version.minor == 0x5000u)); } commit 0cf282a32e5b0fe1fec454ff293ffe04b33f1112 Author: Behdad Esfahbod <[email protected]> Date: Tue Oct 30 20:51:44 2018 -0700 [mort] Grind some more diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index c9d5cfe9..65e7fd93 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -430,6 +430,10 @@ struct StateTable CLASS_END_OF_LINE = 3, }; + inline unsigned int row_stride (void) const { return nClasses * sizeof (HBUSHORT); } + inline unsigned int new_state (unsigned int newState) const + { return newState / (Types::extended ? 1 : row_stride ()); } + inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const { if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH; @@ -495,7 +499,10 @@ struct StateTable { /* Sweep new entries. */ const Entry<Extra> *stop = &entries[num_entries]; for (const Entry<Extra> *p = &entries[entry]; p < stop; p++) - num_states = MAX<unsigned int> (num_states, p->newState + 1); + { + unsigned int newState = new_state (p->newState); + num_states = MAX<unsigned int> (num_states, newState + 1); + } entry = num_entries; } } @@ -620,17 +627,17 @@ struct StateTableDriver } if (unlikely (!c->transition (this, entry))) - break; + break; last_was_dont_advance = (entry->flags & context_t::DontAdvance) && buffer->max_ops-- > 0; - state = entry->newState; + state = machine.new_state (entry->newState); if (buffer->idx == buffer->len) - break; + break; if (!last_was_dont_advance) - buffer->next_glyph (); + buffer->next_glyph (); } if (!c->in_place) commit 90667b31bc3e61e68e27966e4781aba456c6b93b Author: Behdad Esfahbod <[email protected]> Date: Tue Oct 30 20:15:28 2018 -0700 [mort] Hook up more diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index 2b4f5783..b6bdb0be 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -207,7 +207,19 @@ void hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper, hb_aat_map_t *map) { - _get_morx (mapper->face).compile_flags (mapper, map); + const AAT::morx& morx = _get_morx (mapper->face, nullptr); + if (morx.has_data ()) + { + morx.compile_flags (mapper, map); + return; + } + + const AAT::mort& mort = _get_mort (mapper->face, nullptr); + if (mort.has_data ()) + { + mort.compile_flags (mapper, map); + return; + } } commit 9346b1f158dfd7d25ed0057b40aaa6980a85ea17 Author: Behdad Esfahbod <[email protected]> Date: Tue Oct 30 20:04:13 2018 -0700 [morx] Remove stale comment diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 6d6ef708..dba352f9 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -865,8 +865,6 @@ struct Chain { hb_mask_t flags = defaultFlags; { - /* Compute applicable flags. TODO Should move this to planning - * stage and take user-requested features into account. */ unsigned int count = featureCount; for (unsigned i = 0; i < count; i++) { commit f864ef215e1354a1e5a3c8796afafba761404e08 Author: Behdad Esfahbod <[email protected]> Date: Tue Oct 30 19:42:21 2018 -0700 [mort] More massaging towards mort diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index a2dd45a0..6d6ef708 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -782,28 +782,29 @@ struct Feature template <typename Types> struct ChainSubtable { + typedef typename Types::HBUINT HBUINT; + template <typename T> friend struct Chain; inline unsigned int get_size (void) const { return length; } - inline unsigned int get_type (void) const { return coverage & SubtableType; } + inline unsigned int get_type (void) const { return coverage & 0xFF; } + inline unsigned int get_coverage (void) const { return coverage >> (sizeof (HBUINT) * 8 - 8); } enum Coverage { - Vertical = 0x80000000, /* If set, this subtable will only be applied - * to vertical text. If clear, this subtable - * will only be applied to horizontal text. */ - Backwards = 0x40000000, /* If set, this subtable will process glyphs - * in descending order. If clear, it will - * process the glyphs in ascending order. */ - AllDirections = 0x20000000, /* If set, this subtable will be applied to - * both horizontal and vertical text (i.e. - * the state of bit 0x80000000 is ignored). */ - Logical = 0x10000000, /* If set, this subtable will process glyphs - * in logical order (or reverse logical order, - * depending on the value of bit 0x80000000). */ - Reserved = 0x0FFFFF00, /* Reserved, set to zero. */ - SubtableType = 0x000000FF, /* Subtable type; see following table. */ + Vertical = 0x80, /* If set, this subtable will only be applied + * to vertical text. If clear, this subtable + * will only be applied to horizontal text. */ + Backwards = 0x40, /* If set, this subtable will process glyphs + * in descending order. If clear, it will + * process the glyphs in ascending order. */ + AllDirections = 0x20, /* If set, this subtable will be applied to + * both horizontal and vertical text (i.e. + * the state of bit 0x80000000 is ignored). */ + Logical = 0x10, /* If set, this subtable will process glyphs + * in logical order (or reverse logical order, + * depending on the value of bit 0x80000000). */ }; enum Type { @@ -841,8 +842,8 @@ struct ChainSubtable } protected: - HBUINT32 length; /* Total subtable length, including this header. */ - HBUINT32 coverage; /* Coverage flags and subtable type. */ + HBUINT length; /* Total subtable length, including this header. */ + HBUINT coverage; /* Coverage flags and subtable type. */ HBUINT32 subFeatureFlags;/* The 32-bit mask identifying which subtable this is. */ union { RearrangementSubtable<Types> rearrangement; @@ -852,7 +853,7 @@ struct ChainSubtable InsertionSubtable<Types> insertion; } u; public: - DEFINE_SIZE_MIN (2 * sizeof (HBUINT32) + 4); + DEFINE_SIZE_MIN (2 * sizeof (HBUINT) + 4); }; template <typename Types> @@ -895,9 +896,9 @@ struct Chain if (!(subtable->subFeatureFlags & flags)) goto skip; - if (!(subtable->coverage & ChainSubtable<Types>::AllDirections) && + if (!(subtable->get_coverage() & ChainSubtable<Types>::AllDirections) && HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) != - bool (subtable->coverage & ChainSubtable<Types>::Vertical)) + bool (subtable->get_coverage() & ChainSubtable<Types>::Vertical)) goto skip; /* Buffer contents is always in logical direction. Determine if @@ -927,9 +928,9 @@ struct Chain (the order opposite that of the characters, which may be right-to-left or left-to-right). */ - reverse = subtable->coverage & ChainSubtable<Types>::Logical ? - bool (subtable->coverage & ChainSubtable<Types>::Backwards) : - bool (subtable->coverage & ChainSubtable<Types>::Backwards) != + reverse = subtable->get_coverage () & ChainSubtable<Types>::Logical ? + bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) : + bool (subtable->get_coverage () & ChainSubtable<Types>::Backwards) != HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction); if (!c->buffer->message (c->font, "start chain subtable %d", c->lookup_index)) @@ -981,8 +982,8 @@ struct Chain } protected: - HBUINT defaultFlags; /* The default specification for subtables. */ - HBUINT length; /* Total byte count, including this header. */ + HBUINT32 defaultFlags; /* The default specification for subtables. */ + HBUINT32 length; /* Total byte count, including this header. */ HBUINT featureCount; /* Number of feature subtable entries. */ HBUINT subtableCount; /* The number of subtables in the chain. */ @@ -991,7 +992,7 @@ struct Chain /*subtableGlyphCoverageArray*/ /* Only if version >= 3. We don't use. */ public: - DEFINE_SIZE_MIN (2 * sizeof (HBUINT) + 4); + DEFINE_SIZE_MIN (8 + 2 * sizeof (HBUINT)); }; commit 2d9467340b1498ccc0cd47bf915b84ab12dfa025 Author: Behdad Esfahbod <[email protected]> Date: Tue Oct 30 19:33:31 2018 -0700 [mort] Fix version check in sanitize diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index e619d9e9..a2dd45a0 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -1052,8 +1052,7 @@ struct mortmorx inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - if (!version.sanitize (c) || version < 2 || - !chainCount.sanitize (c)) + if (!version.sanitize (c) || !version || !chainCount.sanitize (c)) return_trace (false); const Chain<Types> *chain = &firstChain; @@ -1070,7 +1069,7 @@ struct mortmorx protected: HBUINT16 version; /* Version number of the glyph metamorphosis table. - * 2 or 3. */ + * 1, 2, or 3. */ HBUINT16 unused; /* Set to 0. */ HBUINT32 chainCount; /* Number of metamorphosis chains contained in this * table. */ commit c2527a1bc2b493473f06ea6ae79f0a87b722c4d3 Author: Behdad Esfahbod <[email protected]> Date: Tue Oct 30 19:26:16 2018 -0700 [mort] Make it compile / hook it up Untested. diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index 7327cc5b..c9d5cfe9 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -433,8 +433,7 @@ struct StateTable inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const { if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH; - const HBUINT16 *v = (this+classTable).get_value (glyph_id, num_glyphs); - return v ? (unsigned) *v : (unsigned) CLASS_OUT_OF_BOUNDS; + return (this+classTable).get_class (glyph_id, num_glyphs); } inline const Entry<Extra> *get_entries () const @@ -446,7 +445,7 @@ struct StateTable { if (unlikely (klass >= nClasses)) return nullptr; - const HBUINT16 *states = (this+stateArrayTable).arrayZ; + const HBUSHORT *states = (this+stateArrayTable).arrayZ; const Entry<Extra> *entries = (this+entryTable).arrayZ; unsigned int entry = states[state * nClasses + klass]; @@ -461,7 +460,7 @@ struct StateTable if (unlikely (!(c->check_struct (this) && classTable.sanitize (c, this)))) return_trace (false); - const HBUINT16 *states = (this+stateArrayTable).arrayZ; + const HBUSHORT *states = (this+stateArrayTable).arrayZ; const Entry<Extra> *entries = (this+entryTable).arrayZ; unsigned int num_classes = nClasses; @@ -483,8 +482,8 @@ struct StateTable if ((c->max_ops -= num_states - state) < 0) return_trace (false); { /* Sweep new states. */ - const HBUINT16 *stop = &states[num_states * num_classes]; - for (const HBUINT16 *p = &states[state * num_classes]; p < stop; p++) + const HBUSHORT *stop = &states[num_states * num_classes]; + for (const HBUSHORT *p = &states[state * num_classes]; p < stop; p++) num_entries = MAX<unsigned int> (num_entries, *p + 1); state = num_states; } diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 99627d3a..e619d9e9 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -278,7 +278,7 @@ struct ContextualSubtable private: bool mark_set; unsigned int mark; - const UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT32, false> &subs; + const UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT, false> &subs; }; inline bool apply (hb_aat_apply_context_t *c) const diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index 59157c21..2b4f5783 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -133,20 +133,20 @@ hb_aat_layout_find_feature_mapping (hb_tag_t tag) * mort/morx/kerx/trak */ -// static inline const AAT::mort& -// _get_mort (hb_face_t *face, hb_blob_t **blob = nullptr) -// { -// if (unlikely (!hb_ot_shaper_face_data_ensure (face))) -// { -// if (blob) -// *blob = hb_blob_get_empty (); -// return Null(AAT::mort); -// } -// const AAT::morx& mort = *(hb_ot_face_data (face)->mort.get ()); -// if (blob) -// *blob = hb_ot_face_data (face)->mort.get_blob (); -// return mort; -// } +static inline const AAT::mort& +_get_mort (hb_face_t *face, hb_blob_t **blob = nullptr) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) + { + if (blob) + *blob = hb_blob_get_empty (); + return Null(AAT::mort); + } + const AAT::mort& mort = *(hb_ot_face_data (face)->mort.get ()); + if (blob) + *blob = hb_ot_face_data (face)->mort.get_blob (); + return mort; +} static inline const AAT::morx& _get_morx (hb_face_t *face, hb_blob_t **blob = nullptr) { @@ -214,7 +214,8 @@ hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper, hb_bool_t hb_aat_layout_has_substitution (hb_face_t *face) { - return _get_morx (face).has_data (); + return _get_morx (face).has_data () || + _get_mort (face).has_data (); } void @@ -223,10 +224,22 @@ hb_aat_layout_substitute (hb_ot_shape_plan_t *plan, hb_buffer_t *buffer) { hb_blob_t *blob; + const AAT::morx& morx = _get_morx (font->face, &blob); + if (morx.has_data ()) + { + AAT::hb_aat_apply_context_t c (plan, font, buffer, blob); + morx.apply (&c); + return; + } - AAT::hb_aat_apply_context_t c (plan, font, buffer, blob); - morx.apply (&c); + const AAT::mort& mort = _get_mort (font->face, &blob); + if (mort.has_data ()) + { + AAT::hb_aat_apply_context_t c (plan, font, buffer, blob); + mort.apply (&c); + return; + } } commit 933babdc075c27fbcc1b726c3c9b2aa67338c6ad Author: Behdad Esfahbod <[email protected]> Date: Tue Oct 30 19:22:43 2018 -0700 [mort] Fixup on previous commit diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 336d0e35..99627d3a 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -73,12 +73,12 @@ struct RearrangementSubtable ret (false), start (0), end (0) {} - inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver HB_UNUSED, + inline bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED, const Entry<EntryData> *entry) { return (entry->flags & Verb) && start < end; } - inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver, + inline bool transition (StateTableDriver<Types, EntryData> *driver, const Entry<EntryData> *entry) { hb_buffer_t *buffer = driver->buffer; @@ -169,7 +169,7 @@ struct RearrangementSubtable driver_context_t dc (this); - StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->face); + StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); driver.drive (&dc); return_trace (dc.ret); @@ -219,7 +219,7 @@ struct ContextualSubtable mark (0), subs (table+table->substitutionTables) {} - inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver, + inline bool is_actionable (StateTableDriver<Types, EntryData> *driver, const Entry<EntryData> *entry) { hb_buffer_t *buffer = driver->buffer; @@ -229,7 +229,7 @@ struct ContextualSubtable return entry->data.markIndex != 0xFFFF || entry->data.currentIndex != 0xFFFF; } - inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver, + inline bool transition (StateTableDriver<Types, EntryData> *driver, const Entry<EntryData> *entry) { hb_buffer_t *buffer = driver->buffer; @@ -287,7 +287,7 @@ struct ContextualSubtable driver_context_t dc (this); - StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->face); + StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); driver.drive (&dc); return_trace (dc.ret); @@ -373,12 +373,12 @@ struct LigatureSubtable ligature (table+table->ligature), match_length (0) {} - inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver HB_UNUSED, + inline bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED, const Entry<EntryData> *entry) { return entry->flags & PerformAction; } - inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver, + inline bool transition (StateTableDriver<Types, EntryData> *driver, const Entry<EntryData> *entry) { hb_buffer_t *buffer = driver->buffer; @@ -492,7 +492,7 @@ struct LigatureSubtable driver_context_t dc (this, c); - StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->face); + StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); driver.drive (&dc); return_trace (dc.ret); @@ -636,13 +636,13 @@ struct InsertionSubtable mark (0), insertionAction (table+table->insertionAction) {} - inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver HB_UNUSED, + inline bool is_actionable (StateTableDriver<Types, EntryData> *driver HB_UNUSED, const Entry<EntryData> *entry) { return (entry->flags & (CurrentInsertCount | MarkedInsertCount)) && (entry->data.currentInsertIndex != 0xFFFF ||entry->data.markedInsertIndex != 0xFFFF); } - inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver, + inline bool transition (StateTableDriver<Types, EntryData> *driver, const Entry<EntryData> *entry) { hb_buffer_t *buffer = driver->buffer; @@ -734,7 +734,7 @@ struct InsertionSubtable driver_context_t dc (this, c); - StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->face); + StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); driver.drive (&dc); return_trace (dc.ret); commit b053cabacd99ff69144a1459fe02ffd574c2416c Author: Ebrahim Byagowi <[email protected]> Date: Tue Oct 30 18:41:34 2018 +0330 [mort] Bring back mort generalizations Started by reverting https://github.com/harfbuzz/harfbuzz/commit/1f1c85a5 Just a starting point, if we agree even mort can come back. diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index ce40abd5..7327cc5b 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -410,9 +410,13 @@ struct Entry<void> DEFINE_SIZE_STATIC (4); }; -template <typename Extra> +template <typename Types, typename Extra> struct StateTable { + typedef typename Types::HBUINT HBUINT; + typedef typename Types::HBUSHORT HBUSHORT; + typedef typename Types::ClassType ClassType; + enum State { STATE_START_OF_TEXT = 0, @@ -504,23 +508,73 @@ struct StateTable } protected: - HBUINT32 nClasses; /* Number of classes, which is the number of indices + HBUINT nClasses; /* Number of classes, which is the number of indices * in a single line in the state array. */ - LOffsetTo<Lookup<HBUINT16>, false> + OffsetTo<ClassType, HBUINT, false> classTable; /* Offset to the class table. */ - LOffsetTo<UnsizedArrayOf<HBUINT16>, false> + OffsetTo<UnsizedArrayOf<HBUSHORT>, HBUINT, false> stateArrayTable;/* Offset to the state array. */ - LOffsetTo<UnsizedArrayOf<Entry<Extra> >, false> + OffsetTo<UnsizedArrayOf<Entry<Extra> >, HBUINT, false> entryTable; /* Offset to the entry array. */ public: DEFINE_SIZE_STATIC (16); }; -template <typename EntryData> +struct ClassTable +{ + inline unsigned int get_class (hb_codepoint_t glyph_id) const + { + return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ? classArrayZ[glyph_id - firstGlyph] : 1; + } + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && classArrayZ.sanitize (c, glyphCount)); + } + protected: + GlyphID firstGlyph; /* First glyph index included in the trimmed array. */ + HBUINT16 glyphCount; /* Total number of glyphs (equivalent to the last + * glyph minus the value of firstGlyph plus 1). */ + UnsizedArrayOf<HBUINT8> + classArrayZ; /* The class codes (indexed by glyph index minus + * firstGlyph). */ + public: + DEFINE_SIZE_ARRAY (4, classArrayZ); +}; + +struct MortTypes +{ + static const bool extended = false; + typedef HBUINT16 HBUINT; + typedef HBUINT8 HBUSHORT; + struct ClassType : ClassTable + { + inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs HB_UNUSED) const + { + return ClassTable::get_class (glyph_id); + } + }; +}; +struct MorxTypes +{ + static const bool extended = true; + typedef HBUINT32 HBUINT; + typedef HBUINT16 HBUSHORT; + struct ClassType : Lookup<HBUINT16> + { + inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const + { + const HBUINT16 *v = get_value (glyph_id, num_glyphs); + return v ? *v : 1; + } + }; +}; + +template <typename Types, typename EntryData> struct StateTableDriver { - inline StateTableDriver (const StateTable<EntryData> &machine_, + inline StateTableDriver (const StateTable<Types, EntryData> &machine_, hb_buffer_t *buffer_, hb_face_t *face_) : machine (machine_), @@ -533,13 +587,13 @@ struct StateTableDriver if (!c->in_place) buffer->clear_output (); - unsigned int state = StateTable<EntryData>::STATE_START_OF_TEXT; + unsigned int state = StateTable<Types, EntryData>::STATE_START_OF_TEXT; bool last_was_dont_advance = false; for (buffer->idx = 0; buffer->successful;) { unsigned int klass = buffer->idx < buffer->len ? machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) : - (unsigned) StateTable<EntryData>::CLASS_END_OF_TEXT; + (unsigned) StateTable<Types, EntryData>::CLASS_END_OF_TEXT; const Entry<EntryData> *entry = machine.get_entryZ (state, klass); if (unlikely (!entry)) break; @@ -553,7 +607,7 @@ struct StateTableDriver /* If there's no action and we're just epsilon-transitioning to state 0, * safe to break. */ if (c->is_actionable (this, entry) || - !(entry->newState == StateTable<EntryData>::STATE_START_OF_TEXT && + !(entry->newState == StateTable<Types, EntryData>::STATE_START_OF_TEXT && entry->flags == context_t::DontAdvance)) buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1); } @@ -590,7 +644,7 @@ struct StateTableDriver } public: - const StateTable<EntryData> &machine; + const StateTable<Types, EntryData> &machine; hb_buffer_t *buffer; unsigned int num_glyphs; }; diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index a8831250..94e0a9b6 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -163,12 +163,12 @@ struct KerxSubTableFormat1 kernAction (&table->machine + table->kernAction), depth (0) {} - inline bool is_actionable (StateTableDriver<EntryData> *driver HB_UNUSED, + inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver HB_UNUSED, const Entry<EntryData> *entry) { return entry->data.kernActionIndex != 0xFFFF; } - inline bool transition (StateTableDriver<EntryData> *driver, + inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver, const Entry<EntryData> *entry) { hb_buffer_t *buffer = driver->buffer; @@ -239,7 +239,7 @@ struct KerxSubTableFormat1 driver_context_t dc (this, c); - StateTableDriver<EntryData> driver (machine, c->buffer, c->font->face); + StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->font->face); driver.drive (&dc); return_trace (true); @@ -255,7 +255,7 @@ struct KerxSubTableFormat1 protected: KerxSubTableHeader header; - StateTable<EntryData> machine; + StateTable<MorxTypes, EntryData> machine; LOffsetTo<UnsizedArrayOf<FWORD>, false> kernAction; public: DEFINE_SIZE_STATIC (32); @@ -365,12 +365,12 @@ struct KerxSubTableFormat4 mark_set (false), mark (0) {} - inline bool is_actionable (StateTableDriver<EntryData> *driver HB_UNUSED, + inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver HB_UNUSED, const Entry<EntryData> *entry) { return entry->data.ankrActionIndex != 0xFFFF; } - inline bool transition (StateTableDriver<EntryData> *driver, + inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver, const Entry<EntryData> *entry) { hb_buffer_t *buffer = driver->buffer; @@ -473,7 +473,7 @@ struct KerxSubTableFormat4 driver_context_t dc (this, c); - StateTableDriver<EntryData> driver (machine, c->buffer, c->font->face); + StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->font->face); driver.drive (&dc); return_trace (true); @@ -489,7 +489,8 @@ struct KerxSubTableFormat4 protected: KerxSubTableHeader header; - StateTable<EntryData> machine; + StateTable<MorxTypes, EntryData> + machine; HBUINT32 flags; public: DEFINE_SIZE_STATIC (32); diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index a5620910..336d0e35 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -35,17 +35,21 @@ /* * morx -- Extended Glyph Metamorphosis * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html + * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6mort.html */ #define HB_AAT_TAG_morx HB_TAG('m','o','r','x') +#define HB_AAT_TAG_mort HB_TAG('m','o','r','t') namespace AAT { using namespace OT; - +template <typename Types> struct RearrangementSubtable { + typedef typename Types::HBUINT HBUINT; + typedef void EntryData; struct driver_context_t @@ -69,12 +73,12 @@ struct RearrangementSubtable ret (false), start (0), end (0) {} - inline bool is_actionable (StateTableDriver<EntryData> *driver HB_UNUSED, + inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver HB_UNUSED, const Entry<EntryData> *entry) { return (entry->flags & Verb) && start < end; } - inline bool transition (StateTableDriver<EntryData> *driver, + inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver, const Entry<EntryData> *entry) { hb_buffer_t *buffer = driver->buffer; @@ -165,7 +169,7 @@ struct RearrangementSubtable driver_context_t dc (this); - StateTableDriver<EntryData> driver (machine, c->buffer, c->face); + StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->face); driver.drive (&dc); return_trace (dc.ret); @@ -178,13 +182,16 @@ struct RearrangementSubtable } protected: - StateTable<EntryData> machine; + StateTable<Types, EntryData> machine; public: DEFINE_SIZE_STATIC (16); }; +template <typename Types> struct ContextualSubtable { + typedef typename Types::HBUINT HBUINT; + struct EntryData { HBUINT16 markIndex; /* Index of the substitution table for the @@ -212,7 +219,7 @@ struct ContextualSubtable mark (0), subs (table+table->substitutionTables) {} - inline bool is_actionable (StateTableDriver<EntryData> *driver, + inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver, const Entry<EntryData> *entry) { hb_buffer_t *buffer = driver->buffer; @@ -222,7 +229,7 @@ struct ContextualSubtable return entry->data.markIndex != 0xFFFF || entry->data.currentIndex != 0xFFFF; } - inline bool transition (StateTableDriver<EntryData> *driver, + inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver, const Entry<EntryData> *entry) { hb_buffer_t *buffer = driver->buffer; @@ -280,7 +287,7 @@ struct ContextualSubtable driver_context_t dc (this); - StateTableDriver<EntryData> driver (machine, c->buffer, c->face); + StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->face); driver.drive (&dc); return_trace (dc.ret); @@ -310,16 +317,19 @@ struct ContextualSubtable } protected: - StateTable<EntryData> + StateTable<Types, EntryData> machine; - LOffsetTo<UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT32, false>, false> + OffsetTo<UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT, false>, HBUINT, false> substitutionTables; public: DEFINE_SIZE_STATIC (20); }; +template <typename Types> struct LigatureSubtable { + typedef typename Types::HBUINT HBUINT; + struct EntryData { HBUINT16 ligActionIndex; /* Index to the first ligActionTable entry @@ -363,12 +373,12 @@ struct LigatureSubtable ligature (table+table->ligature), match_length (0) {} - inline bool is_actionable (StateTableDriver<EntryData> *driver HB_UNUSED, + inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver HB_UNUSED, const Entry<EntryData> *entry) { return entry->flags & PerformAction; } - inline bool transition (StateTableDriver<EntryData> *driver, + inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver, const Entry<EntryData> *entry) { hb_buffer_t *buffer = driver->buffer; @@ -482,7 +492,7 @@ struct LigatureSubtable driver_context_t dc (this, c); - StateTableDriver<EntryData> driver (machine, c->buffer, c->face); + StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->face); driver.drive (&dc); return_trace (dc.ret); @@ -497,18 +507,19 @@ struct LigatureSubtable } protected: - StateTable<EntryData> + StateTable<Types, EntryData> machine; - LOffsetTo<UnsizedArrayOf<HBUINT32>, false> + OffsetTo<UnsizedArrayOf<HBUINT32>, HBUINT, false> ligAction; /* Offset to the ligature action table. */ - LOffsetTo<UnsizedArrayOf<HBUINT16>, false> + OffsetTo<UnsizedArrayOf<HBUINT16>, HBUINT, false> component; /* Offset to the component table. */ - LOffsetTo<UnsizedArrayOf<GlyphID>, false> + OffsetTo<UnsizedArrayOf<GlyphID>, HBUINT, false> ligature; /* Offset to the actual ligature lists. */ public: DEFINE_SIZE_STATIC (28); }; +template <typename Types> struct NoncontextualSubtable { inline bool apply (hb_aat_apply_context_t *c) const @@ -545,8 +556,11 @@ struct NoncontextualSubtable DEFINE_SIZE_MIN (2); }; +template <typename Types> struct InsertionSubtable { + typedef typename Types::HBUINT HBUINT; + struct EntryData { HBUINT16 currentInsertIndex; /* Zero-based index into the insertion glyph table. @@ -622,13 +636,13 @@ struct InsertionSubtable mark (0), insertionAction (table+table->insertionAction) {} - inline bool is_actionable (StateTableDriver<EntryData> *driver HB_UNUSED, + inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver HB_UNUSED, const Entry<EntryData> *entry) { return (entry->flags & (CurrentInsertCount | MarkedInsertCount)) && (entry->data.currentInsertIndex != 0xFFFF ||entry->data.markedInsertIndex != 0xFFFF); } - inline bool transition (StateTableDriver<EntryData> *driver, + inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver, const Entry<EntryData> *entry) { hb_buffer_t *buffer = driver->buffer; @@ -720,7 +734,7 @@ struct InsertionSubtable driver_context_t dc (this, c); - StateTableDriver<EntryData> driver (machine, c->buffer, c->face); + StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->face); driver.drive (&dc); return_trace (dc.ret); @@ -735,9 +749,9 @@ struct InsertionSubtable } protected: - StateTable<EntryData> + StateTable<Types, EntryData> machine; - LOffsetTo<UnsizedArrayOf<GlyphID>, false> + OffsetTo<UnsizedArrayOf<GlyphID>, HBUINT, false> insertionAction; /* Byte offset from stateHeader to the start of * the insertion glyph table. */ public: @@ -765,9 +779,10 @@ struct Feature DEFINE_SIZE_STATIC (12); }; - +template <typename Types> struct ChainSubtable { + template <typename T> friend struct Chain; inline unsigned int get_size (void) const { return length; } @@ -830,18 +845,21 @@ struct ChainSubtable HBUINT32 coverage; /* Coverage flags and subtable type. */ HBUINT32 subFeatureFlags;/* The 32-bit mask identifying which subtable this is. */ union { - RearrangementSubtable rearrangement; - ContextualSubtable contextual; - LigatureSubtable ligature; - NoncontextualSubtable noncontextual; - InsertionSubtable insertion; + RearrangementSubtable<Types> rearrangement; + ContextualSubtable<Types> contextual; + LigatureSubtable<Types> ligature; + NoncontextualSubtable<Types> noncontextual; + InsertionSubtable<Types> insertion; } u; public: - DEFINE_SIZE_MIN (12); + DEFINE_SIZE_MIN (2 * sizeof (HBUINT32) + 4); }; +template <typename Types> struct Chain { + typedef typename Types::HBUINT HBUINT; + inline hb_mask_t compile_flags (const hb_aat_map_builder_t *map) const { hb_mask_t flags = defaultFlags; @@ -868,7 +886,7 @@ struct Chain inline void apply (hb_aat_apply_context_t *c, hb_mask_t flags) const { - const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (&featureZ, featureZ[0].static_size * featureCount); + const ChainSubtable<Types> *subtable = &StructAtOffset<ChainSubtable<Types> > (&featureZ, featureZ[0].static_size * featureCount); unsigned int count = subtableCount; for (unsigned int i = 0; i < count; i++) { @@ -877,9 +895,9 @@ struct Chain if (!(subtable->subFeatureFlags & flags)) goto skip; - if (!(subtable->coverage & ChainSubtable::AllDirections) && + if (!(subtable->coverage & ChainSubtable<Types>::AllDirections) && HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) != - bool (subtable->coverage & ChainSubtable::Vertical)) + bool (subtable->coverage & ChainSubtable<Types>::Vertical)) goto skip; /* Buffer contents is always in logical direction. Determine if @@ -909,9 +927,9 @@ struct Chain (the order opposite that of the characters, which may be right-to-left or left-to-right). */ - reverse = subtable->coverage & ChainSubtable::Logical ? - bool (subtable->coverage & ChainSubtable::Backwards) : - bool (subtable->coverage & ChainSubtable::Backwards) != + reverse = subtable->coverage & ChainSubtable<Types>::Logical ? + bool (subtable->coverage & ChainSubtable<Types>::Backwards) : + bool (subtable->coverage & ChainSubtable<Types>::Backwards) != HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction); if (!c->buffer->message (c->font, "start chain subtable %d", c->lookup_index)) @@ -932,7 +950,7 @@ struct Chain if (unlikely (!c->buffer->successful)) return; skip: - subtable = &StructAfter<ChainSubtable> (*subtable); + subtable = &StructAfter<ChainSubtable<Types> > (*subtable); c->set_lookup_index (c->lookup_index + 1); } } @@ -950,38 +968,39 @@ struct Chain if (!c->check_array (featureZ.arrayZ, featureCount)) return_trace (false); - const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (&featureZ, featureZ[0].static_size * featureCount); + const ChainSubtable<Types> *subtable = &StructAtOffset<ChainSubtable<Types> > (&featureZ, featureZ[0].static_size * featureCount); unsigned int count = subtableCount; for (unsigned int i = 0; i < count; i++) { if (!subtable->sanitize (c)) return_trace (false); - subtable = &StructAfter<ChainSubtable> (*subtable); + subtable = &StructAfter<ChainSubtable<Types> > (*subtable); } return_trace (true); } protected: - HBUINT32 defaultFlags; /* The default specification for subtables. */ - HBUINT32 length; /* Total byte count, including this header. */ - HBUINT32 featureCount; /* Number of feature subtable entries. */ - HBUINT32 subtableCount; /* The number of subtables in the chain. */ + HBUINT defaultFlags; /* The default specification for subtables. */ + HBUINT length; /* Total byte count, including this header. */ + HBUINT featureCount; /* Number of feature subtable entries. */ + HBUINT subtableCount; /* The number of subtables in the chain. */ UnsizedArrayOf<Feature> featureZ; /* Features. */ /*ChainSubtable firstSubtable;*//* Subtables. */ /*subtableGlyphCoverageArray*/ /* Only if version >= 3. We don't use. */ public: - DEFINE_SIZE_MIN (16); + DEFINE_SIZE_MIN (2 * sizeof (HBUINT) + 4); }; /* - * The 'morx' Table + * The 'mort'/'morx' Table */ -struct morx +template <typename Types> +struct mortmorx { static const hb_tag_t tableTag = HB_AAT_TAG_morx; @@ -990,12 +1009,12 @@ struct morx inline void compile_flags (const hb_aat_map_builder_t *mapper, hb_aat_map_t *map) const { - const Chain *chain = &firstChain; + const Chain<Types> *chain = &firstChain; unsigned int count = chainCount; for (unsigned int i = 0; i < count; i++) { map->chain_flags.push (chain->compile_flags (mapper)); - chain = &StructAfter<Chain> (*chain); + chain = &StructAfter<Chain<Types> > (*chain); } } @@ -1019,13 +1038,13 @@ struct morx { if (unlikely (!c->buffer->successful)) return; c->set_lookup_index (0); - const Chain *chain = &firstChain; + const Chain<Types> *chain = &firstChain; unsigned int count = chainCount; for (unsigned int i = 0; i < count; i++) { chain->apply (c, c->plan->aat_map.chain_flags[i]); if (unlikely (!c->buffer->successful)) return; - chain = &StructAfter<Chain> (*chain); + chain = &StructAfter<Chain<Types> > (*chain); } remove_deleted_glyphs (c->buffer); } @@ -1037,13 +1056,13 @@ struct morx !chainCount.sanitize (c)) return_trace (false); - const Chain *chain = &firstChain; + const Chain<Types> *chain = &firstChain; unsigned int count = chainCount; for (unsigned int i = 0; i < count; i++) { if (!chain->sanitize (c, version)) return_trace (false); - chain = &StructAfter<Chain> (*chain); + chain = &StructAfter<Chain<Types> > (*chain); } return_trace (true); @@ -1055,12 +1074,22 @@ struct morx HBUINT16 unused; /* Set to 0. */ HBUINT32 chainCount; /* Number of metamorphosis chains contained in this * table. */ - Chain firstChain; /* Chains. */ + Chain<Types> firstChain; /* Chains. */ public: DEFINE_SIZE_MIN (8); }; +struct morx : mortmorx<MorxTypes> +{ + static const hb_tag_t tableTag = HB_AAT_TAG_morx; +}; +struct mort : mortmorx<MortTypes> +{ + static const hb_tag_t tableTag = HB_AAT_TAG_mort; +}; + + } /* namespace AAT */ diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index ec053938..59157c21 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -130,9 +130,23 @@ hb_aat_layout_find_feature_mapping (hb_tag_t tag) /* - * morx/kerx/trak + * mort/morx/kerx/trak */ +// static inline const AAT::mort& +// _get_mort (hb_face_t *face, hb_blob_t **blob = nullptr) +// { +// if (unlikely (!hb_ot_shaper_face_data_ensure (face))) +// { +// if (blob) +// *blob = hb_blob_get_empty (); +// return Null(AAT::mort); +// } +// const AAT::morx& mort = *(hb_ot_face_data (face)->mort.get ()); +// if (blob) +// *blob = hb_ot_face_data (face)->mort.get_blob (); +// return mort; +// } static inline const AAT::morx& _get_morx (hb_face_t *face, hb_blob_t **blob = nullptr) { diff --git a/src/hb-ot-face.hh b/src/hb-ot-face.hh index f3b7945b..6e629eb4 100644 --- a/src/hb-ot-face.hh +++ b/src/hb-ot-face.hh @@ -52,6 +52,7 @@ HB_OT_TABLE(OT, BASE) \ /* AAT shaping. */ \ HB_OT_TABLE(AAT, morx) \ + HB_OT_TABLE(AAT, mort) \ HB_OT_TABLE(AAT, kerx) \ HB_OT_TABLE(AAT, ankr) \ HB_OT_TABLE(AAT, trak) \ _______________________________________________ HarfBuzz mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/harfbuzz
