blob: 40a2fc4ccd35be49840044233488e5ab52880ce3 [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 Esfahbod40ec3bb2017-11-03 16:57:30 -040032#include "hb-private.hh"
Behdad Esfahbod22da7fd2010-05-12 18:23:21 -040033#include "hb-buffer-private.hh"
Garret Rieger45186b92018-06-05 17:14:42 -070034#include "hb-map-private.hh"
Behdad Esfahbod7a750ac2011-08-17 14:19:59 +020035#include "hb-ot-layout-gdef-table.hh"
Behdad Esfahbod1336ecd2012-08-01 21:46:36 -040036#include "hb-set-private.hh"
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040037
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -040038
Behdad Esfahbod7c8e8442012-08-28 17:57:49 -040039namespace OT {
40
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -040041
Behdad Esfahbod77a1a2b2015-10-09 12:20:58 -040042struct hb_closure_context_t :
43 hb_dispatch_context_t<hb_closure_context_t, hb_void_t, HB_DEBUG_CLOSURE>
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040044{
Behdad Esfahboda1733db2012-11-23 16:40:04 -050045 inline const char *get_name (void) { return "CLOSURE"; }
Behdad Esfahbod44fc2372012-11-21 23:33:13 -050046 typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
47 template <typename T>
Behdad Esfahbod9c5a9ee2013-03-09 01:55:04 -050048 inline return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; }
Behdad Esfahbod130bb3f2012-12-05 16:49:47 -050049 static return_t default_return_value (void) { return HB_VOID; }
Behdad Esfahbod7b912c12013-01-04 01:25:27 -060050 bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
Behdad Esfahbod44fc2372012-11-21 23:33:13 -050051 return_t recurse (unsigned int lookup_index)
52 {
Behdad Esfahbod9b346772012-11-23 17:55:40 -050053 if (unlikely (nesting_level_left == 0 || !recurse_func))
Behdad Esfahbod2005fa52012-11-22 14:38:10 -050054 return default_return_value ();
Behdad Esfahbod44fc2372012-11-21 23:33:13 -050055
56 nesting_level_left--;
57 recurse_func (this, lookup_index);
58 nesting_level_left++;
Behdad Esfahbod130bb3f2012-12-05 16:49:47 -050059 return HB_VOID;
Behdad Esfahbod44fc2372012-11-21 23:33:13 -050060 }
61
Behdad Esfahbodba0ea562018-06-11 23:24:41 -040062 bool should_visit_lookup (unsigned int lookup_index)
Garret Rieger45186b92018-06-05 17:14:42 -070063 {
64 if (is_lookup_done (lookup_index))
65 return false;
66 done_lookups->set (lookup_index, glyphs->get_population ());
67 return true;
68 }
69
70 bool is_lookup_done (unsigned int lookup_index)
71 {
Behdad Esfahbodc38bd402018-07-24 09:43:27 -070072 /* Have we visited this lookup with the current set of glyphs? */
Garret Rieger45186b92018-06-05 17:14:42 -070073 return done_lookups->get (lookup_index) == glyphs->get_population ();
74 }
75
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040076 hb_face_t *face;
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -040077 hb_set_t *glyphs;
Behdad Esfahbod6b11fea2018-07-25 16:01:37 -070078 hb_auto_t<hb_set_t> out[1];
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_,
Garret Rieger45186b92018-06-05 17:14:42 -070085 hb_map_t *done_lookups_,
Behdad Esfahbod5ba45042015-11-02 15:43:08 -080086 unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
Behdad Esfahbode72b3602012-07-19 14:35:23 -040087 face (face_),
88 glyphs (glyphs_),
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +020089 recurse_func (nullptr),
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040090 nesting_level_left (nesting_level_left_),
Behdad Esfahboda7e1b4a2018-06-11 22:05:08 -040091 debug_depth (0),
92 done_lookups (done_lookups_) {}
Behdad Esfahbod9b346772012-11-23 17:55:40 -050093
Behdad Esfahbodc38bd402018-07-24 09:43:27 -070094 ~hb_closure_context_t (void)
95 {
96 flush ();
Behdad Esfahbodc38bd402018-07-24 09:43:27 -070097 }
98
Behdad Esfahbod9b346772012-11-23 17:55:40 -050099 void set_recurse_func (recurse_func_t func) { recurse_func = func; }
Garret Rieger45186b92018-06-05 17:14:42 -0700100
Behdad Esfahbodc38bd402018-07-24 09:43:27 -0700101 void flush (void)
102 {
103 hb_set_union (glyphs, out);
104 hb_set_clear (out);
105 }
106
Garret Rieger45186b92018-06-05 17:14:42 -0700107 private:
108 hb_map_t *done_lookups;
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400109};
110
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400111
Behdad Esfahbod77a1a2b2015-10-09 12:20:58 -0400112struct hb_would_apply_context_t :
113 hb_dispatch_context_t<hb_would_apply_context_t, bool, HB_DEBUG_WOULD_APPLY>
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400114{
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500115 inline const char *get_name (void) { return "WOULD_APPLY"; }
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500116 template <typename T>
Behdad Esfahbod9c5a9ee2013-03-09 01:55:04 -0500117 inline return_t dispatch (const T &obj) { return obj.would_apply (this); }
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500118 static return_t default_return_value (void) { return false; }
Behdad Esfahbod7b912c12013-01-04 01:25:27 -0600119 bool stop_sublookup_iteration (return_t r) const { return r; }
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500120
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400121 hb_face_t *face;
Behdad Esfahbod472f2292012-08-07 22:25:24 -0400122 const hb_codepoint_t *glyphs;
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400123 unsigned int len;
Behdad Esfahbodd9b204d2012-08-23 16:22:28 -0400124 bool zero_context;
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400125 unsigned int debug_depth;
126
127 hb_would_apply_context_t (hb_face_t *face_,
Behdad Esfahbod472f2292012-08-07 22:25:24 -0400128 const hb_codepoint_t *glyphs_,
129 unsigned int len_,
Behdad Esfahbod2bd9fe32012-09-04 15:15:19 -0400130 bool zero_context_) :
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400131 face (face_),
Behdad Esfahbod472f2292012-08-07 22:25:24 -0400132 glyphs (glyphs_),
133 len (len_),
Behdad Esfahbodd9b204d2012-08-23 16:22:28 -0400134 zero_context (zero_context_),
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500135 debug_depth (0) {}
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400136};
137
138
Behdad Esfahbod77a1a2b2015-10-09 12:20:58 -0400139struct hb_collect_glyphs_context_t :
140 hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, HB_DEBUG_COLLECT_GLYPHS>
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800141{
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500142 inline const char *get_name (void) { return "COLLECT_GLYPHS"; }
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500143 typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500144 template <typename T>
Behdad Esfahbod9c5a9ee2013-03-09 01:55:04 -0500145 inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
Behdad Esfahbod130bb3f2012-12-05 16:49:47 -0500146 static return_t default_return_value (void) { return HB_VOID; }
Behdad Esfahbod7b912c12013-01-04 01:25:27 -0600147 bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500148 return_t recurse (unsigned int lookup_index)
149 {
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500150 if (unlikely (nesting_level_left == 0 || !recurse_func))
151 return default_return_value ();
152
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200153 /* Note that GPOS sets recurse_func to nullptr already, so it doesn't get
Behdad Esfahbod1bcfa062012-12-04 16:58:09 -0500154 * past the previous check. For GSUB, we only want to collect the output
Behdad Esfahbod76ea5632013-05-04 16:01:20 -0400155 * glyphs in the recursion. If output is not requested, we can go home now.
156 *
157 * Note further, that the above is not exactly correct. A recursed lookup
158 * is allowed to match input that is not matched in the context, but that's
159 * not how most fonts are built. It's possible to relax that and recurse
160 * with all sets here if it proves to be an issue.
161 */
Behdad Esfahbod4a350d02012-12-04 17:13:09 -0500162
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
Behdad Esfahbodfde3e4a2014-10-29 11:23:08 -0700166 /* Return if new lookup was recursed to before. */
Behdad Esfahbod8b9d9b72017-10-22 17:48:06 -0400167 if (recursed_lookups->has (lookup_index))
Behdad Esfahbodfde3e4a2014-10-29 11:23:08 -0700168 return HB_VOID;
169
Behdad Esfahbod4a350d02012-12-04 17:13:09 -0500170 hb_set_t *old_before = before;
171 hb_set_t *old_input = input;
172 hb_set_t *old_after = after;
173 before = input = after = hb_set_get_empty ();
Behdad Esfahbod1bcfa062012-12-04 16:58:09 -0500174
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500175 nesting_level_left--;
Behdad Esfahbod4a350d02012-12-04 17:13:09 -0500176 recurse_func (this, lookup_index);
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500177 nesting_level_left++;
Behdad Esfahbod4a350d02012-12-04 17:13:09 -0500178
179 before = old_before;
180 input = old_input;
181 after = old_after;
182
Behdad Esfahbod8b9d9b72017-10-22 17:48:06 -0400183 recursed_lookups->add (lookup_index);
Behdad Esfahbodfde3e4a2014-10-29 11:23:08 -0700184
Behdad Esfahbod130bb3f2012-12-05 16:49:47 -0500185 return HB_VOID;
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500186 }
187
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800188 hb_face_t *face;
Behdad Esfahbod83035932012-12-04 17:08:41 -0500189 hb_set_t *before;
190 hb_set_t *input;
191 hb_set_t *after;
192 hb_set_t *output;
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500193 recurse_func_t recurse_func;
Behdad Esfahbod8b9d9b72017-10-22 17:48:06 -0400194 hb_set_t *recursed_lookups;
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500195 unsigned int nesting_level_left;
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800196 unsigned int debug_depth;
197
198 hb_collect_glyphs_context_t (hb_face_t *face_,
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200199 hb_set_t *glyphs_before, /* OUT. May be nullptr */
200 hb_set_t *glyphs_input, /* OUT. May be nullptr */
201 hb_set_t *glyphs_after, /* OUT. May be nullptr */
202 hb_set_t *glyphs_output, /* OUT. May be nullptr */
Behdad Esfahbod5ba45042015-11-02 15:43:08 -0800203 unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800204 face (face_),
Behdad Esfahbod83035932012-12-04 17:08:41 -0500205 before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
206 input (glyphs_input ? glyphs_input : hb_set_get_empty ()),
207 after (glyphs_after ? glyphs_after : hb_set_get_empty ()),
208 output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200209 recurse_func (nullptr),
Behdad Esfahbod8b9d9b72017-10-22 17:48:06 -0400210 recursed_lookups (nullptr),
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500211 nesting_level_left (nesting_level_left_),
Behdad Esfahbodfde3e4a2014-10-29 11:23:08 -0700212 debug_depth (0)
213 {
Behdad Esfahbod8b9d9b72017-10-22 17:48:06 -0400214 recursed_lookups = hb_set_create ();
Behdad Esfahbodfde3e4a2014-10-29 11:23:08 -0700215 }
216 ~hb_collect_glyphs_context_t (void)
217 {
Behdad Esfahbod8b9d9b72017-10-22 17:48:06 -0400218 hb_set_destroy (recursed_lookups);
Behdad Esfahbodfde3e4a2014-10-29 11:23:08 -0700219 }
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500220
221 void set_recurse_func (recurse_func_t func) { recurse_func = func; }
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800222};
223
224
225
Behdad Esfahbod77a1a2b2015-10-09 12:20:58 -0400226/* XXX Can we remove this? */
227
Behdad Esfahbod8e36ccf2015-02-17 19:15:34 +0300228template <typename set_t>
Behdad Esfahbod77a1a2b2015-10-09 12:20:58 -0400229struct hb_add_coverage_context_t :
230 hb_dispatch_context_t<hb_add_coverage_context_t<set_t>, const Coverage &, HB_DEBUG_GET_COVERAGE>
Behdad Esfahbod2005fa52012-11-22 14:38:10 -0500231{
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500232 inline const char *get_name (void) { return "GET_COVERAGE"; }
Behdad Esfahbod2005fa52012-11-22 14:38:10 -0500233 typedef const Coverage &return_t;
234 template <typename T>
Behdad Esfahbod9c5a9ee2013-03-09 01:55:04 -0500235 inline return_t dispatch (const T &obj) { return obj.get_coverage (); }
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500236 static return_t default_return_value (void) { return Null(Coverage); }
Behdad Esfahbod8e36ccf2015-02-17 19:15:34 +0300237 bool stop_sublookup_iteration (return_t r) const
238 {
239 r.add_coverage (set);
240 return false;
241 }
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500242
Behdad Esfahbod8e36ccf2015-02-17 19:15:34 +0300243 hb_add_coverage_context_t (set_t *set_) :
244 set (set_),
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500245 debug_depth (0) {}
246
Behdad Esfahbod8e36ccf2015-02-17 19:15:34 +0300247 set_t *set;
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500248 unsigned int debug_depth;
Behdad Esfahbod2005fa52012-11-22 14:38:10 -0500249};
250
251
Behdad Esfahbodfd034492018-01-17 16:46:51 -0800252struct hb_ot_apply_context_t :
253 hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400254{
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500255 struct matcher_t
256 {
257 inline matcher_t (void) :
258 lookup_props (0),
Behdad Esfahbodcfc507c2013-02-14 10:40:12 -0500259 ignore_zwnj (false),
260 ignore_zwj (false),
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500261 mask (-1),
262#define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
263 syllable arg1(0),
264#undef arg1
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200265 match_func (nullptr),
266 match_data (nullptr) {};
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500267
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100268 typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500269
270 inline void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
Behdad Esfahbod0b454792013-02-14 10:46:52 -0500271 inline void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500272 inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
273 inline void set_mask (hb_mask_t mask_) { mask = mask_; }
274 inline void set_syllable (uint8_t syllable_) { syllable = syllable_; }
275 inline void set_match_func (match_func_t match_func_,
276 const void *match_data_)
277 { match_func = match_func_; match_data = match_data_; }
278
Behdad Esfahbod2b2a6e82013-02-21 15:07:03 -0500279 enum may_match_t {
280 MATCH_NO,
281 MATCH_YES,
282 MATCH_MAYBE
283 };
284
285 inline may_match_t may_match (const hb_glyph_info_t &info,
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100286 const HBUINT16 *glyph_data) const
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500287 {
Behdad Esfahbod2b2a6e82013-02-21 15:07:03 -0500288 if (!(info.mask & mask) ||
289 (syllable && syllable != info.syllable ()))
290 return MATCH_NO;
291
292 if (match_func)
293 return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
294
295 return MATCH_MAYBE;
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500296 }
297
298 enum may_skip_t {
299 SKIP_NO,
300 SKIP_YES,
301 SKIP_MAYBE
302 };
303
304 inline may_skip_t
Behdad Esfahbodfd034492018-01-17 16:46:51 -0800305 may_skip (const hb_ot_apply_context_t *c,
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500306 const hb_glyph_info_t &info) const
307 {
Behdad Esfahbodb98c5db2014-07-16 13:44:01 -0400308 if (!c->check_glyph_property (&info, lookup_props))
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500309 return SKIP_YES;
310
Khaled Hosny06cfe3f2017-05-17 21:32:47 +0300311 if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_hidden (&info) &&
Behdad Esfahbod0b454792013-02-14 10:46:52 -0500312 (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
Behdad Esfahbod4ba796b2015-07-22 17:41:31 +0100313 (ignore_zwj || !_hb_glyph_info_is_zwj (&info))))
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500314 return SKIP_MAYBE;
315
316 return SKIP_NO;
317 }
318
319 protected:
320 unsigned int lookup_props;
321 bool ignore_zwnj;
Behdad Esfahbod0b454792013-02-14 10:46:52 -0500322 bool ignore_zwj;
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500323 hb_mask_t mask;
324 uint8_t syllable;
325 match_func_t match_func;
326 const void *match_data;
327 };
328
Behdad Esfahbod69626692015-01-29 13:08:41 +0100329 struct skipping_iterator_t
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500330 {
Behdad Esfahbodfd034492018-01-17 16:46:51 -0800331 inline void init (hb_ot_apply_context_t *c_, bool context_match = false)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500332 {
Behdad Esfahbod514564f2015-01-29 13:48:48 +0100333 c = c_;
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200334 match_glyph_data = nullptr;
335 matcher.set_match_func (nullptr, nullptr);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500336 matcher.set_lookup_props (c->lookup_props);
Behdad Esfahboda8cf7b42013-03-19 05:53:26 -0400337 /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100338 matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj));
Behdad Esfahboda8cf7b42013-03-19 05:53:26 -0400339 /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100340 matcher.set_ignore_zwj (c->table_index == 1 || (context_match || c->auto_zwj));
Behdad Esfahbod514564f2015-01-29 13:48:48 +0100341 matcher.set_mask (context_match ? -1 : c->lookup_mask);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500342 }
Behdad Esfahbod514564f2015-01-29 13:48:48 +0100343 inline void set_lookup_props (unsigned int lookup_props)
344 {
345 matcher.set_lookup_props (lookup_props);
346 }
Behdad Esfahbod4a6b1ee2015-10-21 11:20:55 -0200347 inline void set_match_func (matcher_t::match_func_t match_func_,
348 const void *match_data_,
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100349 const HBUINT16 glyph_data[])
Behdad Esfahbodc074ebc2013-02-13 11:22:42 -0500350 {
Behdad Esfahbod4a6b1ee2015-10-21 11:20:55 -0200351 matcher.set_match_func (match_func_, match_data_);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500352 match_glyph_data = glyph_data;
Behdad Esfahbodc074ebc2013-02-13 11:22:42 -0500353 }
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500354
Behdad Esfahbodb051be52015-01-29 13:40:39 +0100355 inline void reset (unsigned int start_index_,
356 unsigned int num_items_)
357 {
358 idx = start_index_;
359 num_items = num_items_;
360 end = c->buffer->len;
361 matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
362 }
363
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500364 inline void reject (void) { num_items++; match_glyph_data--; }
Behdad Esfahbod69626692015-01-29 13:08:41 +0100365
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200366 inline matcher_t::may_skip_t
Behdad Esfahbod12757b62018-01-26 18:14:05 -0800367 may_skip (const hb_glyph_info_t &info) const
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200368 {
369 return matcher.may_skip (c, info);
370 }
371
Behdad Esfahbodc074ebc2013-02-13 11:22:42 -0500372 inline bool next (void)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500373 {
Behdad Esfahbod506ffeb2012-01-18 16:07:53 -0500374 assert (num_items > 0);
Behdad Esfahbod37d13ac2015-01-29 11:38:01 +0100375 while (idx + num_items < end)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500376 {
Behdad Esfahboda4a48fe2012-01-17 18:08:41 -0500377 idx++;
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500378 const hb_glyph_info_t &info = c->buffer->info[idx];
379
Behdad Esfahbodff93ac82013-02-21 14:51:40 -0500380 matcher_t::may_skip_t skip = matcher.may_skip (c, info);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500381 if (unlikely (skip == matcher_t::SKIP_YES))
382 continue;
383
Behdad Esfahbod2b2a6e82013-02-21 15:07:03 -0500384 matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
Behdad Esfahbod722e8b82013-02-21 15:37:51 -0500385 if (match == matcher_t::MATCH_YES ||
386 (match == matcher_t::MATCH_MAYBE &&
387 skip == matcher_t::SKIP_NO))
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500388 {
389 num_items--;
390 match_glyph_data++;
391 return true;
392 }
393
394 if (skip == matcher_t::SKIP_NO)
Behdad Esfahbod722e8b82013-02-21 15:37:51 -0500395 return false;
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500396 }
397 return false;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500398 }
Behdad Esfahbodc074ebc2013-02-13 11:22:42 -0500399 inline bool prev (void)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500400 {
Behdad Esfahbod506ffeb2012-01-18 16:07:53 -0500401 assert (num_items > 0);
Behdad Esfahbod18a06f82018-07-05 14:03:48 +0430402 while (idx > num_items - 1)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500403 {
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500404 idx--;
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500405 const hb_glyph_info_t &info = c->buffer->out_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 if (unlikely (skip == matcher_t::SKIP_YES))
409 continue;
410
Behdad Esfahbod2b2a6e82013-02-21 15:07:03 -0500411 matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
Behdad Esfahbod722e8b82013-02-21 15:37:51 -0500412 if (match == matcher_t::MATCH_YES ||
413 (match == matcher_t::MATCH_MAYBE &&
414 skip == matcher_t::SKIP_NO))
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500415 {
416 num_items--;
417 match_glyph_data++;
418 return true;
419 }
420
421 if (skip == matcher_t::SKIP_NO)
Behdad Esfahbod722e8b82013-02-21 15:37:51 -0500422 return false;
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500423 }
424 return false;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500425 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500426
427 unsigned int idx;
Behdad Esfahbodec8d2492012-07-24 15:40:37 -0400428 protected:
Behdad Esfahbodfd034492018-01-17 16:46:51 -0800429 hb_ot_apply_context_t *c;
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500430 matcher_t matcher;
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100431 const HBUINT16 *match_glyph_data;
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500432
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500433 unsigned int num_items;
Behdad Esfahbod69626692015-01-29 13:08:41 +0100434 unsigned int end;
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500435 };
436
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100437
438 inline const char *get_name (void) { return "APPLY"; }
Behdad Esfahbodfd034492018-01-17 16:46:51 -0800439 typedef return_t (*recurse_func_t) (hb_ot_apply_context_t *c, unsigned int lookup_index);
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100440 template <typename T>
441 inline return_t dispatch (const T &obj) { return obj.apply (this); }
442 static return_t default_return_value (void) { return false; }
443 bool stop_sublookup_iteration (return_t r) const { return r; }
Behdad Esfahbod12757b62018-01-26 18:14:05 -0800444 return_t recurse (unsigned int sub_lookup_index)
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100445 {
Behdad Esfahbodbaf77792017-11-14 21:53:48 -0800446 if (unlikely (nesting_level_left == 0 || !recurse_func || buffer->max_ops-- <= 0))
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100447 return default_return_value ();
448
449 nesting_level_left--;
Behdad Esfahbod12757b62018-01-26 18:14:05 -0800450 bool ret = recurse_func (this, sub_lookup_index);
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100451 nesting_level_left++;
452 return ret;
453 }
454
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100455 skipping_iterator_t iter_input, iter_context;
456
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100457 hb_font_t *font;
458 hb_face_t *face;
459 hb_buffer_t *buffer;
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100460 recurse_func_t recurse_func;
461 const GDEF &gdef;
462 const VariationStore &var_store;
463
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100464 hb_direction_t direction;
465 hb_mask_t lookup_mask;
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100466 unsigned int table_index; /* GSUB/GPOS */
Behdad Esfahbod2c8b3b22015-08-18 14:36:43 +0100467 unsigned int lookup_index;
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100468 unsigned int lookup_props;
469 unsigned int nesting_level_left;
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100470 unsigned int debug_depth;
471
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100472 bool auto_zwnj;
473 bool auto_zwj;
474 bool has_glyph_classes;
475
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100476
Behdad Esfahbodfd034492018-01-17 16:46:51 -0800477 hb_ot_apply_context_t (unsigned int table_index_,
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100478 hb_font_t *font_,
479 hb_buffer_t *buffer_) :
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100480 iter_input (), iter_context (),
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100481 font (font_), face (font->face), buffer (buffer_),
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200482 recurse_func (nullptr),
Behdad Esfahbod74b4df22018-08-03 16:57:40 -0700483 gdef (*hb_ot_layout_from_face (face)->table.GDEF),
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100484 var_store (gdef.get_var_store ()),
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100485 direction (buffer_->props.direction),
486 lookup_mask (1),
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100487 table_index (table_index_),
Behdad Esfahbod2c8b3b22015-08-18 14:36:43 +0100488 lookup_index ((unsigned int) -1),
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100489 lookup_props (0),
490 nesting_level_left (HB_MAX_NESTING_LEVEL),
491 debug_depth (0),
492 auto_zwnj (true),
493 auto_zwj (true),
494 has_glyph_classes (gdef.has_glyph_classes ()) {}
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100495
496 inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; }
497 inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; }
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100498 inline void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; }
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100499 inline void set_recurse_func (recurse_func_t func) { recurse_func = func; }
Behdad Esfahbod2c8b3b22015-08-18 14:36:43 +0100500 inline void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
Behdad Esfahbod365576d2015-01-29 13:59:42 +0100501 inline void set_lookup_props (unsigned int lookup_props_)
502 {
503 lookup_props = lookup_props_;
504 iter_input.init (this, false);
505 iter_context.init (this, true);
506 }
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100507
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400508 inline bool
509 match_properties_mark (hb_codepoint_t glyph,
510 unsigned int glyph_props,
Behdad Esfahbodb931e0b2015-04-08 14:39:00 -0700511 unsigned int match_props) const
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400512 {
513 /* If using mark filtering sets, the high short of
Behdad Esfahbodb931e0b2015-04-08 14:39:00 -0700514 * match_props has the set index.
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400515 */
Behdad Esfahbodb931e0b2015-04-08 14:39:00 -0700516 if (match_props & LookupFlag::UseMarkFilteringSet)
517 return gdef.mark_set_covers (match_props >> 16, glyph);
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400518
Behdad Esfahbodb931e0b2015-04-08 14:39:00 -0700519 /* The second byte of match_props has the meaning
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400520 * "ignore marks of attachment type different than
521 * the attachment type specified."
522 */
Behdad Esfahbodb931e0b2015-04-08 14:39:00 -0700523 if (match_props & LookupFlag::MarkAttachmentType)
524 return (match_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400525
526 return true;
527 }
528
529 inline bool
Behdad Esfahbodb98c5db2014-07-16 13:44:01 -0400530 check_glyph_property (const hb_glyph_info_t *info,
Behdad Esfahbodb931e0b2015-04-08 14:39:00 -0700531 unsigned int match_props) const
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400532 {
Behdad Esfahbodb98c5db2014-07-16 13:44:01 -0400533 hb_codepoint_t glyph = info->codepoint;
534 unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info);
535
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400536 /* Not covered, if, for example, glyph class is ligature and
Behdad Esfahbodb931e0b2015-04-08 14:39:00 -0700537 * match_props includes LookupFlags::IgnoreLigatures
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400538 */
Behdad Esfahbodb931e0b2015-04-08 14:39:00 -0700539 if (glyph_props & match_props & LookupFlag::IgnoreFlags)
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400540 return false;
541
Behdad Esfahbod5a08ecf2012-11-16 13:34:29 -0800542 if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
Behdad Esfahbodb931e0b2015-04-08 14:39:00 -0700543 return match_properties_mark (glyph, glyph_props, match_props);
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400544
545 return true;
546 }
547
Behdad Esfahboda0161742013-10-18 00:06:30 +0200548 inline void _set_glyph_props (hb_codepoint_t glyph_index,
Behdad Esfahbod71b4c992013-10-28 00:20:59 +0100549 unsigned int class_guess = 0,
Behdad Esfahbod832a6f92014-06-04 16:57:42 -0400550 bool ligature = false,
551 bool component = false) const
Behdad Esfahbod60da7632012-07-16 16:13:32 -0400552 {
Behdad Esfahbod09675a82013-10-18 01:05:58 +0200553 unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
554 HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
555 add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
556 if (ligature)
Behdad Esfahbod832a6f92014-06-04 16:57:42 -0400557 {
Behdad Esfahbod09675a82013-10-18 01:05:58 +0200558 add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
Behdad Esfahbod832a6f92014-06-04 16:57:42 -0400559 /* In the only place that the MULTIPLIED bit is used, Uniscribe
560 * seems to only care about the "last" transformation between
561 * Ligature and Multiple substitions. Ie. if you ligate, expand,
562 * and ligate again, it forgives the multiplication and acts as
563 * if only ligation happened. As such, clear MULTIPLIED bit.
564 */
565 add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
566 }
567 if (component)
568 add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
Behdad Esfahbod2fca1422012-07-30 18:46:41 -0400569 if (likely (has_glyph_classes))
Behdad Esfahbod05ad6b52013-10-18 00:45:59 +0200570 _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400571 else if (class_guess)
Behdad Esfahbod09675a82013-10-18 01:05:58 +0200572 _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess);
Behdad Esfahbod60da7632012-07-16 16:13:32 -0400573 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500574
Behdad Esfahboda0161742013-10-18 00:06:30 +0200575 inline void replace_glyph (hb_codepoint_t glyph_index) const
Behdad Esfahbod3ec77d62012-06-08 21:44:06 -0400576 {
Behdad Esfahboda0161742013-10-18 00:06:30 +0200577 _set_glyph_props (glyph_index);
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400578 buffer->replace_glyph (glyph_index);
579 }
Behdad Esfahboda0161742013-10-18 00:06:30 +0200580 inline void replace_glyph_inplace (hb_codepoint_t glyph_index) const
Behdad Esfahbod7fbbf862012-07-30 18:36:42 -0400581 {
Behdad Esfahboda0161742013-10-18 00:06:30 +0200582 _set_glyph_props (glyph_index);
Behdad Esfahbod7fbbf862012-07-30 18:36:42 -0400583 buffer->cur().codepoint = glyph_index;
584 }
Behdad Esfahboda0161742013-10-18 00:06:30 +0200585 inline void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
586 unsigned int class_guess) const
587 {
Behdad Esfahbod09675a82013-10-18 01:05:58 +0200588 _set_glyph_props (glyph_index, class_guess, true);
Behdad Esfahboda0161742013-10-18 00:06:30 +0200589 buffer->replace_glyph (glyph_index);
590 }
Behdad Esfahbod832a6f92014-06-04 16:57:42 -0400591 inline void output_glyph_for_component (hb_codepoint_t glyph_index,
592 unsigned int class_guess) const
Behdad Esfahboda0161742013-10-18 00:06:30 +0200593 {
Behdad Esfahbod832a6f92014-06-04 16:57:42 -0400594 _set_glyph_props (glyph_index, class_guess, false, true);
Behdad Esfahboda0161742013-10-18 00:06:30 +0200595 buffer->output_glyph (glyph_index);
596 }
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400597};
598
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400599
Behdad Esfahbod94a23aa2010-05-05 01:13:09 -0400600
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100601typedef bool (*intersects_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
602typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
603typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400604
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400605struct ContextClosureFuncs
606{
607 intersects_func_t intersects;
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400608};
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500609struct ContextCollectGlyphsFuncs
610{
611 collect_glyphs_func_t collect;
612};
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400613struct ContextApplyFuncs
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400614{
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400615 match_func_t match;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400616};
617
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500618
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100619static inline bool intersects_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400620{
621 return glyphs->has (value);
622}
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100623static inline bool intersects_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400624{
625 const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
626 return class_def.intersects_class (glyphs, value);
627}
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100628static inline bool intersects_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400629{
630 const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
631 return (data+coverage).intersects (glyphs);
632}
633
634static inline bool intersects_array (hb_closure_context_t *c,
635 unsigned int count,
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100636 const HBUINT16 values[],
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400637 intersects_func_t intersects_func,
638 const void *intersects_data)
639{
640 for (unsigned int i = 0; i < count; i++)
641 if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
642 return false;
643 return true;
644}
645
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400646
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100647static inline void collect_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500648{
649 glyphs->add (value);
650}
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100651static inline void collect_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500652{
653 const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
Behdad Esfahbod71e6adf2017-12-16 11:07:37 -0500654 class_def.add_class (glyphs, value);
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500655}
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100656static inline void collect_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500657{
658 const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
659 (data+coverage).add_coverage (glyphs);
660}
Behdad Esfahbod0beb66e2012-12-05 18:46:04 -0500661static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
Behdad Esfahbodf1b12782012-11-24 01:55:34 -0500662 hb_set_t *glyphs,
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500663 unsigned int count,
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100664 const HBUINT16 values[],
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500665 collect_glyphs_func_t collect_func,
666 const void *collect_data)
667{
668 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbodf1b12782012-11-24 01:55:34 -0500669 collect_func (glyphs, values[i], collect_data);
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500670}
671
672
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100673static inline bool match_glyph (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data HB_UNUSED)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400674{
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400675 return glyph_id == value;
676}
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100677static inline bool match_class (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400678{
Behdad Esfahbod2b5a59c2009-08-04 11:38:50 -0400679 const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400680 return class_def.get_class (glyph_id) == value;
681}
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100682static inline bool match_coverage (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400683{
Behdad Esfahbod6b54c5d2009-05-18 18:30:25 -0400684 const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400685 return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400686}
687
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400688static inline bool would_match_input (hb_would_apply_context_t *c,
689 unsigned int count, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100690 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400691 match_func_t match_func,
692 const void *match_data)
693{
694 if (count != c->len)
695 return false;
696
697 for (unsigned int i = 1; i < count; i++)
Behdad Esfahbod472f2292012-08-07 22:25:24 -0400698 if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400699 return false;
700
701 return true;
702}
Behdad Esfahbodfd034492018-01-17 16:46:51 -0800703static inline bool match_input (hb_ot_apply_context_t *c,
Behdad Esfahbode072c242009-05-18 03:47:31 -0400704 unsigned int count, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100705 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400706 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400707 const void *match_data,
Behdad Esfahbod6cc136f2013-10-17 13:55:48 +0200708 unsigned int *end_offset,
Behdad Esfahbod5ba45042015-11-02 15:43:08 -0800709 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200710 bool *p_is_mark_ligature = nullptr,
711 unsigned int *p_total_component_count = nullptr)
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400712{
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200713 TRACE_APPLY (nullptr);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400714
Behdad Esfahbod5ba45042015-11-02 15:43:08 -0800715 if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
Behdad Esfahbod6b65a762013-10-14 18:51:39 +0200716
Behdad Esfahbod3c3df9c2013-10-17 13:58:31 +0200717 hb_buffer_t *buffer = c->buffer;
718
Behdad Esfahbodfd034492018-01-17 16:46:51 -0800719 hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
Behdad Esfahbodb051be52015-01-29 13:40:39 +0100720 skippy_iter.reset (buffer->idx, count - 1);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500721 skippy_iter.set_match_func (match_func, match_data, input);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400722
Behdad Esfahbod191fa882012-08-28 22:58:55 -0400723 /*
724 * This is perhaps the trickiest part of OpenType... Remarks:
725 *
726 * - If all components of the ligature were marks, we call this a mark ligature.
727 *
728 * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
729 * it as a ligature glyph.
730 *
731 * - Ligatures cannot be formed across glyphs attached to different components
732 * of previous ligatures. Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
733 * LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200734 * However, it would be wrong to ligate that SHADDA,FATHA sequence.
735 * There are a couple of exceptions to this:
736 *
737 * o If a ligature tries ligating with marks that belong to it itself, go ahead,
738 * assuming that the font designer knows what they are doing (otherwise it can
739 * break Indic stuff when a matra wants to ligate with a conjunct,
740 *
741 * o If two marks want to ligate and they belong to different components of the
742 * same ligature glyph, and said ligature glyph is to be ignored according to
743 * mark-filtering rules, then allow.
ebraminio7c6937e2017-11-20 14:49:22 -0500744 * https://github.com/harfbuzz/harfbuzz/issues/545
Behdad Esfahbod191fa882012-08-28 22:58:55 -0400745 */
746
Behdad Esfahbod101303d2013-10-18 00:42:39 +0200747 bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur());
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400748
749 unsigned int total_component_count = 0;
Behdad Esfahbod3ddf8922013-10-18 00:02:43 +0200750 total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400751
Behdad Esfahbod3ddf8922013-10-18 00:02:43 +0200752 unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
753 unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400754
Behdad Esfahbod621c49c2017-10-04 15:06:48 +0200755 enum {
756 LIGBASE_NOT_CHECKED,
757 LIGBASE_MAY_NOT_SKIP,
758 LIGBASE_MAY_SKIP
759 } ligbase = LIGBASE_NOT_CHECKED;
760
Behdad Esfahbod3c3df9c2013-10-17 13:58:31 +0200761 match_positions[0] = buffer->idx;
Behdad Esfahbod370f03e2012-01-16 17:03:55 -0500762 for (unsigned int i = 1; i < count; i++)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400763 {
Behdad Esfahbodb4715902015-09-29 14:57:02 +0100764 if (!skippy_iter.next ()) return_trace (false);
Behdad Esfahbod6cc136f2013-10-17 13:55:48 +0200765
766 match_positions[i] = skippy_iter.idx;
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400767
Behdad Esfahbod3ddf8922013-10-18 00:02:43 +0200768 unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]);
769 unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400770
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200771 if (first_lig_id && first_lig_comp)
772 {
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400773 /* If first component was attached to a previous ligature component,
774 * all subsequent components should be attached to the same ligature
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200775 * component, otherwise we shouldn't ligate them... */
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400776 if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200777 {
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200778 /* ...unless, we are attached to a base ligature and that base
779 * ligature is ignorable. */
Behdad Esfahbod621c49c2017-10-04 15:06:48 +0200780 if (ligbase == LIGBASE_NOT_CHECKED)
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200781 {
Behdad Esfahbod621c49c2017-10-04 15:06:48 +0200782 bool found = false;
783 const hb_glyph_info_t *out = buffer->out_info;
784 unsigned int j = buffer->out_len;
785 while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id)
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200786 {
Behdad Esfahbod621c49c2017-10-04 15:06:48 +0200787 if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0)
788 {
789 j--;
790 found = true;
791 break;
792 }
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200793 j--;
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200794 }
Behdad Esfahbod621c49c2017-10-04 15:06:48 +0200795
Behdad Esfahbod12757b62018-01-26 18:14:05 -0800796 if (found && skippy_iter.may_skip (out[j]) == hb_ot_apply_context_t::matcher_t::SKIP_YES)
Behdad Esfahbod621c49c2017-10-04 15:06:48 +0200797 ligbase = LIGBASE_MAY_SKIP;
798 else
799 ligbase = LIGBASE_MAY_NOT_SKIP;
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200800 }
801
Behdad Esfahbod621c49c2017-10-04 15:06:48 +0200802 if (ligbase == LIGBASE_MAY_NOT_SKIP)
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200803 return_trace (false);
804 }
805 }
806 else
Behdad Esfahbod621c49c2017-10-04 15:06:48 +0200807 {
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400808 /* If first component was NOT attached to a previous ligature component,
809 * all subsequent components should also NOT be attached to any ligature
810 * component, unless they are attached to the first component itself! */
811 if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
Behdad Esfahbodb4715902015-09-29 14:57:02 +0100812 return_trace (false);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400813 }
814
Behdad Esfahbod101303d2013-10-18 00:42:39 +0200815 is_mark_ligature = is_mark_ligature && _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]);
Behdad Esfahbod3ddf8922013-10-18 00:02:43 +0200816 total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[skippy_iter.idx]);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400817 }
818
Behdad Esfahbod3c3df9c2013-10-17 13:58:31 +0200819 *end_offset = skippy_iter.idx - buffer->idx + 1;
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400820
Behdad Esfahbod191fa882012-08-28 22:58:55 -0400821 if (p_is_mark_ligature)
822 *p_is_mark_ligature = is_mark_ligature;
823
824 if (p_total_component_count)
825 *p_total_component_count = total_component_count;
826
Behdad Esfahbodb4715902015-09-29 14:57:02 +0100827 return_trace (true);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400828}
Behdad Esfahbodfd034492018-01-17 16:46:51 -0800829static inline bool ligate_input (hb_ot_apply_context_t *c,
Behdad Esfahbode714fe62013-10-17 13:49:51 +0200830 unsigned int count, /* Including the first glyph */
Behdad Esfahbod5ba45042015-11-02 15:43:08 -0800831 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
Behdad Esfahbode714fe62013-10-17 13:49:51 +0200832 unsigned int match_length,
Behdad Esfahboda177d022012-08-28 23:18:22 -0400833 hb_codepoint_t lig_glyph,
Behdad Esfahboda177d022012-08-28 23:18:22 -0400834 bool is_mark_ligature,
835 unsigned int total_component_count)
836{
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200837 TRACE_APPLY (nullptr);
Behdad Esfahbode714fe62013-10-17 13:49:51 +0200838
Behdad Esfahbod3c3df9c2013-10-17 13:58:31 +0200839 hb_buffer_t *buffer = c->buffer;
840
841 buffer->merge_clusters (buffer->idx, buffer->idx + match_length);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500842
Behdad Esfahboda177d022012-08-28 23:18:22 -0400843 /*
844 * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave
845 * the ligature to keep its old ligature id. This will allow it to attach to
846 * a base ligature in GPOS. Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
847 * and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA wit a
848 * ligature id and component value of 2. Then if SHADDA,FATHA form a ligature
849 * later, we don't want them to lose their ligature id/component, otherwise
850 * GPOS will fail to correctly position the mark ligature on top of the
851 * LAM,LAM,HEH ligature. See:
852 * https://bugzilla.gnome.org/show_bug.cgi?id=676343
853 *
854 * - If a ligature is formed of components that some of which are also ligatures
855 * themselves, and those ligature components had marks attached to *their*
856 * components, we have to attach the marks to the new ligature component
857 * positions! Now *that*'s tricky! And these marks may be following the
858 * last component of the whole sequence, so we should loop forward looking
859 * for them and update them.
860 *
861 * Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
862 * 'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
863 * id and component == 1. Now, during 'liga', the LAM and the LAM-HEH ligature
864 * form a LAM-LAM-HEH ligature. We need to reassign the SHADDA and FATHA to
865 * the new ligature with a component value of 2.
866 *
867 * This in fact happened to a font... See:
868 * https://bugzilla.gnome.org/show_bug.cgi?id=437633
869 */
870
Behdad Esfahbod5a08ecf2012-11-16 13:34:29 -0800871 unsigned int klass = is_mark_ligature ? 0 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
Behdad Esfahbod3ddf8922013-10-18 00:02:43 +0200872 unsigned int lig_id = is_mark_ligature ? 0 : _hb_allocate_lig_id (buffer);
873 unsigned int last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
874 unsigned int last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
Behdad Esfahboda177d022012-08-28 23:18:22 -0400875 unsigned int components_so_far = last_num_components;
876
877 if (!is_mark_ligature)
Behdad Esfahbod7e08f122013-05-27 14:48:34 -0400878 {
Behdad Esfahbod3ddf8922013-10-18 00:02:43 +0200879 _hb_glyph_info_set_lig_props_for_ligature (&buffer->cur(), lig_id, total_component_count);
Behdad Esfahbod3c3df9c2013-10-17 13:58:31 +0200880 if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
Behdad Esfahbod3d436d32013-10-28 21:00:37 +0100881 {
Behdad Esfahbod82596692015-11-02 17:44:05 -0800882 _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER);
Behdad Esfahbod3d436d32013-10-28 21:00:37 +0100883 }
Behdad Esfahbod7e08f122013-05-27 14:48:34 -0400884 }
Behdad Esfahboda0161742013-10-18 00:06:30 +0200885 c->replace_glyph_with_ligature (lig_glyph, klass);
Behdad Esfahboda177d022012-08-28 23:18:22 -0400886
887 for (unsigned int i = 1; i < count; i++)
888 {
Behdad Esfahbod7185b272018-05-31 20:03:00 -0700889 while (buffer->idx < match_positions[i] && buffer->successful)
Behdad Esfahboda177d022012-08-28 23:18:22 -0400890 {
891 if (!is_mark_ligature) {
Behdad Esfahbod2f02fc72015-12-17 15:21:14 +0000892 unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
893 if (this_comp == 0)
Behdad Esfahbod100fbea2015-12-17 15:23:09 +0000894 this_comp = last_num_components;
Behdad Esfahboda177d022012-08-28 23:18:22 -0400895 unsigned int new_lig_comp = components_so_far - last_num_components +
Behdad Esfahbod2f02fc72015-12-17 15:21:14 +0000896 MIN (this_comp, last_num_components);
897 _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
Behdad Esfahboda177d022012-08-28 23:18:22 -0400898 }
Behdad Esfahbod3c3df9c2013-10-17 13:58:31 +0200899 buffer->next_glyph ();
Behdad Esfahboda177d022012-08-28 23:18:22 -0400900 }
901
Behdad Esfahbod3ddf8922013-10-18 00:02:43 +0200902 last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
903 last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
Behdad Esfahboda177d022012-08-28 23:18:22 -0400904 components_so_far += last_num_components;
905
906 /* Skip the base glyph */
Behdad Esfahbod3c3df9c2013-10-17 13:58:31 +0200907 buffer->idx++;
Behdad Esfahboda177d022012-08-28 23:18:22 -0400908 }
909
910 if (!is_mark_ligature && last_lig_id) {
911 /* Re-adjust components for any marks following. */
Behdad Esfahbod3c3df9c2013-10-17 13:58:31 +0200912 for (unsigned int i = buffer->idx; i < buffer->len; i++) {
Behdad Esfahbod3ddf8922013-10-18 00:02:43 +0200913 if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) {
Behdad Esfahbod2f02fc72015-12-17 15:21:14 +0000914 unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
915 if (!this_comp)
916 break;
Behdad Esfahboda177d022012-08-28 23:18:22 -0400917 unsigned int new_lig_comp = components_so_far - last_num_components +
Behdad Esfahbod2f02fc72015-12-17 15:21:14 +0000918 MIN (this_comp, last_num_components);
Behdad Esfahbod3ddf8922013-10-18 00:02:43 +0200919 _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
Behdad Esfahboda177d022012-08-28 23:18:22 -0400920 } else
921 break;
922 }
923 }
Behdad Esfahbodb4715902015-09-29 14:57:02 +0100924 return_trace (true);
Behdad Esfahboda177d022012-08-28 23:18:22 -0400925}
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400926
Behdad Esfahbodfd034492018-01-17 16:46:51 -0800927static inline bool match_backtrack (hb_ot_apply_context_t *c,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400928 unsigned int count,
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100929 const HBUINT16 backtrack[],
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400930 match_func_t match_func,
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +0200931 const void *match_data,
932 unsigned int *match_start)
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400933{
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200934 TRACE_APPLY (nullptr);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400935
Behdad Esfahbodfd034492018-01-17 16:46:51 -0800936 hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
Behdad Esfahbodb051be52015-01-29 13:40:39 +0100937 skippy_iter.reset (c->buffer->backtrack_len (), count);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500938 skippy_iter.set_match_func (match_func, match_data, backtrack);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400939
Behdad Esfahbod4d3aeb82012-01-16 16:43:26 -0500940 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500941 if (!skippy_iter.prev ())
Behdad Esfahbodb4715902015-09-29 14:57:02 +0100942 return_trace (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400943
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +0200944 *match_start = skippy_iter.idx;
945
Behdad Esfahbodb4715902015-09-29 14:57:02 +0100946 return_trace (true);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400947}
948
Behdad Esfahbodfd034492018-01-17 16:46:51 -0800949static inline bool match_lookahead (hb_ot_apply_context_t *c,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400950 unsigned int count,
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100951 const HBUINT16 lookahead[],
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400952 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400953 const void *match_data,
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +0200954 unsigned int offset,
955 unsigned int *end_index)
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400956{
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200957 TRACE_APPLY (nullptr);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400958
Behdad Esfahbodfd034492018-01-17 16:46:51 -0800959 hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
Behdad Esfahbodb051be52015-01-29 13:40:39 +0100960 skippy_iter.reset (c->buffer->idx + offset - 1, count);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500961 skippy_iter.set_match_func (match_func, match_data, lookahead);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400962
Behdad Esfahbod370f03e2012-01-16 17:03:55 -0500963 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500964 if (!skippy_iter.next ())
Behdad Esfahbodb4715902015-09-29 14:57:02 +0100965 return_trace (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400966
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +0200967 *end_index = skippy_iter.idx + 1;
968
Behdad Esfahbodb4715902015-09-29 14:57:02 +0100969 return_trace (true);
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400970}
971
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400972
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400973
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400974struct LookupRecord
975{
Behdad Esfahbodde2118e2015-02-17 17:27:44 +0300976 inline bool sanitize (hb_sanitize_context_t *c) const
977 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -0500978 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +0100979 return_trace (c->check_struct (this));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -0400980 }
981
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100982 HBUINT16 sequenceIndex; /* Index into current glyph
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400983 * sequence--first glyph = 0 */
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100984 HBUINT16 lookupListIndex; /* Lookup to apply to that
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400985 * position--zero--based */
Behdad Esfahbod569da922010-05-10 16:38:32 -0400986 public:
987 DEFINE_SIZE_STATIC (4);
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400988};
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400989
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400990
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500991template <typename context_t>
992static inline void recurse_lookups (context_t *c,
993 unsigned int lookupCount,
994 const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400995{
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400996 for (unsigned int i = 0; i < lookupCount; i++)
Behdad Esfahbod86522e42013-07-22 19:07:53 -0400997 c->recurse (lookupRecord[i].lookupListIndex);
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400998}
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -0400999
Behdad Esfahbodfd034492018-01-17 16:46:51 -08001000static inline bool apply_lookup (hb_ot_apply_context_t *c,
Behdad Esfahbode072c242009-05-18 03:47:31 -04001001 unsigned int count, /* Including the first glyph */
Behdad Esfahbod5ba45042015-11-02 15:43:08 -08001002 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
Behdad Esfahbode072c242009-05-18 03:47:31 -04001003 unsigned int lookupCount,
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001004 const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
1005 unsigned int match_length)
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001006{
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02001007 TRACE_APPLY (nullptr);
Behdad Esfahbod902cc8a2012-11-23 15:06:59 -05001008
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001009 hb_buffer_t *buffer = c->buffer;
jfkthame44f7d6e2017-02-17 03:03:24 +00001010 int end;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001011
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001012 /* All positions are distance from beginning of *output* buffer.
1013 * Adjust. */
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001014 {
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001015 unsigned int bl = buffer->backtrack_len ();
1016 end = bl + match_length;
Behdad Esfahbod8751de52013-07-18 16:29:50 -04001017
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001018 int delta = bl - buffer->idx;
1019 /* Convert positions to new indexing. */
1020 for (unsigned int j = 0; j < count; j++)
1021 match_positions[j] += delta;
Behdad Esfahbod8820bb22013-02-14 07:41:03 -05001022 }
Behdad Esfahbode73a0c22009-05-18 04:15:25 -04001023
Behdad Esfahbod7185b272018-05-31 20:03:00 -07001024 for (unsigned int i = 0; i < lookupCount && buffer->successful; i++)
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001025 {
1026 unsigned int idx = lookupRecord[i].sequenceIndex;
1027 if (idx >= count)
1028 continue;
1029
Behdad Esfahbod9cc1ed42015-11-19 12:39:09 -08001030 /* Don't recurse to ourself at same position.
1031 * Note that this test is too naive, it doesn't catch longer loops. */
1032 if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)
1033 continue;
1034
Behdad Esfahbode5930722017-11-14 15:47:55 -08001035 if (unlikely (!buffer->move_to (match_positions[idx])))
1036 break;
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001037
Behdad Esfahbodbaf77792017-11-14 21:53:48 -08001038 if (unlikely (buffer->max_ops <= 0))
1039 break;
1040
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001041 unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
1042 if (!c->recurse (lookupRecord[i].lookupListIndex))
1043 continue;
1044
1045 unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
1046 int delta = new_len - orig_len;
1047
1048 if (!delta)
1049 continue;
1050
Behdad Esfahbod9ac9af72017-03-05 13:51:01 -08001051 /* Recursed lookup changed buffer len. Adjust.
1052 *
1053 * TODO:
1054 *
1055 * Right now, if buffer length increased by n, we assume n new glyphs
1056 * were added right after the current position, and if buffer length
1057 * was decreased by n, we assume n match positions after the current
1058 * one where removed. The former (buffer length increased) case is
1059 * fine, but the decrease case can be improved in at least two ways,
1060 * both of which are significant:
1061 *
1062 * - If recursed-to lookup is MultipleSubst and buffer length
1063 * decreased, then it's current match position that was deleted,
1064 * NOT the one after it.
1065 *
1066 * - If buffer length was decreased by n, it does not necessarily
1067 * mean that n match positions where removed, as there might
1068 * have been marks and default-ignorables in the sequence. We
1069 * should instead drop match positions between current-position
1070 * and current-position + n instead.
1071 *
1072 * It should be possible to construct tests for both of these cases.
1073 */
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001074
jfkthame44f7d6e2017-02-17 03:03:24 +00001075 end += delta;
Behdad Esfahbod47e7a182017-03-10 13:23:02 -08001076 if (end <= int (match_positions[idx]))
Behdad Esfahbod359dead2016-05-06 16:19:19 +01001077 {
Behdad Esfahbod4b4a1b92016-12-21 23:10:43 -06001078 /* End might end up being smaller than match_positions[idx] if the recursed
Behdad Esfahbod47e7a182017-03-10 13:23:02 -08001079 * lookup ended up removing many items, more than we have had matched.
Behdad Esfahbod4b4a1b92016-12-21 23:10:43 -06001080 * Just never rewind end back and get out of here.
1081 * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */
1082 end = match_positions[idx];
Behdad Esfahbod47e7a182017-03-10 13:23:02 -08001083 /* There can't be any further changes. */
Behdad Esfahbod359dead2016-05-06 16:19:19 +01001084 break;
1085 }
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001086
1087 unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
1088
1089 if (delta > 0)
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001090 {
Behdad Esfahbod5ba45042015-11-02 15:43:08 -08001091 if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001092 break;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001093 }
1094 else
1095 {
Behdad Esfahbod47e7a182017-03-10 13:23:02 -08001096 /* NOTE: delta is negative. */
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001097 delta = MAX (delta, (int) next - (int) count);
1098 next -= delta;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001099 }
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001100
1101 /* Shift! */
1102 memmove (match_positions + next + delta, match_positions + next,
1103 (count - next) * sizeof (match_positions[0]));
1104 next += delta;
1105 count += delta;
1106
1107 /* Fill in new entries. */
1108 for (unsigned int j = idx + 1; j < next; j++)
1109 match_positions[j] = match_positions[j - 1] + 1;
1110
1111 /* And fixup the rest. */
1112 for (; next < count; next++)
1113 match_positions[next] += delta;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001114 }
1115
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001116 buffer->move_to (end);
1117
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001118 return_trace (true);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001119}
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001120
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -04001121
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001122
1123/* Contextual lookups */
1124
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001125struct ContextClosureLookupContext
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001126{
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001127 ContextClosureFuncs funcs;
1128 const void *intersects_data;
1129};
1130
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001131struct ContextCollectGlyphsLookupContext
1132{
1133 ContextCollectGlyphsFuncs funcs;
1134 const void *collect_data;
1135};
1136
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001137struct ContextApplyLookupContext
1138{
1139 ContextApplyFuncs funcs;
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001140 const void *match_data;
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001141};
1142
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001143static inline void context_closure_lookup (hb_closure_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001144 unsigned int inputCount, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001145 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001146 unsigned int lookupCount,
1147 const LookupRecord lookupRecord[],
1148 ContextClosureLookupContext &lookup_context)
1149{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001150 if (intersects_array (c,
1151 inputCount ? inputCount - 1 : 0, input,
1152 lookup_context.funcs.intersects, lookup_context.intersects_data))
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001153 recurse_lookups (c,
1154 lookupCount, lookupRecord);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001155}
1156
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001157static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
1158 unsigned int inputCount, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001159 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001160 unsigned int lookupCount,
1161 const LookupRecord lookupRecord[],
1162 ContextCollectGlyphsLookupContext &lookup_context)
1163{
Behdad Esfahbod83035932012-12-04 17:08:41 -05001164 collect_array (c, c->input,
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001165 inputCount ? inputCount - 1 : 0, input,
1166 lookup_context.funcs.collect, lookup_context.collect_data);
1167 recurse_lookups (c,
1168 lookupCount, lookupRecord);
1169}
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001170
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001171static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
1172 unsigned int inputCount, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001173 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbod0beb66e2012-12-05 18:46:04 -05001174 unsigned int lookupCount HB_UNUSED,
1175 const LookupRecord lookupRecord[] HB_UNUSED,
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001176 ContextApplyLookupContext &lookup_context)
1177{
1178 return would_match_input (c,
1179 inputCount, input,
1180 lookup_context.funcs.match, lookup_context.match_data);
1181}
Behdad Esfahbodfd034492018-01-17 16:46:51 -08001182static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001183 unsigned int inputCount, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001184 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001185 unsigned int lookupCount,
1186 const LookupRecord lookupRecord[],
1187 ContextApplyLookupContext &lookup_context)
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001188{
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001189 unsigned int match_length = 0;
Behdad Esfahbod5ba45042015-11-02 15:43:08 -08001190 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001191 return match_input (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -04001192 inputCount, input,
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001193 lookup_context.funcs.match, lookup_context.match_data,
1194 &match_length, match_positions)
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +02001195 && (c->buffer->unsafe_to_break (c->buffer->idx, c->buffer->idx + match_length),
1196 apply_lookup (c,
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001197 inputCount, match_positions,
1198 lookupCount, lookupRecord,
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +02001199 match_length));
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001200}
1201
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001202struct Rule
1203{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001204 inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001205 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001206 TRACE_CLOSURE (this);
Behdad Esfahbod093c5202014-12-12 21:07:53 -08001207 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001208 context_closure_lookup (c,
Behdad Esfahbod093c5202014-12-12 21:07:53 -08001209 inputCount, inputZ,
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001210 lookupCount, lookupRecord,
1211 lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001212 }
1213
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001214 inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
1215 {
1216 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbod093c5202014-12-12 21:07:53 -08001217 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001218 context_collect_glyphs_lookup (c,
Behdad Esfahbod093c5202014-12-12 21:07:53 -08001219 inputCount, inputZ,
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001220 lookupCount, lookupRecord,
1221 lookup_context);
1222 }
1223
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001224 inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
1225 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001226 TRACE_WOULD_APPLY (this);
Behdad Esfahbod093c5202014-12-12 21:07:53 -08001227 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001228 return_trace (context_would_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001229 }
1230
Behdad Esfahbodfd034492018-01-17 16:46:51 -08001231 inline bool apply (hb_ot_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001232 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001233 TRACE_APPLY (this);
Behdad Esfahbod093c5202014-12-12 21:07:53 -08001234 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001235 return_trace (context_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001236 }
1237
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001238 public:
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03001239 inline bool sanitize (hb_sanitize_context_t *c) const
1240 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001241 TRACE_SANITIZE (this);
Behdad Esfahbod5aad8192017-11-03 17:16:26 -04001242 return_trace (inputCount.sanitize (c) &&
1243 lookupCount.sanitize (c) &&
1244 c->check_range (inputZ,
1245 inputZ[0].static_size * inputCount +
Behdad Esfahbod6d7c6e12018-02-07 14:09:56 -06001246 LookupRecord::static_size * lookupCount));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001247 }
1248
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001249 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001250 HBUINT16 inputCount; /* Total number of glyphs in input
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001251 * glyph sequence--includes the first
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001252 * glyph */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001253 HBUINT16 lookupCount; /* Number of LookupRecords */
1254 HBUINT16 inputZ[VAR]; /* Array of match inputs--start with
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001255 * second glyph */
Behdad Esfahbod6d7c6e12018-02-07 14:09:56 -06001256/*LookupRecord lookupRecordX[VAR];*/ /* Array of LookupRecords--in
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001257 * design order */
Behdad Esfahbod569da922010-05-10 16:38:32 -04001258 public:
Behdad Esfahbod6d7c6e12018-02-07 14:09:56 -06001259 DEFINE_SIZE_ARRAY (4, inputZ);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001260};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001261
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001262struct RuleSet
1263{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001264 inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001265 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001266 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001267 unsigned int num_rules = rule.len;
1268 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001269 (this+rule[i]).closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001270 }
1271
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001272 inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
1273 {
1274 TRACE_COLLECT_GLYPHS (this);
1275 unsigned int num_rules = rule.len;
1276 for (unsigned int i = 0; i < num_rules; i++)
1277 (this+rule[i]).collect_glyphs (c, lookup_context);
1278 }
1279
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001280 inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
1281 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001282 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001283 unsigned int num_rules = rule.len;
1284 for (unsigned int i = 0; i < num_rules; i++)
1285 {
1286 if ((this+rule[i]).would_apply (c, lookup_context))
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001287 return_trace (true);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001288 }
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001289 return_trace (false);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001290 }
1291
Behdad Esfahbodfd034492018-01-17 16:46:51 -08001292 inline bool apply (hb_ot_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001293 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001294 TRACE_APPLY (this);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001295 unsigned int num_rules = rule.len;
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001296 for (unsigned int i = 0; i < num_rules; i++)
1297 {
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001298 if ((this+rule[i]).apply (c, lookup_context))
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001299 return_trace (true);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001300 }
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001301 return_trace (false);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001302 }
1303
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03001304 inline bool sanitize (hb_sanitize_context_t *c) const
1305 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001306 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001307 return_trace (rule.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001308 }
1309
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001310 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001311 OffsetArrayOf<Rule>
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001312 rule; /* Array of Rule tables
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001313 * ordered by preference */
Behdad Esfahboded074222010-05-10 18:08:46 -04001314 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001315 DEFINE_SIZE_ARRAY (2, rule);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001316};
1317
1318
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001319struct ContextFormat1
1320{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001321 inline void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001322 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001323 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001324
1325 const Coverage &cov = (this+coverage);
1326
1327 struct ContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001328 {intersects_glyph},
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02001329 nullptr
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001330 };
1331
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001332 unsigned int count = ruleSet.len;
1333 for (unsigned int i = 0; i < count; i++)
1334 if (cov.intersects_coverage (c->glyphs, i)) {
1335 const RuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001336 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001337 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001338 }
1339
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001340 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
1341 {
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001342 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbod83035932012-12-04 17:08:41 -05001343 (this+coverage).add_coverage (c->input);
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001344
1345 struct ContextCollectGlyphsLookupContext lookup_context = {
1346 {collect_glyph},
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02001347 nullptr
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001348 };
1349
1350 unsigned int count = ruleSet.len;
1351 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001352 (this+ruleSet[i]).collect_glyphs (c, lookup_context);
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001353 }
1354
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001355 inline bool would_apply (hb_would_apply_context_t *c) const
1356 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001357 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001358
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05001359 const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001360 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001361 {match_glyph},
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02001362 nullptr
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001363 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001364 return_trace (rule_set.would_apply (c, lookup_context));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001365 }
1366
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001367 inline const Coverage &get_coverage (void) const
1368 {
1369 return this+coverage;
1370 }
1371
Behdad Esfahbodfd034492018-01-17 16:46:51 -08001372 inline bool apply (hb_ot_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001373 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001374 TRACE_APPLY (this);
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05001375 unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
Behdad Esfahbod64d3fc82010-05-03 22:51:19 -04001376 if (likely (index == NOT_COVERED))
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001377 return_trace (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001378
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001379 const RuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001380 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001381 {match_glyph},
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02001382 nullptr
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001383 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001384 return_trace (rule_set.apply (c, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001385 }
1386
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03001387 inline bool sanitize (hb_sanitize_context_t *c) const
1388 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001389 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001390 return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001391 }
1392
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001393 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001394 HBUINT16 format; /* Format identifier--format = 1 */
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001395 OffsetTo<Coverage>
1396 coverage; /* Offset to Coverage table--from
1397 * beginning of table */
1398 OffsetArrayOf<RuleSet>
1399 ruleSet; /* Array of RuleSet tables
1400 * ordered by Coverage Index */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001401 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001402 DEFINE_SIZE_ARRAY (6, ruleSet);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001403};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001404
1405
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001406struct ContextFormat2
1407{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001408 inline void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001409 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001410 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001411 if (!(this+coverage).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001412 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001413
1414 const ClassDef &class_def = this+classDef;
1415
1416 struct ContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001417 {intersects_class},
Behdad Esfahbod11fba792013-01-02 23:36:37 -06001418 &class_def
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001419 };
1420
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001421 unsigned int count = ruleSet.len;
1422 for (unsigned int i = 0; i < count; i++)
1423 if (class_def.intersects_class (c->glyphs, i)) {
1424 const RuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001425 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001426 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001427 }
1428
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001429 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
1430 {
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001431 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbod83035932012-12-04 17:08:41 -05001432 (this+coverage).add_coverage (c->input);
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001433
Behdad Esfahbod11fba792013-01-02 23:36:37 -06001434 const ClassDef &class_def = this+classDef;
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001435 struct ContextCollectGlyphsLookupContext lookup_context = {
1436 {collect_class},
Behdad Esfahbod11fba792013-01-02 23:36:37 -06001437 &class_def
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001438 };
1439
1440 unsigned int count = ruleSet.len;
1441 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001442 (this+ruleSet[i]).collect_glyphs (c, lookup_context);
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001443 }
1444
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001445 inline bool would_apply (hb_would_apply_context_t *c) const
1446 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001447 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001448
1449 const ClassDef &class_def = this+classDef;
Behdad Esfahbod2dc11412012-11-24 19:16:34 -05001450 unsigned int index = class_def.get_class (c->glyphs[0]);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001451 const RuleSet &rule_set = this+ruleSet[index];
1452 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001453 {match_class},
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001454 &class_def
1455 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001456 return_trace (rule_set.would_apply (c, lookup_context));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001457 }
1458
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001459 inline const Coverage &get_coverage (void) const
1460 {
1461 return this+coverage;
1462 }
1463
Behdad Esfahbodfd034492018-01-17 16:46:51 -08001464 inline bool apply (hb_ot_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001465 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001466 TRACE_APPLY (this);
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05001467 unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001468 if (likely (index == NOT_COVERED)) return_trace (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001469
1470 const ClassDef &class_def = this+classDef;
Behdad Esfahbod2dc11412012-11-24 19:16:34 -05001471 index = class_def.get_class (c->buffer->cur().codepoint);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001472 const RuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001473 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001474 {match_class},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001475 &class_def
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001476 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001477 return_trace (rule_set.apply (c, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001478 }
1479
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03001480 inline bool sanitize (hb_sanitize_context_t *c) const
1481 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001482 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001483 return_trace (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001484 }
1485
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001486 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001487 HBUINT16 format; /* Format identifier--format = 2 */
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001488 OffsetTo<Coverage>
1489 coverage; /* Offset to Coverage table--from
1490 * beginning of table */
1491 OffsetTo<ClassDef>
1492 classDef; /* Offset to glyph ClassDef table--from
1493 * beginning of table */
1494 OffsetArrayOf<RuleSet>
1495 ruleSet; /* Array of RuleSet tables
1496 * ordered by class */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001497 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001498 DEFINE_SIZE_ARRAY (8, ruleSet);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001499};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001500
1501
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001502struct ContextFormat3
1503{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001504 inline void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001505 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001506 TRACE_CLOSURE (this);
Behdad Esfahbod093c5202014-12-12 21:07:53 -08001507 if (!(this+coverageZ[0]).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001508 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001509
Behdad Esfahbod093c5202014-12-12 21:07:53 -08001510 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001511 struct ContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001512 {intersects_coverage},
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001513 this
1514 };
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001515 context_closure_lookup (c,
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001516 glyphCount, (const HBUINT16 *) (coverageZ + 1),
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001517 lookupCount, lookupRecord,
1518 lookup_context);
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001519 }
1520
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001521 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
1522 {
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001523 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbod093c5202014-12-12 21:07:53 -08001524 (this+coverageZ[0]).add_coverage (c->input);
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001525
Behdad Esfahbod093c5202014-12-12 21:07:53 -08001526 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001527 struct ContextCollectGlyphsLookupContext lookup_context = {
1528 {collect_coverage},
Behdad Esfahbode75943d2012-11-30 08:38:24 +02001529 this
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001530 };
1531
1532 context_collect_glyphs_lookup (c,
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001533 glyphCount, (const HBUINT16 *) (coverageZ + 1),
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001534 lookupCount, lookupRecord,
1535 lookup_context);
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001536 }
1537
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001538 inline bool would_apply (hb_would_apply_context_t *c) const
1539 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001540 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001541
Behdad Esfahbod093c5202014-12-12 21:07:53 -08001542 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001543 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001544 {match_coverage},
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001545 this
1546 };
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001547 return_trace (context_would_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001548 }
1549
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001550 inline const Coverage &get_coverage (void) const
1551 {
Behdad Esfahbod093c5202014-12-12 21:07:53 -08001552 return this+coverageZ[0];
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001553 }
1554
Behdad Esfahbodfd034492018-01-17 16:46:51 -08001555 inline bool apply (hb_ot_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001556 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001557 TRACE_APPLY (this);
Behdad Esfahbod093c5202014-12-12 21:07:53 -08001558 unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001559 if (likely (index == NOT_COVERED)) return_trace (false);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001560
Behdad Esfahbod093c5202014-12-12 21:07:53 -08001561 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001562 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001563 {match_coverage},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001564 this
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001565 };
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001566 return_trace (context_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001567 }
1568
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03001569 inline bool sanitize (hb_sanitize_context_t *c) const
1570 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001571 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001572 if (!c->check_struct (this)) return_trace (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001573 unsigned int count = glyphCount;
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001574 if (!count) return_trace (false); /* We want to access coverageZ[0] freely. */
1575 if (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return_trace (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001576 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001577 if (!coverageZ[i].sanitize (c, this)) return_trace (false);
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03001578 const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001579 return_trace (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001580 }
1581
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001582 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001583 HBUINT16 format; /* Format identifier--format = 3 */
1584 HBUINT16 glyphCount; /* Number of glyphs in the input glyph
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001585 * sequence */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001586 HBUINT16 lookupCount; /* Number of LookupRecords */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001587 OffsetTo<Coverage>
Behdad Esfahbod093c5202014-12-12 21:07:53 -08001588 coverageZ[VAR]; /* Array of offsets to Coverage
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001589 * table in glyph sequence order */
Behdad Esfahbod6d7c6e12018-02-07 14:09:56 -06001590/*LookupRecord lookupRecordX[VAR];*/ /* Array of LookupRecords--in
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001591 * design order */
Behdad Esfahbod569da922010-05-10 16:38:32 -04001592 public:
Behdad Esfahbod6d7c6e12018-02-07 14:09:56 -06001593 DEFINE_SIZE_ARRAY (6, coverageZ);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001594};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001595
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001596struct Context
1597{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001598 template <typename context_t>
Behdad Esfahbod9c5a9ee2013-03-09 01:55:04 -05001599 inline typename context_t::return_t dispatch (context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001600 {
Behdad Esfahbod00f6a8e2014-12-12 20:36:49 -08001601 TRACE_DISPATCH (this, u.format);
Behdad Esfahbodf396fbb2015-10-09 12:25:55 -04001602 if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001603 switch (u.format) {
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001604 case 1: return_trace (c->dispatch (u.format1));
1605 case 2: return_trace (c->dispatch (u.format2));
1606 case 3: return_trace (c->dispatch (u.format3));
1607 default:return_trace (c->default_return_value ());
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001608 }
1609 }
1610
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001611 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001612 union {
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001613 HBUINT16 format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001614 ContextFormat1 format1;
1615 ContextFormat2 format2;
1616 ContextFormat3 format3;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001617 } u;
1618};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001619
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001620
1621/* Chaining Contextual lookups */
1622
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001623struct ChainContextClosureLookupContext
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001624{
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001625 ContextClosureFuncs funcs;
1626 const void *intersects_data[3];
1627};
1628
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001629struct ChainContextCollectGlyphsLookupContext
1630{
1631 ContextCollectGlyphsFuncs funcs;
1632 const void *collect_data[3];
1633};
1634
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001635struct ChainContextApplyLookupContext
1636{
1637 ContextApplyFuncs funcs;
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001638 const void *match_data[3];
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001639};
1640
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001641static inline void chain_context_closure_lookup (hb_closure_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001642 unsigned int backtrackCount,
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001643 const HBUINT16 backtrack[],
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001644 unsigned int inputCount, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001645 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001646 unsigned int lookaheadCount,
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001647 const HBUINT16 lookahead[],
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001648 unsigned int lookupCount,
1649 const LookupRecord lookupRecord[],
1650 ChainContextClosureLookupContext &lookup_context)
1651{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001652 if (intersects_array (c,
1653 backtrackCount, backtrack,
1654 lookup_context.funcs.intersects, lookup_context.intersects_data[0])
1655 && intersects_array (c,
1656 inputCount ? inputCount - 1 : 0, input,
1657 lookup_context.funcs.intersects, lookup_context.intersects_data[1])
Behdad Esfahbod74439d02013-07-22 19:02:29 -04001658 && intersects_array (c,
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001659 lookaheadCount, lookahead,
1660 lookup_context.funcs.intersects, lookup_context.intersects_data[2]))
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001661 recurse_lookups (c,
1662 lookupCount, lookupRecord);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001663}
1664
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001665static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
1666 unsigned int backtrackCount,
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001667 const HBUINT16 backtrack[],
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001668 unsigned int inputCount, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001669 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001670 unsigned int lookaheadCount,
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001671 const HBUINT16 lookahead[],
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001672 unsigned int lookupCount,
1673 const LookupRecord lookupRecord[],
1674 ChainContextCollectGlyphsLookupContext &lookup_context)
1675{
Behdad Esfahbod83035932012-12-04 17:08:41 -05001676 collect_array (c, c->before,
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001677 backtrackCount, backtrack,
1678 lookup_context.funcs.collect, lookup_context.collect_data[0]);
Behdad Esfahbod83035932012-12-04 17:08:41 -05001679 collect_array (c, c->input,
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001680 inputCount ? inputCount - 1 : 0, input,
1681 lookup_context.funcs.collect, lookup_context.collect_data[1]);
Behdad Esfahbod83035932012-12-04 17:08:41 -05001682 collect_array (c, c->after,
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001683 lookaheadCount, lookahead,
1684 lookup_context.funcs.collect, lookup_context.collect_data[2]);
1685 recurse_lookups (c,
1686 lookupCount, lookupRecord);
1687}
1688
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001689static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
1690 unsigned int backtrackCount,
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001691 const HBUINT16 backtrack[] HB_UNUSED,
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001692 unsigned int inputCount, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001693 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001694 unsigned int lookaheadCount,
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001695 const HBUINT16 lookahead[] HB_UNUSED,
Behdad Esfahbod0beb66e2012-12-05 18:46:04 -05001696 unsigned int lookupCount HB_UNUSED,
1697 const LookupRecord lookupRecord[] HB_UNUSED,
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001698 ChainContextApplyLookupContext &lookup_context)
1699{
Behdad Esfahbodd9b204d2012-08-23 16:22:28 -04001700 return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
Behdad Esfahbod1f2bb172012-08-23 16:10:37 -04001701 && would_match_input (c,
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001702 inputCount, input,
1703 lookup_context.funcs.match, lookup_context.match_data[1]);
1704}
1705
Behdad Esfahbodfd034492018-01-17 16:46:51 -08001706static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001707 unsigned int backtrackCount,
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001708 const HBUINT16 backtrack[],
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001709 unsigned int inputCount, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001710 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001711 unsigned int lookaheadCount,
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001712 const HBUINT16 lookahead[],
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001713 unsigned int lookupCount,
1714 const LookupRecord lookupRecord[],
1715 ChainContextApplyLookupContext &lookup_context)
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001716{
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +02001717 unsigned int start_index = 0, match_length = 0, end_index = 0;
Behdad Esfahbod5ba45042015-11-02 15:43:08 -08001718 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
Behdad Esfahbodf19e0b02012-06-09 02:26:57 -04001719 return match_input (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -04001720 inputCount, input,
1721 lookup_context.funcs.match, lookup_context.match_data[1],
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001722 &match_length, match_positions)
Behdad Esfahbodf19e0b02012-06-09 02:26:57 -04001723 && match_backtrack (c,
1724 backtrackCount, backtrack,
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +02001725 lookup_context.funcs.match, lookup_context.match_data[0],
1726 &start_index)
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001727 && match_lookahead (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -04001728 lookaheadCount, lookahead,
1729 lookup_context.funcs.match, lookup_context.match_data[2],
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +02001730 match_length, &end_index)
1731 && (c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index),
1732 apply_lookup (c,
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001733 inputCount, match_positions,
1734 lookupCount, lookupRecord,
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +02001735 match_length));
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001736}
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001737
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001738struct ChainRule
1739{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001740 inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001741 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001742 TRACE_CLOSURE (this);
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001743 const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
1744 const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001745 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001746 chain_context_closure_lookup (c,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07001747 backtrack.len, backtrack.arrayZ,
1748 input.len, input.arrayZ,
1749 lookahead.len, lookahead.arrayZ,
1750 lookup.len, lookup.arrayZ,
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001751 lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001752 }
1753
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001754 inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
1755 {
1756 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001757 const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
1758 const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001759 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1760 chain_context_collect_glyphs_lookup (c,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07001761 backtrack.len, backtrack.arrayZ,
1762 input.len, input.arrayZ,
1763 lookahead.len, lookahead.arrayZ,
1764 lookup.len, lookup.arrayZ,
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001765 lookup_context);
1766 }
1767
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001768 inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
1769 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001770 TRACE_WOULD_APPLY (this);
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001771 const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
1772 const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001773 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001774 return_trace (chain_context_would_apply_lookup (c,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07001775 backtrack.len, backtrack.arrayZ,
1776 input.len, input.arrayZ,
1777 lookahead.len, lookahead.arrayZ, lookup.len,
1778 lookup.arrayZ, lookup_context));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001779 }
1780
Behdad Esfahbodfd034492018-01-17 16:46:51 -08001781 inline bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001782 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001783 TRACE_APPLY (this);
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001784 const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
1785 const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001786 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001787 return_trace (chain_context_apply_lookup (c,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07001788 backtrack.len, backtrack.arrayZ,
1789 input.len, input.arrayZ,
1790 lookahead.len, lookahead.arrayZ, lookup.len,
1791 lookup.arrayZ, lookup_context));
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001792 }
1793
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03001794 inline bool sanitize (hb_sanitize_context_t *c) const
1795 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001796 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001797 if (!backtrack.sanitize (c)) return_trace (false);
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001798 const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001799 if (!input.sanitize (c)) return_trace (false);
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001800 const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001801 if (!lookahead.sanitize (c)) return_trace (false);
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03001802 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001803 return_trace (lookup.sanitize (c));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001804 }
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001805
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001806 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001807 ArrayOf<HBUINT16>
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001808 backtrack; /* Array of backtracking values
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001809 * (to be matched before the input
1810 * sequence) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001811 HeadlessArrayOf<HBUINT16>
Behdad Esfahbode8cbaaf2009-05-18 02:03:58 -04001812 inputX; /* Array of input values (start with
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001813 * second glyph) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001814 ArrayOf<HBUINT16>
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001815 lookaheadX; /* Array of lookahead values's (to be
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001816 * matched after the input sequence) */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04001817 ArrayOf<LookupRecord>
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001818 lookupX; /* Array of LookupRecords--in
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001819 * design order) */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001820 public:
Behdad Esfahbodbea34c72010-05-10 17:28:16 -04001821 DEFINE_SIZE_MIN (8);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001822};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001823
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001824struct ChainRuleSet
1825{
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001826 inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001827 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001828 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001829 unsigned int num_rules = rule.len;
1830 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001831 (this+rule[i]).closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001832 }
1833
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001834 inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
1835 {
1836 TRACE_COLLECT_GLYPHS (this);
1837 unsigned int num_rules = rule.len;
1838 for (unsigned int i = 0; i < num_rules; i++)
1839 (this+rule[i]).collect_glyphs (c, lookup_context);
1840 }
1841
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001842 inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
1843 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001844 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001845 unsigned int num_rules = rule.len;
1846 for (unsigned int i = 0; i < num_rules; i++)
1847 if ((this+rule[i]).would_apply (c, lookup_context))
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001848 return_trace (true);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001849
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001850 return_trace (false);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001851 }
1852
Behdad Esfahbodfd034492018-01-17 16:46:51 -08001853 inline bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001854 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001855 TRACE_APPLY (this);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001856 unsigned int num_rules = rule.len;
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001857 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001858 if ((this+rule[i]).apply (c, lookup_context))
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001859 return_trace (true);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001860
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001861 return_trace (false);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001862 }
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001863
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03001864 inline bool sanitize (hb_sanitize_context_t *c) const
1865 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001866 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001867 return_trace (rule.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001868 }
1869
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001870 protected:
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001871 OffsetArrayOf<ChainRule>
1872 rule; /* Array of ChainRule tables
1873 * ordered by preference */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001874 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001875 DEFINE_SIZE_ARRAY (2, rule);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001876};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001877
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001878struct ChainContextFormat1
1879{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001880 inline void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001881 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001882 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001883 const Coverage &cov = (this+coverage);
1884
1885 struct ChainContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001886 {intersects_glyph},
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02001887 {nullptr, nullptr, nullptr}
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001888 };
1889
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001890 unsigned int count = ruleSet.len;
1891 for (unsigned int i = 0; i < count; i++)
1892 if (cov.intersects_coverage (c->glyphs, i)) {
1893 const ChainRuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001894 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001895 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001896 }
1897
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001898 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
1899 {
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001900 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbod83035932012-12-04 17:08:41 -05001901 (this+coverage).add_coverage (c->input);
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001902
1903 struct ChainContextCollectGlyphsLookupContext lookup_context = {
1904 {collect_glyph},
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02001905 {nullptr, nullptr, nullptr}
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001906 };
1907
1908 unsigned int count = ruleSet.len;
1909 for (unsigned int i = 0; i < count; i++)
1910 (this+ruleSet[i]).collect_glyphs (c, lookup_context);
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001911 }
1912
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001913 inline bool would_apply (hb_would_apply_context_t *c) const
1914 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001915 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001916
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05001917 const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001918 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001919 {match_glyph},
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02001920 {nullptr, nullptr, nullptr}
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001921 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001922 return_trace (rule_set.would_apply (c, lookup_context));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001923 }
1924
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001925 inline const Coverage &get_coverage (void) const
1926 {
1927 return this+coverage;
1928 }
1929
Behdad Esfahbodfd034492018-01-17 16:46:51 -08001930 inline bool apply (hb_ot_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001931 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001932 TRACE_APPLY (this);
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05001933 unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001934 if (likely (index == NOT_COVERED)) return_trace (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001935
1936 const ChainRuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001937 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001938 {match_glyph},
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02001939 {nullptr, nullptr, nullptr}
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001940 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001941 return_trace (rule_set.apply (c, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001942 }
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001943
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03001944 inline bool sanitize (hb_sanitize_context_t *c) const
1945 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001946 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001947 return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001948 }
1949
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001950 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001951 HBUINT16 format; /* Format identifier--format = 1 */
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001952 OffsetTo<Coverage>
1953 coverage; /* Offset to Coverage table--from
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001954 * beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001955 OffsetArrayOf<ChainRuleSet>
1956 ruleSet; /* Array of ChainRuleSet tables
1957 * ordered by Coverage Index */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001958 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001959 DEFINE_SIZE_ARRAY (6, ruleSet);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001960};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001961
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001962struct ChainContextFormat2
1963{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001964 inline void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001965 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001966 TRACE_CLOSURE (this);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001967 if (!(this+coverage).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001968 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001969
1970 const ClassDef &backtrack_class_def = this+backtrackClassDef;
1971 const ClassDef &input_class_def = this+inputClassDef;
1972 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
1973
1974 struct ChainContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001975 {intersects_class},
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001976 {&backtrack_class_def,
1977 &input_class_def,
1978 &lookahead_class_def}
1979 };
1980
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001981 unsigned int count = ruleSet.len;
1982 for (unsigned int i = 0; i < count; i++)
1983 if (input_class_def.intersects_class (c->glyphs, i)) {
1984 const ChainRuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001985 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001986 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001987 }
1988
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001989 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
1990 {
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001991 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbod83035932012-12-04 17:08:41 -05001992 (this+coverage).add_coverage (c->input);
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001993
Behdad Esfahbod11fba792013-01-02 23:36:37 -06001994 const ClassDef &backtrack_class_def = this+backtrackClassDef;
1995 const ClassDef &input_class_def = this+inputClassDef;
1996 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
1997
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001998 struct ChainContextCollectGlyphsLookupContext lookup_context = {
1999 {collect_class},
Behdad Esfahbod11fba792013-01-02 23:36:37 -06002000 {&backtrack_class_def,
2001 &input_class_def,
2002 &lookahead_class_def}
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05002003 };
2004
2005 unsigned int count = ruleSet.len;
2006 for (unsigned int i = 0; i < count; i++)
2007 (this+ruleSet[i]).collect_glyphs (c, lookup_context);
Behdad Esfahbod26514d52012-11-23 18:13:48 -05002008 }
2009
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002010 inline bool would_apply (hb_would_apply_context_t *c) const
2011 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002012 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002013
Behdad Esfahbod11fba792013-01-02 23:36:37 -06002014 const ClassDef &backtrack_class_def = this+backtrackClassDef;
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002015 const ClassDef &input_class_def = this+inputClassDef;
Behdad Esfahbod11fba792013-01-02 23:36:37 -06002016 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002017
Behdad Esfahbod2dc11412012-11-24 19:16:34 -05002018 unsigned int index = input_class_def.get_class (c->glyphs[0]);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002019 const ChainRuleSet &rule_set = this+ruleSet[index];
2020 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05002021 {match_class},
Behdad Esfahbod11fba792013-01-02 23:36:37 -06002022 {&backtrack_class_def,
2023 &input_class_def,
2024 &lookahead_class_def}
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002025 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002026 return_trace (rule_set.would_apply (c, lookup_context));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002027 }
2028
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05002029 inline const Coverage &get_coverage (void) const
2030 {
2031 return this+coverage;
2032 }
2033
Behdad Esfahbodfd034492018-01-17 16:46:51 -08002034 inline bool apply (hb_ot_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04002035 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002036 TRACE_APPLY (this);
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05002037 unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002038 if (likely (index == NOT_COVERED)) return_trace (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002039
2040 const ClassDef &backtrack_class_def = this+backtrackClassDef;
2041 const ClassDef &input_class_def = this+inputClassDef;
2042 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
2043
Behdad Esfahbod2dc11412012-11-24 19:16:34 -05002044 index = input_class_def.get_class (c->buffer->cur().codepoint);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002045 const ChainRuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04002046 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05002047 {match_class},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04002048 {&backtrack_class_def,
2049 &input_class_def,
2050 &lookahead_class_def}
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002051 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002052 return_trace (rule_set.apply (c, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002053 }
2054
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03002055 inline bool sanitize (hb_sanitize_context_t *c) const
2056 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002057 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002058 return_trace (coverage.sanitize (c, this) &&
2059 backtrackClassDef.sanitize (c, this) &&
2060 inputClassDef.sanitize (c, this) &&
2061 lookaheadClassDef.sanitize (c, this) &&
2062 ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002063 }
2064
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04002065 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +01002066 HBUINT16 format; /* Format identifier--format = 2 */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002067 OffsetTo<Coverage>
2068 coverage; /* Offset to Coverage table--from
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002069 * beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002070 OffsetTo<ClassDef>
2071 backtrackClassDef; /* Offset to glyph ClassDef table
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002072 * containing backtrack sequence
2073 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002074 OffsetTo<ClassDef>
2075 inputClassDef; /* Offset to glyph ClassDef
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002076 * table containing input sequence
2077 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002078 OffsetTo<ClassDef>
2079 lookaheadClassDef; /* Offset to glyph ClassDef table
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002080 * containing lookahead sequence
2081 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002082 OffsetArrayOf<ChainRuleSet>
2083 ruleSet; /* Array of ChainRuleSet tables
2084 * ordered by class */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04002085 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04002086 DEFINE_SIZE_ARRAY (12, ruleSet);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002087};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002088
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04002089struct ChainContextFormat3
2090{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05002091 inline void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04002092 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002093 TRACE_CLOSURE (this);
Behdad Esfahbod5caece62012-04-23 23:03:12 -04002094 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
2095
2096 if (!(this+input[0]).intersects (c->glyphs))
2097 return;
2098
2099 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2100 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
2101 struct ChainContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05002102 {intersects_coverage},
Behdad Esfahbod5caece62012-04-23 23:03:12 -04002103 {this, this, this}
2104 };
2105 chain_context_closure_lookup (c,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07002106 backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
2107 input.len, (const HBUINT16 *) input.arrayZ + 1,
2108 lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
2109 lookup.len, lookup.arrayZ,
Behdad Esfahbod5caece62012-04-23 23:03:12 -04002110 lookup_context);
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04002111 }
2112
Behdad Esfahbod26514d52012-11-23 18:13:48 -05002113 inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
2114 {
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05002115 TRACE_COLLECT_GLYPHS (this);
2116 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
2117
Behdad Esfahbod83035932012-12-04 17:08:41 -05002118 (this+input[0]).add_coverage (c->input);
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05002119
2120 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2121 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
2122 struct ChainContextCollectGlyphsLookupContext lookup_context = {
2123 {collect_coverage},
2124 {this, this, this}
2125 };
2126 chain_context_collect_glyphs_lookup (c,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07002127 backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
2128 input.len, (const HBUINT16 *) input.arrayZ + 1,
2129 lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
2130 lookup.len, lookup.arrayZ,
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05002131 lookup_context);
Behdad Esfahbod26514d52012-11-23 18:13:48 -05002132 }
2133
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002134 inline bool would_apply (hb_would_apply_context_t *c) const
2135 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002136 TRACE_WOULD_APPLY (this);
Behdad Esfahbode6f74792012-07-28 18:34:58 -04002137
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002138 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002139 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2140 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
2141 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05002142 {match_coverage},
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002143 {this, this, this}
2144 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002145 return_trace (chain_context_would_apply_lookup (c,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07002146 backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
2147 input.len, (const HBUINT16 *) input.arrayZ + 1,
2148 lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
2149 lookup.len, lookup.arrayZ, lookup_context));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002150 }
2151
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05002152 inline const Coverage &get_coverage (void) const
2153 {
2154 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
2155 return this+input[0];
2156 }
2157
Behdad Esfahbodfd034492018-01-17 16:46:51 -08002158 inline bool apply (hb_ot_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04002159 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002160 TRACE_APPLY (this);
Behdad Esfahbode961c862010-04-21 15:56:11 -04002161 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04002162
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05002163 unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002164 if (likely (index == NOT_COVERED)) return_trace (false);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002165
Behdad Esfahbode961c862010-04-21 15:56:11 -04002166 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2167 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04002168 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05002169 {match_coverage},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04002170 {this, this, this}
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04002171 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002172 return_trace (chain_context_apply_lookup (c,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07002173 backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
2174 input.len, (const HBUINT16 *) input.arrayZ + 1,
2175 lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
2176 lookup.len, lookup.arrayZ, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002177 }
2178
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03002179 inline bool sanitize (hb_sanitize_context_t *c) const
2180 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002181 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002182 if (!backtrack.sanitize (c, this)) return_trace (false);
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03002183 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002184 if (!input.sanitize (c, this)) return_trace (false);
2185 if (!input.len) return_trace (false); /* To be consistent with Context. */
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03002186 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002187 if (!lookahead.sanitize (c, this)) return_trace (false);
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03002188 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002189 return_trace (lookup.sanitize (c));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002190 }
2191
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04002192 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +01002193 HBUINT16 format; /* Format identifier--format = 3 */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04002194 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04002195 backtrack; /* Array of coverage tables
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002196 * in backtracking sequence, in glyph
2197 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04002198 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04002199 inputX ; /* Array of coverage
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002200 * tables in input sequence, in glyph
2201 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04002202 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04002203 lookaheadX; /* Array of coverage tables
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002204 * in lookahead sequence, in glyph
2205 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04002206 ArrayOf<LookupRecord>
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04002207 lookupX; /* Array of LookupRecords--in
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04002208 * design order) */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04002209 public:
Behdad Esfahbodbea34c72010-05-10 17:28:16 -04002210 DEFINE_SIZE_MIN (10);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002211};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002212
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04002213struct ChainContext
2214{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05002215 template <typename context_t>
Behdad Esfahbod9c5a9ee2013-03-09 01:55:04 -05002216 inline typename context_t::return_t dispatch (context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04002217 {
Behdad Esfahbod00f6a8e2014-12-12 20:36:49 -08002218 TRACE_DISPATCH (this, u.format);
Behdad Esfahbodf396fbb2015-10-09 12:25:55 -04002219 if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04002220 switch (u.format) {
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002221 case 1: return_trace (c->dispatch (u.format1));
2222 case 2: return_trace (c->dispatch (u.format2));
2223 case 3: return_trace (c->dispatch (u.format3));
2224 default:return_trace (c->default_return_value ());
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002225 }
2226 }
2227
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04002228 protected:
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002229 union {
Behdad Esfahbod6b191782018-01-10 03:07:30 +01002230 HBUINT16 format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -04002231 ChainContextFormat1 format1;
2232 ChainContextFormat2 format2;
2233 ChainContextFormat3 format3;
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002234 } u;
2235};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002236
2237
Behdad Esfahbod095a1252015-02-19 10:29:41 +03002238template <typename T>
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002239struct ExtensionFormat1
2240{
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002241 inline unsigned int get_type (void) const { return extensionLookupType; }
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002242
Behdad Esfahbod095a1252015-02-19 10:29:41 +03002243 template <typename X>
2244 inline const X& get_subtable (void) const
2245 {
2246 unsigned int offset = extensionOffset;
2247 if (unlikely (!offset)) return Null(typename T::LookupSubTable);
2248 return StructAtOffset<typename T::LookupSubTable> (this, offset);
2249 }
2250
2251 template <typename context_t>
2252 inline typename context_t::return_t dispatch (context_t *c) const
2253 {
2254 TRACE_DISPATCH (this, format);
Behdad Esfahbodf396fbb2015-10-09 12:25:55 -04002255 if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ());
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002256 return_trace (get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ()));
Behdad Esfahbod095a1252015-02-19 10:29:41 +03002257 }
2258
2259 /* This is called from may_dispatch() above with hb_sanitize_context_t. */
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03002260 inline bool sanitize (hb_sanitize_context_t *c) const
2261 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002262 TRACE_SANITIZE (this);
Behdad Esfahbod949f6af2018-01-15 20:44:10 -05002263 return_trace (c->check_struct (this) &&
2264 extensionOffset != 0 &&
2265 extensionLookupType != T::LookupSubTable::Extension);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002266 }
2267
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04002268 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +01002269 HBUINT16 format; /* Format identifier. Set to 1. */
2270 HBUINT16 extensionLookupType; /* Lookup type of subtable referenced
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002271 * by ExtensionOffset (i.e. the
2272 * extension subtable). */
Behdad Esfahbodbcb6f1a2018-01-15 20:34:05 -05002273 HBUINT32 extensionOffset; /* Offset to the extension subtable,
Behdad Esfahbod81f2af42010-04-22 00:58:49 -04002274 * of lookup type subtable. */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04002275 public:
2276 DEFINE_SIZE_STATIC (8);
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002277};
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002278
Behdad Esfahbod653eeb22012-11-23 16:57:36 -05002279template <typename T>
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002280struct Extension
2281{
2282 inline unsigned int get_type (void) const
2283 {
2284 switch (u.format) {
Behdad Esfahboddacebca2010-05-10 19:45:41 -04002285 case 1: return u.format1.get_type ();
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002286 default:return 0;
2287 }
2288 }
Behdad Esfahbod7dddd4e2012-11-23 17:04:55 -05002289 template <typename X>
2290 inline const X& get_subtable (void) const
2291 {
Behdad Esfahbod095a1252015-02-19 10:29:41 +03002292 switch (u.format) {
2293 case 1: return u.format1.template get_subtable<typename T::LookupSubTable> ();
2294 default:return Null(typename T::LookupSubTable);
2295 }
Behdad Esfahbod7dddd4e2012-11-23 17:04:55 -05002296 }
2297
Behdad Esfahbod653eeb22012-11-23 16:57:36 -05002298 template <typename context_t>
Behdad Esfahbod9c5a9ee2013-03-09 01:55:04 -05002299 inline typename context_t::return_t dispatch (context_t *c) const
Behdad Esfahbod653eeb22012-11-23 16:57:36 -05002300 {
Behdad Esfahbod095a1252015-02-19 10:29:41 +03002301 TRACE_DISPATCH (this, u.format);
Behdad Esfahbodf396fbb2015-10-09 12:25:55 -04002302 if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002303 switch (u.format) {
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002304 case 1: return_trace (u.format1.dispatch (c));
2305 default:return_trace (c->default_return_value ());
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002306 }
2307 }
2308
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04002309 protected:
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002310 union {
Behdad Esfahbod6b191782018-01-10 03:07:30 +01002311 HBUINT16 format; /* Format identifier */
Behdad Esfahbod095a1252015-02-19 10:29:41 +03002312 ExtensionFormat1<T> format1;
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002313 } u;
2314};
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002315
2316
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04002317/*
2318 * GSUB/GPOS Common
2319 */
2320
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04002321struct GSUBGPOS
2322{
Behdad Esfahbodb912fbe2018-08-06 06:30:12 -07002323 inline bool has_data (void) const { return version.to_int () != 0; }
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04002324 inline unsigned int get_script_count (void) const
2325 { return (this+scriptList).len; }
2326 inline const Tag& get_script_tag (unsigned int i) const
2327 { return (this+scriptList).get_tag (i); }
Behdad Esfahbode21899b2009-11-04 16:36:14 -05002328 inline unsigned int get_script_tags (unsigned int start_offset,
2329 unsigned int *script_count /* IN/OUT */,
2330 hb_tag_t *script_tags /* OUT */) const
2331 { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04002332 inline const Script& get_script (unsigned int i) const
2333 { return (this+scriptList)[i]; }
2334 inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
2335 { return (this+scriptList).find_index (tag, index); }
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04002336
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04002337 inline unsigned int get_feature_count (void) const
2338 { return (this+featureList).len; }
Jonathan Kewda132932014-04-27 14:05:24 +01002339 inline hb_tag_t get_feature_tag (unsigned int i) const
2340 { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
Behdad Esfahbode21899b2009-11-04 16:36:14 -05002341 inline unsigned int get_feature_tags (unsigned int start_offset,
2342 unsigned int *feature_count /* IN/OUT */,
2343 hb_tag_t *feature_tags /* OUT */) const
2344 { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04002345 inline const Feature& get_feature (unsigned int i) const
2346 { return (this+featureList)[i]; }
2347 inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
2348 { return (this+featureList).find_index (tag, index); }
2349
2350 inline unsigned int get_lookup_count (void) const
2351 { return (this+lookupList).len; }
2352 inline const Lookup& get_lookup (unsigned int i) const
2353 { return (this+lookupList)[i]; }
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04002354
Behdad Esfahbod30c42b62016-09-10 03:32:39 -07002355 inline bool find_variations_index (const int *coords, unsigned int num_coords,
2356 unsigned int *index) const
Behdad Esfahbod59055b52016-09-10 01:24:28 -07002357 { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
Behdad Esfahbod30c42b62016-09-10 03:32:39 -07002358 .find_index (coords, num_coords, index); }
Behdad Esfahbodec87ba92016-09-10 03:53:11 -07002359 inline const Feature& get_feature_variation (unsigned int feature_index,
2360 unsigned int variations_index) const
2361 {
2362 if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
2363 version.to_int () >= 0x00010001u)
2364 {
Behdad Esfahbod4ebbeb72016-09-10 04:52:34 -07002365 const Feature *feature = (this+featureVars).find_substitute (variations_index,
2366 feature_index);
Behdad Esfahbodec87ba92016-09-10 03:53:11 -07002367 if (feature)
2368 return *feature;
2369 }
2370 return get_feature (feature_index);
2371 }
Behdad Esfahbod59055b52016-09-10 01:24:28 -07002372
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03002373 inline bool sanitize (hb_sanitize_context_t *c) const
2374 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002375 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002376 return_trace (version.sanitize (c) &&
2377 likely (version.major == 1) &&
2378 scriptList.sanitize (c, this) &&
2379 featureList.sanitize (c, this) &&
Behdad Esfahbod59055b52016-09-10 01:24:28 -07002380 lookupList.sanitize (c, this) &&
2381 (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -04002382 }
2383
Behdad Esfahbod212aba62009-05-24 00:50:27 -04002384 protected:
Behdad Esfahbod9a13ed42016-02-22 11:44:45 +09002385 FixedVersion<>version; /* Version of the GSUB/GPOS table--initially set
Behdad Esfahbod76271002014-07-11 14:54:42 -04002386 * to 0x00010000u */
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04002387 OffsetTo<ScriptList>
2388 scriptList; /* ScriptList table */
2389 OffsetTo<FeatureList>
2390 featureList; /* FeatureList table */
2391 OffsetTo<LookupList>
2392 lookupList; /* LookupList table */
Behdad Esfahbod5e156fa2017-01-22 20:28:56 -08002393 LOffsetTo<FeatureVariations>
Behdad Esfahbod59055b52016-09-10 01:24:28 -07002394 featureVars; /* Offset to Feature Variations
2395 table--from beginning of table
2396 * (may be NULL). Introduced
2397 * in version 0x00010001. */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04002398 public:
Behdad Esfahbod59055b52016-09-10 01:24:28 -07002399 DEFINE_SIZE_MIN (10);
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04002400};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04002401
Behdad Esfahbod6f20f722009-05-17 20:28:01 -04002402
Behdad Esfahbod7d52e662012-11-16 18:49:54 -08002403} /* namespace OT */
Behdad Esfahbod7c8e8442012-08-28 17:57:49 -04002404
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -04002405
Behdad Esfahbod5f5b24f2009-08-02 20:03:12 -04002406#endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */