diff options
Diffstat (limited to 'Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh')
-rw-r--r-- | Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh | 192 |
1 files changed, 150 insertions, 42 deletions
diff --git a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh index ee2136ed972..6572b26d86f 100644 --- a/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh +++ b/Build/source/libs/harfbuzz/harfbuzz-src/src/hb-aat-layout-common.hh @@ -58,6 +58,11 @@ struct LookupFormat0 TRACE_SANITIZE (this); return_trace (arrayZ.sanitize (c, c->get_num_glyphs ())); } + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (arrayZ.sanitize (c, c->get_num_glyphs (), base)); + } protected: HBUINT16 format; /* Format identifier--format = 0 */ @@ -80,6 +85,11 @@ struct LookupSegmentSingle TRACE_SANITIZE (this); return_trace (c->check_struct (this) && value.sanitize (c)); } + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && value.sanitize (c, base)); + } GlyphID last; /* Last GlyphID in this segment */ GlyphID first; /* First GlyphID in this segment */ @@ -105,6 +115,11 @@ struct LookupFormat2 TRACE_SANITIZE (this); return_trace (segments.sanitize (c)); } + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (segments.sanitize (c, base)); + } protected: HBUINT16 format; /* Format identifier--format = 2 */ @@ -135,6 +150,14 @@ struct LookupSegmentArray first <= last && valuesZ.sanitize (c, base, last - first + 1)); } + template <typename T2> + inline bool sanitize (hb_sanitize_context_t *c, const void *base, T2 user_data) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && + first <= last && + valuesZ.sanitize (c, base, last - first + 1, user_data)); + } GlyphID last; /* Last GlyphID in this segment */ GlyphID first; /* First GlyphID in this segment */ @@ -162,6 +185,11 @@ struct LookupFormat4 TRACE_SANITIZE (this); return_trace (segments.sanitize (c, this)); } + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (segments.sanitize (c, this, base)); + } protected: HBUINT16 format; /* Format identifier--format = 4 */ @@ -183,6 +211,11 @@ struct LookupSingle TRACE_SANITIZE (this); return_trace (c->check_struct (this) && value.sanitize (c)); } + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && value.sanitize (c, base)); + } GlyphID glyph; /* Last GlyphID */ T value; /* The lookup value (only one) */ @@ -207,6 +240,11 @@ struct LookupFormat6 TRACE_SANITIZE (this); return_trace (entries.sanitize (c)); } + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (entries.sanitize (c, base)); + } protected: HBUINT16 format; /* Format identifier--format = 6 */ @@ -233,6 +271,11 @@ struct LookupFormat8 TRACE_SANITIZE (this); return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount)); } + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount, base)); + } protected: HBUINT16 format; /* Format identifier--format = 8 */ @@ -328,6 +371,20 @@ struct Lookup default:return_trace (true); } } + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { + TRACE_SANITIZE (this); + if (!u.format.sanitize (c)) return_trace (false); + switch (u.format) { + case 0: return_trace (u.format0.sanitize (c, base)); + case 2: return_trace (u.format2.sanitize (c, base)); + case 4: return_trace (u.format4.sanitize (c, base)); + case 6: return_trace (u.format6.sanitize (c, base)); + case 8: return_trace (u.format8.sanitize (c, base)); + case 10: return_trace (false); /* No need to support format10 apparently */ + default:return_trace (true); + } + } protected: union { @@ -365,7 +422,7 @@ namespace AAT { enum { DELETED_GLYPH = 0xFFFF }; /* - * Extended State Table + * (Extended) State Table */ template <typename T> @@ -430,13 +487,13 @@ struct StateTable CLASS_END_OF_LINE = 3, }; - inline unsigned int new_state (unsigned int newState) const - { return Types::extended ? newState : (newState - stateArrayTable) / nClasses; } + inline int new_state (unsigned int newState) const + { return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / nClasses; } 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; - return (this+classTable).get_class (glyph_id, num_glyphs); + return (this+classTable).get_class (glyph_id, num_glyphs, 1); } inline const Entry<Extra> *get_entries () const @@ -444,7 +501,7 @@ struct StateTable return (this+entryTable).arrayZ; } - inline const Entry<Extra> *get_entryZ (unsigned int state, unsigned int klass) const + inline const Entry<Extra> *get_entryZ (int state, unsigned int klass) const { if (unlikely (klass >= nClasses)) return nullptr; @@ -452,6 +509,7 @@ struct StateTable const Entry<Extra> *entries = (this+entryTable).arrayZ; unsigned int entry = states[state * nClasses + klass]; + DEBUG_MSG (APPLY, nullptr, "e%u", entry); return &entries[entry]; } @@ -467,28 +525,73 @@ struct StateTable const Entry<Extra> *entries = (this+entryTable).arrayZ; unsigned int num_classes = nClasses; + if (unlikely (hb_unsigned_mul_overflows (num_classes, states[0].static_size))) + return_trace (false); + unsigned int row_stride = num_classes * states[0].static_size; - unsigned int num_states = 1; + /* Apple 'kern' table has this peculiarity: + * + * "Because the stateTableOffset in the state table header is (strictly + * speaking) redundant, some 'kern' tables use it to record an initial + * state where that should not be StartOfText. To determine if this is + * done, calculate what the stateTableOffset should be. If it's different + * from the actual stateTableOffset, use it as the initial state." + * + * We implement this by calling the initial state zero, but allow *negative* + * states if the start state indeed was not the first state. Since the code + * is shared, this will also apply to 'mort' table. The 'kerx' / 'morx' + * tables are not affected since those address states by index, not offset. + */ + + int min_state = 0; + int max_state = 0; unsigned int num_entries = 0; - unsigned int state = 0; + int state_pos = 0; + int state_neg = 0; unsigned int entry = 0; - while (state < num_states) + while (min_state < state_neg || state_pos <= max_state) { - if (unlikely (hb_unsigned_mul_overflows (num_classes, states[0].static_size))) - return_trace (false); + if (min_state < state_neg) + { + /* Negative states. */ + if (unlikely (hb_unsigned_mul_overflows (min_state, num_classes))) + return_trace (false); + if (unlikely (!c->check_range (&states[min_state * num_classes], + -min_state, + row_stride))) + return_trace (false); + if ((c->max_ops -= state_neg - min_state) < 0) + return_trace (false); + { /* Sweep new states. */ + const HBUSHORT *stop = &states[min_state * num_classes]; + if (unlikely (stop > states)) + return_trace (false); + for (const HBUSHORT *p = states; stop < p; p--) + num_entries = MAX<unsigned int> (num_entries, *(p - 1) + 1); + state_neg = min_state; + } + } - if (unlikely (!c->check_array (states, - num_states, - num_classes * states[0].static_size))) - return_trace (false); - if ((c->max_ops -= num_states - state) < 0) - return_trace (false); - { /* Sweep new states. */ - 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; + if (state_pos <= max_state) + { + /* Positive states. */ + if (unlikely (!c->check_range (states, + max_state + 1, + row_stride))) + return_trace (false); + if ((c->max_ops -= max_state - state_pos + 1) < 0) + return_trace (false); + { /* Sweep new states. */ + if (unlikely (hb_unsigned_mul_overflows ((max_state + 1), num_classes))) + return_trace (false); + const HBUSHORT *stop = &states[(max_state + 1) * num_classes]; + if (unlikely (stop < states)) + return_trace (false); + for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++) + num_entries = MAX<unsigned int> (num_entries, *p + 1); + state_pos = max_state + 1; + } } if (unlikely (!c->check_array (entries, num_entries))) @@ -499,8 +602,9 @@ struct StateTable const Entry<Extra> *stop = &entries[num_entries]; for (const Entry<Extra> *p = &entries[entry]; p < stop; p++) { - unsigned int newState = new_state (p->newState); - num_states = MAX<unsigned int> (num_states, newState + 1); + int newState = new_state (p->newState); + min_state = MIN (min_state, newState); + max_state = MAX (max_state, newState); } entry = num_entries; } @@ -528,36 +632,36 @@ struct StateTable struct ClassTable { - inline unsigned int get_class (hb_codepoint_t glyph_id) const + inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int outOfRange) const { - return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ? classArrayZ[glyph_id - firstGlyph] : 1; + unsigned int i = glyph_id - firstGlyph; + return i >= classArray.len ? outOfRange : classArray.arrayZ[i]; } inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (this) && classArrayZ.sanitize (c, glyphCount)); + return_trace (c->check_struct (this) && classArray.sanitize (c)); } 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). */ + GlyphID firstGlyph; /* First glyph index included in the trimmed array. */ + ArrayOf<HBUINT8> classArray; /* The class codes (indexed by glyph index minus + * firstGlyph). */ public: - DEFINE_SIZE_ARRAY (4, classArrayZ); + DEFINE_SIZE_ARRAY (4, classArray); }; -struct MortTypes +struct ObsoleteTypes { 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 + inline unsigned int get_class (hb_codepoint_t glyph_id, + unsigned int num_glyphs HB_UNUSED, + unsigned int outOfRange) const { - return ClassTable::get_class (glyph_id); + return ClassTable::get_class (glyph_id, outOfRange); } }; template <typename T> @@ -575,17 +679,19 @@ struct MortTypes return offsetToIndex (2 * offset, base, array); } }; -struct MorxTypes +struct ExtendedTypes { 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 + inline unsigned int get_class (hb_codepoint_t glyph_id, + unsigned int num_glyphs, + unsigned int outOfRange) const { const HBUINT16 *v = get_value (glyph_id, num_glyphs); - return v ? *v : 1; + return v ? *v : outOfRange; } }; template <typename T> @@ -620,13 +726,14 @@ struct StateTableDriver if (!c->in_place) buffer->clear_output (); - unsigned int state = StateTable<Types, EntryData>::STATE_START_OF_TEXT; + 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<Types, EntryData>::CLASS_END_OF_TEXT; + DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx); const Entry<EntryData> *entry = machine.get_entryZ (state, klass); if (unlikely (!entry)) break; @@ -659,6 +766,7 @@ struct StateTableDriver last_was_dont_advance = (entry->flags & context_t::DontAdvance) && buffer->max_ops-- > 0; state = machine.new_state (entry->newState); + DEBUG_MSG (APPLY, nullptr, "s%d", state); if (buffer->idx == buffer->len) break; @@ -693,7 +801,7 @@ struct hb_aat_apply_context_t : static return_t default_return_value (void) { return false; } bool stop_sublookup_iteration (return_t r) const { return r; } - hb_ot_shape_plan_t *plan; + const hb_ot_shape_plan_t *plan; hb_font_t *font; hb_face_t *face; hb_buffer_t *buffer; @@ -705,7 +813,7 @@ struct hb_aat_apply_context_t : unsigned int lookup_index; unsigned int debug_depth; - HB_INTERNAL hb_aat_apply_context_t (hb_ot_shape_plan_t *plan_, + 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))); |