blob: 89ed91f28a737445f1a99e643743b2ac388bc722 [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 Esfahbod2c824d32018-10-11 16:41:01 -0400167 HBUINT16 format; /* Format identifier--format = 4 */
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 Esfahbod2c824d32018-10-11 16:41:01 -0400190 DEFINE_SIZE_STATIC (2 + 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 Esfahbod44af1f92018-10-14 14:52:17 -0700227 return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ?
228 &valueArrayZ[glyph_id - firstGlyph] : nullptr;
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100229 }
230
231 inline bool sanitize (hb_sanitize_context_t *c) const
232 {
233 TRACE_SANITIZE (this);
234 return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount));
235 }
236
237 protected:
Behdad Esfahbod44af1f92018-10-14 14:52:17 -0700238 HBUINT16 format; /* Format identifier--format = 8 */
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100239 GlyphID firstGlyph; /* First glyph index included in the trimmed array. */
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100240 HBUINT16 glyphCount; /* Total number of glyphs (equivalent to the last
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100241 * glyph minus the value of firstGlyph plus 1). */
242 UnsizedArrayOf<T>
243 valueArrayZ; /* The lookup values (indexed by the glyph index
244 * minus the value of firstGlyph). */
245 public:
246 DEFINE_SIZE_ARRAY (6, valueArrayZ);
247};
248
249template <typename T>
250struct Lookup
251{
Behdad Esfahbod748b9892018-01-09 17:55:17 +0100252 inline const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100253 {
254 switch (u.format) {
255 case 0: return u.format0.get_value (glyph_id, num_glyphs);
256 case 2: return u.format2.get_value (glyph_id);
257 case 4: return u.format4.get_value (glyph_id);
258 case 6: return u.format6.get_value (glyph_id);
259 case 8: return u.format8.get_value (glyph_id);
Behdad Esfahbod748b9892018-01-09 17:55:17 +0100260 default:return nullptr;
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100261 }
262 }
263
Behdad Esfahbod7727e732018-10-10 13:24:51 -0400264 inline const T& get_value_or_null (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
265 {
266 const T *v = get_value (glyph_id, num_glyphs);
267 return v ? *v : Null(T);
268 }
269
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100270 inline bool sanitize (hb_sanitize_context_t *c) const
271 {
272 TRACE_SANITIZE (this);
273 if (!u.format.sanitize (c)) return_trace (false);
274 switch (u.format) {
275 case 0: return_trace (u.format0.sanitize (c));
276 case 2: return_trace (u.format2.sanitize (c));
277 case 4: return_trace (u.format4.sanitize (c));
278 case 6: return_trace (u.format6.sanitize (c));
279 case 8: return_trace (u.format8.sanitize (c));
280 default:return_trace (true);
281 }
282 }
283
284 protected:
285 union {
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100286 HBUINT16 format; /* Format identifier */
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100287 LookupFormat0<T> format0;
288 LookupFormat2<T> format2;
289 LookupFormat4<T> format4;
290 LookupFormat6<T> format6;
291 LookupFormat8<T> format8;
292 } u;
293 public:
Behdad Esfahbod9e8a9b82018-10-17 21:41:25 -0700294 DEFINE_SIZE_UNION (2, format);
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100295};
Behdad Esfahbod9e8a9b82018-10-17 21:41:25 -0700296/* Lookup 0 has unbounded size (dependant on num_glyphs). So we need to defined
297 * special NULL objects for Lookup<> objects, but since it's template our macros
298 * don't work. So we have to hand-code them here. UGLY. */
299} /* Close namespace. */
300/* Ugly hand-coded null objects for template Lookup<> :(. */
301extern HB_INTERNAL const unsigned char _hb_Null_AAT_Lookup[2];
302template <>
303/*static*/ inline const AAT::Lookup<OT::HBUINT16>& Null<AAT::Lookup<OT::HBUINT16> > (void) {
304 return *reinterpret_cast<const AAT::Lookup<OT::HBUINT16> *> (_hb_Null_AAT_Lookup);
305}
306template <>
307/*static*/ inline const AAT::Lookup<OT::HBUINT32>& Null<AAT::Lookup<OT::HBUINT32> > (void) {
308 return *reinterpret_cast<const AAT::Lookup<OT::HBUINT32> *> (_hb_Null_AAT_Lookup);
309}
310template <>
Behdad Esfahbod270a37c2018-10-17 22:42:47 -0700311/*static*/ inline const AAT::Lookup<OT::Offset<OT::HBUINT16, false> >& Null<AAT::Lookup<OT::Offset<OT::HBUINT16, false> > > (void) {
312 return *reinterpret_cast<const AAT::Lookup<OT::Offset<OT::HBUINT16, false> > *> (_hb_Null_AAT_Lookup);
Behdad Esfahbod9e8a9b82018-10-17 21:41:25 -0700313}
314namespace AAT {
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100315
Behdad Esfahbod470fe5b2018-01-09 15:48:51 +0100316
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100317/*
Behdad Esfahbod1f1c85a2018-01-11 22:43:57 +0100318 * Extended State Table
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100319 */
320
321template <typename T>
322struct Entry
323{
324 inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
325 {
326 TRACE_SANITIZE (this);
Behdad Esfahbod17f01af2018-01-11 18:54:49 +0100327 /* Note, we don't recurse-sanitize data because we don't access it.
328 * That said, in our DEFINE_SIZE_STATIC we access T::static_size,
329 * which ensures that data has a simple sanitize(). To be determined
330 * if I need to remove that as well. */
331 return_trace (c->check_struct (this));
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100332 }
333
334 public:
Behdad Esfahbod17f01af2018-01-11 18:54:49 +0100335 HBUINT16 newState; /* Byte offset from beginning of state table
336 * to the new state. Really?!?! Or just state
337 * number? The latter in morx for sure. */
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100338 HBUINT16 flags; /* Table specific. */
339 T data; /* Optional offsets to per-glyph tables. */
340 public:
341 DEFINE_SIZE_STATIC (4 + T::static_size);
342};
343
344template <>
345struct Entry<void>
346{
347 inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
348 {
349 TRACE_SANITIZE (this);
350 return_trace (c->check_struct (this));
351 }
352
353 public:
354 HBUINT16 newState; /* Byte offset from beginning of state table to the new state. */
355 HBUINT16 flags; /* Table specific. */
356 public:
357 DEFINE_SIZE_STATIC (4);
358};
359
Behdad Esfahbod1f1c85a2018-01-11 22:43:57 +0100360template <typename Extra>
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100361struct StateTable
362{
Behdad Esfahbod4653e6c2018-09-14 11:31:33 +0200363 enum State
364 {
365 STATE_START_OF_TEXT = 0,
366 STATE_START_OF_LINE = 1,
367 };
368 enum Class
369 {
370 CLASS_END_OF_TEXT = 0,
371 CLASS_OUT_OF_BOUNDS = 1,
372 CLASS_DELETED_GLYPH = 2,
373 CLASS_END_OF_LINE = 3,
374 };
375
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100376 inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
Behdad Esfahbod1f1c85a2018-01-11 22:43:57 +0100377 {
378 const HBUINT16 *v = (this+classTable).get_value (glyph_id, num_glyphs);
Behdad Esfahbod957dbed2018-09-14 12:14:42 +0200379 return v ? (unsigned) *v : (unsigned) CLASS_OUT_OF_BOUNDS;
Behdad Esfahbod1f1c85a2018-01-11 22:43:57 +0100380 }
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100381
Behdad Esfahbod17f01af2018-01-11 18:54:49 +0100382 inline const Entry<Extra> *get_entries () const
383 {
384 return (this+entryTable).arrayZ;
385 }
386
387 inline const Entry<Extra> *get_entryZ (unsigned int state, unsigned int klass) const
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100388 {
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100389 if (unlikely (klass >= nClasses)) return nullptr;
390
Behdad Esfahbod1f1c85a2018-01-11 22:43:57 +0100391 const HBUINT16 *states = (this+stateArrayTable).arrayZ;
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100392 const Entry<Extra> *entries = (this+entryTable).arrayZ;
393
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100394 unsigned int entry = states[state * nClasses + klass];
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100395
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100396 return &entries[entry];
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100397 }
398
Behdad Esfahbod17f01af2018-01-11 18:54:49 +0100399 inline bool sanitize (hb_sanitize_context_t *c,
400 unsigned int *num_entries_out = nullptr) const
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100401 {
402 TRACE_SANITIZE (this);
Behdad Esfahbod12fffce2018-01-15 15:41:51 -0500403 if (unlikely (!(c->check_struct (this) &&
404 classTable.sanitize (c, this)))) return_trace (false);
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100405
Behdad Esfahbod1f1c85a2018-01-11 22:43:57 +0100406 const HBUINT16 *states = (this+stateArrayTable).arrayZ;
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100407 const Entry<Extra> *entries = (this+entryTable).arrayZ;
408
Behdad Esfahbode9405302018-10-11 15:56:17 -0400409 unsigned int num_classes = nClasses;
410
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100411 unsigned int num_states = 1;
412 unsigned int num_entries = 0;
413
414 unsigned int state = 0;
415 unsigned int entry = 0;
416 while (state < num_states)
417 {
Behdad Esfahbode9405302018-10-11 15:56:17 -0400418 if (unlikely (hb_unsigned_mul_overflows (num_classes, states[0].static_size)))
419 return_trace (false);
420
Behdad Esfahbod5021ba22018-02-08 15:11:28 -0600421 if (unlikely (!c->check_array (states,
Behdad Esfahbod9507b052018-09-10 23:18:07 +0200422 num_states,
Behdad Esfahbode9405302018-10-11 15:56:17 -0400423 num_classes * states[0].static_size)))
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100424 return_trace (false);
Behdad Esfahbod83780302018-10-17 22:34:16 -0700425 if ((c->max_ops -= num_states - state) < 0)
426 return_trace (false);
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100427 { /* Sweep new states. */
Behdad Esfahbode9405302018-10-11 15:56:17 -0400428 const HBUINT16 *stop = &states[num_states * num_classes];
429 for (const HBUINT16 *p = &states[state * num_classes]; p < stop; p++)
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100430 num_entries = MAX<unsigned int> (num_entries, *p + 1);
431 state = num_states;
432 }
433
Behdad Esfahbod9507b052018-09-10 23:18:07 +0200434 if (unlikely (!c->check_array (entries, num_entries)))
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100435 return_trace (false);
Behdad Esfahbod83780302018-10-17 22:34:16 -0700436 if ((c->max_ops -= num_entries - entry) < 0)
437 return_trace (false);
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100438 { /* Sweep new entries. */
439 const Entry<Extra> *stop = &entries[num_entries];
440 for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
441 num_states = MAX<unsigned int> (num_states, p->newState + 1);
442 entry = num_entries;
443 }
444 }
445
Behdad Esfahbod17f01af2018-01-11 18:54:49 +0100446 if (num_entries_out)
447 *num_entries_out = num_entries;
448
Behdad Esfahbod680cbc22018-01-11 18:15:53 +0100449 return_trace (true);
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100450 }
451
452 protected:
Behdad Esfahbod1f1c85a2018-01-11 22:43:57 +0100453 HBUINT32 nClasses; /* Number of classes, which is the number of indices
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100454 * in a single line in the state array. */
Behdad Esfahbod10642b32018-09-15 19:43:33 +0200455 LOffsetTo<Lookup<HBUINT16>, false>
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100456 classTable; /* Offset to the class table. */
Behdad Esfahbod10642b32018-09-15 19:43:33 +0200457 LOffsetTo<UnsizedArrayOf<HBUINT16>, false>
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100458 stateArrayTable;/* Offset to the state array. */
Behdad Esfahbod10642b32018-09-15 19:43:33 +0200459 LOffsetTo<UnsizedArrayOf<Entry<Extra> >, false>
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100460 entryTable; /* Offset to the entry array. */
461
462 public:
Behdad Esfahbod9009b342018-01-12 12:04:53 +0100463 DEFINE_SIZE_STATIC (16);
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100464};
465
Behdad Esfahbod117cfe72018-01-12 00:01:36 +0100466template <typename EntryData>
467struct StateTableDriver
468{
469 inline StateTableDriver (const StateTable<EntryData> &machine_,
470 hb_buffer_t *buffer_,
471 hb_face_t *face_) :
472 machine (machine_),
473 buffer (buffer_),
Behdad Esfahbod54e6efa2018-02-04 14:58:02 -0500474 num_glyphs (face_->get_num_glyphs ()) {}
Behdad Esfahbod117cfe72018-01-12 00:01:36 +0100475
476 template <typename context_t>
477 inline void drive (context_t *c)
478 {
Behdad Esfahbode6f283e2018-01-19 18:08:56 -0800479 if (!c->in_place)
480 buffer->clear_output ();
481
Behdad Esfahbod4653e6c2018-09-14 11:31:33 +0200482 unsigned int state = StateTable<EntryData>::STATE_START_OF_TEXT;
Behdad Esfahbodf7600222018-01-12 11:09:21 +0100483 bool last_was_dont_advance = false;
Behdad Esfahbode6f283e2018-01-19 18:08:56 -0800484 for (buffer->idx = 0;;)
Behdad Esfahbod117cfe72018-01-12 00:01:36 +0100485 {
Behdad Esfahbode6f283e2018-01-19 18:08:56 -0800486 unsigned int klass = buffer->idx < buffer->len ?
Behdad Esfahbod4831e612018-10-05 18:14:13 +0200487 machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) :
Behdad Esfahbod4653e6c2018-09-14 11:31:33 +0200488 (unsigned) StateTable<EntryData>::CLASS_END_OF_TEXT;
Behdad Esfahbod117cfe72018-01-12 00:01:36 +0100489 const Entry<EntryData> *entry = machine.get_entryZ (state, klass);
490 if (unlikely (!entry))
491 break;
492
Behdad Esfahbod54e6efa2018-02-04 14:58:02 -0500493 /* Unsafe-to-break before this if not in state 0, as things might
Behdad Esfahbod7ee50af2018-10-06 21:31:44 +0200494 * go differently if we start from state 0 here.
495 *
496 * Ugh. The indexing here is ugly... */
497 if (state && buffer->backtrack_len () && buffer->idx < buffer->len)
Behdad Esfahbod54e6efa2018-02-04 14:58:02 -0500498 {
Behdad Esfahbod2971e9d2018-02-06 11:48:04 -0500499 /* If there's no action and we're just epsilon-transitioning to state 0,
500 * safe to break. */
501 if (c->is_actionable (this, entry) ||
Behdad Esfahbod0739b282018-09-19 17:32:21 -0400502 !(entry->newState == StateTable<EntryData>::STATE_START_OF_TEXT &&
503 entry->flags == context_t::DontAdvance))
Behdad Esfahbod7ee50af2018-10-06 21:31:44 +0200504 buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
Behdad Esfahbod54e6efa2018-02-04 14:58:02 -0500505 }
506
507 /* Unsafe-to-break if end-of-text would kick in here. */
508 if (buffer->idx + 2 <= buffer->len)
509 {
510 const Entry<EntryData> *end_entry = machine.get_entryZ (state, 0);
511 if (c->is_actionable (this, end_entry))
512 buffer->unsafe_to_break (buffer->idx, buffer->idx + 2);
513 }
514
Behdad Esfahbode6f283e2018-01-19 18:08:56 -0800515 if (unlikely (!c->transition (this, entry)))
516 break;
Behdad Esfahbodf7600222018-01-12 11:09:21 +0100517
Behdad Esfahbod98ac01d2018-10-01 12:10:00 +0200518 if (unlikely (!buffer->successful)) return;
519
Behdad Esfahbod7033fe52018-02-18 17:12:04 -0800520 last_was_dont_advance = (entry->flags & context_t::DontAdvance) && buffer->max_ops-- > 0;
Behdad Esfahbod117cfe72018-01-12 00:01:36 +0100521
Behdad Esfahbode6f283e2018-01-19 18:08:56 -0800522 state = entry->newState;
523
524 if (buffer->idx == buffer->len)
525 break;
526
Behdad Esfahbod57051b42018-01-12 11:42:25 +0100527 if (!last_was_dont_advance)
528 buffer->next_glyph ();
Behdad Esfahbod117cfe72018-01-12 00:01:36 +0100529 }
530
Behdad Esfahbod57051b42018-01-12 11:42:25 +0100531 if (!c->in_place)
532 {
Behdad Esfahbod7efa3822018-10-14 19:30:44 -0700533 for (; buffer->successful && buffer->idx < buffer->len;)
534 buffer->next_glyph ();
535 if (likely (buffer->successful))
536 buffer->swap_buffers ();
Behdad Esfahbod57051b42018-01-12 11:42:25 +0100537 }
Behdad Esfahbod117cfe72018-01-12 00:01:36 +0100538 }
539
540 public:
541 const StateTable<EntryData> &machine;
542 hb_buffer_t *buffer;
Behdad Esfahbod117cfe72018-01-12 00:01:36 +0100543 unsigned int num_glyphs;
Behdad Esfahbod117cfe72018-01-12 00:01:36 +0100544};
545
Behdad Esfahbodca42d962018-01-11 09:15:34 +0100546
Behdad Esfahbod7bb4da72018-10-11 00:52:07 -0400547struct ankr;
Behdad Esfahbod046690a2018-01-17 16:59:55 -0800548
549struct hb_aat_apply_context_t :
550 hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
551{
552 inline const char *get_name (void) { return "APPLY"; }
553 template <typename T>
554 inline return_t dispatch (const T &obj) { return obj.apply (this); }
555 static return_t default_return_value (void) { return false; }
556 bool stop_sublookup_iteration (return_t r) const { return r; }
557
Behdad Esfahbod53e55942018-10-09 22:35:22 -0400558 hb_ot_shape_plan_t *plan;
Behdad Esfahbod046690a2018-01-17 16:59:55 -0800559 hb_font_t *font;
560 hb_face_t *face;
561 hb_buffer_t *buffer;
Behdad Esfahbodf07ce662018-01-19 16:52:01 -0800562 hb_sanitize_context_t sanitizer;
Behdad Esfahbod7bb4da72018-10-11 00:52:07 -0400563 const ankr &ankr_table;
Behdad Esfahbod1622ba52018-10-11 01:14:18 -0400564 const char *ankr_end;
Behdad Esfahbod046690a2018-01-17 16:59:55 -0800565
Behdad Esfahbod126ffdb2018-02-07 12:26:41 -0500566 /* Unused. For debug tracing only. */
567 unsigned int lookup_index;
568 unsigned int debug_depth;
569
Behdad Esfahbod53e55942018-10-09 22:35:22 -0400570 inline hb_aat_apply_context_t (hb_ot_shape_plan_t *plan_,
571 hb_font_t *font_,
Behdad Esfahbodf07ce662018-01-19 16:52:01 -0800572 hb_buffer_t *buffer_,
Behdad Esfahbodd6a12db2018-10-11 11:10:06 -0400573 hb_blob_t *blob = const_cast<hb_blob_t *> (&Null(hb_blob_t)),
Behdad Esfahbod1622ba52018-10-11 01:14:18 -0400574 const ankr &ankr_table_ = Null(ankr),
575 const char *ankr_end_ = nullptr) :
Behdad Esfahbod53e55942018-10-09 22:35:22 -0400576 plan (plan_), font (font_), face (font->face), buffer (buffer_),
Behdad Esfahbod1622ba52018-10-11 01:14:18 -0400577 sanitizer (),
578 ankr_table (ankr_table_), ankr_end (ankr_end_),
579 lookup_index (0), debug_depth (0)
Behdad Esfahbodf07ce662018-01-19 16:52:01 -0800580 {
Behdad Esfahbodd6a12db2018-10-11 11:10:06 -0400581 sanitizer.init (blob);
Behdad Esfahbodbe707382018-07-17 18:45:25 +0200582 sanitizer.set_num_glyphs (face->get_num_glyphs ());
Behdad Esfahbodf07ce662018-01-19 16:52:01 -0800583 sanitizer.start_processing ();
Behdad Esfahbodd35315c2018-10-09 23:17:32 -0400584 sanitizer.set_max_ops (HB_SANITIZE_MAX_OPS_MAX);
Behdad Esfahbodf07ce662018-01-19 16:52:01 -0800585 }
586
Behdad Esfahbodee433d32018-02-07 12:30:18 -0500587 inline void set_lookup_index (unsigned int i) { lookup_index = i; }
588
Behdad Esfahbodf07ce662018-01-19 16:52:01 -0800589 inline ~hb_aat_apply_context_t (void)
590 {
591 sanitizer.end_processing ();
592 }
Behdad Esfahbod046690a2018-01-17 16:59:55 -0800593};
594
595
Behdad Esfahboda0175e72017-08-17 16:55:54 -0700596} /* namespace AAT */
597
598
Behdad Esfahbodc77ae402018-08-25 22:36:36 -0700599#endif /* HB_AAT_LAYOUT_COMMON_HH */