blob: 4ff8940312ac231e25b0c87d598bca50eb2a1e12 [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 Esfahbod902cc8a2012-11-23 15:06:59 -050040
Behdad Esfahboda1733db2012-11-23 16:40:04 -050041#define TRACE_PROCESS(this) \
42 hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
43 (&c->debug_depth, c->get_name (), this, HB_FUNC, \
44 "");
45
46
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040047#ifndef HB_DEBUG_CLOSURE
48#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
49#endif
50
Behdad Esfahbodbe218c62012-11-23 15:32:14 -050051#define TRACE_CLOSURE(this) \
Behdad Esfahbod902cc8a2012-11-23 15:06:59 -050052 hb_auto_trace_t<HB_DEBUG_CLOSURE, void_t> trace \
53 (&c->debug_depth, "CLOSURE", this, HB_FUNC, \
54 "");
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040055
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040056struct hb_closure_context_t
57{
Behdad Esfahboda1733db2012-11-23 16:40:04 -050058 inline const char *get_name (void) { return "CLOSURE"; }
59 static const unsigned int max_debug_depth = HB_DEBUG_CLOSURE;
Behdad Esfahbod44fc2372012-11-21 23:33:13 -050060 typedef void_t return_t;
61 typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
62 template <typename T>
Behdad Esfahboda1733db2012-11-23 16:40:04 -050063 inline return_t process (const T &obj) { obj.closure (this); return VOID; }
64 static return_t default_return_value (void) { return VOID; }
Behdad Esfahbod44fc2372012-11-21 23:33:13 -050065 bool stop_sublookup_iteration (const return_t r) const { return false; }
66 return_t recurse (unsigned int lookup_index)
67 {
68 if (unlikely (nesting_level_left == 0))
Behdad Esfahbod2005fa52012-11-22 14:38:10 -050069 return default_return_value ();
Behdad Esfahbod44fc2372012-11-21 23:33:13 -050070
71 nesting_level_left--;
72 recurse_func (this, lookup_index);
73 nesting_level_left++;
Behdad Esfahbod2005fa52012-11-22 14:38:10 -050074 return default_return_value ();
Behdad Esfahbod44fc2372012-11-21 23:33:13 -050075 }
76
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040077 hb_face_t *face;
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -040078 hb_set_t *glyphs;
Behdad Esfahbod44fc2372012-11-21 23:33:13 -050079 recurse_func_t recurse_func;
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040080 unsigned int nesting_level_left;
81 unsigned int debug_depth;
82
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040083 hb_closure_context_t (hb_face_t *face_,
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -040084 hb_set_t *glyphs_,
Behdad Esfahbod44fc2372012-11-21 23:33:13 -050085 recurse_func_t recurse_func_,
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040086 unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
Behdad Esfahbode72b3602012-07-19 14:35:23 -040087 face (face_),
88 glyphs (glyphs_),
Behdad Esfahbod44fc2372012-11-21 23:33:13 -050089 recurse_func (recurse_func_),
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040090 nesting_level_left (nesting_level_left_),
91 debug_depth (0) {}
92};
93
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040094
95
Behdad Esfahbod472f2292012-08-07 22:25:24 -040096#ifndef HB_DEBUG_WOULD_APPLY
97#define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
98#endif
99
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500100#define TRACE_WOULD_APPLY(this) \
Behdad Esfahbod902cc8a2012-11-23 15:06:59 -0500101 hb_auto_trace_t<HB_DEBUG_WOULD_APPLY, bool> trace \
102 (&c->debug_depth, "WOULD_APPLY", this, HB_FUNC, \
103 "%d glyphs", c->len);
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400104
105struct hb_would_apply_context_t
106{
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500107 inline const char *get_name (void) { return "WOULD_APPLY"; }
108 static const unsigned int max_debug_depth = HB_DEBUG_WOULD_APPLY;
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500109 typedef bool return_t;
110 template <typename T>
111 inline return_t process (const T &obj) { return obj.would_apply (this); }
112 static return_t default_return_value (void) { return false; }
113 bool stop_sublookup_iteration (const return_t r) const { return r; }
114 return_t recurse (unsigned int lookup_index) { return true; }
115
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400116 hb_face_t *face;
Behdad Esfahbod472f2292012-08-07 22:25:24 -0400117 const hb_codepoint_t *glyphs;
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400118 unsigned int len;
Behdad Esfahbodd9b204d2012-08-23 16:22:28 -0400119 bool zero_context;
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400120 unsigned int debug_depth;
121
122 hb_would_apply_context_t (hb_face_t *face_,
Behdad Esfahbod472f2292012-08-07 22:25:24 -0400123 const hb_codepoint_t *glyphs_,
124 unsigned int len_,
Behdad Esfahbod2bd9fe32012-09-04 15:15:19 -0400125 bool zero_context_) :
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400126 face (face_),
Behdad Esfahbod472f2292012-08-07 22:25:24 -0400127 glyphs (glyphs_),
128 len (len_),
Behdad Esfahbodd9b204d2012-08-23 16:22:28 -0400129 zero_context (zero_context_),
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500130 debug_depth (0) {}
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400131};
132
133
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800134
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800135#ifndef HB_DEBUG_COLLECT_GLYPHS
136#define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0)
137#endif
138
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500139#define TRACE_COLLECT_GLYPHS(this) \
Behdad Esfahbod902cc8a2012-11-23 15:06:59 -0500140 hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, void_t> trace \
141 (&c->debug_depth, "COLLECT_GLYPHS", this, HB_FUNC, \
142 "");
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800143
144struct hb_collect_glyphs_context_t
145{
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500146 inline const char *get_name (void) { return "COLLECT_GLYPHS"; }
147 static const unsigned int max_debug_depth = HB_DEBUG_COLLECT_GLYPHS;
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500148 typedef void_t return_t;
149 template <typename T>
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500150 inline return_t process (const T &obj) { obj.collect_glyphs (this); return VOID; }
151 static return_t default_return_value (void) { return VOID; }
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500152 bool stop_iteration (const return_t r) const { return false; }
153 return_t recurse (unsigned int lookup_index)
154 {
155#if 0
156 /* XXX */
157#endif
158 return default_return_value ();
159 }
160
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800161 hb_face_t *face;
162 hb_set_t &before;
163 hb_set_t &input;
164 hb_set_t &after;
165 hb_set_t &output;
166 unsigned int debug_depth;
167
168 hb_collect_glyphs_context_t (hb_face_t *face_,
169 hb_set_t *glyphs_before, /* OUT. May be NULL */
170 hb_set_t *glyphs_input, /* OUT. May be NULL */
171 hb_set_t *glyphs_after, /* OUT. May be NULL */
172 hb_set_t *glyphs_output /* OUT. May be NULL */) :
173 face (face_),
174 before (glyphs_before ? *glyphs_before : *hb_set_get_empty ()),
175 input (glyphs_input ? *glyphs_input : *hb_set_get_empty ()),
176 after (glyphs_after ? *glyphs_after : *hb_set_get_empty ()),
177 output (glyphs_output ? *glyphs_output : *hb_set_get_empty ()),
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500178 debug_depth (0) {}
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800179};
180
181
182
Behdad Esfahbod2005fa52012-11-22 14:38:10 -0500183struct hb_get_coverage_context_t
184{
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500185 inline const char *get_name (void) { return "GET_COVERAGE"; }
186 static const unsigned int max_debug_depth = 0;
Behdad Esfahbod2005fa52012-11-22 14:38:10 -0500187 typedef const Coverage &return_t;
188 template <typename T>
189 inline return_t process (const T &obj) { return obj.get_coverage (); }
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500190 static return_t default_return_value (void) { return Null(Coverage); }
Behdad Esfahbod2005fa52012-11-22 14:38:10 -0500191 bool stop_sublookup_iteration (const return_t r) const { return true; /* Unused */ }
192 return_t recurse (unsigned int lookup_index)
193 { return default_return_value (); }
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500194
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500195 hb_get_coverage_context_t (void) :
196 debug_depth (0) {}
197
198 unsigned int debug_depth;
Behdad Esfahbod2005fa52012-11-22 14:38:10 -0500199};
200
201
202
Behdad Esfahbod0535b502009-08-28 17:14:33 -0400203#ifndef HB_DEBUG_APPLY
Behdad Esfahbod11e3ec42010-11-03 15:11:04 -0400204#define HB_DEBUG_APPLY (HB_DEBUG+0)
Behdad Esfahbod0535b502009-08-28 17:14:33 -0400205#endif
206
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500207#define TRACE_APPLY(this) \
Behdad Esfahbod902cc8a2012-11-23 15:06:59 -0500208 hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \
209 (&c->debug_depth, "APPLY", this, HB_FUNC, \
210 "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint);
Behdad Esfahbod0535b502009-08-28 17:14:33 -0400211
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400212struct hb_apply_context_t
213{
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500214 inline const char *get_name (void) { return "APPLY"; }
215 static const unsigned int max_debug_depth = HB_DEBUG_APPLY;
Behdad Esfahbodec35a722012-11-22 16:05:59 -0500216 typedef bool return_t;
217 typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
218 template <typename T>
219 inline return_t process (const T &obj) { return obj.apply (this); }
Behdad Esfahboddabe6982012-11-23 14:21:35 -0500220 static return_t default_return_value (void) { return false; }
Behdad Esfahbodec35a722012-11-22 16:05:59 -0500221 bool stop_sublookup_iteration (const return_t r) const { return r; }
222 return_t recurse (unsigned int lookup_index)
223 {
224 if (unlikely (nesting_level_left == 0 || !recurse_func))
225 return default_return_value ();
226
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500227 /* TODO Reuse context. */
Behdad Esfahbodec35a722012-11-22 16:05:59 -0500228 hb_apply_context_t new_c (*this);
229 new_c.nesting_level_left--;
230 return recurse_func (&new_c, lookup_index);
231 }
232
Behdad Esfahbodabcfe9b2011-05-11 00:02:02 -0400233 hb_font_t *font;
234 hb_face_t *face;
Behdad Esfahbod94a23aa2010-05-05 01:13:09 -0400235 hb_buffer_t *buffer;
Behdad Esfahbod744970a2011-05-16 18:15:37 -0400236 hb_direction_t direction;
Behdad Esfahbodf7acd8d2010-05-20 17:26:35 +0100237 hb_mask_t lookup_mask;
Behdad Esfahbodec35a722012-11-22 16:05:59 -0500238 recurse_func_t recurse_func;
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400239 unsigned int nesting_level_left;
Behdad Esfahbod8c69e652010-10-27 22:07:49 -0400240 unsigned int lookup_props;
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400241 unsigned int property; /* propety of first glyph */
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400242 const GDEF &gdef;
Behdad Esfahbod300c7302012-07-30 19:37:44 -0400243 bool has_glyph_classes;
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500244 unsigned int debug_depth;
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400245
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400246
247 hb_apply_context_t (hb_font_t *font_,
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400248 hb_buffer_t *buffer_,
Behdad Esfahbod2bd9fe32012-09-04 15:15:19 -0400249 hb_mask_t lookup_mask_) :
Behdad Esfahbodafbcc242012-08-02 08:36:40 -0400250 font (font_), face (font->face), buffer (buffer_),
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400251 direction (buffer_->props.direction),
252 lookup_mask (lookup_mask_),
Behdad Esfahbodec35a722012-11-22 16:05:59 -0500253 recurse_func (NULL),
Behdad Esfahbod6736f3c2012-05-13 15:21:06 +0200254 nesting_level_left (MAX_NESTING_LEVEL),
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500255 lookup_props (0), property (0),
Behdad Esfahbodafbcc242012-08-02 08:36:40 -0400256 gdef (*hb_ot_layout_from_face (face)->gdef),
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500257 has_glyph_classes (gdef.has_glyph_classes ()),
258 debug_depth (0) {}
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400259
Behdad Esfahbodec35a722012-11-22 16:05:59 -0500260 void set_recurse_func (recurse_func_t func) { recurse_func = func; }
261 void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
262 void set_lookup (const Lookup &l) { lookup_props = l.get_props (); }
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400263
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500264 struct mark_skipping_forward_iterator_t
265 {
266 inline mark_skipping_forward_iterator_t (hb_apply_context_t *c_,
267 unsigned int start_index_,
Behdad Esfahbod203d7102012-05-11 16:01:44 +0200268 unsigned int num_items_,
Behdad Esfahbod28b9d502012-05-13 15:04:00 +0200269 bool context_match = false)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500270 {
271 c = c_;
272 idx = start_index_;
273 num_items = num_items_;
Behdad Esfahbod28b9d502012-05-13 15:04:00 +0200274 mask = context_match ? -1 : c->lookup_mask;
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200275 syllable = context_match ? 0 : c->buffer->cur().syllable ();
Behdad Esfahbod5df809b2012-05-13 15:17:51 +0200276 end = c->buffer->len;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500277 }
278 inline bool has_no_chance (void) const
279 {
280 return unlikely (num_items && idx + num_items >= end);
281 }
Behdad Esfahbodb12e2542012-06-09 03:05:20 -0400282 inline void reject (void)
Behdad Esfahbod7b84c532012-06-08 22:04:23 -0400283 {
284 num_items++;
285 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500286 inline bool next (unsigned int *property_out,
Behdad Esfahbod89328582012-07-19 21:02:38 -0400287 unsigned int lookup_props)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500288 {
Behdad Esfahbod506ffeb2012-01-18 16:07:53 -0500289 assert (num_items > 0);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500290 do
291 {
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500292 if (has_no_chance ())
293 return false;
Behdad Esfahboda4a48fe2012-01-17 18:08:41 -0500294 idx++;
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400295 } while (c->should_skip_mark (&c->buffer->info[idx], lookup_props, property_out));
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500296 num_items--;
Behdad Esfahbod5f131d32012-05-11 17:29:40 +0200297 return (c->buffer->info[idx].mask & mask) && (!syllable || syllable == c->buffer->info[idx].syllable ());
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500298 }
299 inline bool next (unsigned int *property_out = NULL)
300 {
301 return next (property_out, c->lookup_props);
302 }
303
304 unsigned int idx;
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400305 protected:
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500306 hb_apply_context_t *c;
307 unsigned int num_items;
Behdad Esfahbod203d7102012-05-11 16:01:44 +0200308 hb_mask_t mask;
Behdad Esfahbod5f131d32012-05-11 17:29:40 +0200309 uint8_t syllable;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500310 unsigned int end;
311 };
312
313 struct mark_skipping_backward_iterator_t
314 {
315 inline mark_skipping_backward_iterator_t (hb_apply_context_t *c_,
316 unsigned int start_index_,
Behdad Esfahbod203d7102012-05-11 16:01:44 +0200317 unsigned int num_items_,
Behdad Esfahbod5f131d32012-05-11 17:29:40 +0200318 hb_mask_t mask_ = 0,
Behdad Esfahbod6736f3c2012-05-13 15:21:06 +0200319 bool match_syllable_ = true)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500320 {
321 c = c_;
322 idx = start_index_;
323 num_items = num_items_;
Behdad Esfahbod203d7102012-05-11 16:01:44 +0200324 mask = mask_ ? mask_ : c->lookup_mask;
Behdad Esfahbod99c26952012-05-13 15:45:18 +0200325 syllable = match_syllable_ ? c->buffer->cur().syllable () : 0;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500326 }
327 inline bool has_no_chance (void) const
328 {
Behdad Esfahbod506ffeb2012-01-18 16:07:53 -0500329 return unlikely (idx < num_items);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500330 }
Behdad Esfahbodb12e2542012-06-09 03:05:20 -0400331 inline void reject (void)
Behdad Esfahbod7b84c532012-06-08 22:04:23 -0400332 {
333 num_items++;
334 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500335 inline bool prev (unsigned int *property_out,
Behdad Esfahbod89328582012-07-19 21:02:38 -0400336 unsigned int lookup_props)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500337 {
Behdad Esfahbod506ffeb2012-01-18 16:07:53 -0500338 assert (num_items > 0);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500339 do
340 {
341 if (has_no_chance ())
342 return false;
343 idx--;
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400344 } while (c->should_skip_mark (&c->buffer->out_info[idx], lookup_props, property_out));
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500345 num_items--;
Behdad Esfahbod5f131d32012-05-11 17:29:40 +0200346 return (c->buffer->out_info[idx].mask & mask) && (!syllable || syllable == c->buffer->out_info[idx].syllable ());
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500347 }
348 inline bool prev (unsigned int *property_out = NULL)
349 {
350 return prev (property_out, c->lookup_props);
351 }
352
353 unsigned int idx;
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400354 protected:
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500355 hb_apply_context_t *c;
356 unsigned int num_items;
Behdad Esfahbod203d7102012-05-11 16:01:44 +0200357 hb_mask_t mask;
Behdad Esfahbod5f131d32012-05-11 17:29:40 +0200358 uint8_t syllable;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500359 };
360
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400361 inline bool
362 match_properties_mark (hb_codepoint_t glyph,
363 unsigned int glyph_props,
364 unsigned int lookup_props) const
365 {
366 /* If using mark filtering sets, the high short of
367 * lookup_props has the set index.
368 */
369 if (lookup_props & LookupFlag::UseMarkFilteringSet)
370 return gdef.mark_set_covers (lookup_props >> 16, glyph);
371
372 /* The second byte of lookup_props has the meaning
373 * "ignore marks of attachment type different than
374 * the attachment type specified."
375 */
376 if (lookup_props & LookupFlag::MarkAttachmentType)
377 return (lookup_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
378
379 return true;
380 }
381
382 inline bool
383 match_properties (hb_codepoint_t glyph,
384 unsigned int glyph_props,
385 unsigned int lookup_props) const
386 {
387 /* Not covered, if, for example, glyph class is ligature and
388 * lookup_props includes LookupFlags::IgnoreLigatures
389 */
390 if (glyph_props & lookup_props & LookupFlag::IgnoreFlags)
391 return false;
392
Behdad Esfahbod5a08ecf2012-11-16 13:34:29 -0800393 if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400394 return match_properties_mark (glyph, glyph_props, lookup_props);
395
396 return true;
397 }
398
399 inline bool
400 check_glyph_property (hb_glyph_info_t *info,
401 unsigned int lookup_props,
402 unsigned int *property_out) const
Behdad Esfahbod7d479902012-01-18 21:19:32 -0500403 {
Behdad Esfahbodce476132012-06-09 01:10:26 -0400404 unsigned int property;
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400405
Behdad Esfahbodc2e42c32012-07-30 19:54:50 -0400406 property = info->glyph_props();
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400407 *property_out = property;
408
409 return match_properties (info->codepoint, property, lookup_props);
410 }
411
412 inline bool
413 should_skip_mark (hb_glyph_info_t *info,
414 unsigned int lookup_props,
415 unsigned int *property_out) const
416 {
417 unsigned int property;
418
Behdad Esfahbodc2e42c32012-07-30 19:54:50 -0400419 property = info->glyph_props();
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400420 if (property_out)
421 *property_out = property;
422
423 /* If it's a mark, skip it if we don't accept it. */
Behdad Esfahbod5a08ecf2012-11-16 13:34:29 -0800424 if (unlikely (property & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400425 return !match_properties (info->codepoint, property, lookup_props);
426
427 /* If not a mark, don't skip. */
428 return false;
429 }
430
431
432 inline bool should_mark_skip_current_glyph (void) const
433 {
434 return should_skip_mark (&buffer->cur(), lookup_props, NULL);
Behdad Esfahbod7d479902012-01-18 21:19:32 -0500435 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500436
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400437 inline void set_class (hb_codepoint_t glyph_index, unsigned int class_guess) const
Behdad Esfahbod60da7632012-07-16 16:13:32 -0400438 {
Behdad Esfahbod2fca1422012-07-30 18:46:41 -0400439 if (likely (has_glyph_classes))
Behdad Esfahbodc2e42c32012-07-30 19:54:50 -0400440 buffer->cur().glyph_props() = gdef.get_glyph_props (glyph_index);
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400441 else if (class_guess)
Behdad Esfahbodc2e42c32012-07-30 19:54:50 -0400442 buffer->cur().glyph_props() = class_guess;
Behdad Esfahbod60da7632012-07-16 16:13:32 -0400443 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500444
Behdad Esfahbod3ec77d62012-06-08 21:44:06 -0400445 inline void output_glyph (hb_codepoint_t glyph_index,
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400446 unsigned int class_guess = 0) const
Behdad Esfahbod3ec77d62012-06-08 21:44:06 -0400447 {
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400448 set_class (glyph_index, class_guess);
Behdad Esfahbod3ec77d62012-06-08 21:44:06 -0400449 buffer->output_glyph (glyph_index);
450 }
Behdad Esfahboded2f1362012-05-22 22:12:22 -0400451 inline void replace_glyph (hb_codepoint_t glyph_index,
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400452 unsigned int class_guess = 0) const
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400453 {
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400454 set_class (glyph_index, class_guess);
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400455 buffer->replace_glyph (glyph_index);
456 }
Behdad Esfahbod7fbbf862012-07-30 18:36:42 -0400457 inline void replace_glyph_inplace (hb_codepoint_t glyph_index,
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400458 unsigned int class_guess = 0) const
Behdad Esfahbod7fbbf862012-07-30 18:36:42 -0400459 {
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400460 set_class (glyph_index, class_guess);
Behdad Esfahbod7fbbf862012-07-30 18:36:42 -0400461 buffer->cur().codepoint = glyph_index;
462 }
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400463};
464
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400465
Behdad Esfahbod94a23aa2010-05-05 01:13:09 -0400466
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400467typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400468typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400469
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400470struct ContextClosureFuncs
471{
472 intersects_func_t intersects;
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400473};
474struct ContextApplyFuncs
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400475{
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400476 match_func_t match;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400477};
478
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400479static inline bool intersects_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400480{
481 return glyphs->has (value);
482}
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400483static inline bool intersects_class (hb_set_t *glyphs, const USHORT &value, const void *data)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400484{
485 const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
486 return class_def.intersects_class (glyphs, value);
487}
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400488static inline bool intersects_coverage (hb_set_t *glyphs, const USHORT &value, const void *data)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400489{
490 const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
491 return (data+coverage).intersects (glyphs);
492}
493
494static inline bool intersects_array (hb_closure_context_t *c,
495 unsigned int count,
496 const USHORT values[],
497 intersects_func_t intersects_func,
498 const void *intersects_data)
499{
500 for (unsigned int i = 0; i < count; i++)
501 if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
502 return false;
503 return true;
504}
505
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400506
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400507static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, const void *data HB_UNUSED)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400508{
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400509 return glyph_id == value;
510}
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400511static inline bool match_class (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400512{
Behdad Esfahbod2b5a59c2009-08-04 11:38:50 -0400513 const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400514 return class_def.get_class (glyph_id) == value;
515}
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400516static inline bool match_coverage (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400517{
Behdad Esfahbod6b54c5d2009-05-18 18:30:25 -0400518 const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400519 return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400520}
521
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400522
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400523static inline bool would_match_input (hb_would_apply_context_t *c,
524 unsigned int count, /* Including the first glyph (not matched) */
525 const USHORT input[], /* Array of input values--start with second glyph */
526 match_func_t match_func,
527 const void *match_data)
528{
529 if (count != c->len)
530 return false;
531
532 for (unsigned int i = 1; i < count; i++)
Behdad Esfahbod472f2292012-08-07 22:25:24 -0400533 if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400534 return false;
535
536 return true;
537}
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400538static inline bool match_input (hb_apply_context_t *c,
Behdad Esfahbode072c242009-05-18 03:47:31 -0400539 unsigned int count, /* Including the first glyph (not matched) */
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400540 const USHORT input[], /* Array of input values--start with second glyph */
541 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400542 const void *match_data,
Behdad Esfahbod191fa882012-08-28 22:58:55 -0400543 unsigned int *end_offset = NULL,
544 bool *p_is_mark_ligature = NULL,
545 unsigned int *p_total_component_count = NULL)
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400546{
Behdad Esfahbod73c18ae2012-11-23 15:34:11 -0500547 TRACE_APPLY (NULL);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400548
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500549 hb_apply_context_t::mark_skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400550 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
551
Behdad Esfahbod191fa882012-08-28 22:58:55 -0400552 /*
553 * This is perhaps the trickiest part of OpenType... Remarks:
554 *
555 * - If all components of the ligature were marks, we call this a mark ligature.
556 *
557 * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
558 * it as a ligature glyph.
559 *
560 * - Ligatures cannot be formed across glyphs attached to different components
561 * of previous ligatures. Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
562 * LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
563 * However, it would be wrong to ligate that SHADDA,FATHA sequence.o
564 * There is an exception to this: If a ligature tries ligating with marks that
565 * belong to it itself, go ahead, assuming that the font designer knows what
566 * they are doing (otherwise it can break Indic stuff when a matra wants to
567 * ligate with a conjunct...)
568 */
569
Behdad Esfahbod5a08ecf2012-11-16 13:34:29 -0800570 bool is_mark_ligature = !!(c->property & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400571
572 unsigned int total_component_count = 0;
573 total_component_count += get_lig_num_comps (c->buffer->cur());
574
575 unsigned int first_lig_id = get_lig_id (c->buffer->cur());
576 unsigned int first_lig_comp = get_lig_comp (c->buffer->cur());
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400577
Behdad Esfahbod370f03e2012-01-16 17:03:55 -0500578 for (unsigned int i = 1; i < count; i++)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400579 {
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400580 unsigned int property;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400581
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400582 if (!skippy_iter.next (&property)) return TRACE_RETURN (false);
583
Behdad Esfahbod26166892012-10-29 21:51:56 -0700584 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 -0400585
586 unsigned int this_lig_id = get_lig_id (c->buffer->info[skippy_iter.idx]);
587 unsigned int this_lig_comp = get_lig_comp (c->buffer->info[skippy_iter.idx]);
588
589 if (first_lig_id && first_lig_comp) {
590 /* If first component was attached to a previous ligature component,
591 * all subsequent components should be attached to the same ligature
592 * component, otherwise we shouldn't ligate them. */
593 if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
594 return TRACE_RETURN (false);
595 } else {
596 /* If first component was NOT attached to a previous ligature component,
597 * all subsequent components should also NOT be attached to any ligature
598 * component, unless they are attached to the first component itself! */
599 if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
600 return TRACE_RETURN (false);
601 }
602
Behdad Esfahbod5a08ecf2012-11-16 13:34:29 -0800603 is_mark_ligature = is_mark_ligature && (property & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400604 total_component_count += get_lig_num_comps (c->buffer->info[skippy_iter.idx]);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400605 }
606
Behdad Esfahbod5df809b2012-05-13 15:17:51 +0200607 if (end_offset)
608 *end_offset = skippy_iter.idx - c->buffer->idx + 1;
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400609
Behdad Esfahbod191fa882012-08-28 22:58:55 -0400610 if (p_is_mark_ligature)
611 *p_is_mark_ligature = is_mark_ligature;
612
613 if (p_total_component_count)
614 *p_total_component_count = total_component_count;
615
Behdad Esfahbodbc513ad2012-10-29 19:03:55 -0700616 return TRACE_RETURN (true);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400617}
Behdad Esfahboda177d022012-08-28 23:18:22 -0400618static inline void ligate_input (hb_apply_context_t *c,
619 unsigned int count, /* Including the first glyph (not matched) */
620 const USHORT input[], /* Array of input values--start with second glyph */
621 hb_codepoint_t lig_glyph,
622 match_func_t match_func,
623 const void *match_data,
Behdad Esfahboda177d022012-08-28 23:18:22 -0400624 bool is_mark_ligature,
625 unsigned int total_component_count)
626{
627 /*
628 * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave
629 * the ligature to keep its old ligature id. This will allow it to attach to
630 * a base ligature in GPOS. Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
631 * and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA wit a
632 * ligature id and component value of 2. Then if SHADDA,FATHA form a ligature
633 * later, we don't want them to lose their ligature id/component, otherwise
634 * GPOS will fail to correctly position the mark ligature on top of the
635 * LAM,LAM,HEH ligature. See:
636 * https://bugzilla.gnome.org/show_bug.cgi?id=676343
637 *
638 * - If a ligature is formed of components that some of which are also ligatures
639 * themselves, and those ligature components had marks attached to *their*
640 * components, we have to attach the marks to the new ligature component
641 * positions! Now *that*'s tricky! And these marks may be following the
642 * last component of the whole sequence, so we should loop forward looking
643 * for them and update them.
644 *
645 * Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
646 * 'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
647 * id and component == 1. Now, during 'liga', the LAM and the LAM-HEH ligature
648 * form a LAM-LAM-HEH ligature. We need to reassign the SHADDA and FATHA to
649 * the new ligature with a component value of 2.
650 *
651 * This in fact happened to a font... See:
652 * https://bugzilla.gnome.org/show_bug.cgi?id=437633
653 */
654
Behdad Esfahbod5a08ecf2012-11-16 13:34:29 -0800655 unsigned int klass = is_mark_ligature ? 0 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
Behdad Esfahboda177d022012-08-28 23:18:22 -0400656 unsigned int lig_id = is_mark_ligature ? 0 : allocate_lig_id (c->buffer);
657 unsigned int last_lig_id = get_lig_id (c->buffer->cur());
658 unsigned int last_num_components = get_lig_num_comps (c->buffer->cur());
659 unsigned int components_so_far = last_num_components;
660
661 if (!is_mark_ligature)
662 set_lig_props_for_ligature (c->buffer->cur(), lig_id, total_component_count);
663 c->replace_glyph (lig_glyph, klass);
664
665 for (unsigned int i = 1; i < count; i++)
666 {
667 while (c->should_mark_skip_current_glyph ())
668 {
669 if (!is_mark_ligature) {
670 unsigned int new_lig_comp = components_so_far - last_num_components +
671 MIN (MAX (get_lig_comp (c->buffer->cur()), 1u), last_num_components);
672 set_lig_props_for_mark (c->buffer->cur(), lig_id, new_lig_comp);
673 }
674 c->buffer->next_glyph ();
675 }
676
677 last_lig_id = get_lig_id (c->buffer->cur());
678 last_num_components = get_lig_num_comps (c->buffer->cur());
679 components_so_far += last_num_components;
680
681 /* Skip the base glyph */
682 c->buffer->idx++;
683 }
684
685 if (!is_mark_ligature && last_lig_id) {
686 /* Re-adjust components for any marks following. */
687 for (unsigned int i = c->buffer->idx; i < c->buffer->len; i++) {
688 if (last_lig_id == get_lig_id (c->buffer->info[i])) {
689 unsigned int new_lig_comp = components_so_far - last_num_components +
690 MIN (MAX (get_lig_comp (c->buffer->info[i]), 1u), last_num_components);
691 set_lig_props_for_mark (c->buffer->info[i], lig_id, new_lig_comp);
692 } else
693 break;
694 }
695 }
696}
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400697
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400698static inline bool match_backtrack (hb_apply_context_t *c,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400699 unsigned int count,
700 const USHORT backtrack[],
701 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400702 const void *match_data)
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400703{
Behdad Esfahbod73c18ae2012-11-23 15:34:11 -0500704 TRACE_APPLY (NULL);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400705
Behdad Esfahbod28b9d502012-05-13 15:04:00 +0200706 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 -0500707 if (skippy_iter.has_no_chance ())
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400708 return TRACE_RETURN (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400709
Behdad Esfahbod4d3aeb82012-01-16 16:43:26 -0500710 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400711 {
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500712 if (!skippy_iter.prev ())
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400713 return TRACE_RETURN (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400714
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500715 if (likely (!match_func (c->buffer->out_info[skippy_iter.idx].codepoint, backtrack[i], match_data)))
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400716 return TRACE_RETURN (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400717 }
718
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400719 return TRACE_RETURN (true);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400720}
721
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400722static inline bool match_lookahead (hb_apply_context_t *c,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400723 unsigned int count,
724 const USHORT lookahead[],
725 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400726 const void *match_data,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400727 unsigned int offset)
728{
Behdad Esfahbod73c18ae2012-11-23 15:34:11 -0500729 TRACE_APPLY (NULL);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400730
Behdad Esfahbod28b9d502012-05-13 15:04:00 +0200731 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 -0500732 if (skippy_iter.has_no_chance ())
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400733 return TRACE_RETURN (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400734
Behdad Esfahbod370f03e2012-01-16 17:03:55 -0500735 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400736 {
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500737 if (!skippy_iter.next ())
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400738 return TRACE_RETURN (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400739
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500740 if (likely (!match_func (c->buffer->info[skippy_iter.idx].codepoint, lookahead[i], match_data)))
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400741 return TRACE_RETURN (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400742 }
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400743
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400744 return TRACE_RETURN (true);
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400745}
746
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400747
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400748
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400749struct LookupRecord
750{
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400751 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500752 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200753 return TRACE_RETURN (c->check_struct (this));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -0400754 }
755
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400756 USHORT sequenceIndex; /* Index into current glyph
757 * sequence--first glyph = 0 */
758 USHORT lookupListIndex; /* Lookup to apply to that
759 * position--zero--based */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400760 public:
761 DEFINE_SIZE_STATIC (4);
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400762};
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400763
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400764
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400765static inline void closure_lookup (hb_closure_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400766 unsigned int lookupCount,
Behdad Esfahbod44fc2372012-11-21 23:33:13 -0500767 const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400768{
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400769 for (unsigned int i = 0; i < lookupCount; i++)
Behdad Esfahbod44fc2372012-11-21 23:33:13 -0500770 c->recurse (lookupRecord->lookupListIndex);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400771}
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400772
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400773static inline bool apply_lookup (hb_apply_context_t *c,
Behdad Esfahbode072c242009-05-18 03:47:31 -0400774 unsigned int count, /* Including the first glyph */
775 unsigned int lookupCount,
Behdad Esfahbodec35a722012-11-22 16:05:59 -0500776 const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400777{
Behdad Esfahbod73c18ae2012-11-23 15:34:11 -0500778 TRACE_APPLY (NULL);
Behdad Esfahbod902cc8a2012-11-23 15:06:59 -0500779
Behdad Esfahbod5df809b2012-05-13 15:17:51 +0200780 unsigned int end = c->buffer->len;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400781 if (unlikely (count == 0 || c->buffer->idx + count > end))
Behdad Esfahbod26166892012-10-29 21:51:56 -0700782 return TRACE_RETURN (false);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400783
Behdad Esfahbod7cff75b2009-05-18 04:09:05 -0400784 /* TODO We don't support lookupRecord arrays that are not increasing:
785 * Should be easy for in_place ones at least. */
Behdad Esfahbod52e9a712009-09-21 13:58:56 -0400786
Behdad Esfahbod7eb87512010-12-13 14:13:35 -0500787 /* Note: If sublookup is reverse, it will underflow after the first loop
Behdad Esfahbod52e9a712009-09-21 13:58:56 -0400788 * and we jump out of it. Not entirely disastrous. So we don't check
789 * for reverse lookup here.
790 */
Behdad Esfahbodf9c0a2d2009-09-21 13:43:54 -0400791 for (unsigned int i = 0; i < count; /* NOP */)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400792 {
Behdad Esfahbod03408ce2012-01-18 21:28:34 -0500793 if (unlikely (c->buffer->idx == end))
Behdad Esfahbod26166892012-10-29 21:51:56 -0700794 return TRACE_RETURN (true);
Behdad Esfahbod7d479902012-01-18 21:19:32 -0500795 while (c->should_mark_skip_current_glyph ())
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400796 {
Behdad Esfahbode73a0c22009-05-18 04:15:25 -0400797 /* No lookup applied for this index */
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400798 c->buffer->next_glyph ();
Behdad Esfahbod03408ce2012-01-18 21:28:34 -0500799 if (unlikely (c->buffer->idx == end))
Behdad Esfahbod26166892012-10-29 21:51:56 -0700800 return TRACE_RETURN (true);
Behdad Esfahbode73a0c22009-05-18 04:15:25 -0400801 }
802
Behdad Esfahbod47958de2009-05-18 04:17:47 -0400803 if (lookupCount && i == lookupRecord->sequenceIndex)
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400804 {
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400805 unsigned int old_pos = c->buffer->idx;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400806
807 /* Apply a lookup */
Behdad Esfahbodec35a722012-11-22 16:05:59 -0500808 bool done = c->recurse (lookupRecord->lookupListIndex);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400809
Behdad Esfahbod47958de2009-05-18 04:17:47 -0400810 lookupRecord++;
811 lookupCount--;
Behdad Esfahbodf9c0a2d2009-09-21 13:43:54 -0400812 /* Err, this is wrong if the lookup jumped over some glyphs */
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400813 i += c->buffer->idx - old_pos;
814 if (unlikely (c->buffer->idx == end))
Behdad Esfahbod26166892012-10-29 21:51:56 -0700815 return TRACE_RETURN (true);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400816
817 if (!done)
818 goto not_applied;
819 }
820 else
821 {
822 not_applied:
823 /* No lookup applied for this index */
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400824 c->buffer->next_glyph ();
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400825 i++;
826 }
827 }
828
Behdad Esfahbod26166892012-10-29 21:51:56 -0700829 return TRACE_RETURN (true);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400830}
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400831
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400832
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400833
834/* Contextual lookups */
835
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400836struct ContextClosureLookupContext
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400837{
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400838 ContextClosureFuncs funcs;
839 const void *intersects_data;
840};
841
842struct ContextApplyLookupContext
843{
844 ContextApplyFuncs funcs;
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400845 const void *match_data;
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400846};
847
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400848static inline void context_closure_lookup (hb_closure_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400849 unsigned int inputCount, /* Including the first glyph (not matched) */
850 const USHORT input[], /* Array of input values--start with second glyph */
851 unsigned int lookupCount,
852 const LookupRecord lookupRecord[],
853 ContextClosureLookupContext &lookup_context)
854{
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400855 if (intersects_array (c,
856 inputCount ? inputCount - 1 : 0, input,
857 lookup_context.funcs.intersects, lookup_context.intersects_data))
858 closure_lookup (c,
Behdad Esfahbod44fc2372012-11-21 23:33:13 -0500859 lookupCount, lookupRecord);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400860}
861
862
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400863static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
864 unsigned int inputCount, /* Including the first glyph (not matched) */
865 const USHORT input[], /* Array of input values--start with second glyph */
866 unsigned int lookupCount,
867 const LookupRecord lookupRecord[],
868 ContextApplyLookupContext &lookup_context)
869{
870 return would_match_input (c,
871 inputCount, input,
872 lookup_context.funcs.match, lookup_context.match_data);
873}
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400874static inline bool context_apply_lookup (hb_apply_context_t *c,
875 unsigned int inputCount, /* Including the first glyph (not matched) */
876 const USHORT input[], /* Array of input values--start with second glyph */
877 unsigned int lookupCount,
878 const LookupRecord lookupRecord[],
879 ContextApplyLookupContext &lookup_context)
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400880{
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400881 return match_input (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -0400882 inputCount, input,
Behdad Esfahbod5df809b2012-05-13 15:17:51 +0200883 lookup_context.funcs.match, lookup_context.match_data)
884 && apply_lookup (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -0400885 inputCount,
Behdad Esfahbodec35a722012-11-22 16:05:59 -0500886 lookupCount, lookupRecord);
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400887}
888
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400889struct Rule
890{
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400891 inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400892 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500893 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400894 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400895 context_closure_lookup (c,
896 inputCount, input,
897 lookupCount, lookupRecord,
898 lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400899 }
900
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400901 inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
902 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500903 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400904 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
905 return TRACE_RETURN (context_would_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context));
906 }
907
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400908 inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400909 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500910 TRACE_APPLY (this);
Behdad Esfahbode45d3f82010-05-06 19:33:31 -0400911 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200912 return TRACE_RETURN (context_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400913 }
914
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400915 public:
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400916 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500917 TRACE_SANITIZE (this);
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400918 return inputCount.sanitize (c)
919 && lookupCount.sanitize (c)
920 && c->check_range (input,
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400921 input[0].static_size * inputCount
922 + lookupRecordX[0].static_size * lookupCount);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400923 }
924
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400925 protected:
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400926 USHORT inputCount; /* Total number of glyphs in input
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400927 * glyph sequence--includes the first
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400928 * glyph */
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400929 USHORT lookupCount; /* Number of LookupRecords */
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -0500930 USHORT input[VAR]; /* Array of match inputs--start with
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400931 * second glyph */
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -0500932 LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400933 * design order */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400934 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400935 DEFINE_SIZE_ARRAY2 (4, input, lookupRecordX);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400936};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400937
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400938struct RuleSet
939{
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400940 inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400941 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500942 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400943 unsigned int num_rules = rule.len;
944 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbod5caece62012-04-23 23:03:12 -0400945 (this+rule[i]).closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400946 }
947
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400948 inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
949 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500950 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400951 unsigned int num_rules = rule.len;
952 for (unsigned int i = 0; i < num_rules; i++)
953 {
954 if ((this+rule[i]).would_apply (c, lookup_context))
955 return TRACE_RETURN (true);
956 }
957 return TRACE_RETURN (false);
958 }
959
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400960 inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400961 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500962 TRACE_APPLY (this);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400963 unsigned int num_rules = rule.len;
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400964 for (unsigned int i = 0; i < num_rules; i++)
965 {
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400966 if ((this+rule[i]).apply (c, lookup_context))
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200967 return TRACE_RETURN (true);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400968 }
Behdad Esfahbodacea1832012-05-11 02:33:11 +0200969 return TRACE_RETURN (false);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400970 }
971
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400972 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500973 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200974 return TRACE_RETURN (rule.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -0400975 }
976
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400977 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400978 OffsetArrayOf<Rule>
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400979 rule; /* Array of Rule tables
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400980 * ordered by preference */
Behdad Esfahboded074222010-05-10 18:08:46 -0400981 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -0400982 DEFINE_SIZE_ARRAY (2, rule);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400983};
984
985
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400986struct ContextFormat1
987{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -0500988 inline void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400989 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500990 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400991
992 const Coverage &cov = (this+coverage);
993
994 struct ContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -0500995 {intersects_glyph},
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400996 NULL
997 };
998
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400999 unsigned int count = ruleSet.len;
1000 for (unsigned int i = 0; i < count; i++)
1001 if (cov.intersects_coverage (c->glyphs, i)) {
1002 const RuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001003 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001004 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001005 }
1006
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001007 inline bool would_apply (hb_would_apply_context_t *c) const
1008 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001009 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001010
Behdad Esfahbod472f2292012-08-07 22:25:24 -04001011 const RuleSet &rule_set = this+ruleSet[(this+coverage) (c->glyphs[0])];
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001012 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001013 {match_glyph},
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001014 NULL
1015 };
1016 return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
1017 }
1018
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001019 inline const Coverage &get_coverage (void) const
1020 {
1021 return this+coverage;
1022 }
1023
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001024 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001025 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001026 TRACE_APPLY (this);
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001027 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
Behdad Esfahbod64d3fc82010-05-03 22:51:19 -04001028 if (likely (index == NOT_COVERED))
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001029 return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001030
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001031 const RuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001032 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001033 {match_glyph},
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001034 NULL
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001035 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001036 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001037 }
1038
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001039 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001040 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001041 return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001042 }
1043
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001044 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001045 USHORT format; /* Format identifier--format = 1 */
1046 OffsetTo<Coverage>
1047 coverage; /* Offset to Coverage table--from
1048 * beginning of table */
1049 OffsetArrayOf<RuleSet>
1050 ruleSet; /* Array of RuleSet tables
1051 * ordered by Coverage Index */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001052 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001053 DEFINE_SIZE_ARRAY (6, ruleSet);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001054};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001055
1056
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001057struct ContextFormat2
1058{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001059 inline void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001060 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001061 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001062 if (!(this+coverage).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001063 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001064
1065 const ClassDef &class_def = this+classDef;
1066
1067 struct ContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001068 {intersects_class},
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001069 NULL
1070 };
1071
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001072 unsigned int count = ruleSet.len;
1073 for (unsigned int i = 0; i < count; i++)
1074 if (class_def.intersects_class (c->glyphs, i)) {
1075 const RuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001076 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001077 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001078 }
1079
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001080 inline bool would_apply (hb_would_apply_context_t *c) const
1081 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001082 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001083
1084 const ClassDef &class_def = this+classDef;
Behdad Esfahbod472f2292012-08-07 22:25:24 -04001085 unsigned int index = class_def (c->glyphs[0]);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001086 const RuleSet &rule_set = this+ruleSet[index];
1087 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001088 {match_class},
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001089 &class_def
1090 };
1091 return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
1092 }
1093
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001094 inline const Coverage &get_coverage (void) const
1095 {
1096 return this+coverage;
1097 }
1098
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001099 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001100 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001101 TRACE_APPLY (this);
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001102 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001103 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001104
1105 const ClassDef &class_def = this+classDef;
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001106 index = class_def (c->buffer->cur().codepoint);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001107 const RuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001108 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001109 {match_class},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001110 &class_def
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001111 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001112 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001113 }
1114
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001115 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001116 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001117 return TRACE_RETURN (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001118 }
1119
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001120 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001121 USHORT format; /* Format identifier--format = 2 */
1122 OffsetTo<Coverage>
1123 coverage; /* Offset to Coverage table--from
1124 * beginning of table */
1125 OffsetTo<ClassDef>
1126 classDef; /* Offset to glyph ClassDef table--from
1127 * beginning of table */
1128 OffsetArrayOf<RuleSet>
1129 ruleSet; /* Array of RuleSet tables
1130 * ordered by class */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001131 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001132 DEFINE_SIZE_ARRAY (8, ruleSet);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001133};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001134
1135
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001136struct ContextFormat3
1137{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001138 inline void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001139 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001140 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001141 if (!(this+coverage[0]).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001142 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001143
1144 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
1145 struct ContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001146 {intersects_coverage},
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001147 this
1148 };
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001149 context_closure_lookup (c,
1150 glyphCount, (const USHORT *) (coverage + 1),
1151 lookupCount, lookupRecord,
1152 lookup_context);
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001153 }
1154
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001155 inline bool would_apply (hb_would_apply_context_t *c) const
1156 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001157 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001158
1159 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
1160 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001161 {match_coverage},
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001162 this
1163 };
1164 return TRACE_RETURN (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context));
1165 }
1166
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001167 inline const Coverage &get_coverage (void) const
1168 {
1169 return this+coverage[0];
1170 }
1171
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001172 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001173 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001174 TRACE_APPLY (this);
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001175 unsigned int index = (this+coverage[0]) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001176 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001177
Behdad Esfahbode45d3f82010-05-06 19:33:31 -04001178 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001179 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001180 {match_coverage},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001181 this
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001182 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001183 return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001184 }
1185
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001186 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001187 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001188 if (!c->check_struct (this)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001189 unsigned int count = glyphCount;
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001190 if (!c->check_array (coverage, coverage[0].static_size, count)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001191 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001192 if (!coverage[i].sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode45d3f82010-05-06 19:33:31 -04001193 LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * count);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001194 return TRACE_RETURN (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001195 }
1196
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001197 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001198 USHORT format; /* Format identifier--format = 3 */
1199 USHORT glyphCount; /* Number of glyphs in the input glyph
1200 * sequence */
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001201 USHORT lookupCount; /* Number of LookupRecords */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001202 OffsetTo<Coverage>
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -05001203 coverage[VAR]; /* Array of offsets to Coverage
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001204 * table in glyph sequence order */
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -05001205 LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001206 * design order */
Behdad Esfahbod569da922010-05-10 16:38:32 -04001207 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001208 DEFINE_SIZE_ARRAY2 (6, coverage, lookupRecordX);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001209};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001210
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001211struct Context
1212{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001213 template <typename context_t>
1214 inline typename context_t::return_t process (context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001215 {
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001216 switch (u.format) {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001217 case 1: return c->process (u.format1);
1218 case 2: return c->process (u.format2);
1219 case 3: return c->process (u.format3);
Behdad Esfahbod2005fa52012-11-22 14:38:10 -05001220 default:return c->default_return_value ();
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001221 }
1222 }
1223
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001224 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001225 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001226 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001227 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001228 case 1: return TRACE_RETURN (u.format1.sanitize (c));
1229 case 2: return TRACE_RETURN (u.format2.sanitize (c));
1230 case 3: return TRACE_RETURN (u.format3.sanitize (c));
1231 default:return TRACE_RETURN (true);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001232 }
1233 }
1234
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001235 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001236 union {
Behdad Esfahbodf8dc67b2009-05-17 19:47:54 -04001237 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001238 ContextFormat1 format1;
1239 ContextFormat2 format2;
1240 ContextFormat3 format3;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001241 } u;
1242};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001243
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001244
1245/* Chaining Contextual lookups */
1246
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001247struct ChainContextClosureLookupContext
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001248{
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001249 ContextClosureFuncs funcs;
1250 const void *intersects_data[3];
1251};
1252
1253struct ChainContextApplyLookupContext
1254{
1255 ContextApplyFuncs funcs;
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001256 const void *match_data[3];
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001257};
1258
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001259static inline void chain_context_closure_lookup (hb_closure_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001260 unsigned int backtrackCount,
1261 const USHORT backtrack[],
1262 unsigned int inputCount, /* Including the first glyph (not matched) */
1263 const USHORT input[], /* Array of input values--start with second glyph */
1264 unsigned int lookaheadCount,
1265 const USHORT lookahead[],
1266 unsigned int lookupCount,
1267 const LookupRecord lookupRecord[],
1268 ChainContextClosureLookupContext &lookup_context)
1269{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001270 if (intersects_array (c,
1271 backtrackCount, backtrack,
1272 lookup_context.funcs.intersects, lookup_context.intersects_data[0])
1273 && intersects_array (c,
1274 inputCount ? inputCount - 1 : 0, input,
1275 lookup_context.funcs.intersects, lookup_context.intersects_data[1])
1276 && intersects_array (c,
1277 lookaheadCount, lookahead,
1278 lookup_context.funcs.intersects, lookup_context.intersects_data[2]))
1279 closure_lookup (c,
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001280 lookupCount, lookupRecord);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001281}
1282
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001283static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
1284 unsigned int backtrackCount,
1285 const USHORT backtrack[],
1286 unsigned int inputCount, /* Including the first glyph (not matched) */
1287 const USHORT input[], /* Array of input values--start with second glyph */
1288 unsigned int lookaheadCount,
1289 const USHORT lookahead[],
1290 unsigned int lookupCount,
1291 const LookupRecord lookupRecord[],
1292 ChainContextApplyLookupContext &lookup_context)
1293{
Behdad Esfahbodd9b204d2012-08-23 16:22:28 -04001294 return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
Behdad Esfahbod1f2bb172012-08-23 16:10:37 -04001295 && would_match_input (c,
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001296 inputCount, input,
1297 lookup_context.funcs.match, lookup_context.match_data[1]);
1298}
1299
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001300static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
1301 unsigned int backtrackCount,
1302 const USHORT backtrack[],
1303 unsigned int inputCount, /* Including the first glyph (not matched) */
1304 const USHORT input[], /* Array of input values--start with second glyph */
1305 unsigned int lookaheadCount,
1306 const USHORT lookahead[],
1307 unsigned int lookupCount,
1308 const LookupRecord lookupRecord[],
1309 ChainContextApplyLookupContext &lookup_context)
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001310{
Behdad Esfahbodc779d822012-11-23 14:07:24 -05001311 unsigned int lookahead_offset = 0;
Behdad Esfahbodf19e0b02012-06-09 02:26:57 -04001312 return match_input (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -04001313 inputCount, input,
1314 lookup_context.funcs.match, lookup_context.match_data[1],
Behdad Esfahbod5df809b2012-05-13 15:17:51 +02001315 &lookahead_offset)
Behdad Esfahbodf19e0b02012-06-09 02:26:57 -04001316 && match_backtrack (c,
1317 backtrackCount, backtrack,
1318 lookup_context.funcs.match, lookup_context.match_data[0])
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001319 && match_lookahead (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -04001320 lookaheadCount, lookahead,
1321 lookup_context.funcs.match, lookup_context.match_data[2],
Behdad Esfahbod5df809b2012-05-13 15:17:51 +02001322 lookahead_offset)
1323 && apply_lookup (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -04001324 inputCount,
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001325 lookupCount, lookupRecord);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001326}
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001327
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001328struct ChainRule
1329{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001330 inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001331 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001332 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001333 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
1334 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
1335 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001336 chain_context_closure_lookup (c,
1337 backtrack.len, backtrack.array,
1338 input.len, input.array,
1339 lookahead.len, lookahead.array,
1340 lookup.len, lookup.array,
1341 lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001342 }
1343
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001344 inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
1345 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001346 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001347 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
1348 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
1349 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1350 return TRACE_RETURN (chain_context_would_apply_lookup (c,
1351 backtrack.len, backtrack.array,
1352 input.len, input.array,
1353 lookahead.len, lookahead.array, lookup.len,
1354 lookup.array, lookup_context));
1355 }
1356
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001357 inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001358 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001359 TRACE_APPLY (this);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001360 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
1361 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
1362 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001363 return TRACE_RETURN (chain_context_apply_lookup (c,
1364 backtrack.len, backtrack.array,
1365 input.len, input.array,
1366 lookahead.len, lookahead.array, lookup.len,
1367 lookup.array, lookup_context));
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001368 }
1369
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001370 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001371 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001372 if (!backtrack.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001373 HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001374 if (!input.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001375 ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001376 if (!lookahead.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001377 ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001378 return TRACE_RETURN (lookup.sanitize (c));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001379 }
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001380
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001381 protected:
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001382 ArrayOf<USHORT>
1383 backtrack; /* Array of backtracking values
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001384 * (to be matched before the input
1385 * sequence) */
Behdad Esfahbode8cbaaf2009-05-18 02:03:58 -04001386 HeadlessArrayOf<USHORT>
1387 inputX; /* Array of input values (start with
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001388 * second glyph) */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001389 ArrayOf<USHORT>
1390 lookaheadX; /* Array of lookahead values's (to be
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001391 * matched after the input sequence) */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001392 ArrayOf<LookupRecord>
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001393 lookupX; /* Array of LookupRecords--in
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001394 * design order) */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001395 public:
Behdad Esfahbodbea34c72010-05-10 17:28:16 -04001396 DEFINE_SIZE_MIN (8);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001397};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001398
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001399struct ChainRuleSet
1400{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001401 inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001402 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001403 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001404 unsigned int num_rules = rule.len;
1405 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001406 (this+rule[i]).closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001407 }
1408
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001409 inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
1410 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001411 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001412 unsigned int num_rules = rule.len;
1413 for (unsigned int i = 0; i < num_rules; i++)
1414 if ((this+rule[i]).would_apply (c, lookup_context))
1415 return TRACE_RETURN (true);
1416
1417 return TRACE_RETURN (false);
1418 }
1419
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001420 inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001421 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001422 TRACE_APPLY (this);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001423 unsigned int num_rules = rule.len;
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001424 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001425 if ((this+rule[i]).apply (c, lookup_context))
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001426 return TRACE_RETURN (true);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001427
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001428 return TRACE_RETURN (false);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001429 }
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001430
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001431 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001432 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001433 return TRACE_RETURN (rule.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001434 }
1435
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001436 protected:
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001437 OffsetArrayOf<ChainRule>
1438 rule; /* Array of ChainRule tables
1439 * ordered by preference */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001440 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001441 DEFINE_SIZE_ARRAY (2, rule);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001442};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001443
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001444struct ChainContextFormat1
1445{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001446 inline void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001447 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001448 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001449 const Coverage &cov = (this+coverage);
1450
1451 struct ChainContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001452 {intersects_glyph},
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001453 {NULL, NULL, NULL}
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 (cov.intersects_coverage (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 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001466 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001467
Behdad Esfahbod472f2292012-08-07 22:25:24 -04001468 const ChainRuleSet &rule_set = this+ruleSet[(this+coverage) (c->glyphs[0])];
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001469 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001470 {match_glyph},
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001471 {NULL, NULL, NULL}
1472 };
1473 return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
1474 }
1475
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001476 inline const Coverage &get_coverage (void) const
1477 {
1478 return this+coverage;
1479 }
1480
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001481 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001482 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001483 TRACE_APPLY (this);
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001484 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001485 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001486
1487 const ChainRuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001488 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001489 {match_glyph},
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001490 {NULL, NULL, NULL}
1491 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001492 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001493 }
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001494
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001495 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001496 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001497 return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001498 }
1499
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001500 protected:
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001501 USHORT format; /* Format identifier--format = 1 */
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001502 OffsetTo<Coverage>
1503 coverage; /* Offset to Coverage table--from
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001504 * beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001505 OffsetArrayOf<ChainRuleSet>
1506 ruleSet; /* Array of ChainRuleSet tables
1507 * ordered by Coverage Index */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001508 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001509 DEFINE_SIZE_ARRAY (6, ruleSet);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001510};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001511
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001512struct ChainContextFormat2
1513{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001514 inline void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001515 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001516 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001517 if (!(this+coverage).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001518 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001519
1520 const ClassDef &backtrack_class_def = this+backtrackClassDef;
1521 const ClassDef &input_class_def = this+inputClassDef;
1522 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
1523
1524 struct ChainContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001525 {intersects_class},
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001526 {&backtrack_class_def,
1527 &input_class_def,
1528 &lookahead_class_def}
1529 };
1530
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001531 unsigned int count = ruleSet.len;
1532 for (unsigned int i = 0; i < count; i++)
1533 if (input_class_def.intersects_class (c->glyphs, i)) {
1534 const ChainRuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001535 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001536 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001537 }
1538
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001539 inline bool would_apply (hb_would_apply_context_t *c) const
1540 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001541 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001542
1543 const ClassDef &input_class_def = this+inputClassDef;
1544
Behdad Esfahbod472f2292012-08-07 22:25:24 -04001545 unsigned int index = input_class_def (c->glyphs[0]);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001546 const ChainRuleSet &rule_set = this+ruleSet[index];
1547 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001548 {match_class},
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001549 {NULL, &input_class_def, NULL}
1550 };
1551 return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
1552 }
1553
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001554 inline const Coverage &get_coverage (void) const
1555 {
1556 return this+coverage;
1557 }
1558
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001559 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001560 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001561 TRACE_APPLY (this);
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001562 unsigned int index = (this+coverage) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001563 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001564
1565 const ClassDef &backtrack_class_def = this+backtrackClassDef;
1566 const ClassDef &input_class_def = this+inputClassDef;
1567 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
1568
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001569 index = input_class_def (c->buffer->cur().codepoint);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001570 const ChainRuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001571 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001572 {match_class},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001573 {&backtrack_class_def,
1574 &input_class_def,
1575 &lookahead_class_def}
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001576 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001577 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001578 }
1579
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001580 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001581 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001582 return TRACE_RETURN (coverage.sanitize (c, this) && backtrackClassDef.sanitize (c, this) &&
1583 inputClassDef.sanitize (c, this) && lookaheadClassDef.sanitize (c, this) &&
1584 ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001585 }
1586
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001587 protected:
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001588 USHORT format; /* Format identifier--format = 2 */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001589 OffsetTo<Coverage>
1590 coverage; /* Offset to Coverage table--from
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001591 * beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001592 OffsetTo<ClassDef>
1593 backtrackClassDef; /* Offset to glyph ClassDef table
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001594 * containing backtrack sequence
1595 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001596 OffsetTo<ClassDef>
1597 inputClassDef; /* Offset to glyph ClassDef
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001598 * table containing input sequence
1599 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001600 OffsetTo<ClassDef>
1601 lookaheadClassDef; /* Offset to glyph ClassDef table
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001602 * containing lookahead sequence
1603 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001604 OffsetArrayOf<ChainRuleSet>
1605 ruleSet; /* Array of ChainRuleSet tables
1606 * ordered by class */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001607 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001608 DEFINE_SIZE_ARRAY (12, ruleSet);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001609};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001610
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001611struct ChainContextFormat3
1612{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001613 inline void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001614 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001615 TRACE_CLOSURE (this);
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001616 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
1617
1618 if (!(this+input[0]).intersects (c->glyphs))
1619 return;
1620
1621 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
1622 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1623 struct ChainContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001624 {intersects_coverage},
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001625 {this, this, this}
1626 };
1627 chain_context_closure_lookup (c,
1628 backtrack.len, (const USHORT *) backtrack.array,
1629 input.len, (const USHORT *) input.array + 1,
1630 lookahead.len, (const USHORT *) lookahead.array,
1631 lookup.len, lookup.array,
1632 lookup_context);
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001633 }
1634
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001635 inline bool would_apply (hb_would_apply_context_t *c) const
1636 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001637 TRACE_WOULD_APPLY (this);
Behdad Esfahbode6f74792012-07-28 18:34:58 -04001638
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001639 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001640 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
1641 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1642 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001643 {match_coverage},
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001644 {this, this, this}
1645 };
1646 return TRACE_RETURN (chain_context_would_apply_lookup (c,
1647 backtrack.len, (const USHORT *) backtrack.array,
1648 input.len, (const USHORT *) input.array + 1,
1649 lookahead.len, (const USHORT *) lookahead.array,
1650 lookup.len, lookup.array, lookup_context));
1651 }
1652
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001653 inline const Coverage &get_coverage (void) const
1654 {
1655 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
1656 return this+input[0];
1657 }
1658
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001659 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001660 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001661 TRACE_APPLY (this);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001662 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001663
Behdad Esfahbod99c26952012-05-13 15:45:18 +02001664 unsigned int index = (this+input[0]) (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001665 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001666
Behdad Esfahbode961c862010-04-21 15:56:11 -04001667 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
1668 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001669 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001670 {match_coverage},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001671 {this, this, this}
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001672 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001673 return TRACE_RETURN (chain_context_apply_lookup (c,
1674 backtrack.len, (const USHORT *) backtrack.array,
1675 input.len, (const USHORT *) input.array + 1,
1676 lookahead.len, (const USHORT *) lookahead.array,
1677 lookup.len, lookup.array, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001678 }
1679
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001680 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001681 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001682 if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001683 OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001684 if (!input.sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001685 OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001686 if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001687 ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001688 return TRACE_RETURN (lookup.sanitize (c));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001689 }
1690
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001691 protected:
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001692 USHORT format; /* Format identifier--format = 3 */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001693 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04001694 backtrack; /* Array of coverage tables
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001695 * in backtracking sequence, in glyph
1696 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001697 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04001698 inputX ; /* Array of coverage
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001699 * tables in input sequence, in glyph
1700 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001701 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04001702 lookaheadX; /* Array of coverage tables
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001703 * in lookahead sequence, in glyph
1704 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001705 ArrayOf<LookupRecord>
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001706 lookupX; /* Array of LookupRecords--in
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001707 * design order) */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001708 public:
Behdad Esfahbodbea34c72010-05-10 17:28:16 -04001709 DEFINE_SIZE_MIN (10);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001710};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001711
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001712struct ChainContext
1713{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001714 template <typename context_t>
1715 inline typename context_t::return_t process (context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001716 {
Behdad Esfahboda1733db2012-11-23 16:40:04 -05001717 TRACE_PROCESS (this);
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001718 switch (u.format) {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001719 case 1: return c->process (u.format1);
1720 case 2: return c->process (u.format2);
1721 case 3: return c->process (u.format3);
Behdad Esfahbod2005fa52012-11-22 14:38:10 -05001722 default:return c->default_return_value ();
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001723 }
1724 }
1725
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001726 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001727 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001728 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001729 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001730 case 1: return TRACE_RETURN (u.format1.sanitize (c));
1731 case 2: return TRACE_RETURN (u.format2.sanitize (c));
1732 case 3: return TRACE_RETURN (u.format3.sanitize (c));
1733 default:return TRACE_RETURN (true);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001734 }
1735 }
1736
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001737 protected:
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001738 union {
1739 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001740 ChainContextFormat1 format1;
1741 ChainContextFormat2 format2;
1742 ChainContextFormat3 format3;
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001743 } u;
1744};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001745
1746
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001747struct ExtensionFormat1
1748{
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001749 inline unsigned int get_type (void) const { return extensionLookupType; }
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -04001750 inline unsigned int get_offset (void) const { return extensionOffset; }
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001751
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001752 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001753 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001754 return TRACE_RETURN (c->check_struct (this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001755 }
1756
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001757 protected:
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001758 USHORT format; /* Format identifier. Set to 1. */
1759 USHORT extensionLookupType; /* Lookup type of subtable referenced
1760 * by ExtensionOffset (i.e. the
1761 * extension subtable). */
Behdad Esfahbod81f2af42010-04-22 00:58:49 -04001762 ULONG extensionOffset; /* Offset to the extension subtable,
1763 * of lookup type subtable. */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001764 public:
1765 DEFINE_SIZE_STATIC (8);
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001766};
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001767
Behdad Esfahbod653eeb22012-11-23 16:57:36 -05001768template <typename T>
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001769struct Extension
1770{
1771 inline unsigned int get_type (void) const
1772 {
1773 switch (u.format) {
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001774 case 1: return u.format1.get_type ();
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001775 default:return 0;
1776 }
1777 }
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -04001778 inline unsigned int get_offset (void) const
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001779 {
1780 switch (u.format) {
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001781 case 1: return u.format1.get_offset ();
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -04001782 default:return 0;
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001783 }
1784 }
1785
Behdad Esfahbod7dddd4e2012-11-23 17:04:55 -05001786 template <typename X>
1787 inline const X& get_subtable (void) const
1788 {
1789 unsigned int offset = get_offset ();
1790 if (unlikely (!offset)) return Null(typename T::LookupSubTable);
1791 return StructAtOffset<typename T::LookupSubTable> (this, offset);
1792 }
1793
Behdad Esfahbod653eeb22012-11-23 16:57:36 -05001794 template <typename context_t>
1795 inline typename context_t::return_t process (context_t *c) const
1796 {
Behdad Esfahbod7dddd4e2012-11-23 17:04:55 -05001797 return CastP<T>(this)->get_subtable<typename T::LookupSubTable> ().process (c, get_type ());
Behdad Esfahbod653eeb22012-11-23 16:57:36 -05001798 }
1799
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001800 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001801 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001802 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001803 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001804 case 1: return TRACE_RETURN (u.format1.sanitize (c));
1805 default:return TRACE_RETURN (true);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001806 }
1807 }
1808
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001809 protected:
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001810 union {
1811 USHORT format; /* Format identifier */
Behdad Esfahbod6d08c7f2012-07-11 18:01:27 -04001812 ExtensionFormat1 format1;
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001813 } u;
1814};
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04001815
1816
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001817/*
1818 * GSUB/GPOS Common
1819 */
1820
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001821struct GSUBGPOS
1822{
Behdad Esfahboda328d662009-08-04 20:27:05 -04001823 static const hb_tag_t GSUBTag = HB_OT_TAG_GSUB;
1824 static const hb_tag_t GPOSTag = HB_OT_TAG_GPOS;
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001825
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04001826 inline unsigned int get_script_count (void) const
1827 { return (this+scriptList).len; }
1828 inline const Tag& get_script_tag (unsigned int i) const
1829 { return (this+scriptList).get_tag (i); }
Behdad Esfahbode21899b2009-11-04 16:36:14 -05001830 inline unsigned int get_script_tags (unsigned int start_offset,
1831 unsigned int *script_count /* IN/OUT */,
1832 hb_tag_t *script_tags /* OUT */) const
1833 { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04001834 inline const Script& get_script (unsigned int i) const
1835 { return (this+scriptList)[i]; }
1836 inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
1837 { return (this+scriptList).find_index (tag, index); }
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001838
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04001839 inline unsigned int get_feature_count (void) const
1840 { return (this+featureList).len; }
1841 inline const Tag& get_feature_tag (unsigned int i) const
1842 { return (this+featureList).get_tag (i); }
Behdad Esfahbode21899b2009-11-04 16:36:14 -05001843 inline unsigned int get_feature_tags (unsigned int start_offset,
1844 unsigned int *feature_count /* IN/OUT */,
1845 hb_tag_t *feature_tags /* OUT */) const
1846 { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04001847 inline const Feature& get_feature (unsigned int i) const
1848 { return (this+featureList)[i]; }
1849 inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
1850 { return (this+featureList).find_index (tag, index); }
1851
1852 inline unsigned int get_lookup_count (void) const
1853 { return (this+lookupList).len; }
1854 inline const Lookup& get_lookup (unsigned int i) const
1855 { return (this+lookupList)[i]; }
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001856
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001857 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001858 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001859 return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) &&
1860 scriptList.sanitize (c, this) &&
1861 featureList.sanitize (c, this) &&
1862 lookupList.sanitize (c, this));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -04001863 }
1864
Behdad Esfahbod212aba62009-05-24 00:50:27 -04001865 protected:
Behdad Esfahbod87fcdcb2009-05-24 01:03:24 -04001866 FixedVersion version; /* Version of the GSUB/GPOS table--initially set
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001867 * to 0x00010000 */
1868 OffsetTo<ScriptList>
1869 scriptList; /* ScriptList table */
1870 OffsetTo<FeatureList>
1871 featureList; /* FeatureList table */
1872 OffsetTo<LookupList>
1873 lookupList; /* LookupList table */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001874 public:
1875 DEFINE_SIZE_STATIC (10);
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04001876};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001877
Behdad Esfahbod6f20f722009-05-17 20:28:01 -04001878
Behdad Esfahbod7d52e662012-11-16 18:49:54 -08001879} /* namespace OT */
Behdad Esfahbod7c8e8442012-08-28 17:57:49 -04001880
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -04001881
Behdad Esfahbod5f5b24f2009-08-02 20:03:12 -04001882#endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */