2 * Copyright © 2017 Google, Inc.
4 * This is part of HarfBuzz, a text shaping library.
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 * Google Author(s): Behdad Esfahbod
27 #ifndef HB_AAT_LAYOUT_COMMON_HH
28 #define HB_AAT_LAYOUT_COMMON_HH
30 #include "hb-aat-layout.hh"
31 #include "hb-open-type.hh"
46 template <typename T> struct Lookup;
51 friend struct Lookup<T>;
54 const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
56 if (unlikely (glyph_id >= num_glyphs)) return nullptr;
57 return &arrayZ[glyph_id];
60 bool sanitize (hb_sanitize_context_t *c) const
62 TRACE_SANITIZE (this);
63 return_trace (arrayZ.sanitize (c, c->get_num_glyphs ()));
65 bool sanitize (hb_sanitize_context_t *c, const void *base) const
67 TRACE_SANITIZE (this);
68 return_trace (arrayZ.sanitize (c, c->get_num_glyphs (), base));
72 HBUINT16 format; /* Format identifier--format = 0 */
74 arrayZ; /* Array of lookup values, indexed by glyph index. */
76 DEFINE_SIZE_UNBOUNDED (2);
81 struct LookupSegmentSingle
83 static constexpr unsigned TerminationWordCount = 2u;
85 int cmp (hb_codepoint_t g) const
86 { return g < first ? -1 : g <= last ? 0 : +1 ; }
88 bool sanitize (hb_sanitize_context_t *c) const
90 TRACE_SANITIZE (this);
91 return_trace (c->check_struct (this) && value.sanitize (c));
93 bool sanitize (hb_sanitize_context_t *c, const void *base) const
95 TRACE_SANITIZE (this);
96 return_trace (c->check_struct (this) && value.sanitize (c, base));
99 HBGlyphID16 last; /* Last GlyphID in this segment */
100 HBGlyphID16 first; /* First GlyphID in this segment */
101 T value; /* The lookup value (only one) */
103 DEFINE_SIZE_STATIC (4 + T::static_size);
106 template <typename T>
109 friend struct Lookup<T>;
112 const T* get_value (hb_codepoint_t glyph_id) const
114 const LookupSegmentSingle<T> *v = segments.bsearch (glyph_id);
115 return v ? &v->value : nullptr;
118 bool sanitize (hb_sanitize_context_t *c) const
120 TRACE_SANITIZE (this);
121 return_trace (segments.sanitize (c));
123 bool sanitize (hb_sanitize_context_t *c, const void *base) const
125 TRACE_SANITIZE (this);
126 return_trace (segments.sanitize (c, base));
130 HBUINT16 format; /* Format identifier--format = 2 */
131 VarSizedBinSearchArrayOf<LookupSegmentSingle<T>>
132 segments; /* The actual segments. These must already be sorted,
133 * according to the first word in each one (the last
134 * glyph in each segment). */
136 DEFINE_SIZE_ARRAY (8, segments);
139 template <typename T>
140 struct LookupSegmentArray
142 static constexpr unsigned TerminationWordCount = 2u;
144 const T* get_value (hb_codepoint_t glyph_id, const void *base) const
146 return first <= glyph_id && glyph_id <= last ? &(base+valuesZ)[glyph_id - first] : nullptr;
149 int cmp (hb_codepoint_t g) const
150 { return g < first ? -1 : g <= last ? 0 : +1; }
152 bool sanitize (hb_sanitize_context_t *c, const void *base) const
154 TRACE_SANITIZE (this);
155 return_trace (c->check_struct (this) &&
157 valuesZ.sanitize (c, base, last - first + 1));
159 template <typename ...Ts>
160 bool sanitize (hb_sanitize_context_t *c, const void *base, Ts&&... ds) const
162 TRACE_SANITIZE (this);
163 return_trace (c->check_struct (this) &&
165 valuesZ.sanitize (c, base, last - first + 1, std::forward<Ts> (ds)...));
168 HBGlyphID16 last; /* Last GlyphID in this segment */
169 HBGlyphID16 first; /* First GlyphID in this segment */
170 NNOffset16To<UnsizedArrayOf<T>>
171 valuesZ; /* A 16-bit offset from the start of
172 * the table to the data. */
174 DEFINE_SIZE_STATIC (6);
177 template <typename T>
180 friend struct Lookup<T>;
183 const T* get_value (hb_codepoint_t glyph_id) const
185 const LookupSegmentArray<T> *v = segments.bsearch (glyph_id);
186 return v ? v->get_value (glyph_id, this) : nullptr;
189 bool sanitize (hb_sanitize_context_t *c) const
191 TRACE_SANITIZE (this);
192 return_trace (segments.sanitize (c, this));
194 bool sanitize (hb_sanitize_context_t *c, const void *base) const
196 TRACE_SANITIZE (this);
197 return_trace (segments.sanitize (c, this, base));
201 HBUINT16 format; /* Format identifier--format = 4 */
202 VarSizedBinSearchArrayOf<LookupSegmentArray<T>>
203 segments; /* The actual segments. These must already be sorted,
204 * according to the first word in each one (the last
205 * glyph in each segment). */
207 DEFINE_SIZE_ARRAY (8, segments);
210 template <typename T>
213 static constexpr unsigned TerminationWordCount = 1u;
215 int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
217 bool sanitize (hb_sanitize_context_t *c) const
219 TRACE_SANITIZE (this);
220 return_trace (c->check_struct (this) && value.sanitize (c));
222 bool sanitize (hb_sanitize_context_t *c, const void *base) const
224 TRACE_SANITIZE (this);
225 return_trace (c->check_struct (this) && value.sanitize (c, base));
228 HBGlyphID16 glyph; /* Last GlyphID */
229 T value; /* The lookup value (only one) */
231 DEFINE_SIZE_STATIC (2 + T::static_size);
234 template <typename T>
237 friend struct Lookup<T>;
240 const T* get_value (hb_codepoint_t glyph_id) const
242 const LookupSingle<T> *v = entries.bsearch (glyph_id);
243 return v ? &v->value : nullptr;
246 bool sanitize (hb_sanitize_context_t *c) const
248 TRACE_SANITIZE (this);
249 return_trace (entries.sanitize (c));
251 bool sanitize (hb_sanitize_context_t *c, const void *base) const
253 TRACE_SANITIZE (this);
254 return_trace (entries.sanitize (c, base));
258 HBUINT16 format; /* Format identifier--format = 6 */
259 VarSizedBinSearchArrayOf<LookupSingle<T>>
260 entries; /* The actual entries, sorted by glyph index. */
262 DEFINE_SIZE_ARRAY (8, entries);
265 template <typename T>
268 friend struct Lookup<T>;
271 const T* get_value (hb_codepoint_t glyph_id) const
273 return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ?
274 &valueArrayZ[glyph_id - firstGlyph] : nullptr;
277 bool sanitize (hb_sanitize_context_t *c) const
279 TRACE_SANITIZE (this);
280 return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount));
282 bool sanitize (hb_sanitize_context_t *c, const void *base) const
284 TRACE_SANITIZE (this);
285 return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount, base));
289 HBUINT16 format; /* Format identifier--format = 8 */
290 HBGlyphID16 firstGlyph; /* First glyph index included in the trimmed array. */
291 HBUINT16 glyphCount; /* Total number of glyphs (equivalent to the last
292 * glyph minus the value of firstGlyph plus 1). */
294 valueArrayZ; /* The lookup values (indexed by the glyph index
295 * minus the value of firstGlyph). */
297 DEFINE_SIZE_ARRAY (6, valueArrayZ);
300 template <typename T>
301 struct LookupFormat10
303 friend struct Lookup<T>;
306 const typename T::type get_value_or_null (hb_codepoint_t glyph_id) const
308 if (!(firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount))
311 const HBUINT8 *p = &valueArrayZ[(glyph_id - firstGlyph) * valueSize];
314 unsigned int count = valueSize;
315 for (unsigned int i = 0; i < count; i++)
321 bool sanitize (hb_sanitize_context_t *c) const
323 TRACE_SANITIZE (this);
324 return_trace (c->check_struct (this) &&
326 valueArrayZ.sanitize (c, glyphCount * valueSize));
330 HBUINT16 format; /* Format identifier--format = 8 */
331 HBUINT16 valueSize; /* Byte size of each value. */
332 HBGlyphID16 firstGlyph; /* First glyph index included in the trimmed array. */
333 HBUINT16 glyphCount; /* Total number of glyphs (equivalent to the last
334 * glyph minus the value of firstGlyph plus 1). */
335 UnsizedArrayOf<HBUINT8>
336 valueArrayZ; /* The lookup values (indexed by the glyph index
337 * minus the value of firstGlyph). */
339 DEFINE_SIZE_ARRAY (8, valueArrayZ);
342 template <typename T>
345 const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
348 case 0: return u.format0.get_value (glyph_id, num_glyphs);
349 case 2: return u.format2.get_value (glyph_id);
350 case 4: return u.format4.get_value (glyph_id);
351 case 6: return u.format6.get_value (glyph_id);
352 case 8: return u.format8.get_value (glyph_id);
353 default:return nullptr;
357 const typename T::type get_value_or_null (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
360 /* Format 10 cannot return a pointer. */
361 case 10: return u.format10.get_value_or_null (glyph_id);
363 const T *v = get_value (glyph_id, num_glyphs);
364 return v ? *v : Null (T);
368 typename T::type get_class (hb_codepoint_t glyph_id,
369 unsigned int num_glyphs,
370 unsigned int outOfRange) const
372 const T *v = get_value (glyph_id, num_glyphs);
373 return v ? *v : outOfRange;
376 bool sanitize (hb_sanitize_context_t *c) const
378 TRACE_SANITIZE (this);
379 if (!u.format.sanitize (c)) return_trace (false);
381 case 0: return_trace (u.format0.sanitize (c));
382 case 2: return_trace (u.format2.sanitize (c));
383 case 4: return_trace (u.format4.sanitize (c));
384 case 6: return_trace (u.format6.sanitize (c));
385 case 8: return_trace (u.format8.sanitize (c));
386 case 10: return_trace (u.format10.sanitize (c));
387 default:return_trace (true);
390 bool sanitize (hb_sanitize_context_t *c, const void *base) const
392 TRACE_SANITIZE (this);
393 if (!u.format.sanitize (c)) return_trace (false);
395 case 0: return_trace (u.format0.sanitize (c, base));
396 case 2: return_trace (u.format2.sanitize (c, base));
397 case 4: return_trace (u.format4.sanitize (c, base));
398 case 6: return_trace (u.format6.sanitize (c, base));
399 case 8: return_trace (u.format8.sanitize (c, base));
400 case 10: return_trace (false); /* We don't support format10 here currently. */
401 default:return_trace (true);
407 HBUINT16 format; /* Format identifier */
408 LookupFormat0<T> format0;
409 LookupFormat2<T> format2;
410 LookupFormat4<T> format4;
411 LookupFormat6<T> format6;
412 LookupFormat8<T> format8;
413 LookupFormat10<T> format10;
416 DEFINE_SIZE_UNION (2, format);
418 /* Lookup 0 has unbounded size (dependant on num_glyphs). So we need to defined
419 * special NULL objects for Lookup<> objects, but since it's template our macros
420 * don't work. So we have to hand-code them here. UGLY. */
421 } /* Close namespace. */
422 /* Ugly hand-coded null objects for template Lookup<> :(. */
423 extern HB_INTERNAL const unsigned char _hb_Null_AAT_Lookup[2];
424 template <typename T>
425 struct Null<AAT::Lookup<T>> {
426 static AAT::Lookup<T> const & get_null ()
427 { return *reinterpret_cast<const AAT::Lookup<T> *> (_hb_Null_AAT_Lookup); }
431 enum { DELETED_GLYPH = 0xFFFF };
434 * (Extended) State Table
437 template <typename T>
440 bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
442 TRACE_SANITIZE (this);
443 /* Note, we don't recurse-sanitize data because we don't access it.
444 * That said, in our DEFINE_SIZE_STATIC we access T::static_size,
445 * which ensures that data has a simple sanitize(). To be determined
446 * if I need to remove that as well.
448 * HOWEVER! Because we are a template, our DEFINE_SIZE_STATIC
449 * assertion wouldn't be checked, hence the line below. */
450 static_assert (T::static_size, "");
452 return_trace (c->check_struct (this));
456 HBUINT16 newState; /* Byte offset from beginning of state table
457 * to the new state. Really?!?! Or just state
458 * number? The latter in morx for sure. */
459 HBUINT16 flags; /* Table specific. */
460 T data; /* Optional offsets to per-glyph tables. */
462 DEFINE_SIZE_STATIC (4 + T::static_size);
468 bool sanitize (hb_sanitize_context_t *c, unsigned int count /*XXX Unused?*/) const
470 TRACE_SANITIZE (this);
471 return_trace (c->check_struct (this));
475 HBUINT16 newState; /* Byte offset from beginning of state table to the new state. */
476 HBUINT16 flags; /* Table specific. */
478 DEFINE_SIZE_STATIC (4);
481 template <typename Types, typename Extra>
484 typedef typename Types::HBUINT HBUINT;
485 typedef typename Types::HBUSHORT HBUSHORT;
486 typedef typename Types::ClassTypeNarrow ClassType;
490 STATE_START_OF_TEXT = 0,
491 STATE_START_OF_LINE = 1,
495 CLASS_END_OF_TEXT = 0,
496 CLASS_OUT_OF_BOUNDS = 1,
497 CLASS_DELETED_GLYPH = 2,
498 CLASS_END_OF_LINE = 3,
501 int new_state (unsigned int newState) const
502 { return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
504 unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
506 if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
507 return (this+classTable).get_class (glyph_id, num_glyphs, 1);
510 const Entry<Extra> *get_entries () const
511 { return (this+entryTable).arrayZ; }
513 const Entry<Extra> &get_entry (int state, unsigned int klass) const
515 if (unlikely (klass >= nClasses))
516 klass = StateTable::CLASS_OUT_OF_BOUNDS;
518 const HBUSHORT *states = (this+stateArrayTable).arrayZ;
519 const Entry<Extra> *entries = (this+entryTable).arrayZ;
521 unsigned int entry = states[state * nClasses + klass];
522 DEBUG_MSG (APPLY, nullptr, "e%u", entry);
524 return entries[entry];
527 bool sanitize (hb_sanitize_context_t *c,
528 unsigned int *num_entries_out = nullptr) const
530 TRACE_SANITIZE (this);
531 if (unlikely (!(c->check_struct (this) &&
532 nClasses >= 4 /* Ensure pre-defined classes fit. */ &&
533 classTable.sanitize (c, this)))) return_trace (false);
535 const HBUSHORT *states = (this+stateArrayTable).arrayZ;
536 const Entry<Extra> *entries = (this+entryTable).arrayZ;
538 unsigned int num_classes = nClasses;
539 if (unlikely (hb_unsigned_mul_overflows (num_classes, states[0].static_size)))
540 return_trace (false);
541 unsigned int row_stride = num_classes * states[0].static_size;
543 /* Apple 'kern' table has this peculiarity:
545 * "Because the stateTableOffset in the state table header is (strictly
546 * speaking) redundant, some 'kern' tables use it to record an initial
547 * state where that should not be StartOfText. To determine if this is
548 * done, calculate what the stateTableOffset should be. If it's different
549 * from the actual stateTableOffset, use it as the initial state."
551 * We implement this by calling the initial state zero, but allow *negative*
552 * states if the start state indeed was not the first state. Since the code
553 * is shared, this will also apply to 'mort' table. The 'kerx' / 'morx'
554 * tables are not affected since those address states by index, not offset.
559 unsigned int num_entries = 0;
563 unsigned int entry = 0;
564 while (min_state < state_neg || state_pos <= max_state)
566 if (min_state < state_neg)
568 /* Negative states. */
569 if (unlikely (hb_unsigned_mul_overflows (min_state, num_classes)))
570 return_trace (false);
571 if (unlikely (!c->check_range (&states[min_state * num_classes],
574 return_trace (false);
575 if ((c->max_ops -= state_neg - min_state) <= 0)
576 return_trace (false);
577 { /* Sweep new states. */
578 const HBUSHORT *stop = &states[min_state * num_classes];
579 if (unlikely (stop > states))
580 return_trace (false);
581 for (const HBUSHORT *p = states; stop < p; p--)
582 num_entries = hb_max (num_entries, *(p - 1) + 1u);
583 state_neg = min_state;
587 if (state_pos <= max_state)
589 /* Positive states. */
590 if (unlikely (!c->check_range (states,
593 return_trace (false);
594 if ((c->max_ops -= max_state - state_pos + 1) <= 0)
595 return_trace (false);
596 { /* Sweep new states. */
597 if (unlikely (hb_unsigned_mul_overflows ((max_state + 1), num_classes)))
598 return_trace (false);
599 const HBUSHORT *stop = &states[(max_state + 1) * num_classes];
600 if (unlikely (stop < states))
601 return_trace (false);
602 for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
603 num_entries = hb_max (num_entries, *p + 1u);
604 state_pos = max_state + 1;
608 if (unlikely (!c->check_array (entries, num_entries)))
609 return_trace (false);
610 if ((c->max_ops -= num_entries - entry) <= 0)
611 return_trace (false);
612 { /* Sweep new entries. */
613 const Entry<Extra> *stop = &entries[num_entries];
614 for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
616 int newState = new_state (p->newState);
617 min_state = hb_min (min_state, newState);
618 max_state = hb_max (max_state, newState);
625 *num_entries_out = num_entries;
631 HBUINT nClasses; /* Number of classes, which is the number of indices
632 * in a single line in the state array. */
633 NNOffsetTo<ClassType, HBUINT>
634 classTable; /* Offset to the class table. */
635 NNOffsetTo<UnsizedArrayOf<HBUSHORT>, HBUINT>
636 stateArrayTable;/* Offset to the state array. */
637 NNOffsetTo<UnsizedArrayOf<Entry<Extra>>, HBUINT>
638 entryTable; /* Offset to the entry array. */
641 DEFINE_SIZE_STATIC (4 * sizeof (HBUINT));
644 template <typename HBUCHAR>
647 unsigned int get_class (hb_codepoint_t glyph_id, unsigned int outOfRange) const
649 unsigned int i = glyph_id - firstGlyph;
650 return i >= classArray.len ? outOfRange : classArray.arrayZ[i];
652 unsigned int get_class (hb_codepoint_t glyph_id,
653 unsigned int num_glyphs HB_UNUSED,
654 unsigned int outOfRange) const
656 return get_class (glyph_id, outOfRange);
658 bool sanitize (hb_sanitize_context_t *c) const
660 TRACE_SANITIZE (this);
661 return_trace (c->check_struct (this) && classArray.sanitize (c));
664 HBGlyphID16 firstGlyph; /* First glyph index included in the trimmed array. */
665 Array16Of<HBUCHAR> classArray; /* The class codes (indexed by glyph index minus
668 DEFINE_SIZE_ARRAY (4, classArray);
673 static constexpr bool extended = false;
674 typedef HBUINT16 HBUINT;
675 typedef HBUINT8 HBUSHORT;
676 typedef ClassTable<HBUINT8> ClassTypeNarrow;
677 typedef ClassTable<HBUINT16> ClassTypeWide;
679 template <typename T>
680 static unsigned int offsetToIndex (unsigned int offset,
684 /* https://github.com/harfbuzz/harfbuzz/issues/2816 */
685 return (offset - unsigned ((const char *) array - (const char *) base)) / T::static_size;
687 template <typename T>
688 static unsigned int byteOffsetToIndex (unsigned int offset,
692 return offsetToIndex (offset, base, array);
694 template <typename T>
695 static unsigned int wordOffsetToIndex (unsigned int offset,
699 return offsetToIndex (2 * offset, base, array);
704 static constexpr bool extended = true;
705 typedef HBUINT32 HBUINT;
706 typedef HBUINT16 HBUSHORT;
707 typedef Lookup<HBUINT16> ClassTypeNarrow;
708 typedef Lookup<HBUINT16> ClassTypeWide;
710 template <typename T>
711 static unsigned int offsetToIndex (unsigned int offset,
712 const void *base HB_UNUSED,
713 const T *array HB_UNUSED)
717 template <typename T>
718 static unsigned int byteOffsetToIndex (unsigned int offset,
719 const void *base HB_UNUSED,
720 const T *array HB_UNUSED)
724 template <typename T>
725 static unsigned int wordOffsetToIndex (unsigned int offset,
726 const void *base HB_UNUSED,
727 const T *array HB_UNUSED)
733 template <typename Types, typename EntryData>
734 struct StateTableDriver
736 using StateTableT = StateTable<Types, EntryData>;
737 using EntryT = Entry<EntryData>;
739 StateTableDriver (const StateTableT &machine_,
740 hb_buffer_t *buffer_,
744 num_glyphs (face_->get_num_glyphs ()) {}
746 template <typename context_t>
747 void drive (context_t *c)
750 buffer->clear_output ();
752 int state = StateTableT::STATE_START_OF_TEXT;
753 for (buffer->idx = 0; buffer->successful;)
755 unsigned int klass = buffer->idx < buffer->len ?
756 machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) :
757 (unsigned) StateTableT::CLASS_END_OF_TEXT;
758 DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
759 const EntryT &entry = machine.get_entry (state, klass);
760 const int next_state = machine.new_state (entry.newState);
762 /* Conditions under which it's guaranteed safe-to-break before current glyph:
764 * 1. There was no action in this transition; and
766 * 2. If we break before current glyph, the results will be the same. That
769 * 2a. We were already in start-of-text state; or
771 * 2b. We are epsilon-transitioning to start-of-text state; or
773 * 2c. Starting from start-of-text state seeing current glyph:
775 * 2c'. There won't be any actions; and
777 * 2c". We would end up in the same state that we were going to end up
778 * in now, including whether epsilon-transitioning.
782 * 3. If we break before current glyph, there won't be any end-of-text action
783 * after previous glyph.
785 * This triples the transitions we need to look up, but is worth returning
786 * granular unsafe-to-break results. See eg.:
788 * https://github.com/harfbuzz/harfbuzz/issues/2860
790 const EntryT *wouldbe_entry;
793 !c->is_actionable (this, entry)
798 state == StateTableT::STATE_START_OF_TEXT
802 (entry.flags & context_t::DontAdvance) &&
803 next_state == StateTableT::STATE_START_OF_TEXT
808 wouldbe_entry = &machine.get_entry (StateTableT::STATE_START_OF_TEXT, klass)
811 !c->is_actionable (this, *wouldbe_entry)
815 next_state == machine.new_state (wouldbe_entry->newState)
817 (entry.flags & context_t::DontAdvance) == (wouldbe_entry->flags & context_t::DontAdvance)
823 !c->is_actionable (this, machine.get_entry (state, StateTableT::CLASS_END_OF_TEXT))
826 if (!safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len)
827 buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
829 c->transition (this, entry);
832 DEBUG_MSG (APPLY, nullptr, "s%d", state);
834 if (buffer->idx == buffer->len || unlikely (!buffer->successful))
837 if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
838 (void) buffer->next_glyph ();
846 const StateTableT &machine;
848 unsigned int num_glyphs;
854 struct hb_aat_apply_context_t :
855 hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
857 const char *get_name () { return "APPLY"; }
858 template <typename T>
859 return_t dispatch (const T &obj) { return obj.apply (this); }
860 static return_t default_return_value () { return false; }
861 bool stop_sublookup_iteration (return_t r) const { return r; }
863 const hb_ot_shape_plan_t *plan;
867 hb_sanitize_context_t sanitizer;
868 const ankr *ankr_table;
869 const OT::GDEF *gdef_table;
871 /* Unused. For debug tracing only. */
872 unsigned int lookup_index;
874 HB_INTERNAL hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
876 hb_buffer_t *buffer_,
877 hb_blob_t *blob = const_cast<hb_blob_t *> (&Null (hb_blob_t)));
879 HB_INTERNAL ~hb_aat_apply_context_t ();
881 HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_);
883 void set_lookup_index (unsigned int i) { lookup_index = i; }
887 } /* namespace AAT */
890 #endif /* HB_AAT_LAYOUT_COMMON_HH */