diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index ce40abd55..7327cc5b2 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -410,9 +410,13 @@ struct Entry DEFINE_SIZE_STATIC (4); }; -template +template 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, false> + OffsetTo classTable; /* Offset to the class table. */ - LOffsetTo, false> + OffsetTo, HBUINT, false> stateArrayTable;/* Offset to the state array. */ - LOffsetTo >, false> + OffsetTo >, HBUINT, false> entryTable; /* Offset to the entry array. */ public: DEFINE_SIZE_STATIC (16); }; -template +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 + 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 + { + 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 struct StateTableDriver { - inline StateTableDriver (const StateTable &machine_, + inline StateTableDriver (const StateTable &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::STATE_START_OF_TEXT; + unsigned int state = StateTable::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::CLASS_END_OF_TEXT; + (unsigned) StateTable::CLASS_END_OF_TEXT; const Entry *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::STATE_START_OF_TEXT && + !(entry->newState == StateTable::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 &machine; + const StateTable &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 a88312501..94e0a9b62 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 *driver HB_UNUSED, + inline bool is_actionable (StateTableDriver *driver HB_UNUSED, const Entry *entry) { return entry->data.kernActionIndex != 0xFFFF; } - inline bool transition (StateTableDriver *driver, + inline bool transition (StateTableDriver *driver, const Entry *entry) { hb_buffer_t *buffer = driver->buffer; @@ -239,7 +239,7 @@ struct KerxSubTableFormat1 driver_context_t dc (this, c); - StateTableDriver driver (machine, c->buffer, c->font->face); + StateTableDriver driver (machine, c->buffer, c->font->face); driver.drive (&dc); return_trace (true); @@ -255,7 +255,7 @@ struct KerxSubTableFormat1 protected: KerxSubTableHeader header; - StateTable machine; + StateTable machine; LOffsetTo, false> kernAction; public: DEFINE_SIZE_STATIC (32); @@ -365,12 +365,12 @@ struct KerxSubTableFormat4 mark_set (false), mark (0) {} - inline bool is_actionable (StateTableDriver *driver HB_UNUSED, + inline bool is_actionable (StateTableDriver *driver HB_UNUSED, const Entry *entry) { return entry->data.ankrActionIndex != 0xFFFF; } - inline bool transition (StateTableDriver *driver, + inline bool transition (StateTableDriver *driver, const Entry *entry) { hb_buffer_t *buffer = driver->buffer; @@ -473,7 +473,7 @@ struct KerxSubTableFormat4 driver_context_t dc (this, c); - StateTableDriver driver (machine, c->buffer, c->font->face); + StateTableDriver driver (machine, c->buffer, c->font->face); driver.drive (&dc); return_trace (true); @@ -489,7 +489,8 @@ struct KerxSubTableFormat4 protected: KerxSubTableHeader header; - StateTable machine; + StateTable + 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 a56209104..336d0e35f 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 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 *driver HB_UNUSED, + inline bool is_actionable (StateTableDriver *driver HB_UNUSED, const Entry *entry) { return (entry->flags & Verb) && start < end; } - inline bool transition (StateTableDriver *driver, + inline bool transition (StateTableDriver *driver, const Entry *entry) { hb_buffer_t *buffer = driver->buffer; @@ -165,7 +169,7 @@ struct RearrangementSubtable driver_context_t dc (this); - StateTableDriver driver (machine, c->buffer, c->face); + StateTableDriver driver (machine, c->buffer, c->face); driver.drive (&dc); return_trace (dc.ret); @@ -178,13 +182,16 @@ struct RearrangementSubtable } protected: - StateTable machine; + StateTable machine; public: DEFINE_SIZE_STATIC (16); }; +template 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 *driver, + inline bool is_actionable (StateTableDriver *driver, const Entry *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 *driver, + inline bool transition (StateTableDriver *driver, const Entry *entry) { hb_buffer_t *buffer = driver->buffer; @@ -280,7 +287,7 @@ struct ContextualSubtable driver_context_t dc (this); - StateTableDriver driver (machine, c->buffer, c->face); + StateTableDriver driver (machine, c->buffer, c->face); driver.drive (&dc); return_trace (dc.ret); @@ -310,16 +317,19 @@ struct ContextualSubtable } protected: - StateTable + StateTable machine; - LOffsetTo, HBUINT32, false>, false> + OffsetTo, HBUINT, false>, HBUINT, false> substitutionTables; public: DEFINE_SIZE_STATIC (20); }; +template 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 *driver HB_UNUSED, + inline bool is_actionable (StateTableDriver *driver HB_UNUSED, const Entry *entry) { return entry->flags & PerformAction; } - inline bool transition (StateTableDriver *driver, + inline bool transition (StateTableDriver *driver, const Entry *entry) { hb_buffer_t *buffer = driver->buffer; @@ -482,7 +492,7 @@ struct LigatureSubtable driver_context_t dc (this, c); - StateTableDriver driver (machine, c->buffer, c->face); + StateTableDriver driver (machine, c->buffer, c->face); driver.drive (&dc); return_trace (dc.ret); @@ -497,18 +507,19 @@ struct LigatureSubtable } protected: - StateTable + StateTable machine; - LOffsetTo, false> + OffsetTo, HBUINT, false> ligAction; /* Offset to the ligature action table. */ - LOffsetTo, false> + OffsetTo, HBUINT, false> component; /* Offset to the component table. */ - LOffsetTo, false> + OffsetTo, HBUINT, false> ligature; /* Offset to the actual ligature lists. */ public: DEFINE_SIZE_STATIC (28); }; +template struct NoncontextualSubtable { inline bool apply (hb_aat_apply_context_t *c) const @@ -545,8 +556,11 @@ struct NoncontextualSubtable DEFINE_SIZE_MIN (2); }; +template 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 *driver HB_UNUSED, + inline bool is_actionable (StateTableDriver *driver HB_UNUSED, const Entry *entry) { return (entry->flags & (CurrentInsertCount | MarkedInsertCount)) && (entry->data.currentInsertIndex != 0xFFFF ||entry->data.markedInsertIndex != 0xFFFF); } - inline bool transition (StateTableDriver *driver, + inline bool transition (StateTableDriver *driver, const Entry *entry) { hb_buffer_t *buffer = driver->buffer; @@ -720,7 +734,7 @@ struct InsertionSubtable driver_context_t dc (this, c); - StateTableDriver driver (machine, c->buffer, c->face); + StateTableDriver driver (machine, c->buffer, c->face); driver.drive (&dc); return_trace (dc.ret); @@ -735,9 +749,9 @@ struct InsertionSubtable } protected: - StateTable + StateTable machine; - LOffsetTo, false> + OffsetTo, 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 struct ChainSubtable { + template 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 rearrangement; + ContextualSubtable contextual; + LigatureSubtable ligature; + NoncontextualSubtable noncontextual; + InsertionSubtable insertion; } u; public: - DEFINE_SIZE_MIN (12); + DEFINE_SIZE_MIN (2 * sizeof (HBUINT32) + 4); }; +template 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 (&featureZ, featureZ[0].static_size * featureCount); + const ChainSubtable *subtable = &StructAtOffset > (&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::AllDirections) && HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) != - bool (subtable->coverage & ChainSubtable::Vertical)) + bool (subtable->coverage & ChainSubtable::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::Logical ? + bool (subtable->coverage & ChainSubtable::Backwards) : + bool (subtable->coverage & ChainSubtable::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 (*subtable); + subtable = &StructAfter > (*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 (&featureZ, featureZ[0].static_size * featureCount); + const ChainSubtable *subtable = &StructAtOffset > (&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 (*subtable); + subtable = &StructAfter > (*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 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 +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 *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 = &StructAfter > (*chain); } } @@ -1019,13 +1038,13 @@ struct morx { if (unlikely (!c->buffer->successful)) return; c->set_lookup_index (0); - const Chain *chain = &firstChain; + const Chain *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 = &StructAfter > (*chain); } remove_deleted_glyphs (c->buffer); } @@ -1037,13 +1056,13 @@ struct morx !chainCount.sanitize (c)) return_trace (false); - const Chain *chain = &firstChain; + const Chain *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 = &StructAfter > (*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 firstChain; /* Chains. */ public: DEFINE_SIZE_MIN (8); }; +struct morx : mortmorx +{ + static const hb_tag_t tableTag = HB_AAT_TAG_morx; +}; +struct mort : mortmorx +{ + 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 ec053938f..59157c216 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 f3b7945bb..6e629eb41 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) \