blob: 22c84255ba1161ec31212bd2a65d95dae0ec33c8 [file] [log] [blame]
Behdad Esfahboda0175e72017-08-17 16:55:54 -07001/*
2 * Copyright © 2017 Google, Inc.
3 *
4 * This is part of HarfBuzz, a text shaping library.
5 *
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.
11 *
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
16 * DAMAGE.
17 *
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.
23 *
24 * Google Author(s): Behdad Esfahbod
25 */
26
Behdad Esfahbodc77ae402018-08-25 22:36:36 -070027#ifndef HB_AAT_LAYOUT_COMMON_HH
28#define HB_AAT_LAYOUT_COMMON_HH
Behdad Esfahboda0175e72017-08-17 16:55:54 -070029
Behdad Esfahbodc77ae402018-08-25 22:36:36 -070030#include "hb-aat-layout.hh"
Behdad Esfahboda0175e72017-08-17 16:55:54 -070031
32
33namespace AAT {
34
35using namespace OT;
36
37
38/*
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +010039 * Lookup Table
40 */
41
42template <typename T> struct Lookup;
43
44template <typename T>
45struct LookupFormat0
46{
47 friend struct Lookup<T>;
48
49 private:
Behdad Esfahbod748b9892018-01-09 17:55:17 +010050 inline const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +010051 {
Behdad Esfahbod748b9892018-01-09 17:55:17 +010052 if (unlikely (glyph_id >= num_glyphs)) return nullptr;
53 return &arrayZ[glyph_id];
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +010054 }
55
56 inline bool sanitize (hb_sanitize_context_t *c) const
57 {
58 TRACE_SANITIZE (this);
Behdad Esfahbodbe707382018-07-17 18:45:25 +020059 return_trace (arrayZ.sanitize (c, c->get_num_glyphs ()));
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +010060 }
61
62 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +010063 HBUINT16 format; /* Format identifier--format = 0 */
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +010064 UnsizedArrayOf<T>
65 arrayZ; /* Array of lookup values, indexed by glyph index. */
66 public:
67 DEFINE_SIZE_ARRAY (2, arrayZ);
68};
69
70
71template <typename T>
72struct LookupSegmentSingle
73{
74 inline int cmp (hb_codepoint_t g) const {
75 return g < first ? -1 : g <= last ? 0 : +1 ;
76 }
77
78 inline bool sanitize (hb_sanitize_context_t *c) const
79 {
80 TRACE_SANITIZE (this);
81 return_trace (c->check_struct (this) && value.sanitize (c));
82 }
83
84 GlyphID last; /* Last GlyphID in this segment */
85 GlyphID first; /* First GlyphID in this segment */
86 T value; /* The lookup value (only one) */
87 public:
Behdad Esfahbodca42d962018-01-11 09:15:34 +010088 DEFINE_SIZE_STATIC (4 + T::static_size);
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +010089};
90
91template <typename T>
92struct LookupFormat2
93{
94 friend struct Lookup<T>;
95
96 private:
Behdad Esfahbod748b9892018-01-09 17:55:17 +010097 inline const T* get_value (hb_codepoint_t glyph_id) const
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +010098 {
99 const LookupSegmentSingle<T> *v = segments.bsearch (glyph_id);
Behdad Esfahbod748b9892018-01-09 17:55:17 +0100100 return v ? &v->value : nullptr;
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100101 }
102
103 inline bool sanitize (hb_sanitize_context_t *c) const
104 {
105 TRACE_SANITIZE (this);
106 return_trace (segments.sanitize (c));
107 }
108
109 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100110 HBUINT16 format; /* Format identifier--format = 2 */
Behdad Esfahbod3515c8b2018-10-07 22:27:00 -0400111 VarSizedBinSearchArrayOf<LookupSegmentSingle<T> >
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100112 segments; /* The actual segments. These must already be sorted,
113 * according to the first word in each one (the last
114 * glyph in each segment). */
115 public:
116 DEFINE_SIZE_ARRAY (8, segments);
117};
118
119template <typename T>
120struct LookupSegmentArray
121{
Behdad Esfahbod748b9892018-01-09 17:55:17 +0100122 inline const T* get_value (hb_codepoint_t glyph_id, const void *base) const
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100123 {
Behdad Esfahbod748b9892018-01-09 17:55:17 +0100124 return first <= glyph_id && glyph_id <= last ? &(base+valuesZ)[glyph_id - first] : nullptr;
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100125 }
126
127 inline int cmp (hb_codepoint_t g) const {
128 return g < first ? -1 : g <= last ? 0 : +1 ;
129 }
130
131 inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
132 {
133 TRACE_SANITIZE (this);
134 return_trace (c->check_struct (this) &&
135 first <= last &&
136 valuesZ.sanitize (c, base, last - first + 1));
137 }
138
139 GlyphID last; /* Last GlyphID in this segment */
140 GlyphID first; /* First GlyphID in this segment */
Behdad Esfahbod10642b32018-09-15 19:43:33 +0200141 OffsetTo<UnsizedArrayOf<T>, HBUINT16, false>
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100142 valuesZ; /* A 16-bit offset from the start of
143 * the table to the data. */
144 public:
145 DEFINE_SIZE_STATIC (6);
146};
147
148template <typename T>
149struct LookupFormat4
150{
151 friend struct Lookup<T>;
152
153 private:
Behdad Esfahbod748b9892018-01-09 17:55:17 +0100154 inline const T* get_value (hb_codepoint_t glyph_id) const
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100155 {
156 const LookupSegmentArray<T> *v = segments.bsearch (glyph_id);
Behdad Esfahbod748b9892018-01-09 17:55:17 +0100157 return v ? v->get_value (glyph_id, this) : nullptr;
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100158 }
159
160 inline bool sanitize (hb_sanitize_context_t *c) const
161 {
162 TRACE_SANITIZE (this);
163 return_trace (segments.sanitize (c, this));
164 }
165
166 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100167 HBUINT16 format; /* Format identifier--format = 2 */
Behdad Esfahbod3515c8b2018-10-07 22:27:00 -0400168 VarSizedBinSearchArrayOf<LookupSegmentArray<T> >
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100169 segments; /* The actual segments. These must already be sorted,
170 * according to the first word in each one (the last
171 * glyph in each segment). */
172 public:
173 DEFINE_SIZE_ARRAY (8, segments);
174};
175
176template <typename T>
177struct LookupSingle
178{
179 inline int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
180
181 inline bool sanitize (hb_sanitize_context_t *c) const
182 {
183 TRACE_SANITIZE (this);
184 return_trace (c->check_struct (this) && value.sanitize (c));
185 }
186
187 GlyphID glyph; /* Last GlyphID */
188 T value; /* The lookup value (only one) */
189 public:
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100190 DEFINE_SIZE_STATIC (4 + T::static_size);
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100191};
192
193template <typename T>
194struct LookupFormat6
195{
196 friend struct Lookup<T>;
197
198 private:
Behdad Esfahbod748b9892018-01-09 17:55:17 +0100199 inline const T* get_value (hb_codepoint_t glyph_id) const
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100200 {
201 const LookupSingle<T> *v = entries.bsearch (glyph_id);
Behdad Esfahbod748b9892018-01-09 17:55:17 +0100202 return v ? &v->value : nullptr;
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100203 }
204
205 inline bool sanitize (hb_sanitize_context_t *c) const
206 {
207 TRACE_SANITIZE (this);
208 return_trace (entries.sanitize (c));
209 }
210
211 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100212 HBUINT16 format; /* Format identifier--format = 6 */
Behdad Esfahbod3515c8b2018-10-07 22:27:00 -0400213 VarSizedBinSearchArrayOf<LookupSingle<T> >
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100214 entries; /* The actual entries, sorted by glyph index. */
215 public:
216 DEFINE_SIZE_ARRAY (8, entries);
217};
218
219template <typename T>
220struct LookupFormat8
221{
222 friend struct Lookup<T>;
223
224 private:
Behdad Esfahbod748b9892018-01-09 17:55:17 +0100225 inline const T* get_value (hb_codepoint_t glyph_id) const
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100226 {
Behdad Esfahbod748b9892018-01-09 17:55:17 +0100227 return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ? &valueArrayZ[glyph_id - firstGlyph] : nullptr;
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100228 }
229
230 inline bool sanitize (hb_sanitize_context_t *c) const
231 {
232 TRACE_SANITIZE (this);
233 return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount));
234 }
235
236 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100237 HBUINT16 format; /* Format identifier--format = 6 */
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100238 GlyphID firstGlyph; /* First glyph index included in the trimmed array. */
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100239 HBUINT16 glyphCount; /* Total number of glyphs (equivalent to the last
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100240 * glyph minus the value of firstGlyph plus 1). */
241 UnsizedArrayOf<T>
242 valueArrayZ; /* The lookup values (indexed by the glyph index
243 * minus the value of firstGlyph). */
244 public:
245 DEFINE_SIZE_ARRAY (6, valueArrayZ);
246};
247
248template <typename T>
249struct Lookup
250{
Behdad Esfahbod748b9892018-01-09 17:55:17 +0100251 inline const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100252 {
253 switch (u.format) {
254 case 0: return u.format0.get_value (glyph_id, num_glyphs);
255 case 2: return u.format2.get_value (glyph_id);
256 case 4: return u.format4.get_value (glyph_id);
257 case 6: return u.format6.get_value (glyph_id);
258 case 8: return u.format8.get_value (glyph_id);
Behdad Esfahbod748b9892018-01-09 17:55:17 +0100259 default:return nullptr;
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100260 }
261 }
262
263 inline bool sanitize (hb_sanitize_context_t *c) const
264 {
265 TRACE_SANITIZE (this);
266 if (!u.format.sanitize (c)) return_trace (false);
267 switch (u.format) {
268 case 0: return_trace (u.format0.sanitize (c));
269 case 2: return_trace (u.format2.sanitize (c));
270 case 4: return_trace (u.format4.sanitize (c));
271 case 6: return_trace (u.format6.sanitize (c));
272 case 8: return_trace (u.format8.sanitize (c));
273 default:return_trace (true);
274 }
275 }
276
277 protected:
278 union {
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100279 HBUINT16 format; /* Format identifier */
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100280 LookupFormat0<T> format0;
281 LookupFormat2<T> format2;
282 LookupFormat4<T> format4;
283 LookupFormat6<T> format6;
284 LookupFormat8<T> format8;
285 } u;
286 public:
287 DEFINE_SIZE_UNION (2, format);
288};
289
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100290
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100291/*
Behdad Esfahbod1f1c85a2018-01-11 22:43:57 +0100292 * Extended State Table
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100293 */
294
295template <typename T>
296struct Entry
297{
298 inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
299 {
300 TRACE_SANITIZE (this);
Behdad Esfahbod17f01af2018-01-11 18:54:49 +0100301 /* Note, we don't recurse-sanitize data because we don't access it.
302 * That said, in our DEFINE_SIZE_STATIC we access T::static_size,
303 * which ensures that data has a simple sanitize(). To be determined
304 * if I need to remove that as well. */
305 return_trace (c->check_struct (this));
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100306 }
307
308 public:
Behdad Esfahbod17f01af2018-01-11 18:54:49 +0100309 HBUINT16 newState; /* Byte offset from beginning of state table
310 * to the new state. Really?!?! Or just state
311 * number? The latter in morx for sure. */
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100312 HBUINT16 flags; /* Table specific. */
313 T data; /* Optional offsets to per-glyph tables. */
314 public:
315 DEFINE_SIZE_STATIC (4 + T::static_size);
316};
317
318template <>
319struct Entry<void>
320{
321 inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
322 {
323 TRACE_SANITIZE (this);
324 return_trace (c->check_struct (this));
325 }
326
327 public:
328 HBUINT16 newState; /* Byte offset from beginning of state table to the new state. */
329 HBUINT16 flags; /* Table specific. */
330 public:
331 DEFINE_SIZE_STATIC (4);
332};
333
Behdad Esfahbod1f1c85a2018-01-11 22:43:57 +0100334template <typename Extra>
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100335struct StateTable
336{
Behdad Esfahbod4653e6c2018-09-14 11:31:33 +0200337 enum State
338 {
339 STATE_START_OF_TEXT = 0,
340 STATE_START_OF_LINE = 1,
341 };
342 enum Class
343 {
344 CLASS_END_OF_TEXT = 0,
345 CLASS_OUT_OF_BOUNDS = 1,
346 CLASS_DELETED_GLYPH = 2,
347 CLASS_END_OF_LINE = 3,
348 };
349
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100350 inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
Behdad Esfahbod1f1c85a2018-01-11 22:43:57 +0100351 {
352 const HBUINT16 *v = (this+classTable).get_value (glyph_id, num_glyphs);
Behdad Esfahbod957dbed2018-09-14 12:14:42 +0200353 return v ? (unsigned) *v : (unsigned) CLASS_OUT_OF_BOUNDS;
Behdad Esfahbod1f1c85a2018-01-11 22:43:57 +0100354 }
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100355
Behdad Esfahbod17f01af2018-01-11 18:54:49 +0100356 inline const Entry<Extra> *get_entries () const
357 {
358 return (this+entryTable).arrayZ;
359 }
360
361 inline const Entry<Extra> *get_entryZ (unsigned int state, unsigned int klass) const
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100362 {
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100363 if (unlikely (klass >= nClasses)) return nullptr;
364
Behdad Esfahbod1f1c85a2018-01-11 22:43:57 +0100365 const HBUINT16 *states = (this+stateArrayTable).arrayZ;
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100366 const Entry<Extra> *entries = (this+entryTable).arrayZ;
367
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100368 unsigned int entry = states[state * nClasses + klass];
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100369
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100370 return &entries[entry];
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100371 }
372
Behdad Esfahbod17f01af2018-01-11 18:54:49 +0100373 inline bool sanitize (hb_sanitize_context_t *c,
374 unsigned int *num_entries_out = nullptr) const
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100375 {
376 TRACE_SANITIZE (this);
Behdad Esfahbod12fffce2018-01-15 15:41:51 -0500377 if (unlikely (!(c->check_struct (this) &&
378 classTable.sanitize (c, this)))) return_trace (false);
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100379
Behdad Esfahbod1f1c85a2018-01-11 22:43:57 +0100380 const HBUINT16 *states = (this+stateArrayTable).arrayZ;
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100381 const Entry<Extra> *entries = (this+entryTable).arrayZ;
382
383 unsigned int num_states = 1;
384 unsigned int num_entries = 0;
385
386 unsigned int state = 0;
387 unsigned int entry = 0;
388 while (state < num_states)
389 {
Behdad Esfahbod5021ba22018-02-08 15:11:28 -0600390 if (unlikely (!c->check_array (states,
Behdad Esfahbod9507b052018-09-10 23:18:07 +0200391 num_states,
392 states[0].static_size * nClasses)))
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100393 return_trace (false);
394 { /* Sweep new states. */
Behdad Esfahbod1f1c85a2018-01-11 22:43:57 +0100395 const HBUINT16 *stop = &states[num_states * nClasses];
396 for (const HBUINT16 *p = &states[state * nClasses]; p < stop; p++)
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100397 num_entries = MAX<unsigned int> (num_entries, *p + 1);
398 state = num_states;
399 }
400
Behdad Esfahbod9507b052018-09-10 23:18:07 +0200401 if (unlikely (!c->check_array (entries, num_entries)))
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100402 return_trace (false);
403 { /* Sweep new entries. */
404 const Entry<Extra> *stop = &entries[num_entries];
405 for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
406 num_states = MAX<unsigned int> (num_states, p->newState + 1);
407 entry = num_entries;
408 }
409 }
410
Behdad Esfahbod17f01af2018-01-11 18:54:49 +0100411 if (num_entries_out)
412 *num_entries_out = num_entries;
413
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100414 return_trace (true);
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100415 }
416
417 protected:
Behdad Esfahbod1f1c85a2018-01-11 22:43:57 +0100418 HBUINT32 nClasses; /* Number of classes, which is the number of indices
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100419 * in a single line in the state array. */
Behdad Esfahbod10642b32018-09-15 19:43:33 +0200420 LOffsetTo<Lookup<HBUINT16>, false>
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100421 classTable; /* Offset to the class table. */
Behdad Esfahbod10642b32018-09-15 19:43:33 +0200422 LOffsetTo<UnsizedArrayOf<HBUINT16>, false>
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100423 stateArrayTable;/* Offset to the state array. */
Behdad Esfahbod10642b32018-09-15 19:43:33 +0200424 LOffsetTo<UnsizedArrayOf<Entry<Extra> >, false>
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100425 entryTable; /* Offset to the entry array. */
426
427 public:
Behdad Esfahbod9009b342018-01-12 12:04:53 +0100428 DEFINE_SIZE_STATIC (16);
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100429};
430
Behdad Esfahbod117cfe72018-01-12 00:01:36 +0100431template <typename EntryData>
432struct StateTableDriver
433{
434 inline StateTableDriver (const StateTable<EntryData> &machine_,
435 hb_buffer_t *buffer_,
436 hb_face_t *face_) :
437 machine (machine_),
438 buffer (buffer_),
Behdad Esfahbod54e6efa2018-02-04 14:58:02 -0500439 num_glyphs (face_->get_num_glyphs ()) {}
Behdad Esfahbod117cfe72018-01-12 00:01:36 +0100440
441 template <typename context_t>
442 inline void drive (context_t *c)
443 {
Behdad Esfahbode6f283e2018-01-19 18:08:56 -0800444 if (!c->in_place)
445 buffer->clear_output ();
446
Behdad Esfahbod4653e6c2018-09-14 11:31:33 +0200447 unsigned int state = StateTable<EntryData>::STATE_START_OF_TEXT;
Behdad Esfahbodf7600222018-01-12 11:09:21 +0100448 bool last_was_dont_advance = false;
Behdad Esfahbode6f283e2018-01-19 18:08:56 -0800449 for (buffer->idx = 0;;)
Behdad Esfahbod117cfe72018-01-12 00:01:36 +0100450 {
Behdad Esfahbode6f283e2018-01-19 18:08:56 -0800451 unsigned int klass = buffer->idx < buffer->len ?
Behdad Esfahbod4831e612018-10-05 18:14:13 +0200452 machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) :
Behdad Esfahbod4653e6c2018-09-14 11:31:33 +0200453 (unsigned) StateTable<EntryData>::CLASS_END_OF_TEXT;
Behdad Esfahbod117cfe72018-01-12 00:01:36 +0100454 const Entry<EntryData> *entry = machine.get_entryZ (state, klass);
455 if (unlikely (!entry))
456 break;
457
Behdad Esfahbod54e6efa2018-02-04 14:58:02 -0500458 /* Unsafe-to-break before this if not in state 0, as things might
Behdad Esfahbod7ee50af2018-10-06 21:31:44 +0200459 * go differently if we start from state 0 here.
460 *
461 * Ugh. The indexing here is ugly... */
462 if (state && buffer->backtrack_len () && buffer->idx < buffer->len)
Behdad Esfahbod54e6efa2018-02-04 14:58:02 -0500463 {
Behdad Esfahbod2971e9d2018-02-06 11:48:04 -0500464 /* If there's no action and we're just epsilon-transitioning to state 0,
465 * safe to break. */
466 if (c->is_actionable (this, entry) ||
Behdad Esfahbod0739b282018-09-19 17:32:21 -0400467 !(entry->newState == StateTable<EntryData>::STATE_START_OF_TEXT &&
468 entry->flags == context_t::DontAdvance))
Behdad Esfahbod7ee50af2018-10-06 21:31:44 +0200469 buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
Behdad Esfahbod54e6efa2018-02-04 14:58:02 -0500470 }
471
472 /* Unsafe-to-break if end-of-text would kick in here. */
473 if (buffer->idx + 2 <= buffer->len)
474 {
475 const Entry<EntryData> *end_entry = machine.get_entryZ (state, 0);
476 if (c->is_actionable (this, end_entry))
477 buffer->unsafe_to_break (buffer->idx, buffer->idx + 2);
478 }
479
Behdad Esfahbode6f283e2018-01-19 18:08:56 -0800480 if (unlikely (!c->transition (this, entry)))
481 break;
Behdad Esfahbodf7600222018-01-12 11:09:21 +0100482
Behdad Esfahbod98ac01d2018-10-01 12:10:00 +0200483 if (unlikely (!buffer->successful)) return;
484
Behdad Esfahbod7033fe52018-02-18 17:12:04 -0800485 last_was_dont_advance = (entry->flags & context_t::DontAdvance) && buffer->max_ops-- > 0;
Behdad Esfahbod117cfe72018-01-12 00:01:36 +0100486
Behdad Esfahbode6f283e2018-01-19 18:08:56 -0800487 state = entry->newState;
488
489 if (buffer->idx == buffer->len)
490 break;
491
Behdad Esfahbod57051b42018-01-12 11:42:25 +0100492 if (!last_was_dont_advance)
493 buffer->next_glyph ();
Behdad Esfahbod117cfe72018-01-12 00:01:36 +0100494 }
495
Behdad Esfahbod57051b42018-01-12 11:42:25 +0100496 if (!c->in_place)
497 {
Behdad Esfahbode6f283e2018-01-19 18:08:56 -0800498 for (; buffer->idx < buffer->len;)
Behdad Esfahbod57051b42018-01-12 11:42:25 +0100499 buffer->next_glyph ();
Behdad Esfahbode6f283e2018-01-19 18:08:56 -0800500 buffer->swap_buffers ();
Behdad Esfahbod57051b42018-01-12 11:42:25 +0100501 }
Behdad Esfahbod117cfe72018-01-12 00:01:36 +0100502 }
503
504 public:
505 const StateTable<EntryData> &machine;
506 hb_buffer_t *buffer;
Behdad Esfahbod117cfe72018-01-12 00:01:36 +0100507 unsigned int num_glyphs;
Behdad Esfahbod117cfe72018-01-12 00:01:36 +0100508};
509
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100510
Behdad Esfahbod046690a2018-01-17 16:59:55 -0800511
512struct hb_aat_apply_context_t :
513 hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
514{
515 inline const char *get_name (void) { return "APPLY"; }
516 template <typename T>
517 inline return_t dispatch (const T &obj) { return obj.apply (this); }
518 static return_t default_return_value (void) { return false; }
519 bool stop_sublookup_iteration (return_t r) const { return r; }
520
Behdad Esfahbod53e55942018-10-09 22:35:22 -0400521 hb_ot_shape_plan_t *plan;
Behdad Esfahbod046690a2018-01-17 16:59:55 -0800522 hb_font_t *font;
523 hb_face_t *face;
524 hb_buffer_t *buffer;
Behdad Esfahbodf07ce662018-01-19 16:52:01 -0800525 hb_sanitize_context_t sanitizer;
Behdad Esfahbod046690a2018-01-17 16:59:55 -0800526
Behdad Esfahbod126ffdb2018-02-07 12:26:41 -0500527 /* Unused. For debug tracing only. */
528 unsigned int lookup_index;
529 unsigned int debug_depth;
530
Behdad Esfahbod53e55942018-10-09 22:35:22 -0400531 inline hb_aat_apply_context_t (hb_ot_shape_plan_t *plan_,
532 hb_font_t *font_,
Behdad Esfahbodf07ce662018-01-19 16:52:01 -0800533 hb_buffer_t *buffer_,
534 hb_blob_t *table) :
Behdad Esfahbod53e55942018-10-09 22:35:22 -0400535 plan (plan_), font (font_), face (font->face), buffer (buffer_),
Behdad Esfahbod126ffdb2018-02-07 12:26:41 -0500536 sanitizer (), lookup_index (0), debug_depth (0)
Behdad Esfahbodf07ce662018-01-19 16:52:01 -0800537 {
538 sanitizer.init (table);
Behdad Esfahbodbe707382018-07-17 18:45:25 +0200539 sanitizer.set_num_glyphs (face->get_num_glyphs ());
Behdad Esfahbodf07ce662018-01-19 16:52:01 -0800540 sanitizer.start_processing ();
541 }
542
Behdad Esfahbodee433d32018-02-07 12:30:18 -0500543 inline void set_lookup_index (unsigned int i) { lookup_index = i; }
544
Behdad Esfahbodf07ce662018-01-19 16:52:01 -0800545 inline ~hb_aat_apply_context_t (void)
546 {
547 sanitizer.end_processing ();
548 }
Behdad Esfahbod046690a2018-01-17 16:59:55 -0800549};
550
551
Behdad Esfahboda0175e72017-08-17 16:55:54 -0700552} /* namespace AAT */
553
554
Behdad Esfahbodc77ae402018-08-25 22:36:36 -0700555#endif /* HB_AAT_LAYOUT_COMMON_HH */