blob: c9abd516e6557aa4a3d95faf1b4e4bf264f11d1c [file] [log] [blame]
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001/*
Behdad Esfahbod2409d5f2011-04-21 17:14:28 -04002 * Copyright © 2007,2008,2009,2010 Red Hat, Inc.
Behdad Esfahbod5b93e8d2012-04-23 22:26:13 -04003 * Copyright © 2010,2012 Google, Inc.
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04004 *
Behdad Esfahbodc755cb32010-04-22 00:11:43 -04005 * This is part of HarfBuzz, a text shaping library.
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04006 *
7 * Permission is hereby granted, without written agreement and without
8 * license or royalty fees, to use, copy, modify, and distribute this
9 * software and its documentation for any purpose, provided that the
10 * above copyright notice and the following two paragraphs appear in
11 * all copies of this software.
12 *
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17 * DAMAGE.
18 *
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 *
25 * Red Hat Author(s): Behdad Esfahbod
Behdad Esfahbod98370e82010-10-27 17:39:01 -040026 * Google Author(s): Behdad Esfahbod
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -040027 */
28
Behdad Esfahbod5f5b24f2009-08-02 20:03:12 -040029#ifndef HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
30#define HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -040031
Behdad Esfahbod22da7fd2010-05-12 18:23:21 -040032#include "hb-buffer-private.hh"
Behdad Esfahbod7a750ac2011-08-17 14:19:59 +020033#include "hb-ot-layout-gdef-table.hh"
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040034
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -040035
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -040036
Behdad Esfahbodc2709112010-10-27 23:18:51 -040037/* buffer var allocations */
Behdad Esfahboda9844d42012-05-09 17:53:13 +020038#define lig_props() var2.u8[3]
39
40/* unique ligature id */
41/* component number in the ligature (0 = base) */
42static inline void
43set_lig_props (hb_glyph_info_t &info, unsigned int lig_id, unsigned int lig_comp)
44{
45 info.lig_props() = (lig_id << 4) | (lig_comp & 0x0F);
46}
47static inline unsigned int
48get_lig_id (hb_glyph_info_t &info)
49{
50 return info.lig_props() >> 4;
51}
52static inline unsigned int
53get_lig_comp (hb_glyph_info_t &info)
54{
55 return info.lig_props() & 0x0F;
56}
Behdad Esfahbodc2709112010-10-27 23:18:51 -040057
Behdad Esfahbod18c42852011-07-25 00:36:58 -040058static inline uint8_t allocate_lig_id (hb_buffer_t *buffer) {
Behdad Esfahboda9844d42012-05-09 17:53:13 +020059 uint8_t lig_id = buffer->next_serial () & 0x0F;
60 if (unlikely (!lig_id))
61 lig_id = allocate_lig_id (buffer); /* in case of overflow */
Behdad Esfahbodd8787492011-07-25 00:36:01 -040062 return lig_id;
63}
64
65
Behdad Esfahbodc2709112010-10-27 23:18:51 -040066
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040067#ifndef HB_DEBUG_CLOSURE
68#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
69#endif
70
71#define TRACE_CLOSURE() \
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +020072 hb_auto_trace_t<HB_DEBUG_CLOSURE> trace (&c->debug_depth, "CLOSURE", this, HB_FUNC, "");
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040073
74
75
76struct hb_closure_context_t
77{
78 hb_face_t *face;
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -040079 hb_set_t *glyphs;
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040080 unsigned int nesting_level_left;
81 unsigned int debug_depth;
82
83
84 hb_closure_context_t (hb_face_t *face_,
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -040085 hb_set_t *glyphs_,
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040086 unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
87 face (face_), glyphs (glyphs_),
88 nesting_level_left (nesting_level_left_),
89 debug_depth (0) {}
90};
91
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040092
93
Behdad Esfahbod0535b502009-08-28 17:14:33 -040094#ifndef HB_DEBUG_APPLY
Behdad Esfahbod11e3ec42010-11-03 15:11:04 -040095#define HB_DEBUG_APPLY (HB_DEBUG+0)
Behdad Esfahbod0535b502009-08-28 17:14:33 -040096#endif
97
Behdad Esfahbodbc200452010-04-29 01:40:26 -040098#define TRACE_APPLY() \
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +020099 hb_auto_trace_t<HB_DEBUG_APPLY> trace (&c->debug_depth, "APPLY", this, HB_FUNC, "");
Behdad Esfahbod74e313c2010-04-28 15:15:09 -0400100
Behdad Esfahbod0535b502009-08-28 17:14:33 -0400101
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400102
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400103struct hb_apply_context_t
104{
Behdad Esfahbodabcfe9b2011-05-11 00:02:02 -0400105 hb_font_t *font;
106 hb_face_t *face;
Behdad Esfahbod94a23aa2010-05-05 01:13:09 -0400107 hb_buffer_t *buffer;
Behdad Esfahbod744970a2011-05-16 18:15:37 -0400108 hb_direction_t direction;
Behdad Esfahbodf7acd8d2010-05-20 17:26:35 +0100109 hb_mask_t lookup_mask;
Behdad Esfahbod969c9702010-05-05 01:23:44 -0400110 unsigned int context_length;
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400111 unsigned int nesting_level_left;
Behdad Esfahbod8c69e652010-10-27 22:07:49 -0400112 unsigned int lookup_props;
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400113 unsigned int property; /* propety of first glyph */
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400114 unsigned int debug_depth;
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400115
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400116
117 hb_apply_context_t (hb_font_t *font_,
118 hb_face_t *face_,
119 hb_buffer_t *buffer_,
120 hb_mask_t lookup_mask_,
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400121 unsigned int context_length_ = NO_CONTEXT,
122 unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
123 font (font_), face (face_), buffer (buffer_),
124 direction (buffer_->props.direction),
125 lookup_mask (lookup_mask_),
126 context_length (context_length_),
127 nesting_level_left (nesting_level_left_),
Behdad Esfahbod650ac002012-04-23 13:17:09 -0400128 lookup_props (0), property (0), debug_depth (0) {}
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400129
Behdad Esfahbod650ac002012-04-23 13:17:09 -0400130 void set_lookup (const Lookup &l) {
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400131 lookup_props = l.get_props ();
132 }
133
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500134 struct mark_skipping_forward_iterator_t
135 {
136 inline mark_skipping_forward_iterator_t (hb_apply_context_t *c_,
137 unsigned int start_index_,
138 unsigned int num_items_)
139 {
140 c = c_;
141 idx = start_index_;
142 num_items = num_items_;
143 end = MIN (c->buffer->len, c->buffer->idx + c->context_length);
144 }
145 inline bool has_no_chance (void) const
146 {
147 return unlikely (num_items && idx + num_items >= end);
148 }
149 inline bool next (unsigned int *property_out,
150 unsigned int lookup_props)
151 {
Behdad Esfahbod506ffeb2012-01-18 16:07:53 -0500152 assert (num_items > 0);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500153 do
154 {
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500155 if (has_no_chance ())
156 return false;
Behdad Esfahboda4a48fe2012-01-17 18:08:41 -0500157 idx++;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500158 } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[idx], lookup_props, property_out));
159 num_items--;
160 return true;
161 }
162 inline bool next (unsigned int *property_out = NULL)
163 {
164 return next (property_out, c->lookup_props);
165 }
166
167 unsigned int idx;
168 private:
169 hb_apply_context_t *c;
170 unsigned int num_items;
171 unsigned int end;
172 };
173
174 struct mark_skipping_backward_iterator_t
175 {
176 inline mark_skipping_backward_iterator_t (hb_apply_context_t *c_,
177 unsigned int start_index_,
178 unsigned int num_items_)
179 {
180 c = c_;
181 idx = start_index_;
182 num_items = num_items_;
183 }
184 inline bool has_no_chance (void) const
185 {
Behdad Esfahbod506ffeb2012-01-18 16:07:53 -0500186 return unlikely (idx < num_items);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500187 }
188 inline bool prev (unsigned int *property_out,
189 unsigned int lookup_props)
190 {
Behdad Esfahbod506ffeb2012-01-18 16:07:53 -0500191 assert (num_items > 0);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500192 do
193 {
194 if (has_no_chance ())
195 return false;
196 idx--;
197 } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->out_info[idx], lookup_props, property_out));
198 num_items--;
199 return true;
200 }
201 inline bool prev (unsigned int *property_out = NULL)
202 {
203 return prev (property_out, c->lookup_props);
204 }
205
206 unsigned int idx;
207 private:
208 hb_apply_context_t *c;
209 unsigned int num_items;
210 };
211
Behdad Esfahbod7d479902012-01-18 21:19:32 -0500212 inline bool should_mark_skip_current_glyph (void) const
213 {
214 return _hb_ot_layout_skip_mark (face, &buffer->info[buffer->idx], lookup_props, NULL);
215 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500216
217
218
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400219 inline void replace_glyph (hb_codepoint_t glyph_index) const
220 {
221 clear_property ();
222 buffer->replace_glyph (glyph_index);
223 }
224 inline void replace_glyphs_be16 (unsigned int num_in,
225 unsigned int num_out,
226 const uint16_t *glyph_data_be) const
227 {
228 clear_property ();
229 buffer->replace_glyphs_be16 (num_in, num_out, glyph_data_be);
230 }
231
232 inline void guess_glyph_class (unsigned int klass)
233 {
Behdad Esfahbod300cb412010-11-17 12:57:23 -0500234 /* XXX if ! has gdef */
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400235 buffer->info[buffer->idx].props_cache() = klass;
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400236 }
237
238 private:
239 inline void clear_property (void) const
240 {
Behdad Esfahbod300cb412010-11-17 12:57:23 -0500241 /* XXX if has gdef */
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400242 buffer->info[buffer->idx].props_cache() = 0;
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400243 }
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400244};
245
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400246
Behdad Esfahbod94a23aa2010-05-05 01:13:09 -0400247
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400248typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400249typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400250typedef void (*closure_lookup_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400251typedef bool (*apply_lookup_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400252
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400253struct ContextClosureFuncs
254{
255 intersects_func_t intersects;
256 closure_lookup_func_t closure;
257};
258struct ContextApplyFuncs
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400259{
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400260 match_func_t match;
261 apply_lookup_func_t apply;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400262};
263
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400264static inline bool intersects_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400265{
266 return glyphs->has (value);
267}
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400268static inline bool intersects_class (hb_set_t *glyphs, const USHORT &value, const void *data)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400269{
270 const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
271 return class_def.intersects_class (glyphs, value);
272}
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400273static inline bool intersects_coverage (hb_set_t *glyphs, const USHORT &value, const void *data)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400274{
275 const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
276 return (data+coverage).intersects (glyphs);
277}
278
279static inline bool intersects_array (hb_closure_context_t *c,
280 unsigned int count,
281 const USHORT values[],
282 intersects_func_t intersects_func,
283 const void *intersects_data)
284{
285 for (unsigned int i = 0; i < count; i++)
286 if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
287 return false;
288 return true;
289}
290
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400291
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400292static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, const void *data HB_UNUSED)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400293{
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400294 return glyph_id == value;
295}
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400296static inline bool match_class (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400297{
Behdad Esfahbod2b5a59c2009-08-04 11:38:50 -0400298 const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400299 return class_def.get_class (glyph_id) == value;
300}
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400301static inline bool match_coverage (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400302{
Behdad Esfahbod6b54c5d2009-05-18 18:30:25 -0400303 const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400304 return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400305}
306
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400307
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400308static inline bool match_input (hb_apply_context_t *c,
Behdad Esfahbode072c242009-05-18 03:47:31 -0400309 unsigned int count, /* Including the first glyph (not matched) */
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400310 const USHORT input[], /* Array of input values--start with second glyph */
311 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400312 const void *match_data,
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400313 unsigned int *context_length_out)
314{
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500315 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
316 if (skippy_iter.has_no_chance ())
Behdad Esfahbod7cff75b2009-05-18 04:09:05 -0400317 return false;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400318
Behdad Esfahbod370f03e2012-01-16 17:03:55 -0500319 for (unsigned int i = 1; i < count; i++)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400320 {
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500321 if (!skippy_iter.next ())
322 return false;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400323
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500324 if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, input[i - 1], match_data)))
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400325 return false;
326 }
327
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500328 *context_length_out = skippy_iter.idx - c->buffer->idx + 1;
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400329
330 return true;
331}
332
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400333static inline bool match_backtrack (hb_apply_context_t *c,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400334 unsigned int count,
335 const USHORT backtrack[],
336 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400337 const void *match_data)
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400338{
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500339 hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count);
340 if (skippy_iter.has_no_chance ())
341 return false;
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400342
Behdad Esfahbod4d3aeb82012-01-16 16:43:26 -0500343 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400344 {
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500345 if (!skippy_iter.prev ())
346 return false;
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400347
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500348 if (likely (!match_func (c->buffer->out_info[skippy_iter.idx].codepoint, backtrack[i], match_data)))
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400349 return false;
350 }
351
352 return true;
353}
354
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400355static inline bool match_lookahead (hb_apply_context_t *c,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400356 unsigned int count,
357 const USHORT lookahead[],
358 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400359 const void *match_data,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400360 unsigned int offset)
361{
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500362 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count);
363 if (skippy_iter.has_no_chance ())
364 return false;
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400365
Behdad Esfahbod370f03e2012-01-16 17:03:55 -0500366 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400367 {
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500368 if (!skippy_iter.next ())
369 return false;
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400370
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500371 if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, lookahead[i], match_data)))
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400372 return false;
373 }
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400374
375 return true;
376}
377
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400378
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400379
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400380struct LookupRecord
381{
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400382 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400383 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200384 return TRACE_RETURN (c->check_struct (this));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -0400385 }
386
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400387 USHORT sequenceIndex; /* Index into current glyph
388 * sequence--first glyph = 0 */
389 USHORT lookupListIndex; /* Lookup to apply to that
390 * position--zero--based */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400391 public:
392 DEFINE_SIZE_STATIC (4);
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400393};
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400394
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400395
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400396static inline void closure_lookup (hb_closure_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400397 unsigned int lookupCount,
398 const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
399 closure_lookup_func_t closure_func)
400{
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400401 for (unsigned int i = 0; i < lookupCount; i++)
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400402 closure_func (c, lookupRecord->lookupListIndex);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400403}
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400404
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400405static inline bool apply_lookup (hb_apply_context_t *c,
Behdad Esfahbode072c242009-05-18 03:47:31 -0400406 unsigned int count, /* Including the first glyph */
407 unsigned int lookupCount,
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400408 const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
409 apply_lookup_func_t apply_func)
410{
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400411 unsigned int end = MIN (c->buffer->len, c->buffer->idx + c->context_length);
412 if (unlikely (count == 0 || c->buffer->idx + count > end))
Behdad Esfahbode73a0c22009-05-18 04:15:25 -0400413 return false;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400414
Behdad Esfahbod7cff75b2009-05-18 04:09:05 -0400415 /* TODO We don't support lookupRecord arrays that are not increasing:
416 * Should be easy for in_place ones at least. */
Behdad Esfahbod52e9a712009-09-21 13:58:56 -0400417
Behdad Esfahbod7eb87512010-12-13 14:13:35 -0500418 /* Note: If sublookup is reverse, it will underflow after the first loop
Behdad Esfahbod52e9a712009-09-21 13:58:56 -0400419 * and we jump out of it. Not entirely disastrous. So we don't check
420 * for reverse lookup here.
421 */
Behdad Esfahbodf9c0a2d2009-09-21 13:43:54 -0400422 for (unsigned int i = 0; i < count; /* NOP */)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400423 {
Behdad Esfahbod03408ce2012-01-18 21:28:34 -0500424 if (unlikely (c->buffer->idx == end))
425 return true;
Behdad Esfahbod7d479902012-01-18 21:19:32 -0500426 while (c->should_mark_skip_current_glyph ())
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400427 {
Behdad Esfahbode73a0c22009-05-18 04:15:25 -0400428 /* No lookup applied for this index */
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400429 c->buffer->next_glyph ();
Behdad Esfahbod03408ce2012-01-18 21:28:34 -0500430 if (unlikely (c->buffer->idx == end))
431 return true;
Behdad Esfahbode73a0c22009-05-18 04:15:25 -0400432 }
433
Behdad Esfahbod47958de2009-05-18 04:17:47 -0400434 if (lookupCount && i == lookupRecord->sequenceIndex)
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400435 {
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400436 unsigned int old_pos = c->buffer->idx;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400437
438 /* Apply a lookup */
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400439 bool done = apply_func (c, lookupRecord->lookupListIndex);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400440
Behdad Esfahbod47958de2009-05-18 04:17:47 -0400441 lookupRecord++;
442 lookupCount--;
Behdad Esfahbodf9c0a2d2009-09-21 13:43:54 -0400443 /* Err, this is wrong if the lookup jumped over some glyphs */
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400444 i += c->buffer->idx - old_pos;
445 if (unlikely (c->buffer->idx == end))
Behdad Esfahbod2e8fb6c2009-05-18 04:37:37 -0400446 return true;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400447
448 if (!done)
449 goto not_applied;
450 }
451 else
452 {
453 not_applied:
454 /* No lookup applied for this index */
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400455 c->buffer->next_glyph ();
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400456 i++;
457 }
458 }
459
460 return true;
461}
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400462
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400463
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400464
465/* Contextual lookups */
466
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400467struct ContextClosureLookupContext
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400468{
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400469 ContextClosureFuncs funcs;
470 const void *intersects_data;
471};
472
473struct ContextApplyLookupContext
474{
475 ContextApplyFuncs funcs;
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400476 const void *match_data;
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400477};
478
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400479static inline void context_closure_lookup (hb_closure_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400480 unsigned int inputCount, /* Including the first glyph (not matched) */
481 const USHORT input[], /* Array of input values--start with second glyph */
482 unsigned int lookupCount,
483 const LookupRecord lookupRecord[],
484 ContextClosureLookupContext &lookup_context)
485{
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400486 if (intersects_array (c,
487 inputCount ? inputCount - 1 : 0, input,
488 lookup_context.funcs.intersects, lookup_context.intersects_data))
489 closure_lookup (c,
490 lookupCount, lookupRecord,
491 lookup_context.funcs.closure);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400492}
493
494
495static inline bool context_apply_lookup (hb_apply_context_t *c,
496 unsigned int inputCount, /* Including the first glyph (not matched) */
497 const USHORT input[], /* Array of input values--start with second glyph */
498 unsigned int lookupCount,
499 const LookupRecord lookupRecord[],
500 ContextApplyLookupContext &lookup_context)
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400501{
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400502 hb_apply_context_t new_context = *c;
503 return match_input (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -0400504 inputCount, input,
505 lookup_context.funcs.match, lookup_context.match_data,
506 &new_context.context_length)
507 && apply_lookup (&new_context,
508 inputCount,
509 lookupCount, lookupRecord,
510 lookup_context.funcs.apply);
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400511}
512
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400513struct Rule
514{
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400515 friend struct RuleSet;
516
517 private:
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400518
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400519 inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400520 {
521 TRACE_CLOSURE ();
522 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400523 context_closure_lookup (c,
524 inputCount, input,
525 lookupCount, lookupRecord,
526 lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400527 }
528
529 inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400530 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400531 TRACE_APPLY ();
Behdad Esfahbode45d3f82010-05-06 19:33:31 -0400532 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200533 return TRACE_RETURN (context_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400534 }
535
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400536 public:
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400537 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400538 TRACE_SANITIZE ();
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400539 return inputCount.sanitize (c)
540 && lookupCount.sanitize (c)
541 && c->check_range (input,
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400542 input[0].static_size * inputCount
543 + lookupRecordX[0].static_size * lookupCount);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400544 }
545
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400546 private:
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400547 USHORT inputCount; /* Total number of glyphs in input
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400548 * glyph sequence--includes the first
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400549 * glyph */
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400550 USHORT lookupCount; /* Number of LookupRecords */
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -0500551 USHORT input[VAR]; /* Array of match inputs--start with
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400552 * second glyph */
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -0500553 LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400554 * design order */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400555 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400556 DEFINE_SIZE_ARRAY2 (4, input, lookupRecordX);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400557};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400558
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400559struct RuleSet
560{
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400561 inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400562 {
563 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400564 unsigned int num_rules = rule.len;
565 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400566 (this+rule[i]).closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400567 }
568
569 inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400570 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400571 TRACE_APPLY ();
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400572 unsigned int num_rules = rule.len;
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400573 for (unsigned int i = 0; i < num_rules; i++)
574 {
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400575 if ((this+rule[i]).apply (c, lookup_context))
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200576 return TRACE_RETURN (true);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400577 }
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200578 return TRACE_RETURN (false);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400579 }
580
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400581 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400582 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200583 return TRACE_RETURN (rule.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400584 }
585
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400586 private:
587 OffsetArrayOf<Rule>
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400588 rule; /* Array of Rule tables
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400589 * ordered by preference */
Behdad Esfahboded074222010-05-10 18:08:46 -0400590 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400591 DEFINE_SIZE_ARRAY (2, rule);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400592};
593
594
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400595struct ContextFormat1
596{
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400597 friend struct Context;
598
599 private:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400600
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400601 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400602 {
603 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400604
605 const Coverage &cov = (this+coverage);
606
607 struct ContextClosureLookupContext lookup_context = {
608 {intersects_glyph, closure_func},
609 NULL
610 };
611
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400612 unsigned int count = ruleSet.len;
613 for (unsigned int i = 0; i < count; i++)
614 if (cov.intersects_coverage (c->glyphs, i)) {
615 const RuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400616 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400617 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400618 }
619
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400620 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400621 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400622 TRACE_APPLY ();
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400623 unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
Behdad Esfahbod64d3fc82010-05-03 22:51:19 -0400624 if (likely (index == NOT_COVERED))
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200625 return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -0400626
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400627 const RuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400628 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400629 {match_glyph, apply_func},
630 NULL
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400631 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200632 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400633 }
634
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400635 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400636 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200637 return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400638 }
639
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400640 private:
641 USHORT format; /* Format identifier--format = 1 */
642 OffsetTo<Coverage>
643 coverage; /* Offset to Coverage table--from
644 * beginning of table */
645 OffsetArrayOf<RuleSet>
646 ruleSet; /* Array of RuleSet tables
647 * ordered by Coverage Index */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400648 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400649 DEFINE_SIZE_ARRAY (6, ruleSet);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400650};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400651
652
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400653struct ContextFormat2
654{
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400655 friend struct Context;
656
657 private:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400658
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400659 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400660 {
661 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400662 if (!(this+coverage).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400663 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400664
665 const ClassDef &class_def = this+classDef;
666
667 struct ContextClosureLookupContext lookup_context = {
668 {intersects_class, closure_func},
669 NULL
670 };
671
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400672 unsigned int count = ruleSet.len;
673 for (unsigned int i = 0; i < count; i++)
674 if (class_def.intersects_class (c->glyphs, i)) {
675 const RuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400676 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400677 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400678 }
679
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400680 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400681 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400682 TRACE_APPLY ();
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400683 unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200684 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -0400685
686 const ClassDef &class_def = this+classDef;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400687 index = class_def (c->buffer->info[c->buffer->idx].codepoint);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400688 const RuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400689 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400690 {match_class, apply_func},
691 &class_def
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400692 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200693 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400694 }
695
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400696 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400697 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200698 return TRACE_RETURN (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400699 }
700
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400701 private:
702 USHORT format; /* Format identifier--format = 2 */
703 OffsetTo<Coverage>
704 coverage; /* Offset to Coverage table--from
705 * beginning of table */
706 OffsetTo<ClassDef>
707 classDef; /* Offset to glyph ClassDef table--from
708 * beginning of table */
709 OffsetArrayOf<RuleSet>
710 ruleSet; /* Array of RuleSet tables
711 * ordered by class */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400712 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400713 DEFINE_SIZE_ARRAY (8, ruleSet);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400714};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400715
716
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400717struct ContextFormat3
718{
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400719 friend struct Context;
720
721 private:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400722
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400723 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400724 {
725 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400726 if (!(this+coverage[0]).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400727 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400728
729 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
730 struct ContextClosureLookupContext lookup_context = {
731 {intersects_coverage, closure_func},
732 this
733 };
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400734 context_closure_lookup (c,
735 glyphCount, (const USHORT *) (coverage + 1),
736 lookupCount, lookupRecord,
737 lookup_context);
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400738 }
739
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400740 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400741 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400742 TRACE_APPLY ();
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400743 unsigned int index = (this+coverage[0]) (c->buffer->info[c->buffer->idx].codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200744 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -0400745
Behdad Esfahbode45d3f82010-05-06 19:33:31 -0400746 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400747 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400748 {match_coverage, apply_func},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400749 this
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400750 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200751 return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400752 }
753
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400754 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400755 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200756 if (!c->check_struct (this)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400757 unsigned int count = glyphCount;
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200758 if (!c->check_array (coverage, coverage[0].static_size, count)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400759 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200760 if (!coverage[i].sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode45d3f82010-05-06 19:33:31 -0400761 LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * count);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200762 return TRACE_RETURN (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400763 }
764
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400765 private:
766 USHORT format; /* Format identifier--format = 3 */
767 USHORT glyphCount; /* Number of glyphs in the input glyph
768 * sequence */
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400769 USHORT lookupCount; /* Number of LookupRecords */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -0400770 OffsetTo<Coverage>
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -0500771 coverage[VAR]; /* Array of offsets to Coverage
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -0400772 * table in glyph sequence order */
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -0500773 LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400774 * design order */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400775 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400776 DEFINE_SIZE_ARRAY2 (6, coverage, lookupRecordX);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400777};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400778
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400779struct Context
780{
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400781 protected:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400782
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400783 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400784 {
785 TRACE_CLOSURE ();
786 switch (u.format) {
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400787 case 1: u.format1.closure (c, closure_func); break;
788 case 2: u.format2.closure (c, closure_func); break;
789 case 3: u.format3.closure (c, closure_func); break;
790 default: break;
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400791 }
792 }
793
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400794 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400795 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400796 TRACE_APPLY ();
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400797 switch (u.format) {
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200798 case 1: return TRACE_RETURN (u.format1.apply (c, apply_func));
799 case 2: return TRACE_RETURN (u.format2.apply (c, apply_func));
800 case 3: return TRACE_RETURN (u.format3.apply (c, apply_func));
801 default:return TRACE_RETURN (false);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400802 }
803 }
804
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400805 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400806 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200807 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400808 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200809 case 1: return TRACE_RETURN (u.format1.sanitize (c));
810 case 2: return TRACE_RETURN (u.format2.sanitize (c));
811 case 3: return TRACE_RETURN (u.format3.sanitize (c));
812 default:return TRACE_RETURN (true);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400813 }
814 }
815
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400816 private:
817 union {
Behdad Esfahbodf8dc67b2009-05-17 19:47:54 -0400818 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -0400819 ContextFormat1 format1;
820 ContextFormat2 format2;
821 ContextFormat3 format3;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400822 } u;
823};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400824
Behdad Esfahbodca5290f2009-05-17 20:48:27 -0400825
826/* Chaining Contextual lookups */
827
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400828struct ChainContextClosureLookupContext
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400829{
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400830 ContextClosureFuncs funcs;
831 const void *intersects_data[3];
832};
833
834struct ChainContextApplyLookupContext
835{
836 ContextApplyFuncs funcs;
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400837 const void *match_data[3];
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400838};
839
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400840static inline void chain_context_closure_lookup (hb_closure_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400841 unsigned int backtrackCount,
842 const USHORT backtrack[],
843 unsigned int inputCount, /* Including the first glyph (not matched) */
844 const USHORT input[], /* Array of input values--start with second glyph */
845 unsigned int lookaheadCount,
846 const USHORT lookahead[],
847 unsigned int lookupCount,
848 const LookupRecord lookupRecord[],
849 ChainContextClosureLookupContext &lookup_context)
850{
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400851 if (intersects_array (c,
852 backtrackCount, backtrack,
853 lookup_context.funcs.intersects, lookup_context.intersects_data[0])
854 && intersects_array (c,
855 inputCount ? inputCount - 1 : 0, input,
856 lookup_context.funcs.intersects, lookup_context.intersects_data[1])
857 && intersects_array (c,
858 lookaheadCount, lookahead,
859 lookup_context.funcs.intersects, lookup_context.intersects_data[2]))
860 closure_lookup (c,
861 lookupCount, lookupRecord,
862 lookup_context.funcs.closure);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400863}
864
865static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
866 unsigned int backtrackCount,
867 const USHORT backtrack[],
868 unsigned int inputCount, /* Including the first glyph (not matched) */
869 const USHORT input[], /* Array of input values--start with second glyph */
870 unsigned int lookaheadCount,
871 const USHORT lookahead[],
872 unsigned int lookupCount,
873 const LookupRecord lookupRecord[],
874 ChainContextApplyLookupContext &lookup_context)
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -0400875{
Behdad Esfahbode072c242009-05-18 03:47:31 -0400876 /* First guess */
Behdad Esfahbodcc1a8a92011-01-06 14:58:52 -0500877 if (unlikely (c->buffer->backtrack_len () < backtrackCount ||
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400878 c->buffer->idx + inputCount + lookaheadCount > c->buffer->len ||
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400879 inputCount + lookaheadCount > c->context_length))
Behdad Esfahbode072c242009-05-18 03:47:31 -0400880 return false;
881
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400882 hb_apply_context_t new_context = *c;
883 return match_backtrack (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -0400884 backtrackCount, backtrack,
885 lookup_context.funcs.match, lookup_context.match_data[0])
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400886 && match_input (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -0400887 inputCount, input,
888 lookup_context.funcs.match, lookup_context.match_data[1],
889 &new_context.context_length)
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400890 && match_lookahead (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -0400891 lookaheadCount, lookahead,
892 lookup_context.funcs.match, lookup_context.match_data[2],
893 new_context.context_length)
894 && apply_lookup (&new_context,
895 inputCount,
896 lookupCount, lookupRecord,
897 lookup_context.funcs.apply);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -0400898}
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400899
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400900struct ChainRule
901{
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -0400902 friend struct ChainRuleSet;
903
904 private:
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400905
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400906 inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400907 {
908 TRACE_CLOSURE ();
909 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
910 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
911 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400912 chain_context_closure_lookup (c,
913 backtrack.len, backtrack.array,
914 input.len, input.array,
915 lookahead.len, lookahead.array,
916 lookup.len, lookup.array,
917 lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400918 }
919
920 inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400921 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400922 TRACE_APPLY ();
Behdad Esfahbode961c862010-04-21 15:56:11 -0400923 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
924 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
925 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200926 return TRACE_RETURN (chain_context_apply_lookup (c,
927 backtrack.len, backtrack.array,
928 input.len, input.array,
929 lookahead.len, lookahead.array, lookup.len,
930 lookup.array, lookup_context));
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -0400931 }
932
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400933 public:
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400934 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400935 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200936 if (!backtrack.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -0400937 HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200938 if (!input.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -0400939 ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200940 if (!lookahead.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -0400941 ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200942 return TRACE_RETURN (lookup.sanitize (c));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400943 }
Behdad Esfahbodca5290f2009-05-17 20:48:27 -0400944
945 private:
Behdad Esfahboddcb6b602009-05-18 01:49:57 -0400946 ArrayOf<USHORT>
947 backtrack; /* Array of backtracking values
Behdad Esfahbodca5290f2009-05-17 20:48:27 -0400948 * (to be matched before the input
949 * sequence) */
Behdad Esfahbode8cbaaf2009-05-18 02:03:58 -0400950 HeadlessArrayOf<USHORT>
951 inputX; /* Array of input values (start with
Behdad Esfahbodca5290f2009-05-17 20:48:27 -0400952 * second glyph) */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -0400953 ArrayOf<USHORT>
954 lookaheadX; /* Array of lookahead values's (to be
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400955 * matched after the input sequence) */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -0400956 ArrayOf<LookupRecord>
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -0400957 lookupX; /* Array of LookupRecords--in
Behdad Esfahbodca5290f2009-05-17 20:48:27 -0400958 * design order) */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400959 public:
Behdad Esfahbodbea34c72010-05-10 17:28:16 -0400960 DEFINE_SIZE_MIN (8);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -0400961};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -0400962
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400963struct ChainRuleSet
964{
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400965 inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400966 {
967 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400968 unsigned int num_rules = rule.len;
969 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400970 (this+rule[i]).closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400971 }
972
973 inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400974 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400975 TRACE_APPLY ();
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400976 unsigned int num_rules = rule.len;
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400977 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400978 if ((this+rule[i]).apply (c, lookup_context))
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200979 return TRACE_RETURN (true);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400980
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200981 return TRACE_RETURN (false);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400982 }
Behdad Esfahbodca5290f2009-05-17 20:48:27 -0400983
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400984 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400985 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200986 return TRACE_RETURN (rule.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400987 }
988
Behdad Esfahbodca5290f2009-05-17 20:48:27 -0400989 private:
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400990 OffsetArrayOf<ChainRule>
991 rule; /* Array of ChainRule tables
992 * ordered by preference */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400993 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400994 DEFINE_SIZE_ARRAY (2, rule);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -0400995};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -0400996
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400997struct ChainContextFormat1
998{
Behdad Esfahbodca5290f2009-05-17 20:48:27 -0400999 friend struct ChainContext;
1000
1001 private:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001002
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001003 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001004 {
1005 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001006 const Coverage &cov = (this+coverage);
1007
1008 struct ChainContextClosureLookupContext lookup_context = {
1009 {intersects_glyph, closure_func},
1010 {NULL, NULL, NULL}
1011 };
1012
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001013 unsigned int count = ruleSet.len;
1014 for (unsigned int i = 0; i < count; i++)
1015 if (cov.intersects_coverage (c->glyphs, i)) {
1016 const ChainRuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001017 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001018 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001019 }
1020
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001021 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001022 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001023 TRACE_APPLY ();
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -04001024 unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001025 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001026
1027 const ChainRuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001028 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001029 {match_glyph, apply_func},
1030 {NULL, NULL, NULL}
1031 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001032 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001033 }
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001034
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001035 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001036 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001037 return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001038 }
1039
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001040 private:
1041 USHORT format; /* Format identifier--format = 1 */
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001042 OffsetTo<Coverage>
1043 coverage; /* Offset to Coverage table--from
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001044 * beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001045 OffsetArrayOf<ChainRuleSet>
1046 ruleSet; /* Array of ChainRuleSet tables
1047 * ordered by Coverage Index */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001048 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001049 DEFINE_SIZE_ARRAY (6, ruleSet);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001050};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001051
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001052struct ChainContextFormat2
1053{
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001054 friend struct ChainContext;
1055
1056 private:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001057
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001058 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001059 {
1060 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001061 if (!(this+coverage).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001062 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001063
1064 const ClassDef &backtrack_class_def = this+backtrackClassDef;
1065 const ClassDef &input_class_def = this+inputClassDef;
1066 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
1067
1068 struct ChainContextClosureLookupContext lookup_context = {
1069 {intersects_class, closure_func},
1070 {&backtrack_class_def,
1071 &input_class_def,
1072 &lookahead_class_def}
1073 };
1074
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001075 unsigned int count = ruleSet.len;
1076 for (unsigned int i = 0; i < count; i++)
1077 if (input_class_def.intersects_class (c->glyphs, i)) {
1078 const ChainRuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001079 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001080 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001081 }
1082
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001083 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001084 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001085 TRACE_APPLY ();
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -04001086 unsigned int index = (this+coverage) (c->buffer->info[c->buffer->idx].codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001087 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001088
1089 const ClassDef &backtrack_class_def = this+backtrackClassDef;
1090 const ClassDef &input_class_def = this+inputClassDef;
1091 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
1092
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -04001093 index = input_class_def (c->buffer->info[c->buffer->idx].codepoint);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001094 const ChainRuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001095 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001096 {match_class, apply_func},
1097 {&backtrack_class_def,
1098 &input_class_def,
1099 &lookahead_class_def}
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001100 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001101 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001102 }
1103
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001104 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001105 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001106 return TRACE_RETURN (coverage.sanitize (c, this) && backtrackClassDef.sanitize (c, this) &&
1107 inputClassDef.sanitize (c, this) && lookaheadClassDef.sanitize (c, this) &&
1108 ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001109 }
1110
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001111 private:
1112 USHORT format; /* Format identifier--format = 2 */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001113 OffsetTo<Coverage>
1114 coverage; /* Offset to Coverage table--from
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001115 * beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001116 OffsetTo<ClassDef>
1117 backtrackClassDef; /* Offset to glyph ClassDef table
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001118 * containing backtrack sequence
1119 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001120 OffsetTo<ClassDef>
1121 inputClassDef; /* Offset to glyph ClassDef
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001122 * table containing input sequence
1123 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001124 OffsetTo<ClassDef>
1125 lookaheadClassDef; /* Offset to glyph ClassDef table
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001126 * containing lookahead sequence
1127 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001128 OffsetArrayOf<ChainRuleSet>
1129 ruleSet; /* Array of ChainRuleSet tables
1130 * ordered by class */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001131 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001132 DEFINE_SIZE_ARRAY (12, ruleSet);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001133};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001134
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001135struct ChainContextFormat3
1136{
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001137 friend struct ChainContext;
1138
1139 private:
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001140
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001141 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001142 {
1143 TRACE_CLOSURE ();
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001144 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
1145
1146 if (!(this+input[0]).intersects (c->glyphs))
1147 return;
1148
1149 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
1150 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1151 struct ChainContextClosureLookupContext lookup_context = {
1152 {intersects_coverage, closure_func},
1153 {this, this, this}
1154 };
1155 chain_context_closure_lookup (c,
1156 backtrack.len, (const USHORT *) backtrack.array,
1157 input.len, (const USHORT *) input.array + 1,
1158 lookahead.len, (const USHORT *) lookahead.array,
1159 lookup.len, lookup.array,
1160 lookup_context);
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001161 }
1162
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001163 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001164 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001165 TRACE_APPLY ();
Behdad Esfahbode961c862010-04-21 15:56:11 -04001166 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001167
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -04001168 unsigned int index = (this+input[0]) (c->buffer->info[c->buffer->idx].codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001169 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001170
Behdad Esfahbode961c862010-04-21 15:56:11 -04001171 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
1172 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001173 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001174 {match_coverage, apply_func},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001175 {this, this, this}
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001176 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001177 return TRACE_RETURN (chain_context_apply_lookup (c,
1178 backtrack.len, (const USHORT *) backtrack.array,
1179 input.len, (const USHORT *) input.array + 1,
1180 lookahead.len, (const USHORT *) lookahead.array,
1181 lookup.len, lookup.array, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001182 }
1183
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001184 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001185 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001186 if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001187 OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001188 if (!input.sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001189 OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001190 if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001191 ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001192 return TRACE_RETURN (lookup.sanitize (c));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001193 }
1194
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001195 private:
1196 USHORT format; /* Format identifier--format = 3 */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001197 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04001198 backtrack; /* Array of coverage tables
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001199 * in backtracking sequence, in glyph
1200 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001201 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04001202 inputX ; /* Array of coverage
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001203 * tables in input sequence, in glyph
1204 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001205 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04001206 lookaheadX; /* Array of coverage tables
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001207 * in lookahead sequence, in glyph
1208 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001209 ArrayOf<LookupRecord>
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001210 lookupX; /* Array of LookupRecords--in
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001211 * design order) */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001212 public:
Behdad Esfahbodbea34c72010-05-10 17:28:16 -04001213 DEFINE_SIZE_MIN (10);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001214};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001215
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001216struct ChainContext
1217{
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001218 protected:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001219
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001220 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001221 {
1222 TRACE_CLOSURE ();
1223 switch (u.format) {
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001224 case 1: u.format1.closure (c, closure_func); break;
1225 case 2: u.format2.closure (c, closure_func); break;
1226 case 3: u.format3.closure (c, closure_func); break;
1227 default: break;
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001228 }
1229 }
1230
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001231 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001232 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001233 TRACE_APPLY ();
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001234 switch (u.format) {
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001235 case 1: return TRACE_RETURN (u.format1.apply (c, apply_func));
1236 case 2: return TRACE_RETURN (u.format2.apply (c, apply_func));
1237 case 3: return TRACE_RETURN (u.format3.apply (c, apply_func));
1238 default:return TRACE_RETURN (false);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001239 }
1240 }
1241
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001242 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001243 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001244 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001245 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001246 case 1: return TRACE_RETURN (u.format1.sanitize (c));
1247 case 2: return TRACE_RETURN (u.format2.sanitize (c));
1248 case 3: return TRACE_RETURN (u.format3.sanitize (c));
1249 default:return TRACE_RETURN (true);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001250 }
1251 }
1252
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001253 private:
1254 union {
1255 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001256 ChainContextFormat1 format1;
1257 ChainContextFormat2 format2;
1258 ChainContextFormat3 format3;
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001259 } u;
1260};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001261
1262
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001263struct ExtensionFormat1
1264{
1265 friend struct Extension;
1266
Behdad Esfahbod18939482009-08-04 14:27:56 -04001267 protected:
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001268 inline unsigned int get_type (void) const { return extensionLookupType; }
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -04001269 inline unsigned int get_offset (void) const { return extensionOffset; }
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001270
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001271 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001272 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001273 return TRACE_RETURN (c->check_struct (this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001274 }
1275
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001276 private:
1277 USHORT format; /* Format identifier. Set to 1. */
1278 USHORT extensionLookupType; /* Lookup type of subtable referenced
1279 * by ExtensionOffset (i.e. the
1280 * extension subtable). */
Behdad Esfahbod81f2af42010-04-22 00:58:49 -04001281 ULONG extensionOffset; /* Offset to the extension subtable,
1282 * of lookup type subtable. */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001283 public:
1284 DEFINE_SIZE_STATIC (8);
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001285};
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001286
1287struct Extension
1288{
1289 inline unsigned int get_type (void) const
1290 {
1291 switch (u.format) {
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001292 case 1: return u.format1.get_type ();
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001293 default:return 0;
1294 }
1295 }
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -04001296 inline unsigned int get_offset (void) const
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001297 {
1298 switch (u.format) {
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001299 case 1: return u.format1.get_offset ();
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -04001300 default:return 0;
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001301 }
1302 }
1303
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001304 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001305 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001306 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001307 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001308 case 1: return TRACE_RETURN (u.format1.sanitize (c));
1309 default:return TRACE_RETURN (true);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001310 }
1311 }
1312
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001313 private:
1314 union {
1315 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001316 ExtensionFormat1 format1;
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001317 } u;
1318};
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001319
1320
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001321/*
1322 * GSUB/GPOS Common
1323 */
1324
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001325struct GSUBGPOS
1326{
Behdad Esfahboda328d662009-08-04 20:27:05 -04001327 static const hb_tag_t GSUBTag = HB_OT_TAG_GSUB;
1328 static const hb_tag_t GPOSTag = HB_OT_TAG_GPOS;
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001329
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04001330 inline unsigned int get_script_count (void) const
1331 { return (this+scriptList).len; }
1332 inline const Tag& get_script_tag (unsigned int i) const
1333 { return (this+scriptList).get_tag (i); }
Behdad Esfahbode21899b2009-11-04 16:36:14 -05001334 inline unsigned int get_script_tags (unsigned int start_offset,
1335 unsigned int *script_count /* IN/OUT */,
1336 hb_tag_t *script_tags /* OUT */) const
1337 { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04001338 inline const Script& get_script (unsigned int i) const
1339 { return (this+scriptList)[i]; }
1340 inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
1341 { return (this+scriptList).find_index (tag, index); }
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001342
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04001343 inline unsigned int get_feature_count (void) const
1344 { return (this+featureList).len; }
1345 inline const Tag& get_feature_tag (unsigned int i) const
1346 { return (this+featureList).get_tag (i); }
Behdad Esfahbode21899b2009-11-04 16:36:14 -05001347 inline unsigned int get_feature_tags (unsigned int start_offset,
1348 unsigned int *feature_count /* IN/OUT */,
1349 hb_tag_t *feature_tags /* OUT */) const
1350 { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04001351 inline const Feature& get_feature (unsigned int i) const
1352 { return (this+featureList)[i]; }
1353 inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
1354 { return (this+featureList).find_index (tag, index); }
1355
1356 inline unsigned int get_lookup_count (void) const
1357 { return (this+lookupList).len; }
1358 inline const Lookup& get_lookup (unsigned int i) const
1359 { return (this+lookupList)[i]; }
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001360
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001361 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001362 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001363 return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) &&
1364 scriptList.sanitize (c, this) &&
1365 featureList.sanitize (c, this) &&
1366 lookupList.sanitize (c, this));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -04001367 }
1368
Behdad Esfahbod212aba62009-05-24 00:50:27 -04001369 protected:
Behdad Esfahbod87fcdcb2009-05-24 01:03:24 -04001370 FixedVersion version; /* Version of the GSUB/GPOS table--initially set
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001371 * to 0x00010000 */
1372 OffsetTo<ScriptList>
1373 scriptList; /* ScriptList table */
1374 OffsetTo<FeatureList>
1375 featureList; /* FeatureList table */
1376 OffsetTo<LookupList>
1377 lookupList; /* LookupList table */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001378 public:
1379 DEFINE_SIZE_STATIC (10);
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001380};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001381
Behdad Esfahbod6f20f722009-05-17 20:28:01 -04001382
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -04001383
Behdad Esfahbod5f5b24f2009-08-02 20:03:12 -04001384#endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */