diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index f77521f68..828a35933 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -31,6 +31,8 @@ #include "hb-aat-map.hh" #include "hb-open-type.hh" #include "hb-cache.hh" +#include "hb-bit-page.hh" + namespace OT { struct GDEF; @@ -111,6 +113,13 @@ struct LookupFormat0 { glyphs.add_range (0, num_glyphs - 1); } + template + void collect_glyphs_filtered (set_t &glyphs, unsigned num_glyphs, const filter_t &filter) const + { + for (unsigned i = 0; i < num_glyphs; i++) + if (filter (arrayZ[i])) + glyphs.add (i); + } bool sanitize (hb_sanitize_context_t *c) const { @@ -143,8 +152,13 @@ struct LookupSegmentSingle template void collect_glyphs (set_t &glyphs) const { - if (first == DELETED_GLYPH) - return; + if (first == DELETED_GLYPH) return; + glyphs.add_range (first, last); + } + template + void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const + { + if (!filter (value)) return; glyphs.add_range (first, last); } @@ -185,6 +199,13 @@ struct LookupFormat2 for (unsigned int i = 0; i < count; i++) segments[i].collect_glyphs (glyphs); } + template + void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const + { + unsigned count = segments.get_length (); + for (unsigned int i = 0; i < count; i++) + segments[i].collect_glyphs_filtered (glyphs, filter); + } bool sanitize (hb_sanitize_context_t *c) const { @@ -220,10 +241,17 @@ struct LookupSegmentArray template void collect_glyphs (set_t &glyphs) const { - if (first == DELETED_GLYPH) - return; + if (first == DELETED_GLYPH) return; glyphs.add_range (first, last); } + template + void collect_glyphs_filtered (set_t &glyphs, const void *base, const filter_t &filter) const + { + const auto &values = base+valuesZ; + for (hb_codepoint_t i = first; i <= last; i++) + if (filter (values[i - first])) + glyphs.add (i); + } int cmp (hb_codepoint_t g) const { return g < first ? -1 : g <= last ? 0 : +1; } @@ -274,6 +302,13 @@ struct LookupFormat4 for (unsigned i = 0; i < count; i++) segments[i].collect_glyphs (glyphs); } + template + void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const + { + unsigned count = segments.get_length (); + for (unsigned i = 0; i < count; i++) + segments[i].collect_glyphs_filtered (glyphs, this, filter); + } bool sanitize (hb_sanitize_context_t *c) const { @@ -306,8 +341,13 @@ struct LookupSingle template void collect_glyphs (set_t &glyphs) const { - if (glyph == DELETED_GLYPH) - return; + if (glyph == DELETED_GLYPH) return; + glyphs.add (glyph); + } + template + void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const + { + if (!filter (value)) return; glyphs.add (glyph); } @@ -347,6 +387,13 @@ struct LookupFormat6 for (unsigned i = 0; i < count; i++) entries[i].collect_glyphs (glyphs); } + template + void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const + { + unsigned count = entries.get_length (); + for (unsigned i = 0; i < count; i++) + entries[i].collect_glyphs_filtered (glyphs, filter); + } bool sanitize (hb_sanitize_context_t *c) const { @@ -382,12 +429,20 @@ struct LookupFormat8 template void collect_glyphs (set_t &glyphs) const { - if (unlikely (!glyphCount)) - return; - if (firstGlyph == DELETED_GLYPH) - return; + if (unlikely (!glyphCount)) return; + if (firstGlyph == DELETED_GLYPH) return; glyphs.add_range (firstGlyph, firstGlyph + glyphCount - 1); } + template + void collect_glyphs_filtered (set_t &glyphs, const filter_t &filter) const + { + if (unlikely (!glyphCount)) return; + if (firstGlyph == DELETED_GLYPH) return; + const T *p = valueArrayZ.arrayZ; + for (unsigned i = 0; i < glyphCount; i++) + if (filter (p[i])) + glyphs.add (firstGlyph + i); + } bool sanitize (hb_sanitize_context_t *c) const { @@ -436,10 +491,8 @@ struct LookupFormat10 template void collect_glyphs (set_t &glyphs) const { - if (unlikely (!glyphCount)) - return; - if (firstGlyph == DELETED_GLYPH) - return; + if (unlikely (!glyphCount)) return; + if (firstGlyph == DELETED_GLYPH) return; glyphs.add_range (firstGlyph, firstGlyph + glyphCount - 1); } @@ -504,6 +557,18 @@ struct Lookup default:return; } } + template + void collect_glyphs_filtered (set_t &glyphs, unsigned num_glyphs, const filter_t &filter) const + { + switch (u.format) { + case 0: hb_barrier (); u.format0.collect_glyphs_filtered (glyphs, num_glyphs, filter); return; + case 2: hb_barrier (); u.format2.collect_glyphs_filtered (glyphs, filter); return; + case 4: hb_barrier (); u.format4.collect_glyphs_filtered (glyphs, filter); return; + case 6: hb_barrier (); u.format6.collect_glyphs_filtered (glyphs, filter); return; + case 8: hb_barrier (); u.format8.collect_glyphs_filtered (glyphs, filter); return; + default:return; + } + } typename T::type get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs, @@ -635,6 +700,33 @@ struct StateTable { (this+classTable).collect_glyphs (glyphs, num_glyphs); } + template + void collect_initial_glyphs (set_t &glyphs, unsigned num_glyphs, const table_t &table) const + { + unsigned num_classes = nClasses; + + if (unlikely (num_classes > hb_bit_page_t::BITS)) + { + (this+classTable).collect_glyphs (glyphs, num_glyphs); + return; + } + + // Collect all classes going out from the start state. + hb_bit_page_t filter; + + for (unsigned i = 0; i < num_classes; i++) + { + const auto &entry = get_entry (STATE_START_OF_TEXT, i); + if (new_state (entry.newState) == STATE_START_OF_TEXT && + !table.is_action_initiable (entry) && !table.is_actionable (entry)) + continue; + + filter.add (i); + } + + // And glyphs in those classes. + (this+classTable).collect_glyphs_filtered (glyphs, num_glyphs, filter); + } int new_state (unsigned int newState) const { return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; } @@ -809,6 +901,13 @@ struct ClassTable if (classArray.arrayZ[i] != CLASS_OUT_OF_BOUNDS) glyphs.add (firstGlyph + i); } + template + void collect_glyphs_filtered (set_t &glyphs, unsigned num_glyphs, const filter_t &filter) const + { + for (unsigned i = 0; i < classArray.len; i++) + if (filter (classArray.arrayZ[i])) + glyphs.add (firstGlyph + i); + } bool sanitize (hb_sanitize_context_t *c) const { @@ -924,7 +1023,7 @@ struct ExtendedTypes } }; -template +template struct StateTableDriver { using StateTableT = StateTable; @@ -935,14 +1034,6 @@ struct StateTableDriver machine (machine_), num_glyphs (face_->get_num_glyphs ()) {} - template - bool is_idempotent_on_all_out_of_bounds (context_t *c, hb_aat_apply_context_t *ac) - { - const auto entry = machine.get_entry (StateTableT::STATE_START_OF_TEXT, CLASS_OUT_OF_BOUNDS); - return !c->is_actionable (ac->buffer, this, entry) && - machine.new_state (entry.newState) == StateTableT::STATE_START_OF_TEXT; - } - template void drive (context_t *c, hb_aat_apply_context_t *ac) { @@ -1021,29 +1112,29 @@ struct StateTableDriver bool is_safe_to_break = ( /* 1. */ - !c->is_actionable (buffer, this, entry) && + !c->table->is_actionable (entry) && /* 2. */ // This one is meh, I know... ( state == StateTableT::STATE_START_OF_TEXT - || ((entry.flags & context_t::DontAdvance) && next_state == StateTableT::STATE_START_OF_TEXT) + || ((entry.flags & Flags::DontAdvance) && next_state == StateTableT::STATE_START_OF_TEXT) || ( /* 2c. */ wouldbe_entry = &machine.get_entry(StateTableT::STATE_START_OF_TEXT, klass) , /* 2c'. */ - !c->is_actionable (buffer, this, *wouldbe_entry) && + !c->table->is_actionable (*wouldbe_entry) && /* 2c". */ ( next_state == machine.new_state(wouldbe_entry->newState) && - (entry.flags & context_t::DontAdvance) == (wouldbe_entry->flags & context_t::DontAdvance) + (entry.flags & Flags::DontAdvance) == (wouldbe_entry->flags & Flags::DontAdvance) ) ) ) && /* 3. */ - !c->is_actionable (buffer, this, machine.get_entry (state, CLASS_END_OF_TEXT)) + !c->table->is_actionable (machine.get_entry (state, CLASS_END_OF_TEXT)) ); if (!is_safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len) @@ -1057,7 +1148,7 @@ struct StateTableDriver if (buffer->idx == buffer->len || unlikely (!buffer->successful)) break; - if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0) + if (!(entry.flags & Flags::DontAdvance) || buffer->max_ops-- <= 0) (void) buffer->next_glyph (); } diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index fe8684cbd..47b477263 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -207,6 +207,9 @@ struct Format1Entry typedef void EntryData; + static bool initiateAction (const Entry &entry) + { return entry.flags & Push; } + static bool performAction (const Entry &entry) { return entry.flags & Offset; } @@ -223,13 +226,21 @@ struct KerxSubTableFormat1 typedef Format1Entry Format1EntryT; typedef typename Format1EntryT::EntryData EntryData; + enum Flags + { + DontAdvance = Format1EntryT::DontAdvance, + }; + + bool is_action_initiable (const Entry &entry) const + { + return Format1EntryT::initiateAction (entry); + } + bool is_actionable (const Entry &entry) const + { return Format1EntryT::performAction (entry); } + struct driver_context_t { static constexpr bool in_place = true; - enum - { - DontAdvance = Format1EntryT::DontAdvance, - }; driver_context_t (const KerxSubTableFormat1 *table_, hb_aat_apply_context_t *c_) : @@ -242,12 +253,8 @@ struct KerxSubTableFormat1 depth (0), crossStream (table->header.coverage & table->header.CrossStream) {} - bool is_actionable (hb_buffer_t *buffer HB_UNUSED, - StateTableDriver *driver HB_UNUSED, - const Entry &entry) - { return Format1EntryT::performAction (entry); } void transition (hb_buffer_t *buffer, - StateTableDriver *driver, + StateTableDriver *driver, const Entry &entry) { unsigned int flags = entry.flags; @@ -347,9 +354,10 @@ struct KerxSubTableFormat1 } } - private: + public: hb_aat_apply_context_t *c; const KerxSubTableFormat1 *table; + private: const UnsizedArrayOf &kernAction; unsigned int stack[8]; unsigned int depth; @@ -366,7 +374,7 @@ struct KerxSubTableFormat1 driver_context_t dc (this, c); - StateTableDriver driver (machine, c->font->face); + StateTableDriver driver (machine, c->font->face); driver.drive (&dc, c); @@ -500,17 +508,26 @@ struct KerxSubTableFormat4 DEFINE_SIZE_STATIC (2); }; + enum Flags + { + Mark = 0x8000, /* If set, remember this glyph as the marked glyph. */ + DontAdvance = 0x4000, /* If set, don't advance to the next glyph before + * going to the new state. */ + Reserved = 0x3FFF, /* Not used; set to 0. */ + }; + + bool is_action_initiable (const Entry &entry) const + { + return (entry.flags & Mark); + } + bool is_actionable (const Entry &entry) const + { + return entry.data.ankrActionIndex != 0xFFFF; + } + struct driver_context_t { static constexpr bool in_place = true; - enum Flags - { - Mark = 0x8000, /* If set, remember this glyph as the marked glyph. */ - DontAdvance = 0x4000, /* If set, don't advance to the next glyph before - * going to the new state. */ - Reserved = 0x3FFF, /* Not used; set to 0. */ - }; - enum SubTableFlags { ActionType = 0xC0000000, /* A two-bit field containing the action type. */ @@ -520,20 +537,17 @@ struct KerxSubTableFormat4 * point table. */ }; - driver_context_t (const KerxSubTableFormat4 *table, + driver_context_t (const KerxSubTableFormat4 *table_, hb_aat_apply_context_t *c_) : c (c_), + table (table_), action_type ((table->flags & ActionType) >> 30), ankrData ((HBUINT16 *) ((const char *) &table->machine + (table->flags & Offset))), mark_set (false), mark (0) {} - bool is_actionable (hb_buffer_t *buffer HB_UNUSED, - StateTableDriver *driver HB_UNUSED, - const Entry &entry) - { return entry.data.ankrActionIndex != 0xFFFF; } void transition (hb_buffer_t *buffer, - StateTableDriver *driver, + StateTableDriver *driver, const Entry &entry) { if (mark_set && entry.data.ankrActionIndex != 0xFFFF && buffer->idx < buffer->len) @@ -621,8 +635,10 @@ struct KerxSubTableFormat4 } } - private: + public: hb_aat_apply_context_t *c; + const KerxSubTableFormat4 *table; + private: unsigned int action_type; const HBUINT16 *ankrData; bool mark_set; @@ -635,7 +651,7 @@ struct KerxSubTableFormat4 driver_context_t dc (this, c); - StateTableDriver driver (machine, c->font->face); + StateTableDriver driver (machine, c->font->face); driver.drive (&dc, c); diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index ffe5676a4..f0f5b2141 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -53,35 +53,40 @@ struct RearrangementSubtable typedef void EntryData; - struct driver_context_t + enum Flags { - static constexpr bool in_place = true; - enum Flags - { - MarkFirst = 0x8000, /* If set, make the current glyph the first + MarkFirst = 0x8000, /* If set, make the current glyph the first * glyph to be rearranged. */ - DontAdvance = 0x4000, /* If set, don't advance to the next glyph + DontAdvance = 0x4000, /* If set, don't advance to the next glyph * before going to the new state. This means * that the glyph index doesn't change, even * if the glyph at that index has changed. */ - MarkLast = 0x2000, /* If set, make the current glyph the last + MarkLast = 0x2000, /* If set, make the current glyph the last * glyph to be rearranged. */ - Reserved = 0x1FF0, /* These bits are reserved and should be set to 0. */ - Verb = 0x000F, /* The type of rearrangement specified. */ - }; + Reserved = 0x1FF0, /* These bits are reserved and should be set to 0. */ + Verb = 0x000F, /* The type of rearrangement specified. */ + }; - driver_context_t (const RearrangementSubtable *table HB_UNUSED) : + bool is_action_initiable (const Entry &entry) const + { + return (entry.flags & MarkFirst); + } + bool is_actionable (const Entry &entry) const + { + return (entry.flags & Verb); + } + + struct driver_context_t + { + static constexpr bool in_place = true; + + driver_context_t (const RearrangementSubtable *table_) : ret (false), + table (table_), start (0), end (0) {} - bool is_actionable (hb_buffer_t *buffer HB_UNUSED, - StateTableDriver *driver HB_UNUSED, - const Entry &entry) const - { - return (entry.flags & Verb) && start < end; - } void transition (hb_buffer_t *buffer, - StateTableDriver *driver, + StateTableDriver *driver, const Entry &entry) { unsigned int flags = entry.flags; @@ -158,6 +163,7 @@ struct RearrangementSubtable public: bool ret; + const RearrangementSubtable *table; private: unsigned int start; unsigned int end; @@ -169,10 +175,9 @@ struct RearrangementSubtable driver_context_t dc (this); - StateTableDriver driver (machine, c->face); + StateTableDriver driver (machine, c->face); - if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) && - !c->buffer_glyph_set.may_intersect (*c->machine_glyph_set)) + if (!c->buffer_glyph_set.may_intersect (*c->machine_glyph_set)) { (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); return_trace (false); @@ -210,39 +215,40 @@ struct ContextualSubtable DEFINE_SIZE_STATIC (4); }; + enum Flags + { + SetMark = 0x8000, /* If set, make the current glyph the marked glyph. */ + DontAdvance = 0x4000, /* If set, don't advance to the next glyph before + * going to the new state. */ + Reserved = 0x3FFF, /* These bits are reserved and should be set to 0. */ + }; + + bool is_action_initiable (const Entry &entry) const + { + return (entry.flags & SetMark); + } + bool is_actionable (const Entry &entry) const + { + return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF; + } + struct driver_context_t { static constexpr bool in_place = true; - enum Flags - { - SetMark = 0x8000, /* If set, make the current glyph the marked glyph. */ - DontAdvance = 0x4000, /* If set, don't advance to the next glyph before - * going to the new state. */ - Reserved = 0x3FFF, /* These bits are reserved and should be set to 0. */ - }; driver_context_t (const ContextualSubtable *table_, hb_aat_apply_context_t *c_) : ret (false), c (c_), + table (table_), gdef (*c->gdef_table), mark_set (false), has_glyph_classes (gdef.has_glyph_classes ()), mark (0), - table (table_), subs (table+table->substitutionTables) {} - bool is_actionable (hb_buffer_t *buffer, - StateTableDriver *driver, - const Entry &entry) const - { - if (buffer->idx == buffer->len && !mark_set) - return false; - - return entry.data.markIndex != 0xFFFF || entry.data.currentIndex != 0xFFFF; - } void transition (hb_buffer_t *buffer, - StateTableDriver *driver, + StateTableDriver *driver, const Entry &entry) { /* Looks like CoreText applies neither mark nor current substitution for @@ -323,13 +329,13 @@ struct ContextualSubtable public: bool ret; - private: hb_aat_apply_context_t *c; + const ContextualSubtable *table; + private: const OT::GDEF &gdef; bool mark_set; bool has_glyph_classes; unsigned int mark; - const ContextualSubtable *table; const UnsizedListOfOffset16To, HBUINT, void, false> &subs; }; @@ -339,10 +345,9 @@ struct ContextualSubtable driver_context_t dc (this, c); - StateTableDriver driver (machine, c->face); + StateTableDriver driver (machine, c->face); - if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) && - !c->buffer_glyph_set.may_intersect (*c->machine_glyph_set)) + if (!c->buffer_glyph_set.may_intersect (*c->machine_glyph_set)) { (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); return_trace (false); @@ -397,6 +402,16 @@ struct LigatureEntry; template <> struct LigatureEntry { + + struct EntryData + { + HBUINT16 ligActionIndex; /* Index to the first ligActionTable entry + * for processing this group, if indicated + * by the flags. */ + public: + DEFINE_SIZE_STATIC (2); + }; + enum Flags { SetComponent = 0x8000, /* Push this glyph onto the component stack for @@ -408,14 +423,8 @@ struct LigatureEntry Reserved = 0x1FFF, /* These bits are reserved and should be set to 0. */ }; - struct EntryData - { - HBUINT16 ligActionIndex; /* Index to the first ligActionTable entry - * for processing this group, if indicated - * by the flags. */ - public: - DEFINE_SIZE_STATIC (2); - }; + static bool initiateAction (const Entry &entry) + { return entry.flags & SetComponent; } static bool performAction (const Entry &entry) { return entry.flags & PerformAction; } @@ -426,6 +435,8 @@ struct LigatureEntry template <> struct LigatureEntry { + typedef void EntryData; + enum Flags { SetComponent = 0x8000, /* Push this glyph onto the component stack for @@ -437,7 +448,8 @@ struct LigatureEntry * multiple of 4. */ }; - typedef void EntryData; + static bool initiateAction (const Entry &entry) + { return entry.flags & SetComponent; } static bool performAction (const Entry &entry) { return entry.flags & Offset; } @@ -455,13 +467,23 @@ struct LigatureSubtable typedef LigatureEntry LigatureEntryT; typedef typename LigatureEntryT::EntryData EntryData; + enum Flags + { + DontAdvance = LigatureEntryT::DontAdvance, + }; + + bool is_action_initiable (const Entry &entry) const + { + return LigatureEntryT::initiateAction (entry); + } + bool is_actionable (const Entry &entry) const + { + return LigatureEntryT::performAction (entry); + } + struct driver_context_t { static constexpr bool in_place = false; - enum - { - DontAdvance = LigatureEntryT::DontAdvance, - }; enum LigActionFlags { LigActionLast = 0x80000000, /* This is the last action in the list. This also @@ -484,14 +506,8 @@ struct LigatureSubtable ligature (table+table->ligature), match_length (0) {} - bool is_actionable (hb_buffer_t *buffer HB_UNUSED, - StateTableDriver *driver HB_UNUSED, - const Entry &entry) const - { - return LigatureEntryT::performAction (entry); - } void transition (hb_buffer_t *buffer, - StateTableDriver *driver, + StateTableDriver *driver, const Entry &entry) { DEBUG_MSG (APPLY, nullptr, "Ligature transition at %u", buffer->idx); @@ -589,9 +605,9 @@ struct LigatureSubtable public: bool ret; - private: hb_aat_apply_context_t *c; const LigatureSubtable *table; + private: const UnsizedArrayOf &ligAction; const UnsizedArrayOf &component; const UnsizedArrayOf &ligature; @@ -605,10 +621,9 @@ struct LigatureSubtable driver_context_t dc (this, c); - StateTableDriver driver (machine, c->face); + StateTableDriver driver (machine, c->face); - if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) && - !c->buffer_glyph_set.may_intersect (*c->machine_glyph_set)) + if (!c->buffer_glyph_set.may_intersect (*c->machine_glyph_set)) { (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); return_trace (false); @@ -698,7 +713,7 @@ struct NoncontextualSubtable } template - void collect_glyphs (set_t &glyphs, unsigned num_glyphs) const + void collect_initial_glyphs (set_t &glyphs, unsigned num_glyphs) const { substitute.collect_glyphs (glyphs, num_glyphs); } @@ -736,73 +751,78 @@ struct InsertionSubtable DEFINE_SIZE_STATIC (4); }; + enum Flags + { + SetMark = 0x8000, /* If set, mark the current glyph. */ + DontAdvance = 0x4000, /* If set, don't advance to the next glyph before + * going to the new state. This does not mean + * that the glyph pointed to is the same one as + * before. If you've made insertions immediately + * downstream of the current glyph, the next glyph + * processed would in fact be the first one + * inserted. */ + CurrentIsKashidaLike= 0x2000, /* If set, and the currentInsertList is nonzero, + * then the specified glyph list will be inserted + * as a kashida-like insertion, either before or + * after the current glyph (depending on the state + * of the currentInsertBefore flag). If clear, and + * the currentInsertList is nonzero, then the + * specified glyph list will be inserted as a + * split-vowel-like insertion, either before or + * after the current glyph (depending on the state + * of the currentInsertBefore flag). */ + MarkedIsKashidaLike= 0x1000, /* If set, and the markedInsertList is nonzero, + * then the specified glyph list will be inserted + * as a kashida-like insertion, either before or + * after the marked glyph (depending on the state + * of the markedInsertBefore flag). If clear, and + * the markedInsertList is nonzero, then the + * specified glyph list will be inserted as a + * split-vowel-like insertion, either before or + * after the marked glyph (depending on the state + * of the markedInsertBefore flag). */ + CurrentInsertBefore= 0x0800, /* If set, specifies that insertions are to be made + * to the left of the current glyph. If clear, + * they're made to the right of the current glyph. */ + MarkedInsertBefore= 0x0400, /* If set, specifies that insertions are to be + * made to the left of the marked glyph. If clear, + * they're made to the right of the marked glyph. */ + CurrentInsertCount= 0x3E0, /* This 5-bit field is treated as a count of the + * number of glyphs to insert at the current + * position. Since zero means no insertions, the + * largest number of insertions at any given + * current location is 31 glyphs. */ + MarkedInsertCount= 0x001F, /* This 5-bit field is treated as a count of the + * number of glyphs to insert at the marked + * position. Since zero means no insertions, the + * largest number of insertions at any given + * marked location is 31 glyphs. */ + }; + + bool is_action_initiable (const Entry &entry) const + { + return (entry.flags & SetMark); + } + bool is_actionable (const Entry &entry) const + { + return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) && + (entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF); + } + struct driver_context_t { static constexpr bool in_place = false; - enum Flags - { - SetMark = 0x8000, /* If set, mark the current glyph. */ - DontAdvance = 0x4000, /* If set, don't advance to the next glyph before - * going to the new state. This does not mean - * that the glyph pointed to is the same one as - * before. If you've made insertions immediately - * downstream of the current glyph, the next glyph - * processed would in fact be the first one - * inserted. */ - CurrentIsKashidaLike= 0x2000, /* If set, and the currentInsertList is nonzero, - * then the specified glyph list will be inserted - * as a kashida-like insertion, either before or - * after the current glyph (depending on the state - * of the currentInsertBefore flag). If clear, and - * the currentInsertList is nonzero, then the - * specified glyph list will be inserted as a - * split-vowel-like insertion, either before or - * after the current glyph (depending on the state - * of the currentInsertBefore flag). */ - MarkedIsKashidaLike= 0x1000, /* If set, and the markedInsertList is nonzero, - * then the specified glyph list will be inserted - * as a kashida-like insertion, either before or - * after the marked glyph (depending on the state - * of the markedInsertBefore flag). If clear, and - * the markedInsertList is nonzero, then the - * specified glyph list will be inserted as a - * split-vowel-like insertion, either before or - * after the marked glyph (depending on the state - * of the markedInsertBefore flag). */ - CurrentInsertBefore= 0x0800, /* If set, specifies that insertions are to be made - * to the left of the current glyph. If clear, - * they're made to the right of the current glyph. */ - MarkedInsertBefore= 0x0400, /* If set, specifies that insertions are to be - * made to the left of the marked glyph. If clear, - * they're made to the right of the marked glyph. */ - CurrentInsertCount= 0x3E0, /* This 5-bit field is treated as a count of the - * number of glyphs to insert at the current - * position. Since zero means no insertions, the - * largest number of insertions at any given - * current location is 31 glyphs. */ - MarkedInsertCount= 0x001F, /* This 5-bit field is treated as a count of the - * number of glyphs to insert at the marked - * position. Since zero means no insertions, the - * largest number of insertions at any given - * marked location is 31 glyphs. */ - }; - driver_context_t (const InsertionSubtable *table, + driver_context_t (const InsertionSubtable *table_, hb_aat_apply_context_t *c_) : ret (false), c (c_), + table (table_), mark (0), insertionAction (table+table->insertionAction) {} - bool is_actionable (hb_buffer_t *buffer HB_UNUSED, - StateTableDriver *driver HB_UNUSED, - const Entry &entry) const - { - return (entry.flags & (CurrentInsertCount | MarkedInsertCount)) && - (entry.data.currentInsertIndex != 0xFFFF ||entry.data.markedInsertIndex != 0xFFFF); - } void transition (hb_buffer_t *buffer, - StateTableDriver *driver, + StateTableDriver *driver, const Entry &entry) { unsigned int flags = entry.flags; @@ -882,8 +902,9 @@ struct InsertionSubtable public: bool ret; - private: hb_aat_apply_context_t *c; + const InsertionSubtable *table; + private: unsigned int mark; const UnsizedArrayOf &insertionAction; }; @@ -894,10 +915,9 @@ struct InsertionSubtable driver_context_t dc (this, c); - StateTableDriver driver (machine, c->face); + StateTableDriver driver (machine, c->face); - if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) && - !c->buffer_glyph_set.may_intersect (*c->machine_glyph_set)) + if (!c->buffer_glyph_set.may_intersect (*c->machine_glyph_set)) { (void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches"); return_trace (false); @@ -965,13 +985,13 @@ struct hb_accelerate_subtables_context_t : template auto init_ (const T &obj_, unsigned num_glyphs, hb_priority<1>) HB_AUTO_RETURN ( - obj_.machine.collect_glyphs (glyph_set, num_glyphs) + obj_.machine.collect_initial_glyphs (glyph_set, num_glyphs, obj_) ) template void init_ (const T &obj_, unsigned num_glyphs, hb_priority<0>) { - obj_.collect_glyphs (glyph_set, num_glyphs); + obj_.collect_initial_glyphs (glyph_set, num_glyphs); } template diff --git a/src/hb-bit-page.hh b/src/hb-bit-page.hh index df08c834e..373733c74 100644 --- a/src/hb-bit-page.hh +++ b/src/hb-bit-page.hh @@ -89,6 +89,8 @@ struct hb_vector_size_t struct hb_bit_page_t { + hb_bit_page_t () { init0 (); } + void init0 () { v.init0 (); population = 0; } void init1 () { v.init1 (); population = PAGE_BITS; } @@ -116,6 +118,9 @@ struct hb_bit_page_t void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); } bool get (hb_codepoint_t g) const { return elt (g) & mask (g); } + bool operator [] (hb_codepoint_t g) const { return get (g); } + bool operator () (hb_codepoint_t g) const { return get (g); } + void add_range (hb_codepoint_t a, hb_codepoint_t b) { elt_t *la = &elt (a);