blob: d2cc85b8d085e9148f87619232cd9896cc30115b [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 Esfahbod130bb3f2012-12-05 16:49:47 -050052 hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \
Behdad Esfahbod2c53bd32012-11-23 17:29:05 -050053 (&c->debug_depth, c->get_name (), this, HB_FUNC, \
Behdad Esfahbod902cc8a2012-11-23 15:06:59 -050054 "");
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 Esfahbod130bb3f2012-12-05 16:49:47 -050060 typedef hb_void_t return_t;
Behdad Esfahbod44fc2372012-11-21 23:33:13 -050061 typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
62 template <typename T>
Behdad Esfahbod130bb3f2012-12-05 16:49:47 -050063 inline return_t process (const T &obj) { obj.closure (this); return HB_VOID; }
64 static return_t default_return_value (void) { return HB_VOID; }
Behdad Esfahbod7b912c12013-01-04 01:25:27 -060065 bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
Behdad Esfahbod44fc2372012-11-21 23:33:13 -050066 return_t recurse (unsigned int lookup_index)
67 {
Behdad Esfahbod9b346772012-11-23 17:55:40 -050068 if (unlikely (nesting_level_left == 0 || !recurse_func))
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 Esfahbod130bb3f2012-12-05 16:49:47 -050074 return HB_VOID;
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 Esfahbodf94b0aa2012-04-23 13:04:38 -040085 unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
Behdad Esfahbode72b3602012-07-19 14:35:23 -040086 face (face_),
87 glyphs (glyphs_),
Behdad Esfahbod9b346772012-11-23 17:55:40 -050088 recurse_func (NULL),
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040089 nesting_level_left (nesting_level_left_),
90 debug_depth (0) {}
Behdad Esfahbod9b346772012-11-23 17:55:40 -050091
92 void set_recurse_func (recurse_func_t func) { recurse_func = func; }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040093};
94
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040095
96
Behdad Esfahbod472f2292012-08-07 22:25:24 -040097#ifndef HB_DEBUG_WOULD_APPLY
98#define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
99#endif
100
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500101#define TRACE_WOULD_APPLY(this) \
Behdad Esfahbod902cc8a2012-11-23 15:06:59 -0500102 hb_auto_trace_t<HB_DEBUG_WOULD_APPLY, bool> trace \
Behdad Esfahbod2c53bd32012-11-23 17:29:05 -0500103 (&c->debug_depth, c->get_name (), this, HB_FUNC, \
Behdad Esfahbod902cc8a2012-11-23 15:06:59 -0500104 "%d glyphs", c->len);
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400105
106struct hb_would_apply_context_t
107{
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500108 inline const char *get_name (void) { return "WOULD_APPLY"; }
109 static const unsigned int max_debug_depth = HB_DEBUG_WOULD_APPLY;
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500110 typedef bool return_t;
111 template <typename T>
112 inline return_t process (const T &obj) { return obj.would_apply (this); }
113 static return_t default_return_value (void) { return false; }
Behdad Esfahbod7b912c12013-01-04 01:25:27 -0600114 bool stop_sublookup_iteration (return_t r) const { return r; }
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500115
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 Esfahbod130bb3f2012-12-05 16:49:47 -0500140 hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, hb_void_t> trace \
Behdad Esfahbod2c53bd32012-11-23 17:29:05 -0500141 (&c->debug_depth, c->get_name (), this, HB_FUNC, \
Behdad Esfahbod902cc8a2012-11-23 15:06:59 -0500142 "");
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 Esfahbod130bb3f2012-12-05 16:49:47 -0500148 typedef hb_void_t return_t;
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500149 typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500150 template <typename T>
Behdad Esfahbod130bb3f2012-12-05 16:49:47 -0500151 inline return_t process (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
152 static return_t default_return_value (void) { return HB_VOID; }
Behdad Esfahbod7b912c12013-01-04 01:25:27 -0600153 bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500154 return_t recurse (unsigned int lookup_index)
155 {
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500156 if (unlikely (nesting_level_left == 0 || !recurse_func))
157 return default_return_value ();
158
Behdad Esfahbod1bcfa062012-12-04 16:58:09 -0500159 /* Note that GPOS sets recurse_func to NULL already, so it doesn't get
160 * past the previous check. For GSUB, we only want to collect the output
Behdad Esfahbod4a350d02012-12-04 17:13:09 -0500161 * glyphs in the recursion. If output is not requested, we can go home now. */
162
163 if (output == hb_set_get_empty ())
Behdad Esfahbod130bb3f2012-12-05 16:49:47 -0500164 return HB_VOID;
Behdad Esfahbod4a350d02012-12-04 17:13:09 -0500165
166 hb_set_t *old_before = before;
167 hb_set_t *old_input = input;
168 hb_set_t *old_after = after;
169 before = input = after = hb_set_get_empty ();
Behdad Esfahbod1bcfa062012-12-04 16:58:09 -0500170
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500171 nesting_level_left--;
Behdad Esfahbod4a350d02012-12-04 17:13:09 -0500172 recurse_func (this, lookup_index);
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500173 nesting_level_left++;
Behdad Esfahbod4a350d02012-12-04 17:13:09 -0500174
175 before = old_before;
176 input = old_input;
177 after = old_after;
178
Behdad Esfahbod130bb3f2012-12-05 16:49:47 -0500179 return HB_VOID;
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500180 }
181
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800182 hb_face_t *face;
Behdad Esfahbod83035932012-12-04 17:08:41 -0500183 hb_set_t *before;
184 hb_set_t *input;
185 hb_set_t *after;
186 hb_set_t *output;
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500187 recurse_func_t recurse_func;
188 unsigned int nesting_level_left;
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800189 unsigned int debug_depth;
190
191 hb_collect_glyphs_context_t (hb_face_t *face_,
192 hb_set_t *glyphs_before, /* OUT. May be NULL */
193 hb_set_t *glyphs_input, /* OUT. May be NULL */
194 hb_set_t *glyphs_after, /* OUT. May be NULL */
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500195 hb_set_t *glyphs_output, /* OUT. May be NULL */
196 unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800197 face (face_),
Behdad Esfahbod83035932012-12-04 17:08:41 -0500198 before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
199 input (glyphs_input ? glyphs_input : hb_set_get_empty ()),
200 after (glyphs_after ? glyphs_after : hb_set_get_empty ()),
201 output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500202 recurse_func (NULL),
203 nesting_level_left (nesting_level_left_),
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500204 debug_depth (0) {}
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500205
206 void set_recurse_func (recurse_func_t func) { recurse_func = func; }
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800207};
208
209
210
Behdad Esfahbod2005fa52012-11-22 14:38:10 -0500211struct hb_get_coverage_context_t
212{
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500213 inline const char *get_name (void) { return "GET_COVERAGE"; }
214 static const unsigned int max_debug_depth = 0;
Behdad Esfahbod2005fa52012-11-22 14:38:10 -0500215 typedef const Coverage &return_t;
216 template <typename T>
217 inline return_t process (const T &obj) { return obj.get_coverage (); }
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500218 static return_t default_return_value (void) { return Null(Coverage); }
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500219
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500220 hb_get_coverage_context_t (void) :
221 debug_depth (0) {}
222
223 unsigned int debug_depth;
Behdad Esfahbod2005fa52012-11-22 14:38:10 -0500224};
225
226
227
Behdad Esfahbod0535b502009-08-28 17:14:33 -0400228#ifndef HB_DEBUG_APPLY
Behdad Esfahbod11e3ec42010-11-03 15:11:04 -0400229#define HB_DEBUG_APPLY (HB_DEBUG+0)
Behdad Esfahbod0535b502009-08-28 17:14:33 -0400230#endif
231
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500232#define TRACE_APPLY(this) \
Behdad Esfahbod902cc8a2012-11-23 15:06:59 -0500233 hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \
Behdad Esfahbod2c53bd32012-11-23 17:29:05 -0500234 (&c->debug_depth, c->get_name (), this, HB_FUNC, \
Behdad Esfahbod902cc8a2012-11-23 15:06:59 -0500235 "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint);
Behdad Esfahbod0535b502009-08-28 17:14:33 -0400236
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400237struct hb_apply_context_t
238{
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500239 inline const char *get_name (void) { return "APPLY"; }
240 static const unsigned int max_debug_depth = HB_DEBUG_APPLY;
Behdad Esfahbodec35a722012-11-22 16:05:59 -0500241 typedef bool return_t;
242 typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
243 template <typename T>
244 inline return_t process (const T &obj) { return obj.apply (this); }
Behdad Esfahboddabe6982012-11-23 14:21:35 -0500245 static return_t default_return_value (void) { return false; }
Behdad Esfahbod7b912c12013-01-04 01:25:27 -0600246 bool stop_sublookup_iteration (return_t r) const { return r; }
Behdad Esfahbodec35a722012-11-22 16:05:59 -0500247 return_t recurse (unsigned int lookup_index)
248 {
249 if (unlikely (nesting_level_left == 0 || !recurse_func))
250 return default_return_value ();
251
Behdad Esfahbod4c4e8f02012-11-24 01:13:20 -0500252 nesting_level_left--;
Behdad Esfahbodf18ff5a2012-11-30 08:07:06 +0200253 bool ret = recurse_func (this, lookup_index);
Behdad Esfahbod4c4e8f02012-11-24 01:13:20 -0500254 nesting_level_left++;
Behdad Esfahbodf18ff5a2012-11-30 08:07:06 +0200255 return ret;
Behdad Esfahbodec35a722012-11-22 16:05:59 -0500256 }
257
Behdad Esfahbod6880f7e2013-02-13 12:17:25 -0500258 unsigned int table_index; /* GSUB/GPOS */
Behdad Esfahbodabcfe9b2011-05-11 00:02:02 -0400259 hb_font_t *font;
260 hb_face_t *face;
Behdad Esfahbod94a23aa2010-05-05 01:13:09 -0400261 hb_buffer_t *buffer;
Behdad Esfahbod744970a2011-05-16 18:15:37 -0400262 hb_direction_t direction;
Behdad Esfahbodf7acd8d2010-05-20 17:26:35 +0100263 hb_mask_t lookup_mask;
Behdad Esfahbodcfc507c2013-02-14 10:40:12 -0500264 bool auto_joiners;
Behdad Esfahbodec35a722012-11-22 16:05:59 -0500265 recurse_func_t recurse_func;
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400266 unsigned int nesting_level_left;
Behdad Esfahbod8c69e652010-10-27 22:07:49 -0400267 unsigned int lookup_props;
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400268 const GDEF &gdef;
Behdad Esfahbod300c7302012-07-30 19:37:44 -0400269 bool has_glyph_classes;
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500270 unsigned int debug_depth;
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400271
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400272
Behdad Esfahbod6880f7e2013-02-13 12:17:25 -0500273 hb_apply_context_t (unsigned int table_index_,
274 hb_font_t *font_,
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400275 hb_buffer_t *buffer_,
Behdad Esfahbodcfc507c2013-02-14 10:40:12 -0500276 hb_mask_t lookup_mask_,
277 bool auto_joiners_) :
Behdad Esfahbod6880f7e2013-02-13 12:17:25 -0500278 table_index (table_index_),
Behdad Esfahbodafbcc242012-08-02 08:36:40 -0400279 font (font_), face (font->face), buffer (buffer_),
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400280 direction (buffer_->props.direction),
281 lookup_mask (lookup_mask_),
Behdad Esfahbodcfc507c2013-02-14 10:40:12 -0500282 auto_joiners (auto_joiners_),
Behdad Esfahbodec35a722012-11-22 16:05:59 -0500283 recurse_func (NULL),
Behdad Esfahbod6736f3c2012-05-13 15:21:06 +0200284 nesting_level_left (MAX_NESTING_LEVEL),
Behdad Esfahbod407fc122013-02-13 11:13:06 -0500285 lookup_props (0),
Behdad Esfahbodafbcc242012-08-02 08:36:40 -0400286 gdef (*hb_ot_layout_from_face (face)->gdef),
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500287 has_glyph_classes (gdef.has_glyph_classes ()),
288 debug_depth (0) {}
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400289
Behdad Esfahbodc074ebc2013-02-13 11:22:42 -0500290 inline void set_recurse_func (recurse_func_t func) { recurse_func = func; }
291 inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
292 inline void set_lookup (const Lookup &l) { lookup_props = l.get_props (); }
Behdad Esfahbod41ae6742012-04-11 17:11:05 -0400293
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500294 struct matcher_t
295 {
296 inline matcher_t (void) :
297 lookup_props (0),
Behdad Esfahbodcfc507c2013-02-14 10:40:12 -0500298 ignore_zwnj (false),
299 ignore_zwj (false),
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500300 mask (-1),
301#define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
302 syllable arg1(0),
303#undef arg1
304 match_func (NULL),
305 match_data (NULL) {};
306
307 typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
308
309 inline void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
Behdad Esfahbod0b454792013-02-14 10:46:52 -0500310 inline void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500311 inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
312 inline void set_mask (hb_mask_t mask_) { mask = mask_; }
313 inline void set_syllable (uint8_t syllable_) { syllable = syllable_; }
314 inline void set_match_func (match_func_t match_func_,
315 const void *match_data_)
316 { match_func = match_func_; match_data = match_data_; }
317
318 inline bool matches (const hb_glyph_info_t &info,
319 const USHORT *glyph_data) const
320 {
321 return (info.mask & mask) &&
322 (!syllable || syllable == info.syllable ()) &&
323 (!match_func || match_func (info.codepoint, *glyph_data, match_data));
324 }
325
326 enum may_skip_t {
327 SKIP_NO,
328 SKIP_YES,
329 SKIP_MAYBE
330 };
331
332 inline may_skip_t
333 may_skip (const hb_apply_context_t *c,
334 const hb_glyph_info_t &info) const
335 {
336 unsigned int property;
337
338 property = info.glyph_props();
339
340 if (!c->match_properties (info.codepoint, property, lookup_props))
341 return SKIP_YES;
342
Behdad Esfahbod0b454792013-02-14 10:46:52 -0500343 if (unlikely (_hb_glyph_info_is_default_ignorable (&info) &&
344 (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
345 (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) &&
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500346 !is_a_ligature (info)))
347 return SKIP_MAYBE;
348
349 return SKIP_NO;
350 }
351
352 protected:
353 unsigned int lookup_props;
354 bool ignore_zwnj;
Behdad Esfahbod0b454792013-02-14 10:46:52 -0500355 bool ignore_zwj;
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500356 hb_mask_t mask;
357 uint8_t syllable;
358 match_func_t match_func;
359 const void *match_data;
360 };
361
Behdad Esfahbod9082efc2013-02-11 13:14:15 -0500362 struct skipping_forward_iterator_t
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500363 {
Behdad Esfahbod9082efc2013-02-11 13:14:15 -0500364 inline skipping_forward_iterator_t (hb_apply_context_t *c_,
365 unsigned int start_index_,
366 unsigned int num_items_,
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500367 bool context_match = false) :
368 idx (start_index_),
369 c (c_),
370 match_glyph_data (NULL),
371 num_items (num_items_),
372 end (c->buffer->len)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500373 {
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500374 matcher.set_lookup_props (c->lookup_props);
Behdad Esfahbodcfc507c2013-02-14 10:40:12 -0500375 if (c->auto_joiners)
376 {
377 /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */
378 matcher.set_ignore_zwnj (context_match || c->table_index == 1);
379 matcher.set_ignore_zwj (true);
380 }
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500381 if (!context_match)
382 {
Behdad Esfahbodcfc507c2013-02-14 10:40:12 -0500383 matcher.set_mask (c->lookup_mask);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500384 }
Behdad Esfahbodcb90b1b2013-02-15 07:02:08 -0500385 matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500386 }
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500387 inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); }
388 inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syllable); }
389 inline void set_match_func (matcher_t::match_func_t match_func,
390 const void *match_data,
391 const USHORT glyph_data[])
Behdad Esfahbodc074ebc2013-02-13 11:22:42 -0500392 {
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500393 matcher.set_match_func (match_func, match_data);
394 match_glyph_data = glyph_data;
Behdad Esfahbodc074ebc2013-02-13 11:22:42 -0500395 }
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500396
397 inline bool has_no_chance (void) const { return unlikely (num_items && idx + num_items >= end); }
398 inline void reject (void) { num_items++; match_glyph_data--; }
Behdad Esfahbodc074ebc2013-02-13 11:22:42 -0500399 inline bool next (void)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500400 {
Behdad Esfahbod506ffeb2012-01-18 16:07:53 -0500401 assert (num_items > 0);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500402 while (!has_no_chance ())
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500403 {
Behdad Esfahboda4a48fe2012-01-17 18:08:41 -0500404 idx++;
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500405 const hb_glyph_info_t &info = c->buffer->info[idx];
406
Behdad Esfahbodff93ac82013-02-21 14:51:40 -0500407 matcher_t::may_skip_t skip = matcher.may_skip (c, info);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500408
409 if (unlikely (skip == matcher_t::SKIP_YES))
410 continue;
411
412 if (matcher.matches (info, match_glyph_data))
413 {
414 num_items--;
415 match_glyph_data++;
416 return true;
417 }
418
419 if (skip == matcher_t::SKIP_NO)
420 return false;
421 }
422 return false;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500423 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500424
425 unsigned int idx;
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400426 protected:
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500427 hb_apply_context_t *c;
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500428 matcher_t matcher;
429 const USHORT *match_glyph_data;
430
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500431 unsigned int num_items;
432 unsigned int end;
433 };
434
Behdad Esfahbod9082efc2013-02-11 13:14:15 -0500435 struct skipping_backward_iterator_t
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500436 {
Behdad Esfahbod9082efc2013-02-11 13:14:15 -0500437 inline skipping_backward_iterator_t (hb_apply_context_t *c_,
438 unsigned int start_index_,
439 unsigned int num_items_,
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500440 bool context_match = false) :
441 idx (start_index_),
442 c (c_),
443 match_glyph_data (NULL),
444 num_items (num_items_)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500445 {
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500446 matcher.set_lookup_props (c->lookup_props);
Behdad Esfahbodcfc507c2013-02-14 10:40:12 -0500447 if (c->auto_joiners)
448 {
449 /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */
450 matcher.set_ignore_zwnj (context_match || c->table_index == 1);
451 matcher.set_ignore_zwj (true);
452 }
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500453 if (!context_match)
454 {
Behdad Esfahbodcfc507c2013-02-14 10:40:12 -0500455 matcher.set_mask (c->lookup_mask);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500456 }
Behdad Esfahbodcb90b1b2013-02-15 07:02:08 -0500457 matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500458 }
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500459 inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); }
460 inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syllable); }
461 inline void set_match_func (matcher_t::match_func_t match_func,
462 const void *match_data,
463 const USHORT glyph_data[])
Behdad Esfahbodc074ebc2013-02-13 11:22:42 -0500464 {
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500465 matcher.set_match_func (match_func, match_data);
466 match_glyph_data = glyph_data;
Behdad Esfahbodc074ebc2013-02-13 11:22:42 -0500467 }
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500468
469 inline bool has_no_chance (void) const { return unlikely (idx < num_items); }
470 inline void reject (void) { num_items++; }
Behdad Esfahbodc074ebc2013-02-13 11:22:42 -0500471 inline bool prev (void)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500472 {
Behdad Esfahbod506ffeb2012-01-18 16:07:53 -0500473 assert (num_items > 0);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500474 while (!has_no_chance ())
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500475 {
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500476 idx--;
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500477 const hb_glyph_info_t &info = c->buffer->out_info[idx];
478
Behdad Esfahbodff93ac82013-02-21 14:51:40 -0500479 matcher_t::may_skip_t skip = matcher.may_skip (c, info);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500480
481 if (unlikely (skip == matcher_t::SKIP_YES))
482 continue;
483
484 if (matcher.matches (info, match_glyph_data))
485 {
486 num_items--;
487 match_glyph_data++;
488 return true;
489 }
490
491 if (skip == matcher_t::SKIP_NO)
492 return false;
493 }
494 return false;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500495 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500496
497 unsigned int idx;
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400498 protected:
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500499 hb_apply_context_t *c;
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500500 matcher_t matcher;
501 const USHORT *match_glyph_data;
502
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500503 unsigned int num_items;
504 };
505
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400506 inline bool
507 match_properties_mark (hb_codepoint_t glyph,
508 unsigned int glyph_props,
509 unsigned int lookup_props) const
510 {
511 /* If using mark filtering sets, the high short of
512 * lookup_props has the set index.
513 */
514 if (lookup_props & LookupFlag::UseMarkFilteringSet)
515 return gdef.mark_set_covers (lookup_props >> 16, glyph);
516
517 /* The second byte of lookup_props has the meaning
518 * "ignore marks of attachment type different than
519 * the attachment type specified."
520 */
521 if (lookup_props & LookupFlag::MarkAttachmentType)
522 return (lookup_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
523
524 return true;
525 }
526
527 inline bool
528 match_properties (hb_codepoint_t glyph,
529 unsigned int glyph_props,
530 unsigned int lookup_props) const
531 {
532 /* Not covered, if, for example, glyph class is ligature and
533 * lookup_props includes LookupFlags::IgnoreLigatures
534 */
535 if (glyph_props & lookup_props & LookupFlag::IgnoreFlags)
536 return false;
537
Behdad Esfahbod5a08ecf2012-11-16 13:34:29 -0800538 if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400539 return match_properties_mark (glyph, glyph_props, lookup_props);
540
541 return true;
542 }
543
544 inline bool
545 check_glyph_property (hb_glyph_info_t *info,
Behdad Esfahbod407fc122013-02-13 11:13:06 -0500546 unsigned int lookup_props) const
Behdad Esfahbod7d479902012-01-18 21:19:32 -0500547 {
Behdad Esfahbodce476132012-06-09 01:10:26 -0400548 unsigned int property;
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400549
Behdad Esfahbodc2e42c32012-07-30 19:54:50 -0400550 property = info->glyph_props();
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400551
552 return match_properties (info->codepoint, property, lookup_props);
553 }
554
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400555 inline void set_class (hb_codepoint_t glyph_index, unsigned int class_guess) const
Behdad Esfahbod60da7632012-07-16 16:13:32 -0400556 {
Behdad Esfahbod2fca1422012-07-30 18:46:41 -0400557 if (likely (has_glyph_classes))
Behdad Esfahbodc2e42c32012-07-30 19:54:50 -0400558 buffer->cur().glyph_props() = gdef.get_glyph_props (glyph_index);
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400559 else if (class_guess)
Behdad Esfahbodc2e42c32012-07-30 19:54:50 -0400560 buffer->cur().glyph_props() = class_guess;
Behdad Esfahbod60da7632012-07-16 16:13:32 -0400561 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500562
Behdad Esfahbod3ec77d62012-06-08 21:44:06 -0400563 inline void output_glyph (hb_codepoint_t glyph_index,
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400564 unsigned int class_guess = 0) const
Behdad Esfahbod3ec77d62012-06-08 21:44:06 -0400565 {
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400566 set_class (glyph_index, class_guess);
Behdad Esfahbod3ec77d62012-06-08 21:44:06 -0400567 buffer->output_glyph (glyph_index);
568 }
Behdad Esfahboded2f1362012-05-22 22:12:22 -0400569 inline void replace_glyph (hb_codepoint_t glyph_index,
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400570 unsigned int class_guess = 0) const
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400571 {
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400572 set_class (glyph_index, class_guess);
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400573 buffer->replace_glyph (glyph_index);
574 }
Behdad Esfahbod7fbbf862012-07-30 18:36:42 -0400575 inline void replace_glyph_inplace (hb_codepoint_t glyph_index,
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400576 unsigned int class_guess = 0) const
Behdad Esfahbod7fbbf862012-07-30 18:36:42 -0400577 {
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400578 set_class (glyph_index, class_guess);
Behdad Esfahbod7fbbf862012-07-30 18:36:42 -0400579 buffer->cur().codepoint = glyph_index;
580 }
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400581};
582
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400583
Behdad Esfahbod94a23aa2010-05-05 01:13:09 -0400584
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400585typedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500586typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400587typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400588
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400589struct ContextClosureFuncs
590{
591 intersects_func_t intersects;
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400592};
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500593struct ContextCollectGlyphsFuncs
594{
595 collect_glyphs_func_t collect;
596};
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400597struct ContextApplyFuncs
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400598{
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400599 match_func_t match;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400600};
601
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500602
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400603static inline bool intersects_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400604{
605 return glyphs->has (value);
606}
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400607static inline bool intersects_class (hb_set_t *glyphs, const USHORT &value, const void *data)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400608{
609 const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
610 return class_def.intersects_class (glyphs, value);
611}
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400612static inline bool intersects_coverage (hb_set_t *glyphs, const USHORT &value, const void *data)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400613{
614 const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
615 return (data+coverage).intersects (glyphs);
616}
617
618static inline bool intersects_array (hb_closure_context_t *c,
619 unsigned int count,
620 const USHORT values[],
621 intersects_func_t intersects_func,
622 const void *intersects_data)
623{
624 for (unsigned int i = 0; i < count; i++)
625 if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
626 return false;
627 return true;
628}
629
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400630
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500631static inline void collect_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
632{
633 glyphs->add (value);
634}
635static inline void collect_class (hb_set_t *glyphs, const USHORT &value, const void *data)
636{
637 const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
638 class_def.add_class (glyphs, value);
639}
640static inline void collect_coverage (hb_set_t *glyphs, const USHORT &value, const void *data)
641{
642 const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
643 (data+coverage).add_coverage (glyphs);
644}
Behdad Esfahbod0beb66e2012-12-05 18:46:04 -0500645static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
Behdad Esfahbodf1b12782012-11-24 01:55:34 -0500646 hb_set_t *glyphs,
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500647 unsigned int count,
648 const USHORT values[],
649 collect_glyphs_func_t collect_func,
650 const void *collect_data)
651{
652 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbodf1b12782012-11-24 01:55:34 -0500653 collect_func (glyphs, values[i], collect_data);
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500654}
655
656
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400657static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, const void *data HB_UNUSED)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400658{
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400659 return glyph_id == value;
660}
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400661static inline bool match_class (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400662{
Behdad Esfahbod2b5a59c2009-08-04 11:38:50 -0400663 const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400664 return class_def.get_class (glyph_id) == value;
665}
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400666static inline bool match_coverage (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400667{
Behdad Esfahbod6b54c5d2009-05-18 18:30:25 -0400668 const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400669 return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400670}
671
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400672static inline bool would_match_input (hb_would_apply_context_t *c,
673 unsigned int count, /* Including the first glyph (not matched) */
674 const USHORT input[], /* Array of input values--start with second glyph */
675 match_func_t match_func,
676 const void *match_data)
677{
678 if (count != c->len)
679 return false;
680
681 for (unsigned int i = 1; i < count; i++)
Behdad Esfahbod472f2292012-08-07 22:25:24 -0400682 if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400683 return false;
684
685 return true;
686}
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400687static inline bool match_input (hb_apply_context_t *c,
Behdad Esfahbode072c242009-05-18 03:47:31 -0400688 unsigned int count, /* Including the first glyph (not matched) */
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400689 const USHORT input[], /* Array of input values--start with second glyph */
690 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400691 const void *match_data,
Behdad Esfahbod191fa882012-08-28 22:58:55 -0400692 unsigned int *end_offset = NULL,
693 bool *p_is_mark_ligature = NULL,
694 unsigned int *p_total_component_count = NULL)
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400695{
Behdad Esfahbod73c18ae2012-11-23 15:34:11 -0500696 TRACE_APPLY (NULL);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400697
Behdad Esfahbod9082efc2013-02-11 13:14:15 -0500698 hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500699 skippy_iter.set_match_func (match_func, match_data, input);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400700 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
701
Behdad Esfahbod191fa882012-08-28 22:58:55 -0400702 /*
703 * This is perhaps the trickiest part of OpenType... Remarks:
704 *
705 * - If all components of the ligature were marks, we call this a mark ligature.
706 *
707 * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
708 * it as a ligature glyph.
709 *
710 * - Ligatures cannot be formed across glyphs attached to different components
711 * of previous ligatures. Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
712 * LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
713 * However, it would be wrong to ligate that SHADDA,FATHA sequence.o
714 * There is an exception to this: If a ligature tries ligating with marks that
715 * belong to it itself, go ahead, assuming that the font designer knows what
716 * they are doing (otherwise it can break Indic stuff when a matra wants to
717 * ligate with a conjunct...)
718 */
719
Behdad Esfahbod407fc122013-02-13 11:13:06 -0500720 bool is_mark_ligature = !!(c->buffer->cur().glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400721
722 unsigned int total_component_count = 0;
723 total_component_count += get_lig_num_comps (c->buffer->cur());
724
725 unsigned int first_lig_id = get_lig_id (c->buffer->cur());
726 unsigned int first_lig_comp = get_lig_comp (c->buffer->cur());
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400727
Behdad Esfahbod370f03e2012-01-16 17:03:55 -0500728 for (unsigned int i = 1; i < count; i++)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400729 {
Behdad Esfahbod407fc122013-02-13 11:13:06 -0500730 if (!skippy_iter.next ()) return TRACE_RETURN (false);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400731
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400732 unsigned int this_lig_id = get_lig_id (c->buffer->info[skippy_iter.idx]);
733 unsigned int this_lig_comp = get_lig_comp (c->buffer->info[skippy_iter.idx]);
734
735 if (first_lig_id && first_lig_comp) {
736 /* If first component was attached to a previous ligature component,
737 * all subsequent components should be attached to the same ligature
738 * component, otherwise we shouldn't ligate them. */
739 if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
740 return TRACE_RETURN (false);
741 } else {
742 /* If first component was NOT attached to a previous ligature component,
743 * all subsequent components should also NOT be attached to any ligature
744 * component, unless they are attached to the first component itself! */
745 if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
746 return TRACE_RETURN (false);
747 }
748
Behdad Esfahbod407fc122013-02-13 11:13:06 -0500749 is_mark_ligature = is_mark_ligature && (c->buffer->info[skippy_iter.idx].glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400750 total_component_count += get_lig_num_comps (c->buffer->info[skippy_iter.idx]);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400751 }
752
Behdad Esfahbod5df809b2012-05-13 15:17:51 +0200753 if (end_offset)
754 *end_offset = skippy_iter.idx - c->buffer->idx + 1;
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400755
Behdad Esfahbod191fa882012-08-28 22:58:55 -0400756 if (p_is_mark_ligature)
757 *p_is_mark_ligature = is_mark_ligature;
758
759 if (p_total_component_count)
760 *p_total_component_count = total_component_count;
761
Behdad Esfahbodbc513ad2012-10-29 19:03:55 -0700762 return TRACE_RETURN (true);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400763}
Behdad Esfahboda177d022012-08-28 23:18:22 -0400764static inline void ligate_input (hb_apply_context_t *c,
765 unsigned int count, /* Including the first glyph (not matched) */
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500766 const USHORT input[], /* Array of input values--start with second glyph */
767 match_func_t match_func,
768 const void *match_data,
Behdad Esfahboda177d022012-08-28 23:18:22 -0400769 hb_codepoint_t lig_glyph,
Behdad Esfahboda177d022012-08-28 23:18:22 -0400770 bool is_mark_ligature,
771 unsigned int total_component_count)
772{
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500773 hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
774 skippy_iter.set_match_func (match_func, match_data, input);
775 if (skippy_iter.has_no_chance ()) return;
776
Behdad Esfahboda177d022012-08-28 23:18:22 -0400777 /*
778 * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave
779 * the ligature to keep its old ligature id. This will allow it to attach to
780 * a base ligature in GPOS. Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
781 * and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA wit a
782 * ligature id and component value of 2. Then if SHADDA,FATHA form a ligature
783 * later, we don't want them to lose their ligature id/component, otherwise
784 * GPOS will fail to correctly position the mark ligature on top of the
785 * LAM,LAM,HEH ligature. See:
786 * https://bugzilla.gnome.org/show_bug.cgi?id=676343
787 *
788 * - If a ligature is formed of components that some of which are also ligatures
789 * themselves, and those ligature components had marks attached to *their*
790 * components, we have to attach the marks to the new ligature component
791 * positions! Now *that*'s tricky! And these marks may be following the
792 * last component of the whole sequence, so we should loop forward looking
793 * for them and update them.
794 *
795 * Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
796 * 'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
797 * id and component == 1. Now, during 'liga', the LAM and the LAM-HEH ligature
798 * form a LAM-LAM-HEH ligature. We need to reassign the SHADDA and FATHA to
799 * the new ligature with a component value of 2.
800 *
801 * This in fact happened to a font... See:
802 * https://bugzilla.gnome.org/show_bug.cgi?id=437633
803 */
804
Behdad Esfahbod5a08ecf2012-11-16 13:34:29 -0800805 unsigned int klass = is_mark_ligature ? 0 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
Behdad Esfahboda177d022012-08-28 23:18:22 -0400806 unsigned int lig_id = is_mark_ligature ? 0 : allocate_lig_id (c->buffer);
807 unsigned int last_lig_id = get_lig_id (c->buffer->cur());
808 unsigned int last_num_components = get_lig_num_comps (c->buffer->cur());
809 unsigned int components_so_far = last_num_components;
810
811 if (!is_mark_ligature)
812 set_lig_props_for_ligature (c->buffer->cur(), lig_id, total_component_count);
813 c->replace_glyph (lig_glyph, klass);
814
815 for (unsigned int i = 1; i < count; i++)
816 {
Behdad Esfahboddfca2692013-02-14 07:20:52 -0500817 if (!skippy_iter.next ()) return;
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500818
Behdad Esfahboddfca2692013-02-14 07:20:52 -0500819 while (c->buffer->idx < skippy_iter.idx)
Behdad Esfahboda177d022012-08-28 23:18:22 -0400820 {
821 if (!is_mark_ligature) {
822 unsigned int new_lig_comp = components_so_far - last_num_components +
823 MIN (MAX (get_lig_comp (c->buffer->cur()), 1u), last_num_components);
824 set_lig_props_for_mark (c->buffer->cur(), lig_id, new_lig_comp);
825 }
826 c->buffer->next_glyph ();
827 }
828
829 last_lig_id = get_lig_id (c->buffer->cur());
830 last_num_components = get_lig_num_comps (c->buffer->cur());
831 components_so_far += last_num_components;
832
833 /* Skip the base glyph */
834 c->buffer->idx++;
835 }
836
837 if (!is_mark_ligature && last_lig_id) {
838 /* Re-adjust components for any marks following. */
839 for (unsigned int i = c->buffer->idx; i < c->buffer->len; i++) {
840 if (last_lig_id == get_lig_id (c->buffer->info[i])) {
841 unsigned int new_lig_comp = components_so_far - last_num_components +
842 MIN (MAX (get_lig_comp (c->buffer->info[i]), 1u), last_num_components);
843 set_lig_props_for_mark (c->buffer->info[i], lig_id, new_lig_comp);
844 } else
845 break;
846 }
847 }
848}
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400849
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400850static inline bool match_backtrack (hb_apply_context_t *c,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400851 unsigned int count,
852 const USHORT backtrack[],
853 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400854 const void *match_data)
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400855{
Behdad Esfahbod73c18ae2012-11-23 15:34:11 -0500856 TRACE_APPLY (NULL);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400857
Behdad Esfahbod9082efc2013-02-11 13:14:15 -0500858 hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count, true);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500859 skippy_iter.set_match_func (match_func, match_data, backtrack);
860 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400861
Behdad Esfahbod4d3aeb82012-01-16 16:43:26 -0500862 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500863 if (!skippy_iter.prev ())
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400864 return TRACE_RETURN (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400865
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400866 return TRACE_RETURN (true);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400867}
868
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400869static inline bool match_lookahead (hb_apply_context_t *c,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400870 unsigned int count,
871 const USHORT lookahead[],
872 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400873 const void *match_data,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400874 unsigned int offset)
875{
Behdad Esfahbod73c18ae2012-11-23 15:34:11 -0500876 TRACE_APPLY (NULL);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400877
Behdad Esfahbod9082efc2013-02-11 13:14:15 -0500878 hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count, true);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500879 skippy_iter.set_match_func (match_func, match_data, lookahead);
880 if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400881
Behdad Esfahbod370f03e2012-01-16 17:03:55 -0500882 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500883 if (!skippy_iter.next ())
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400884 return TRACE_RETURN (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400885
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400886 return TRACE_RETURN (true);
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400887}
888
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400889
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400890
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400891struct LookupRecord
892{
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400893 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500894 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +0200895 return TRACE_RETURN (c->check_struct (this));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -0400896 }
897
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400898 USHORT sequenceIndex; /* Index into current glyph
899 * sequence--first glyph = 0 */
900 USHORT lookupListIndex; /* Lookup to apply to that
901 * position--zero--based */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400902 public:
903 DEFINE_SIZE_STATIC (4);
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400904};
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400905
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400906
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500907template <typename context_t>
908static inline void recurse_lookups (context_t *c,
909 unsigned int lookupCount,
910 const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400911{
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400912 for (unsigned int i = 0; i < lookupCount; i++)
Behdad Esfahbod44fc2372012-11-21 23:33:13 -0500913 c->recurse (lookupRecord->lookupListIndex);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400914}
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400915
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -0400916static inline bool apply_lookup (hb_apply_context_t *c,
Behdad Esfahbode072c242009-05-18 03:47:31 -0400917 unsigned int count, /* Including the first glyph */
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500918 const USHORT input[], /* Array of input values--start with second glyph */
919 match_func_t match_func,
920 const void *match_data,
Behdad Esfahbode072c242009-05-18 03:47:31 -0400921 unsigned int lookupCount,
Behdad Esfahbodec35a722012-11-22 16:05:59 -0500922 const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400923{
Behdad Esfahbod73c18ae2012-11-23 15:34:11 -0500924 TRACE_APPLY (NULL);
Behdad Esfahbod902cc8a2012-11-23 15:06:59 -0500925
Behdad Esfahbod5df809b2012-05-13 15:17:51 +0200926 unsigned int end = c->buffer->len;
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400927 if (unlikely (count == 0 || c->buffer->idx + count > end))
Behdad Esfahbod26166892012-10-29 21:51:56 -0700928 return TRACE_RETURN (false);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400929
Behdad Esfahbod7cff75b2009-05-18 04:09:05 -0400930 /* TODO We don't support lookupRecord arrays that are not increasing:
931 * Should be easy for in_place ones at least. */
Behdad Esfahbod52e9a712009-09-21 13:58:56 -0400932
Behdad Esfahbod7eb87512010-12-13 14:13:35 -0500933 /* Note: If sublookup is reverse, it will underflow after the first loop
Behdad Esfahbod52e9a712009-09-21 13:58:56 -0400934 * and we jump out of it. Not entirely disastrous. So we don't check
935 * for reverse lookup here.
936 */
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500937
938 hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx, count - 1);
939 skippy_iter.set_match_func (match_func, match_data, input);
940 uint8_t syllable = c->buffer->cur().syllable();
941
Behdad Esfahbod8820bb22013-02-14 07:41:03 -0500942 unsigned int i = 0;
943 if (lookupCount && 0 == lookupRecord->sequenceIndex)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400944 {
Behdad Esfahbod8820bb22013-02-14 07:41:03 -0500945 unsigned int old_pos = c->buffer->idx;
Behdad Esfahbod7e534152013-02-14 06:24:30 -0500946
Behdad Esfahbod8820bb22013-02-14 07:41:03 -0500947 /* Apply a lookup */
948 bool done = c->recurse (lookupRecord->lookupListIndex);
949
950 lookupRecord++;
951 lookupCount--;
952 /* Err, this is wrong if the lookup jumped over some glyphs */
953 i += c->buffer->idx - old_pos;
954
955 if (!done)
956 goto not_applied;
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500957 else
958 {
959 /* Reinitialize iterator. */
960 hb_apply_context_t::skipping_forward_iterator_t tmp (c, c->buffer->idx - 1, count - i);
961 tmp.set_syllable (syllable);
962 skippy_iter = tmp;
963 }
Behdad Esfahbod8820bb22013-02-14 07:41:03 -0500964 }
965 else
966 {
967 not_applied:
968 /* No lookup applied for this index */
969 c->buffer->next_glyph ();
970 i++;
971 }
Behdad Esfahbod8820bb22013-02-14 07:41:03 -0500972 while (i < count)
973 {
974 if (!skippy_iter.next ()) return TRACE_RETURN (true);
975 while (c->buffer->idx < skippy_iter.idx)
976 c->buffer->next_glyph ();
Behdad Esfahbode73a0c22009-05-18 04:15:25 -0400977
Behdad Esfahbod47958de2009-05-18 04:17:47 -0400978 if (lookupCount && i == lookupRecord->sequenceIndex)
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400979 {
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400980 unsigned int old_pos = c->buffer->idx;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400981
982 /* Apply a lookup */
Behdad Esfahbodec35a722012-11-22 16:05:59 -0500983 bool done = c->recurse (lookupRecord->lookupListIndex);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400984
Behdad Esfahbod47958de2009-05-18 04:17:47 -0400985 lookupRecord++;
986 lookupCount--;
Behdad Esfahbodf9c0a2d2009-09-21 13:43:54 -0400987 /* Err, this is wrong if the lookup jumped over some glyphs */
Behdad Esfahbod468e9cb2011-07-22 11:28:07 -0400988 i += c->buffer->idx - old_pos;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400989
990 if (!done)
Behdad Esfahbod8820bb22013-02-14 07:41:03 -0500991 goto not_applied2;
992 else
993 {
994 /* Reinitialize iterator. */
995 hb_apply_context_t::skipping_forward_iterator_t tmp (c, c->buffer->idx - 1, count - i);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500996 tmp.set_syllable (syllable);
Behdad Esfahbod8820bb22013-02-14 07:41:03 -0500997 skippy_iter = tmp;
998 }
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400999 }
1000 else
1001 {
Behdad Esfahbod8820bb22013-02-14 07:41:03 -05001002 not_applied2:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001003 /* No lookup applied for this index */
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001004 c->buffer->next_glyph ();
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001005 i++;
1006 }
1007 }
1008
Behdad Esfahbod26166892012-10-29 21:51:56 -07001009 return TRACE_RETURN (true);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001010}
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001011
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -04001012
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001013
1014/* Contextual lookups */
1015
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001016struct ContextClosureLookupContext
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001017{
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001018 ContextClosureFuncs funcs;
1019 const void *intersects_data;
1020};
1021
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001022struct ContextCollectGlyphsLookupContext
1023{
1024 ContextCollectGlyphsFuncs funcs;
1025 const void *collect_data;
1026};
1027
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001028struct ContextApplyLookupContext
1029{
1030 ContextApplyFuncs funcs;
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001031 const void *match_data;
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001032};
1033
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001034static inline void context_closure_lookup (hb_closure_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001035 unsigned int inputCount, /* Including the first glyph (not matched) */
1036 const USHORT input[], /* Array of input values--start with second glyph */
1037 unsigned int lookupCount,
1038 const LookupRecord lookupRecord[],
1039 ContextClosureLookupContext &lookup_context)
1040{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001041 if (intersects_array (c,
1042 inputCount ? inputCount - 1 : 0, input,
1043 lookup_context.funcs.intersects, lookup_context.intersects_data))
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001044 recurse_lookups (c,
1045 lookupCount, lookupRecord);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001046}
1047
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001048static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
1049 unsigned int inputCount, /* Including the first glyph (not matched) */
1050 const USHORT input[], /* Array of input values--start with second glyph */
1051 unsigned int lookupCount,
1052 const LookupRecord lookupRecord[],
1053 ContextCollectGlyphsLookupContext &lookup_context)
1054{
Behdad Esfahbod83035932012-12-04 17:08:41 -05001055 collect_array (c, c->input,
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001056 inputCount ? inputCount - 1 : 0, input,
1057 lookup_context.funcs.collect, lookup_context.collect_data);
1058 recurse_lookups (c,
1059 lookupCount, lookupRecord);
1060}
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001061
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001062static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
1063 unsigned int inputCount, /* Including the first glyph (not matched) */
1064 const USHORT input[], /* Array of input values--start with second glyph */
Behdad Esfahbod0beb66e2012-12-05 18:46:04 -05001065 unsigned int lookupCount HB_UNUSED,
1066 const LookupRecord lookupRecord[] HB_UNUSED,
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001067 ContextApplyLookupContext &lookup_context)
1068{
1069 return would_match_input (c,
1070 inputCount, input,
1071 lookup_context.funcs.match, lookup_context.match_data);
1072}
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001073static inline bool context_apply_lookup (hb_apply_context_t *c,
1074 unsigned int inputCount, /* Including the first glyph (not matched) */
1075 const USHORT input[], /* Array of input values--start with second glyph */
1076 unsigned int lookupCount,
1077 const LookupRecord lookupRecord[],
1078 ContextApplyLookupContext &lookup_context)
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001079{
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001080 return match_input (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -04001081 inputCount, input,
Behdad Esfahbod5df809b2012-05-13 15:17:51 +02001082 lookup_context.funcs.match, lookup_context.match_data)
1083 && apply_lookup (c,
Behdad Esfahbod607feb72013-02-14 07:43:13 -05001084 inputCount, input,
1085 lookup_context.funcs.match, lookup_context.match_data,
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001086 lookupCount, lookupRecord);
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001087}
1088
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001089struct Rule
1090{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001091 inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001092 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001093 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001094 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001095 context_closure_lookup (c,
1096 inputCount, input,
1097 lookupCount, lookupRecord,
1098 lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001099 }
1100
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001101 inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
1102 {
1103 TRACE_COLLECT_GLYPHS (this);
1104 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
1105 context_collect_glyphs_lookup (c,
1106 inputCount, input,
1107 lookupCount, lookupRecord,
1108 lookup_context);
1109 }
1110
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001111 inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
1112 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001113 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001114 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
1115 return TRACE_RETURN (context_would_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context));
1116 }
1117
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001118 inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001119 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001120 TRACE_APPLY (this);
Behdad Esfahbode45d3f82010-05-06 19:33:31 -04001121 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (input, input[0].static_size * (inputCount ? inputCount - 1 : 0));
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001122 return TRACE_RETURN (context_apply_lookup (c, inputCount, input, lookupCount, lookupRecord, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001123 }
1124
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001125 public:
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001126 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001127 TRACE_SANITIZE (this);
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001128 return inputCount.sanitize (c)
1129 && lookupCount.sanitize (c)
1130 && c->check_range (input,
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001131 input[0].static_size * inputCount
1132 + lookupRecordX[0].static_size * lookupCount);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001133 }
1134
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001135 protected:
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001136 USHORT inputCount; /* Total number of glyphs in input
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001137 * glyph sequence--includes the first
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001138 * glyph */
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001139 USHORT lookupCount; /* Number of LookupRecords */
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -05001140 USHORT input[VAR]; /* Array of match inputs--start with
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001141 * second glyph */
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -05001142 LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001143 * design order */
Behdad Esfahbod569da922010-05-10 16:38:32 -04001144 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001145 DEFINE_SIZE_ARRAY2 (4, input, lookupRecordX);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001146};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001147
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001148struct RuleSet
1149{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001150 inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001151 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001152 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001153 unsigned int num_rules = rule.len;
1154 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001155 (this+rule[i]).closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001156 }
1157
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001158 inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
1159 {
1160 TRACE_COLLECT_GLYPHS (this);
1161 unsigned int num_rules = rule.len;
1162 for (unsigned int i = 0; i < num_rules; i++)
1163 (this+rule[i]).collect_glyphs (c, lookup_context);
1164 }
1165
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001166 inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
1167 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001168 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001169 unsigned int num_rules = rule.len;
1170 for (unsigned int i = 0; i < num_rules; i++)
1171 {
1172 if ((this+rule[i]).would_apply (c, lookup_context))
1173 return TRACE_RETURN (true);
1174 }
1175 return TRACE_RETURN (false);
1176 }
1177
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001178 inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001179 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001180 TRACE_APPLY (this);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001181 unsigned int num_rules = rule.len;
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001182 for (unsigned int i = 0; i < num_rules; i++)
1183 {
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001184 if ((this+rule[i]).apply (c, lookup_context))
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001185 return TRACE_RETURN (true);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001186 }
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001187 return TRACE_RETURN (false);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001188 }
1189
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001190 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001191 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001192 return TRACE_RETURN (rule.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001193 }
1194
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001195 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001196 OffsetArrayOf<Rule>
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001197 rule; /* Array of Rule tables
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001198 * ordered by preference */
Behdad Esfahboded074222010-05-10 18:08:46 -04001199 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001200 DEFINE_SIZE_ARRAY (2, rule);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001201};
1202
1203
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001204struct ContextFormat1
1205{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001206 inline void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001207 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001208 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001209
1210 const Coverage &cov = (this+coverage);
1211
1212 struct ContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001213 {intersects_glyph},
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001214 NULL
1215 };
1216
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001217 unsigned int count = ruleSet.len;
1218 for (unsigned int i = 0; i < count; i++)
1219 if (cov.intersects_coverage (c->glyphs, i)) {
1220 const RuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001221 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001222 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001223 }
1224
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001225 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
1226 {
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001227 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbod83035932012-12-04 17:08:41 -05001228 (this+coverage).add_coverage (c->input);
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001229
1230 struct ContextCollectGlyphsLookupContext lookup_context = {
1231 {collect_glyph},
1232 NULL
1233 };
1234
1235 unsigned int count = ruleSet.len;
1236 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001237 (this+ruleSet[i]).collect_glyphs (c, lookup_context);
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001238 }
1239
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001240 inline bool would_apply (hb_would_apply_context_t *c) const
1241 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001242 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001243
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05001244 const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001245 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001246 {match_glyph},
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001247 NULL
1248 };
1249 return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
1250 }
1251
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001252 inline const Coverage &get_coverage (void) const
1253 {
1254 return this+coverage;
1255 }
1256
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001257 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001258 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001259 TRACE_APPLY (this);
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05001260 unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
Behdad Esfahbod64d3fc82010-05-03 22:51:19 -04001261 if (likely (index == NOT_COVERED))
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001262 return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001263
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001264 const RuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001265 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001266 {match_glyph},
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001267 NULL
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001268 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001269 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001270 }
1271
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001272 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001273 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001274 return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001275 }
1276
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001277 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001278 USHORT format; /* Format identifier--format = 1 */
1279 OffsetTo<Coverage>
1280 coverage; /* Offset to Coverage table--from
1281 * beginning of table */
1282 OffsetArrayOf<RuleSet>
1283 ruleSet; /* Array of RuleSet tables
1284 * ordered by Coverage Index */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001285 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001286 DEFINE_SIZE_ARRAY (6, ruleSet);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001287};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001288
1289
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001290struct ContextFormat2
1291{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001292 inline void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001293 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001294 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001295 if (!(this+coverage).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001296 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001297
1298 const ClassDef &class_def = this+classDef;
1299
1300 struct ContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001301 {intersects_class},
Behdad Esfahbod11fba792013-01-02 23:36:37 -06001302 &class_def
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001303 };
1304
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001305 unsigned int count = ruleSet.len;
1306 for (unsigned int i = 0; i < count; i++)
1307 if (class_def.intersects_class (c->glyphs, i)) {
1308 const RuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001309 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001310 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001311 }
1312
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001313 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
1314 {
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001315 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbod83035932012-12-04 17:08:41 -05001316 (this+coverage).add_coverage (c->input);
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001317
Behdad Esfahbod11fba792013-01-02 23:36:37 -06001318 const ClassDef &class_def = this+classDef;
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001319 struct ContextCollectGlyphsLookupContext lookup_context = {
1320 {collect_class},
Behdad Esfahbod11fba792013-01-02 23:36:37 -06001321 &class_def
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001322 };
1323
1324 unsigned int count = ruleSet.len;
1325 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001326 (this+ruleSet[i]).collect_glyphs (c, lookup_context);
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001327 }
1328
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001329 inline bool would_apply (hb_would_apply_context_t *c) const
1330 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001331 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001332
1333 const ClassDef &class_def = this+classDef;
Behdad Esfahbod2dc11412012-11-24 19:16:34 -05001334 unsigned int index = class_def.get_class (c->glyphs[0]);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001335 const RuleSet &rule_set = this+ruleSet[index];
1336 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001337 {match_class},
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001338 &class_def
1339 };
1340 return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
1341 }
1342
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001343 inline const Coverage &get_coverage (void) const
1344 {
1345 return this+coverage;
1346 }
1347
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001348 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001349 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001350 TRACE_APPLY (this);
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05001351 unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001352 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001353
1354 const ClassDef &class_def = this+classDef;
Behdad Esfahbod2dc11412012-11-24 19:16:34 -05001355 index = class_def.get_class (c->buffer->cur().codepoint);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001356 const RuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001357 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001358 {match_class},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001359 &class_def
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001360 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001361 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001362 }
1363
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001364 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001365 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001366 return TRACE_RETURN (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001367 }
1368
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001369 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001370 USHORT format; /* Format identifier--format = 2 */
1371 OffsetTo<Coverage>
1372 coverage; /* Offset to Coverage table--from
1373 * beginning of table */
1374 OffsetTo<ClassDef>
1375 classDef; /* Offset to glyph ClassDef table--from
1376 * beginning of table */
1377 OffsetArrayOf<RuleSet>
1378 ruleSet; /* Array of RuleSet tables
1379 * ordered by class */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001380 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001381 DEFINE_SIZE_ARRAY (8, ruleSet);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001382};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001383
1384
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001385struct ContextFormat3
1386{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001387 inline void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001388 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001389 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001390 if (!(this+coverage[0]).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001391 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001392
1393 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
1394 struct ContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001395 {intersects_coverage},
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001396 this
1397 };
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001398 context_closure_lookup (c,
1399 glyphCount, (const USHORT *) (coverage + 1),
1400 lookupCount, lookupRecord,
1401 lookup_context);
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001402 }
1403
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001404 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
1405 {
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001406 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbod83035932012-12-04 17:08:41 -05001407 (this+coverage[0]).add_coverage (c->input);
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001408
1409 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
1410 struct ContextCollectGlyphsLookupContext lookup_context = {
1411 {collect_coverage},
Behdad Esfahbode75943d2012-11-30 08:38:24 +02001412 this
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001413 };
1414
1415 context_collect_glyphs_lookup (c,
1416 glyphCount, (const USHORT *) (coverage + 1),
1417 lookupCount, lookupRecord,
1418 lookup_context);
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001419 }
1420
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001421 inline bool would_apply (hb_would_apply_context_t *c) const
1422 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001423 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001424
1425 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
1426 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001427 {match_coverage},
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001428 this
1429 };
1430 return TRACE_RETURN (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context));
1431 }
1432
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001433 inline const Coverage &get_coverage (void) const
1434 {
1435 return this+coverage[0];
1436 }
1437
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001438 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001439 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001440 TRACE_APPLY (this);
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05001441 unsigned int index = (this+coverage[0]).get_coverage (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001442 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001443
Behdad Esfahbode45d3f82010-05-06 19:33:31 -04001444 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * glyphCount);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001445 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001446 {match_coverage},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001447 this
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001448 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001449 return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverage + 1), lookupCount, lookupRecord, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001450 }
1451
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001452 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001453 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001454 if (!c->check_struct (this)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001455 unsigned int count = glyphCount;
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001456 if (!c->check_array (coverage, coverage[0].static_size, count)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001457 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001458 if (!coverage[i].sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode45d3f82010-05-06 19:33:31 -04001459 LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverage, coverage[0].static_size * count);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001460 return TRACE_RETURN (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001461 }
1462
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001463 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001464 USHORT format; /* Format identifier--format = 3 */
1465 USHORT glyphCount; /* Number of glyphs in the input glyph
1466 * sequence */
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001467 USHORT lookupCount; /* Number of LookupRecords */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001468 OffsetTo<Coverage>
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -05001469 coverage[VAR]; /* Array of offsets to Coverage
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001470 * table in glyph sequence order */
Behdad Esfahbodd3480ba2009-11-03 10:47:29 -05001471 LookupRecord lookupRecordX[VAR]; /* Array of LookupRecords--in
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001472 * design order */
Behdad Esfahbod569da922010-05-10 16:38:32 -04001473 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001474 DEFINE_SIZE_ARRAY2 (6, coverage, lookupRecordX);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001475};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001476
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001477struct Context
1478{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001479 template <typename context_t>
1480 inline typename context_t::return_t process (context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001481 {
Behdad Esfahbodf48ec0e2012-11-23 17:23:41 -05001482 TRACE_PROCESS (this);
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001483 switch (u.format) {
Behdad Esfahbodf48ec0e2012-11-23 17:23:41 -05001484 case 1: return TRACE_RETURN (c->process (u.format1));
1485 case 2: return TRACE_RETURN (c->process (u.format2));
1486 case 3: return TRACE_RETURN (c->process (u.format3));
1487 default:return TRACE_RETURN (c->default_return_value ());
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001488 }
1489 }
1490
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001491 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001492 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001493 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001494 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001495 case 1: return TRACE_RETURN (u.format1.sanitize (c));
1496 case 2: return TRACE_RETURN (u.format2.sanitize (c));
1497 case 3: return TRACE_RETURN (u.format3.sanitize (c));
1498 default:return TRACE_RETURN (true);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001499 }
1500 }
1501
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001502 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001503 union {
Behdad Esfahbodf8dc67b2009-05-17 19:47:54 -04001504 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001505 ContextFormat1 format1;
1506 ContextFormat2 format2;
1507 ContextFormat3 format3;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001508 } u;
1509};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001510
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001511
1512/* Chaining Contextual lookups */
1513
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001514struct ChainContextClosureLookupContext
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001515{
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001516 ContextClosureFuncs funcs;
1517 const void *intersects_data[3];
1518};
1519
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001520struct ChainContextCollectGlyphsLookupContext
1521{
1522 ContextCollectGlyphsFuncs funcs;
1523 const void *collect_data[3];
1524};
1525
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001526struct ChainContextApplyLookupContext
1527{
1528 ContextApplyFuncs funcs;
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001529 const void *match_data[3];
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001530};
1531
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001532static inline void chain_context_closure_lookup (hb_closure_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001533 unsigned int backtrackCount,
1534 const USHORT backtrack[],
1535 unsigned int inputCount, /* Including the first glyph (not matched) */
1536 const USHORT input[], /* Array of input values--start with second glyph */
1537 unsigned int lookaheadCount,
1538 const USHORT lookahead[],
1539 unsigned int lookupCount,
1540 const LookupRecord lookupRecord[],
1541 ChainContextClosureLookupContext &lookup_context)
1542{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001543 if (intersects_array (c,
1544 backtrackCount, backtrack,
1545 lookup_context.funcs.intersects, lookup_context.intersects_data[0])
1546 && intersects_array (c,
1547 inputCount ? inputCount - 1 : 0, input,
1548 lookup_context.funcs.intersects, lookup_context.intersects_data[1])
1549 && intersects_array (c,
1550 lookaheadCount, lookahead,
1551 lookup_context.funcs.intersects, lookup_context.intersects_data[2]))
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001552 recurse_lookups (c,
1553 lookupCount, lookupRecord);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001554}
1555
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001556static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
1557 unsigned int backtrackCount,
1558 const USHORT backtrack[],
1559 unsigned int inputCount, /* Including the first glyph (not matched) */
1560 const USHORT input[], /* Array of input values--start with second glyph */
1561 unsigned int lookaheadCount,
1562 const USHORT lookahead[],
1563 unsigned int lookupCount,
1564 const LookupRecord lookupRecord[],
1565 ChainContextCollectGlyphsLookupContext &lookup_context)
1566{
Behdad Esfahbod83035932012-12-04 17:08:41 -05001567 collect_array (c, c->before,
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001568 backtrackCount, backtrack,
1569 lookup_context.funcs.collect, lookup_context.collect_data[0]);
Behdad Esfahbod83035932012-12-04 17:08:41 -05001570 collect_array (c, c->input,
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001571 inputCount ? inputCount - 1 : 0, input,
1572 lookup_context.funcs.collect, lookup_context.collect_data[1]);
Behdad Esfahbod83035932012-12-04 17:08:41 -05001573 collect_array (c, c->after,
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001574 lookaheadCount, lookahead,
1575 lookup_context.funcs.collect, lookup_context.collect_data[2]);
1576 recurse_lookups (c,
1577 lookupCount, lookupRecord);
1578}
1579
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001580static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
1581 unsigned int backtrackCount,
Behdad Esfahbod0beb66e2012-12-05 18:46:04 -05001582 const USHORT backtrack[] HB_UNUSED,
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001583 unsigned int inputCount, /* Including the first glyph (not matched) */
1584 const USHORT input[], /* Array of input values--start with second glyph */
1585 unsigned int lookaheadCount,
Behdad Esfahbod0beb66e2012-12-05 18:46:04 -05001586 const USHORT lookahead[] HB_UNUSED,
1587 unsigned int lookupCount HB_UNUSED,
1588 const LookupRecord lookupRecord[] HB_UNUSED,
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001589 ChainContextApplyLookupContext &lookup_context)
1590{
Behdad Esfahbodd9b204d2012-08-23 16:22:28 -04001591 return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
Behdad Esfahbod1f2bb172012-08-23 16:10:37 -04001592 && would_match_input (c,
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001593 inputCount, input,
1594 lookup_context.funcs.match, lookup_context.match_data[1]);
1595}
1596
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001597static inline bool chain_context_apply_lookup (hb_apply_context_t *c,
1598 unsigned int backtrackCount,
1599 const USHORT backtrack[],
1600 unsigned int inputCount, /* Including the first glyph (not matched) */
1601 const USHORT input[], /* Array of input values--start with second glyph */
1602 unsigned int lookaheadCount,
1603 const USHORT lookahead[],
1604 unsigned int lookupCount,
1605 const LookupRecord lookupRecord[],
1606 ChainContextApplyLookupContext &lookup_context)
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001607{
Behdad Esfahbodc779d822012-11-23 14:07:24 -05001608 unsigned int lookahead_offset = 0;
Behdad Esfahbodf19e0b02012-06-09 02:26:57 -04001609 return match_input (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -04001610 inputCount, input,
1611 lookup_context.funcs.match, lookup_context.match_data[1],
Behdad Esfahbod5df809b2012-05-13 15:17:51 +02001612 &lookahead_offset)
Behdad Esfahbodf19e0b02012-06-09 02:26:57 -04001613 && match_backtrack (c,
1614 backtrackCount, backtrack,
1615 lookup_context.funcs.match, lookup_context.match_data[0])
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001616 && match_lookahead (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -04001617 lookaheadCount, lookahead,
1618 lookup_context.funcs.match, lookup_context.match_data[2],
Behdad Esfahbod5df809b2012-05-13 15:17:51 +02001619 lookahead_offset)
1620 && apply_lookup (c,
Behdad Esfahbod607feb72013-02-14 07:43:13 -05001621 inputCount, input,
1622 lookup_context.funcs.match, lookup_context.match_data[1],
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001623 lookupCount, lookupRecord);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001624}
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001625
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001626struct ChainRule
1627{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001628 inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001629 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001630 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001631 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
1632 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
1633 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001634 chain_context_closure_lookup (c,
1635 backtrack.len, backtrack.array,
1636 input.len, input.array,
1637 lookahead.len, lookahead.array,
1638 lookup.len, lookup.array,
1639 lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001640 }
1641
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001642 inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
1643 {
1644 TRACE_COLLECT_GLYPHS (this);
1645 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
1646 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
1647 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1648 chain_context_collect_glyphs_lookup (c,
1649 backtrack.len, backtrack.array,
1650 input.len, input.array,
1651 lookahead.len, lookahead.array,
1652 lookup.len, lookup.array,
1653 lookup_context);
1654 }
1655
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001656 inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
1657 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001658 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001659 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
1660 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
1661 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1662 return TRACE_RETURN (chain_context_would_apply_lookup (c,
1663 backtrack.len, backtrack.array,
1664 input.len, input.array,
1665 lookahead.len, lookahead.array, lookup.len,
1666 lookup.array, lookup_context));
1667 }
1668
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001669 inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001670 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001671 TRACE_APPLY (this);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001672 const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
1673 const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
1674 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001675 return TRACE_RETURN (chain_context_apply_lookup (c,
1676 backtrack.len, backtrack.array,
1677 input.len, input.array,
1678 lookahead.len, lookahead.array, lookup.len,
1679 lookup.array, lookup_context));
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001680 }
1681
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001682 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001683 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001684 if (!backtrack.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001685 HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001686 if (!input.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001687 ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001688 if (!lookahead.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001689 ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001690 return TRACE_RETURN (lookup.sanitize (c));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001691 }
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001692
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001693 protected:
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001694 ArrayOf<USHORT>
1695 backtrack; /* Array of backtracking values
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001696 * (to be matched before the input
1697 * sequence) */
Behdad Esfahbode8cbaaf2009-05-18 02:03:58 -04001698 HeadlessArrayOf<USHORT>
1699 inputX; /* Array of input values (start with
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001700 * second glyph) */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001701 ArrayOf<USHORT>
1702 lookaheadX; /* Array of lookahead values's (to be
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001703 * matched after the input sequence) */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001704 ArrayOf<LookupRecord>
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001705 lookupX; /* Array of LookupRecords--in
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001706 * design order) */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001707 public:
Behdad Esfahbodbea34c72010-05-10 17:28:16 -04001708 DEFINE_SIZE_MIN (8);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001709};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001710
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001711struct ChainRuleSet
1712{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001713 inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001714 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001715 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001716 unsigned int num_rules = rule.len;
1717 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001718 (this+rule[i]).closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001719 }
1720
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001721 inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
1722 {
1723 TRACE_COLLECT_GLYPHS (this);
1724 unsigned int num_rules = rule.len;
1725 for (unsigned int i = 0; i < num_rules; i++)
1726 (this+rule[i]).collect_glyphs (c, lookup_context);
1727 }
1728
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001729 inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
1730 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001731 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001732 unsigned int num_rules = rule.len;
1733 for (unsigned int i = 0; i < num_rules; i++)
1734 if ((this+rule[i]).would_apply (c, lookup_context))
1735 return TRACE_RETURN (true);
1736
1737 return TRACE_RETURN (false);
1738 }
1739
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001740 inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001741 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001742 TRACE_APPLY (this);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001743 unsigned int num_rules = rule.len;
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001744 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001745 if ((this+rule[i]).apply (c, lookup_context))
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001746 return TRACE_RETURN (true);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001747
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001748 return TRACE_RETURN (false);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001749 }
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001750
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001751 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001752 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001753 return TRACE_RETURN (rule.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001754 }
1755
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001756 protected:
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001757 OffsetArrayOf<ChainRule>
1758 rule; /* Array of ChainRule tables
1759 * ordered by preference */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001760 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001761 DEFINE_SIZE_ARRAY (2, rule);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001762};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001763
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001764struct ChainContextFormat1
1765{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001766 inline void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001767 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001768 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001769 const Coverage &cov = (this+coverage);
1770
1771 struct ChainContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001772 {intersects_glyph},
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001773 {NULL, NULL, NULL}
1774 };
1775
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001776 unsigned int count = ruleSet.len;
1777 for (unsigned int i = 0; i < count; i++)
1778 if (cov.intersects_coverage (c->glyphs, i)) {
1779 const ChainRuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001780 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001781 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001782 }
1783
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001784 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
1785 {
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001786 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbod83035932012-12-04 17:08:41 -05001787 (this+coverage).add_coverage (c->input);
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001788
1789 struct ChainContextCollectGlyphsLookupContext lookup_context = {
1790 {collect_glyph},
1791 {NULL, NULL, NULL}
1792 };
1793
1794 unsigned int count = ruleSet.len;
1795 for (unsigned int i = 0; i < count; i++)
1796 (this+ruleSet[i]).collect_glyphs (c, lookup_context);
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001797 }
1798
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001799 inline bool would_apply (hb_would_apply_context_t *c) const
1800 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001801 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001802
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05001803 const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001804 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001805 {match_glyph},
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001806 {NULL, NULL, NULL}
1807 };
1808 return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
1809 }
1810
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001811 inline const Coverage &get_coverage (void) const
1812 {
1813 return this+coverage;
1814 }
1815
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001816 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001817 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001818 TRACE_APPLY (this);
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05001819 unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001820 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001821
1822 const ChainRuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001823 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001824 {match_glyph},
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001825 {NULL, NULL, NULL}
1826 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001827 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001828 }
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001829
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001830 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001831 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001832 return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001833 }
1834
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001835 protected:
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001836 USHORT format; /* Format identifier--format = 1 */
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001837 OffsetTo<Coverage>
1838 coverage; /* Offset to Coverage table--from
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001839 * beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001840 OffsetArrayOf<ChainRuleSet>
1841 ruleSet; /* Array of ChainRuleSet tables
1842 * ordered by Coverage Index */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001843 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001844 DEFINE_SIZE_ARRAY (6, ruleSet);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001845};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001846
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001847struct ChainContextFormat2
1848{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001849 inline void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001850 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001851 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001852 if (!(this+coverage).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001853 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001854
1855 const ClassDef &backtrack_class_def = this+backtrackClassDef;
1856 const ClassDef &input_class_def = this+inputClassDef;
1857 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
1858
1859 struct ChainContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001860 {intersects_class},
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001861 {&backtrack_class_def,
1862 &input_class_def,
1863 &lookahead_class_def}
1864 };
1865
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001866 unsigned int count = ruleSet.len;
1867 for (unsigned int i = 0; i < count; i++)
1868 if (input_class_def.intersects_class (c->glyphs, i)) {
1869 const ChainRuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001870 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001871 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001872 }
1873
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001874 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
1875 {
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001876 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbod83035932012-12-04 17:08:41 -05001877 (this+coverage).add_coverage (c->input);
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001878
Behdad Esfahbod11fba792013-01-02 23:36:37 -06001879 const ClassDef &backtrack_class_def = this+backtrackClassDef;
1880 const ClassDef &input_class_def = this+inputClassDef;
1881 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
1882
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001883 struct ChainContextCollectGlyphsLookupContext lookup_context = {
1884 {collect_class},
Behdad Esfahbod11fba792013-01-02 23:36:37 -06001885 {&backtrack_class_def,
1886 &input_class_def,
1887 &lookahead_class_def}
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001888 };
1889
1890 unsigned int count = ruleSet.len;
1891 for (unsigned int i = 0; i < count; i++)
1892 (this+ruleSet[i]).collect_glyphs (c, lookup_context);
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001893 }
1894
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001895 inline bool would_apply (hb_would_apply_context_t *c) const
1896 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001897 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001898
Behdad Esfahbod11fba792013-01-02 23:36:37 -06001899 const ClassDef &backtrack_class_def = this+backtrackClassDef;
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001900 const ClassDef &input_class_def = this+inputClassDef;
Behdad Esfahbod11fba792013-01-02 23:36:37 -06001901 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001902
Behdad Esfahbod2dc11412012-11-24 19:16:34 -05001903 unsigned int index = input_class_def.get_class (c->glyphs[0]);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001904 const ChainRuleSet &rule_set = this+ruleSet[index];
1905 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001906 {match_class},
Behdad Esfahbod11fba792013-01-02 23:36:37 -06001907 {&backtrack_class_def,
1908 &input_class_def,
1909 &lookahead_class_def}
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001910 };
1911 return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
1912 }
1913
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001914 inline const Coverage &get_coverage (void) const
1915 {
1916 return this+coverage;
1917 }
1918
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001919 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001920 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001921 TRACE_APPLY (this);
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05001922 unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001923 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001924
1925 const ClassDef &backtrack_class_def = this+backtrackClassDef;
1926 const ClassDef &input_class_def = this+inputClassDef;
1927 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
1928
Behdad Esfahbod2dc11412012-11-24 19:16:34 -05001929 index = input_class_def.get_class (c->buffer->cur().codepoint);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001930 const ChainRuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001931 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001932 {match_class},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001933 {&backtrack_class_def,
1934 &input_class_def,
1935 &lookahead_class_def}
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001936 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02001937 return TRACE_RETURN (rule_set.apply (c, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001938 }
1939
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001940 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001941 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02001942 return TRACE_RETURN (coverage.sanitize (c, this) && backtrackClassDef.sanitize (c, this) &&
1943 inputClassDef.sanitize (c, this) && lookaheadClassDef.sanitize (c, this) &&
1944 ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001945 }
1946
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001947 protected:
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001948 USHORT format; /* Format identifier--format = 2 */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001949 OffsetTo<Coverage>
1950 coverage; /* Offset to Coverage table--from
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001951 * beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001952 OffsetTo<ClassDef>
1953 backtrackClassDef; /* Offset to glyph ClassDef table
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001954 * containing backtrack sequence
1955 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001956 OffsetTo<ClassDef>
1957 inputClassDef; /* Offset to glyph ClassDef
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001958 * table containing input sequence
1959 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001960 OffsetTo<ClassDef>
1961 lookaheadClassDef; /* Offset to glyph ClassDef table
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001962 * containing lookahead sequence
1963 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001964 OffsetArrayOf<ChainRuleSet>
1965 ruleSet; /* Array of ChainRuleSet tables
1966 * ordered by class */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001967 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001968 DEFINE_SIZE_ARRAY (12, ruleSet);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001969};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001970
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001971struct ChainContextFormat3
1972{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001973 inline void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001974 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001975 TRACE_CLOSURE (this);
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001976 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
1977
1978 if (!(this+input[0]).intersects (c->glyphs))
1979 return;
1980
1981 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
1982 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1983 struct ChainContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001984 {intersects_coverage},
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001985 {this, this, this}
1986 };
1987 chain_context_closure_lookup (c,
1988 backtrack.len, (const USHORT *) backtrack.array,
1989 input.len, (const USHORT *) input.array + 1,
1990 lookahead.len, (const USHORT *) lookahead.array,
1991 lookup.len, lookup.array,
1992 lookup_context);
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001993 }
1994
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001995 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
1996 {
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001997 TRACE_COLLECT_GLYPHS (this);
1998 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
1999
Behdad Esfahbod83035932012-12-04 17:08:41 -05002000 (this+input[0]).add_coverage (c->input);
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05002001
2002 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2003 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
2004 struct ChainContextCollectGlyphsLookupContext lookup_context = {
2005 {collect_coverage},
2006 {this, this, this}
2007 };
2008 chain_context_collect_glyphs_lookup (c,
2009 backtrack.len, (const USHORT *) backtrack.array,
2010 input.len, (const USHORT *) input.array + 1,
2011 lookahead.len, (const USHORT *) lookahead.array,
2012 lookup.len, lookup.array,
2013 lookup_context);
Behdad Esfahbod26514d52012-11-23 18:13:48 -05002014 }
2015
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002016 inline bool would_apply (hb_would_apply_context_t *c) const
2017 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002018 TRACE_WOULD_APPLY (this);
Behdad Esfahbode6f74792012-07-28 18:34:58 -04002019
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002020 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002021 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2022 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
2023 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05002024 {match_coverage},
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002025 {this, this, this}
2026 };
2027 return TRACE_RETURN (chain_context_would_apply_lookup (c,
2028 backtrack.len, (const USHORT *) backtrack.array,
2029 input.len, (const USHORT *) input.array + 1,
2030 lookahead.len, (const USHORT *) lookahead.array,
2031 lookup.len, lookup.array, lookup_context));
2032 }
2033
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05002034 inline const Coverage &get_coverage (void) const
2035 {
2036 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
2037 return this+input[0];
2038 }
2039
Behdad Esfahbodec35a722012-11-22 16:05:59 -05002040 inline bool apply (hb_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04002041 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002042 TRACE_APPLY (this);
Behdad Esfahbode961c862010-04-21 15:56:11 -04002043 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04002044
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05002045 unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
Behdad Esfahbodacea1832012-05-11 02:33:11 +02002046 if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002047
Behdad Esfahbode961c862010-04-21 15:56:11 -04002048 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2049 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04002050 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05002051 {match_coverage},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04002052 {this, this, this}
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04002053 };
Behdad Esfahbodacea1832012-05-11 02:33:11 +02002054 return TRACE_RETURN (chain_context_apply_lookup (c,
2055 backtrack.len, (const USHORT *) backtrack.array,
2056 input.len, (const USHORT *) input.array + 1,
2057 lookahead.len, (const USHORT *) lookahead.array,
2058 lookup.len, lookup.array, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002059 }
2060
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04002061 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002062 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02002063 if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04002064 OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02002065 if (!input.sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04002066 OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02002067 if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false);
Behdad Esfahbode961c862010-04-21 15:56:11 -04002068 ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02002069 return TRACE_RETURN (lookup.sanitize (c));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002070 }
2071
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04002072 protected:
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002073 USHORT format; /* Format identifier--format = 3 */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04002074 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04002075 backtrack; /* Array of coverage tables
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002076 * in backtracking sequence, in glyph
2077 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04002078 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04002079 inputX ; /* Array of coverage
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002080 * tables in input sequence, in glyph
2081 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04002082 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04002083 lookaheadX; /* Array of coverage tables
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002084 * in lookahead sequence, in glyph
2085 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04002086 ArrayOf<LookupRecord>
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04002087 lookupX; /* Array of LookupRecords--in
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04002088 * design order) */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04002089 public:
Behdad Esfahbodbea34c72010-05-10 17:28:16 -04002090 DEFINE_SIZE_MIN (10);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002091};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002092
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04002093struct ChainContext
2094{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05002095 template <typename context_t>
2096 inline typename context_t::return_t process (context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04002097 {
Behdad Esfahboda1733db2012-11-23 16:40:04 -05002098 TRACE_PROCESS (this);
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04002099 switch (u.format) {
Behdad Esfahbodf48ec0e2012-11-23 17:23:41 -05002100 case 1: return TRACE_RETURN (c->process (u.format1));
2101 case 2: return TRACE_RETURN (c->process (u.format2));
2102 case 3: return TRACE_RETURN (c->process (u.format3));
2103 default:return TRACE_RETURN (c->default_return_value ());
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002104 }
2105 }
2106
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04002107 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002108 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02002109 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002110 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02002111 case 1: return TRACE_RETURN (u.format1.sanitize (c));
2112 case 2: return TRACE_RETURN (u.format2.sanitize (c));
2113 case 3: return TRACE_RETURN (u.format3.sanitize (c));
2114 default:return TRACE_RETURN (true);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002115 }
2116 }
2117
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04002118 protected:
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002119 union {
2120 USHORT format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -04002121 ChainContextFormat1 format1;
2122 ChainContextFormat2 format2;
2123 ChainContextFormat3 format3;
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002124 } u;
2125};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002126
2127
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002128struct ExtensionFormat1
2129{
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002130 inline unsigned int get_type (void) const { return extensionLookupType; }
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -04002131 inline unsigned int get_offset (void) const { return extensionOffset; }
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002132
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04002133 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002134 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02002135 return TRACE_RETURN (c->check_struct (this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002136 }
2137
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04002138 protected:
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002139 USHORT format; /* Format identifier. Set to 1. */
2140 USHORT extensionLookupType; /* Lookup type of subtable referenced
2141 * by ExtensionOffset (i.e. the
2142 * extension subtable). */
Behdad Esfahbod81f2af42010-04-22 00:58:49 -04002143 ULONG extensionOffset; /* Offset to the extension subtable,
2144 * of lookup type subtable. */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04002145 public:
2146 DEFINE_SIZE_STATIC (8);
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002147};
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002148
Behdad Esfahbod653eeb22012-11-23 16:57:36 -05002149template <typename T>
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002150struct Extension
2151{
2152 inline unsigned int get_type (void) const
2153 {
2154 switch (u.format) {
Behdad Esfahboddacebca2010-05-10 19:45:41 -04002155 case 1: return u.format1.get_type ();
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002156 default:return 0;
2157 }
2158 }
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -04002159 inline unsigned int get_offset (void) const
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002160 {
2161 switch (u.format) {
Behdad Esfahboddacebca2010-05-10 19:45:41 -04002162 case 1: return u.format1.get_offset ();
Behdad Esfahbod3b2c2df2010-04-22 16:51:42 -04002163 default:return 0;
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002164 }
2165 }
2166
Behdad Esfahbod7dddd4e2012-11-23 17:04:55 -05002167 template <typename X>
2168 inline const X& get_subtable (void) const
2169 {
2170 unsigned int offset = get_offset ();
2171 if (unlikely (!offset)) return Null(typename T::LookupSubTable);
2172 return StructAtOffset<typename T::LookupSubTable> (this, offset);
2173 }
2174
Behdad Esfahbod653eeb22012-11-23 16:57:36 -05002175 template <typename context_t>
2176 inline typename context_t::return_t process (context_t *c) const
2177 {
Behdad Esfahboded2e1352012-11-23 17:10:40 -05002178 return get_subtable<typename T::LookupSubTable> ().process (c, get_type ());
Behdad Esfahbod653eeb22012-11-23 16:57:36 -05002179 }
2180
Behdad Esfahboded2e1352012-11-23 17:10:40 -05002181 inline bool sanitize_self (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002182 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02002183 if (!u.format.sanitize (c)) return TRACE_RETURN (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002184 switch (u.format) {
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02002185 case 1: return TRACE_RETURN (u.format1.sanitize (c));
2186 default:return TRACE_RETURN (true);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002187 }
2188 }
2189
Behdad Esfahboded2e1352012-11-23 17:10:40 -05002190 inline bool sanitize (hb_sanitize_context_t *c) {
2191 TRACE_SANITIZE (this);
2192 if (!sanitize_self (c)) return TRACE_RETURN (false);
2193 unsigned int offset = get_offset ();
2194 if (unlikely (!offset)) return TRACE_RETURN (true);
2195 return TRACE_RETURN (StructAtOffset<typename T::LookupSubTable> (this, offset).sanitize (c, get_type ()));
2196 }
2197
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04002198 protected:
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002199 union {
2200 USHORT format; /* Format identifier */
Behdad Esfahbod6d08c7f2012-07-11 18:01:27 -04002201 ExtensionFormat1 format1;
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002202 } u;
2203};
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002204
2205
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04002206/*
2207 * GSUB/GPOS Common
2208 */
2209
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04002210struct GSUBGPOS
2211{
Behdad Esfahboda328d662009-08-04 20:27:05 -04002212 static const hb_tag_t GSUBTag = HB_OT_TAG_GSUB;
2213 static const hb_tag_t GPOSTag = HB_OT_TAG_GPOS;
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04002214
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04002215 inline unsigned int get_script_count (void) const
2216 { return (this+scriptList).len; }
2217 inline const Tag& get_script_tag (unsigned int i) const
2218 { return (this+scriptList).get_tag (i); }
Behdad Esfahbode21899b2009-11-04 16:36:14 -05002219 inline unsigned int get_script_tags (unsigned int start_offset,
2220 unsigned int *script_count /* IN/OUT */,
2221 hb_tag_t *script_tags /* OUT */) const
2222 { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04002223 inline const Script& get_script (unsigned int i) const
2224 { return (this+scriptList)[i]; }
2225 inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
2226 { return (this+scriptList).find_index (tag, index); }
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04002227
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04002228 inline unsigned int get_feature_count (void) const
2229 { return (this+featureList).len; }
2230 inline const Tag& get_feature_tag (unsigned int i) const
2231 { return (this+featureList).get_tag (i); }
Behdad Esfahbode21899b2009-11-04 16:36:14 -05002232 inline unsigned int get_feature_tags (unsigned int start_offset,
2233 unsigned int *feature_count /* IN/OUT */,
2234 hb_tag_t *feature_tags /* OUT */) const
2235 { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04002236 inline const Feature& get_feature (unsigned int i) const
2237 { return (this+featureList)[i]; }
2238 inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
2239 { return (this+featureList).find_index (tag, index); }
2240
2241 inline unsigned int get_lookup_count (void) const
2242 { return (this+lookupList).len; }
2243 inline const Lookup& get_lookup (unsigned int i) const
2244 { return (this+lookupList)[i]; }
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04002245
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04002246 inline bool sanitize (hb_sanitize_context_t *c) {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002247 TRACE_SANITIZE (this);
Behdad Esfahbod0ab8c862012-05-11 01:25:34 +02002248 return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) &&
2249 scriptList.sanitize (c, this) &&
2250 featureList.sanitize (c, this) &&
2251 lookupList.sanitize (c, this));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -04002252 }
2253
Behdad Esfahbod212aba62009-05-24 00:50:27 -04002254 protected:
Behdad Esfahbod87fcdcb2009-05-24 01:03:24 -04002255 FixedVersion version; /* Version of the GSUB/GPOS table--initially set
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04002256 * to 0x00010000 */
2257 OffsetTo<ScriptList>
2258 scriptList; /* ScriptList table */
2259 OffsetTo<FeatureList>
2260 featureList; /* FeatureList table */
2261 OffsetTo<LookupList>
2262 lookupList; /* LookupList table */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04002263 public:
2264 DEFINE_SIZE_STATIC (10);
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04002265};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04002266
Behdad Esfahbod6f20f722009-05-17 20:28:01 -04002267
Behdad Esfahbod7d52e662012-11-16 18:49:54 -08002268} /* namespace OT */
Behdad Esfahbod7c8e8442012-08-28 17:57:49 -04002269
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -04002270
Behdad Esfahbod5f5b24f2009-08-02 20:03:12 -04002271#endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */