blob: 66e37a670d82b8566d90dbac4dec97a77aac7b68 [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 Esfahbod1336ecd2012-08-01 21:46:36 -040034#include "hb-set-private.hh"
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040035
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -040036
Behdad Esfahbod7c8e8442012-08-28 17:57:49 -040037namespace OT {
38
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -040039
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040040#ifndef HB_DEBUG_CLOSURE
41#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
42#endif
43
44#define TRACE_CLOSURE() \
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +020045 hb_auto_trace_t<HB_DEBUG_CLOSURE> trace (&c->debug_depth, "CLOSURE", this, HB_FUNC, "");
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040046
47
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040048struct hb_closure_context_t
49{
50 hb_face_t *face;
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -040051 hb_set_t *glyphs;
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040052 unsigned int nesting_level_left;
53 unsigned int debug_depth;
54
55
56 hb_closure_context_t (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_ = MAX_NESTING_LEVEL) :
Behdad Esfahbode72b3602012-07-19 14:35:23 -040059 face (face_),
60 glyphs (glyphs_),
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040061 nesting_level_left (nesting_level_left_),
62 debug_depth (0) {}
63};
64
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040065
66
Behdad Esfahbod472f2292012-08-07 22:25:24 -040067/* TODO Add TRACE_RETURN annotation to gsub. */
68#ifndef HB_DEBUG_WOULD_APPLY
69#define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
70#endif
71
72#define TRACE_WOULD_APPLY() \
73 hb_auto_trace_t<HB_DEBUG_WOULD_APPLY> trace (&c->debug_depth, "WOULD_APPLY", this, HB_FUNC, "%d glyphs", c->len);
74
Behdad Esfahbode72b3602012-07-19 14:35:23 -040075
76struct hb_would_apply_context_t
77{
78 hb_face_t *face;
Behdad Esfahbod472f2292012-08-07 22:25:24 -040079 const hb_codepoint_t *glyphs;
Behdad Esfahbode72b3602012-07-19 14:35:23 -040080 unsigned int len;
Behdad Esfahbodd9b204d2012-08-23 16:22:28 -040081 bool zero_context;
Behdad Esfahbode72b3602012-07-19 14:35:23 -040082 unsigned int debug_depth;
83
84 hb_would_apply_context_t (hb_face_t *face_,
Behdad Esfahbod472f2292012-08-07 22:25:24 -040085 const hb_codepoint_t *glyphs_,
86 unsigned int len_,
Behdad Esfahbod2bd9fe32012-09-04 15:15:19 -040087 bool zero_context_) :
Behdad Esfahbode72b3602012-07-19 14:35:23 -040088 face (face_),
Behdad Esfahbod472f2292012-08-07 22:25:24 -040089 glyphs (glyphs_),
90 len (len_),
Behdad Esfahbodd9b204d2012-08-23 16:22:28 -040091 zero_context (zero_context_),
Behdad Esfahbode72b3602012-07-19 14:35:23 -040092 debug_depth (0) {};
93};
94
95
Behdad Esfahbod0535b502009-08-28 17:14:33 -040096#ifndef HB_DEBUG_APPLY
Behdad Esfahbod11e3ec42010-11-03 15:11:04 -040097#define HB_DEBUG_APPLY (HB_DEBUG+0)
Behdad Esfahbod0535b502009-08-28 17:14:33 -040098#endif
99
Behdad Esfahbodbc200452010-04-29 01:40:26 -0400100#define TRACE_APPLY() \
Behdad Esfahbod68b76122012-06-08 10:43:49 -0400101 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 -0400102
Behdad Esfahbod0535b502009-08-28 17:14:33 -0400103
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400104struct hb_apply_context_t
105{
Behdad Esfahbodabcfe9b2011-05-11 00:02:02 -0400106 hb_font_t *font;
107 hb_face_t *face;
Behdad Esfahbod94a23aa2010-05-05 01:13:09 -0400108 hb_buffer_t *buffer;
Behdad Esfahbod744970a2011-05-16 18:15:37 -0400109 hb_direction_t direction;
Behdad Esfahbodf7acd8d2010-05-20 17:26:35 +0100110 hb_mask_t lookup_mask;
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400111 unsigned int nesting_level_left;
Behdad Esfahbod8c69e652010-10-27 22:07:49 -0400112 unsigned int lookup_props;
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400113 unsigned int property; /* propety of first glyph */
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400114 unsigned int debug_depth;
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400115 const GDEF &gdef;
Behdad Esfahbod300c7302012-07-30 19:37:44 -0400116 bool has_glyph_classes;
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400117
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400118
119 hb_apply_context_t (hb_font_t *font_,
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400120 hb_buffer_t *buffer_,
Behdad Esfahbod2bd9fe32012-09-04 15:15:19 -0400121 hb_mask_t lookup_mask_) :
Behdad Esfahbodafbcc242012-08-02 08:36:40 -0400122 font (font_), face (font->face), buffer (buffer_),
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400123 direction (buffer_->props.direction),
124 lookup_mask (lookup_mask_),
Behdad Esfahbod6736f3c2012-05-13 15:21:06 +0200125 nesting_level_left (MAX_NESTING_LEVEL),
Behdad Esfahbod60da7632012-07-16 16:13:32 -0400126 lookup_props (0), property (0), debug_depth (0),
Behdad Esfahbodafbcc242012-08-02 08:36:40 -0400127 gdef (*hb_ot_layout_from_face (face)->gdef),
Behdad Esfahbod2bd9fe32012-09-04 15:15:19 -0400128 has_glyph_classes (gdef.has_glyph_classes ()) {}
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400129
Behdad Esfahbod2fcbbdb2012-08-29 11:11:54 -0400130 void set_lookup_props (unsigned int lookup_props_) {
131 lookup_props = lookup_props_;
132 }
133
Behdad Esfahbod650ac002012-04-23 13:17:09 -0400134 void set_lookup (const Lookup &l) {
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400135 lookup_props = l.get_props ();
136 }
137
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500138 struct mark_skipping_forward_iterator_t
139 {
140 inline mark_skipping_forward_iterator_t (hb_apply_context_t *c_,
141 unsigned int start_index_,
Behdad Esfahbod203d7102012-05-11 16:01:44 +0200142 unsigned int num_items_,
Behdad Esfahbod28b9d502012-05-13 15:04:00 +0200143 bool context_match = false)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500144 {
145 c = c_;
146 idx = start_index_;
147 num_items = num_items_;
Behdad Esfahbod28b9d502012-05-13 15:04:00 +0200148 mask = context_match ? -1 : c->lookup_mask;
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200149 syllable = context_match ? 0 : c->buffer->cur().syllable ();
Behdad Esfahbod5df809b2012-05-13 15:17:51 +0200150 end = c->buffer->len;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500151 }
152 inline bool has_no_chance (void) const
153 {
154 return unlikely (num_items && idx + num_items >= end);
155 }
Behdad Esfahbodb12e2542012-06-09 03:05:20 -0400156 inline void reject (void)
Behdad Esfahbod7b84c532012-06-08 22:04:23 -0400157 {
158 num_items++;
159 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500160 inline bool next (unsigned int *property_out,
Behdad Esfahbod89328582012-07-19 21:02:38 -0400161 unsigned int lookup_props)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500162 {
Behdad Esfahbod506ffeb2012-01-18 16:07:53 -0500163 assert (num_items > 0);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500164 do
165 {
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500166 if (has_no_chance ())
167 return false;
Behdad Esfahboda4a48fe2012-01-17 18:08:41 -0500168 idx++;
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400169 } while (c->should_skip_mark (&c->buffer->info[idx], lookup_props, property_out));
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500170 num_items--;
Behdad Esfahbod5f131d32012-05-11 17:29:40 +0200171 return (c->buffer->info[idx].mask & mask) && (!syllable || syllable == c->buffer->info[idx].syllable ());
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500172 }
173 inline bool next (unsigned int *property_out = NULL)
174 {
175 return next (property_out, c->lookup_props);
176 }
177
178 unsigned int idx;
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400179 protected:
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500180 hb_apply_context_t *c;
181 unsigned int num_items;
Behdad Esfahbod203d7102012-05-11 16:01:44 +0200182 hb_mask_t mask;
Behdad Esfahbod5f131d32012-05-11 17:29:40 +0200183 uint8_t syllable;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500184 unsigned int end;
185 };
186
187 struct mark_skipping_backward_iterator_t
188 {
189 inline mark_skipping_backward_iterator_t (hb_apply_context_t *c_,
190 unsigned int start_index_,
Behdad Esfahbod203d7102012-05-11 16:01:44 +0200191 unsigned int num_items_,
Behdad Esfahbod5f131d32012-05-11 17:29:40 +0200192 hb_mask_t mask_ = 0,
Behdad Esfahbod6736f3c2012-05-13 15:21:06 +0200193 bool match_syllable_ = true)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500194 {
195 c = c_;
196 idx = start_index_;
197 num_items = num_items_;
Behdad Esfahbod203d7102012-05-11 16:01:44 +0200198 mask = mask_ ? mask_ : c->lookup_mask;
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200199 syllable = match_syllable_ ? c->buffer->cur().syllable () : 0;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500200 }
201 inline bool has_no_chance (void) const
202 {
Behdad Esfahbod506ffeb2012-01-18 16:07:53 -0500203 return unlikely (idx < num_items);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500204 }
Behdad Esfahbodb12e2542012-06-09 03:05:20 -0400205 inline void reject (void)
Behdad Esfahbod7b84c532012-06-08 22:04:23 -0400206 {
207 num_items++;
208 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500209 inline bool prev (unsigned int *property_out,
Behdad Esfahbod89328582012-07-19 21:02:38 -0400210 unsigned int lookup_props)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500211 {
Behdad Esfahbod506ffeb2012-01-18 16:07:53 -0500212 assert (num_items > 0);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500213 do
214 {
215 if (has_no_chance ())
216 return false;
217 idx--;
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400218 } while (c->should_skip_mark (&c->buffer->out_info[idx], lookup_props, property_out));
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500219 num_items--;
Behdad Esfahbod5f131d32012-05-11 17:29:40 +0200220 return (c->buffer->out_info[idx].mask & mask) && (!syllable || syllable == c->buffer->out_info[idx].syllable ());
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500221 }
222 inline bool prev (unsigned int *property_out = NULL)
223 {
224 return prev (property_out, c->lookup_props);
225 }
226
227 unsigned int idx;
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400228 protected:
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500229 hb_apply_context_t *c;
230 unsigned int num_items;
Behdad Esfahbod203d7102012-05-11 16:01:44 +0200231 hb_mask_t mask;
Behdad Esfahbod5f131d32012-05-11 17:29:40 +0200232 uint8_t syllable;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500233 };
234
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400235 inline bool
236 match_properties_mark (hb_codepoint_t glyph,
237 unsigned int glyph_props,
238 unsigned int lookup_props) const
239 {
240 /* If using mark filtering sets, the high short of
241 * lookup_props has the set index.
242 */
243 if (lookup_props & LookupFlag::UseMarkFilteringSet)
244 return gdef.mark_set_covers (lookup_props >> 16, glyph);
245
246 /* The second byte of lookup_props has the meaning
247 * "ignore marks of attachment type different than
248 * the attachment type specified."
249 */
250 if (lookup_props & LookupFlag::MarkAttachmentType)
251 return (lookup_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
252
253 return true;
254 }
255
256 inline bool
257 match_properties (hb_codepoint_t glyph,
258 unsigned int glyph_props,
259 unsigned int lookup_props) const
260 {
261 /* Not covered, if, for example, glyph class is ligature and
262 * lookup_props includes LookupFlags::IgnoreLigatures
263 */
264 if (glyph_props & lookup_props & LookupFlag::IgnoreFlags)
265 return false;
266
Behdad Esfahbod5a08ecf2012-11-16 13:34:29 -0800267 if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400268 return match_properties_mark (glyph, glyph_props, lookup_props);
269
270 return true;
271 }
272
273 inline bool
274 check_glyph_property (hb_glyph_info_t *info,
275 unsigned int lookup_props,
276 unsigned int *property_out) const
Behdad Esfahbod7d479902012-01-18 21:19:32 -0500277 {
Behdad Esfahbodce476132012-06-09 01:10:26 -0400278 unsigned int property;
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400279
Behdad Esfahbodc2e42c32012-07-30 19:54:50 -0400280 property = info->glyph_props();
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400281 *property_out = property;
282
283 return match_properties (info->codepoint, property, lookup_props);
284 }
285
286 inline bool
287 should_skip_mark (hb_glyph_info_t *info,
288 unsigned int lookup_props,
289 unsigned int *property_out) const
290 {
291 unsigned int property;
292
Behdad Esfahbodc2e42c32012-07-30 19:54:50 -0400293 property = info->glyph_props();
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400294 if (property_out)
295 *property_out = property;
296
297 /* If it's a mark, skip it if we don't accept it. */
Behdad Esfahbod5a08ecf2012-11-16 13:34:29 -0800298 if (unlikely (property & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400299 return !match_properties (info->codepoint, property, lookup_props);
300
301 /* If not a mark, don't skip. */
302 return false;
303 }
304
305
306 inline bool should_mark_skip_current_glyph (void) const
307 {
308 return should_skip_mark (&buffer->cur(), lookup_props, NULL);
Behdad Esfahbod7d479902012-01-18 21:19:32 -0500309 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500310
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400311 inline void set_class (hb_codepoint_t glyph_index, unsigned int class_guess) const
Behdad Esfahbod60da7632012-07-16 16:13:32 -0400312 {
Behdad Esfahbod2fca1422012-07-30 18:46:41 -0400313 if (likely (has_glyph_classes))
Behdad Esfahbodc2e42c32012-07-30 19:54:50 -0400314 buffer->cur().glyph_props() = gdef.get_glyph_props (glyph_index);
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400315 else if (class_guess)
Behdad Esfahbodc2e42c32012-07-30 19:54:50 -0400316 buffer->cur().glyph_props() = class_guess;
Behdad Esfahbod60da7632012-07-16 16:13:32 -0400317 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500318
Behdad Esfahbod3ec77d62012-06-08 21:44:06 -0400319 inline void output_glyph (hb_codepoint_t glyph_index,
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400320 unsigned int class_guess = 0) const
Behdad Esfahbod3ec77d62012-06-08 21:44:06 -0400321 {
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400322 set_class (glyph_index, class_guess);
Behdad Esfahbod3ec77d62012-06-08 21:44:06 -0400323 buffer->output_glyph (glyph_index);
324 }
Behdad Esfahboded2f1362012-05-22 22:12:22 -0400325 inline void replace_glyph (hb_codepoint_t glyph_index,
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400326 unsigned int class_guess = 0) const
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400327 {
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400328 set_class (glyph_index, class_guess);
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400329 buffer->replace_glyph (glyph_index);
330 }
Behdad Esfahbod7fbbf862012-07-30 18:36:42 -0400331 inline void replace_glyph_inplace (hb_codepoint_t glyph_index,
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400332 unsigned int class_guess = 0) const
Behdad Esfahbod7fbbf862012-07-30 18:36:42 -0400333 {
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400334 set_class (glyph_index, class_guess);
Behdad Esfahbod7fbbf862012-07-30 18:36:42 -0400335 buffer->cur().codepoint = glyph_index;
336 }
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400337};
338
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400339
Behdad Esfahbod94a23aa2010-05-05 01:13:09 -0400340
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400341typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400342typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400343typedef void (*closure_lookup_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400344typedef bool (*apply_lookup_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400345
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400346struct ContextClosureFuncs
347{
348 intersects_func_t intersects;
349 closure_lookup_func_t closure;
350};
351struct ContextApplyFuncs
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400352{
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400353 match_func_t match;
354 apply_lookup_func_t apply;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400355};
356
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400357static inline bool intersects_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400358{
359 return glyphs->has (value);
360}
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400361static inline bool intersects_class (hb_set_t *glyphs, const USHORT &value, const void *data)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400362{
363 const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
364 return class_def.intersects_class (glyphs, value);
365}
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400366static inline bool intersects_coverage (hb_set_t *glyphs, const USHORT &value, const void *data)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400367{
368 const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
369 return (data+coverage).intersects (glyphs);
370}
371
372static inline bool intersects_array (hb_closure_context_t *c,
373 unsigned int count,
374 const USHORT values[],
375 intersects_func_t intersects_func,
376 const void *intersects_data)
377{
378 for (unsigned int i = 0; i < count; i++)
379 if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
380 return false;
381 return true;
382}
383
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400384
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400385static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, const void *data HB_UNUSED)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400386{
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400387 return glyph_id == value;
388}
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400389static inline bool match_class (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400390{
Behdad Esfahbod2b5a59c2009-08-04 11:38:50 -0400391 const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400392 return class_def.get_class (glyph_id) == value;
393}
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400394static inline bool match_coverage (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400395{
Behdad Esfahbod6b54c5d2009-05-18 18:30:25 -0400396 const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400397 return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400398}
399
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400400
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400401static inline bool would_match_input (hb_would_apply_context_t *c,
402 unsigned int count, /* Including the first glyph (not matched) */
403 const USHORT input[], /* Array of input values--start with second glyph */
404 match_func_t match_func,
405 const void *match_data)
406{
407 if (count != c->len)
408 return false;
409
410 for (unsigned int i = 1; i < count; i++)
Behdad Esfahbod472f2292012-08-07 22:25:24 -0400411 if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400412 return false;
413
414 return true;
415}
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400416static inline bool match_input (hb_apply_context_t *c,
Behdad Esfahbode072c242009-05-18 03:47:31 -0400417 unsigned int count, /* Including the first glyph (not matched) */
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400418 const USHORT input[], /* Array of input values--start with second glyph */
419 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400420 const void *match_data,
Behdad Esfahbod191fa882012-08-28 22:58:55 -0400421 unsigned int *end_offset = NULL,
422 bool *p_is_mark_ligature = NULL,
423 unsigned int *p_total_component_count = NULL)
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400424{
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400425 hb_auto_trace_t<HB_DEBUG_APPLY> trace (&c->debug_depth, "APPLY", NULL, HB_FUNC, "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint);
426
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500427 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400428 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
429
Behdad Esfahbod191fa882012-08-28 22:58:55 -0400430 /*
431 * This is perhaps the trickiest part of OpenType... Remarks:
432 *
433 * - If all components of the ligature were marks, we call this a mark ligature.
434 *
435 * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
436 * it as a ligature glyph.
437 *
438 * - Ligatures cannot be formed across glyphs attached to different components
439 * of previous ligatures. Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
440 * LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
441 * However, it would be wrong to ligate that SHADDA,FATHA sequence.o
442 * There is an exception to this: If a ligature tries ligating with marks that
443 * belong to it itself, go ahead, assuming that the font designer knows what
444 * they are doing (otherwise it can break Indic stuff when a matra wants to
445 * ligate with a conjunct...)
446 */
447
Behdad Esfahbod5a08ecf2012-11-16 13:34:29 -0800448 bool is_mark_ligature = !!(c->property & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400449
450 unsigned int total_component_count = 0;
451 total_component_count += get_lig_num_comps (c->buffer->cur());
452
453 unsigned int first_lig_id = get_lig_id (c->buffer->cur());
454 unsigned int first_lig_comp = get_lig_comp (c->buffer->cur());
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400455
Behdad Esfahbod370f03e2012-01-16 17:03:55 -0500456 for (unsigned int i = 1; i < count; i++)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400457 {
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400458 unsigned int property;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400459
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400460 if (!skippy_iter.next (&property)) return TRACE_RETURN (false);
461
Behdad Esfahbod26166892012-10-29 21:51:56 -0700462 if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, input[i - 1], match_data))) return TRACE_RETURN (false);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400463
464 unsigned int this_lig_id = get_lig_id (c->buffer->info[skippy_iter.idx]);
465 unsigned int this_lig_comp = get_lig_comp (c->buffer->info[skippy_iter.idx]);
466
467 if (first_lig_id && first_lig_comp) {
468 /* If first component was attached to a previous ligature component,
469 * all subsequent components should be attached to the same ligature
470 * component, otherwise we shouldn't ligate them. */
471 if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
472 return TRACE_RETURN (false);
473 } else {
474 /* If first component was NOT attached to a previous ligature component,
475 * all subsequent components should also NOT be attached to any ligature
476 * component, unless they are attached to the first component itself! */
477 if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
478 return TRACE_RETURN (false);
479 }
480
Behdad Esfahbod5a08ecf2012-11-16 13:34:29 -0800481 is_mark_ligature = is_mark_ligature && (property & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400482 total_component_count += get_lig_num_comps (c->buffer->info[skippy_iter.idx]);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400483 }
484
Behdad Esfahbod5df809b2012-05-13 15:17:51 +0200485 if (end_offset)
486 *end_offset = skippy_iter.idx - c->buffer->idx + 1;
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400487
Behdad Esfahbod191fa882012-08-28 22:58:55 -0400488 if (p_is_mark_ligature)
489 *p_is_mark_ligature = is_mark_ligature;
490
491 if (p_total_component_count)
492 *p_total_component_count = total_component_count;
493
Behdad Esfahbodbc513ad2012-10-29 19:03:55 -0700494 return TRACE_RETURN (true);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400495}
Behdad Esfahboda177d022012-08-28 23:18:22 -0400496static inline void ligate_input (hb_apply_context_t *c,
497 unsigned int count, /* Including the first glyph (not matched) */
498 const USHORT input[], /* Array of input values--start with second glyph */
499 hb_codepoint_t lig_glyph,
500 match_func_t match_func,
501 const void *match_data,
Behdad Esfahboda177d022012-08-28 23:18:22 -0400502 bool is_mark_ligature,
503 unsigned int total_component_count)
504{
505 /*
506 * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave
507 * the ligature to keep its old ligature id. This will allow it to attach to
508 * a base ligature in GPOS. Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
509 * and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA wit a
510 * ligature id and component value of 2. Then if SHADDA,FATHA form a ligature
511 * later, we don't want them to lose their ligature id/component, otherwise
512 * GPOS will fail to correctly position the mark ligature on top of the
513 * LAM,LAM,HEH ligature. See:
514 * https://bugzilla.gnome.org/show_bug.cgi?id=676343
515 *
516 * - If a ligature is formed of components that some of which are also ligatures
517 * themselves, and those ligature components had marks attached to *their*
518 * components, we have to attach the marks to the new ligature component
519 * positions! Now *that*'s tricky! And these marks may be following the
520 * last component of the whole sequence, so we should loop forward looking
521 * for them and update them.
522 *
523 * Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
524 * 'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
525 * id and component == 1. Now, during 'liga', the LAM and the LAM-HEH ligature
526 * form a LAM-LAM-HEH ligature. We need to reassign the SHADDA and FATHA to
527 * the new ligature with a component value of 2.
528 *
529 * This in fact happened to a font... See:
530 * https://bugzilla.gnome.org/show_bug.cgi?id=437633
531 */
532
Behdad Esfahbod5a08ecf2012-11-16 13:34:29 -0800533 unsigned int klass = is_mark_ligature ? 0 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
Behdad Esfahboda177d022012-08-28 23:18:22 -0400534 unsigned int lig_id = is_mark_ligature ? 0 : allocate_lig_id (c->buffer);
535 unsigned int last_lig_id = get_lig_id (c->buffer->cur());
536 unsigned int last_num_components = get_lig_num_comps (c->buffer->cur());
537 unsigned int components_so_far = last_num_components;
538
539 if (!is_mark_ligature)
540 set_lig_props_for_ligature (c->buffer->cur(), lig_id, total_component_count);
541 c->replace_glyph (lig_glyph, klass);
542
543 for (unsigned int i = 1; i < count; i++)
544 {
545 while (c->should_mark_skip_current_glyph ())
546 {
547 if (!is_mark_ligature) {
548 unsigned int new_lig_comp = components_so_far - last_num_components +
549 MIN (MAX (get_lig_comp (c->buffer->cur()), 1u), last_num_components);
550 set_lig_props_for_mark (c->buffer->cur(), lig_id, new_lig_comp);
551 }
552 c->buffer->next_glyph ();
553 }
554
555 last_lig_id = get_lig_id (c->buffer->cur());
556 last_num_components = get_lig_num_comps (c->buffer->cur());
557 components_so_far += last_num_components;
558
559 /* Skip the base glyph */
560 c->buffer->idx++;
561 }
562
563 if (!is_mark_ligature && last_lig_id) {
564 /* Re-adjust components for any marks following. */
565 for (unsigned int i = c->buffer->idx; i < c->buffer->len; i++) {
566 if (last_lig_id == get_lig_id (c->buffer->info[i])) {
567 unsigned int new_lig_comp = components_so_far - last_num_components +
568 MIN (MAX (get_lig_comp (c->buffer->info[i]), 1u), last_num_components);
569 set_lig_props_for_mark (c->buffer->info[i], lig_id, new_lig_comp);
570 } else
571 break;
572 }
573 }
574}
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400575
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400576static inline bool match_backtrack (hb_apply_context_t *c,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400577 unsigned int count,
578 const USHORT backtrack[],
579 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400580 const void *match_data)
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400581{
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400582 hb_auto_trace_t<HB_DEBUG_APPLY> trace (&c->debug_depth, "APPLY", NULL, HB_FUNC, "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint);
583
Behdad Esfahbod28b9d502012-05-13 15:04:00 +0200584 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 -0500585 if (skippy_iter.has_no_chance ())
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400586 return TRACE_RETURN (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400587
Behdad Esfahbod4d3aeb82012-01-16 16:43:26 -0500588 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400589 {
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500590 if (!skippy_iter.prev ())
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400591 return TRACE_RETURN (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400592
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500593 if (likely (!match_func (c->buffer->out_info[skippy_iter.idx].codepoint, backtrack[i], match_data)))
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400594 return TRACE_RETURN (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400595 }
596
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400597 return TRACE_RETURN (true);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400598}
599
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400600static inline bool match_lookahead (hb_apply_context_t *c,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400601 unsigned int count,
602 const USHORT lookahead[],
603 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400604 const void *match_data,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400605 unsigned int offset)
606{
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400607 hb_auto_trace_t<HB_DEBUG_APPLY> trace (&c->debug_depth, "APPLY", NULL, HB_FUNC, "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint);
608
Behdad Esfahbod28b9d502012-05-13 15:04:00 +0200609 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 -0500610 if (skippy_iter.has_no_chance ())
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400611 return TRACE_RETURN (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400612
Behdad Esfahbod370f03e2012-01-16 17:03:55 -0500613 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400614 {
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500615 if (!skippy_iter.next ())
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400616 return TRACE_RETURN (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400617
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500618 if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, lookahead[i], match_data)))
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400619 return TRACE_RETURN (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400620 }
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400621
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400622 return TRACE_RETURN (true);
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400623}
624
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400625
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400626
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400627struct LookupRecord
628{
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400629 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400630 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200631 return TRACE_RETURN (c->check_struct (this));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -0400632 }
633
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400634 USHORT sequenceIndex; /* Index into current glyph
635 * sequence--first glyph = 0 */
636 USHORT lookupListIndex; /* Lookup to apply to that
637 * position--zero--based */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400638 public:
639 DEFINE_SIZE_STATIC (4);
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400640};
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400641
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400642
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400643static inline void closure_lookup (hb_closure_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400644 unsigned int lookupCount,
645 const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
646 closure_lookup_func_t closure_func)
647{
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400648 for (unsigned int i = 0; i < lookupCount; i++)
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400649 closure_func (c, lookupRecord->lookupListIndex);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400650}
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400651
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400652static inline bool apply_lookup (hb_apply_context_t *c,
Behdad Esfahbode072c242009-05-18 03:47:31 -0400653 unsigned int count, /* Including the first glyph */
654 unsigned int lookupCount,
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400655 const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
656 apply_lookup_func_t apply_func)
657{
Behdad Esfahbod26166892012-10-29 21:51:56 -0700658 hb_auto_trace_t<HB_DEBUG_APPLY> trace (&c->debug_depth, "APPLY", NULL, HB_FUNC, "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint);
Behdad Esfahbod5df809b2012-05-13 15:17:51 +0200659 unsigned int end = c->buffer->len;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400660 if (unlikely (count == 0 || c->buffer->idx + count > end))
Behdad Esfahbod26166892012-10-29 21:51:56 -0700661 return TRACE_RETURN (false);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400662
Behdad Esfahbod7cff75b2009-05-18 04:09:05 -0400663 /* TODO We don't support lookupRecord arrays that are not increasing:
664 * Should be easy for in_place ones at least. */
Behdad Esfahbod52e9a712009-09-21 13:58:56 -0400665
Behdad Esfahbod7eb87512010-12-13 14:13:35 -0500666 /* Note: If sublookup is reverse, it will underflow after the first loop
Behdad Esfahbod52e9a712009-09-21 13:58:56 -0400667 * and we jump out of it. Not entirely disastrous. So we don't check
668 * for reverse lookup here.
669 */
Behdad Esfahbodf9c0a2d2009-09-21 13:43:54 -0400670 for (unsigned int i = 0; i < count; /* NOP */)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400671 {
Behdad Esfahbod03408ce2012-01-18 21:28:34 -0500672 if (unlikely (c->buffer->idx == end))
Behdad Esfahbod26166892012-10-29 21:51:56 -0700673 return TRACE_RETURN (true);
Behdad Esfahbod7d479902012-01-18 21:19:32 -0500674 while (c->should_mark_skip_current_glyph ())
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400675 {
Behdad Esfahbode73a0c22009-05-18 04:15:25 -0400676 /* No lookup applied for this index */
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400677 c->buffer->next_glyph ();
Behdad Esfahbod03408ce2012-01-18 21:28:34 -0500678 if (unlikely (c->buffer->idx == end))
Behdad Esfahbod26166892012-10-29 21:51:56 -0700679 return TRACE_RETURN (true);
Behdad Esfahbode73a0c22009-05-18 04:15:25 -0400680 }
681
Behdad Esfahbod47958de2009-05-18 04:17:47 -0400682 if (lookupCount && i == lookupRecord->sequenceIndex)
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400683 {
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400684 unsigned int old_pos = c->buffer->idx;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400685
686 /* Apply a lookup */
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400687 bool done = apply_func (c, lookupRecord->lookupListIndex);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400688
Behdad Esfahbod47958de2009-05-18 04:17:47 -0400689 lookupRecord++;
690 lookupCount--;
Behdad Esfahbodf9c0a2d2009-09-21 13:43:54 -0400691 /* Err, this is wrong if the lookup jumped over some glyphs */
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400692 i += c->buffer->idx - old_pos;
693 if (unlikely (c->buffer->idx == end))
Behdad Esfahbod26166892012-10-29 21:51:56 -0700694 return TRACE_RETURN (true);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400695
696 if (!done)
697 goto not_applied;
698 }
699 else
700 {
701 not_applied:
702 /* No lookup applied for this index */
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400703 c->buffer->next_glyph ();
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400704 i++;
705 }
706 }
707
Behdad Esfahbod26166892012-10-29 21:51:56 -0700708 return TRACE_RETURN (true);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400709}
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400710
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400711
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400712
713/* Contextual lookups */
714
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400715struct ContextClosureLookupContext
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400716{
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400717 ContextClosureFuncs funcs;
718 const void *intersects_data;
719};
720
721struct ContextApplyLookupContext
722{
723 ContextApplyFuncs funcs;
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400724 const void *match_data;
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400725};
726
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400727static inline void context_closure_lookup (hb_closure_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400728 unsigned int inputCount, /* Including the first glyph (not matched) */
729 const USHORT input[], /* Array of input values--start with second glyph */
730 unsigned int lookupCount,
731 const LookupRecord lookupRecord[],
732 ContextClosureLookupContext &lookup_context)
733{
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400734 if (intersects_array (c,
735 inputCount ? inputCount - 1 : 0, input,
736 lookup_context.funcs.intersects, lookup_context.intersects_data))
737 closure_lookup (c,
738 lookupCount, lookupRecord,
739 lookup_context.funcs.closure);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400740}
741
742
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400743static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
744 unsigned int inputCount, /* Including the first glyph (not matched) */
745 const USHORT input[], /* Array of input values--start with second glyph */
746 unsigned int lookupCount,
747 const LookupRecord lookupRecord[],
748 ContextApplyLookupContext &lookup_context)
749{
750 return would_match_input (c,
751 inputCount, input,
752 lookup_context.funcs.match, lookup_context.match_data);
753}
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400754static inline bool context_apply_lookup (hb_apply_context_t *c,
755 unsigned int inputCount, /* Including the first glyph (not matched) */
756 const USHORT input[], /* Array of input values--start with second glyph */
757 unsigned int lookupCount,
758 const LookupRecord lookupRecord[],
759 ContextApplyLookupContext &lookup_context)
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400760{
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400761 return match_input (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -0400762 inputCount, input,
Behdad Esfahbod5df809b2012-05-13 15:17:51 +0200763 lookup_context.funcs.match, lookup_context.match_data)
764 && apply_lookup (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -0400765 inputCount,
766 lookupCount, lookupRecord,
767 lookup_context.funcs.apply);
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400768}
769
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400770struct Rule
771{
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400772 friend struct RuleSet;
773
774 private:
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400775
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400776 inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400777 {
778 TRACE_CLOSURE ();
779 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400780 context_closure_lookup (c,
781 inputCount, input,
782 lookupCount, lookupRecord,
783 lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400784 }
785
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400786 inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
787 {
788 TRACE_WOULD_APPLY ();
789 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
790 return TRACE_RETURN (context_would_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context));
791 }
792
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400793 inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400794 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400795 TRACE_APPLY ();
Behdad Esfahbode45d3f82010-05-06 19:33:31 -0400796 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200797 return TRACE_RETURN (context_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400798 }
799
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400800 public:
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400801 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400802 TRACE_SANITIZE ();
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400803 return inputCount.sanitize (c)
804 && lookupCount.sanitize (c)
805 && c->check_range (input,
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400806 input[0].static_size * inputCount
807 + lookupRecordX[0].static_size * lookupCount);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400808 }
809
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400810 protected:
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400811 USHORT inputCount; /* Total number of glyphs in input
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400812 * glyph sequence--includes the first
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400813 * glyph */
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400814 USHORT lookupCount; /* Number of LookupRecords */
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -0500815 USHORT input[VAR]; /* Array of match inputs--start with
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400816 * second glyph */
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -0500817 LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400818 * design order */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400819 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400820 DEFINE_SIZE_ARRAY2 (4, input, lookupRecordX);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400821};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400822
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400823struct RuleSet
824{
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400825 inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400826 {
827 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400828 unsigned int num_rules = rule.len;
829 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400830 (this+rule[i]).closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400831 }
832
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400833 inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
834 {
835 TRACE_WOULD_APPLY ();
836 unsigned int num_rules = rule.len;
837 for (unsigned int i = 0; i < num_rules; i++)
838 {
839 if ((this+rule[i]).would_apply (c, lookup_context))
840 return TRACE_RETURN (true);
841 }
842 return TRACE_RETURN (false);
843 }
844
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400845 inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400846 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400847 TRACE_APPLY ();
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400848 unsigned int num_rules = rule.len;
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400849 for (unsigned int i = 0; i < num_rules; i++)
850 {
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400851 if ((this+rule[i]).apply (c, lookup_context))
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200852 return TRACE_RETURN (true);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400853 }
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200854 return TRACE_RETURN (false);
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 (rule.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 OffsetArrayOf<Rule>
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400864 rule; /* Array of Rule tables
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400865 * ordered by preference */
Behdad Esfahboded074222010-05-10 18:08:46 -0400866 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400867 DEFINE_SIZE_ARRAY (2, rule);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400868};
869
870
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400871struct ContextFormat1
872{
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400873 friend struct Context;
874
875 private:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400876
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400877 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400878 {
879 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400880
881 const Coverage &cov = (this+coverage);
882
883 struct ContextClosureLookupContext lookup_context = {
884 {intersects_glyph, closure_func},
885 NULL
886 };
887
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400888 unsigned int count = ruleSet.len;
889 for (unsigned int i = 0; i < count; i++)
890 if (cov.intersects_coverage (c->glyphs, i)) {
891 const RuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400892 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400893 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400894 }
895
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400896 inline bool would_apply (hb_would_apply_context_t *c) const
897 {
898 TRACE_WOULD_APPLY ();
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400899
Behdad Esfahbod472f2292012-08-07 22:25:24 -0400900 const RuleSet &rule_set = this+ruleSet[(this+coverage) (c->glyphs[0])];
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400901 struct ContextApplyLookupContext lookup_context = {
902 {match_glyph, NULL},
903 NULL
904 };
905 return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
906 }
907
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400908 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400909 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400910 TRACE_APPLY ();
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200911 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
Behdad Esfahbod64d3fc82010-05-03 22:51:19 -0400912 if (likely (index == NOT_COVERED))
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200913 return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -0400914
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400915 const RuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400916 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400917 {match_glyph, apply_func},
918 NULL
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400919 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200920 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400921 }
922
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400923 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400924 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200925 return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400926 }
927
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400928 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400929 USHORT format; /* Format identifier--format = 1 */
930 OffsetTo<Coverage>
931 coverage; /* Offset to Coverage table--from
932 * beginning of table */
933 OffsetArrayOf<RuleSet>
934 ruleSet; /* Array of RuleSet tables
935 * ordered by Coverage Index */
Behdad Esfahbodb3651232010-05-10 16:57:29 -0400936 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400937 DEFINE_SIZE_ARRAY (6, ruleSet);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400938};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400939
940
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400941struct ContextFormat2
942{
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400943 friend struct Context;
944
945 private:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400946
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400947 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400948 {
949 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400950 if (!(this+coverage).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400951 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400952
953 const ClassDef &class_def = this+classDef;
954
955 struct ContextClosureLookupContext lookup_context = {
956 {intersects_class, closure_func},
957 NULL
958 };
959
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400960 unsigned int count = ruleSet.len;
961 for (unsigned int i = 0; i < count; i++)
962 if (class_def.intersects_class (c->glyphs, i)) {
963 const RuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400964 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400965 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400966 }
967
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400968 inline bool would_apply (hb_would_apply_context_t *c) const
969 {
970 TRACE_WOULD_APPLY ();
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400971
972 const ClassDef &class_def = this+classDef;
Behdad Esfahbod472f2292012-08-07 22:25:24 -0400973 unsigned int index = class_def (c->glyphs[0]);
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400974 const RuleSet &rule_set = this+ruleSet[index];
975 struct ContextApplyLookupContext lookup_context = {
976 {match_class, NULL},
977 &class_def
978 };
979 return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
980 }
981
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400982 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400983 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400984 TRACE_APPLY ();
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200985 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200986 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -0400987
988 const ClassDef &class_def = this+classDef;
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200989 index = class_def (c->buffer->cur().codepoint);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400990 const RuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400991 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400992 {match_class, apply_func},
993 &class_def
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400994 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200995 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400996 }
997
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400998 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -0400999 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001000 return TRACE_RETURN (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001001 }
1002
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001003 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001004 USHORT format; /* Format identifier--format = 2 */
1005 OffsetTo<Coverage>
1006 coverage; /* Offset to Coverage table--from
1007 * beginning of table */
1008 OffsetTo<ClassDef>
1009 classDef; /* Offset to glyph ClassDef table--from
1010 * beginning of table */
1011 OffsetArrayOf<RuleSet>
1012 ruleSet; /* Array of RuleSet tables
1013 * ordered by class */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001014 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001015 DEFINE_SIZE_ARRAY (8, ruleSet);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001016};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001017
1018
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001019struct ContextFormat3
1020{
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001021 friend struct Context;
1022
1023 private:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001024
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001025 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001026 {
1027 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001028 if (!(this+coverage[0]).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001029 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001030
1031 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
1032 struct ContextClosureLookupContext lookup_context = {
1033 {intersects_coverage, closure_func},
1034 this
1035 };
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001036 context_closure_lookup (c,
1037 glyphCount, (const USHORT *) (coverage + 1),
1038 lookupCount, lookupRecord,
1039 lookup_context);
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001040 }
1041
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001042 inline bool would_apply (hb_would_apply_context_t *c) const
1043 {
1044 TRACE_WOULD_APPLY ();
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001045
1046 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
1047 struct ContextApplyLookupContext lookup_context = {
1048 {match_coverage, NULL},
1049 this
1050 };
1051 return TRACE_RETURN (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context));
1052 }
1053
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001054 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001055 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001056 TRACE_APPLY ();
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001057 unsigned int index = (this+coverage[0]) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001058 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001059
Behdad Esfahbode45d3f82010-05-06 19:33:31 -04001060 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001061 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001062 {match_coverage, apply_func},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001063 this
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001064 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001065 return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001066 }
1067
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001068 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001069 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001070 if (!c->check_struct (this)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001071 unsigned int count = glyphCount;
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001072 if (!c->check_array (coverage, coverage[0].static_size, count)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001073 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001074 if (!coverage[i].sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode45d3f82010-05-06 19:33:31 -04001075 LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * count);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001076 return TRACE_RETURN (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001077 }
1078
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001079 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001080 USHORT format; /* Format identifier--format = 3 */
1081 USHORT glyphCount; /* Number of glyphs in the input glyph
1082 * sequence */
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001083 USHORT lookupCount; /* Number of LookupRecords */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001084 OffsetTo<Coverage>
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -05001085 coverage[VAR]; /* Array of offsets to Coverage
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001086 * table in glyph sequence order */
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -05001087 LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001088 * design order */
Behdad Esfahbod569da922010-05-10 16:38:32 -04001089 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001090 DEFINE_SIZE_ARRAY2 (6, coverage, lookupRecordX);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001091};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001092
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001093struct Context
1094{
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001095 protected:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001096
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001097 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001098 {
1099 TRACE_CLOSURE ();
1100 switch (u.format) {
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001101 case 1: u.format1.closure (c, closure_func); break;
1102 case 2: u.format2.closure (c, closure_func); break;
1103 case 3: u.format3.closure (c, closure_func); break;
1104 default: break;
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001105 }
1106 }
1107
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001108 inline const Coverage &get_coverage (void) const
1109 {
1110 switch (u.format) {
1111 case 1: return this + u.format1.coverage;
1112 case 2: return this + u.format2.coverage;
1113 case 3: return this + u.format3.coverage[0];
1114 default:return Null(Coverage);
1115 }
1116 }
1117
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001118 inline bool would_apply (hb_would_apply_context_t *c) const
1119 {
1120 switch (u.format) {
1121 case 1: return u.format1.would_apply (c);
1122 case 2: return u.format2.would_apply (c);
1123 case 3: return u.format3.would_apply (c);
1124 default:return false;
1125 }
1126 }
1127
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001128 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001129 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001130 TRACE_APPLY ();
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001131 switch (u.format) {
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001132 case 1: return TRACE_RETURN (u.format1.apply (c, apply_func));
1133 case 2: return TRACE_RETURN (u.format2.apply (c, apply_func));
1134 case 3: return TRACE_RETURN (u.format3.apply (c, apply_func));
1135 default:return TRACE_RETURN (false);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001136 }
1137 }
1138
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001139 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001140 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001141 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001142 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001143 case 1: return TRACE_RETURN (u.format1.sanitize (c));
1144 case 2: return TRACE_RETURN (u.format2.sanitize (c));
1145 case 3: return TRACE_RETURN (u.format3.sanitize (c));
1146 default:return TRACE_RETURN (true);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001147 }
1148 }
1149
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001150 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001151 union {
Behdad Esfahbodf8dc67b2009-05-17 19:47:54 -04001152 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001153 ContextFormat1 format1;
1154 ContextFormat2 format2;
1155 ContextFormat3 format3;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001156 } u;
1157};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001158
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001159
1160/* Chaining Contextual lookups */
1161
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001162struct ChainContextClosureLookupContext
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001163{
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001164 ContextClosureFuncs funcs;
1165 const void *intersects_data[3];
1166};
1167
1168struct ChainContextApplyLookupContext
1169{
1170 ContextApplyFuncs funcs;
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001171 const void *match_data[3];
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001172};
1173
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001174static inline void chain_context_closure_lookup (hb_closure_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001175 unsigned int backtrackCount,
1176 const USHORT backtrack[],
1177 unsigned int inputCount, /* Including the first glyph (not matched) */
1178 const USHORT input[], /* Array of input values--start with second glyph */
1179 unsigned int lookaheadCount,
1180 const USHORT lookahead[],
1181 unsigned int lookupCount,
1182 const LookupRecord lookupRecord[],
1183 ChainContextClosureLookupContext &lookup_context)
1184{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001185 if (intersects_array (c,
1186 backtrackCount, backtrack,
1187 lookup_context.funcs.intersects, lookup_context.intersects_data[0])
1188 && intersects_array (c,
1189 inputCount ? inputCount - 1 : 0, input,
1190 lookup_context.funcs.intersects, lookup_context.intersects_data[1])
1191 && intersects_array (c,
1192 lookaheadCount, lookahead,
1193 lookup_context.funcs.intersects, lookup_context.intersects_data[2]))
1194 closure_lookup (c,
1195 lookupCount, lookupRecord,
1196 lookup_context.funcs.closure);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001197}
1198
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001199static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
1200 unsigned int backtrackCount,
1201 const USHORT backtrack[],
1202 unsigned int inputCount, /* Including the first glyph (not matched) */
1203 const USHORT input[], /* Array of input values--start with second glyph */
1204 unsigned int lookaheadCount,
1205 const USHORT lookahead[],
1206 unsigned int lookupCount,
1207 const LookupRecord lookupRecord[],
1208 ChainContextApplyLookupContext &lookup_context)
1209{
Behdad Esfahbodd9b204d2012-08-23 16:22:28 -04001210 return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
Behdad Esfahbod1f2bb172012-08-23 16:10:37 -04001211 && would_match_input (c,
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001212 inputCount, input,
1213 lookup_context.funcs.match, lookup_context.match_data[1]);
1214}
1215
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001216static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
1217 unsigned int backtrackCount,
1218 const USHORT backtrack[],
1219 unsigned int inputCount, /* Including the first glyph (not matched) */
1220 const USHORT input[], /* Array of input values--start with second glyph */
1221 unsigned int lookaheadCount,
1222 const USHORT lookahead[],
1223 unsigned int lookupCount,
1224 const LookupRecord lookupRecord[],
1225 ChainContextApplyLookupContext &lookup_context)
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001226{
Behdad Esfahbod5df809b2012-05-13 15:17:51 +02001227 unsigned int lookahead_offset;
Behdad Esfahbodf19e0b02012-06-09 02:26:57 -04001228 return match_input (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -04001229 inputCount, input,
1230 lookup_context.funcs.match, lookup_context.match_data[1],
Behdad Esfahbod5df809b2012-05-13 15:17:51 +02001231 &lookahead_offset)
Behdad Esfahbodf19e0b02012-06-09 02:26:57 -04001232 && match_backtrack (c,
1233 backtrackCount, backtrack,
1234 lookup_context.funcs.match, lookup_context.match_data[0])
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001235 && match_lookahead (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -04001236 lookaheadCount, lookahead,
1237 lookup_context.funcs.match, lookup_context.match_data[2],
Behdad Esfahbod5df809b2012-05-13 15:17:51 +02001238 lookahead_offset)
1239 && apply_lookup (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -04001240 inputCount,
1241 lookupCount, lookupRecord,
1242 lookup_context.funcs.apply);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001243}
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001244
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001245struct ChainRule
1246{
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001247 friend struct ChainRuleSet;
1248
1249 private:
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001250
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001251 inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001252 {
1253 TRACE_CLOSURE ();
1254 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
1255 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
1256 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001257 chain_context_closure_lookup (c,
1258 backtrack.len, backtrack.array,
1259 input.len, input.array,
1260 lookahead.len, lookahead.array,
1261 lookup.len, lookup.array,
1262 lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001263 }
1264
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001265 inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
1266 {
1267 TRACE_WOULD_APPLY ();
1268 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
1269 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
1270 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1271 return TRACE_RETURN (chain_context_would_apply_lookup (c,
1272 backtrack.len, backtrack.array,
1273 input.len, input.array,
1274 lookahead.len, lookahead.array, lookup.len,
1275 lookup.array, lookup_context));
1276 }
1277
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001278 inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001279 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001280 TRACE_APPLY ();
Behdad Esfahbode961c862010-04-21 15:56:11 -04001281 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
1282 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
1283 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001284 return TRACE_RETURN (chain_context_apply_lookup (c,
1285 backtrack.len, backtrack.array,
1286 input.len, input.array,
1287 lookahead.len, lookahead.array, lookup.len,
1288 lookup.array, lookup_context));
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001289 }
1290
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001291 public:
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001292 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001293 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001294 if (!backtrack.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001295 HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001296 if (!input.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001297 ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001298 if (!lookahead.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001299 ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001300 return TRACE_RETURN (lookup.sanitize (c));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001301 }
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001302
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001303 protected:
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001304 ArrayOf<USHORT>
1305 backtrack; /* Array of backtracking values
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001306 * (to be matched before the input
1307 * sequence) */
Behdad Esfahbode8cbaaf2009-05-18 02:03:58 -04001308 HeadlessArrayOf<USHORT>
1309 inputX; /* Array of input values (start with
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001310 * second glyph) */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001311 ArrayOf<USHORT>
1312 lookaheadX; /* Array of lookahead values's (to be
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001313 * matched after the input sequence) */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001314 ArrayOf<LookupRecord>
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001315 lookupX; /* Array of LookupRecords--in
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001316 * design order) */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001317 public:
Behdad Esfahbodbea34c72010-05-10 17:28:16 -04001318 DEFINE_SIZE_MIN (8);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001319};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001320
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001321struct ChainRuleSet
1322{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001323 inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001324 {
1325 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001326 unsigned int num_rules = rule.len;
1327 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001328 (this+rule[i]).closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001329 }
1330
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001331 inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
1332 {
1333 TRACE_WOULD_APPLY ();
1334 unsigned int num_rules = rule.len;
1335 for (unsigned int i = 0; i < num_rules; i++)
1336 if ((this+rule[i]).would_apply (c, lookup_context))
1337 return TRACE_RETURN (true);
1338
1339 return TRACE_RETURN (false);
1340 }
1341
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001342 inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001343 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001344 TRACE_APPLY ();
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001345 unsigned int num_rules = rule.len;
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001346 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001347 if ((this+rule[i]).apply (c, lookup_context))
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001348 return TRACE_RETURN (true);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001349
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001350 return TRACE_RETURN (false);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001351 }
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001352
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001353 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001354 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001355 return TRACE_RETURN (rule.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001356 }
1357
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001358 protected:
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001359 OffsetArrayOf<ChainRule>
1360 rule; /* Array of ChainRule tables
1361 * ordered by preference */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001362 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001363 DEFINE_SIZE_ARRAY (2, rule);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001364};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001365
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001366struct ChainContextFormat1
1367{
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001368 friend struct ChainContext;
1369
1370 private:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001371
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001372 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001373 {
1374 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001375 const Coverage &cov = (this+coverage);
1376
1377 struct ChainContextClosureLookupContext lookup_context = {
1378 {intersects_glyph, closure_func},
1379 {NULL, NULL, NULL}
1380 };
1381
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001382 unsigned int count = ruleSet.len;
1383 for (unsigned int i = 0; i < count; i++)
1384 if (cov.intersects_coverage (c->glyphs, i)) {
1385 const ChainRuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001386 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001387 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001388 }
1389
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001390 inline bool would_apply (hb_would_apply_context_t *c) const
1391 {
1392 TRACE_WOULD_APPLY ();
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001393
Behdad Esfahbod472f2292012-08-07 22:25:24 -04001394 const ChainRuleSet &rule_set = this+ruleSet[(this+coverage) (c->glyphs[0])];
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001395 struct ChainContextApplyLookupContext lookup_context = {
1396 {match_glyph, NULL},
1397 {NULL, NULL, NULL}
1398 };
1399 return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
1400 }
1401
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001402 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001403 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001404 TRACE_APPLY ();
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001405 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001406 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001407
1408 const ChainRuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001409 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001410 {match_glyph, apply_func},
1411 {NULL, NULL, NULL}
1412 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001413 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001414 }
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001415
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001416 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001417 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001418 return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001419 }
1420
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001421 protected:
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001422 USHORT format; /* Format identifier--format = 1 */
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001423 OffsetTo<Coverage>
1424 coverage; /* Offset to Coverage table--from
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001425 * beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001426 OffsetArrayOf<ChainRuleSet>
1427 ruleSet; /* Array of ChainRuleSet tables
1428 * ordered by Coverage Index */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001429 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001430 DEFINE_SIZE_ARRAY (6, ruleSet);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001431};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001432
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001433struct ChainContextFormat2
1434{
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001435 friend struct ChainContext;
1436
1437 private:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001438
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001439 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001440 {
1441 TRACE_CLOSURE ();
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001442 if (!(this+coverage).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001443 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001444
1445 const ClassDef &backtrack_class_def = this+backtrackClassDef;
1446 const ClassDef &input_class_def = this+inputClassDef;
1447 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
1448
1449 struct ChainContextClosureLookupContext lookup_context = {
1450 {intersects_class, closure_func},
1451 {&backtrack_class_def,
1452 &input_class_def,
1453 &lookahead_class_def}
1454 };
1455
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001456 unsigned int count = ruleSet.len;
1457 for (unsigned int i = 0; i < count; i++)
1458 if (input_class_def.intersects_class (c->glyphs, i)) {
1459 const ChainRuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001460 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001461 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001462 }
1463
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001464 inline bool would_apply (hb_would_apply_context_t *c) const
1465 {
1466 TRACE_WOULD_APPLY ();
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001467
1468 const ClassDef &input_class_def = this+inputClassDef;
1469
Behdad Esfahbod472f2292012-08-07 22:25:24 -04001470 unsigned int index = input_class_def (c->glyphs[0]);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001471 const ChainRuleSet &rule_set = this+ruleSet[index];
1472 struct ChainContextApplyLookupContext lookup_context = {
1473 {match_class, NULL},
1474 {NULL, &input_class_def, NULL}
1475 };
1476 return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
1477 }
1478
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001479 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001480 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001481 TRACE_APPLY ();
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001482 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001483 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001484
1485 const ClassDef &backtrack_class_def = this+backtrackClassDef;
1486 const ClassDef &input_class_def = this+inputClassDef;
1487 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
1488
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001489 index = input_class_def (c->buffer->cur().codepoint);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001490 const ChainRuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001491 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001492 {match_class, apply_func},
1493 {&backtrack_class_def,
1494 &input_class_def,
1495 &lookahead_class_def}
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001496 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001497 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001498 }
1499
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001500 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001501 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001502 return TRACE_RETURN (coverage.sanitize (c, this) && backtrackClassDef.sanitize (c, this) &&
1503 inputClassDef.sanitize (c, this) && lookaheadClassDef.sanitize (c, this) &&
1504 ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001505 }
1506
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001507 protected:
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001508 USHORT format; /* Format identifier--format = 2 */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001509 OffsetTo<Coverage>
1510 coverage; /* Offset to Coverage table--from
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001511 * beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001512 OffsetTo<ClassDef>
1513 backtrackClassDef; /* Offset to glyph ClassDef table
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001514 * containing backtrack sequence
1515 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001516 OffsetTo<ClassDef>
1517 inputClassDef; /* Offset to glyph ClassDef
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001518 * table containing input sequence
1519 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001520 OffsetTo<ClassDef>
1521 lookaheadClassDef; /* Offset to glyph ClassDef table
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001522 * containing lookahead sequence
1523 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001524 OffsetArrayOf<ChainRuleSet>
1525 ruleSet; /* Array of ChainRuleSet tables
1526 * ordered by class */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001527 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001528 DEFINE_SIZE_ARRAY (12, ruleSet);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001529};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001530
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001531struct ChainContextFormat3
1532{
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001533 friend struct ChainContext;
1534
1535 private:
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001536
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001537 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001538 {
1539 TRACE_CLOSURE ();
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001540 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
1541
1542 if (!(this+input[0]).intersects (c->glyphs))
1543 return;
1544
1545 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
1546 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1547 struct ChainContextClosureLookupContext lookup_context = {
1548 {intersects_coverage, closure_func},
1549 {this, this, this}
1550 };
1551 chain_context_closure_lookup (c,
1552 backtrack.len, (const USHORT *) backtrack.array,
1553 input.len, (const USHORT *) input.array + 1,
1554 lookahead.len, (const USHORT *) lookahead.array,
1555 lookup.len, lookup.array,
1556 lookup_context);
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001557 }
1558
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001559 inline const Coverage &get_coverage (void) const
1560 {
1561 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
1562 return this+input[0];
1563 }
1564
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001565 inline bool would_apply (hb_would_apply_context_t *c) const
1566 {
1567 TRACE_WOULD_APPLY ();
Behdad Esfahbode6f74792012-07-28 18:34:58 -04001568
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001569 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001570 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
1571 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1572 struct ChainContextApplyLookupContext lookup_context = {
1573 {match_coverage, NULL},
1574 {this, this, this}
1575 };
1576 return TRACE_RETURN (chain_context_would_apply_lookup (c,
1577 backtrack.len, (const USHORT *) backtrack.array,
1578 input.len, (const USHORT *) input.array + 1,
1579 lookahead.len, (const USHORT *) lookahead.array,
1580 lookup.len, lookup.array, lookup_context));
1581 }
1582
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001583 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001584 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001585 TRACE_APPLY ();
Behdad Esfahbode961c862010-04-21 15:56:11 -04001586 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001587
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001588 unsigned int index = (this+input[0]) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001589 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001590
Behdad Esfahbode961c862010-04-21 15:56:11 -04001591 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
1592 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001593 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001594 {match_coverage, apply_func},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001595 {this, this, this}
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001596 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001597 return TRACE_RETURN (chain_context_apply_lookup (c,
1598 backtrack.len, (const USHORT *) backtrack.array,
1599 input.len, (const USHORT *) input.array + 1,
1600 lookahead.len, (const USHORT *) lookahead.array,
1601 lookup.len, lookup.array, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001602 }
1603
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001604 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001605 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001606 if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001607 OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001608 if (!input.sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001609 OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001610 if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001611 ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001612 return TRACE_RETURN (lookup.sanitize (c));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001613 }
1614
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001615 protected:
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001616 USHORT format; /* Format identifier--format = 3 */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001617 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04001618 backtrack; /* Array of coverage tables
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001619 * in backtracking sequence, in glyph
1620 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001621 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04001622 inputX ; /* Array of coverage
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001623 * tables in input sequence, in glyph
1624 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001625 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04001626 lookaheadX; /* Array of coverage tables
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001627 * in lookahead sequence, in glyph
1628 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001629 ArrayOf<LookupRecord>
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001630 lookupX; /* Array of LookupRecords--in
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001631 * design order) */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001632 public:
Behdad Esfahbodbea34c72010-05-10 17:28:16 -04001633 DEFINE_SIZE_MIN (10);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001634};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001635
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001636struct ChainContext
1637{
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001638 protected:
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001639
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001640 inline void closure (hb_closure_context_t *c, closure_lookup_func_t closure_func) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001641 {
1642 TRACE_CLOSURE ();
1643 switch (u.format) {
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001644 case 1: u.format1.closure (c, closure_func); break;
1645 case 2: u.format2.closure (c, closure_func); break;
1646 case 3: u.format3.closure (c, closure_func); break;
1647 default: break;
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001648 }
1649 }
1650
Behdad Esfahbod0b994292012-07-28 17:31:01 -04001651 inline const Coverage &get_coverage (void) const
1652 {
1653 switch (u.format) {
1654 case 1: return this + u.format1.coverage;
1655 case 2: return this + u.format2.coverage;
1656 case 3: return u.format3.get_coverage ();
1657 default:return Null(Coverage);
1658 }
1659 }
1660
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001661 inline bool would_apply (hb_would_apply_context_t *c) const
1662 {
1663 switch (u.format) {
1664 case 1: return u.format1.would_apply (c);
1665 case 2: return u.format2.would_apply (c);
1666 case 3: return u.format3.would_apply (c);
1667 default:return false;
1668 }
1669 }
1670
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001671 inline bool apply (hb_apply_context_t *c, apply_lookup_func_t apply_func) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001672 {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001673 TRACE_APPLY ();
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001674 switch (u.format) {
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001675 case 1: return TRACE_RETURN (u.format1.apply (c, apply_func));
1676 case 2: return TRACE_RETURN (u.format2.apply (c, apply_func));
1677 case 3: return TRACE_RETURN (u.format3.apply (c, apply_func));
1678 default:return TRACE_RETURN (false);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001679 }
1680 }
1681
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001682 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001683 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001684 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001685 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001686 case 1: return TRACE_RETURN (u.format1.sanitize (c));
1687 case 2: return TRACE_RETURN (u.format2.sanitize (c));
1688 case 3: return TRACE_RETURN (u.format3.sanitize (c));
1689 default:return TRACE_RETURN (true);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001690 }
1691 }
1692
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001693 protected:
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001694 union {
1695 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001696 ChainContextFormat1 format1;
1697 ChainContextFormat2 format2;
1698 ChainContextFormat3 format3;
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001699 } u;
1700};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001701
1702
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001703struct ExtensionFormat1
1704{
Behdad Esfahbod6d08c7f2012-07-11 18:01:27 -04001705 friend struct Extension;
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001706
Behdad Esfahbod18939482009-08-04 14:27:56 -04001707 protected:
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001708 inline unsigned int get_type (void) const { return extensionLookupType; }
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -04001709 inline unsigned int get_offset (void) const { return extensionOffset; }
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001710
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001711 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001712 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001713 return TRACE_RETURN (c->check_struct (this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001714 }
1715
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001716 protected:
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001717 USHORT format; /* Format identifier. Set to 1. */
1718 USHORT extensionLookupType; /* Lookup type of subtable referenced
1719 * by ExtensionOffset (i.e. the
1720 * extension subtable). */
Behdad Esfahbod81f2af42010-04-22 00:58:49 -04001721 ULONG extensionOffset; /* Offset to the extension subtable,
1722 * of lookup type subtable. */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001723 public:
1724 DEFINE_SIZE_STATIC (8);
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001725};
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001726
1727struct Extension
1728{
1729 inline unsigned int get_type (void) const
1730 {
1731 switch (u.format) {
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001732 case 1: return u.format1.get_type ();
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001733 default:return 0;
1734 }
1735 }
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -04001736 inline unsigned int get_offset (void) const
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001737 {
1738 switch (u.format) {
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001739 case 1: return u.format1.get_offset ();
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -04001740 default:return 0;
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001741 }
1742 }
1743
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001744 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001745 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001746 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001747 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001748 case 1: return TRACE_RETURN (u.format1.sanitize (c));
1749 default:return TRACE_RETURN (true);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001750 }
1751 }
1752
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001753 protected:
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001754 union {
1755 USHORT format; /* Format identifier */
Behdad Esfahbod6d08c7f2012-07-11 18:01:27 -04001756 ExtensionFormat1 format1;
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001757 } u;
1758};
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001759
1760
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001761/*
1762 * GSUB/GPOS Common
1763 */
1764
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001765struct GSUBGPOS
1766{
Behdad Esfahboda328d662009-08-04 20:27:05 -04001767 static const hb_tag_t GSUBTag = HB_OT_TAG_GSUB;
1768 static const hb_tag_t GPOSTag = HB_OT_TAG_GPOS;
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001769
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04001770 inline unsigned int get_script_count (void) const
1771 { return (this+scriptList).len; }
1772 inline const Tag& get_script_tag (unsigned int i) const
1773 { return (this+scriptList).get_tag (i); }
Behdad Esfahbode21899b2009-11-04 16:36:14 -05001774 inline unsigned int get_script_tags (unsigned int start_offset,
1775 unsigned int *script_count /* IN/OUT */,
1776 hb_tag_t *script_tags /* OUT */) const
1777 { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04001778 inline const Script& get_script (unsigned int i) const
1779 { return (this+scriptList)[i]; }
1780 inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
1781 { return (this+scriptList).find_index (tag, index); }
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001782
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04001783 inline unsigned int get_feature_count (void) const
1784 { return (this+featureList).len; }
1785 inline const Tag& get_feature_tag (unsigned int i) const
1786 { return (this+featureList).get_tag (i); }
Behdad Esfahbode21899b2009-11-04 16:36:14 -05001787 inline unsigned int get_feature_tags (unsigned int start_offset,
1788 unsigned int *feature_count /* IN/OUT */,
1789 hb_tag_t *feature_tags /* OUT */) const
1790 { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04001791 inline const Feature& get_feature (unsigned int i) const
1792 { return (this+featureList)[i]; }
1793 inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
1794 { return (this+featureList).find_index (tag, index); }
1795
1796 inline unsigned int get_lookup_count (void) const
1797 { return (this+lookupList).len; }
1798 inline const Lookup& get_lookup (unsigned int i) const
1799 { return (this+lookupList)[i]; }
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001800
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001801 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbod3e2401f2009-08-28 17:17:11 -04001802 TRACE_SANITIZE ();
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001803 return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) &&
1804 scriptList.sanitize (c, this) &&
1805 featureList.sanitize (c, this) &&
1806 lookupList.sanitize (c, this));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -04001807 }
1808
Behdad Esfahbod212aba62009-05-24 00:50:27 -04001809 protected:
Behdad Esfahbod87fcdcb2009-05-24 01:03:24 -04001810 FixedVersion version; /* Version of the GSUB/GPOS table--initially set
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001811 * to 0x00010000 */
1812 OffsetTo<ScriptList>
1813 scriptList; /* ScriptList table */
1814 OffsetTo<FeatureList>
1815 featureList; /* FeatureList table */
1816 OffsetTo<LookupList>
1817 lookupList; /* LookupList table */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001818 public:
1819 DEFINE_SIZE_STATIC (10);
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001820};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001821
Behdad Esfahbod6f20f722009-05-17 20:28:01 -04001822
Behdad Esfahbod7d52e662012-11-16 18:49:54 -08001823} /* namespace OT */
Behdad Esfahbod7c8e8442012-08-28 17:57:49 -04001824
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -04001825
Behdad Esfahbod5f5b24f2009-08-02 20:03:12 -04001826#endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */