blob: 00c64d5f799534fe83acf56d04daf608587777e3 [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 Esfahbodf94b0aa2012-04-23 13:04:38 -040037#ifndef HB_DEBUG_CLOSURE
38#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
39#endif
40
41#define TRACE_CLOSURE() \
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +020042 hb_auto_trace_t<HB_DEBUG_CLOSURE> trace (&c->debug_depth, "CLOSURE", this, HB_FUNC, "");
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040043
44
Behdad Esfahbode72b3602012-07-19 14:35:23 -040045/* TODO Add TRACE_RETURN annotation to gsub. */
46#ifndef HB_DEBUG_WOULD_APPLY
47#define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
48#endif
49
50#define TRACE_WOULD_APPLY() \
51 hb_auto_trace_t<HB_DEBUG_WOULD_APPLY> trace (&c->debug_depth, "WOULD_APPLY", this, HB_FUNC, "first %u second %u", c->first, c->second);
Behdad Esfahbod98619ce2012-05-11 02:34:06 +020052
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040053
54struct hb_closure_context_t
55{
56 hb_face_t *face;
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -040057 hb_set_t *glyphs;
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040058 unsigned int nesting_level_left;
59 unsigned int debug_depth;
60
61
62 hb_closure_context_t (hb_face_t *face_,
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -040063 hb_set_t *glyphs_,
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040064 unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
Behdad Esfahbode72b3602012-07-19 14:35:23 -040065 face (face_),
66 glyphs (glyphs_),
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040067 nesting_level_left (nesting_level_left_),
68 debug_depth (0) {}
69};
70
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040071
72
Behdad Esfahbode72b3602012-07-19 14:35:23 -040073
74struct hb_would_apply_context_t
75{
76 hb_face_t *face;
77 hb_codepoint_t first;
78 hb_codepoint_t second;
79 unsigned int len;
80 unsigned int debug_depth;
81
82 hb_would_apply_context_t (hb_face_t *face_,
83 hb_codepoint_t first_,
84 hb_codepoint_t second_ = -1) :
85 face (face_),
86 first (first_), second (second_), len (second == (hb_codepoint_t) -1 ? 1 : 2),
87 debug_depth (0) {};
88};
89
90
Behdad Esfahbod0535b502009-08-28 17:14:33 -040091#ifndef HB_DEBUG_APPLY
Behdad Esfahbod11e3ec42010-11-03 15:11:04 -040092#define HB_DEBUG_APPLY (HB_DEBUG+0)
Behdad Esfahbod0535b502009-08-28 17:14:33 -040093#endif
94
Behdad Esfahbodbc200452010-04-29 01:40:26 -040095#define TRACE_APPLY() \
Behdad Esfahbod68b76122012-06-08 10:43:49 -040096 hb_auto_trace_t<HB_DEBUG_APPLY> trace (&c->debug_depth, "APPLY", this, HB_FUNC, "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint);
Behdad Esfahbod74e313c2010-04-28 15:15:09 -040097
Behdad Esfahbod0535b502009-08-28 17:14:33 -040098
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -040099
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400100static inline hb_bool_t
101_hb_ot_layout_match_properties_mark (hb_face_t *face,
102 hb_codepoint_t glyph,
103 unsigned int glyph_props,
104 unsigned int lookup_props)
105{
106 /* If using mark filtering sets, the high short of
107 * lookup_props has the set index.
108 */
109 if (lookup_props & LookupFlag::UseMarkFilteringSet)
110 return hb_ot_layout_from_face (face)->gdef->mark_set_covers (lookup_props >> 16, glyph);
111
112 /* The second byte of lookup_props has the meaning
113 * "ignore marks of attachment type different than
114 * the attachment type specified."
115 */
116 if (lookup_props & LookupFlag::MarkAttachmentType)
117 return (lookup_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
118
119 return true;
120}
121
122static inline hb_bool_t
123_hb_ot_layout_match_properties (hb_face_t *face,
124 hb_codepoint_t glyph,
125 unsigned int glyph_props,
126 unsigned int lookup_props)
127{
128 /* Not covered, if, for example, glyph class is ligature and
129 * lookup_props includes LookupFlags::IgnoreLigatures
130 */
131 if (glyph_props & lookup_props & LookupFlag::IgnoreFlags)
132 return false;
133
134 if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_CLASS_MARK))
135 return _hb_ot_layout_match_properties_mark (face, glyph, glyph_props, lookup_props);
136
137 return true;
138}
139
140static inline hb_bool_t
141_hb_ot_layout_check_glyph_property (hb_face_t *face,
142 hb_glyph_info_t *ginfo,
143 unsigned int lookup_props,
144 unsigned int *property_out)
145{
146 unsigned int property;
147
148 property = ginfo->props_cache();
149 *property_out = property;
150
151 return _hb_ot_layout_match_properties (face, ginfo->codepoint, property, lookup_props);
152}
153
154static inline hb_bool_t
155_hb_ot_layout_skip_mark (hb_face_t *face,
156 hb_glyph_info_t *ginfo,
157 unsigned int lookup_props,
158 unsigned int *property_out)
159{
160 unsigned int property;
161
162 property = ginfo->props_cache();
163 if (property_out)
164 *property_out = property;
165
166 /* If it's a mark, skip it if we don't accept it. */
167 if (unlikely (property & HB_OT_LAYOUT_GLYPH_CLASS_MARK))
168 return !_hb_ot_layout_match_properties (face, ginfo->codepoint, property, lookup_props);
169
170 /* If not a mark, don't skip. */
171 return false;
172}
173
174
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400175struct hb_apply_context_t
176{
Behdad Esfahbodabcfe9b2011-05-11 00:02:02 -0400177 hb_font_t *font;
178 hb_face_t *face;
Behdad Esfahbod94a23aa2010-05-05 01:13:09 -0400179 hb_buffer_t *buffer;
Behdad Esfahbod744970a2011-05-16 18:15:37 -0400180 hb_direction_t direction;
Behdad Esfahbodf7acd8d2010-05-20 17:26:35 +0100181 hb_mask_t lookup_mask;
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400182 unsigned int nesting_level_left;
Behdad Esfahbod8c69e652010-10-27 22:07:49 -0400183 unsigned int lookup_props;
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400184 unsigned int property; /* propety of first glyph */
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400185 unsigned int debug_depth;
Behdad Esfahbod60da7632012-07-16 16:13:32 -0400186 bool has_glyph_classes;
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400187 const GDEF &gdef;
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400188
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400189
190 hb_apply_context_t (hb_font_t *font_,
191 hb_face_t *face_,
192 hb_buffer_t *buffer_,
Behdad Esfahbod6736f3c2012-05-13 15:21:06 +0200193 hb_mask_t lookup_mask_) :
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400194 font (font_), face (face_), buffer (buffer_),
195 direction (buffer_->props.direction),
196 lookup_mask (lookup_mask_),
Behdad Esfahbod6736f3c2012-05-13 15:21:06 +0200197 nesting_level_left (MAX_NESTING_LEVEL),
Behdad Esfahbod60da7632012-07-16 16:13:32 -0400198 lookup_props (0), property (0), debug_depth (0),
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400199 has_glyph_classes (hb_ot_layout_has_glyph_classes (face_)),
200 gdef (*hb_ot_layout_from_face (face_)->gdef /* XXX Unsafe dereference */) {}
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400201
Behdad Esfahbod650ac002012-04-23 13:17:09 -0400202 void set_lookup (const Lookup &l) {
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400203 lookup_props = l.get_props ();
204 }
205
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500206 struct mark_skipping_forward_iterator_t
207 {
208 inline mark_skipping_forward_iterator_t (hb_apply_context_t *c_,
209 unsigned int start_index_,
Behdad Esfahbod203d7102012-05-11 16:01:44 +0200210 unsigned int num_items_,
Behdad Esfahbod28b9d502012-05-13 15:04:00 +0200211 bool context_match = false)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500212 {
213 c = c_;
214 idx = start_index_;
215 num_items = num_items_;
Behdad Esfahbod28b9d502012-05-13 15:04:00 +0200216 mask = context_match ? -1 : c->lookup_mask;
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200217 syllable = context_match ? 0 : c->buffer->cur().syllable ();
Behdad Esfahbod5df809b2012-05-13 15:17:51 +0200218 end = c->buffer->len;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500219 }
220 inline bool has_no_chance (void) const
221 {
222 return unlikely (num_items && idx + num_items >= end);
223 }
Behdad Esfahbodb12e2542012-06-09 03:05:20 -0400224 inline void reject (void)
Behdad Esfahbod7b84c532012-06-08 22:04:23 -0400225 {
226 num_items++;
227 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500228 inline bool next (unsigned int *property_out,
Behdad Esfahbod89328582012-07-19 21:02:38 -0400229 unsigned int lookup_props)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500230 {
Behdad Esfahbod506ffeb2012-01-18 16:07:53 -0500231 assert (num_items > 0);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500232 do
233 {
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500234 if (has_no_chance ())
235 return false;
Behdad Esfahboda4a48fe2012-01-17 18:08:41 -0500236 idx++;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500237 } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[idx], lookup_props, property_out));
238 num_items--;
Behdad Esfahbod5f131d32012-05-11 17:29:40 +0200239 return (c->buffer->info[idx].mask & mask) && (!syllable || syllable == c->buffer->info[idx].syllable ());
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500240 }
241 inline bool next (unsigned int *property_out = NULL)
242 {
243 return next (property_out, c->lookup_props);
244 }
245
246 unsigned int idx;
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400247 protected:
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500248 hb_apply_context_t *c;
249 unsigned int num_items;
Behdad Esfahbod203d7102012-05-11 16:01:44 +0200250 hb_mask_t mask;
Behdad Esfahbod5f131d32012-05-11 17:29:40 +0200251 uint8_t syllable;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500252 unsigned int end;
253 };
254
255 struct mark_skipping_backward_iterator_t
256 {
257 inline mark_skipping_backward_iterator_t (hb_apply_context_t *c_,
258 unsigned int start_index_,
Behdad Esfahbod203d7102012-05-11 16:01:44 +0200259 unsigned int num_items_,
Behdad Esfahbod5f131d32012-05-11 17:29:40 +0200260 hb_mask_t mask_ = 0,
Behdad Esfahbod6736f3c2012-05-13 15:21:06 +0200261 bool match_syllable_ = true)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500262 {
263 c = c_;
264 idx = start_index_;
265 num_items = num_items_;
Behdad Esfahbod203d7102012-05-11 16:01:44 +0200266 mask = mask_ ? mask_ : c->lookup_mask;
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200267 syllable = match_syllable_ ? c->buffer->cur().syllable () : 0;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500268 }
269 inline bool has_no_chance (void) const
270 {
Behdad Esfahbod506ffeb2012-01-18 16:07:53 -0500271 return unlikely (idx < num_items);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500272 }
Behdad Esfahbodb12e2542012-06-09 03:05:20 -0400273 inline void reject (void)
Behdad Esfahbod7b84c532012-06-08 22:04:23 -0400274 {
275 num_items++;
276 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500277 inline bool prev (unsigned int *property_out,
Behdad Esfahbod89328582012-07-19 21:02:38 -0400278 unsigned int lookup_props)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500279 {
Behdad Esfahbod506ffeb2012-01-18 16:07:53 -0500280 assert (num_items > 0);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500281 do
282 {
283 if (has_no_chance ())
284 return false;
285 idx--;
286 } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->out_info[idx], lookup_props, property_out));
287 num_items--;
Behdad Esfahbod5f131d32012-05-11 17:29:40 +0200288 return (c->buffer->out_info[idx].mask & mask) && (!syllable || syllable == c->buffer->out_info[idx].syllable ());
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500289 }
290 inline bool prev (unsigned int *property_out = NULL)
291 {
292 return prev (property_out, c->lookup_props);
293 }
294
295 unsigned int idx;
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400296 protected:
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500297 hb_apply_context_t *c;
298 unsigned int num_items;
Behdad Esfahbod203d7102012-05-11 16:01:44 +0200299 hb_mask_t mask;
Behdad Esfahbod5f131d32012-05-11 17:29:40 +0200300 uint8_t syllable;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500301 };
302
Behdad Esfahbod7d479902012-01-18 21:19:32 -0500303 inline bool should_mark_skip_current_glyph (void) const
304 {
Behdad Esfahbodce476132012-06-09 01:10:26 -0400305 unsigned int property;
306 return _hb_ot_layout_skip_mark (face, &buffer->cur(), lookup_props, &property);
Behdad Esfahbod7d479902012-01-18 21:19:32 -0500307 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500308
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400309 inline void set_class (hb_codepoint_t glyph_index, unsigned int class_guess) const
Behdad Esfahbod60da7632012-07-16 16:13:32 -0400310 {
Behdad Esfahbod2fca1422012-07-30 18:46:41 -0400311 if (likely (has_glyph_classes))
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400312 buffer->cur().props_cache() = gdef.get_glyph_props (glyph_index);
313 else if (class_guess)
314 buffer->cur().props_cache() = class_guess;
Behdad Esfahbod60da7632012-07-16 16:13:32 -0400315 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500316
Behdad Esfahbod3ec77d62012-06-08 21:44:06 -0400317 inline void output_glyph (hb_codepoint_t glyph_index,
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400318 unsigned int class_guess = 0) const
Behdad Esfahbod3ec77d62012-06-08 21:44:06 -0400319 {
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400320 set_class (glyph_index, class_guess);
Behdad Esfahbod3ec77d62012-06-08 21:44:06 -0400321 buffer->output_glyph (glyph_index);
322 }
Behdad Esfahboded2f1362012-05-22 22:12:22 -0400323 inline void replace_glyph (hb_codepoint_t glyph_index,
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400324 unsigned int class_guess = 0) const
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400325 {
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400326 set_class (glyph_index, class_guess);
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400327 buffer->replace_glyph (glyph_index);
328 }
Behdad Esfahbod7fbbf862012-07-30 18:36:42 -0400329 inline void replace_glyph_inplace (hb_codepoint_t glyph_index,
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400330 unsigned int class_guess = 0) const
Behdad Esfahbod7fbbf862012-07-30 18:36:42 -0400331 {
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400332 set_class (glyph_index, class_guess);
Behdad Esfahbod7fbbf862012-07-30 18:36:42 -0400333 buffer->cur().codepoint = glyph_index;
334 }
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400335};
336
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400337
Behdad Esfahbod94a23aa2010-05-05 01:13:09 -0400338
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400339typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400340typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400341typedef void (*closure_lookup_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400342typedef bool (*apply_lookup_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400343
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400344struct ContextClosureFuncs
345{
346 intersects_func_t intersects;
347 closure_lookup_func_t closure;
348};
349struct ContextApplyFuncs
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400350{
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400351 match_func_t match;
352 apply_lookup_func_t apply;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400353};
354
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400355static inline bool intersects_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400356{
357 return glyphs->has (value);
358}
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400359static inline bool intersects_class (hb_set_t *glyphs, const USHORT &value, const void *data)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400360{
361 const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
362 return class_def.intersects_class (glyphs, value);
363}
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400364static inline bool intersects_coverage (hb_set_t *glyphs, const USHORT &value, const void *data)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400365{
366 const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
367 return (data+coverage).intersects (glyphs);
368}
369
370static inline bool intersects_array (hb_closure_context_t *c,
371 unsigned int count,
372 const USHORT values[],
373 intersects_func_t intersects_func,
374 const void *intersects_data)
375{
376 for (unsigned int i = 0; i < count; i++)
377 if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
378 return false;
379 return true;
380}
381
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400382
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400383static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, const void *data HB_UNUSED)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400384{
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400385 return glyph_id == value;
386}
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400387static inline bool match_class (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400388{
Behdad Esfahbod2b5a59c2009-08-04 11:38:50 -0400389 const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400390 return class_def.get_class (glyph_id) == value;
391}
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400392static inline bool match_coverage (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400393{
Behdad Esfahbod6b54c5d2009-05-18 18:30:25 -0400394 const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400395 return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400396}
397
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400398
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400399static inline bool would_match_input (hb_would_apply_context_t *c,
400 unsigned int count, /* Including the first glyph (not matched) */
401 const USHORT input[], /* Array of input values--start with second glyph */
402 match_func_t match_func,
403 const void *match_data)
404{
405 if (count != c->len)
406 return false;
407
408 for (unsigned int i = 1; i < count; i++)
409 if (likely (!match_func (c->second, input[i - 1], match_data)))
410 return false;
411
412 return true;
413}
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400414static inline bool match_input (hb_apply_context_t *c,
Behdad Esfahbode072c242009-05-18 03:47:31 -0400415 unsigned int count, /* Including the first glyph (not matched) */
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400416 const USHORT input[], /* Array of input values--start with second glyph */
417 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400418 const void *match_data,
Behdad Esfahbod5df809b2012-05-13 15:17:51 +0200419 unsigned int *end_offset = NULL)
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400420{
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500421 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
422 if (skippy_iter.has_no_chance ())
Behdad Esfahbod7cff75b2009-05-18 04:09:05 -0400423 return false;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400424
Behdad Esfahbod370f03e2012-01-16 17:03:55 -0500425 for (unsigned int i = 1; i < count; i++)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400426 {
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500427 if (!skippy_iter.next ())
428 return false;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400429
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500430 if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, input[i - 1], match_data)))
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400431 return false;
432 }
433
Behdad Esfahbod5df809b2012-05-13 15:17:51 +0200434 if (end_offset)
435 *end_offset = skippy_iter.idx - c->buffer->idx + 1;
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400436
437 return true;
438}
439
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400440static inline bool match_backtrack (hb_apply_context_t *c,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400441 unsigned int count,
442 const USHORT backtrack[],
443 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400444 const void *match_data)
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400445{
Behdad Esfahbod28b9d502012-05-13 15:04:00 +0200446 hb_apply_context_t::mark_skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count, true);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500447 if (skippy_iter.has_no_chance ())
448 return false;
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400449
Behdad Esfahbod4d3aeb82012-01-16 16:43:26 -0500450 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400451 {
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500452 if (!skippy_iter.prev ())
453 return false;
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400454
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500455 if (likely (!match_func (c->buffer->out_info[skippy_iter.idx].codepoint, backtrack[i], match_data)))
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400456 return false;
457 }
458
459 return true;
460}
461
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400462static inline bool match_lookahead (hb_apply_context_t *c,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400463 unsigned int count,
464 const USHORT lookahead[],
465 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400466 const void *match_data,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400467 unsigned int offset)
468{
Behdad Esfahbod28b9d502012-05-13 15:04:00 +0200469 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count, true);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500470 if (skippy_iter.has_no_chance ())
471 return false;
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400472
Behdad Esfahbod370f03e2012-01-16 17:03:55 -0500473 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400474 {
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500475 if (!skippy_iter.next ())
476 return false;
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400477
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500478 if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, lookahead[i], match_data)))
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400479 return false;
480 }
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400481
482 return true;
483}
484
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400485
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400486
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400487struct LookupRecord
488{
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400489 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400490 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200491 return TRACE_RETURN (c->check_struct (this));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -0400492 }
493
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400494 USHORT sequenceIndex; /* Index into current glyph
495 * sequence--first glyph = 0 */
496 USHORT lookupListIndex; /* Lookup to apply to that
497 * position--zero--based */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400498 public:
499 DEFINE_SIZE_STATIC (4);
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400500};
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400501
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400502
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400503static inline void closure_lookup (hb_closure_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400504 unsigned int lookupCount,
505 const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
506 closure_lookup_func_t closure_func)
507{
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400508 for (unsigned int i = 0; i < lookupCount; i++)
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400509 closure_func (c, lookupRecord->lookupListIndex);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400510}
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400511
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400512static inline bool apply_lookup (hb_apply_context_t *c,
Behdad Esfahbode072c242009-05-18 03:47:31 -0400513 unsigned int count, /* Including the first glyph */
514 unsigned int lookupCount,
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400515 const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
516 apply_lookup_func_t apply_func)
517{
Behdad Esfahbod5df809b2012-05-13 15:17:51 +0200518 unsigned int end = c->buffer->len;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400519 if (unlikely (count == 0 || c->buffer->idx + count > end))
Behdad Esfahbode73a0c22009-05-18 04:15:25 -0400520 return false;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400521
Behdad Esfahbod7cff75b2009-05-18 04:09:05 -0400522 /* TODO We don't support lookupRecord arrays that are not increasing:
523 * Should be easy for in_place ones at least. */
Behdad Esfahbod52e9a712009-09-21 13:58:56 -0400524
Behdad Esfahbod7eb87512010-12-13 14:13:35 -0500525 /* Note: If sublookup is reverse, it will underflow after the first loop
Behdad Esfahbod52e9a712009-09-21 13:58:56 -0400526 * and we jump out of it. Not entirely disastrous. So we don't check
527 * for reverse lookup here.
528 */
Behdad Esfahbodf9c0a2d2009-09-21 13:43:54 -0400529 for (unsigned int i = 0; i < count; /* NOP */)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400530 {
Behdad Esfahbod03408ce2012-01-18 21:28:34 -0500531 if (unlikely (c->buffer->idx == end))
532 return true;
Behdad Esfahbod7d479902012-01-18 21:19:32 -0500533 while (c->should_mark_skip_current_glyph ())
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400534 {
Behdad Esfahbode73a0c22009-05-18 04:15:25 -0400535 /* No lookup applied for this index */
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400536 c->buffer->next_glyph ();
Behdad Esfahbod03408ce2012-01-18 21:28:34 -0500537 if (unlikely (c->buffer->idx == end))
538 return true;
Behdad Esfahbode73a0c22009-05-18 04:15:25 -0400539 }
540
Behdad Esfahbod47958de2009-05-18 04:17:47 -0400541 if (lookupCount && i == lookupRecord->sequenceIndex)
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400542 {
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400543 unsigned int old_pos = c->buffer->idx;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400544
545 /* Apply a lookup */
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400546 bool done = apply_func (c, lookupRecord->lookupListIndex);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400547
Behdad Esfahbod47958de2009-05-18 04:17:47 -0400548 lookupRecord++;
549 lookupCount--;
Behdad Esfahbodf9c0a2d2009-09-21 13:43:54 -0400550 /* Err, this is wrong if the lookup jumped over some glyphs */
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400551 i += c->buffer->idx - old_pos;
552 if (unlikely (c->buffer->idx == end))
Behdad Esfahbod2e8fb6c2009-05-18 04:37:37 -0400553 return true;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400554
555 if (!done)
556 goto not_applied;
557 }
558 else
559 {
560 not_applied:
561 /* No lookup applied for this index */
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400562 c->buffer->next_glyph ();
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400563 i++;
564 }
565 }
566
567 return true;
568}
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400569
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400570
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400571
572/* Contextual lookups */
573
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400574struct ContextClosureLookupContext
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400575{
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400576 ContextClosureFuncs funcs;
577 const void *intersects_data;
578};
579
580struct ContextApplyLookupContext
581{
582 ContextApplyFuncs funcs;
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400583 const void *match_data;
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400584};
585
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400586static inline void context_closure_lookup (hb_closure_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400587 unsigned int inputCount, /* Including the first glyph (not matched) */
588 const USHORT input[], /* Array of input values--start with second glyph */
589 unsigned int lookupCount,
590 const LookupRecord lookupRecord[],
591 ContextClosureLookupContext &lookup_context)
592{
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400593 if (intersects_array (c,
594 inputCount ? inputCount - 1 : 0, input,
595 lookup_context.funcs.intersects, lookup_context.intersects_data))
596 closure_lookup (c,
597 lookupCount, lookupRecord,
598 lookup_context.funcs.closure);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400599}
600
601
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400602static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
603 unsigned int inputCount, /* Including the first glyph (not matched) */
604 const USHORT input[], /* Array of input values--start with second glyph */
605 unsigned int lookupCount,
606 const LookupRecord lookupRecord[],
607 ContextApplyLookupContext &lookup_context)
608{
609 return would_match_input (c,
610 inputCount, input,
611 lookup_context.funcs.match, lookup_context.match_data);
612}
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400613static inline bool context_apply_lookup (hb_apply_context_t *c,
614 unsigned int inputCount, /* Including the first glyph (not matched) */
615 const USHORT input[], /* Array of input values--start with second glyph */
616 unsigned int lookupCount,
617 const LookupRecord lookupRecord[],
618 ContextApplyLookupContext &lookup_context)
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400619{
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400620 return match_input (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -0400621 inputCount, input,
Behdad Esfahbod5df809b2012-05-13 15:17:51 +0200622 lookup_context.funcs.match, lookup_context.match_data)
623 && apply_lookup (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -0400624 inputCount,
625 lookupCount, lookupRecord,
626 lookup_context.funcs.apply);
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400627}
628
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400629struct Rule
630{
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400631 friend struct RuleSet;
632
633 private:
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400634
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400635 inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400636 {
637 TRACE_CLOSURE ();
638 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400639 context_closure_lookup (c,
640 inputCount, input,
641 lookupCount, lookupRecord,
642 lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400643 }
644
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400645 inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
646 {
647 TRACE_WOULD_APPLY ();
648 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
649 return TRACE_RETURN (context_would_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context));
650 }
651
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400652 inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400653 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400654 TRACE_APPLY ();
Behdad Esfahbode45d3f82010-05-06 19:33:31 -0400655 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200656 return TRACE_RETURN (context_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400657 }
658
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400659 public:
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400660 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400661 TRACE_SANITIZE ();
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400662 return inputCount.sanitize (c)
663 && lookupCount.sanitize (c)
664 && c->check_range (input,
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400665 input[0].static_size * inputCount
666 + lookupRecordX[0].static_size * lookupCount);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400667 }
668
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400669 protected:
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400670 USHORT inputCount; /* Total number of glyphs in input
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400671 * glyph sequence--includes the first
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400672 * glyph */
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400673 USHORT lookupCount; /* Number of LookupRecords */
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -0500674 USHORT input[VAR]; /* Array of match inputs--start with
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400675 * second glyph */
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -0500676 LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400677 * design order */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400678 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400679 DEFINE_SIZE_ARRAY2 (4, input, lookupRecordX);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400680};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400681
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400682struct RuleSet
683{
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400684 inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400685 {
686 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400687 unsigned int num_rules = rule.len;
688 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400689 (this+rule[i]).closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400690 }
691
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400692 inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
693 {
694 TRACE_WOULD_APPLY ();
695 unsigned int num_rules = rule.len;
696 for (unsigned int i = 0; i < num_rules; i++)
697 {
698 if ((this+rule[i]).would_apply (c, lookup_context))
699 return TRACE_RETURN (true);
700 }
701 return TRACE_RETURN (false);
702 }
703
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400704 inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400705 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400706 TRACE_APPLY ();
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400707 unsigned int num_rules = rule.len;
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400708 for (unsigned int i = 0; i < num_rules; i++)
709 {
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400710 if ((this+rule[i]).apply (c, lookup_context))
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200711 return TRACE_RETURN (true);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400712 }
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200713 return TRACE_RETURN (false);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400714 }
715
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400716 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400717 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200718 return TRACE_RETURN (rule.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400719 }
720
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400721 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400722 OffsetArrayOf<Rule>
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400723 rule; /* Array of Rule tables
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400724 * ordered by preference */
Behdad Esfahboded074222010-05-10 18:08:46 -0400725 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400726 DEFINE_SIZE_ARRAY (2, rule);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400727};
728
729
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400730struct ContextFormat1
731{
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400732 friend struct Context;
733
734 private:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400735
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400736 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400737 {
738 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400739
740 const Coverage &cov = (this+coverage);
741
742 struct ContextClosureLookupContext lookup_context = {
743 {intersects_glyph, closure_func},
744 NULL
745 };
746
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400747 unsigned int count = ruleSet.len;
748 for (unsigned int i = 0; i < count; i++)
749 if (cov.intersects_coverage (c->glyphs, i)) {
750 const RuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400751 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400752 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400753 }
754
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400755 inline bool would_apply (hb_would_apply_context_t *c) const
756 {
757 TRACE_WOULD_APPLY ();
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400758
Behdad Esfahbode6f74792012-07-28 18:34:58 -0400759 const RuleSet &rule_set = this+ruleSet[(this+coverage) (c->first)];
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400760 struct ContextApplyLookupContext lookup_context = {
761 {match_glyph, NULL},
762 NULL
763 };
764 return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
765 }
766
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400767 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400768 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400769 TRACE_APPLY ();
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200770 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
Behdad Esfahbod64d3fc82010-05-03 22:51:19 -0400771 if (likely (index == NOT_COVERED))
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200772 return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -0400773
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400774 const RuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400775 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400776 {match_glyph, apply_func},
777 NULL
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400778 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200779 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400780 }
781
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400782 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400783 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200784 return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400785 }
786
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400787 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400788 USHORT format; /* Format identifier--format = 1 */
789 OffsetTo<Coverage>
790 coverage; /* Offset to Coverage table--from
791 * beginning of table */
792 OffsetArrayOf<RuleSet>
793 ruleSet; /* Array of RuleSet tables
794 * ordered by Coverage Index */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400795 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400796 DEFINE_SIZE_ARRAY (6, ruleSet);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400797};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400798
799
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400800struct ContextFormat2
801{
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400802 friend struct Context;
803
804 private:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400805
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400806 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400807 {
808 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400809 if (!(this+coverage).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400810 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400811
812 const ClassDef &class_def = this+classDef;
813
814 struct ContextClosureLookupContext lookup_context = {
815 {intersects_class, closure_func},
816 NULL
817 };
818
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400819 unsigned int count = ruleSet.len;
820 for (unsigned int i = 0; i < count; i++)
821 if (class_def.intersects_class (c->glyphs, i)) {
822 const RuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400823 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400824 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400825 }
826
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400827 inline bool would_apply (hb_would_apply_context_t *c) const
828 {
829 TRACE_WOULD_APPLY ();
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400830
831 const ClassDef &class_def = this+classDef;
Behdad Esfahbode6f74792012-07-28 18:34:58 -0400832 unsigned int index = class_def (c->first);
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400833 const RuleSet &rule_set = this+ruleSet[index];
834 struct ContextApplyLookupContext lookup_context = {
835 {match_class, NULL},
836 &class_def
837 };
838 return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
839 }
840
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400841 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400842 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400843 TRACE_APPLY ();
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200844 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200845 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -0400846
847 const ClassDef &class_def = this+classDef;
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200848 index = class_def (c->buffer->cur().codepoint);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400849 const RuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400850 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400851 {match_class, apply_func},
852 &class_def
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400853 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200854 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400855 }
856
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400857 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400858 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200859 return TRACE_RETURN (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400860 }
861
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400862 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400863 USHORT format; /* Format identifier--format = 2 */
864 OffsetTo<Coverage>
865 coverage; /* Offset to Coverage table--from
866 * beginning of table */
867 OffsetTo<ClassDef>
868 classDef; /* Offset to glyph ClassDef table--from
869 * beginning of table */
870 OffsetArrayOf<RuleSet>
871 ruleSet; /* Array of RuleSet tables
872 * ordered by class */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400873 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400874 DEFINE_SIZE_ARRAY (8, ruleSet);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400875};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400876
877
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400878struct ContextFormat3
879{
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400880 friend struct Context;
881
882 private:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400883
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400884 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400885 {
886 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400887 if (!(this+coverage[0]).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400888 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400889
890 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
891 struct ContextClosureLookupContext lookup_context = {
892 {intersects_coverage, closure_func},
893 this
894 };
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400895 context_closure_lookup (c,
896 glyphCount, (const USHORT *) (coverage + 1),
897 lookupCount, lookupRecord,
898 lookup_context);
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400899 }
900
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400901 inline bool would_apply (hb_would_apply_context_t *c) const
902 {
903 TRACE_WOULD_APPLY ();
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400904
905 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
906 struct ContextApplyLookupContext lookup_context = {
907 {match_coverage, NULL},
908 this
909 };
910 return TRACE_RETURN (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context));
911 }
912
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400913 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400914 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400915 TRACE_APPLY ();
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200916 unsigned int index = (this+coverage[0]) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200917 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -0400918
Behdad Esfahbode45d3f82010-05-06 19:33:31 -0400919 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400920 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400921 {match_coverage, apply_func},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400922 this
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400923 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200924 return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400925 }
926
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400927 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400928 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200929 if (!c->check_struct (this)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400930 unsigned int count = glyphCount;
Behdad Esfahbod09810682012-07-28 17:01:59 -0400931 if (unlikely (!glyphCount)) return TRACE_RETURN (false);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200932 if (!c->check_array (coverage, coverage[0].static_size, count)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400933 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200934 if (!coverage[i].sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode45d3f82010-05-06 19:33:31 -0400935 LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * count);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200936 return TRACE_RETURN (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400937 }
938
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400939 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400940 USHORT format; /* Format identifier--format = 3 */
941 USHORT glyphCount; /* Number of glyphs in the input glyph
942 * sequence */
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400943 USHORT lookupCount; /* Number of LookupRecords */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -0400944 OffsetTo<Coverage>
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -0500945 coverage[VAR]; /* Array of offsets to Coverage
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -0400946 * table in glyph sequence order */
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -0500947 LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400948 * design order */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400949 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400950 DEFINE_SIZE_ARRAY2 (6, coverage, lookupRecordX);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400951};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400952
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400953struct Context
954{
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400955 protected:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400956
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400957 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400958 {
959 TRACE_CLOSURE ();
960 switch (u.format) {
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400961 case 1: u.format1.closure (c, closure_func); break;
962 case 2: u.format2.closure (c, closure_func); break;
963 case 3: u.format3.closure (c, closure_func); break;
964 default: break;
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400965 }
966 }
967
Behdad Esfahbod0b994292012-07-28 17:31:01 -0400968 inline const Coverage &get_coverage (void) const
969 {
970 switch (u.format) {
971 case 1: return this + u.format1.coverage;
972 case 2: return this + u.format2.coverage;
973 case 3: return this + u.format3.coverage[0];
974 default:return Null(Coverage);
975 }
976 }
977
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400978 inline bool would_apply (hb_would_apply_context_t *c) const
979 {
980 switch (u.format) {
981 case 1: return u.format1.would_apply (c);
982 case 2: return u.format2.would_apply (c);
983 case 3: return u.format3.would_apply (c);
984 default:return false;
985 }
986 }
987
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400988 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400989 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400990 TRACE_APPLY ();
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400991 switch (u.format) {
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200992 case 1: return TRACE_RETURN (u.format1.apply (c, apply_func));
993 case 2: return TRACE_RETURN (u.format2.apply (c, apply_func));
994 case 3: return TRACE_RETURN (u.format3.apply (c, apply_func));
995 default:return TRACE_RETURN (false);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400996 }
997 }
998
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400999 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001000 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001001 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001002 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001003 case 1: return TRACE_RETURN (u.format1.sanitize (c));
1004 case 2: return TRACE_RETURN (u.format2.sanitize (c));
1005 case 3: return TRACE_RETURN (u.format3.sanitize (c));
1006 default:return TRACE_RETURN (true);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001007 }
1008 }
1009
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001010 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001011 union {
Behdad Esfahbodf8dc67b2009-05-17 19:47:54 -04001012 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001013 ContextFormat1 format1;
1014 ContextFormat2 format2;
1015 ContextFormat3 format3;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001016 } u;
1017};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001018
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001019
1020/* Chaining Contextual lookups */
1021
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001022struct ChainContextClosureLookupContext
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001023{
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001024 ContextClosureFuncs funcs;
1025 const void *intersects_data[3];
1026};
1027
1028struct ChainContextApplyLookupContext
1029{
1030 ContextApplyFuncs funcs;
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001031 const void *match_data[3];
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001032};
1033
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001034static inline void chain_context_closure_lookup (hb_closure_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001035 unsigned int backtrackCount,
1036 const USHORT backtrack[],
1037 unsigned int inputCount, /* Including the first glyph (not matched) */
1038 const USHORT input[], /* Array of input values--start with second glyph */
1039 unsigned int lookaheadCount,
1040 const USHORT lookahead[],
1041 unsigned int lookupCount,
1042 const LookupRecord lookupRecord[],
1043 ChainContextClosureLookupContext &lookup_context)
1044{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001045 if (intersects_array (c,
1046 backtrackCount, backtrack,
1047 lookup_context.funcs.intersects, lookup_context.intersects_data[0])
1048 && intersects_array (c,
1049 inputCount ? inputCount - 1 : 0, input,
1050 lookup_context.funcs.intersects, lookup_context.intersects_data[1])
1051 && intersects_array (c,
1052 lookaheadCount, lookahead,
1053 lookup_context.funcs.intersects, lookup_context.intersects_data[2]))
1054 closure_lookup (c,
1055 lookupCount, lookupRecord,
1056 lookup_context.funcs.closure);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001057}
1058
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001059static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
1060 unsigned int backtrackCount,
1061 const USHORT backtrack[],
1062 unsigned int inputCount, /* Including the first glyph (not matched) */
1063 const USHORT input[], /* Array of input values--start with second glyph */
1064 unsigned int lookaheadCount,
1065 const USHORT lookahead[],
1066 unsigned int lookupCount,
1067 const LookupRecord lookupRecord[],
1068 ChainContextApplyLookupContext &lookup_context)
1069{
1070 return !backtrackCount
1071 && !lookaheadCount
1072 && would_match_input (c,
1073 inputCount, input,
1074 lookup_context.funcs.match, lookup_context.match_data[1]);
1075}
1076
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001077static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
1078 unsigned int backtrackCount,
1079 const USHORT backtrack[],
1080 unsigned int inputCount, /* Including the first glyph (not matched) */
1081 const USHORT input[], /* Array of input values--start with second glyph */
1082 unsigned int lookaheadCount,
1083 const USHORT lookahead[],
1084 unsigned int lookupCount,
1085 const LookupRecord lookupRecord[],
1086 ChainContextApplyLookupContext &lookup_context)
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001087{
Behdad Esfahbod5df809b2012-05-13 15:17:51 +02001088 unsigned int lookahead_offset;
Behdad Esfahbodf19e0b02012-06-09 02:26:57 -04001089 return match_input (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -04001090 inputCount, input,
1091 lookup_context.funcs.match, lookup_context.match_data[1],
Behdad Esfahbod5df809b2012-05-13 15:17:51 +02001092 &lookahead_offset)
Behdad Esfahbodf19e0b02012-06-09 02:26:57 -04001093 && match_backtrack (c,
1094 backtrackCount, backtrack,
1095 lookup_context.funcs.match, lookup_context.match_data[0])
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001096 && match_lookahead (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -04001097 lookaheadCount, lookahead,
1098 lookup_context.funcs.match, lookup_context.match_data[2],
Behdad Esfahbod5df809b2012-05-13 15:17:51 +02001099 lookahead_offset)
1100 && apply_lookup (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -04001101 inputCount,
1102 lookupCount, lookupRecord,
1103 lookup_context.funcs.apply);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001104}
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001105
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001106struct ChainRule
1107{
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001108 friend struct ChainRuleSet;
1109
1110 private:
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001111
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001112 inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001113 {
1114 TRACE_CLOSURE ();
1115 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
1116 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
1117 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001118 chain_context_closure_lookup (c,
1119 backtrack.len, backtrack.array,
1120 input.len, input.array,
1121 lookahead.len, lookahead.array,
1122 lookup.len, lookup.array,
1123 lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001124 }
1125
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001126 inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
1127 {
1128 TRACE_WOULD_APPLY ();
1129 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
1130 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
1131 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1132 return TRACE_RETURN (chain_context_would_apply_lookup (c,
1133 backtrack.len, backtrack.array,
1134 input.len, input.array,
1135 lookahead.len, lookahead.array, lookup.len,
1136 lookup.array, lookup_context));
1137 }
1138
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001139 inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001140 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001141 TRACE_APPLY ();
Behdad Esfahbode961c862010-04-21 15:56:11 -04001142 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
1143 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
1144 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001145 return TRACE_RETURN (chain_context_apply_lookup (c,
1146 backtrack.len, backtrack.array,
1147 input.len, input.array,
1148 lookahead.len, lookahead.array, lookup.len,
1149 lookup.array, lookup_context));
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001150 }
1151
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001152 public:
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001153 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001154 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001155 if (!backtrack.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001156 HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001157 if (!input.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001158 ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001159 if (!lookahead.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001160 ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001161 return TRACE_RETURN (lookup.sanitize (c));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001162 }
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001163
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001164 protected:
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001165 ArrayOf<USHORT>
1166 backtrack; /* Array of backtracking values
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001167 * (to be matched before the input
1168 * sequence) */
Behdad Esfahbode8cbaaf2009-05-18 02:03:58 -04001169 HeadlessArrayOf<USHORT>
1170 inputX; /* Array of input values (start with
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001171 * second glyph) */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001172 ArrayOf<USHORT>
1173 lookaheadX; /* Array of lookahead values's (to be
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001174 * matched after the input sequence) */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001175 ArrayOf<LookupRecord>
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001176 lookupX; /* Array of LookupRecords--in
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001177 * design order) */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001178 public:
Behdad Esfahbodbea34c72010-05-10 17:28:16 -04001179 DEFINE_SIZE_MIN (8);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001180};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001181
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001182struct ChainRuleSet
1183{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001184 inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001185 {
1186 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001187 unsigned int num_rules = rule.len;
1188 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001189 (this+rule[i]).closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001190 }
1191
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001192 inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
1193 {
1194 TRACE_WOULD_APPLY ();
1195 unsigned int num_rules = rule.len;
1196 for (unsigned int i = 0; i < num_rules; i++)
1197 if ((this+rule[i]).would_apply (c, lookup_context))
1198 return TRACE_RETURN (true);
1199
1200 return TRACE_RETURN (false);
1201 }
1202
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001203 inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001204 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001205 TRACE_APPLY ();
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001206 unsigned int num_rules = rule.len;
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001207 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001208 if ((this+rule[i]).apply (c, lookup_context))
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001209 return TRACE_RETURN (true);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001210
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001211 return TRACE_RETURN (false);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001212 }
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001213
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001214 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001215 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001216 return TRACE_RETURN (rule.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001217 }
1218
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001219 protected:
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001220 OffsetArrayOf<ChainRule>
1221 rule; /* Array of ChainRule tables
1222 * ordered by preference */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001223 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001224 DEFINE_SIZE_ARRAY (2, rule);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001225};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001226
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001227struct ChainContextFormat1
1228{
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001229 friend struct ChainContext;
1230
1231 private:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001232
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001233 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001234 {
1235 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001236 const Coverage &cov = (this+coverage);
1237
1238 struct ChainContextClosureLookupContext lookup_context = {
1239 {intersects_glyph, closure_func},
1240 {NULL, NULL, NULL}
1241 };
1242
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001243 unsigned int count = ruleSet.len;
1244 for (unsigned int i = 0; i < count; i++)
1245 if (cov.intersects_coverage (c->glyphs, i)) {
1246 const ChainRuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001247 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001248 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001249 }
1250
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001251 inline bool would_apply (hb_would_apply_context_t *c) const
1252 {
1253 TRACE_WOULD_APPLY ();
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001254
Behdad Esfahbode6f74792012-07-28 18:34:58 -04001255 const ChainRuleSet &rule_set = this+ruleSet[(this+coverage) (c->first)];
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001256 struct ChainContextApplyLookupContext lookup_context = {
1257 {match_glyph, NULL},
1258 {NULL, NULL, NULL}
1259 };
1260 return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
1261 }
1262
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001263 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001264 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001265 TRACE_APPLY ();
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001266 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001267 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001268
1269 const ChainRuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001270 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001271 {match_glyph, apply_func},
1272 {NULL, NULL, NULL}
1273 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001274 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001275 }
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001276
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001277 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001278 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001279 return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001280 }
1281
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001282 protected:
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001283 USHORT format; /* Format identifier--format = 1 */
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001284 OffsetTo<Coverage>
1285 coverage; /* Offset to Coverage table--from
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001286 * beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001287 OffsetArrayOf<ChainRuleSet>
1288 ruleSet; /* Array of ChainRuleSet tables
1289 * ordered by Coverage Index */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001290 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001291 DEFINE_SIZE_ARRAY (6, ruleSet);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001292};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001293
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001294struct ChainContextFormat2
1295{
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001296 friend struct ChainContext;
1297
1298 private:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001299
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001300 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001301 {
1302 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001303 if (!(this+coverage).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001304 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001305
1306 const ClassDef &backtrack_class_def = this+backtrackClassDef;
1307 const ClassDef &input_class_def = this+inputClassDef;
1308 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
1309
1310 struct ChainContextClosureLookupContext lookup_context = {
1311 {intersects_class, closure_func},
1312 {&backtrack_class_def,
1313 &input_class_def,
1314 &lookahead_class_def}
1315 };
1316
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001317 unsigned int count = ruleSet.len;
1318 for (unsigned int i = 0; i < count; i++)
1319 if (input_class_def.intersects_class (c->glyphs, i)) {
1320 const ChainRuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001321 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001322 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001323 }
1324
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001325 inline bool would_apply (hb_would_apply_context_t *c) const
1326 {
1327 TRACE_WOULD_APPLY ();
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001328
1329 const ClassDef &input_class_def = this+inputClassDef;
1330
Behdad Esfahbode6f74792012-07-28 18:34:58 -04001331 unsigned int index = input_class_def (c->first);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001332 const ChainRuleSet &rule_set = this+ruleSet[index];
1333 struct ChainContextApplyLookupContext lookup_context = {
1334 {match_class, NULL},
1335 {NULL, &input_class_def, NULL}
1336 };
1337 return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
1338 }
1339
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001340 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001341 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001342 TRACE_APPLY ();
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001343 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001344 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001345
1346 const ClassDef &backtrack_class_def = this+backtrackClassDef;
1347 const ClassDef &input_class_def = this+inputClassDef;
1348 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
1349
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001350 index = input_class_def (c->buffer->cur().codepoint);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001351 const ChainRuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001352 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001353 {match_class, apply_func},
1354 {&backtrack_class_def,
1355 &input_class_def,
1356 &lookahead_class_def}
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001357 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001358 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001359 }
1360
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 (coverage.sanitize (c, this) && backtrackClassDef.sanitize (c, this) &&
1364 inputClassDef.sanitize (c, this) && lookaheadClassDef.sanitize (c, this) &&
1365 ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001366 }
1367
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001368 protected:
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001369 USHORT format; /* Format identifier--format = 2 */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001370 OffsetTo<Coverage>
1371 coverage; /* Offset to Coverage table--from
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001372 * beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001373 OffsetTo<ClassDef>
1374 backtrackClassDef; /* Offset to glyph ClassDef table
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001375 * containing backtrack sequence
1376 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001377 OffsetTo<ClassDef>
1378 inputClassDef; /* Offset to glyph ClassDef
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001379 * table containing input sequence
1380 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001381 OffsetTo<ClassDef>
1382 lookaheadClassDef; /* Offset to glyph ClassDef table
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001383 * containing lookahead sequence
1384 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001385 OffsetArrayOf<ChainRuleSet>
1386 ruleSet; /* Array of ChainRuleSet tables
1387 * ordered by class */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001388 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001389 DEFINE_SIZE_ARRAY (12, ruleSet);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001390};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001391
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001392struct ChainContextFormat3
1393{
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001394 friend struct ChainContext;
1395
1396 private:
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001397
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001398 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001399 {
1400 TRACE_CLOSURE ();
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001401 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
1402
1403 if (!(this+input[0]).intersects (c->glyphs))
1404 return;
1405
1406 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
1407 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1408 struct ChainContextClosureLookupContext lookup_context = {
1409 {intersects_coverage, closure_func},
1410 {this, this, this}
1411 };
1412 chain_context_closure_lookup (c,
1413 backtrack.len, (const USHORT *) backtrack.array,
1414 input.len, (const USHORT *) input.array + 1,
1415 lookahead.len, (const USHORT *) lookahead.array,
1416 lookup.len, lookup.array,
1417 lookup_context);
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001418 }
1419
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001420 inline const Coverage &get_coverage (void) const
1421 {
1422 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
1423 return this+input[0];
1424 }
1425
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001426 inline bool would_apply (hb_would_apply_context_t *c) const
1427 {
1428 TRACE_WOULD_APPLY ();
Behdad Esfahbode6f74792012-07-28 18:34:58 -04001429
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001430 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001431 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
1432 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1433 struct ChainContextApplyLookupContext lookup_context = {
1434 {match_coverage, NULL},
1435 {this, this, this}
1436 };
1437 return TRACE_RETURN (chain_context_would_apply_lookup (c,
1438 backtrack.len, (const USHORT *) backtrack.array,
1439 input.len, (const USHORT *) input.array + 1,
1440 lookahead.len, (const USHORT *) lookahead.array,
1441 lookup.len, lookup.array, lookup_context));
1442 }
1443
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001444 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001445 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001446 TRACE_APPLY ();
Behdad Esfahbode961c862010-04-21 15:56:11 -04001447 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001448
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001449 unsigned int index = (this+input[0]) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001450 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001451
Behdad Esfahbode961c862010-04-21 15:56:11 -04001452 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
1453 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001454 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001455 {match_coverage, apply_func},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001456 {this, this, this}
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001457 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001458 return TRACE_RETURN (chain_context_apply_lookup (c,
1459 backtrack.len, (const USHORT *) backtrack.array,
1460 input.len, (const USHORT *) input.array + 1,
1461 lookahead.len, (const USHORT *) lookahead.array,
1462 lookup.len, lookup.array, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001463 }
1464
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001465 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001466 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001467 if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001468 OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001469 if (!input.sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbod09810682012-07-28 17:01:59 -04001470 if (unlikely (!input.len)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001471 OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001472 if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001473 ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001474 return TRACE_RETURN (lookup.sanitize (c));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001475 }
1476
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001477 protected:
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001478 USHORT format; /* Format identifier--format = 3 */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001479 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04001480 backtrack; /* Array of coverage tables
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001481 * in backtracking sequence, in glyph
1482 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001483 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04001484 inputX ; /* Array of coverage
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001485 * tables in input sequence, in glyph
1486 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001487 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04001488 lookaheadX; /* Array of coverage tables
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001489 * in lookahead sequence, in glyph
1490 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001491 ArrayOf<LookupRecord>
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001492 lookupX; /* Array of LookupRecords--in
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001493 * design order) */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001494 public:
Behdad Esfahbodbea34c72010-05-10 17:28:16 -04001495 DEFINE_SIZE_MIN (10);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001496};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001497
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001498struct ChainContext
1499{
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001500 protected:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001501
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001502 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001503 {
1504 TRACE_CLOSURE ();
1505 switch (u.format) {
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001506 case 1: u.format1.closure (c, closure_func); break;
1507 case 2: u.format2.closure (c, closure_func); break;
1508 case 3: u.format3.closure (c, closure_func); break;
1509 default: break;
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001510 }
1511 }
1512
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001513 inline const Coverage &get_coverage (void) const
1514 {
1515 switch (u.format) {
1516 case 1: return this + u.format1.coverage;
1517 case 2: return this + u.format2.coverage;
1518 case 3: return u.format3.get_coverage ();
1519 default:return Null(Coverage);
1520 }
1521 }
1522
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001523 inline bool would_apply (hb_would_apply_context_t *c) const
1524 {
1525 switch (u.format) {
1526 case 1: return u.format1.would_apply (c);
1527 case 2: return u.format2.would_apply (c);
1528 case 3: return u.format3.would_apply (c);
1529 default:return false;
1530 }
1531 }
1532
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001533 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001534 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001535 TRACE_APPLY ();
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001536 switch (u.format) {
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001537 case 1: return TRACE_RETURN (u.format1.apply (c, apply_func));
1538 case 2: return TRACE_RETURN (u.format2.apply (c, apply_func));
1539 case 3: return TRACE_RETURN (u.format3.apply (c, apply_func));
1540 default:return TRACE_RETURN (false);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001541 }
1542 }
1543
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001544 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001545 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001546 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001547 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001548 case 1: return TRACE_RETURN (u.format1.sanitize (c));
1549 case 2: return TRACE_RETURN (u.format2.sanitize (c));
1550 case 3: return TRACE_RETURN (u.format3.sanitize (c));
1551 default:return TRACE_RETURN (true);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001552 }
1553 }
1554
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001555 protected:
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001556 union {
1557 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001558 ChainContextFormat1 format1;
1559 ChainContextFormat2 format2;
1560 ChainContextFormat3 format3;
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001561 } u;
1562};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001563
1564
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001565struct ExtensionFormat1
1566{
Behdad Esfahbod6d08c7f2012-07-11 18:01:27 -04001567 friend struct Extension;
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001568
Behdad Esfahbod18939482009-08-04 14:27:56 -04001569 protected:
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001570 inline unsigned int get_type (void) const { return extensionLookupType; }
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -04001571 inline unsigned int get_offset (void) const { return extensionOffset; }
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001572
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001573 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001574 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001575 return TRACE_RETURN (c->check_struct (this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001576 }
1577
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001578 protected:
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001579 USHORT format; /* Format identifier. Set to 1. */
1580 USHORT extensionLookupType; /* Lookup type of subtable referenced
1581 * by ExtensionOffset (i.e. the
1582 * extension subtable). */
Behdad Esfahbod81f2af42010-04-22 00:58:49 -04001583 ULONG extensionOffset; /* Offset to the extension subtable,
1584 * of lookup type subtable. */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001585 public:
1586 DEFINE_SIZE_STATIC (8);
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001587};
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001588
1589struct Extension
1590{
1591 inline unsigned int get_type (void) const
1592 {
1593 switch (u.format) {
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001594 case 1: return u.format1.get_type ();
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001595 default:return 0;
1596 }
1597 }
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -04001598 inline unsigned int get_offset (void) const
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001599 {
1600 switch (u.format) {
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001601 case 1: return u.format1.get_offset ();
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -04001602 default:return 0;
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001603 }
1604 }
1605
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001606 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001607 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001608 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001609 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001610 case 1: return TRACE_RETURN (u.format1.sanitize (c));
1611 default:return TRACE_RETURN (true);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001612 }
1613 }
1614
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001615 protected:
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001616 union {
1617 USHORT format; /* Format identifier */
Behdad Esfahbod6d08c7f2012-07-11 18:01:27 -04001618 ExtensionFormat1 format1;
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001619 } u;
1620};
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001621
1622
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001623/*
1624 * GSUB/GPOS Common
1625 */
1626
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001627struct GSUBGPOS
1628{
Behdad Esfahboda328d662009-08-04 20:27:05 -04001629 static const hb_tag_t GSUBTag = HB_OT_TAG_GSUB;
1630 static const hb_tag_t GPOSTag = HB_OT_TAG_GPOS;
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001631
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04001632 inline unsigned int get_script_count (void) const
1633 { return (this+scriptList).len; }
1634 inline const Tag& get_script_tag (unsigned int i) const
1635 { return (this+scriptList).get_tag (i); }
Behdad Esfahbode21899b2009-11-04 16:36:14 -05001636 inline unsigned int get_script_tags (unsigned int start_offset,
1637 unsigned int *script_count /* IN/OUT */,
1638 hb_tag_t *script_tags /* OUT */) const
1639 { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04001640 inline const Script& get_script (unsigned int i) const
1641 { return (this+scriptList)[i]; }
1642 inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
1643 { return (this+scriptList).find_index (tag, index); }
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001644
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04001645 inline unsigned int get_feature_count (void) const
1646 { return (this+featureList).len; }
1647 inline const Tag& get_feature_tag (unsigned int i) const
1648 { return (this+featureList).get_tag (i); }
Behdad Esfahbode21899b2009-11-04 16:36:14 -05001649 inline unsigned int get_feature_tags (unsigned int start_offset,
1650 unsigned int *feature_count /* IN/OUT */,
1651 hb_tag_t *feature_tags /* OUT */) const
1652 { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04001653 inline const Feature& get_feature (unsigned int i) const
1654 { return (this+featureList)[i]; }
1655 inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
1656 { return (this+featureList).find_index (tag, index); }
1657
1658 inline unsigned int get_lookup_count (void) const
1659 { return (this+lookupList).len; }
1660 inline const Lookup& get_lookup (unsigned int i) const
1661 { return (this+lookupList)[i]; }
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001662
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001663 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001664 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001665 return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) &&
1666 scriptList.sanitize (c, this) &&
1667 featureList.sanitize (c, this) &&
1668 lookupList.sanitize (c, this));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -04001669 }
1670
Behdad Esfahbod212aba62009-05-24 00:50:27 -04001671 protected:
Behdad Esfahbod87fcdcb2009-05-24 01:03:24 -04001672 FixedVersion version; /* Version of the GSUB/GPOS table--initially set
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001673 * to 0x00010000 */
1674 OffsetTo<ScriptList>
1675 scriptList; /* ScriptList table */
1676 OffsetTo<FeatureList>
1677 featureList; /* FeatureList table */
1678 OffsetTo<LookupList>
1679 lookupList; /* LookupList table */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001680 public:
1681 DEFINE_SIZE_STATIC (10);
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001682};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001683
Behdad Esfahbod6f20f722009-05-17 20:28:01 -04001684
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -04001685
Behdad Esfahbod5f5b24f2009-08-02 20:03:12 -04001686#endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */