blob: 7c31b28c80fd017e0b833d9eb6110fe57765fa21 [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 Esfahbodc77ae402018-08-25 22:36:36 -070029#ifndef HB_OT_LAYOUT_GSUBGPOS_HH
30#define HB_OT_LAYOUT_GSUBGPOS_HH
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -040031
Behdad Esfahbodc77ae402018-08-25 22:36:36 -070032#include "hb.hh"
33#include "hb-buffer.hh"
34#include "hb-map.hh"
Behdad Esfahbodc77ae402018-08-25 22:36:36 -070035#include "hb-set.hh"
Behdad Esfahbod71c9f842018-09-10 22:37:19 +020036#include "hb-ot-map.hh"
Behdad Esfahbodb9291002018-08-26 01:15:47 -070037#include "hb-ot-layout-common.hh"
38#include "hb-ot-layout-gdef-table.hh"
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040039
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -040040
Behdad Esfahbod7c8e8442012-08-28 17:57:49 -040041namespace OT {
42
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -040043
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -070044struct hb_intersects_context_t :
45 hb_dispatch_context_t<hb_intersects_context_t, bool, 0>
46{
Ebrahim Byagowie4120082018-12-17 21:31:01 +033047 const char *get_name () { return "INTERSECTS"; }
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -070048 template <typename T>
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +033049 return_t dispatch (const T &obj) { return obj.intersects (this->glyphs); }
Ebrahim Byagowie4120082018-12-17 21:31:01 +033050 static return_t default_return_value () { return false; }
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -070051 bool stop_sublookup_iteration (return_t r) const { return r; }
52
53 const hb_set_t *glyphs;
54 unsigned int debug_depth;
55
56 hb_intersects_context_t (const hb_set_t *glyphs_) :
57 glyphs (glyphs_),
58 debug_depth (0) {}
59};
60
Behdad Esfahbod77a1a2b2015-10-09 12:20:58 -040061struct hb_closure_context_t :
Behdad Esfahbod0772c062019-01-18 12:53:06 -050062 hb_dispatch_context_t<hb_closure_context_t, hb_void_t, 0>
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040063{
Ebrahim Byagowie4120082018-12-17 21:31:01 +033064 const char *get_name () { return "CLOSURE"; }
Behdad Esfahbod44fc2372012-11-21 23:33:13 -050065 typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
66 template <typename T>
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +033067 return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; }
Ebrahim Byagowie4120082018-12-17 21:31:01 +033068 static return_t default_return_value () { return HB_VOID; }
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -070069 void recurse (unsigned int lookup_index)
Behdad Esfahbod44fc2372012-11-21 23:33:13 -050070 {
Behdad Esfahbod9b346772012-11-23 17:55:40 -050071 if (unlikely (nesting_level_left == 0 || !recurse_func))
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -070072 return;
Behdad Esfahbod44fc2372012-11-21 23:33:13 -050073
74 nesting_level_left--;
75 recurse_func (this, lookup_index);
76 nesting_level_left++;
Behdad Esfahbod44fc2372012-11-21 23:33:13 -050077 }
78
Behdad Esfahbodba0ea562018-06-11 23:24:41 -040079 bool should_visit_lookup (unsigned int lookup_index)
Garret Rieger45186b92018-06-05 17:14:42 -070080 {
81 if (is_lookup_done (lookup_index))
82 return false;
83 done_lookups->set (lookup_index, glyphs->get_population ());
84 return true;
85 }
86
87 bool is_lookup_done (unsigned int lookup_index)
88 {
Behdad Esfahbodc38bd402018-07-24 09:43:27 -070089 /* Have we visited this lookup with the current set of glyphs? */
Garret Rieger45186b92018-06-05 17:14:42 -070090 return done_lookups->get (lookup_index) == glyphs->get_population ();
91 }
92
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040093 hb_face_t *face;
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -040094 hb_set_t *glyphs;
Behdad Esfahbod3a4e5dd2018-10-29 18:05:25 -070095 hb_set_t out[1];
Behdad Esfahbod44fc2372012-11-21 23:33:13 -050096 recurse_func_t recurse_func;
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -040097 unsigned int nesting_level_left;
98 unsigned int debug_depth;
99
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400100 hb_closure_context_t (hb_face_t *face_,
Behdad Esfahbod6a9be5b2012-04-23 22:23:17 -0400101 hb_set_t *glyphs_,
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330102 hb_map_t *done_lookups_,
103 unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400104 face (face_),
105 glyphs (glyphs_),
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200106 recurse_func (nullptr),
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400107 nesting_level_left (nesting_level_left_),
Behdad Esfahboda7e1b4a2018-06-11 22:05:08 -0400108 debug_depth (0),
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330109 done_lookups (done_lookups_) {}
Behdad Esfahbod9b346772012-11-23 17:55:40 -0500110
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330111 ~hb_closure_context_t () { flush (); }
Behdad Esfahbodc38bd402018-07-24 09:43:27 -0700112
Behdad Esfahbod9b346772012-11-23 17:55:40 -0500113 void set_recurse_func (recurse_func_t func) { recurse_func = func; }
Garret Rieger45186b92018-06-05 17:14:42 -0700114
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330115 void flush ()
Behdad Esfahbodc38bd402018-07-24 09:43:27 -0700116 {
117 hb_set_union (glyphs, out);
118 hb_set_clear (out);
119 }
120
Garret Rieger45186b92018-06-05 17:14:42 -0700121 private:
122 hb_map_t *done_lookups;
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400123};
124
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -0400125
Behdad Esfahbod77a1a2b2015-10-09 12:20:58 -0400126struct hb_would_apply_context_t :
127 hb_dispatch_context_t<hb_would_apply_context_t, bool, HB_DEBUG_WOULD_APPLY>
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400128{
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330129 const char *get_name () { return "WOULD_APPLY"; }
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500130 template <typename T>
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330131 return_t dispatch (const T &obj) { return obj.would_apply (this); }
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330132 static return_t default_return_value () { return false; }
Behdad Esfahbod7b912c12013-01-04 01:25:27 -0600133 bool stop_sublookup_iteration (return_t r) const { return r; }
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500134
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400135 hb_face_t *face;
Behdad Esfahbod472f2292012-08-07 22:25:24 -0400136 const hb_codepoint_t *glyphs;
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400137 unsigned int len;
Behdad Esfahbodd9b204d2012-08-23 16:22:28 -0400138 bool zero_context;
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400139 unsigned int debug_depth;
140
141 hb_would_apply_context_t (hb_face_t *face_,
Behdad Esfahbod472f2292012-08-07 22:25:24 -0400142 const hb_codepoint_t *glyphs_,
143 unsigned int len_,
Behdad Esfahbod2bd9fe32012-09-04 15:15:19 -0400144 bool zero_context_) :
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400145 face (face_),
Behdad Esfahbod472f2292012-08-07 22:25:24 -0400146 glyphs (glyphs_),
147 len (len_),
Behdad Esfahbodd9b204d2012-08-23 16:22:28 -0400148 zero_context (zero_context_),
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500149 debug_depth (0) {}
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400150};
151
152
Behdad Esfahbod77a1a2b2015-10-09 12:20:58 -0400153struct hb_collect_glyphs_context_t :
154 hb_dispatch_context_t<hb_collect_glyphs_context_t, hb_void_t, HB_DEBUG_COLLECT_GLYPHS>
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800155{
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330156 const char *get_name () { return "COLLECT_GLYPHS"; }
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500157 typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500158 template <typename T>
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330159 return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330160 static return_t default_return_value () { return HB_VOID; }
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -0700161 void recurse (unsigned int lookup_index)
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500162 {
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500163 if (unlikely (nesting_level_left == 0 || !recurse_func))
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -0700164 return;
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500165
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200166 /* Note that GPOS sets recurse_func to nullptr already, so it doesn't get
Behdad Esfahbod1bcfa062012-12-04 16:58:09 -0500167 * past the previous check. For GSUB, we only want to collect the output
Behdad Esfahbod76ea5632013-05-04 16:01:20 -0400168 * glyphs in the recursion. If output is not requested, we can go home now.
169 *
170 * Note further, that the above is not exactly correct. A recursed lookup
171 * is allowed to match input that is not matched in the context, but that's
172 * not how most fonts are built. It's possible to relax that and recurse
173 * with all sets here if it proves to be an issue.
174 */
Behdad Esfahbod4a350d02012-12-04 17:13:09 -0500175
176 if (output == hb_set_get_empty ())
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -0700177 return;
Behdad Esfahbod4a350d02012-12-04 17:13:09 -0500178
Behdad Esfahbodfde3e4a2014-10-29 11:23:08 -0700179 /* Return if new lookup was recursed to before. */
Behdad Esfahbod8b9d9b72017-10-22 17:48:06 -0400180 if (recursed_lookups->has (lookup_index))
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -0700181 return;
Behdad Esfahbodfde3e4a2014-10-29 11:23:08 -0700182
Behdad Esfahbod4a350d02012-12-04 17:13:09 -0500183 hb_set_t *old_before = before;
184 hb_set_t *old_input = input;
185 hb_set_t *old_after = after;
186 before = input = after = hb_set_get_empty ();
Behdad Esfahbod1bcfa062012-12-04 16:58:09 -0500187
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500188 nesting_level_left--;
Behdad Esfahbod4a350d02012-12-04 17:13:09 -0500189 recurse_func (this, lookup_index);
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500190 nesting_level_left++;
Behdad Esfahbod4a350d02012-12-04 17:13:09 -0500191
192 before = old_before;
193 input = old_input;
194 after = old_after;
195
Behdad Esfahbod8b9d9b72017-10-22 17:48:06 -0400196 recursed_lookups->add (lookup_index);
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500197 }
198
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800199 hb_face_t *face;
Behdad Esfahbod83035932012-12-04 17:08:41 -0500200 hb_set_t *before;
201 hb_set_t *input;
202 hb_set_t *after;
203 hb_set_t *output;
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500204 recurse_func_t recurse_func;
Behdad Esfahbod8b9d9b72017-10-22 17:48:06 -0400205 hb_set_t *recursed_lookups;
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500206 unsigned int nesting_level_left;
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800207 unsigned int debug_depth;
208
209 hb_collect_glyphs_context_t (hb_face_t *face_,
Ebrahim Byagowi63109432018-10-13 14:00:05 +0330210 hb_set_t *glyphs_before, /* OUT. May be NULL */
211 hb_set_t *glyphs_input, /* OUT. May be NULL */
212 hb_set_t *glyphs_after, /* OUT. May be NULL */
213 hb_set_t *glyphs_output, /* OUT. May be NULL */
Behdad Esfahbod5ba45042015-11-02 15:43:08 -0800214 unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800215 face (face_),
Behdad Esfahbod83035932012-12-04 17:08:41 -0500216 before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
217 input (glyphs_input ? glyphs_input : hb_set_get_empty ()),
218 after (glyphs_after ? glyphs_after : hb_set_get_empty ()),
219 output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200220 recurse_func (nullptr),
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -0700221 recursed_lookups (hb_set_create ()),
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500222 nesting_level_left (nesting_level_left_),
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -0700223 debug_depth (0) {}
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330224 ~hb_collect_glyphs_context_t () { hb_set_destroy (recursed_lookups); }
Behdad Esfahbod26514d52012-11-23 18:13:48 -0500225
226 void set_recurse_func (recurse_func_t func) { recurse_func = func; }
Behdad Esfahbode8cfdd72012-11-16 19:07:06 -0800227};
228
229
230
Behdad Esfahbod8e36ccf2015-02-17 19:15:34 +0300231template <typename set_t>
Behdad Esfahbod77a1a2b2015-10-09 12:20:58 -0400232struct hb_add_coverage_context_t :
233 hb_dispatch_context_t<hb_add_coverage_context_t<set_t>, const Coverage &, HB_DEBUG_GET_COVERAGE>
Behdad Esfahbod2005fa52012-11-22 14:38:10 -0500234{
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330235 const char *get_name () { return "GET_COVERAGE"; }
Behdad Esfahbod2005fa52012-11-22 14:38:10 -0500236 typedef const Coverage &return_t;
237 template <typename T>
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330238 return_t dispatch (const T &obj) { return obj.get_coverage (); }
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330239 static return_t default_return_value () { return Null(Coverage); }
Behdad Esfahbod8e36ccf2015-02-17 19:15:34 +0300240 bool stop_sublookup_iteration (return_t r) const
241 {
242 r.add_coverage (set);
243 return false;
244 }
Behdad Esfahbod1d67ef92012-11-22 16:47:53 -0500245
Behdad Esfahbod8e36ccf2015-02-17 19:15:34 +0300246 hb_add_coverage_context_t (set_t *set_) :
247 set (set_),
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500248 debug_depth (0) {}
249
Behdad Esfahbod8e36ccf2015-02-17 19:15:34 +0300250 set_t *set;
Behdad Esfahboda1733db2012-11-23 16:40:04 -0500251 unsigned int debug_depth;
Behdad Esfahbod2005fa52012-11-22 14:38:10 -0500252};
253
254
Behdad Esfahbodfd034492018-01-17 16:46:51 -0800255struct hb_ot_apply_context_t :
256 hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400257{
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500258 struct matcher_t
259 {
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330260 matcher_t () :
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500261 lookup_props (0),
Behdad Esfahbodcfc507c2013-02-14 10:40:12 -0500262 ignore_zwnj (false),
263 ignore_zwj (false),
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500264 mask (-1),
265#define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
266 syllable arg1(0),
267#undef arg1
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200268 match_func (nullptr),
Ebrahim Byagowif7a08cd2018-10-30 11:29:09 +0330269 match_data (nullptr) {}
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500270
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100271 typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500272
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330273 void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
274 void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
275 void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
276 void set_mask (hb_mask_t mask_) { mask = mask_; }
277 void set_syllable (uint8_t syllable_) { syllable = syllable_; }
278 void set_match_func (match_func_t match_func_,
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500279 const void *match_data_)
280 { match_func = match_func_; match_data = match_data_; }
281
Behdad Esfahbod2b2a6e82013-02-21 15:07:03 -0500282 enum may_match_t {
283 MATCH_NO,
284 MATCH_YES,
285 MATCH_MAYBE
286 };
287
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330288 may_match_t may_match (const hb_glyph_info_t &info,
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330289 const HBUINT16 *glyph_data) const
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500290 {
Behdad Esfahbod2b2a6e82013-02-21 15:07:03 -0500291 if (!(info.mask & mask) ||
292 (syllable && syllable != info.syllable ()))
293 return MATCH_NO;
294
295 if (match_func)
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330296 return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
Behdad Esfahbod2b2a6e82013-02-21 15:07:03 -0500297
298 return MATCH_MAYBE;
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500299 }
300
301 enum may_skip_t {
302 SKIP_NO,
303 SKIP_YES,
304 SKIP_MAYBE
305 };
306
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330307 may_skip_t may_skip (const hb_ot_apply_context_t *c,
308 const hb_glyph_info_t &info) const
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500309 {
Behdad Esfahbodb98c5db2014-07-16 13:44:01 -0400310 if (!c->check_glyph_property (&info, lookup_props))
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500311 return SKIP_YES;
312
Khaled Hosny06cfe3f2017-05-17 21:32:47 +0300313 if (unlikely (_hb_glyph_info_is_default_ignorable_and_not_hidden (&info) &&
Behdad Esfahbod0b454792013-02-14 10:46:52 -0500314 (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
Behdad Esfahbod4ba796b2015-07-22 17:41:31 +0100315 (ignore_zwj || !_hb_glyph_info_is_zwj (&info))))
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500316 return SKIP_MAYBE;
317
318 return SKIP_NO;
319 }
320
321 protected:
322 unsigned int lookup_props;
323 bool ignore_zwnj;
Behdad Esfahbod0b454792013-02-14 10:46:52 -0500324 bool ignore_zwj;
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500325 hb_mask_t mask;
326 uint8_t syllable;
327 match_func_t match_func;
328 const void *match_data;
329 };
330
Behdad Esfahbod69626692015-01-29 13:08:41 +0100331 struct skipping_iterator_t
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500332 {
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330333 void init (hb_ot_apply_context_t *c_, bool context_match = false)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500334 {
Behdad Esfahbod514564f2015-01-29 13:48:48 +0100335 c = c_;
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200336 match_glyph_data = nullptr;
337 matcher.set_match_func (nullptr, nullptr);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500338 matcher.set_lookup_props (c->lookup_props);
Behdad Esfahbod3583fb02018-09-23 22:33:38 -0400339 /* Ignore ZWNJ if we are matching GPOS, or matching GSUB context and asked to. */
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100340 matcher.set_ignore_zwnj (c->table_index == 1 || (context_match && c->auto_zwnj));
Behdad Esfahbod3583fb02018-09-23 22:33:38 -0400341 /* Ignore ZWJ if we are matching context, or asked to. */
342 matcher.set_ignore_zwj (context_match || c->auto_zwj);
Behdad Esfahbod514564f2015-01-29 13:48:48 +0100343 matcher.set_mask (context_match ? -1 : c->lookup_mask);
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500344 }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330345 void set_lookup_props (unsigned int lookup_props)
Behdad Esfahbod514564f2015-01-29 13:48:48 +0100346 {
347 matcher.set_lookup_props (lookup_props);
348 }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330349 void set_match_func (matcher_t::match_func_t match_func_,
350 const void *match_data_,
351 const HBUINT16 glyph_data[])
Behdad Esfahbodc074ebc2013-02-13 11:22:42 -0500352 {
Behdad Esfahbod4a6b1ee2015-10-21 11:20:55 -0200353 matcher.set_match_func (match_func_, match_data_);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500354 match_glyph_data = glyph_data;
Behdad Esfahbodc074ebc2013-02-13 11:22:42 -0500355 }
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500356
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330357 void reset (unsigned int start_index_,
Behdad Esfahbodb051be52015-01-29 13:40:39 +0100358 unsigned int num_items_)
359 {
360 idx = start_index_;
361 num_items = num_items_;
362 end = c->buffer->len;
363 matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
364 }
365
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330366 void reject () { num_items++; match_glyph_data--; }
Behdad Esfahbod69626692015-01-29 13:08:41 +0100367
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330368 matcher_t::may_skip_t
369 may_skip (const hb_glyph_info_t &info) const
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330370 { return matcher.may_skip (c, info); }
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200371
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330372 bool next ()
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 }
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330399 bool prev ()
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
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330438 const char *get_name () { 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>
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330441 return_t dispatch (const T &obj) { return obj.apply (this); }
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330442 static return_t default_return_value () { return false; }
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100443 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 Esfahbod80de4bc2018-09-10 16:24:52 +0200472 bool has_glyph_classes;
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100473 bool auto_zwnj;
474 bool auto_zwj;
David Corbettc2a75e02018-01-25 14:22:03 -0500475 bool random;
Behdad Esfahbod80de4bc2018-09-10 16:24:52 +0200476
Behdad Esfahbodcfdea882018-09-11 10:57:48 +0200477 uint32_t random_state;
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100478
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100479
Behdad Esfahbodfd034492018-01-17 16:46:51 -0800480 hb_ot_apply_context_t (unsigned int table_index_,
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100481 hb_font_t *font_,
482 hb_buffer_t *buffer_) :
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100483 iter_input (), iter_context (),
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100484 font (font_), face (font->face), buffer (buffer_),
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200485 recurse_func (nullptr),
Behdad Esfahbod33b006c2018-11-05 23:19:04 -0500486 gdef (*face->table.GDEF->table),
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100487 var_store (gdef.get_var_store ()),
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100488 direction (buffer_->props.direction),
489 lookup_mask (1),
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100490 table_index (table_index_),
Behdad Esfahbod2c8b3b22015-08-18 14:36:43 +0100491 lookup_index ((unsigned int) -1),
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100492 lookup_props (0),
493 nesting_level_left (HB_MAX_NESTING_LEVEL),
494 debug_depth (0),
Behdad Esfahbod80de4bc2018-09-10 16:24:52 +0200495 has_glyph_classes (gdef.has_glyph_classes ()),
Behdad Esfahbodcdf1fd02017-07-14 12:43:34 +0100496 auto_zwnj (true),
497 auto_zwj (true),
David Corbettc2a75e02018-01-25 14:22:03 -0500498 random (false),
Behdad Esfahbodd748dc72018-09-24 18:30:50 -0400499 random_state (1) { init_iters (); }
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100500
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330501 void init_iters ()
Behdad Esfahbod365576d2015-01-29 13:59:42 +0100502 {
Behdad Esfahbod365576d2015-01-29 13:59:42 +0100503 iter_input.init (this, false);
504 iter_context.init (this, true);
505 }
Behdad Esfahbod2cecc382015-01-29 13:32:05 +0100506
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330507 void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; init_iters (); }
508 void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; init_iters (); }
509 void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; init_iters (); }
510 void set_random (bool random_) { random = random_; }
511 void set_recurse_func (recurse_func_t func) { recurse_func = func; }
512 void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
513 void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; init_iters (); }
Behdad Esfahbod9516cbd2018-09-23 22:00:34 -0400514
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330515 uint32_t random_number ()
Behdad Esfahbod08260c72018-09-11 10:51:19 +0200516 {
Behdad Esfahbodcfdea882018-09-11 10:57:48 +0200517 /* http://www.cplusplus.com/reference/random/minstd_rand/ */
518 random_state = random_state * 48271 % 2147483647;
519 return random_state;
Behdad Esfahbod08260c72018-09-11 10:51:19 +0200520 }
521
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330522 bool match_properties_mark (hb_codepoint_t glyph,
523 unsigned int glyph_props,
524 unsigned int match_props) const
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400525 {
526 /* If using mark filtering sets, the high short of
Behdad Esfahbodb931e0b2015-04-08 14:39:00 -0700527 * match_props has the set index.
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400528 */
Behdad Esfahbodb931e0b2015-04-08 14:39:00 -0700529 if (match_props & LookupFlag::UseMarkFilteringSet)
530 return gdef.mark_set_covers (match_props >> 16, glyph);
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400531
Behdad Esfahbodb931e0b2015-04-08 14:39:00 -0700532 /* The second byte of match_props has the meaning
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400533 * "ignore marks of attachment type different than
534 * the attachment type specified."
535 */
Behdad Esfahbodb931e0b2015-04-08 14:39:00 -0700536 if (match_props & LookupFlag::MarkAttachmentType)
537 return (match_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400538
539 return true;
540 }
541
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330542 bool check_glyph_property (const hb_glyph_info_t *info,
543 unsigned int match_props) const
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400544 {
Behdad Esfahbodb98c5db2014-07-16 13:44:01 -0400545 hb_codepoint_t glyph = info->codepoint;
546 unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info);
547
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400548 /* Not covered, if, for example, glyph class is ligature and
Behdad Esfahbodb931e0b2015-04-08 14:39:00 -0700549 * match_props includes LookupFlags::IgnoreLigatures
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400550 */
Behdad Esfahbodb931e0b2015-04-08 14:39:00 -0700551 if (glyph_props & match_props & LookupFlag::IgnoreFlags)
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400552 return false;
553
Behdad Esfahbod5a08ecf2012-11-16 13:34:29 -0800554 if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
Behdad Esfahbodb931e0b2015-04-08 14:39:00 -0700555 return match_properties_mark (glyph, glyph_props, match_props);
Behdad Esfahbod03f67bc2012-07-30 19:47:53 -0400556
557 return true;
558 }
559
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330560 void _set_glyph_props (hb_codepoint_t glyph_index,
Behdad Esfahbod71b4c992013-10-28 00:20:59 +0100561 unsigned int class_guess = 0,
Behdad Esfahbod832a6f92014-06-04 16:57:42 -0400562 bool ligature = false,
563 bool component = false) const
Behdad Esfahbod60da7632012-07-16 16:13:32 -0400564 {
Behdad Esfahbod09675a82013-10-18 01:05:58 +0200565 unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
566 HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
567 add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
568 if (ligature)
Behdad Esfahbod832a6f92014-06-04 16:57:42 -0400569 {
Behdad Esfahbod09675a82013-10-18 01:05:58 +0200570 add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
Behdad Esfahbod832a6f92014-06-04 16:57:42 -0400571 /* In the only place that the MULTIPLIED bit is used, Uniscribe
572 * seems to only care about the "last" transformation between
Bruce Mitchener257d0e52018-10-19 22:49:21 +0700573 * Ligature and Multiple substitutions. Ie. if you ligate, expand,
Behdad Esfahbod832a6f92014-06-04 16:57:42 -0400574 * and ligate again, it forgives the multiplication and acts as
575 * if only ligation happened. As such, clear MULTIPLIED bit.
576 */
577 add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
578 }
579 if (component)
580 add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
Behdad Esfahbod2fca1422012-07-30 18:46:41 -0400581 if (likely (has_glyph_classes))
Behdad Esfahbod05ad6b52013-10-18 00:45:59 +0200582 _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
Behdad Esfahbod05bd1b62012-07-30 19:30:01 -0400583 else if (class_guess)
Behdad Esfahbod09675a82013-10-18 01:05:58 +0200584 _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess);
Behdad Esfahbod60da7632012-07-16 16:13:32 -0400585 }
Behdad Esfahbod4ab97312012-01-16 22:05:08 -0500586
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330587 void replace_glyph (hb_codepoint_t glyph_index) const
Behdad Esfahbod3ec77d62012-06-08 21:44:06 -0400588 {
Behdad Esfahboda0161742013-10-18 00:06:30 +0200589 _set_glyph_props (glyph_index);
Behdad Esfahbod98370e82010-10-27 17:39:01 -0400590 buffer->replace_glyph (glyph_index);
591 }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330592 void replace_glyph_inplace (hb_codepoint_t glyph_index) const
Behdad Esfahbod7fbbf862012-07-30 18:36:42 -0400593 {
Behdad Esfahboda0161742013-10-18 00:06:30 +0200594 _set_glyph_props (glyph_index);
Behdad Esfahbod7fbbf862012-07-30 18:36:42 -0400595 buffer->cur().codepoint = glyph_index;
596 }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330597 void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
Behdad Esfahboda0161742013-10-18 00:06:30 +0200598 unsigned int class_guess) const
599 {
Behdad Esfahbod09675a82013-10-18 01:05:58 +0200600 _set_glyph_props (glyph_index, class_guess, true);
Behdad Esfahboda0161742013-10-18 00:06:30 +0200601 buffer->replace_glyph (glyph_index);
602 }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330603 void output_glyph_for_component (hb_codepoint_t glyph_index,
Behdad Esfahbod832a6f92014-06-04 16:57:42 -0400604 unsigned int class_guess) const
Behdad Esfahboda0161742013-10-18 00:06:30 +0200605 {
Behdad Esfahbod832a6f92014-06-04 16:57:42 -0400606 _set_glyph_props (glyph_index, class_guess, false, true);
Behdad Esfahboda0161742013-10-18 00:06:30 +0200607 buffer->output_glyph (glyph_index);
608 }
Behdad Esfahbod1376fb72010-04-29 02:19:21 -0400609};
610
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400611
Behdad Esfahbodb3390992018-10-10 12:07:49 -0400612struct hb_get_subtables_context_t :
613 hb_dispatch_context_t<hb_get_subtables_context_t, hb_void_t, HB_DEBUG_APPLY>
614{
615 template <typename Type>
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330616 static bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
Behdad Esfahbodb3390992018-10-10 12:07:49 -0400617 {
618 const Type *typed_obj = (const Type *) obj;
619 return typed_obj->apply (c);
620 }
621
622 typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_ot_apply_context_t *c);
623
624 struct hb_applicable_t
625 {
626 template <typename T>
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330627 void init (const T &obj_, hb_apply_func_t apply_func_)
Behdad Esfahbodb3390992018-10-10 12:07:49 -0400628 {
629 obj = &obj_;
630 apply_func = apply_func_;
631 digest.init ();
632 obj_.get_coverage ().add_coverage (&digest);
633 }
634
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330635 bool apply (OT::hb_ot_apply_context_t *c) const
Behdad Esfahbodb3390992018-10-10 12:07:49 -0400636 {
637 return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c);
638 }
639
640 private:
641 const void *obj;
642 hb_apply_func_t apply_func;
643 hb_set_digest_t digest;
644 };
645
Behdad Esfahbodfa333e32018-12-27 17:56:22 -0500646 typedef hb_vector_t<hb_applicable_t> array_t;
Behdad Esfahbodb3390992018-10-10 12:07:49 -0400647
648 /* Dispatch interface. */
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330649 const char *get_name () { return "GET_SUBTABLES"; }
Behdad Esfahbodb3390992018-10-10 12:07:49 -0400650 template <typename T>
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330651 return_t dispatch (const T &obj)
Behdad Esfahbodb3390992018-10-10 12:07:49 -0400652 {
653 hb_applicable_t *entry = array.push();
654 entry->init (obj, apply_to<T>);
655 return HB_VOID;
656 }
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330657 static return_t default_return_value () { return HB_VOID; }
Behdad Esfahbodb3390992018-10-10 12:07:49 -0400658
659 hb_get_subtables_context_t (array_t &array_) :
660 array (array_),
661 debug_depth (0) {}
662
663 array_t &array;
664 unsigned int debug_depth;
665};
666
667
668
Behdad Esfahbod94a23aa2010-05-05 01:13:09 -0400669
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -0700670typedef bool (*intersects_func_t) (const hb_set_t *glyphs, const HBUINT16 &value, const void *data);
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100671typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
672typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400673
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400674struct ContextClosureFuncs
675{
676 intersects_func_t intersects;
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400677};
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500678struct ContextCollectGlyphsFuncs
679{
680 collect_glyphs_func_t collect;
681};
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400682struct ContextApplyFuncs
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400683{
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400684 match_func_t match;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400685};
686
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500687
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -0700688static inline bool intersects_glyph (const hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400689{
690 return glyphs->has (value);
691}
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -0700692static inline bool intersects_class (const hb_set_t *glyphs, const HBUINT16 &value, const void *data)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400693{
694 const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
695 return class_def.intersects_class (glyphs, value);
696}
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -0700697static inline bool intersects_coverage (const hb_set_t *glyphs, const HBUINT16 &value, const void *data)
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400698{
699 const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
700 return (data+coverage).intersects (glyphs);
701}
702
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -0700703static inline bool intersects_array (const hb_set_t *glyphs,
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400704 unsigned int count,
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100705 const HBUINT16 values[],
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400706 intersects_func_t intersects_func,
707 const void *intersects_data)
708{
709 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -0700710 if (likely (!intersects_func (glyphs, values[i], intersects_data)))
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400711 return false;
712 return true;
713}
714
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400715
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100716static inline void collect_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500717{
718 glyphs->add (value);
719}
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100720static inline void collect_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500721{
722 const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
Behdad Esfahbod71e6adf2017-12-16 11:07:37 -0500723 class_def.add_class (glyphs, value);
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500724}
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100725static inline void collect_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500726{
727 const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
728 (data+coverage).add_coverage (glyphs);
729}
Behdad Esfahbod0beb66e2012-12-05 18:46:04 -0500730static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
Behdad Esfahbodf1b12782012-11-24 01:55:34 -0500731 hb_set_t *glyphs,
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500732 unsigned int count,
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100733 const HBUINT16 values[],
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500734 collect_glyphs_func_t collect_func,
735 const void *collect_data)
736{
737 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbodf1b12782012-11-24 01:55:34 -0500738 collect_func (glyphs, values[i], collect_data);
Behdad Esfahbodd0a52332012-11-23 18:54:59 -0500739}
740
741
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100742static inline bool match_glyph (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data HB_UNUSED)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400743{
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400744 return glyph_id == value;
745}
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100746static inline bool match_class (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400747{
Behdad Esfahbod2b5a59c2009-08-04 11:38:50 -0400748 const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400749 return class_def.get_class (glyph_id) == value;
750}
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100751static inline bool match_coverage (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400752{
Behdad Esfahbod6b54c5d2009-05-18 18:30:25 -0400753 const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
Behdad Esfahbod31081f72012-04-23 16:54:58 -0400754 return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -0400755}
756
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400757static inline bool would_match_input (hb_would_apply_context_t *c,
758 unsigned int count, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100759 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400760 match_func_t match_func,
761 const void *match_data)
762{
763 if (count != c->len)
764 return false;
765
766 for (unsigned int i = 1; i < count; i++)
Behdad Esfahbod472f2292012-08-07 22:25:24 -0400767 if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
Behdad Esfahbode72b3602012-07-19 14:35:23 -0400768 return false;
769
770 return true;
771}
Behdad Esfahbodfd034492018-01-17 16:46:51 -0800772static inline bool match_input (hb_ot_apply_context_t *c,
Behdad Esfahbode072c242009-05-18 03:47:31 -0400773 unsigned int count, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +0100774 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400775 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -0400776 const void *match_data,
Behdad Esfahbod6cc136f2013-10-17 13:55:48 +0200777 unsigned int *end_offset,
Behdad Esfahbod5ba45042015-11-02 15:43:08 -0800778 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH],
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200779 unsigned int *p_total_component_count = nullptr)
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -0400780{
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200781 TRACE_APPLY (nullptr);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400782
Behdad Esfahbod5ba45042015-11-02 15:43:08 -0800783 if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
Behdad Esfahbod6b65a762013-10-14 18:51:39 +0200784
Behdad Esfahbod3c3df9c2013-10-17 13:58:31 +0200785 hb_buffer_t *buffer = c->buffer;
786
Behdad Esfahbodfd034492018-01-17 16:46:51 -0800787 hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
Behdad Esfahbodb051be52015-01-29 13:40:39 +0100788 skippy_iter.reset (buffer->idx, count - 1);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500789 skippy_iter.set_match_func (match_func, match_data, input);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400790
Behdad Esfahbod191fa882012-08-28 22:58:55 -0400791 /*
792 * This is perhaps the trickiest part of OpenType... Remarks:
793 *
794 * - If all components of the ligature were marks, we call this a mark ligature.
795 *
796 * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
797 * it as a ligature glyph.
798 *
799 * - Ligatures cannot be formed across glyphs attached to different components
800 * of previous ligatures. Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
801 * LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200802 * However, it would be wrong to ligate that SHADDA,FATHA sequence.
803 * There are a couple of exceptions to this:
804 *
805 * o If a ligature tries ligating with marks that belong to it itself, go ahead,
806 * assuming that the font designer knows what they are doing (otherwise it can
807 * break Indic stuff when a matra wants to ligate with a conjunct,
808 *
809 * o If two marks want to ligate and they belong to different components of the
810 * same ligature glyph, and said ligature glyph is to be ignored according to
811 * mark-filtering rules, then allow.
ebraminio7c6937e2017-11-20 14:49:22 -0500812 * https://github.com/harfbuzz/harfbuzz/issues/545
Behdad Esfahbod191fa882012-08-28 22:58:55 -0400813 */
814
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400815 unsigned int total_component_count = 0;
Behdad Esfahbod3ddf8922013-10-18 00:02:43 +0200816 total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400817
Behdad Esfahbod3ddf8922013-10-18 00:02:43 +0200818 unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
819 unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400820
Behdad Esfahbod621c49c2017-10-04 15:06:48 +0200821 enum {
822 LIGBASE_NOT_CHECKED,
823 LIGBASE_MAY_NOT_SKIP,
824 LIGBASE_MAY_SKIP
825 } ligbase = LIGBASE_NOT_CHECKED;
826
Behdad Esfahbod3c3df9c2013-10-17 13:58:31 +0200827 match_positions[0] = buffer->idx;
Behdad Esfahbod370f03e2012-01-16 17:03:55 -0500828 for (unsigned int i = 1; i < count; i++)
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -0400829 {
Behdad Esfahbodb4715902015-09-29 14:57:02 +0100830 if (!skippy_iter.next ()) return_trace (false);
Behdad Esfahbod6cc136f2013-10-17 13:55:48 +0200831
832 match_positions[i] = skippy_iter.idx;
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400833
Behdad Esfahbod3ddf8922013-10-18 00:02:43 +0200834 unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]);
835 unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400836
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200837 if (first_lig_id && first_lig_comp)
838 {
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400839 /* If first component was attached to a previous ligature component,
840 * all subsequent components should be attached to the same ligature
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200841 * component, otherwise we shouldn't ligate them... */
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400842 if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200843 {
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330844 /* ...unless, we are attached to a base ligature and that base
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200845 * ligature is ignorable. */
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330846 if (ligbase == LIGBASE_NOT_CHECKED)
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200847 {
Behdad Esfahbod621c49c2017-10-04 15:06:48 +0200848 bool found = false;
849 const hb_glyph_info_t *out = buffer->out_info;
850 unsigned int j = buffer->out_len;
851 while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id)
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200852 {
Behdad Esfahbod621c49c2017-10-04 15:06:48 +0200853 if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0)
854 {
855 j--;
856 found = true;
857 break;
858 }
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200859 j--;
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200860 }
Behdad Esfahbod621c49c2017-10-04 15:06:48 +0200861
Behdad Esfahbod12757b62018-01-26 18:14:05 -0800862 if (found && skippy_iter.may_skip (out[j]) == hb_ot_apply_context_t::matcher_t::SKIP_YES)
Behdad Esfahbod621c49c2017-10-04 15:06:48 +0200863 ligbase = LIGBASE_MAY_SKIP;
864 else
865 ligbase = LIGBASE_MAY_NOT_SKIP;
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200866 }
867
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330868 if (ligbase == LIGBASE_MAY_NOT_SKIP)
Behdad Esfahbod8b2c94c2017-10-02 20:02:45 +0200869 return_trace (false);
870 }
871 }
872 else
Behdad Esfahbod621c49c2017-10-04 15:06:48 +0200873 {
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400874 /* If first component was NOT attached to a previous ligature component,
875 * all subsequent components should also NOT be attached to any ligature
876 * component, unless they are attached to the first component itself! */
877 if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
Behdad Esfahbodb4715902015-09-29 14:57:02 +0100878 return_trace (false);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -0400879 }
880
Behdad Esfahbod3ddf8922013-10-18 00:02:43 +0200881 total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[skippy_iter.idx]);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -0400882 }
883
Behdad Esfahbod3c3df9c2013-10-17 13:58:31 +0200884 *end_offset = skippy_iter.idx - buffer->idx + 1;
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400885
Behdad Esfahbod191fa882012-08-28 22:58:55 -0400886 if (p_total_component_count)
887 *p_total_component_count = total_component_count;
888
Behdad Esfahbodb4715902015-09-29 14:57:02 +0100889 return_trace (true);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -0400890}
Behdad Esfahbodfd034492018-01-17 16:46:51 -0800891static inline bool ligate_input (hb_ot_apply_context_t *c,
Behdad Esfahbode714fe62013-10-17 13:49:51 +0200892 unsigned int count, /* Including the first glyph */
Bruce Mitchener5a24ea12018-10-20 08:09:52 +0700893 const unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
Behdad Esfahbode714fe62013-10-17 13:49:51 +0200894 unsigned int match_length,
Behdad Esfahboda177d022012-08-28 23:18:22 -0400895 hb_codepoint_t lig_glyph,
Behdad Esfahboda177d022012-08-28 23:18:22 -0400896 unsigned int total_component_count)
897{
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +0200898 TRACE_APPLY (nullptr);
Behdad Esfahbode714fe62013-10-17 13:49:51 +0200899
Behdad Esfahbod3c3df9c2013-10-17 13:58:31 +0200900 hb_buffer_t *buffer = c->buffer;
901
902 buffer->merge_clusters (buffer->idx, buffer->idx + match_length);
Behdad Esfahbod607feb72013-02-14 07:43:13 -0500903
Behdad Esfahbod9efddb92018-10-02 16:05:26 +0200904 /* - If a base and one or more marks ligate, consider that as a base, NOT
905 * ligature, such that all following marks can still attach to it.
906 * https://github.com/harfbuzz/harfbuzz/issues/1109
907 *
908 * - If all components of the ligature were marks, we call this a mark ligature.
Behdad Esfahbod3cca9782018-10-02 15:02:16 +0200909 * If it *is* a mark ligature, we don't allocate a new ligature id, and leave
Behdad Esfahboda177d022012-08-28 23:18:22 -0400910 * the ligature to keep its old ligature id. This will allow it to attach to
911 * a base ligature in GPOS. Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
Behdad Esfahbod3cca9782018-10-02 15:02:16 +0200912 * and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA with a
Behdad Esfahboda177d022012-08-28 23:18:22 -0400913 * ligature id and component value of 2. Then if SHADDA,FATHA form a ligature
914 * later, we don't want them to lose their ligature id/component, otherwise
915 * GPOS will fail to correctly position the mark ligature on top of the
916 * LAM,LAM,HEH ligature. See:
917 * https://bugzilla.gnome.org/show_bug.cgi?id=676343
918 *
919 * - If a ligature is formed of components that some of which are also ligatures
920 * themselves, and those ligature components had marks attached to *their*
921 * components, we have to attach the marks to the new ligature component
922 * positions! Now *that*'s tricky! And these marks may be following the
923 * last component of the whole sequence, so we should loop forward looking
924 * for them and update them.
925 *
926 * Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
927 * 'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
928 * id and component == 1. Now, during 'liga', the LAM and the LAM-HEH ligature
929 * form a LAM-LAM-HEH ligature. We need to reassign the SHADDA and FATHA to
930 * the new ligature with a component value of 2.
931 *
932 * This in fact happened to a font... See:
933 * https://bugzilla.gnome.org/show_bug.cgi?id=437633
934 */
935
Behdad Esfahbod9efddb92018-10-02 16:05:26 +0200936 bool is_base_ligature = _hb_glyph_info_is_base_glyph (&buffer->info[match_positions[0]]);
937 bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->info[match_positions[0]]);
938 for (unsigned int i = 1; i < count; i++)
Behdad Esfahbod3cca9782018-10-02 15:02:16 +0200939 if (!_hb_glyph_info_is_mark (&buffer->info[match_positions[i]]))
940 {
Behdad Esfahbod9efddb92018-10-02 16:05:26 +0200941 is_base_ligature = false;
Behdad Esfahbod3cca9782018-10-02 15:02:16 +0200942 is_mark_ligature = false;
943 break;
944 }
Behdad Esfahbod9efddb92018-10-02 16:05:26 +0200945 bool is_ligature = !is_base_ligature && !is_mark_ligature;
Behdad Esfahbod3cca9782018-10-02 15:02:16 +0200946
Behdad Esfahbod9efddb92018-10-02 16:05:26 +0200947 unsigned int klass = is_ligature ? HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE : 0;
948 unsigned int lig_id = is_ligature ? _hb_allocate_lig_id (buffer) : 0;
Behdad Esfahbod3ddf8922013-10-18 00:02:43 +0200949 unsigned int last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
950 unsigned int last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
Behdad Esfahboda177d022012-08-28 23:18:22 -0400951 unsigned int components_so_far = last_num_components;
952
Behdad Esfahbod9efddb92018-10-02 16:05:26 +0200953 if (is_ligature)
Behdad Esfahbod7e08f122013-05-27 14:48:34 -0400954 {
Behdad Esfahbod3ddf8922013-10-18 00:02:43 +0200955 _hb_glyph_info_set_lig_props_for_ligature (&buffer->cur(), lig_id, total_component_count);
Behdad Esfahbod3c3df9c2013-10-17 13:58:31 +0200956 if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
Behdad Esfahbod3d436d32013-10-28 21:00:37 +0100957 {
Behdad Esfahbod82596692015-11-02 17:44:05 -0800958 _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER);
Behdad Esfahbod3d436d32013-10-28 21:00:37 +0100959 }
Behdad Esfahbod7e08f122013-05-27 14:48:34 -0400960 }
Behdad Esfahboda0161742013-10-18 00:06:30 +0200961 c->replace_glyph_with_ligature (lig_glyph, klass);
Behdad Esfahboda177d022012-08-28 23:18:22 -0400962
963 for (unsigned int i = 1; i < count; i++)
964 {
Behdad Esfahbod7185b272018-05-31 20:03:00 -0700965 while (buffer->idx < match_positions[i] && buffer->successful)
Behdad Esfahboda177d022012-08-28 23:18:22 -0400966 {
Behdad Esfahbod9efddb92018-10-02 16:05:26 +0200967 if (is_ligature)
968 {
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330969 unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
Behdad Esfahbod2f02fc72015-12-17 15:21:14 +0000970 if (this_comp == 0)
Behdad Esfahbod100fbea2015-12-17 15:23:09 +0000971 this_comp = last_num_components;
Behdad Esfahboda177d022012-08-28 23:18:22 -0400972 unsigned int new_lig_comp = components_so_far - last_num_components +
Behdad Esfahbod2f02fc72015-12-17 15:21:14 +0000973 MIN (this_comp, last_num_components);
974 _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
Behdad Esfahboda177d022012-08-28 23:18:22 -0400975 }
Behdad Esfahbod3c3df9c2013-10-17 13:58:31 +0200976 buffer->next_glyph ();
Behdad Esfahboda177d022012-08-28 23:18:22 -0400977 }
978
Behdad Esfahbod3ddf8922013-10-18 00:02:43 +0200979 last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
980 last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
Behdad Esfahboda177d022012-08-28 23:18:22 -0400981 components_so_far += last_num_components;
982
983 /* Skip the base glyph */
Behdad Esfahbod3c3df9c2013-10-17 13:58:31 +0200984 buffer->idx++;
Behdad Esfahboda177d022012-08-28 23:18:22 -0400985 }
986
987 if (!is_mark_ligature && last_lig_id) {
988 /* Re-adjust components for any marks following. */
Behdad Esfahbod3c3df9c2013-10-17 13:58:31 +0200989 for (unsigned int i = buffer->idx; i < buffer->len; i++) {
Behdad Esfahbod3ddf8922013-10-18 00:02:43 +0200990 if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) {
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +0330991 unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
Behdad Esfahbod2f02fc72015-12-17 15:21:14 +0000992 if (!this_comp)
993 break;
Behdad Esfahboda177d022012-08-28 23:18:22 -0400994 unsigned int new_lig_comp = components_so_far - last_num_components +
Behdad Esfahbod2f02fc72015-12-17 15:21:14 +0000995 MIN (this_comp, last_num_components);
Behdad Esfahbod3ddf8922013-10-18 00:02:43 +0200996 _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
Behdad Esfahboda177d022012-08-28 23:18:22 -0400997 } else
998 break;
999 }
1000 }
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001001 return_trace (true);
Behdad Esfahboda177d022012-08-28 23:18:22 -04001002}
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -04001003
Behdad Esfahbodfd034492018-01-17 16:46:51 -08001004static inline bool match_backtrack (hb_ot_apply_context_t *c,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -04001005 unsigned int count,
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001006 const HBUINT16 backtrack[],
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -04001007 match_func_t match_func,
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +02001008 const void *match_data,
1009 unsigned int *match_start)
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -04001010{
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02001011 TRACE_APPLY (nullptr);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -04001012
Behdad Esfahbodfd034492018-01-17 16:46:51 -08001013 hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
Behdad Esfahbodb051be52015-01-29 13:40:39 +01001014 skippy_iter.reset (c->buffer->backtrack_len (), count);
Behdad Esfahbod607feb72013-02-14 07:43:13 -05001015 skippy_iter.set_match_func (match_func, match_data, backtrack);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -04001016
Behdad Esfahbod4d3aeb82012-01-16 16:43:26 -05001017 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -05001018 if (!skippy_iter.prev ())
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001019 return_trace (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -04001020
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +02001021 *match_start = skippy_iter.idx;
1022
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001023 return_trace (true);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -04001024}
1025
Behdad Esfahbodfd034492018-01-17 16:46:51 -08001026static inline bool match_lookahead (hb_ot_apply_context_t *c,
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -04001027 unsigned int count,
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001028 const HBUINT16 lookahead[],
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -04001029 match_func_t match_func,
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001030 const void *match_data,
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +02001031 unsigned int offset,
1032 unsigned int *end_index)
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -04001033{
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02001034 TRACE_APPLY (nullptr);
Behdad Esfahbod93814ca2012-08-28 22:24:51 -04001035
Behdad Esfahbodfd034492018-01-17 16:46:51 -08001036 hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
Behdad Esfahbodb051be52015-01-29 13:40:39 +01001037 skippy_iter.reset (c->buffer->idx + offset - 1, count);
Behdad Esfahbod607feb72013-02-14 07:43:13 -05001038 skippy_iter.set_match_func (match_func, match_data, lookahead);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -04001039
Behdad Esfahbod370f03e2012-01-16 17:03:55 -05001040 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbod4ab97312012-01-16 22:05:08 -05001041 if (!skippy_iter.next ())
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001042 return_trace (false);
Behdad Esfahbodd0ba0552009-05-18 03:56:39 -04001043
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +02001044 *end_index = skippy_iter.idx + 1;
1045
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001046 return_trace (true);
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001047}
1048
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -04001049
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001050
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001051struct LookupRecord
1052{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301053 bool sanitize (hb_sanitize_context_t *c) const
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03001054 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001055 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001056 return_trace (c->check_struct (this));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -04001057 }
1058
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001059 HBUINT16 sequenceIndex; /* Index into current glyph
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001060 * sequence--first glyph = 0 */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001061 HBUINT16 lookupListIndex; /* Lookup to apply to that
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001062 * position--zero--based */
Behdad Esfahbod569da922010-05-10 16:38:32 -04001063 public:
1064 DEFINE_SIZE_STATIC (4);
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001065};
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001066
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001067template <typename context_t>
1068static inline void recurse_lookups (context_t *c,
1069 unsigned int lookupCount,
1070 const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001071{
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001072 for (unsigned int i = 0; i < lookupCount; i++)
Behdad Esfahbod86522e42013-07-22 19:07:53 -04001073 c->recurse (lookupRecord[i].lookupListIndex);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001074}
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -04001075
Behdad Esfahbodfd034492018-01-17 16:46:51 -08001076static inline bool apply_lookup (hb_ot_apply_context_t *c,
Behdad Esfahbode072c242009-05-18 03:47:31 -04001077 unsigned int count, /* Including the first glyph */
Behdad Esfahbod5ba45042015-11-02 15:43:08 -08001078 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH], /* Including the first glyph */
Behdad Esfahbode072c242009-05-18 03:47:31 -04001079 unsigned int lookupCount,
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001080 const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
1081 unsigned int match_length)
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001082{
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02001083 TRACE_APPLY (nullptr);
Behdad Esfahbod902cc8a2012-11-23 15:06:59 -05001084
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001085 hb_buffer_t *buffer = c->buffer;
jfkthame44f7d6e2017-02-17 03:03:24 +00001086 int end;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001087
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001088 /* All positions are distance from beginning of *output* buffer.
1089 * Adjust. */
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001090 {
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001091 unsigned int bl = buffer->backtrack_len ();
1092 end = bl + match_length;
Behdad Esfahbod8751de52013-07-18 16:29:50 -04001093
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001094 int delta = bl - buffer->idx;
1095 /* Convert positions to new indexing. */
1096 for (unsigned int j = 0; j < count; j++)
1097 match_positions[j] += delta;
Behdad Esfahbod8820bb22013-02-14 07:41:03 -05001098 }
Behdad Esfahbode73a0c22009-05-18 04:15:25 -04001099
Behdad Esfahbod7185b272018-05-31 20:03:00 -07001100 for (unsigned int i = 0; i < lookupCount && buffer->successful; i++)
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001101 {
1102 unsigned int idx = lookupRecord[i].sequenceIndex;
1103 if (idx >= count)
1104 continue;
1105
Behdad Esfahbod9cc1ed42015-11-19 12:39:09 -08001106 /* Don't recurse to ourself at same position.
1107 * Note that this test is too naive, it doesn't catch longer loops. */
1108 if (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index)
1109 continue;
1110
Behdad Esfahbode5930722017-11-14 15:47:55 -08001111 if (unlikely (!buffer->move_to (match_positions[idx])))
1112 break;
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001113
Behdad Esfahbodbaf77792017-11-14 21:53:48 -08001114 if (unlikely (buffer->max_ops <= 0))
1115 break;
1116
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001117 unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
1118 if (!c->recurse (lookupRecord[i].lookupListIndex))
1119 continue;
1120
1121 unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
1122 int delta = new_len - orig_len;
1123
1124 if (!delta)
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03301125 continue;
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001126
Behdad Esfahbod9ac9af72017-03-05 13:51:01 -08001127 /* Recursed lookup changed buffer len. Adjust.
1128 *
1129 * TODO:
1130 *
1131 * Right now, if buffer length increased by n, we assume n new glyphs
1132 * were added right after the current position, and if buffer length
1133 * was decreased by n, we assume n match positions after the current
1134 * one where removed. The former (buffer length increased) case is
1135 * fine, but the decrease case can be improved in at least two ways,
1136 * both of which are significant:
1137 *
1138 * - If recursed-to lookup is MultipleSubst and buffer length
1139 * decreased, then it's current match position that was deleted,
1140 * NOT the one after it.
1141 *
1142 * - If buffer length was decreased by n, it does not necessarily
1143 * mean that n match positions where removed, as there might
1144 * have been marks and default-ignorables in the sequence. We
1145 * should instead drop match positions between current-position
1146 * and current-position + n instead.
1147 *
1148 * It should be possible to construct tests for both of these cases.
1149 */
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001150
jfkthame44f7d6e2017-02-17 03:03:24 +00001151 end += delta;
Behdad Esfahbod47e7a182017-03-10 13:23:02 -08001152 if (end <= int (match_positions[idx]))
Behdad Esfahbod359dead2016-05-06 16:19:19 +01001153 {
Behdad Esfahbod4b4a1b92016-12-21 23:10:43 -06001154 /* End might end up being smaller than match_positions[idx] if the recursed
Behdad Esfahbod47e7a182017-03-10 13:23:02 -08001155 * lookup ended up removing many items, more than we have had matched.
Behdad Esfahbod4b4a1b92016-12-21 23:10:43 -06001156 * Just never rewind end back and get out of here.
1157 * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */
1158 end = match_positions[idx];
Behdad Esfahbod47e7a182017-03-10 13:23:02 -08001159 /* There can't be any further changes. */
Behdad Esfahbod359dead2016-05-06 16:19:19 +01001160 break;
1161 }
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001162
1163 unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
1164
1165 if (delta > 0)
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001166 {
Behdad Esfahbod5ba45042015-11-02 15:43:08 -08001167 if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001168 break;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001169 }
1170 else
1171 {
Behdad Esfahbod47e7a182017-03-10 13:23:02 -08001172 /* NOTE: delta is negative. */
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001173 delta = MAX (delta, (int) next - (int) count);
1174 next -= delta;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001175 }
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001176
1177 /* Shift! */
1178 memmove (match_positions + next + delta, match_positions + next,
1179 (count - next) * sizeof (match_positions[0]));
1180 next += delta;
1181 count += delta;
1182
1183 /* Fill in new entries. */
1184 for (unsigned int j = idx + 1; j < next; j++)
1185 match_positions[j] = match_positions[j - 1] + 1;
1186
1187 /* And fixup the rest. */
1188 for (; next < count; next++)
1189 match_positions[next] += delta;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001190 }
1191
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001192 buffer->move_to (end);
1193
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001194 return_trace (true);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001195}
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001196
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -04001197
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001198
1199/* Contextual lookups */
1200
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001201struct ContextClosureLookupContext
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001202{
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001203 ContextClosureFuncs funcs;
1204 const void *intersects_data;
1205};
1206
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001207struct ContextCollectGlyphsLookupContext
1208{
1209 ContextCollectGlyphsFuncs funcs;
1210 const void *collect_data;
1211};
1212
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001213struct ContextApplyLookupContext
1214{
1215 ContextApplyFuncs funcs;
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001216 const void *match_data;
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001217};
1218
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001219static inline bool context_intersects (const hb_set_t *glyphs,
1220 unsigned int inputCount, /* Including the first glyph (not matched) */
1221 const HBUINT16 input[], /* Array of input values--start with second glyph */
1222 ContextClosureLookupContext &lookup_context)
1223{
1224 return intersects_array (glyphs,
1225 inputCount ? inputCount - 1 : 0, input,
1226 lookup_context.funcs.intersects, lookup_context.intersects_data);
1227}
1228
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001229static inline void context_closure_lookup (hb_closure_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001230 unsigned int inputCount, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001231 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001232 unsigned int lookupCount,
1233 const LookupRecord lookupRecord[],
1234 ContextClosureLookupContext &lookup_context)
1235{
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001236 if (context_intersects (c->glyphs,
1237 inputCount, input,
1238 lookup_context))
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001239 recurse_lookups (c,
1240 lookupCount, lookupRecord);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001241}
1242
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001243static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
1244 unsigned int inputCount, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001245 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001246 unsigned int lookupCount,
1247 const LookupRecord lookupRecord[],
1248 ContextCollectGlyphsLookupContext &lookup_context)
1249{
Behdad Esfahbod83035932012-12-04 17:08:41 -05001250 collect_array (c, c->input,
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001251 inputCount ? inputCount - 1 : 0, input,
1252 lookup_context.funcs.collect, lookup_context.collect_data);
1253 recurse_lookups (c,
1254 lookupCount, lookupRecord);
1255}
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001256
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001257static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
1258 unsigned int inputCount, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001259 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbod0beb66e2012-12-05 18:46:04 -05001260 unsigned int lookupCount HB_UNUSED,
1261 const LookupRecord lookupRecord[] HB_UNUSED,
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001262 ContextApplyLookupContext &lookup_context)
1263{
1264 return would_match_input (c,
1265 inputCount, input,
1266 lookup_context.funcs.match, lookup_context.match_data);
1267}
Behdad Esfahbodfd034492018-01-17 16:46:51 -08001268static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001269 unsigned int inputCount, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001270 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001271 unsigned int lookupCount,
1272 const LookupRecord lookupRecord[],
1273 ContextApplyLookupContext &lookup_context)
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001274{
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001275 unsigned int match_length = 0;
Behdad Esfahbod5ba45042015-11-02 15:43:08 -08001276 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001277 return match_input (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -04001278 inputCount, input,
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001279 lookup_context.funcs.match, lookup_context.match_data,
1280 &match_length, match_positions)
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +02001281 && (c->buffer->unsafe_to_break (c->buffer->idx, c->buffer->idx + match_length),
1282 apply_lookup (c,
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001283 inputCount, match_positions,
1284 lookupCount, lookupRecord,
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +02001285 match_length));
Behdad Esfahbodf14c2b72009-05-18 02:36:18 -04001286}
1287
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001288struct Rule
1289{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301290 bool intersects (const hb_set_t *glyphs, ContextClosureLookupContext &lookup_context) const
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001291 {
1292 return context_intersects (glyphs,
Behdad Esfahbodbc485a92018-09-10 23:02:24 +02001293 inputCount, inputZ.arrayZ,
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001294 lookup_context);
1295 }
1296
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301297 void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001298 {
Behdad Esfahbod0382b712018-11-02 12:23:26 -04001299 const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
1300 (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001301 context_closure_lookup (c,
Behdad Esfahbodbc485a92018-09-10 23:02:24 +02001302 inputCount, inputZ.arrayZ,
1303 lookupCount, lookupRecord.arrayZ,
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001304 lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001305 }
1306
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301307 void collect_glyphs (hb_collect_glyphs_context_t *c,
1308 ContextCollectGlyphsLookupContext &lookup_context) const
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001309 {
1310 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbod0382b712018-11-02 12:23:26 -04001311 const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
1312 (inputZ.as_array (inputCount ? inputCount - 1 : 0));
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001313 context_collect_glyphs_lookup (c,
Behdad Esfahbodbc485a92018-09-10 23:02:24 +02001314 inputCount, inputZ.arrayZ,
1315 lookupCount, lookupRecord.arrayZ,
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001316 lookup_context);
1317 }
1318
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301319 bool would_apply (hb_would_apply_context_t *c,
1320 ContextApplyLookupContext &lookup_context) const
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001321 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001322 TRACE_WOULD_APPLY (this);
Behdad Esfahbod0382b712018-11-02 12:23:26 -04001323 const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
1324 (inputZ.as_array (inputCount ? inputCount - 1 : 0));
Behdad Esfahbodbc485a92018-09-10 23:02:24 +02001325 return_trace (context_would_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001326 }
1327
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301328 bool apply (hb_ot_apply_context_t *c,
1329 ContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001330 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001331 TRACE_APPLY (this);
Behdad Esfahbod0382b712018-11-02 12:23:26 -04001332 const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord> >
1333 (inputZ.as_array (inputCount ? inputCount - 1 : 0));
Behdad Esfahbodbc485a92018-09-10 23:02:24 +02001334 return_trace (context_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001335 }
1336
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001337 public:
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301338 bool sanitize (hb_sanitize_context_t *c) const
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03001339 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001340 TRACE_SANITIZE (this);
Behdad Esfahbod5aad8192017-11-03 17:16:26 -04001341 return_trace (inputCount.sanitize (c) &&
1342 lookupCount.sanitize (c) &&
Behdad Esfahbodbc485a92018-09-10 23:02:24 +02001343 c->check_range (inputZ.arrayZ,
Behdad Esfahbod9c6921c2018-11-30 15:16:57 -05001344 inputZ.item_size * (inputCount ? inputCount - 1 : 0) +
Behdad Esfahbod6d7c6e12018-02-07 14:09:56 -06001345 LookupRecord::static_size * lookupCount));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001346 }
1347
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001348 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001349 HBUINT16 inputCount; /* Total number of glyphs in input
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001350 * glyph sequence--includes the first
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001351 * glyph */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001352 HBUINT16 lookupCount; /* Number of LookupRecords */
Behdad Esfahbodbc485a92018-09-10 23:02:24 +02001353 UnsizedArrayOf<HBUINT16>
1354 inputZ; /* Array of match inputs--start with
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001355 * second glyph */
Behdad Esfahbodbc485a92018-09-10 23:02:24 +02001356/*UnsizedArrayOf<LookupRecord>
1357 lookupRecordX;*/ /* Array of LookupRecords--in
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001358 * design order */
Behdad Esfahbod569da922010-05-10 16:38:32 -04001359 public:
Behdad Esfahbod6d7c6e12018-02-07 14:09:56 -06001360 DEFINE_SIZE_ARRAY (4, inputZ);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001361};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001362
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001363struct RuleSet
1364{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301365 bool intersects (const hb_set_t *glyphs,
1366 ContextClosureLookupContext &lookup_context) const
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001367 {
1368 unsigned int num_rules = rule.len;
1369 for (unsigned int i = 0; i < num_rules; i++)
1370 if ((this+rule[i]).intersects (glyphs, lookup_context))
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03301371 return true;
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001372 return false;
1373 }
1374
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301375 void closure (hb_closure_context_t *c,
1376 ContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001377 {
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001378 unsigned int num_rules = rule.len;
1379 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001380 (this+rule[i]).closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001381 }
1382
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301383 void collect_glyphs (hb_collect_glyphs_context_t *c,
1384 ContextCollectGlyphsLookupContext &lookup_context) const
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001385 {
1386 TRACE_COLLECT_GLYPHS (this);
1387 unsigned int num_rules = rule.len;
1388 for (unsigned int i = 0; i < num_rules; i++)
1389 (this+rule[i]).collect_glyphs (c, lookup_context);
1390 }
1391
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301392 bool would_apply (hb_would_apply_context_t *c,
1393 ContextApplyLookupContext &lookup_context) const
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001394 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001395 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001396 unsigned int num_rules = rule.len;
1397 for (unsigned int i = 0; i < num_rules; i++)
1398 {
1399 if ((this+rule[i]).would_apply (c, lookup_context))
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03301400 return_trace (true);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001401 }
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001402 return_trace (false);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001403 }
1404
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301405 bool apply (hb_ot_apply_context_t *c,
1406 ContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001407 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001408 TRACE_APPLY (this);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001409 unsigned int num_rules = rule.len;
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001410 for (unsigned int i = 0; i < num_rules; i++)
1411 {
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001412 if ((this+rule[i]).apply (c, lookup_context))
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03301413 return_trace (true);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001414 }
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001415 return_trace (false);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001416 }
1417
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301418 bool sanitize (hb_sanitize_context_t *c) const
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03001419 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001420 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001421 return_trace (rule.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001422 }
1423
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001424 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001425 OffsetArrayOf<Rule>
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001426 rule; /* Array of Rule tables
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001427 * ordered by preference */
Behdad Esfahboded074222010-05-10 18:08:46 -04001428 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001429 DEFINE_SIZE_ARRAY (2, rule);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001430};
1431
1432
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001433struct ContextFormat1
1434{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301435 bool intersects (const hb_set_t *glyphs) const
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001436 {
1437 struct ContextClosureLookupContext lookup_context = {
1438 {intersects_glyph},
1439 nullptr
1440 };
1441
1442 unsigned int count = ruleSet.len;
Behdad Esfahbodca5e5a42018-10-29 22:30:21 -07001443 for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001444 {
1445 if (unlikely (iter.get_coverage () >= count))
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03301446 break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001447 if (glyphs->has (iter.get_glyph ()) &&
1448 (this+ruleSet[iter.get_coverage ()]).intersects (glyphs, lookup_context))
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03301449 return true;
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001450 }
1451 return false;
1452 }
1453
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301454 void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001455 {
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001456 struct ContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001457 {intersects_glyph},
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02001458 nullptr
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001459 };
1460
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001461 unsigned int count = ruleSet.len;
Behdad Esfahbodca5e5a42018-10-29 22:30:21 -07001462 for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001463 {
1464 if (unlikely (iter.get_coverage () >= count))
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03301465 break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001466 if (c->glyphs->has (iter.get_glyph ()))
1467 (this+ruleSet[iter.get_coverage ()]).closure (c, lookup_context);
1468 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001469 }
1470
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301471 void collect_glyphs (hb_collect_glyphs_context_t *c) const
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001472 {
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001473 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbod83035932012-12-04 17:08:41 -05001474 (this+coverage).add_coverage (c->input);
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001475
1476 struct ContextCollectGlyphsLookupContext lookup_context = {
1477 {collect_glyph},
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02001478 nullptr
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001479 };
1480
1481 unsigned int count = ruleSet.len;
1482 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001483 (this+ruleSet[i]).collect_glyphs (c, lookup_context);
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001484 }
1485
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301486 bool would_apply (hb_would_apply_context_t *c) const
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001487 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001488 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001489
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05001490 const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001491 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001492 {match_glyph},
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02001493 nullptr
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001494 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001495 return_trace (rule_set.would_apply (c, lookup_context));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001496 }
1497
Ebrahim Byagowie4120082018-12-17 21:31:01 +03301498 const Coverage &get_coverage () const { return this+coverage; }
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001499
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301500 bool apply (hb_ot_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001501 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001502 TRACE_APPLY (this);
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05001503 unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
Behdad Esfahbod64d3fc82010-05-03 22:51:19 -04001504 if (likely (index == NOT_COVERED))
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001505 return_trace (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001506
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001507 const RuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001508 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001509 {match_glyph},
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02001510 nullptr
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001511 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001512 return_trace (rule_set.apply (c, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001513 }
1514
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301515 bool subset (hb_subset_context_t *c) const
Behdad Esfahbod339d3602018-09-03 17:33:34 -07001516 {
1517 TRACE_SUBSET (this);
1518 // TODO(subset)
1519 return_trace (false);
1520 }
1521
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301522 bool sanitize (hb_sanitize_context_t *c) const
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03001523 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001524 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001525 return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001526 }
1527
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001528 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001529 HBUINT16 format; /* Format identifier--format = 1 */
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001530 OffsetTo<Coverage>
1531 coverage; /* Offset to Coverage table--from
1532 * beginning of table */
1533 OffsetArrayOf<RuleSet>
1534 ruleSet; /* Array of RuleSet tables
1535 * ordered by Coverage Index */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001536 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001537 DEFINE_SIZE_ARRAY (6, ruleSet);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001538};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001539
1540
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001541struct ContextFormat2
1542{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301543 bool intersects (const hb_set_t *glyphs) const
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001544 {
1545 if (!(this+coverage).intersects (glyphs))
1546 return false;
1547
1548 const ClassDef &class_def = this+classDef;
1549
1550 struct ContextClosureLookupContext lookup_context = {
1551 {intersects_class},
1552 &class_def
1553 };
1554
1555 unsigned int count = ruleSet.len;
1556 for (unsigned int i = 0; i < count; i++)
1557 if (class_def.intersects_class (glyphs, i) &&
1558 (this+ruleSet[i]).intersects (glyphs, lookup_context))
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03301559 return true;
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001560
1561 return false;
1562 }
1563
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301564 void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001565 {
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001566 if (!(this+coverage).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001567 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001568
1569 const ClassDef &class_def = this+classDef;
1570
1571 struct ContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001572 {intersects_class},
Behdad Esfahbod11fba792013-01-02 23:36:37 -06001573 &class_def
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001574 };
1575
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001576 unsigned int count = ruleSet.len;
1577 for (unsigned int i = 0; i < count; i++)
1578 if (class_def.intersects_class (c->glyphs, i)) {
1579 const RuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001580 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001581 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001582 }
1583
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301584 void collect_glyphs (hb_collect_glyphs_context_t *c) const
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001585 {
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001586 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbod83035932012-12-04 17:08:41 -05001587 (this+coverage).add_coverage (c->input);
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001588
Behdad Esfahbod11fba792013-01-02 23:36:37 -06001589 const ClassDef &class_def = this+classDef;
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001590 struct ContextCollectGlyphsLookupContext lookup_context = {
1591 {collect_class},
Behdad Esfahbod11fba792013-01-02 23:36:37 -06001592 &class_def
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001593 };
1594
1595 unsigned int count = ruleSet.len;
1596 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001597 (this+ruleSet[i]).collect_glyphs (c, lookup_context);
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001598 }
1599
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301600 bool would_apply (hb_would_apply_context_t *c) const
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001601 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001602 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001603
1604 const ClassDef &class_def = this+classDef;
Behdad Esfahbod2dc11412012-11-24 19:16:34 -05001605 unsigned int index = class_def.get_class (c->glyphs[0]);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001606 const RuleSet &rule_set = this+ruleSet[index];
1607 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001608 {match_class},
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001609 &class_def
1610 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001611 return_trace (rule_set.would_apply (c, lookup_context));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001612 }
1613
Ebrahim Byagowie4120082018-12-17 21:31:01 +03301614 const Coverage &get_coverage () const { return this+coverage; }
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001615
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301616 bool apply (hb_ot_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001617 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001618 TRACE_APPLY (this);
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05001619 unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001620 if (likely (index == NOT_COVERED)) return_trace (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001621
1622 const ClassDef &class_def = this+classDef;
Behdad Esfahbod2dc11412012-11-24 19:16:34 -05001623 index = class_def.get_class (c->buffer->cur().codepoint);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001624 const RuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001625 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001626 {match_class},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001627 &class_def
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001628 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001629 return_trace (rule_set.apply (c, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001630 }
1631
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301632 bool subset (hb_subset_context_t *c) const
Behdad Esfahbod339d3602018-09-03 17:33:34 -07001633 {
1634 TRACE_SUBSET (this);
1635 // TODO(subset)
1636 return_trace (false);
1637 }
1638
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301639 bool sanitize (hb_sanitize_context_t *c) const
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03001640 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001641 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001642 return_trace (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001643 }
1644
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001645 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001646 HBUINT16 format; /* Format identifier--format = 2 */
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001647 OffsetTo<Coverage>
1648 coverage; /* Offset to Coverage table--from
1649 * beginning of table */
1650 OffsetTo<ClassDef>
1651 classDef; /* Offset to glyph ClassDef table--from
1652 * beginning of table */
1653 OffsetArrayOf<RuleSet>
1654 ruleSet; /* Array of RuleSet tables
1655 * ordered by class */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04001656 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04001657 DEFINE_SIZE_ARRAY (8, ruleSet);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001658};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001659
1660
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001661struct ContextFormat3
1662{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301663 bool intersects (const hb_set_t *glyphs) const
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001664 {
Behdad Esfahbodfb059082018-11-30 20:45:40 -05001665 if (!(this+coverageZ[0]).intersects (glyphs))
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001666 return false;
1667
1668 struct ContextClosureLookupContext lookup_context = {
1669 {intersects_coverage},
1670 this
1671 };
1672 return context_intersects (glyphs,
Behdad Esfahbodbc485a92018-09-10 23:02:24 +02001673 glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001674 lookup_context);
1675 }
1676
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301677 void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001678 {
Behdad Esfahbodfb059082018-11-30 20:45:40 -05001679 if (!(this+coverageZ[0]).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001680 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001681
Behdad Esfahbod0382b712018-11-02 12:23:26 -04001682 const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001683 struct ContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001684 {intersects_coverage},
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001685 this
1686 };
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001687 context_closure_lookup (c,
Behdad Esfahbodbc485a92018-09-10 23:02:24 +02001688 glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001689 lookupCount, lookupRecord,
1690 lookup_context);
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001691 }
1692
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301693 void collect_glyphs (hb_collect_glyphs_context_t *c) const
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001694 {
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001695 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbodfb059082018-11-30 20:45:40 -05001696 (this+coverageZ[0]).add_coverage (c->input);
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001697
Behdad Esfahbod0382b712018-11-02 12:23:26 -04001698 const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001699 struct ContextCollectGlyphsLookupContext lookup_context = {
1700 {collect_coverage},
Behdad Esfahbode75943d2012-11-30 08:38:24 +02001701 this
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001702 };
1703
1704 context_collect_glyphs_lookup (c,
Behdad Esfahbodbc485a92018-09-10 23:02:24 +02001705 glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001706 lookupCount, lookupRecord,
1707 lookup_context);
Behdad Esfahbod26514d52012-11-23 18:13:48 -05001708 }
1709
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301710 bool would_apply (hb_would_apply_context_t *c) const
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001711 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001712 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001713
Behdad Esfahbod0382b712018-11-02 12:23:26 -04001714 const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001715 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001716 {match_coverage},
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001717 this
1718 };
Behdad Esfahbodbc485a92018-09-10 23:02:24 +02001719 return_trace (context_would_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1), lookupCount, lookupRecord, lookup_context));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001720 }
1721
Ebrahim Byagowie4120082018-12-17 21:31:01 +03301722 const Coverage &get_coverage () const { return this+coverageZ[0]; }
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001723
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301724 bool apply (hb_ot_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001725 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001726 TRACE_APPLY (this);
Behdad Esfahbodfb059082018-11-30 20:45:40 -05001727 unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001728 if (likely (index == NOT_COVERED)) return_trace (false);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001729
Behdad Esfahbod0382b712018-11-02 12:23:26 -04001730 const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001731 struct ContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05001732 {match_coverage},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001733 this
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001734 };
Behdad Esfahbodbc485a92018-09-10 23:02:24 +02001735 return_trace (context_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1), lookupCount, lookupRecord, lookup_context));
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001736 }
1737
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301738 bool subset (hb_subset_context_t *c) const
Behdad Esfahbod339d3602018-09-03 17:33:34 -07001739 {
1740 TRACE_SUBSET (this);
1741 // TODO(subset)
1742 return_trace (false);
1743 }
1744
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301745 bool sanitize (hb_sanitize_context_t *c) const
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03001746 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001747 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001748 if (!c->check_struct (this)) return_trace (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001749 unsigned int count = glyphCount;
Behdad Esfahbodfb059082018-11-30 20:45:40 -05001750 if (!count) return_trace (false); /* We want to access coverageZ[0] freely. */
Behdad Esfahbod9507b052018-09-10 23:18:07 +02001751 if (!c->check_array (coverageZ.arrayZ, count)) return_trace (false);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001752 for (unsigned int i = 0; i < count; i++)
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001753 if (!coverageZ[i].sanitize (c, this)) return_trace (false);
Behdad Esfahbod0382b712018-11-02 12:23:26 -04001754 const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
Behdad Esfahbod9507b052018-09-10 23:18:07 +02001755 return_trace (c->check_array (lookupRecord, lookupCount));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04001756 }
1757
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001758 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001759 HBUINT16 format; /* Format identifier--format = 3 */
1760 HBUINT16 glyphCount; /* Number of glyphs in the input glyph
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001761 * sequence */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001762 HBUINT16 lookupCount; /* Number of LookupRecords */
Behdad Esfahbodbc485a92018-09-10 23:02:24 +02001763 UnsizedArrayOf<OffsetTo<Coverage> >
1764 coverageZ; /* Array of offsets to Coverage
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001765 * table in glyph sequence order */
Behdad Esfahbodbc485a92018-09-10 23:02:24 +02001766/*UnsizedArrayOf<LookupRecord>
1767 lookupRecordX;*/ /* Array of LookupRecords--in
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001768 * design order */
Behdad Esfahbod569da922010-05-10 16:38:32 -04001769 public:
Behdad Esfahbod6d7c6e12018-02-07 14:09:56 -06001770 DEFINE_SIZE_ARRAY (6, coverageZ);
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001771};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001772
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001773struct Context
1774{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05001775 template <typename context_t>
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301776 typename context_t::return_t dispatch (context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001777 {
Behdad Esfahbod00f6a8e2014-12-12 20:36:49 -08001778 TRACE_DISPATCH (this, u.format);
Behdad Esfahbodf396fbb2015-10-09 12:25:55 -04001779 if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04001780 switch (u.format) {
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001781 case 1: return_trace (c->dispatch (u.format1));
1782 case 2: return_trace (c->dispatch (u.format2));
1783 case 3: return_trace (c->dispatch (u.format3));
1784 default:return_trace (c->default_return_value ());
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001785 }
1786 }
1787
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04001788 protected:
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001789 union {
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001790 HBUINT16 format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -04001791 ContextFormat1 format1;
1792 ContextFormat2 format2;
1793 ContextFormat3 format3;
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001794 } u;
1795};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04001796
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04001797
1798/* Chaining Contextual lookups */
1799
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001800struct ChainContextClosureLookupContext
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001801{
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001802 ContextClosureFuncs funcs;
1803 const void *intersects_data[3];
1804};
1805
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001806struct ChainContextCollectGlyphsLookupContext
1807{
1808 ContextCollectGlyphsFuncs funcs;
1809 const void *collect_data[3];
1810};
1811
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001812struct ChainContextApplyLookupContext
1813{
1814 ContextApplyFuncs funcs;
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04001815 const void *match_data[3];
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001816};
1817
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001818static inline bool chain_context_intersects (const hb_set_t *glyphs,
1819 unsigned int backtrackCount,
1820 const HBUINT16 backtrack[],
1821 unsigned int inputCount, /* Including the first glyph (not matched) */
1822 const HBUINT16 input[], /* Array of input values--start with second glyph */
1823 unsigned int lookaheadCount,
1824 const HBUINT16 lookahead[],
1825 ChainContextClosureLookupContext &lookup_context)
1826{
1827 return intersects_array (glyphs,
1828 backtrackCount, backtrack,
Behdad Esfahbodfb059082018-11-30 20:45:40 -05001829 lookup_context.funcs.intersects, lookup_context.intersects_data[0])
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001830 && intersects_array (glyphs,
1831 inputCount ? inputCount - 1 : 0, input,
1832 lookup_context.funcs.intersects, lookup_context.intersects_data[1])
1833 && intersects_array (glyphs,
1834 lookaheadCount, lookahead,
1835 lookup_context.funcs.intersects, lookup_context.intersects_data[2]);
1836}
1837
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001838static inline void chain_context_closure_lookup (hb_closure_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001839 unsigned int backtrackCount,
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001840 const HBUINT16 backtrack[],
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001841 unsigned int inputCount, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001842 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001843 unsigned int lookaheadCount,
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001844 const HBUINT16 lookahead[],
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001845 unsigned int lookupCount,
1846 const LookupRecord lookupRecord[],
1847 ChainContextClosureLookupContext &lookup_context)
1848{
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001849 if (chain_context_intersects (c->glyphs,
1850 backtrackCount, backtrack,
1851 inputCount, input,
1852 lookaheadCount, lookahead,
1853 lookup_context))
Behdad Esfahbodd0a52332012-11-23 18:54:59 -05001854 recurse_lookups (c,
1855 lookupCount, lookupRecord);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001856}
1857
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001858static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03301859 unsigned int backtrackCount,
1860 const HBUINT16 backtrack[],
1861 unsigned int inputCount, /* Including the first glyph (not matched) */
1862 const HBUINT16 input[], /* Array of input values--start with second glyph */
1863 unsigned int lookaheadCount,
1864 const HBUINT16 lookahead[],
1865 unsigned int lookupCount,
1866 const LookupRecord lookupRecord[],
1867 ChainContextCollectGlyphsLookupContext &lookup_context)
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001868{
Behdad Esfahbod83035932012-12-04 17:08:41 -05001869 collect_array (c, c->before,
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001870 backtrackCount, backtrack,
1871 lookup_context.funcs.collect, lookup_context.collect_data[0]);
Behdad Esfahbod83035932012-12-04 17:08:41 -05001872 collect_array (c, c->input,
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001873 inputCount ? inputCount - 1 : 0, input,
1874 lookup_context.funcs.collect, lookup_context.collect_data[1]);
Behdad Esfahbod83035932012-12-04 17:08:41 -05001875 collect_array (c, c->after,
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001876 lookaheadCount, lookahead,
1877 lookup_context.funcs.collect, lookup_context.collect_data[2]);
1878 recurse_lookups (c,
1879 lookupCount, lookupRecord);
1880}
1881
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001882static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
1883 unsigned int backtrackCount,
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001884 const HBUINT16 backtrack[] HB_UNUSED,
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001885 unsigned int inputCount, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001886 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001887 unsigned int lookaheadCount,
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001888 const HBUINT16 lookahead[] HB_UNUSED,
Behdad Esfahbod0beb66e2012-12-05 18:46:04 -05001889 unsigned int lookupCount HB_UNUSED,
1890 const LookupRecord lookupRecord[] HB_UNUSED,
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001891 ChainContextApplyLookupContext &lookup_context)
1892{
Behdad Esfahbodd9b204d2012-08-23 16:22:28 -04001893 return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
Behdad Esfahbod1f2bb172012-08-23 16:10:37 -04001894 && would_match_input (c,
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001895 inputCount, input,
1896 lookup_context.funcs.match, lookup_context.match_data[1]);
1897}
1898
Behdad Esfahbodfd034492018-01-17 16:46:51 -08001899static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001900 unsigned int backtrackCount,
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001901 const HBUINT16 backtrack[],
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001902 unsigned int inputCount, /* Including the first glyph (not matched) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001903 const HBUINT16 input[], /* Array of input values--start with second glyph */
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001904 unsigned int lookaheadCount,
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001905 const HBUINT16 lookahead[],
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001906 unsigned int lookupCount,
1907 const LookupRecord lookupRecord[],
1908 ChainContextApplyLookupContext &lookup_context)
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001909{
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +02001910 unsigned int start_index = 0, match_length = 0, end_index = 0;
Behdad Esfahbod5ba45042015-11-02 15:43:08 -08001911 unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
Behdad Esfahbodf19e0b02012-06-09 02:26:57 -04001912 return match_input (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -04001913 inputCount, input,
1914 lookup_context.funcs.match, lookup_context.match_data[1],
Behdad Esfahbod6b65a762013-10-14 18:51:39 +02001915 &match_length, match_positions)
Behdad Esfahbodf19e0b02012-06-09 02:26:57 -04001916 && match_backtrack (c,
1917 backtrackCount, backtrack,
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +02001918 lookup_context.funcs.match, lookup_context.match_data[0],
1919 &start_index)
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04001920 && match_lookahead (c,
Behdad Esfahbod41697102010-05-05 01:37:58 -04001921 lookaheadCount, lookahead,
1922 lookup_context.funcs.match, lookup_context.match_data[2],
Behdad Esfahbod40bd7e92016-05-02 14:47:45 +02001923 match_length, &end_index)
1924 && (c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index),
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03301925 apply_lookup (c,
1926 inputCount, match_positions,
1927 lookupCount, lookupRecord,
1928 match_length));
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04001929}
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04001930
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001931struct ChainRule
1932{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301933 bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001934 {
1935 const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
1936 const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
1937 return chain_context_intersects (glyphs,
1938 backtrack.len, backtrack.arrayZ,
Behdad Esfahbodeffc7ce2018-09-13 20:21:54 +02001939 input.lenP1, input.arrayZ,
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07001940 lookahead.len, lookahead.arrayZ,
1941 lookup_context);
1942 }
1943
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301944 void closure (hb_closure_context_t *c,
1945 ChainContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001946 {
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001947 const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
1948 const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001949 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001950 chain_context_closure_lookup (c,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07001951 backtrack.len, backtrack.arrayZ,
Behdad Esfahbodeffc7ce2018-09-13 20:21:54 +02001952 input.lenP1, input.arrayZ,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07001953 lookahead.len, lookahead.arrayZ,
1954 lookup.len, lookup.arrayZ,
Behdad Esfahbod5caece62012-04-23 23:03:12 -04001955 lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04001956 }
1957
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301958 void collect_glyphs (hb_collect_glyphs_context_t *c,
1959 ChainContextCollectGlyphsLookupContext &lookup_context) const
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001960 {
1961 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001962 const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
1963 const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001964 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1965 chain_context_collect_glyphs_lookup (c,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07001966 backtrack.len, backtrack.arrayZ,
Behdad Esfahbodeffc7ce2018-09-13 20:21:54 +02001967 input.lenP1, input.arrayZ,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07001968 lookahead.len, lookahead.arrayZ,
1969 lookup.len, lookup.arrayZ,
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05001970 lookup_context);
1971 }
1972
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301973 bool would_apply (hb_would_apply_context_t *c,
1974 ChainContextApplyLookupContext &lookup_context) const
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001975 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001976 TRACE_WOULD_APPLY (this);
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001977 const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
1978 const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001979 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001980 return_trace (chain_context_would_apply_lookup (c,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07001981 backtrack.len, backtrack.arrayZ,
Behdad Esfahbodeffc7ce2018-09-13 20:21:54 +02001982 input.lenP1, input.arrayZ,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07001983 lookahead.len, lookahead.arrayZ, lookup.len,
1984 lookup.arrayZ, lookup_context));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04001985 }
1986
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301987 bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04001988 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05001989 TRACE_APPLY (this);
Behdad Esfahbod6b191782018-01-10 03:07:30 +01001990 const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
1991 const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
Behdad Esfahbode961c862010-04-21 15:56:11 -04001992 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01001993 return_trace (chain_context_apply_lookup (c,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07001994 backtrack.len, backtrack.arrayZ,
Behdad Esfahbodeffc7ce2018-09-13 20:21:54 +02001995 input.lenP1, input.arrayZ,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07001996 lookahead.len, lookahead.arrayZ, lookup.len,
1997 lookup.arrayZ, lookup_context));
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04001998 }
1999
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302000 bool sanitize (hb_sanitize_context_t *c) const
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03002001 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002002 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002003 if (!backtrack.sanitize (c)) return_trace (false);
Behdad Esfahbod6b191782018-01-10 03:07:30 +01002004 const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002005 if (!input.sanitize (c)) return_trace (false);
Behdad Esfahbod6b191782018-01-10 03:07:30 +01002006 const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002007 if (!lookahead.sanitize (c)) return_trace (false);
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03002008 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002009 return_trace (lookup.sanitize (c));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002010 }
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002011
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04002012 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +01002013 ArrayOf<HBUINT16>
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04002014 backtrack; /* Array of backtracking values
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002015 * (to be matched before the input
2016 * sequence) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01002017 HeadlessArrayOf<HBUINT16>
Behdad Esfahbode8cbaaf2009-05-18 02:03:58 -04002018 inputX; /* Array of input values (start with
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002019 * second glyph) */
Behdad Esfahbod6b191782018-01-10 03:07:30 +01002020 ArrayOf<HBUINT16>
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04002021 lookaheadX; /* Array of lookahead values's (to be
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04002022 * matched after the input sequence) */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04002023 ArrayOf<LookupRecord>
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04002024 lookupX; /* Array of LookupRecords--in
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002025 * design order) */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04002026 public:
Behdad Esfahbodbea34c72010-05-10 17:28:16 -04002027 DEFINE_SIZE_MIN (8);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002028};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002029
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04002030struct ChainRuleSet
2031{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302032 bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07002033 {
2034 unsigned int num_rules = rule.len;
2035 for (unsigned int i = 0; i < num_rules; i++)
2036 if ((this+rule[i]).intersects (glyphs, lookup_context))
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03302037 return true;
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07002038 return false;
2039 }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302040 void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
Behdad Esfahbod31081f72012-04-23 16:54:58 -04002041 {
Behdad Esfahbod31081f72012-04-23 16:54:58 -04002042 unsigned int num_rules = rule.len;
2043 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbod5caece62012-04-23 23:03:12 -04002044 (this+rule[i]).closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04002045 }
2046
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302047 void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05002048 {
2049 TRACE_COLLECT_GLYPHS (this);
2050 unsigned int num_rules = rule.len;
2051 for (unsigned int i = 0; i < num_rules; i++)
2052 (this+rule[i]).collect_glyphs (c, lookup_context);
2053 }
2054
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302055 bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002056 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002057 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002058 unsigned int num_rules = rule.len;
2059 for (unsigned int i = 0; i < num_rules; i++)
2060 if ((this+rule[i]).would_apply (c, lookup_context))
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03302061 return_trace (true);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002062
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002063 return_trace (false);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002064 }
2065
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302066 bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04002067 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002068 TRACE_APPLY (this);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04002069 unsigned int num_rules = rule.len;
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04002070 for (unsigned int i = 0; i < num_rules; i++)
Behdad Esfahbodd7cfb3b2010-05-13 14:18:49 -04002071 if ((this+rule[i]).apply (c, lookup_context))
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03302072 return_trace (true);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04002073
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002074 return_trace (false);
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04002075 }
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002076
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302077 bool sanitize (hb_sanitize_context_t *c) const
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03002078 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002079 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002080 return_trace (rule.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002081 }
2082
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04002083 protected:
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04002084 OffsetArrayOf<ChainRule>
2085 rule; /* Array of ChainRule tables
2086 * ordered by preference */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04002087 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04002088 DEFINE_SIZE_ARRAY (2, rule);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002089};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002090
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04002091struct ChainContextFormat1
2092{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302093 bool intersects (const hb_set_t *glyphs) const
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07002094 {
2095 struct ChainContextClosureLookupContext lookup_context = {
2096 {intersects_glyph},
2097 {nullptr, nullptr, nullptr}
2098 };
2099
2100 unsigned int count = ruleSet.len;
Behdad Esfahbodca5e5a42018-10-29 22:30:21 -07002101 for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07002102 {
2103 if (unlikely (iter.get_coverage () >= count))
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03302104 break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07002105 if (glyphs->has (iter.get_glyph ()) &&
2106 (this+ruleSet[iter.get_coverage ()]).intersects (glyphs, lookup_context))
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03302107 return true;
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07002108 }
2109 return false;
2110 }
2111
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302112 void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04002113 {
Behdad Esfahbod31081f72012-04-23 16:54:58 -04002114 struct ChainContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05002115 {intersects_glyph},
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02002116 {nullptr, nullptr, nullptr}
Behdad Esfahbod31081f72012-04-23 16:54:58 -04002117 };
2118
Behdad Esfahbod31081f72012-04-23 16:54:58 -04002119 unsigned int count = ruleSet.len;
Behdad Esfahbodca5e5a42018-10-29 22:30:21 -07002120 for (Coverage::Iter iter (this+coverage); iter.more (); iter.next ())
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07002121 {
2122 if (unlikely (iter.get_coverage () >= count))
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03302123 break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07002124 if (c->glyphs->has (iter.get_glyph ()))
2125 (this+ruleSet[iter.get_coverage ()]).closure (c, lookup_context);
2126 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04002127 }
2128
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302129 void collect_glyphs (hb_collect_glyphs_context_t *c) const
Behdad Esfahbod26514d52012-11-23 18:13:48 -05002130 {
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05002131 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbod83035932012-12-04 17:08:41 -05002132 (this+coverage).add_coverage (c->input);
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05002133
2134 struct ChainContextCollectGlyphsLookupContext lookup_context = {
2135 {collect_glyph},
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02002136 {nullptr, nullptr, nullptr}
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05002137 };
2138
2139 unsigned int count = ruleSet.len;
2140 for (unsigned int i = 0; i < count; i++)
2141 (this+ruleSet[i]).collect_glyphs (c, lookup_context);
Behdad Esfahbod26514d52012-11-23 18:13:48 -05002142 }
2143
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302144 bool would_apply (hb_would_apply_context_t *c) const
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002145 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002146 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002147
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05002148 const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002149 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05002150 {match_glyph},
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02002151 {nullptr, nullptr, nullptr}
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002152 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002153 return_trace (rule_set.would_apply (c, lookup_context));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002154 }
2155
Ebrahim Byagowie4120082018-12-17 21:31:01 +03302156 const Coverage &get_coverage () const { return this+coverage; }
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05002157
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302158 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 Esfahbodb67881b2012-11-24 19:13:55 -05002161 unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002162 if (likely (index == NOT_COVERED)) return_trace (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002163
2164 const ChainRuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04002165 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05002166 {match_glyph},
Behdad Esfahboddbdbfe32017-10-15 12:11:08 +02002167 {nullptr, nullptr, nullptr}
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002168 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002169 return_trace (rule_set.apply (c, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002170 }
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002171
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302172 bool subset (hb_subset_context_t *c) const
Behdad Esfahbod339d3602018-09-03 17:33:34 -07002173 {
2174 TRACE_SUBSET (this);
2175 // TODO(subset)
2176 return_trace (false);
2177 }
2178
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302179 bool sanitize (hb_sanitize_context_t *c) const
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03002180 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002181 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002182 return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002183 }
2184
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04002185 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +01002186 HBUINT16 format; /* Format identifier--format = 1 */
Behdad Esfahbod48f16ed2009-05-17 22:11:30 -04002187 OffsetTo<Coverage>
2188 coverage; /* Offset to Coverage table--from
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002189 * beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002190 OffsetArrayOf<ChainRuleSet>
2191 ruleSet; /* Array of ChainRuleSet tables
2192 * ordered by Coverage Index */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04002193 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04002194 DEFINE_SIZE_ARRAY (6, ruleSet);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002195};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002196
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04002197struct ChainContextFormat2
2198{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302199 bool intersects (const hb_set_t *glyphs) const
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07002200 {
2201 if (!(this+coverage).intersects (glyphs))
2202 return false;
2203
2204 const ClassDef &backtrack_class_def = this+backtrackClassDef;
2205 const ClassDef &input_class_def = this+inputClassDef;
2206 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
2207
2208 struct ChainContextClosureLookupContext lookup_context = {
2209 {intersects_class},
2210 {&backtrack_class_def,
2211 &input_class_def,
2212 &lookahead_class_def}
2213 };
2214
2215 unsigned int count = ruleSet.len;
2216 for (unsigned int i = 0; i < count; i++)
2217 if (input_class_def.intersects_class (glyphs, i) &&
2218 (this+ruleSet[i]).intersects (glyphs, lookup_context))
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03302219 return true;
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07002220
2221 return false;
2222 }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302223 void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04002224 {
Behdad Esfahbod31081f72012-04-23 16:54:58 -04002225 if (!(this+coverage).intersects (c->glyphs))
Behdad Esfahbod5caece62012-04-23 23:03:12 -04002226 return;
Behdad Esfahbod31081f72012-04-23 16:54:58 -04002227
2228 const ClassDef &backtrack_class_def = this+backtrackClassDef;
2229 const ClassDef &input_class_def = this+inputClassDef;
2230 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
2231
2232 struct ChainContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05002233 {intersects_class},
Behdad Esfahbod31081f72012-04-23 16:54:58 -04002234 {&backtrack_class_def,
2235 &input_class_def,
2236 &lookahead_class_def}
2237 };
2238
Behdad Esfahbod31081f72012-04-23 16:54:58 -04002239 unsigned int count = ruleSet.len;
2240 for (unsigned int i = 0; i < count; i++)
2241 if (input_class_def.intersects_class (c->glyphs, i)) {
2242 const ChainRuleSet &rule_set = this+ruleSet[i];
Behdad Esfahbod5caece62012-04-23 23:03:12 -04002243 rule_set.closure (c, lookup_context);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04002244 }
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04002245 }
2246
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302247 void collect_glyphs (hb_collect_glyphs_context_t *c) const
Behdad Esfahbod26514d52012-11-23 18:13:48 -05002248 {
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05002249 TRACE_COLLECT_GLYPHS (this);
Behdad Esfahbod83035932012-12-04 17:08:41 -05002250 (this+coverage).add_coverage (c->input);
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05002251
Behdad Esfahbod11fba792013-01-02 23:36:37 -06002252 const ClassDef &backtrack_class_def = this+backtrackClassDef;
2253 const ClassDef &input_class_def = this+inputClassDef;
2254 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
2255
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05002256 struct ChainContextCollectGlyphsLookupContext lookup_context = {
2257 {collect_class},
Behdad Esfahbod11fba792013-01-02 23:36:37 -06002258 {&backtrack_class_def,
2259 &input_class_def,
2260 &lookahead_class_def}
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05002261 };
2262
2263 unsigned int count = ruleSet.len;
2264 for (unsigned int i = 0; i < count; i++)
2265 (this+ruleSet[i]).collect_glyphs (c, lookup_context);
Behdad Esfahbod26514d52012-11-23 18:13:48 -05002266 }
2267
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302268 bool would_apply (hb_would_apply_context_t *c) const
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002269 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002270 TRACE_WOULD_APPLY (this);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002271
Behdad Esfahbod11fba792013-01-02 23:36:37 -06002272 const ClassDef &backtrack_class_def = this+backtrackClassDef;
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002273 const ClassDef &input_class_def = this+inputClassDef;
Behdad Esfahbod11fba792013-01-02 23:36:37 -06002274 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002275
Behdad Esfahbod2dc11412012-11-24 19:16:34 -05002276 unsigned int index = input_class_def.get_class (c->glyphs[0]);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002277 const ChainRuleSet &rule_set = this+ruleSet[index];
2278 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05002279 {match_class},
Behdad Esfahbod11fba792013-01-02 23:36:37 -06002280 {&backtrack_class_def,
2281 &input_class_def,
2282 &lookahead_class_def}
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002283 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002284 return_trace (rule_set.would_apply (c, lookup_context));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002285 }
2286
Ebrahim Byagowie4120082018-12-17 21:31:01 +03302287 const Coverage &get_coverage () const { return this+coverage; }
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05002288
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302289 bool apply (hb_ot_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04002290 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002291 TRACE_APPLY (this);
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05002292 unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002293 if (likely (index == NOT_COVERED)) return_trace (false);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002294
2295 const ClassDef &backtrack_class_def = this+backtrackClassDef;
2296 const ClassDef &input_class_def = this+inputClassDef;
2297 const ClassDef &lookahead_class_def = this+lookaheadClassDef;
2298
Behdad Esfahbod2dc11412012-11-24 19:16:34 -05002299 index = input_class_def.get_class (c->buffer->cur().codepoint);
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002300 const ChainRuleSet &rule_set = this+ruleSet[index];
Behdad Esfahbod31081f72012-04-23 16:54:58 -04002301 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05002302 {match_class},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04002303 {&backtrack_class_def,
2304 &input_class_def,
2305 &lookahead_class_def}
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002306 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002307 return_trace (rule_set.apply (c, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002308 }
2309
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302310 bool subset (hb_subset_context_t *c) const
Behdad Esfahbod339d3602018-09-03 17:33:34 -07002311 {
2312 TRACE_SUBSET (this);
2313 // TODO(subset)
2314 return_trace (false);
2315 }
2316
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302317 bool sanitize (hb_sanitize_context_t *c) const
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03002318 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002319 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002320 return_trace (coverage.sanitize (c, this) &&
2321 backtrackClassDef.sanitize (c, this) &&
2322 inputClassDef.sanitize (c, this) &&
2323 lookaheadClassDef.sanitize (c, this) &&
2324 ruleSet.sanitize (c, this));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002325 }
2326
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04002327 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +01002328 HBUINT16 format; /* Format identifier--format = 2 */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002329 OffsetTo<Coverage>
2330 coverage; /* Offset to Coverage table--from
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002331 * beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002332 OffsetTo<ClassDef>
2333 backtrackClassDef; /* Offset to glyph ClassDef table
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002334 * containing backtrack sequence
2335 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002336 OffsetTo<ClassDef>
2337 inputClassDef; /* Offset to glyph ClassDef
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002338 * table containing input sequence
2339 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002340 OffsetTo<ClassDef>
2341 lookaheadClassDef; /* Offset to glyph ClassDef table
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002342 * containing lookahead sequence
2343 * data--from beginning of table */
Behdad Esfahbodaa3d7ad2009-05-17 23:17:56 -04002344 OffsetArrayOf<ChainRuleSet>
2345 ruleSet; /* Array of ChainRuleSet tables
2346 * ordered by class */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04002347 public:
Behdad Esfahbod0eb9fc62010-05-10 19:01:17 -04002348 DEFINE_SIZE_ARRAY (12, ruleSet);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002349};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002350
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04002351struct ChainContextFormat3
2352{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302353 bool intersects (const hb_set_t *glyphs) const
Behdad Esfahbod7c9cfa22018-09-02 19:47:50 -07002354 {
2355 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
2356
2357 if (!(this+input[0]).intersects (glyphs))
2358 return false;
2359
2360 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2361 struct ChainContextClosureLookupContext lookup_context = {
2362 {intersects_coverage},
2363 {this, this, this}
2364 };
2365 return chain_context_intersects (glyphs,
2366 backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
2367 input.len, (const HBUINT16 *) input.arrayZ + 1,
2368 lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
2369 lookup_context);
2370 }
2371
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302372 void closure (hb_closure_context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04002373 {
Behdad Esfahbod5caece62012-04-23 23:03:12 -04002374 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
2375
2376 if (!(this+input[0]).intersects (c->glyphs))
2377 return;
2378
2379 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2380 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
2381 struct ChainContextClosureLookupContext lookup_context = {
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05002382 {intersects_coverage},
Behdad Esfahbod5caece62012-04-23 23:03:12 -04002383 {this, this, this}
2384 };
2385 chain_context_closure_lookup (c,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07002386 backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
2387 input.len, (const HBUINT16 *) input.arrayZ + 1,
2388 lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
2389 lookup.len, lookup.arrayZ,
Behdad Esfahbod5caece62012-04-23 23:03:12 -04002390 lookup_context);
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04002391 }
2392
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302393 void collect_glyphs (hb_collect_glyphs_context_t *c) const
Behdad Esfahbod26514d52012-11-23 18:13:48 -05002394 {
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05002395 TRACE_COLLECT_GLYPHS (this);
2396 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
2397
Behdad Esfahbod83035932012-12-04 17:08:41 -05002398 (this+input[0]).add_coverage (c->input);
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05002399
2400 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2401 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
2402 struct ChainContextCollectGlyphsLookupContext lookup_context = {
2403 {collect_coverage},
2404 {this, this, this}
2405 };
2406 chain_context_collect_glyphs_lookup (c,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07002407 backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
2408 input.len, (const HBUINT16 *) input.arrayZ + 1,
2409 lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
2410 lookup.len, lookup.arrayZ,
Behdad Esfahbodf1b12782012-11-24 01:55:34 -05002411 lookup_context);
Behdad Esfahbod26514d52012-11-23 18:13:48 -05002412 }
2413
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302414 bool would_apply (hb_would_apply_context_t *c) const
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002415 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002416 TRACE_WOULD_APPLY (this);
Behdad Esfahbode6f74792012-07-28 18:34:58 -04002417
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002418 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002419 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2420 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
2421 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05002422 {match_coverage},
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002423 {this, this, this}
2424 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002425 return_trace (chain_context_would_apply_lookup (c,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07002426 backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
2427 input.len, (const HBUINT16 *) input.arrayZ + 1,
2428 lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
2429 lookup.len, lookup.arrayZ, lookup_context));
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002430 }
2431
Ebrahim Byagowie4120082018-12-17 21:31:01 +03302432 const Coverage &get_coverage () const
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05002433 {
2434 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
2435 return this+input[0];
2436 }
2437
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302438 bool apply (hb_ot_apply_context_t *c) const
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04002439 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002440 TRACE_APPLY (this);
Behdad Esfahbode961c862010-04-21 15:56:11 -04002441 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04002442
Behdad Esfahbodb67881b2012-11-24 19:13:55 -05002443 unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002444 if (likely (index == NOT_COVERED)) return_trace (false);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002445
Behdad Esfahbode961c862010-04-21 15:56:11 -04002446 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2447 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbod31081f72012-04-23 16:54:58 -04002448 struct ChainContextApplyLookupContext lookup_context = {
Behdad Esfahbodec35a722012-11-22 16:05:59 -05002449 {match_coverage},
Behdad Esfahbod40cbefe2010-05-10 17:47:22 -04002450 {this, this, this}
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04002451 };
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002452 return_trace (chain_context_apply_lookup (c,
Behdad Esfahbod63f57f42018-05-08 16:56:11 -07002453 backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
2454 input.len, (const HBUINT16 *) input.arrayZ + 1,
2455 lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
2456 lookup.len, lookup.arrayZ, lookup_context));
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002457 }
2458
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302459 bool subset (hb_subset_context_t *c) const
Behdad Esfahbod339d3602018-09-03 17:33:34 -07002460 {
2461 TRACE_SUBSET (this);
2462 // TODO(subset)
2463 return_trace (false);
2464 }
2465
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302466 bool sanitize (hb_sanitize_context_t *c) const
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03002467 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002468 TRACE_SANITIZE (this);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002469 if (!backtrack.sanitize (c, this)) return_trace (false);
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03002470 const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002471 if (!input.sanitize (c, this)) return_trace (false);
2472 if (!input.len) return_trace (false); /* To be consistent with Context. */
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03002473 const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002474 if (!lookahead.sanitize (c, this)) return_trace (false);
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03002475 const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002476 return_trace (lookup.sanitize (c));
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002477 }
2478
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04002479 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +01002480 HBUINT16 format; /* Format identifier--format = 3 */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04002481 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04002482 backtrack; /* Array of coverage tables
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002483 * in backtracking sequence, in glyph
2484 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04002485 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04002486 inputX ; /* Array of coverage
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002487 * tables in input sequence, in glyph
2488 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04002489 OffsetArrayOf<Coverage>
Behdad Esfahbod13ed4402009-05-18 02:14:37 -04002490 lookaheadX; /* Array of coverage tables
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002491 * in lookahead sequence, in glyph
2492 * sequence order */
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04002493 ArrayOf<LookupRecord>
Behdad Esfahbod02e1e5c2009-05-18 02:47:57 -04002494 lookupX; /* Array of LookupRecords--in
Behdad Esfahboddcb6b602009-05-18 01:49:57 -04002495 * design order) */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04002496 public:
Behdad Esfahbodbea34c72010-05-10 17:28:16 -04002497 DEFINE_SIZE_MIN (10);
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002498};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002499
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04002500struct ChainContext
2501{
Behdad Esfahbod44fc2372012-11-21 23:33:13 -05002502 template <typename context_t>
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302503 typename context_t::return_t dispatch (context_t *c) const
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04002504 {
Behdad Esfahbod00f6a8e2014-12-12 20:36:49 -08002505 TRACE_DISPATCH (this, u.format);
Behdad Esfahbodf396fbb2015-10-09 12:25:55 -04002506 if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
Behdad Esfahbodf94b0aa2012-04-23 13:04:38 -04002507 switch (u.format) {
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002508 case 1: return_trace (c->dispatch (u.format1));
2509 case 2: return_trace (c->dispatch (u.format2));
2510 case 3: return_trace (c->dispatch (u.format3));
2511 default:return_trace (c->default_return_value ());
Behdad Esfahbode72b3602012-07-19 14:35:23 -04002512 }
2513 }
2514
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04002515 protected:
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002516 union {
Behdad Esfahbod6b191782018-01-10 03:07:30 +01002517 HBUINT16 format; /* Format identifier */
Behdad Esfahboddacebca2010-05-10 19:45:41 -04002518 ChainContextFormat1 format1;
2519 ChainContextFormat2 format2;
2520 ChainContextFormat3 format3;
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002521 } u;
2522};
Behdad Esfahbodca5290f2009-05-17 20:48:27 -04002523
2524
Behdad Esfahbod095a1252015-02-19 10:29:41 +03002525template <typename T>
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002526struct ExtensionFormat1
2527{
Ebrahim Byagowie4120082018-12-17 21:31:01 +03302528 unsigned int get_type () const { return extensionLookupType; }
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002529
Behdad Esfahbod095a1252015-02-19 10:29:41 +03002530 template <typename X>
Ebrahim Byagowie4120082018-12-17 21:31:01 +03302531 const X& get_subtable () const
Behdad Esfahbod095a1252015-02-19 10:29:41 +03002532 {
2533 unsigned int offset = extensionOffset;
Behdad Esfahbod9c3747c2018-09-03 16:53:03 -07002534 if (unlikely (!offset)) return Null(typename T::SubTable);
2535 return StructAtOffset<typename T::SubTable> (this, offset);
Behdad Esfahbod095a1252015-02-19 10:29:41 +03002536 }
2537
2538 template <typename context_t>
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302539 typename context_t::return_t dispatch (context_t *c) const
Behdad Esfahbod095a1252015-02-19 10:29:41 +03002540 {
2541 TRACE_DISPATCH (this, format);
Behdad Esfahbodf396fbb2015-10-09 12:25:55 -04002542 if (unlikely (!c->may_dispatch (this, this))) return_trace (c->no_dispatch_return_value ());
Behdad Esfahbod9c3747c2018-09-03 16:53:03 -07002543 return_trace (get_subtable<typename T::SubTable> ().dispatch (c, get_type ()));
Behdad Esfahbod095a1252015-02-19 10:29:41 +03002544 }
2545
2546 /* This is called from may_dispatch() above with hb_sanitize_context_t. */
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302547 bool sanitize (hb_sanitize_context_t *c) const
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03002548 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002549 TRACE_SANITIZE (this);
Behdad Esfahbod949f6af2018-01-15 20:44:10 -05002550 return_trace (c->check_struct (this) &&
2551 extensionOffset != 0 &&
Behdad Esfahbod9c3747c2018-09-03 16:53:03 -07002552 extensionLookupType != T::SubTable::Extension);
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002553 }
2554
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04002555 protected:
Behdad Esfahbod6b191782018-01-10 03:07:30 +01002556 HBUINT16 format; /* Format identifier. Set to 1. */
2557 HBUINT16 extensionLookupType; /* Lookup type of subtable referenced
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002558 * by ExtensionOffset (i.e. the
2559 * extension subtable). */
Behdad Esfahbodbcb6f1a2018-01-15 20:34:05 -05002560 HBUINT32 extensionOffset; /* Offset to the extension subtable,
Behdad Esfahbod81f2af42010-04-22 00:58:49 -04002561 * of lookup type subtable. */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04002562 public:
2563 DEFINE_SIZE_STATIC (8);
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002564};
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002565
Behdad Esfahbod653eeb22012-11-23 16:57:36 -05002566template <typename T>
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002567struct Extension
2568{
Ebrahim Byagowie4120082018-12-17 21:31:01 +03302569 unsigned int get_type () const
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002570 {
2571 switch (u.format) {
Behdad Esfahboddacebca2010-05-10 19:45:41 -04002572 case 1: return u.format1.get_type ();
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002573 default:return 0;
2574 }
2575 }
Behdad Esfahbod7dddd4e2012-11-23 17:04:55 -05002576 template <typename X>
Ebrahim Byagowie4120082018-12-17 21:31:01 +03302577 const X& get_subtable () const
Behdad Esfahbod7dddd4e2012-11-23 17:04:55 -05002578 {
Behdad Esfahbod095a1252015-02-19 10:29:41 +03002579 switch (u.format) {
Behdad Esfahbod9c3747c2018-09-03 16:53:03 -07002580 case 1: return u.format1.template get_subtable<typename T::SubTable> ();
2581 default:return Null(typename T::SubTable);
Behdad Esfahbod095a1252015-02-19 10:29:41 +03002582 }
Behdad Esfahbod7dddd4e2012-11-23 17:04:55 -05002583 }
2584
Behdad Esfahbod653eeb22012-11-23 16:57:36 -05002585 template <typename context_t>
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302586 typename context_t::return_t dispatch (context_t *c) const
Behdad Esfahbod653eeb22012-11-23 16:57:36 -05002587 {
Behdad Esfahbod095a1252015-02-19 10:29:41 +03002588 TRACE_DISPATCH (this, u.format);
Behdad Esfahbodf396fbb2015-10-09 12:25:55 -04002589 if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002590 switch (u.format) {
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002591 case 1: return_trace (u.format1.dispatch (c));
2592 default:return_trace (c->default_return_value ());
Behdad Esfahbod70de50c2009-08-04 00:58:28 -04002593 }
2594 }
2595
Behdad Esfahbodec8d2492012-07-24 15:40:37 -04002596 protected:
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002597 union {
Behdad Esfahbod6b191782018-01-10 03:07:30 +01002598 HBUINT16 format; /* Format identifier */
Behdad Esfahbod095a1252015-02-19 10:29:41 +03002599 ExtensionFormat1<T> format1;
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002600 } u;
2601};
Behdad Esfahbodd468f9a2009-05-21 22:31:33 -04002602
2603
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04002604/*
2605 * GSUB/GPOS Common
2606 */
2607
Behdad Esfahbod97e59132018-10-10 11:41:05 -04002608struct hb_ot_layout_lookup_accelerator_t
2609{
2610 template <typename TLookup>
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302611 void init (const TLookup &lookup)
Behdad Esfahbod97e59132018-10-10 11:41:05 -04002612 {
2613 digest.init ();
2614 lookup.add_coverage (&digest);
Behdad Esfahbod78c09bf2018-10-10 11:50:46 -04002615
2616 subtables.init ();
2617 OT::hb_get_subtables_context_t c_get_subtables (subtables);
2618 lookup.dispatch (&c_get_subtables);
Behdad Esfahbod97e59132018-10-10 11:41:05 -04002619 }
Ebrahim Byagowie4120082018-12-17 21:31:01 +03302620 void fini () { subtables.fini (); }
Behdad Esfahbod97e59132018-10-10 11:41:05 -04002621
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302622 bool may_have (hb_codepoint_t g) const
Behdad Esfahbod97e59132018-10-10 11:41:05 -04002623 { return digest.may_have (g); }
2624
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302625 bool apply (hb_ot_apply_context_t *c) const
Behdad Esfahbode78549e2018-10-10 11:54:48 -04002626 {
Behdad Esfahbod474a1202018-12-21 18:46:51 -05002627 for (unsigned int i = 0; i < subtables.length; i++)
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03302628 if (subtables[i].apply (c))
2629 return true;
2630 return false;
Behdad Esfahbode78549e2018-10-10 11:54:48 -04002631 }
2632
2633 private:
Behdad Esfahbod97e59132018-10-10 11:41:05 -04002634 hb_set_digest_t digest;
Behdad Esfahbod78c09bf2018-10-10 11:50:46 -04002635 hb_get_subtables_context_t::array_t subtables;
Behdad Esfahbod97e59132018-10-10 11:41:05 -04002636};
2637
Behdad Esfahbod60d77cf2009-05-19 23:58:54 -04002638struct GSUBGPOS
2639{
Ebrahim Byagowie4120082018-12-17 21:31:01 +03302640 bool has_data () const { return version.to_int (); }
2641 unsigned int get_script_count () const
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04002642 { return (this+scriptList).len; }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302643 const Tag& get_script_tag (unsigned int i) const
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04002644 { return (this+scriptList).get_tag (i); }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302645 unsigned int get_script_tags (unsigned int start_offset,
2646 unsigned int *script_count /* IN/OUT */,
2647 hb_tag_t *script_tags /* OUT */) const
Behdad Esfahbode21899b2009-11-04 16:36:14 -05002648 { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302649 const Script& get_script (unsigned int i) const
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04002650 { return (this+scriptList)[i]; }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302651 bool find_script_index (hb_tag_t tag, unsigned int *index) const
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04002652 { return (this+scriptList).find_index (tag, index); }
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04002653
Ebrahim Byagowie4120082018-12-17 21:31:01 +03302654 unsigned int get_feature_count () const
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04002655 { return (this+featureList).len; }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302656 hb_tag_t get_feature_tag (unsigned int i) const
Jonathan Kewda132932014-04-27 14:05:24 +01002657 { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302658 unsigned int get_feature_tags (unsigned int start_offset,
2659 unsigned int *feature_count /* IN/OUT */,
2660 hb_tag_t *feature_tags /* OUT */) const
Behdad Esfahbode21899b2009-11-04 16:36:14 -05002661 { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302662 const Feature& get_feature (unsigned int i) const
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04002663 { return (this+featureList)[i]; }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302664 bool find_feature_index (hb_tag_t tag, unsigned int *index) const
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04002665 { return (this+featureList).find_index (tag, index); }
2666
Ebrahim Byagowie4120082018-12-17 21:31:01 +03302667 unsigned int get_lookup_count () const
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04002668 { return (this+lookupList).len; }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302669 const Lookup& get_lookup (unsigned int i) const
Behdad Esfahbodbff3c0f2009-08-07 19:46:30 -04002670 { return (this+lookupList)[i]; }
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04002671
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302672 bool find_variations_index (const int *coords, unsigned int num_coords,
2673 unsigned int *index) const
Behdad Esfahbod59055b52016-09-10 01:24:28 -07002674 { return (version.to_int () >= 0x00010001u ? this+featureVars : Null(FeatureVariations))
Behdad Esfahbod30c42b62016-09-10 03:32:39 -07002675 .find_index (coords, num_coords, index); }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302676 const Feature& get_feature_variation (unsigned int feature_index,
Behdad Esfahbodec87ba92016-09-10 03:53:11 -07002677 unsigned int variations_index) const
2678 {
2679 if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
2680 version.to_int () >= 0x00010001u)
2681 {
Behdad Esfahbod4ebbeb72016-09-10 04:52:34 -07002682 const Feature *feature = (this+featureVars).find_substitute (variations_index,
2683 feature_index);
Behdad Esfahbodec87ba92016-09-10 03:53:11 -07002684 if (feature)
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03302685 return *feature;
Behdad Esfahbodec87ba92016-09-10 03:53:11 -07002686 }
2687 return get_feature (feature_index);
2688 }
Behdad Esfahbod59055b52016-09-10 01:24:28 -07002689
Behdad Esfahbod9c3747c2018-09-03 16:53:03 -07002690 template <typename TLookup>
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302691 bool subset (hb_subset_context_t *c) const
Behdad Esfahbodbfa72a92018-09-01 18:34:50 -07002692 {
2693 TRACE_SUBSET (this);
2694 struct GSUBGPOS *out = c->serializer->embed (*this);
2695 if (unlikely (!out)) return_trace (false);
Behdad Esfahbod1b6d0c42018-12-13 18:10:48 -05002696
Behdad Esfahbod49c44b52018-09-03 16:37:17 -07002697 out->scriptList.serialize_subset (c, this+scriptList, out);
2698 out->featureList.serialize_subset (c, this+featureList, out);
Behdad Esfahbod9c3747c2018-09-03 16:53:03 -07002699
2700 typedef OffsetListOf<TLookup> TLookupList;
2701 /* TODO Use intersects() to count how many subtables survive? */
2702 CastR<OffsetTo<TLookupList> > (out->lookupList)
2703 .serialize_subset (c,
2704 this+CastR<const OffsetTo<TLookupList> > (lookupList),
2705 out);
2706
Behdad Esfahbodbfa72a92018-09-01 18:34:50 -07002707 if (version.to_int () >= 0x00010001u)
Behdad Esfahbod49c44b52018-09-03 16:37:17 -07002708 out->featureVars.serialize_subset (c, this+featureVars, out);
Behdad Esfahbod1b6d0c42018-12-13 18:10:48 -05002709
Behdad Esfahbodbfa72a92018-09-01 18:34:50 -07002710 return_trace (true);
2711 }
2712
Ebrahim Byagowie4120082018-12-17 21:31:01 +03302713 unsigned int get_size () const
Behdad Esfahbodbfa72a92018-09-01 18:34:50 -07002714 {
2715 return min_size +
2716 (version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
2717 }
2718
Behdad Esfahbod6d618522018-09-03 16:41:28 -07002719 template <typename TLookup>
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302720 bool sanitize (hb_sanitize_context_t *c) const
Behdad Esfahbodde2118e2015-02-17 17:27:44 +03002721 {
Behdad Esfahbodbe218c62012-11-23 15:32:14 -05002722 TRACE_SANITIZE (this);
Behdad Esfahbod6d618522018-09-03 16:41:28 -07002723 typedef OffsetListOf<TLookup> TLookupList;
Behdad Esfahbodb4715902015-09-29 14:57:02 +01002724 return_trace (version.sanitize (c) &&
2725 likely (version.major == 1) &&
2726 scriptList.sanitize (c, this) &&
2727 featureList.sanitize (c, this) &&
Behdad Esfahbod6d618522018-09-03 16:41:28 -07002728 CastR<OffsetTo<TLookupList> > (lookupList).sanitize (c, this) &&
Behdad Esfahbod59055b52016-09-10 01:24:28 -07002729 (version.to_int () < 0x00010001u || featureVars.sanitize (c, this)));
Behdad Esfahbodcd3827e2009-08-04 02:09:34 -04002730 }
2731
Behdad Esfahbod963413f2018-08-26 00:47:55 -07002732 template <typename T>
2733 struct accelerator_t
2734 {
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03302735 void init (hb_face_t *face)
Behdad Esfahbod963413f2018-08-26 00:47:55 -07002736 {
Behdad Esfahbod5d0078a2018-11-10 23:52:15 -05002737 this->table = hb_sanitize_context_t().reference_table<T> (face);
Behdad Esfahbod574d8882018-11-25 16:51:22 -05002738 if (unlikely (this->table->is_blacklisted (this->table.get_blob (), face)))
2739 {
2740 hb_blob_destroy (this->table.get_blob ());
2741 this->table = hb_blob_get_empty ();
2742 }
Behdad Esfahbod963413f2018-08-26 00:47:55 -07002743
Behdad Esfahbodb9291002018-08-26 01:15:47 -07002744 this->lookup_count = table->get_lookup_count ();
Behdad Esfahbod963413f2018-08-26 00:47:55 -07002745
2746 this->accels = (hb_ot_layout_lookup_accelerator_t *) calloc (this->lookup_count, sizeof (hb_ot_layout_lookup_accelerator_t));
2747 if (unlikely (!this->accels))
Ebrahim Byagowi11aa0462018-11-15 23:10:56 +03302748 this->lookup_count = 0;
Behdad Esfahbod963413f2018-08-26 00:47:55 -07002749
2750 for (unsigned int i = 0; i < this->lookup_count; i++)
Behdad Esfahbodb9291002018-08-26 01:15:47 -07002751 this->accels[i].init (table->get_lookup (i));
Behdad Esfahbod963413f2018-08-26 00:47:55 -07002752 }
2753
Ebrahim Byagowie4120082018-12-17 21:31:01 +03302754 void fini ()
Behdad Esfahbod963413f2018-08-26 00:47:55 -07002755 {
Behdad Esfahbodb9291002018-08-26 01:15:47 -07002756 for (unsigned int i = 0; i < this->lookup_count; i++)
2757 this->accels[i].fini ();
2758 free (this->accels);
Behdad Esfahbodda6aa3b2018-11-11 11:40:57 -05002759 this->table.destroy ();
Behdad Esfahbod963413f2018-08-26 00:47:55 -07002760 }
2761
Behdad Esfahbod5d0078a2018-11-10 23:52:15 -05002762 hb_blob_ptr_t<T> table;
Behdad Esfahbodb9291002018-08-26 01:15:47 -07002763 unsigned int lookup_count;
2764 hb_ot_layout_lookup_accelerator_t *accels;
Behdad Esfahbod963413f2018-08-26 00:47:55 -07002765 };
2766
Behdad Esfahbod212aba62009-05-24 00:50:27 -04002767 protected:
Behdad Esfahbod9a13ed42016-02-22 11:44:45 +09002768 FixedVersion<>version; /* Version of the GSUB/GPOS table--initially set
Behdad Esfahbod76271002014-07-11 14:54:42 -04002769 * to 0x00010000u */
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04002770 OffsetTo<ScriptList>
2771 scriptList; /* ScriptList table */
2772 OffsetTo<FeatureList>
2773 featureList; /* FeatureList table */
2774 OffsetTo<LookupList>
2775 lookupList; /* LookupList table */
Behdad Esfahbod5e156fa2017-01-22 20:28:56 -08002776 LOffsetTo<FeatureVariations>
Behdad Esfahbod59055b52016-09-10 01:24:28 -07002777 featureVars; /* Offset to Feature Variations
2778 table--from beginning of table
2779 * (may be NULL). Introduced
2780 * in version 0x00010001. */
Behdad Esfahbodb3651232010-05-10 16:57:29 -04002781 public:
Behdad Esfahbod59055b52016-09-10 01:24:28 -07002782 DEFINE_SIZE_MIN (10);
Behdad Esfahbodf45107f2009-05-17 20:13:02 -04002783};
Behdad Esfahbod66bf7ce2009-05-17 08:28:42 -04002784
Behdad Esfahbod6f20f722009-05-17 20:28:01 -04002785
Behdad Esfahbod7d52e662012-11-16 18:49:54 -08002786} /* namespace OT */
Behdad Esfahbod7c8e8442012-08-28 17:57:49 -04002787
Behdad Esfahbodacdba3f2010-07-23 15:11:18 -04002788
Behdad Esfahbodc77ae402018-08-25 22:36:36 -07002789#endif /* HB_OT_LAYOUT_GSUBGPOS_HH */