166bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod/*
22409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
35b93e8d94fb4c2474816304ae3f52e1c704882deBehdad Esfahbod * Copyright © 2010,2012  Google, Inc.
466bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod *
5c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod *  This is part of HarfBuzz, a text shaping library.
666bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod *
766bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod * Permission is hereby granted, without written agreement and without
866bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
966bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod * software and its documentation for any purpose, provided that the
1066bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod * above copyright notice and the following two paragraphs appear in
1166bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod * all copies of this software.
1266bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod *
1366bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
1466bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
1566bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
1666bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
1766bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod * DAMAGE.
1866bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod *
1966bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
2066bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
2166bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
2266bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
2366bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
2466bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod *
2566bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod * Red Hat Author(s): Behdad Esfahbod
2698370e89d1bff248737b482d129c2a4deb8bfd95Behdad Esfahbod * Google Author(s): Behdad Esfahbod
2766bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod */
2866bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
295f5b24f99f52bbc922e238b65c06061ba07c8548Behdad Esfahbod#ifndef HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
305f5b24f99f52bbc922e238b65c06061ba07c8548Behdad Esfahbod#define HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH
3166bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
3222da7fd94d6318c52df69d70470a85464ffc533dBehdad Esfahbod#include "hb-buffer-private.hh"
337a750ac33ec482e2c4856c19ea607f3563741c24Behdad Esfahbod#include "hb-ot-layout-gdef-table.hh"
341336ecdf8e4e9879b96b26ecfbf5c9ba6c49e2b9Behdad Esfahbod#include "hb-set-private.hh"
35f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod
3666bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
377c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbodnamespace OT {
387c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod
39acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
40902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod
4100f6a8e334ec4c586e4e633a95b411ccb50306d3Behdad Esfahbod#define TRACE_DISPATCH(this, format) \
42a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod	hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
43a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
4400f6a8e334ec4c586e4e633a95b411ccb50306d3Behdad Esfahbod	 "format %d", (int) format);
45a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod
46f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod#ifndef HB_DEBUG_CLOSURE
47f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod#define HB_DEBUG_CLOSURE (HB_DEBUG+0)
48f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod#endif
49f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod
50be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod#define TRACE_CLOSURE(this) \
51130bb3f6144afe5c88bb5b4e4c98e7cba03b1e26Behdad Esfahbod	hb_auto_trace_t<HB_DEBUG_CLOSURE, hb_void_t> trace \
522c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
53902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod	 "");
54f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod
55f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbodstruct hb_closure_context_t
56f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod{
57a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod  inline const char *get_name (void) { return "CLOSURE"; }
58a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod  static const unsigned int max_debug_depth = HB_DEBUG_CLOSURE;
59130bb3f6144afe5c88bb5b4e4c98e7cba03b1e26Behdad Esfahbod  typedef hb_void_t return_t;
6044fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned int lookup_index);
6144fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  template <typename T>
629c5a9ee967120c8a968a1160c420e03620d46c24Behdad Esfahbod  inline return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; }
63130bb3f6144afe5c88bb5b4e4c98e7cba03b1e26Behdad Esfahbod  static return_t default_return_value (void) { return HB_VOID; }
647b912c1936c3e8a7df27a30782ca127d0a83822dBehdad Esfahbod  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
6544fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  return_t recurse (unsigned int lookup_index)
6644fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  {
679b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod    if (unlikely (nesting_level_left == 0 || !recurse_func))
682005fa5340fc528c32dc2af945ad2431964a47d2Behdad Esfahbod      return default_return_value ();
6944fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod
7044fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod    nesting_level_left--;
7144fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod    recurse_func (this, lookup_index);
7244fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod    nesting_level_left++;
73130bb3f6144afe5c88bb5b4e4c98e7cba03b1e26Behdad Esfahbod    return HB_VOID;
7444fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  }
7544fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod
76f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod  hb_face_t *face;
776a9be5bd3524dc3eb1e88d1063bde2e4d8b57011Behdad Esfahbod  hb_set_t *glyphs;
7844fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  recurse_func_t recurse_func;
79f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod  unsigned int nesting_level_left;
80f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod  unsigned int debug_depth;
81f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod
82f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod  hb_closure_context_t (hb_face_t *face_,
836a9be5bd3524dc3eb1e88d1063bde2e4d8b57011Behdad Esfahbod			hb_set_t *glyphs_,
84f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod		        unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
85e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod			  face (face_),
86e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod			  glyphs (glyphs_),
879b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod			  recurse_func (NULL),
88f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod			  nesting_level_left (nesting_level_left_),
89f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod			  debug_depth (0) {}
909b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod
919b34677f362fb0ef5a7cb8a284a9e06d1a4cc03bBehdad Esfahbod  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
92f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod};
93f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod
94f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod
95f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod
96472f229a63f0d1bb21b02179ef430b7698df8f12Behdad Esfahbod#ifndef HB_DEBUG_WOULD_APPLY
97472f229a63f0d1bb21b02179ef430b7698df8f12Behdad Esfahbod#define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
98472f229a63f0d1bb21b02179ef430b7698df8f12Behdad Esfahbod#endif
99472f229a63f0d1bb21b02179ef430b7698df8f12Behdad Esfahbod
100be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod#define TRACE_WOULD_APPLY(this) \
101902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod	hb_auto_trace_t<HB_DEBUG_WOULD_APPLY, bool> trace \
1022c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
103902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod	 "%d glyphs", c->len);
104e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
105e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbodstruct hb_would_apply_context_t
106e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod{
107a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod  inline const char *get_name (void) { return "WOULD_APPLY"; }
108a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod  static const unsigned int max_debug_depth = HB_DEBUG_WOULD_APPLY;
1091d67ef980f35ae30d4f8975f65ee07b8cc5deeeaBehdad Esfahbod  typedef bool return_t;
1101d67ef980f35ae30d4f8975f65ee07b8cc5deeeaBehdad Esfahbod  template <typename T>
1119c5a9ee967120c8a968a1160c420e03620d46c24Behdad Esfahbod  inline return_t dispatch (const T &obj) { return obj.would_apply (this); }
1121d67ef980f35ae30d4f8975f65ee07b8cc5deeeaBehdad Esfahbod  static return_t default_return_value (void) { return false; }
1137b912c1936c3e8a7df27a30782ca127d0a83822dBehdad Esfahbod  bool stop_sublookup_iteration (return_t r) const { return r; }
1141d67ef980f35ae30d4f8975f65ee07b8cc5deeeaBehdad Esfahbod
115e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  hb_face_t *face;
116472f229a63f0d1bb21b02179ef430b7698df8f12Behdad Esfahbod  const hb_codepoint_t *glyphs;
117e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  unsigned int len;
118d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod  bool zero_context;
119e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  unsigned int debug_depth;
120e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
121e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  hb_would_apply_context_t (hb_face_t *face_,
122472f229a63f0d1bb21b02179ef430b7698df8f12Behdad Esfahbod			    const hb_codepoint_t *glyphs_,
123472f229a63f0d1bb21b02179ef430b7698df8f12Behdad Esfahbod			    unsigned int len_,
1242bd9fe359839a653f7caae534bf768af1735f155Behdad Esfahbod			    bool zero_context_) :
125e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod			      face (face_),
126472f229a63f0d1bb21b02179ef430b7698df8f12Behdad Esfahbod			      glyphs (glyphs_),
127472f229a63f0d1bb21b02179ef430b7698df8f12Behdad Esfahbod			      len (len_),
128d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod			      zero_context (zero_context_),
129a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod			      debug_depth (0) {}
130e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod};
131e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
132e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
133e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
134e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod#ifndef HB_DEBUG_COLLECT_GLYPHS
135e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod#define HB_DEBUG_COLLECT_GLYPHS (HB_DEBUG+0)
136e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod#endif
137e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
138be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod#define TRACE_COLLECT_GLYPHS(this) \
139130bb3f6144afe5c88bb5b4e4c98e7cba03b1e26Behdad Esfahbod	hb_auto_trace_t<HB_DEBUG_COLLECT_GLYPHS, hb_void_t> trace \
1402c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
141902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod	 "");
142e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
143e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbodstruct hb_collect_glyphs_context_t
144e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod{
145a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod  inline const char *get_name (void) { return "COLLECT_GLYPHS"; }
146a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod  static const unsigned int max_debug_depth = HB_DEBUG_COLLECT_GLYPHS;
147130bb3f6144afe5c88bb5b4e4c98e7cba03b1e26Behdad Esfahbod  typedef hb_void_t return_t;
14826514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
1491d67ef980f35ae30d4f8975f65ee07b8cc5deeeaBehdad Esfahbod  template <typename T>
1509c5a9ee967120c8a968a1160c420e03620d46c24Behdad Esfahbod  inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
151130bb3f6144afe5c88bb5b4e4c98e7cba03b1e26Behdad Esfahbod  static return_t default_return_value (void) { return HB_VOID; }
1527b912c1936c3e8a7df27a30782ca127d0a83822dBehdad Esfahbod  bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
1531d67ef980f35ae30d4f8975f65ee07b8cc5deeeaBehdad Esfahbod  return_t recurse (unsigned int lookup_index)
1541d67ef980f35ae30d4f8975f65ee07b8cc5deeeaBehdad Esfahbod  {
15526514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod    if (unlikely (nesting_level_left == 0 || !recurse_func))
15626514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod      return default_return_value ();
15726514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod
1581bcfa06d1173f219809542a7380ce77f1c907becBehdad Esfahbod    /* Note that GPOS sets recurse_func to NULL already, so it doesn't get
1591bcfa06d1173f219809542a7380ce77f1c907becBehdad Esfahbod     * past the previous check.  For GSUB, we only want to collect the output
16076ea563673d24ae1673a5aa3a21da6014479d433Behdad Esfahbod     * glyphs in the recursion.  If output is not requested, we can go home now.
16176ea563673d24ae1673a5aa3a21da6014479d433Behdad Esfahbod     *
16276ea563673d24ae1673a5aa3a21da6014479d433Behdad Esfahbod     * Note further, that the above is not exactly correct.  A recursed lookup
16376ea563673d24ae1673a5aa3a21da6014479d433Behdad Esfahbod     * is allowed to match input that is not matched in the context, but that's
16476ea563673d24ae1673a5aa3a21da6014479d433Behdad Esfahbod     * not how most fonts are built.  It's possible to relax that and recurse
16576ea563673d24ae1673a5aa3a21da6014479d433Behdad Esfahbod     * with all sets here if it proves to be an issue.
16676ea563673d24ae1673a5aa3a21da6014479d433Behdad Esfahbod     */
1674a350d0eb25db60d95638664c892d4c8dacf050bBehdad Esfahbod
1684a350d0eb25db60d95638664c892d4c8dacf050bBehdad Esfahbod    if (output == hb_set_get_empty ())
169130bb3f6144afe5c88bb5b4e4c98e7cba03b1e26Behdad Esfahbod      return HB_VOID;
1704a350d0eb25db60d95638664c892d4c8dacf050bBehdad Esfahbod
171fde3e4a423871463c883cb969e99c29cb6f69f6bBehdad Esfahbod    /* Return if new lookup was recursed to before. */
172fde3e4a423871463c883cb969e99c29cb6f69f6bBehdad Esfahbod    if (recursed_lookups.has (lookup_index))
173fde3e4a423871463c883cb969e99c29cb6f69f6bBehdad Esfahbod      return HB_VOID;
174fde3e4a423871463c883cb969e99c29cb6f69f6bBehdad Esfahbod
1754a350d0eb25db60d95638664c892d4c8dacf050bBehdad Esfahbod    hb_set_t *old_before = before;
1764a350d0eb25db60d95638664c892d4c8dacf050bBehdad Esfahbod    hb_set_t *old_input  = input;
1774a350d0eb25db60d95638664c892d4c8dacf050bBehdad Esfahbod    hb_set_t *old_after  = after;
1784a350d0eb25db60d95638664c892d4c8dacf050bBehdad Esfahbod    before = input = after = hb_set_get_empty ();
1791bcfa06d1173f219809542a7380ce77f1c907becBehdad Esfahbod
18026514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod    nesting_level_left--;
1814a350d0eb25db60d95638664c892d4c8dacf050bBehdad Esfahbod    recurse_func (this, lookup_index);
18226514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod    nesting_level_left++;
1834a350d0eb25db60d95638664c892d4c8dacf050bBehdad Esfahbod
1844a350d0eb25db60d95638664c892d4c8dacf050bBehdad Esfahbod    before = old_before;
1854a350d0eb25db60d95638664c892d4c8dacf050bBehdad Esfahbod    input  = old_input;
1864a350d0eb25db60d95638664c892d4c8dacf050bBehdad Esfahbod    after  = old_after;
1874a350d0eb25db60d95638664c892d4c8dacf050bBehdad Esfahbod
188fde3e4a423871463c883cb969e99c29cb6f69f6bBehdad Esfahbod    recursed_lookups.add (lookup_index);
189fde3e4a423871463c883cb969e99c29cb6f69f6bBehdad Esfahbod
190130bb3f6144afe5c88bb5b4e4c98e7cba03b1e26Behdad Esfahbod    return HB_VOID;
1911d67ef980f35ae30d4f8975f65ee07b8cc5deeeaBehdad Esfahbod  }
1921d67ef980f35ae30d4f8975f65ee07b8cc5deeeaBehdad Esfahbod
193e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod  hb_face_t *face;
1948303593ba1db06e402eab52df47f21f13049112dBehdad Esfahbod  hb_set_t *before;
1958303593ba1db06e402eab52df47f21f13049112dBehdad Esfahbod  hb_set_t *input;
1968303593ba1db06e402eab52df47f21f13049112dBehdad Esfahbod  hb_set_t *after;
1978303593ba1db06e402eab52df47f21f13049112dBehdad Esfahbod  hb_set_t *output;
19826514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  recurse_func_t recurse_func;
199fde3e4a423871463c883cb969e99c29cb6f69f6bBehdad Esfahbod  hb_set_t recursed_lookups;
20026514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  unsigned int nesting_level_left;
201e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod  unsigned int debug_depth;
202e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
203e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod  hb_collect_glyphs_context_t (hb_face_t *face_,
204e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod			       hb_set_t  *glyphs_before, /* OUT. May be NULL */
205e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod			       hb_set_t  *glyphs_input,  /* OUT. May be NULL */
206e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod			       hb_set_t  *glyphs_after,  /* OUT. May be NULL */
20726514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod			       hb_set_t  *glyphs_output, /* OUT. May be NULL */
20826514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod			       unsigned int nesting_level_left_ = MAX_NESTING_LEVEL) :
209e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod			      face (face_),
2108303593ba1db06e402eab52df47f21f13049112dBehdad Esfahbod			      before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
2118303593ba1db06e402eab52df47f21f13049112dBehdad Esfahbod			      input  (glyphs_input  ? glyphs_input  : hb_set_get_empty ()),
2128303593ba1db06e402eab52df47f21f13049112dBehdad Esfahbod			      after  (glyphs_after  ? glyphs_after  : hb_set_get_empty ()),
2138303593ba1db06e402eab52df47f21f13049112dBehdad Esfahbod			      output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
21426514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod			      recurse_func (NULL),
215fde3e4a423871463c883cb969e99c29cb6f69f6bBehdad Esfahbod			      recursed_lookups (),
21626514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod			      nesting_level_left (nesting_level_left_),
217fde3e4a423871463c883cb969e99c29cb6f69f6bBehdad Esfahbod			      debug_depth (0)
218fde3e4a423871463c883cb969e99c29cb6f69f6bBehdad Esfahbod  {
219fde3e4a423871463c883cb969e99c29cb6f69f6bBehdad Esfahbod    recursed_lookups.init ();
220fde3e4a423871463c883cb969e99c29cb6f69f6bBehdad Esfahbod  }
221fde3e4a423871463c883cb969e99c29cb6f69f6bBehdad Esfahbod  ~hb_collect_glyphs_context_t (void)
222fde3e4a423871463c883cb969e99c29cb6f69f6bBehdad Esfahbod  {
223fde3e4a423871463c883cb969e99c29cb6f69f6bBehdad Esfahbod    recursed_lookups.fini ();
224fde3e4a423871463c883cb969e99c29cb6f69f6bBehdad Esfahbod  }
22526514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod
22626514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
227e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod};
228e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
229e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
230e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod
231295ef1dd5229f47d8e0eb5b4eb48c90a6b470073Behdad Esfahbod#ifndef HB_DEBUG_GET_COVERAGE
232295ef1dd5229f47d8e0eb5b4eb48c90a6b470073Behdad Esfahbod#define HB_DEBUG_GET_COVERAGE (HB_DEBUG+0)
233295ef1dd5229f47d8e0eb5b4eb48c90a6b470073Behdad Esfahbod#endif
234295ef1dd5229f47d8e0eb5b4eb48c90a6b470073Behdad Esfahbod
2352005fa5340fc528c32dc2af945ad2431964a47d2Behdad Esfahbodstruct hb_get_coverage_context_t
2362005fa5340fc528c32dc2af945ad2431964a47d2Behdad Esfahbod{
237a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod  inline const char *get_name (void) { return "GET_COVERAGE"; }
238295ef1dd5229f47d8e0eb5b4eb48c90a6b470073Behdad Esfahbod  static const unsigned int max_debug_depth = HB_DEBUG_GET_COVERAGE;
2392005fa5340fc528c32dc2af945ad2431964a47d2Behdad Esfahbod  typedef const Coverage &return_t;
2402005fa5340fc528c32dc2af945ad2431964a47d2Behdad Esfahbod  template <typename T>
2419c5a9ee967120c8a968a1160c420e03620d46c24Behdad Esfahbod  inline return_t dispatch (const T &obj) { return obj.get_coverage (); }
242a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod  static return_t default_return_value (void) { return Null(Coverage); }
2431d67ef980f35ae30d4f8975f65ee07b8cc5deeeaBehdad Esfahbod
244a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod  hb_get_coverage_context_t (void) :
245a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod			    debug_depth (0) {}
246a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod
247a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod  unsigned int debug_depth;
2482005fa5340fc528c32dc2af945ad2431964a47d2Behdad Esfahbod};
2492005fa5340fc528c32dc2af945ad2431964a47d2Behdad Esfahbod
2502005fa5340fc528c32dc2af945ad2431964a47d2Behdad Esfahbod
2512005fa5340fc528c32dc2af945ad2431964a47d2Behdad Esfahbod
2520535b50f436f3dac85e6df1761957f86c2bd7213Behdad Esfahbod#ifndef HB_DEBUG_APPLY
25311e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod#define HB_DEBUG_APPLY (HB_DEBUG+0)
2540535b50f436f3dac85e6df1761957f86c2bd7213Behdad Esfahbod#endif
2550535b50f436f3dac85e6df1761957f86c2bd7213Behdad Esfahbod
256be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod#define TRACE_APPLY(this) \
257902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod	hb_auto_trace_t<HB_DEBUG_APPLY, bool> trace \
2582c53bd3c3ec4f81eff126c5bf84b7f2ddf2f0fefBehdad Esfahbod	(&c->debug_depth, c->get_name (), this, HB_FUNC, \
259902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod	 "idx %d codepoint %u", c->buffer->idx, c->buffer->cur().codepoint);
2600535b50f436f3dac85e6df1761957f86c2bd7213Behdad Esfahbod
2611376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbodstruct hb_apply_context_t
2621376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbod{
263a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod  inline const char *get_name (void) { return "APPLY"; }
264a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod  static const unsigned int max_debug_depth = HB_DEBUG_APPLY;
265ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod  typedef bool return_t;
266ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod  typedef return_t (*recurse_func_t) (hb_apply_context_t *c, unsigned int lookup_index);
267ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod  template <typename T>
2689c5a9ee967120c8a968a1160c420e03620d46c24Behdad Esfahbod  inline return_t dispatch (const T &obj) { return obj.apply (this); }
269dabe698fcbeb02911128b17aa8e3b2d864795960Behdad Esfahbod  static return_t default_return_value (void) { return false; }
2707b912c1936c3e8a7df27a30782ca127d0a83822dBehdad Esfahbod  bool stop_sublookup_iteration (return_t r) const { return r; }
271ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod  return_t recurse (unsigned int lookup_index)
272ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod  {
273ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod    if (unlikely (nesting_level_left == 0 || !recurse_func))
274ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod      return default_return_value ();
275ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod
2764c4e8f0e754b79ac6190d21878eaaf0b790c7579Behdad Esfahbod    nesting_level_left--;
277f18ff5a84d9fe859c40a7a0c9a207cb40df0e84aBehdad Esfahbod    bool ret = recurse_func (this, lookup_index);
2784c4e8f0e754b79ac6190d21878eaaf0b790c7579Behdad Esfahbod    nesting_level_left++;
279f18ff5a84d9fe859c40a7a0c9a207cb40df0e84aBehdad Esfahbod    return ret;
280ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod  }
281ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod
2826880f7e19d44c50e45ecb86d26381aad956d9acbBehdad Esfahbod  unsigned int table_index; /* GSUB/GPOS */
283abcfe9b59b4475eb02dd679aac4bc59616713b28Behdad Esfahbod  hb_font_t *font;
284abcfe9b59b4475eb02dd679aac4bc59616713b28Behdad Esfahbod  hb_face_t *face;
28594a23aaeca39c662614037ef887412249bdc8d49Behdad Esfahbod  hb_buffer_t *buffer;
286744970af4d884cc87ffa645804578fec8df674a9Behdad Esfahbod  hb_direction_t direction;
287f7acd8df5146155b51d6f50aeb04f54f3030c1c3Behdad Esfahbod  hb_mask_t lookup_mask;
288a8cf7b43fa795150ae3d42d64424bb6e0373d0b2Behdad Esfahbod  bool auto_zwj;
289ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod  recurse_func_t recurse_func;
2901376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbod  unsigned int nesting_level_left;
2918c69e65abed961002d90024c92e18538c6516262Behdad Esfahbod  unsigned int lookup_props;
29205bd1b63426e07d1df7a1b40bf845dc94ab995a8Behdad Esfahbod  const GDEF &gdef;
293300c7307eb7943ba7416b672345506be1e27c6baBehdad Esfahbod  bool has_glyph_classes;
294a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod  unsigned int debug_depth;
29598370e89d1bff248737b482d129c2a4deb8bfd95Behdad Esfahbod
29641ae674f6871f43d0a6e4ca67a747074d63ae576Behdad Esfahbod
2976880f7e19d44c50e45ecb86d26381aad956d9acbBehdad Esfahbod  hb_apply_context_t (unsigned int table_index_,
2986880f7e19d44c50e45ecb86d26381aad956d9acbBehdad Esfahbod		      hb_font_t *font_,
299bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod		      hb_buffer_t *buffer_) :
3006880f7e19d44c50e45ecb86d26381aad956d9acbBehdad Esfahbod			table_index (table_index_),
301afbcc24be01a64bdb5c05c63880269145fa1d3c8Behdad Esfahbod			font (font_), face (font->face), buffer (buffer_),
30241ae674f6871f43d0a6e4ca67a747074d63ae576Behdad Esfahbod			direction (buffer_->props.direction),
303bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod			lookup_mask (1),
304bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod			auto_zwj (true),
305ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod			recurse_func (NULL),
3066736f3c5b09af6a71935afc04248b033e171a9b2Behdad Esfahbod			nesting_level_left (MAX_NESTING_LEVEL),
307407fc12466ef460d0edf11b89f0d04c4d724875fBehdad Esfahbod			lookup_props (0),
308afbcc24be01a64bdb5c05c63880269145fa1d3c8Behdad Esfahbod			gdef (*hb_ot_layout_from_face (face)->gdef),
309a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod			has_glyph_classes (gdef.has_glyph_classes ()),
310a1733db1c6ff40aae71fa142a12b1fea7b53dd37Behdad Esfahbod			debug_depth (0) {}
31141ae674f6871f43d0a6e4ca67a747074d63ae576Behdad Esfahbod
312bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  inline void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; }
313bac1dd6a0ff4d4fae4254506d38ae662b7e9dda7Behdad Esfahbod  inline void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; }
314c074ebc466dcc9bcc0d8a5dd7e942dea974ff718Behdad Esfahbod  inline void set_recurse_func (recurse_func_t func) { recurse_func = func; }
315c074ebc466dcc9bcc0d8a5dd7e942dea974ff718Behdad Esfahbod  inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
316c074ebc466dcc9bcc0d8a5dd7e942dea974ff718Behdad Esfahbod  inline void set_lookup (const Lookup &l) { lookup_props = l.get_props (); }
31741ae674f6871f43d0a6e4ca67a747074d63ae576Behdad Esfahbod
318607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod  struct matcher_t
3194ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod  {
320607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    inline matcher_t (void) :
321607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	     lookup_props (0),
322cfc507c5432e6327e8484b07b9e091212653bc92Behdad Esfahbod	     ignore_zwnj (false),
323cfc507c5432e6327e8484b07b9e091212653bc92Behdad Esfahbod	     ignore_zwj (false),
324607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	     mask (-1),
325607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod#define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
326607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	     syllable arg1(0),
327607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod#undef arg1
328607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	     match_func (NULL),
329607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	     match_data (NULL) {};
330607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
331607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
332607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
333607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    inline void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
3340b45479198d61d5135dad771e9c68408eb13f930Behdad Esfahbod    inline void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
335607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    inline void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
336607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    inline void set_mask (hb_mask_t mask_) { mask = mask_; }
337607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    inline void set_syllable (uint8_t syllable_)  { syllable = syllable_; }
338607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    inline void set_match_func (match_func_t match_func_,
339607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod				const void *match_data_)
340607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    { match_func = match_func_; match_data = match_data_; }
341607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
3422b2a6e8944144755ab641f2842e36d9a847719f3Behdad Esfahbod    enum may_match_t {
3432b2a6e8944144755ab641f2842e36d9a847719f3Behdad Esfahbod      MATCH_NO,
3442b2a6e8944144755ab641f2842e36d9a847719f3Behdad Esfahbod      MATCH_YES,
3452b2a6e8944144755ab641f2842e36d9a847719f3Behdad Esfahbod      MATCH_MAYBE
3462b2a6e8944144755ab641f2842e36d9a847719f3Behdad Esfahbod    };
3472b2a6e8944144755ab641f2842e36d9a847719f3Behdad Esfahbod
3482b2a6e8944144755ab641f2842e36d9a847719f3Behdad Esfahbod    inline may_match_t may_match (const hb_glyph_info_t &info,
3492b2a6e8944144755ab641f2842e36d9a847719f3Behdad Esfahbod				  const USHORT          *glyph_data) const
3504ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod    {
3512b2a6e8944144755ab641f2842e36d9a847719f3Behdad Esfahbod      if (!(info.mask & mask) ||
3522b2a6e8944144755ab641f2842e36d9a847719f3Behdad Esfahbod	  (syllable && syllable != info.syllable ()))
3532b2a6e8944144755ab641f2842e36d9a847719f3Behdad Esfahbod	return MATCH_NO;
3542b2a6e8944144755ab641f2842e36d9a847719f3Behdad Esfahbod
3552b2a6e8944144755ab641f2842e36d9a847719f3Behdad Esfahbod      if (match_func)
3562b2a6e8944144755ab641f2842e36d9a847719f3Behdad Esfahbod        return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
3572b2a6e8944144755ab641f2842e36d9a847719f3Behdad Esfahbod
3582b2a6e8944144755ab641f2842e36d9a847719f3Behdad Esfahbod      return MATCH_MAYBE;
3594ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod    }
360607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
361607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    enum may_skip_t {
362607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod      SKIP_NO,
363607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod      SKIP_YES,
364607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod      SKIP_MAYBE
365607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    };
366607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
367607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    inline may_skip_t
368607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    may_skip (const hb_apply_context_t *c,
369607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	      const hb_glyph_info_t    &info) const
370c074ebc466dcc9bcc0d8a5dd7e942dea974ff718Behdad Esfahbod    {
371b98c5db32d15fcfb27ce2f6737203ce1ad124319Behdad Esfahbod      if (!c->check_glyph_property (&info, lookup_props))
372607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	return SKIP_YES;
373607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
3740b45479198d61d5135dad771e9c68408eb13f930Behdad Esfahbod      if (unlikely (_hb_glyph_info_is_default_ignorable (&info) &&
3750b45479198d61d5135dad771e9c68408eb13f930Behdad Esfahbod		    (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
3760b45479198d61d5135dad771e9c68408eb13f930Behdad Esfahbod		    (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) &&
377a1f7b2856184959e965c9c2b80363f9f46d486a7Behdad Esfahbod		    !_hb_glyph_info_ligated (&info)))
378607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	return SKIP_MAYBE;
379607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
380607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod      return SKIP_NO;
381c074ebc466dcc9bcc0d8a5dd7e942dea974ff718Behdad Esfahbod    }
382607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
383607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    protected:
384607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    unsigned int lookup_props;
385607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    bool ignore_zwnj;
3860b45479198d61d5135dad771e9c68408eb13f930Behdad Esfahbod    bool ignore_zwj;
387607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    hb_mask_t mask;
388607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    uint8_t syllable;
389607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    match_func_t match_func;
390607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    const void *match_data;
391607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod  };
392607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
393607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod  struct skipping_forward_iterator_t
394607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod  {
395607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    inline skipping_forward_iterator_t (hb_apply_context_t *c_,
396607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod					unsigned int start_index_,
397607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod					unsigned int num_items_,
398607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod					bool context_match = false) :
399607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod					 idx (start_index_),
400607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod					 c (c_),
401607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod					 match_glyph_data (NULL),
402607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod					 num_items (num_items_),
403607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod					 end (c->buffer->len)
4044ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod    {
405607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod      matcher.set_lookup_props (c->lookup_props);
406a8cf7b43fa795150ae3d42d64424bb6e0373d0b2Behdad Esfahbod      /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */
407a8cf7b43fa795150ae3d42d64424bb6e0373d0b2Behdad Esfahbod      matcher.set_ignore_zwnj (context_match || c->table_index == 1);
408a8cf7b43fa795150ae3d42d64424bb6e0373d0b2Behdad Esfahbod      /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */
409a8cf7b43fa795150ae3d42d64424bb6e0373d0b2Behdad Esfahbod      matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zwj);
410607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod      if (!context_match)
411cfc507c5432e6327e8484b07b9e091212653bc92Behdad Esfahbod	matcher.set_mask (c->lookup_mask);
412cb90b1bbe6d27ca6968b70d2dbfea7ab7fb73293Behdad Esfahbod      matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
4134ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod    }
414607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); }
415607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syllable); }
416607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    inline void set_match_func (matcher_t::match_func_t match_func,
417607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod				const void *match_data,
418607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod				const USHORT glyph_data[])
4197b84c536c10ab90ed96a033d88e9ad232d46c5b8Behdad Esfahbod    {
420607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod      matcher.set_match_func (match_func, match_data);
421607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod      match_glyph_data = glyph_data;
4227b84c536c10ab90ed96a033d88e9ad232d46c5b8Behdad Esfahbod    }
423607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
424607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    inline bool has_no_chance (void) const { return unlikely (num_items && idx + num_items >= end); }
425607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    inline void reject (void) { num_items++; match_glyph_data--; }
426c074ebc466dcc9bcc0d8a5dd7e942dea974ff718Behdad Esfahbod    inline bool next (void)
4274ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod    {
428506ffeb8e77a668fa305139582d215c32e46bb03Behdad Esfahbod      assert (num_items > 0);
429607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod      while (!has_no_chance ())
4304ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod      {
431a4a48fe6d4f884a37e720430347d10dbe3562a79Behdad Esfahbod	idx++;
432607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	const hb_glyph_info_t &info = c->buffer->info[idx];
433607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
434ff93ac8cb24cbc3d9dc1a2bfb0faa88950f4a507Behdad Esfahbod	matcher_t::may_skip_t skip = matcher.may_skip (c, info);
435607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	if (unlikely (skip == matcher_t::SKIP_YES))
436607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	  continue;
437607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
4382b2a6e8944144755ab641f2842e36d9a847719f3Behdad Esfahbod	matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
439722e8b857eafc52e07dee5d9b253b88ed5c5c8edBehdad Esfahbod	if (match == matcher_t::MATCH_YES ||
440722e8b857eafc52e07dee5d9b253b88ed5c5c8edBehdad Esfahbod	    (match == matcher_t::MATCH_MAYBE &&
441722e8b857eafc52e07dee5d9b253b88ed5c5c8edBehdad Esfahbod	     skip == matcher_t::SKIP_NO))
442607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	{
443607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	  num_items--;
444607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	  match_glyph_data++;
445607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	  return true;
446607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	}
447607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
448607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	if (skip == matcher_t::SKIP_NO)
449722e8b857eafc52e07dee5d9b253b88ed5c5c8edBehdad Esfahbod	  return false;
450607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod      }
451607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod      return false;
4524ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod    }
4534ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod
4544ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod    unsigned int idx;
455ec8d2494694275dfbbac2dd0d33ca2894b0463d6Behdad Esfahbod    protected:
4564ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod    hb_apply_context_t *c;
457607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    matcher_t matcher;
458607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    const USHORT *match_glyph_data;
459607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
4604ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod    unsigned int num_items;
4614ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod    unsigned int end;
4624ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod  };
4634ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod
4649082efc4aacb34de8574d6a4a3c037987df58bd8Behdad Esfahbod  struct skipping_backward_iterator_t
4654ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod  {
4669082efc4aacb34de8574d6a4a3c037987df58bd8Behdad Esfahbod    inline skipping_backward_iterator_t (hb_apply_context_t *c_,
4679082efc4aacb34de8574d6a4a3c037987df58bd8Behdad Esfahbod					 unsigned int start_index_,
4689082efc4aacb34de8574d6a4a3c037987df58bd8Behdad Esfahbod					 unsigned int num_items_,
469607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod					 bool context_match = false) :
470607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod					  idx (start_index_),
471607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod					  c (c_),
472607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod					  match_glyph_data (NULL),
473607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod					  num_items (num_items_)
474c074ebc466dcc9bcc0d8a5dd7e942dea974ff718Behdad Esfahbod    {
475607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod      matcher.set_lookup_props (c->lookup_props);
476a8cf7b43fa795150ae3d42d64424bb6e0373d0b2Behdad Esfahbod      /* Ignore ZWNJ if we are matching GSUB context, or matching GPOS. */
477a8cf7b43fa795150ae3d42d64424bb6e0373d0b2Behdad Esfahbod      matcher.set_ignore_zwnj (context_match || c->table_index == 1);
478a8cf7b43fa795150ae3d42d64424bb6e0373d0b2Behdad Esfahbod      /* Ignore ZWJ if we are matching GSUB context, or matching GPOS, or if asked to. */
479a8cf7b43fa795150ae3d42d64424bb6e0373d0b2Behdad Esfahbod      matcher.set_ignore_zwj (context_match || c->table_index == 1 || c->auto_zwj);
480607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod      if (!context_match)
481cfc507c5432e6327e8484b07b9e091212653bc92Behdad Esfahbod	matcher.set_mask (c->lookup_mask);
482cb90b1bbe6d27ca6968b70d2dbfea7ab7fb73293Behdad Esfahbod      matcher.set_syllable (start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0);
4834ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod    }
484607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    inline void set_lookup_props (unsigned int lookup_props) { matcher.set_lookup_props (lookup_props); }
485607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    inline void set_syllable (unsigned int syllable) { matcher.set_syllable (syllable); }
486607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    inline void set_match_func (matcher_t::match_func_t match_func,
487607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod				const void *match_data,
488607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod				const USHORT glyph_data[])
4897b84c536c10ab90ed96a033d88e9ad232d46c5b8Behdad Esfahbod    {
490607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod      matcher.set_match_func (match_func, match_data);
491607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod      match_glyph_data = glyph_data;
4927b84c536c10ab90ed96a033d88e9ad232d46c5b8Behdad Esfahbod    }
493607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
494607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    inline bool has_no_chance (void) const { return unlikely (idx < num_items); }
495607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    inline void reject (void) { num_items++; }
496c074ebc466dcc9bcc0d8a5dd7e942dea974ff718Behdad Esfahbod    inline bool prev (void)
4974ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod    {
498506ffeb8e77a668fa305139582d215c32e46bb03Behdad Esfahbod      assert (num_items > 0);
499607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod      while (!has_no_chance ())
5004ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod      {
5014ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod	idx--;
502607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	const hb_glyph_info_t &info = c->buffer->out_info[idx];
503607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
504ff93ac8cb24cbc3d9dc1a2bfb0faa88950f4a507Behdad Esfahbod	matcher_t::may_skip_t skip = matcher.may_skip (c, info);
505607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	if (unlikely (skip == matcher_t::SKIP_YES))
506607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	  continue;
507607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
5082b2a6e8944144755ab641f2842e36d9a847719f3Behdad Esfahbod	matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
509722e8b857eafc52e07dee5d9b253b88ed5c5c8edBehdad Esfahbod	if (match == matcher_t::MATCH_YES ||
510722e8b857eafc52e07dee5d9b253b88ed5c5c8edBehdad Esfahbod	    (match == matcher_t::MATCH_MAYBE &&
511722e8b857eafc52e07dee5d9b253b88ed5c5c8edBehdad Esfahbod	     skip == matcher_t::SKIP_NO))
512607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	{
513607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	  num_items--;
514607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	  match_glyph_data++;
515607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	  return true;
516607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	}
517607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
518607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod	if (skip == matcher_t::SKIP_NO)
519722e8b857eafc52e07dee5d9b253b88ed5c5c8edBehdad Esfahbod	  return false;
520607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod      }
521607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod      return false;
5224ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod    }
5234ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod
5244ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod    unsigned int idx;
525ec8d2494694275dfbbac2dd0d33ca2894b0463d6Behdad Esfahbod    protected:
5264ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod    hb_apply_context_t *c;
527607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    matcher_t matcher;
528607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod    const USHORT *match_glyph_data;
529607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
5304ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod    unsigned int num_items;
5314ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod  };
5324ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod
53303f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod  inline bool
53403f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod  match_properties_mark (hb_codepoint_t  glyph,
53503f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod			 unsigned int    glyph_props,
53603f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod			 unsigned int    lookup_props) const
53703f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod  {
53803f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod    /* If using mark filtering sets, the high short of
53903f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod     * lookup_props has the set index.
54003f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod     */
54103f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod    if (lookup_props & LookupFlag::UseMarkFilteringSet)
54203f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod      return gdef.mark_set_covers (lookup_props >> 16, glyph);
54303f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod
54403f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod    /* The second byte of lookup_props has the meaning
54503f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod     * "ignore marks of attachment type different than
54603f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod     * the attachment type specified."
54703f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod     */
54803f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod    if (lookup_props & LookupFlag::MarkAttachmentType)
54903f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod      return (lookup_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
55003f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod
55103f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod    return true;
55203f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod  }
55303f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod
55403f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod  inline bool
555b98c5db32d15fcfb27ce2f6737203ce1ad124319Behdad Esfahbod  check_glyph_property (const hb_glyph_info_t *info,
556b98c5db32d15fcfb27ce2f6737203ce1ad124319Behdad Esfahbod			unsigned int  lookup_props) const
55703f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod  {
558b98c5db32d15fcfb27ce2f6737203ce1ad124319Behdad Esfahbod    hb_codepoint_t glyph = info->codepoint;
559b98c5db32d15fcfb27ce2f6737203ce1ad124319Behdad Esfahbod    unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info);
560b98c5db32d15fcfb27ce2f6737203ce1ad124319Behdad Esfahbod
56103f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod    /* Not covered, if, for example, glyph class is ligature and
56203f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod     * lookup_props includes LookupFlags::IgnoreLigatures
56303f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod     */
56403f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod    if (glyph_props & lookup_props & LookupFlag::IgnoreFlags)
56503f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod      return false;
56603f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod
5675a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbod    if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
56803f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod      return match_properties_mark (glyph, glyph_props, lookup_props);
56903f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod
57003f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod    return true;
57103f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod  }
57203f67bc012f42131b36083a23efc78e1b04b828cBehdad Esfahbod
573a0161746589934e93c3b115814bbd81f56ab962fBehdad Esfahbod  inline void _set_glyph_props (hb_codepoint_t glyph_index,
57471b4c999a511bf018acaf48a45e070470c0daf12Behdad Esfahbod			  unsigned int class_guess = 0,
575832a6f99b34f334b1e82b8e3a7ad137e823d203cBehdad Esfahbod			  bool ligature = false,
576832a6f99b34f334b1e82b8e3a7ad137e823d203cBehdad Esfahbod			  bool component = false) const
57760da763dfac96a7931d6e6bdef8b9973bd5209abBehdad Esfahbod  {
57809675a8115b9d77261c33940401aa919cede8662Behdad Esfahbod    unsigned int add_in = _hb_glyph_info_get_glyph_props (&buffer->cur()) &
57909675a8115b9d77261c33940401aa919cede8662Behdad Esfahbod			  HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
58009675a8115b9d77261c33940401aa919cede8662Behdad Esfahbod    add_in |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
58109675a8115b9d77261c33940401aa919cede8662Behdad Esfahbod    if (ligature)
582832a6f99b34f334b1e82b8e3a7ad137e823d203cBehdad Esfahbod    {
58309675a8115b9d77261c33940401aa919cede8662Behdad Esfahbod      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
584832a6f99b34f334b1e82b8e3a7ad137e823d203cBehdad Esfahbod      /* In the only place that the MULTIPLIED bit is used, Uniscribe
585832a6f99b34f334b1e82b8e3a7ad137e823d203cBehdad Esfahbod       * seems to only care about the "last" transformation between
586832a6f99b34f334b1e82b8e3a7ad137e823d203cBehdad Esfahbod       * Ligature and Multiple substitions.  Ie. if you ligate, expand,
587832a6f99b34f334b1e82b8e3a7ad137e823d203cBehdad Esfahbod       * and ligate again, it forgives the multiplication and acts as
588832a6f99b34f334b1e82b8e3a7ad137e823d203cBehdad Esfahbod       * if only ligation happened.  As such, clear MULTIPLIED bit.
589832a6f99b34f334b1e82b8e3a7ad137e823d203cBehdad Esfahbod       */
590832a6f99b34f334b1e82b8e3a7ad137e823d203cBehdad Esfahbod      add_in &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
591832a6f99b34f334b1e82b8e3a7ad137e823d203cBehdad Esfahbod    }
592832a6f99b34f334b1e82b8e3a7ad137e823d203cBehdad Esfahbod    if (component)
593832a6f99b34f334b1e82b8e3a7ad137e823d203cBehdad Esfahbod      add_in |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
5942fca1426ca06cabbe8f027f2dc9dee9c27560c76Behdad Esfahbod    if (likely (has_glyph_classes))
59505ad6b50ac0a1b9a8da10d2ee2238068b7811e7dBehdad Esfahbod      _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | gdef.get_glyph_props (glyph_index));
59605bd1b63426e07d1df7a1b40bf845dc94ab995a8Behdad Esfahbod    else if (class_guess)
59709675a8115b9d77261c33940401aa919cede8662Behdad Esfahbod      _hb_glyph_info_set_glyph_props (&buffer->cur(), add_in | class_guess);
59860da763dfac96a7931d6e6bdef8b9973bd5209abBehdad Esfahbod  }
5994ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod
600a0161746589934e93c3b115814bbd81f56ab962fBehdad Esfahbod  inline void replace_glyph (hb_codepoint_t glyph_index) const
6013ec77d6ae0510dc2c0ec64382c4948bc6e109844Behdad Esfahbod  {
602a0161746589934e93c3b115814bbd81f56ab962fBehdad Esfahbod    _set_glyph_props (glyph_index);
603a0161746589934e93c3b115814bbd81f56ab962fBehdad Esfahbod    buffer->replace_glyph (glyph_index);
6043ec77d6ae0510dc2c0ec64382c4948bc6e109844Behdad Esfahbod  }
605a0161746589934e93c3b115814bbd81f56ab962fBehdad Esfahbod  inline void replace_glyph_inplace (hb_codepoint_t glyph_index) const
60698370e89d1bff248737b482d129c2a4deb8bfd95Behdad Esfahbod  {
607a0161746589934e93c3b115814bbd81f56ab962fBehdad Esfahbod    _set_glyph_props (glyph_index);
608a0161746589934e93c3b115814bbd81f56ab962fBehdad Esfahbod    buffer->cur().codepoint = glyph_index;
609a0161746589934e93c3b115814bbd81f56ab962fBehdad Esfahbod  }
610a0161746589934e93c3b115814bbd81f56ab962fBehdad Esfahbod  inline void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
611a0161746589934e93c3b115814bbd81f56ab962fBehdad Esfahbod					   unsigned int class_guess) const
612a0161746589934e93c3b115814bbd81f56ab962fBehdad Esfahbod  {
61309675a8115b9d77261c33940401aa919cede8662Behdad Esfahbod    _set_glyph_props (glyph_index, class_guess, true);
61498370e89d1bff248737b482d129c2a4deb8bfd95Behdad Esfahbod    buffer->replace_glyph (glyph_index);
61598370e89d1bff248737b482d129c2a4deb8bfd95Behdad Esfahbod  }
616832a6f99b34f334b1e82b8e3a7ad137e823d203cBehdad Esfahbod  inline void output_glyph_for_component (hb_codepoint_t glyph_index,
617832a6f99b34f334b1e82b8e3a7ad137e823d203cBehdad Esfahbod					  unsigned int class_guess) const
6187fbbf86efe675e4c038dfc5985c24bbc544620cdBehdad Esfahbod  {
619832a6f99b34f334b1e82b8e3a7ad137e823d203cBehdad Esfahbod    _set_glyph_props (glyph_index, class_guess, false, true);
620a0161746589934e93c3b115814bbd81f56ab962fBehdad Esfahbod    buffer->output_glyph (glyph_index);
6217fbbf86efe675e4c038dfc5985c24bbc544620cdBehdad Esfahbod  }
6221376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbod};
6231376fb7bf9ef07970f0ba13dc64d6a8ab8252762Behdad Esfahbod
62466bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
62594a23aaeca39c662614037ef887412249bdc8d49Behdad Esfahbod
6266a9be5bd3524dc3eb1e88d1063bde2e4d8b57011Behdad Esfahbodtypedef bool (*intersects_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
627d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbodtypedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const USHORT &value, const void *data);
62840cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbodtypedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const void *data);
62966bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
63031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbodstruct ContextClosureFuncs
63131081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod{
63231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  intersects_func_t intersects;
63331081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod};
634d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbodstruct ContextCollectGlyphsFuncs
635d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod{
636d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod  collect_glyphs_func_t collect;
637d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod};
63831081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbodstruct ContextApplyFuncs
63960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
64048f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod  match_func_t match;
64166bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod};
64266bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
643d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod
6446a9be5bd3524dc3eb1e88d1063bde2e4d8b57011Behdad Esfahbodstatic inline bool intersects_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
64531081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod{
64631081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  return glyphs->has (value);
64731081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod}
6486a9be5bd3524dc3eb1e88d1063bde2e4d8b57011Behdad Esfahbodstatic inline bool intersects_class (hb_set_t *glyphs, const USHORT &value, const void *data)
64931081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod{
65031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
65131081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  return class_def.intersects_class (glyphs, value);
65231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod}
6536a9be5bd3524dc3eb1e88d1063bde2e4d8b57011Behdad Esfahbodstatic inline bool intersects_coverage (hb_set_t *glyphs, const USHORT &value, const void *data)
65431081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod{
65531081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
65631081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  return (data+coverage).intersects (glyphs);
65731081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod}
65831081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
65931081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbodstatic inline bool intersects_array (hb_closure_context_t *c,
66031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod				     unsigned int count,
66131081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod				     const USHORT values[],
66231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod				     intersects_func_t intersects_func,
66331081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod				     const void *intersects_data)
66431081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod{
66531081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  for (unsigned int i = 0; i < count; i++)
66631081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
66731081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod      return false;
66831081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  return true;
66931081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod}
67031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
671f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod
672d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbodstatic inline void collect_glyph (hb_set_t *glyphs, const USHORT &value, const void *data HB_UNUSED)
673d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod{
674d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod  glyphs->add (value);
675d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod}
676d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbodstatic inline void collect_class (hb_set_t *glyphs, const USHORT &value, const void *data)
677d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod{
678d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
679d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod  class_def.add_class (glyphs, value);
680d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod}
681d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbodstatic inline void collect_coverage (hb_set_t *glyphs, const USHORT &value, const void *data)
682d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod{
683d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
684d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod  (data+coverage).add_coverage (glyphs);
685d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod}
6860beb66e3a61ae8bb1fa66e54b1ff1abb2f8711e9Behdad Esfahbodstatic inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
687f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod				  hb_set_t *glyphs,
688d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod				  unsigned int count,
689d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod				  const USHORT values[],
690d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod				  collect_glyphs_func_t collect_func,
691d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod				  const void *collect_data)
692d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod{
693d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod  for (unsigned int i = 0; i < count; i++)
694f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    collect_func (glyphs, values[i], collect_data);
695d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod}
696d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod
697d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod
69840cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbodstatic inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, const void *data HB_UNUSED)
69960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
70048f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod  return glyph_id == value;
70148f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod}
70240cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbodstatic inline bool match_class (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
70360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
7042b5a59c277f4c5bf7aac9a9005054763e322e02dBehdad Esfahbod  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
70548f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod  return class_def.get_class (glyph_id) == value;
70648f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod}
70740cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbodstatic inline bool match_coverage (hb_codepoint_t glyph_id, const USHORT &value, const void *data)
70860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
7096b54c5d0446b514fbb6521e7e9e614d153435f0eBehdad Esfahbod  const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
71031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
71148f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod}
71248f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod
713e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbodstatic inline bool would_match_input (hb_would_apply_context_t *c,
714e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod				      unsigned int count, /* Including the first glyph (not matched) */
715e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod				      const USHORT input[], /* Array of input values--start with second glyph */
716e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod				      match_func_t match_func,
717e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod				      const void *match_data)
718e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod{
719e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  if (count != c->len)
720e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    return false;
721e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
722e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  for (unsigned int i = 1; i < count; i++)
723472f229a63f0d1bb21b02179ef430b7698df8f12Behdad Esfahbod    if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
724e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod      return false;
725e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
726e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  return true;
727e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod}
728d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbodstatic inline bool match_input (hb_apply_context_t *c,
729d0ba0557007798db2c60ddd0b7a5a0624cd1698dBehdad Esfahbod				unsigned int count, /* Including the first glyph (not matched) */
730d0ba0557007798db2c60ddd0b7a5a0624cd1698dBehdad Esfahbod				const USHORT input[], /* Array of input values--start with second glyph */
731d0ba0557007798db2c60ddd0b7a5a0624cd1698dBehdad Esfahbod				match_func_t match_func,
73240cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbod				const void *match_data,
7336cc136f7531a45e71ea08a7dc8a2187172cb813dBehdad Esfahbod				unsigned int *end_offset,
7346cc136f7531a45e71ea08a7dc8a2187172cb813dBehdad Esfahbod				unsigned int match_positions[MAX_CONTEXT_LENGTH],
735191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod				bool *p_is_mark_ligature = NULL,
736191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod				unsigned int *p_total_component_count = NULL)
737d0ba0557007798db2c60ddd0b7a5a0624cd1698dBehdad Esfahbod{
73873c18ae1b982a4e65086afe5177afa79e721e2c0Behdad Esfahbod  TRACE_APPLY (NULL);
73993814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod
7406b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod  if (unlikely (count > MAX_CONTEXT_LENGTH)) TRACE_RETURN (false);
7416b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod
7423c3df9cba13fec2c35e0e7ae587d9699ac0c37f5Behdad Esfahbod  hb_buffer_t *buffer = c->buffer;
7433c3df9cba13fec2c35e0e7ae587d9699ac0c37f5Behdad Esfahbod
7443c3df9cba13fec2c35e0e7ae587d9699ac0c37f5Behdad Esfahbod  hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, buffer->idx, count - 1);
745607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod  skippy_iter.set_match_func (match_func, match_data, input);
74693814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod  if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
74793814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod
748191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod  /*
749191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod   * This is perhaps the trickiest part of OpenType...  Remarks:
750191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod   *
751191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod   * - If all components of the ligature were marks, we call this a mark ligature.
752191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod   *
753191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod   * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
754191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod   *   it as a ligature glyph.
755191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod   *
756191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod   * - Ligatures cannot be formed across glyphs attached to different components
757191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod   *   of previous ligatures.  Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
758191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod   *   LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
759191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod   *   However, it would be wrong to ligate that SHADDA,FATHA sequence.o
760191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod   *   There is an exception to this: If a ligature tries ligating with marks that
761191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod   *   belong to it itself, go ahead, assuming that the font designer knows what
762191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod   *   they are doing (otherwise it can break Indic stuff when a matra wants to
763191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod   *   ligate with a conjunct...)
764191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod   */
765191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod
766101303dbf7cf15d044bf2518f14b3aec65970feaBehdad Esfahbod  bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->cur());
76793814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod
76893814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod  unsigned int total_component_count = 0;
7693ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod  total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
77093814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod
7713ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod  unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
7723ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod  unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
773d0ba0557007798db2c60ddd0b7a5a0624cd1698dBehdad Esfahbod
7743c3df9cba13fec2c35e0e7ae587d9699ac0c37f5Behdad Esfahbod  match_positions[0] = buffer->idx;
775370f03e9c69d98d735eafb7e72b13b17f42cbaa9Behdad Esfahbod  for (unsigned int i = 1; i < count; i++)
77660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
777407fc12466ef460d0edf11b89f0d04c4d724875fBehdad Esfahbod    if (!skippy_iter.next ()) return TRACE_RETURN (false);
7786cc136f7531a45e71ea08a7dc8a2187172cb813dBehdad Esfahbod
7796cc136f7531a45e71ea08a7dc8a2187172cb813dBehdad Esfahbod    match_positions[i] = skippy_iter.idx;
78093814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod
7813ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod    unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]);
7823ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod    unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]);
78393814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod
78493814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod    if (first_lig_id && first_lig_comp) {
78593814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod      /* If first component was attached to a previous ligature component,
78693814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod       * all subsequent components should be attached to the same ligature
78793814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod       * component, otherwise we shouldn't ligate them. */
78893814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod      if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
78993814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod	return TRACE_RETURN (false);
79093814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod    } else {
79193814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod      /* If first component was NOT attached to a previous ligature component,
79293814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod       * all subsequent components should also NOT be attached to any ligature
79393814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod       * component, unless they are attached to the first component itself! */
79493814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod      if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
79593814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod	return TRACE_RETURN (false);
79693814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod    }
79793814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod
798101303dbf7cf15d044bf2518f14b3aec65970feaBehdad Esfahbod    is_mark_ligature = is_mark_ligature && _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]);
7993ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod    total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[skippy_iter.idx]);
800d0ba0557007798db2c60ddd0b7a5a0624cd1698dBehdad Esfahbod  }
801d0ba0557007798db2c60ddd0b7a5a0624cd1698dBehdad Esfahbod
8023c3df9cba13fec2c35e0e7ae587d9699ac0c37f5Behdad Esfahbod  *end_offset = skippy_iter.idx - buffer->idx + 1;
803d0ba0557007798db2c60ddd0b7a5a0624cd1698dBehdad Esfahbod
804191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod  if (p_is_mark_ligature)
805191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod    *p_is_mark_ligature = is_mark_ligature;
806191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod
807191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod  if (p_total_component_count)
808191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod    *p_total_component_count = total_component_count;
809191fa885d9e0a2dce92dd8727cddd18495e62409Behdad Esfahbod
810bc513add7999baf32f126ceebbd318105ee66985Behdad Esfahbod  return TRACE_RETURN (true);
811d0ba0557007798db2c60ddd0b7a5a0624cd1698dBehdad Esfahbod}
812a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbodstatic inline void ligate_input (hb_apply_context_t *c,
813e714fe6d6a2633494cb1fa7170a32ca2638cbb51Behdad Esfahbod				 unsigned int count, /* Including the first glyph */
814e714fe6d6a2633494cb1fa7170a32ca2638cbb51Behdad Esfahbod				 unsigned int match_positions[MAX_CONTEXT_LENGTH], /* Including the first glyph */
815e714fe6d6a2633494cb1fa7170a32ca2638cbb51Behdad Esfahbod				 unsigned int match_length,
816a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod				 hb_codepoint_t lig_glyph,
817a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod				 bool is_mark_ligature,
818a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod				 unsigned int total_component_count)
819a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod{
820e714fe6d6a2633494cb1fa7170a32ca2638cbb51Behdad Esfahbod  TRACE_APPLY (NULL);
821e714fe6d6a2633494cb1fa7170a32ca2638cbb51Behdad Esfahbod
8223c3df9cba13fec2c35e0e7ae587d9699ac0c37f5Behdad Esfahbod  hb_buffer_t *buffer = c->buffer;
8233c3df9cba13fec2c35e0e7ae587d9699ac0c37f5Behdad Esfahbod
8243c3df9cba13fec2c35e0e7ae587d9699ac0c37f5Behdad Esfahbod  buffer->merge_clusters (buffer->idx, buffer->idx + match_length);
825607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
826a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod  /*
827a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   * - If it *is* a mark ligature, we don't allocate a new ligature id, and leave
828a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   the ligature to keep its old ligature id.  This will allow it to attach to
829a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   a base ligature in GPOS.  Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
830a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA wit a
831a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   ligature id and component value of 2.  Then if SHADDA,FATHA form a ligature
832a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   later, we don't want them to lose their ligature id/component, otherwise
833a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   GPOS will fail to correctly position the mark ligature on top of the
834a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   LAM,LAM,HEH ligature.  See:
835a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *     https://bugzilla.gnome.org/show_bug.cgi?id=676343
836a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *
837a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   * - If a ligature is formed of components that some of which are also ligatures
838a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   themselves, and those ligature components had marks attached to *their*
839a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   components, we have to attach the marks to the new ligature component
840a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   positions!  Now *that*'s tricky!  And these marks may be following the
841a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   last component of the whole sequence, so we should loop forward looking
842a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   for them and update them.
843a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *
844a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
845a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
846a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   id and component == 1.  Now, during 'liga', the LAM and the LAM-HEH ligature
847a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   form a LAM-LAM-HEH ligature.  We need to reassign the SHADDA and FATHA to
848a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   the new ligature with a component value of 2.
849a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *
850a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   This in fact happened to a font...  See:
851a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   *   https://bugzilla.gnome.org/show_bug.cgi?id=437633
852a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod   */
853a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod
8545a08ecf9200a6ac9b4ebb7ec5c13dcb42d8820ceBehdad Esfahbod  unsigned int klass = is_mark_ligature ? 0 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
8553ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod  unsigned int lig_id = is_mark_ligature ? 0 : _hb_allocate_lig_id (buffer);
8563ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod  unsigned int last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
8573ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod  unsigned int last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
858a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod  unsigned int components_so_far = last_num_components;
859a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod
860a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod  if (!is_mark_ligature)
8617e08f1258da229dfaf7e1c4b5c41e5bb83906cb0Behdad Esfahbod  {
8623ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod    _hb_glyph_info_set_lig_props_for_ligature (&buffer->cur(), lig_id, total_component_count);
8633c3df9cba13fec2c35e0e7ae587d9699ac0c37f5Behdad Esfahbod    if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
8643d436d325edccc0f3dd820e06e3d529cc8f3eca4Behdad Esfahbod    {
8653c3df9cba13fec2c35e0e7ae587d9699ac0c37f5Behdad Esfahbod      _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER);
8663d436d325edccc0f3dd820e06e3d529cc8f3eca4Behdad Esfahbod      _hb_glyph_info_set_modified_combining_class (&buffer->cur(), 0);
8673d436d325edccc0f3dd820e06e3d529cc8f3eca4Behdad Esfahbod    }
8687e08f1258da229dfaf7e1c4b5c41e5bb83906cb0Behdad Esfahbod  }
869a0161746589934e93c3b115814bbd81f56ab962fBehdad Esfahbod  c->replace_glyph_with_ligature (lig_glyph, klass);
870a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod
871a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod  for (unsigned int i = 1; i < count; i++)
872a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod  {
8733c3df9cba13fec2c35e0e7ae587d9699ac0c37f5Behdad Esfahbod    while (buffer->idx < match_positions[i])
874a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod    {
875a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod      if (!is_mark_ligature) {
876a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod	unsigned int new_lig_comp = components_so_far - last_num_components +
8773ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod				    MIN (MAX (_hb_glyph_info_get_lig_comp (&buffer->cur()), 1u), last_num_components);
8783ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod	_hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
879a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod      }
8803c3df9cba13fec2c35e0e7ae587d9699ac0c37f5Behdad Esfahbod      buffer->next_glyph ();
881a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod    }
882a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod
8833ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod    last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
8843ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod    last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
885a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod    components_so_far += last_num_components;
886a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod
887a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod    /* Skip the base glyph */
8883c3df9cba13fec2c35e0e7ae587d9699ac0c37f5Behdad Esfahbod    buffer->idx++;
889a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod  }
890a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod
891a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod  if (!is_mark_ligature && last_lig_id) {
892a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod    /* Re-adjust components for any marks following. */
8933c3df9cba13fec2c35e0e7ae587d9699ac0c37f5Behdad Esfahbod    for (unsigned int i = buffer->idx; i < buffer->len; i++) {
8943ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod      if (last_lig_id == _hb_glyph_info_get_lig_id (&buffer->info[i])) {
895a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod	unsigned int new_lig_comp = components_so_far - last_num_components +
8963ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod				    MIN (MAX (_hb_glyph_info_get_lig_comp (&buffer->info[i]), 1u), last_num_components);
8973ddf892b5328b74afb6e7d9da727d8771ca5d288Behdad Esfahbod	_hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
898a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod      } else
899a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod	break;
900a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod    }
901a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod  }
90204d894e89795041b2055dc172744a018644f2bcaBehdad Esfahbod  TRACE_RETURN (true);
903a177d027d1d0ad9539e30ed75d8652e0e8da20ffBehdad Esfahbod}
904d0ba0557007798db2c60ddd0b7a5a0624cd1698dBehdad Esfahbod
905d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbodstatic inline bool match_backtrack (hb_apply_context_t *c,
906e072c24e79f0e7c1e078a87c782ab5dd8f21dcdaBehdad Esfahbod				    unsigned int count,
907e072c24e79f0e7c1e078a87c782ab5dd8f21dcdaBehdad Esfahbod				    const USHORT backtrack[],
908e072c24e79f0e7c1e078a87c782ab5dd8f21dcdaBehdad Esfahbod				    match_func_t match_func,
90940cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbod				    const void *match_data)
910e072c24e79f0e7c1e078a87c782ab5dd8f21dcdaBehdad Esfahbod{
91173c18ae1b982a4e65086afe5177afa79e721e2c0Behdad Esfahbod  TRACE_APPLY (NULL);
91293814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod
9139082efc4aacb34de8574d6a4a3c037987df58bd8Behdad Esfahbod  hb_apply_context_t::skipping_backward_iterator_t skippy_iter (c, c->buffer->backtrack_len (), count, true);
914607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod  skippy_iter.set_match_func (match_func, match_data, backtrack);
915607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod  if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
916e072c24e79f0e7c1e078a87c782ab5dd8f21dcdaBehdad Esfahbod
9174d3aeb8cb2bc1ca7cdd03ba28ba8c334f12d4c03Behdad Esfahbod  for (unsigned int i = 0; i < count; i++)
9184ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod    if (!skippy_iter.prev ())
91993814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod      return TRACE_RETURN (false);
920e072c24e79f0e7c1e078a87c782ab5dd8f21dcdaBehdad Esfahbod
92193814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod  return TRACE_RETURN (true);
922e072c24e79f0e7c1e078a87c782ab5dd8f21dcdaBehdad Esfahbod}
923e072c24e79f0e7c1e078a87c782ab5dd8f21dcdaBehdad Esfahbod
924d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbodstatic inline bool match_lookahead (hb_apply_context_t *c,
925d0ba0557007798db2c60ddd0b7a5a0624cd1698dBehdad Esfahbod				    unsigned int count,
926d0ba0557007798db2c60ddd0b7a5a0624cd1698dBehdad Esfahbod				    const USHORT lookahead[],
927d0ba0557007798db2c60ddd0b7a5a0624cd1698dBehdad Esfahbod				    match_func_t match_func,
92840cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbod				    const void *match_data,
929d0ba0557007798db2c60ddd0b7a5a0624cd1698dBehdad Esfahbod				    unsigned int offset)
930f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod{
93173c18ae1b982a4e65086afe5177afa79e721e2c0Behdad Esfahbod  TRACE_APPLY (NULL);
93293814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod
9339082efc4aacb34de8574d6a4a3c037987df58bd8Behdad Esfahbod  hb_apply_context_t::skipping_forward_iterator_t skippy_iter (c, c->buffer->idx + offset - 1, count, true);
934607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod  skippy_iter.set_match_func (match_func, match_data, lookahead);
935607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod  if (skippy_iter.has_no_chance ()) return TRACE_RETURN (false);
93666bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
937370f03e9c69d98d735eafb7e72b13b17f42cbaa9Behdad Esfahbod  for (unsigned int i = 0; i < count; i++)
9384ab97311541225906f6b737a2b47de252224cc09Behdad Esfahbod    if (!skippy_iter.next ())
93993814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod      return TRACE_RETURN (false);
94066bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
94193814ca7dc2a7251f861c1c47ba155ba6e6bdf19Behdad Esfahbod  return TRACE_RETURN (true);
942f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod}
943f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod
944acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
945f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod
94660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct LookupRecord
94760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
948d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
949be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_SANITIZE (this);
9500ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (c->check_struct (this));
951cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
952cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
953f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod  USHORT	sequenceIndex;		/* Index into current glyph
954f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod					 * sequence--first glyph = 0 */
955f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod  USHORT	lookupListIndex;	/* Lookup to apply to that
956f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod					 * position--zero--based */
957569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod  public:
958569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod  DEFINE_SIZE_STATIC (4);
959f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod};
960f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod
961acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
962d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbodtemplate <typename context_t>
963d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbodstatic inline void recurse_lookups (context_t *c,
964d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod				    unsigned int lookupCount,
965d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod				    const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
96631081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod{
96731081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  for (unsigned int i = 0; i < lookupCount; i++)
96886522e493d071f395b5abf64289232bf8867ac29Behdad Esfahbod    c->recurse (lookupRecord[i].lookupListIndex);
96931081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod}
970acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
971d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbodstatic inline bool apply_lookup (hb_apply_context_t *c,
972e072c24e79f0e7c1e078a87c782ab5dd8f21dcdaBehdad Esfahbod				 unsigned int count, /* Including the first glyph */
9736b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod				 unsigned int match_positions[MAX_CONTEXT_LENGTH], /* Including the first glyph */
974e072c24e79f0e7c1e078a87c782ab5dd8f21dcdaBehdad Esfahbod				 unsigned int lookupCount,
9756b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod				 const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
9766b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod				 unsigned int match_length)
977f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod{
97873c18ae1b982a4e65086afe5177afa79e721e2c0Behdad Esfahbod  TRACE_APPLY (NULL);
979902cc8aca0b3ff25eeee50b3a84d729e31731ef3Behdad Esfahbod
9806b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod  hb_buffer_t *buffer = c->buffer;
9816b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod  unsigned int end;
98252e9a71d578c5171bbb0f4bfc1b70841c3270328Behdad Esfahbod
9836b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod  /* All positions are distance from beginning of *output* buffer.
9846b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod   * Adjust. */
9856b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod  {
9866b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    unsigned int bl = buffer->backtrack_len ();
9876b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    end = bl + match_length;
988607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
9896b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    int delta = bl - buffer->idx;
9906b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    /* Convert positions to new indexing. */
9916b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    for (unsigned int j = 0; j < count; j++)
9926b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod      match_positions[j] += delta;
9936b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod  }
994607feb7cff0e50f8738d2e49ca463fc9d7d494deBehdad Esfahbod
9956b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod  for (unsigned int i = 0; i < lookupCount; i++)
99660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
9976b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    unsigned int idx = lookupRecord[i].sequenceIndex;
9986b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    if (idx >= count)
9996b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod      continue;
10008751de50831338ce550601c34c17d152ad89c1fdBehdad Esfahbod
10016b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    buffer->move_to (match_positions[idx]);
10028820bb235b1f63e4d93c8a2f5c08b44d89e06b78Behdad Esfahbod
10036b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
10046b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    if (!c->recurse (lookupRecord[i].lookupListIndex))
10056b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod      continue;
10068820bb235b1f63e4d93c8a2f5c08b44d89e06b78Behdad Esfahbod
10076b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
10086b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    int delta = new_len - orig_len;
1009e73a0c2a903112ce9a35b95e14e10ab8ea2dc337Behdad Esfahbod
10106b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    if (!delta)
10116b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod        continue;
10128751de50831338ce550601c34c17d152ad89c1fdBehdad Esfahbod
10136b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    /* Recursed lookup changed buffer len.  Adjust. */
101466bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
1015b6b304f12be917b7449b3ac9409069fcd4a27d95Behdad Esfahbod    /* end can't go back past the current match position.
1016b6b304f12be917b7449b3ac9409069fcd4a27d95Behdad Esfahbod     * Note: this is only true because we do NOT allow MultipleSubst
1017b6b304f12be917b7449b3ac9409069fcd4a27d95Behdad Esfahbod     * with zero sequence len. */
1018da72042c52ed3cc0ee19d3eabb8db7c7dd34d3edBehdad Esfahbod    end = MAX ((int) match_positions[idx] + 1, int (end) + delta);
101966bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
10206b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
10216b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod
10226b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    if (delta > 0)
10236b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    {
10246b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod      if (unlikely (delta + count > MAX_CONTEXT_LENGTH))
10256b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod	break;
102666bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod    }
102766bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod    else
102866bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod    {
10296b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod      /* NOTE: delta is negative. */
10306b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod      delta = MAX (delta, (int) next - (int) count);
10316b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod      next -= delta;
103266bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod    }
10336b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod
10346b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    /* Shift! */
10356b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    memmove (match_positions + next + delta, match_positions + next,
10366b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod	     (count - next) * sizeof (match_positions[0]));
10376b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    next += delta;
10386b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    count += delta;
10396b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod
10406b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    /* Fill in new entries. */
10416b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    for (unsigned int j = idx + 1; j < next; j++)
10426b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod      match_positions[j] = match_positions[j - 1] + 1;
10436b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod
10446b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    /* And fixup the rest. */
10456b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod    for (; next < count; next++)
10466b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod      match_positions[next] += delta;
104766bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod  }
104866bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
10496b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod  buffer->move_to (end);
10506b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod
10512616689d159024d2b1cb1e68f9936b2129bf9be6Behdad Esfahbod  return TRACE_RETURN (true);
105266bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod}
105348f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod
1054acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
1055f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod
1056f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod/* Contextual lookups */
1057f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod
105831081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbodstruct ContextClosureLookupContext
105931081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod{
106031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  ContextClosureFuncs funcs;
106131081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  const void *intersects_data;
106231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod};
106331081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
1064d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbodstruct ContextCollectGlyphsLookupContext
1065d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod{
1066d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod  ContextCollectGlyphsFuncs funcs;
1067d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod  const void *collect_data;
1068d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod};
1069d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod
107031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbodstruct ContextApplyLookupContext
107160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
107231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  ContextApplyFuncs funcs;
107340cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbod  const void *match_data;
1074f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod};
1075f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod
10765caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbodstatic inline void context_closure_lookup (hb_closure_context_t *c,
107731081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					   unsigned int inputCount, /* Including the first glyph (not matched) */
107831081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					   const USHORT input[], /* Array of input values--start with second glyph */
107931081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					   unsigned int lookupCount,
108031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					   const LookupRecord lookupRecord[],
108131081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					   ContextClosureLookupContext &lookup_context)
108231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod{
10835caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod  if (intersects_array (c,
10845caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod			inputCount ? inputCount - 1 : 0, input,
10855caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod			lookup_context.funcs.intersects, lookup_context.intersects_data))
1086d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    recurse_lookups (c,
1087d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod		     lookupCount, lookupRecord);
108831081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod}
108931081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
1090d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbodstatic inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
1091d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod						  unsigned int inputCount, /* Including the first glyph (not matched) */
1092d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod						  const USHORT input[], /* Array of input values--start with second glyph */
1093d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod						  unsigned int lookupCount,
1094d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod						  const LookupRecord lookupRecord[],
1095d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod						  ContextCollectGlyphsLookupContext &lookup_context)
1096d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod{
10978303593ba1db06e402eab52df47f21f13049112dBehdad Esfahbod  collect_array (c, c->input,
1098d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod		 inputCount ? inputCount - 1 : 0, input,
1099d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod		 lookup_context.funcs.collect, lookup_context.collect_data);
1100d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod  recurse_lookups (c,
1101d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod		   lookupCount, lookupRecord);
1102d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod}
110331081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
1104e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbodstatic inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
1105e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod					       unsigned int inputCount, /* Including the first glyph (not matched) */
1106e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod					       const USHORT input[], /* Array of input values--start with second glyph */
11070beb66e3a61ae8bb1fa66e54b1ff1abb2f8711e9Behdad Esfahbod					       unsigned int lookupCount HB_UNUSED,
11080beb66e3a61ae8bb1fa66e54b1ff1abb2f8711e9Behdad Esfahbod					       const LookupRecord lookupRecord[] HB_UNUSED,
1109e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod					       ContextApplyLookupContext &lookup_context)
1110e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod{
1111e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  return would_match_input (c,
1112e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod			    inputCount, input,
1113e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod			    lookup_context.funcs.match, lookup_context.match_data);
1114e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod}
111531081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbodstatic inline bool context_apply_lookup (hb_apply_context_t *c,
111631081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					 unsigned int inputCount, /* Including the first glyph (not matched) */
111731081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					 const USHORT input[], /* Array of input values--start with second glyph */
111831081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					 unsigned int lookupCount,
111931081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					 const LookupRecord lookupRecord[],
112031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					 ContextApplyLookupContext &lookup_context)
1121f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod{
11226b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod  unsigned int match_length = 0;
11236b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod  unsigned int match_positions[MAX_CONTEXT_LENGTH];
1124d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  return match_input (c,
11254169710911450e0f9bc045fe279bfc8ba9e8457cBehdad Esfahbod		      inputCount, input,
11266b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod		      lookup_context.funcs.match, lookup_context.match_data,
11276b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod		      &match_length, match_positions)
11285df809b655bb1318115651fd87d4555cdd9b41cbBehdad Esfahbod      && apply_lookup (c,
11296b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod		       inputCount, match_positions,
11306b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod		       lookupCount, lookupRecord,
11316b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod		       match_length);
1132f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod}
1133f14c2b7acfba75b8a6880f41ceec758f9a56abceBehdad Esfahbod
113460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct Rule
113560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
11365caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod  inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
113731081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  {
1138be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_CLOSURE (this);
1139093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
11405caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod    context_closure_lookup (c,
1141093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod			    inputCount, inputZ,
11425caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod			    lookupCount, lookupRecord,
11435caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod			    lookup_context);
114431081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  }
114531081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
1146d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
1147d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod  {
1148d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    TRACE_COLLECT_GLYPHS (this);
1149093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
1150d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    context_collect_glyphs_lookup (c,
1151093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod				   inputCount, inputZ,
1152d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod				   lookupCount, lookupRecord,
1153d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod				   lookup_context);
1154d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod  }
1155d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod
1156e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
1157e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  {
1158be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_WOULD_APPLY (this);
1159093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
1160093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    return TRACE_RETURN (context_would_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
1161e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  }
1162e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
116331081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
116460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
1165be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_APPLY (this);
1166093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (inputZ, inputZ[0].static_size * (inputCount ? inputCount - 1 : 0));
1167093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    return TRACE_RETURN (context_apply_lookup (c, inputCount, inputZ, lookupCount, lookupRecord, lookup_context));
116866bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod  }
116966bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
117070de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  public:
1171d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
1172be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_SANITIZE (this);
1173d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod    return inputCount.sanitize (c)
1174d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod	&& lookupCount.sanitize (c)
1175093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod	&& c->check_range (inputZ,
1176093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod			   inputZ[0].static_size * inputCount
1177f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod			   + lookupRecordX[0].static_size * lookupCount);
117870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
117970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
1180ec8d2494694275dfbbac2dd0d33ca2894b0463d6Behdad Esfahbod  protected:
118148f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod  USHORT	inputCount;		/* Total number of glyphs in input
118231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					 * glyph sequence--includes the first
118366bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod					 * glyph */
118448f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod  USHORT	lookupCount;		/* Number of LookupRecords */
1185093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod  USHORT	inputZ[VAR];		/* Array of match inputs--start with
118666bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod					 * second glyph */
1187d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod  LookupRecord	lookupRecordX[VAR];	/* Array of LookupRecords--in
118866bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod					 * design order */
1189569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod  public:
1190093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod  DEFINE_SIZE_ARRAY2 (4, inputZ, lookupRecordX);
119166bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod};
119266bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
119360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct RuleSet
119460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
11955caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod  inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
119631081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  {
1197be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_CLOSURE (this);
119831081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    unsigned int num_rules = rule.len;
119931081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    for (unsigned int i = 0; i < num_rules; i++)
12005caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod      (this+rule[i]).closure (c, lookup_context);
120131081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  }
120231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
1203d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ContextCollectGlyphsLookupContext &lookup_context) const
1204d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod  {
1205d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    TRACE_COLLECT_GLYPHS (this);
1206d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    unsigned int num_rules = rule.len;
1207d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    for (unsigned int i = 0; i < num_rules; i++)
1208d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod      (this+rule[i]).collect_glyphs (c, lookup_context);
1209d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod  }
1210d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod
1211e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  inline bool would_apply (hb_would_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
1212e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  {
1213be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_WOULD_APPLY (this);
1214e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    unsigned int num_rules = rule.len;
1215e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    for (unsigned int i = 0; i < num_rules; i++)
1216e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    {
1217e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod      if ((this+rule[i]).would_apply (c, lookup_context))
1218e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod        return TRACE_RETURN (true);
1219e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    }
1220e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    return TRACE_RETURN (false);
1221e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  }
1222e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
122331081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  inline bool apply (hb_apply_context_t *c, ContextApplyLookupContext &lookup_context) const
122460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
1225be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_APPLY (this);
122666bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod    unsigned int num_rules = rule.len;
122760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod    for (unsigned int i = 0; i < num_rules; i++)
122860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod    {
1229d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod      if ((this+rule[i]).apply (c, lookup_context))
1230acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod        return TRACE_RETURN (true);
123166bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod    }
1232acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod    return TRACE_RETURN (false);
123366bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod  }
123466bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
1235d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
1236be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_SANITIZE (this);
12370ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (rule.sanitize (c, this));
123870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
123970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
1240ec8d2494694275dfbbac2dd0d33ca2894b0463d6Behdad Esfahbod  protected:
124166bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod  OffsetArrayOf<Rule>
124248f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod		rule;			/* Array of Rule tables
124366bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod					 * ordered by preference */
1244ed07422c33bbb52ff4d79e65986171e3f07697d8Behdad Esfahbod  public:
12450eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod  DEFINE_SIZE_ARRAY (2, rule);
124666bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod};
124766bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
124866bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
124960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct ContextFormat1
125060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
125144fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  inline void closure (hb_closure_context_t *c) const
1252f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod  {
1253be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_CLOSURE (this);
125431081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
125531081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    const Coverage &cov = (this+coverage);
125631081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
125731081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    struct ContextClosureLookupContext lookup_context = {
125844fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod      {intersects_glyph},
125931081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod      NULL
126031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    };
126131081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
126231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    unsigned int count = ruleSet.len;
126331081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
126431081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod      if (cov.intersects_coverage (c->glyphs, i)) {
126531081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod	const RuleSet &rule_set = this+ruleSet[i];
12665caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod	rule_set.closure (c, lookup_context);
126731081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod      }
1268f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod  }
1269f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod
127026514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
127126514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  {
1272d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    TRACE_COLLECT_GLYPHS (this);
12738303593ba1db06e402eab52df47f21f13049112dBehdad Esfahbod    (this+coverage).add_coverage (c->input);
1274d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod
1275d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    struct ContextCollectGlyphsLookupContext lookup_context = {
1276d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod      {collect_glyph},
1277d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod      NULL
1278d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    };
1279d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod
1280d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    unsigned int count = ruleSet.len;
1281d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
1282f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
128326514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  }
128426514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod
1285e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  inline bool would_apply (hb_would_apply_context_t *c) const
1286e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  {
1287be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_WOULD_APPLY (this);
1288e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
1289b67881b171a7cf865af58df146da52fc1e27b160Behdad Esfahbod    const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
1290e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    struct ContextApplyLookupContext lookup_context = {
1291ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod      {match_glyph},
1292e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod      NULL
1293e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    };
1294e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
1295e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  }
1296e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
129744fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  inline const Coverage &get_coverage (void) const
129844fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  {
129944fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod    return this+coverage;
130044fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  }
130144fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod
1302ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod  inline bool apply (hb_apply_context_t *c) const
130360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
1304be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_APPLY (this);
1305b67881b171a7cf865af58df146da52fc1e27b160Behdad Esfahbod    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
130664d3fc8d0dada673245cc8c0b1c12cd849b30997Behdad Esfahbod    if (likely (index == NOT_COVERED))
1307acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod      return TRACE_RETURN (false);
1308aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod
130966bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod    const RuleSet &rule_set = this+ruleSet[index];
131031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    struct ContextApplyLookupContext lookup_context = {
1311ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod      {match_glyph},
131248f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod      NULL
131366bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod    };
1314acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod    return TRACE_RETURN (rule_set.apply (c, lookup_context));
131566bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod  }
131666bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
1317d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
1318be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_SANITIZE (this);
13190ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
132070de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
132170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
1322ec8d2494694275dfbbac2dd0d33ca2894b0463d6Behdad Esfahbod  protected:
132366bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod  USHORT	format;			/* Format identifier--format = 1 */
132466bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod  OffsetTo<Coverage>
132566bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod		coverage;		/* Offset to Coverage table--from
132666bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod					 * beginning of table */
132766bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod  OffsetArrayOf<RuleSet>
132866bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod		ruleSet;		/* Array of RuleSet tables
132966bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod					 * ordered by Coverage Index */
1330b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
13310eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod  DEFINE_SIZE_ARRAY (6, ruleSet);
133266bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod};
133366bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
133466bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
133560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct ContextFormat2
133660d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
133744fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  inline void closure (hb_closure_context_t *c) const
1338f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod  {
1339be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_CLOSURE (this);
134031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    if (!(this+coverage).intersects (c->glyphs))
13415caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod      return;
134231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
134331081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    const ClassDef &class_def = this+classDef;
134431081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
134531081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    struct ContextClosureLookupContext lookup_context = {
134644fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod      {intersects_class},
134711fba79ee9383eb995ddf7eb924dd64c67e2df63Behdad Esfahbod      &class_def
134831081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    };
134931081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
135031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    unsigned int count = ruleSet.len;
135131081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
135231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod      if (class_def.intersects_class (c->glyphs, i)) {
135331081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod	const RuleSet &rule_set = this+ruleSet[i];
13545caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod	rule_set.closure (c, lookup_context);
135531081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod      }
1356f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod  }
1357f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod
135826514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
135926514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  {
1360d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    TRACE_COLLECT_GLYPHS (this);
13618303593ba1db06e402eab52df47f21f13049112dBehdad Esfahbod    (this+coverage).add_coverage (c->input);
1362d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod
136311fba79ee9383eb995ddf7eb924dd64c67e2df63Behdad Esfahbod    const ClassDef &class_def = this+classDef;
1364d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    struct ContextCollectGlyphsLookupContext lookup_context = {
1365d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod      {collect_class},
136611fba79ee9383eb995ddf7eb924dd64c67e2df63Behdad Esfahbod      &class_def
1367d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    };
1368d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod
1369d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    unsigned int count = ruleSet.len;
1370d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
1371f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
137226514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  }
137326514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod
1374e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  inline bool would_apply (hb_would_apply_context_t *c) const
1375e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  {
1376be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_WOULD_APPLY (this);
1377e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
1378e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    const ClassDef &class_def = this+classDef;
13792dc1141d7d0a9f5818862b09d6b9cfe0a27f1fc1Behdad Esfahbod    unsigned int index = class_def.get_class (c->glyphs[0]);
1380e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    const RuleSet &rule_set = this+ruleSet[index];
1381e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    struct ContextApplyLookupContext lookup_context = {
1382ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod      {match_class},
1383e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod      &class_def
1384e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    };
1385e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
1386e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  }
1387e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
138844fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  inline const Coverage &get_coverage (void) const
138944fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  {
139044fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod    return this+coverage;
139144fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  }
139244fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod
1393ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod  inline bool apply (hb_apply_context_t *c) const
139460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
1395be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_APPLY (this);
1396b67881b171a7cf865af58df146da52fc1e27b160Behdad Esfahbod    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
1397acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
1398aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod
1399aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod    const ClassDef &class_def = this+classDef;
14002dc1141d7d0a9f5818862b09d6b9cfe0a27f1fc1Behdad Esfahbod    index = class_def.get_class (c->buffer->cur().codepoint);
140166bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod    const RuleSet &rule_set = this+ruleSet[index];
140231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    struct ContextApplyLookupContext lookup_context = {
1403ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod      {match_class},
140440cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbod      &class_def
140566bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod    };
1406acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod    return TRACE_RETURN (rule_set.apply (c, lookup_context));
140766bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod  }
140866bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
1409d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
1410be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_SANITIZE (this);
14110ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
141270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
141370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
1414ec8d2494694275dfbbac2dd0d33ca2894b0463d6Behdad Esfahbod  protected:
141566bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod  USHORT	format;			/* Format identifier--format = 2 */
141666bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod  OffsetTo<Coverage>
141766bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod		coverage;		/* Offset to Coverage table--from
141866bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod					 * beginning of table */
141966bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod  OffsetTo<ClassDef>
142066bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod		classDef;		/* Offset to glyph ClassDef table--from
142166bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod					 * beginning of table */
142266bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod  OffsetArrayOf<RuleSet>
142366bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod		ruleSet;		/* Array of RuleSet tables
142466bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod					 * ordered by class */
1425b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
14260eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod  DEFINE_SIZE_ARRAY (8, ruleSet);
142766bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod};
142866bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
142966bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
143060d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct ContextFormat3
143160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
143244fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  inline void closure (hb_closure_context_t *c) const
1433f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod  {
1434be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_CLOSURE (this);
1435093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    if (!(this+coverageZ[0]).intersects (c->glyphs))
14365caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod      return;
143731081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
1438093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
143931081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    struct ContextClosureLookupContext lookup_context = {
144044fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod      {intersects_coverage},
144131081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod      this
144231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    };
14435caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod    context_closure_lookup (c,
1444093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod			    glyphCount, (const USHORT *) (coverageZ + 1),
14455caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod			    lookupCount, lookupRecord,
14465caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod			    lookup_context);
1447f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod  }
1448f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod
144926514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
145026514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  {
1451d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    TRACE_COLLECT_GLYPHS (this);
1452093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    (this+coverageZ[0]).add_coverage (c->input);
1453d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod
1454093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
1455d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    struct ContextCollectGlyphsLookupContext lookup_context = {
1456d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod      {collect_coverage},
1457e75943de803f571b7ad2cf2f777119753a209656Behdad Esfahbod      this
1458d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    };
1459d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod
1460d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    context_collect_glyphs_lookup (c,
1461093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod				   glyphCount, (const USHORT *) (coverageZ + 1),
1462d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod				   lookupCount, lookupRecord,
1463d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod				   lookup_context);
146426514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  }
146526514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod
1466e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  inline bool would_apply (hb_would_apply_context_t *c) const
1467e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  {
1468be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_WOULD_APPLY (this);
1469e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
1470093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
1471e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    struct ContextApplyLookupContext lookup_context = {
1472ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod      {match_coverage},
1473e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod      this
1474e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    };
1475093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    return TRACE_RETURN (context_would_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
1476e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  }
1477e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
147844fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  inline const Coverage &get_coverage (void) const
147944fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  {
1480093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    return this+coverageZ[0];
148144fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  }
148244fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod
1483ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod  inline bool apply (hb_apply_context_t *c) const
148460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
1485be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_APPLY (this);
1486093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
1487acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
148866bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
1489093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    const LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * glyphCount);
149031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    struct ContextApplyLookupContext lookup_context = {
1491ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod      {match_coverage},
149240cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbod      this
149366bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod    };
1494093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    return TRACE_RETURN (context_apply_lookup (c, glyphCount, (const USHORT *) (coverageZ + 1), lookupCount, lookupRecord, lookup_context));
149566bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod  }
149666bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
1497d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
1498be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_SANITIZE (this);
14990ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    if (!c->check_struct (this)) return TRACE_RETURN (false);
150070de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    unsigned int count = glyphCount;
1501093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    if (!count) return TRACE_RETURN (false); /* We want to access coverageZ[0] freely. */
1502093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    if (!c->check_array (coverageZ, coverageZ[0].static_size, count)) return TRACE_RETURN (false);
150370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
1504093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod      if (!coverageZ[i].sanitize (c, this)) return TRACE_RETURN (false);
1505093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod    LookupRecord *lookupRecord = &StructAtOffset<LookupRecord> (coverageZ, coverageZ[0].static_size * count);
15060ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (c->check_array (lookupRecord, lookupRecord[0].static_size, lookupCount));
150770de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
150870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
1509ec8d2494694275dfbbac2dd0d33ca2894b0463d6Behdad Esfahbod  protected:
151066bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod  USHORT	format;			/* Format identifier--format = 3 */
151166bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod  USHORT	glyphCount;		/* Number of glyphs in the input glyph
151266bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod					 * sequence */
151348f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod  USHORT	lookupCount;		/* Number of LookupRecords */
1514aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod  OffsetTo<Coverage>
1515093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod		coverageZ[VAR];		/* Array of offsets to Coverage
1516aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod					 * table in glyph sequence order */
1517d3480ba37fbb5d4be75b094060f5b2f1ce98fb53Behdad Esfahbod  LookupRecord	lookupRecordX[VAR];	/* Array of LookupRecords--in
151866bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod					 * design order */
1519569da92bc6956f42d9b2d65c784e184fb6380efeBehdad Esfahbod  public:
1520093c520de506aec74f3fb1e195c0ca85813424ddBehdad Esfahbod  DEFINE_SIZE_ARRAY2 (6, coverageZ, lookupRecordX);
152166bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod};
152266bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
152360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct Context
152460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
152544fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  template <typename context_t>
15269c5a9ee967120c8a968a1160c420e03620d46c24Behdad Esfahbod  inline typename context_t::return_t dispatch (context_t *c) const
1527e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod  {
152800f6a8e334ec4c586e4e633a95b411ccb50306d3Behdad Esfahbod    TRACE_DISPATCH (this, u.format);
1529e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    switch (u.format) {
15309c5a9ee967120c8a968a1160c420e03620d46c24Behdad Esfahbod    case 1: return TRACE_RETURN (c->dispatch (u.format1));
15319c5a9ee967120c8a968a1160c420e03620d46c24Behdad Esfahbod    case 2: return TRACE_RETURN (c->dispatch (u.format2));
15329c5a9ee967120c8a968a1160c420e03620d46c24Behdad Esfahbod    case 3: return TRACE_RETURN (c->dispatch (u.format3));
1533f48ec0e83432c038b50d9715a38ba1469e82e1e4Behdad Esfahbod    default:return TRACE_RETURN (c->default_return_value ());
1534e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    }
1535e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  }
1536e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
1537d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
1538be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_SANITIZE (this);
15390ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
154070de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    switch (u.format) {
15410ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    case 1: return TRACE_RETURN (u.format1.sanitize (c));
15420ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    case 2: return TRACE_RETURN (u.format2.sanitize (c));
15430ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    case 3: return TRACE_RETURN (u.format3.sanitize (c));
15440ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    default:return TRACE_RETURN (true);
154570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    }
154670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
154770de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
1548ec8d2494694275dfbbac2dd0d33ca2894b0463d6Behdad Esfahbod  protected:
154966bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod  union {
1550f8dc67b3c24dfc805da756a73cb217b36e16b4b8Behdad Esfahbod  USHORT		format;		/* Format identifier */
1551dacebcadae36b35531d635d81df2afb937677b7aBehdad Esfahbod  ContextFormat1	format1;
1552dacebcadae36b35531d635d81df2afb937677b7aBehdad Esfahbod  ContextFormat2	format2;
1553dacebcadae36b35531d635d81df2afb937677b7aBehdad Esfahbod  ContextFormat3	format3;
155466bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod  } u;
155566bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod};
155666bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
1557ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod
1558ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod/* Chaining Contextual lookups */
1559ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod
156031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbodstruct ChainContextClosureLookupContext
156160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
156231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  ContextClosureFuncs funcs;
156331081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  const void *intersects_data[3];
156431081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod};
156531081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
1566f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbodstruct ChainContextCollectGlyphsLookupContext
1567f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod{
1568f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod  ContextCollectGlyphsFuncs funcs;
1569f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod  const void *collect_data[3];
1570f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod};
1571f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod
157231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbodstruct ChainContextApplyLookupContext
157331081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod{
157431081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  ContextApplyFuncs funcs;
157540cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbod  const void *match_data[3];
157648f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod};
157748f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod
15785caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbodstatic inline void chain_context_closure_lookup (hb_closure_context_t *c,
157931081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod						 unsigned int backtrackCount,
158031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod						 const USHORT backtrack[],
158131081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod						 unsigned int inputCount, /* Including the first glyph (not matched) */
158231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod						 const USHORT input[], /* Array of input values--start with second glyph */
158331081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod						 unsigned int lookaheadCount,
158431081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod						 const USHORT lookahead[],
158531081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod						 unsigned int lookupCount,
158631081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod						 const LookupRecord lookupRecord[],
158731081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod						 ChainContextClosureLookupContext &lookup_context)
158831081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod{
15895caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod  if (intersects_array (c,
15905caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod			backtrackCount, backtrack,
15915caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod			lookup_context.funcs.intersects, lookup_context.intersects_data[0])
15925caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod   && intersects_array (c,
15935caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod			inputCount ? inputCount - 1 : 0, input,
15945caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod			lookup_context.funcs.intersects, lookup_context.intersects_data[1])
159574439d0aa10184451adc6c6469f5119be352ecbbBehdad Esfahbod   && intersects_array (c,
15965caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod		       lookaheadCount, lookahead,
15975caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod		       lookup_context.funcs.intersects, lookup_context.intersects_data[2]))
1598d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod    recurse_lookups (c,
1599d0a5233785eb327c4080432f597fe470a1046af3Behdad Esfahbod		     lookupCount, lookupRecord);
160031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod}
160131081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
1602f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbodstatic inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
1603f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod						        unsigned int backtrackCount,
1604f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod						        const USHORT backtrack[],
1605f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod						        unsigned int inputCount, /* Including the first glyph (not matched) */
1606f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod						        const USHORT input[], /* Array of input values--start with second glyph */
1607f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod						        unsigned int lookaheadCount,
1608f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod						        const USHORT lookahead[],
1609f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod						        unsigned int lookupCount,
1610f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod						        const LookupRecord lookupRecord[],
1611f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod						        ChainContextCollectGlyphsLookupContext &lookup_context)
1612f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod{
16138303593ba1db06e402eab52df47f21f13049112dBehdad Esfahbod  collect_array (c, c->before,
1614f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod		 backtrackCount, backtrack,
1615f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod		 lookup_context.funcs.collect, lookup_context.collect_data[0]);
16168303593ba1db06e402eab52df47f21f13049112dBehdad Esfahbod  collect_array (c, c->input,
1617f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod		 inputCount ? inputCount - 1 : 0, input,
1618f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod		 lookup_context.funcs.collect, lookup_context.collect_data[1]);
16198303593ba1db06e402eab52df47f21f13049112dBehdad Esfahbod  collect_array (c, c->after,
1620f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod		 lookaheadCount, lookahead,
1621f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod		 lookup_context.funcs.collect, lookup_context.collect_data[2]);
1622f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod  recurse_lookups (c,
1623f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod		   lookupCount, lookupRecord);
1624f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod}
1625f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod
1626e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbodstatic inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
1627e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod						     unsigned int backtrackCount,
16280beb66e3a61ae8bb1fa66e54b1ff1abb2f8711e9Behdad Esfahbod						     const USHORT backtrack[] HB_UNUSED,
1629e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod						     unsigned int inputCount, /* Including the first glyph (not matched) */
1630e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod						     const USHORT input[], /* Array of input values--start with second glyph */
1631e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod						     unsigned int lookaheadCount,
16320beb66e3a61ae8bb1fa66e54b1ff1abb2f8711e9Behdad Esfahbod						     const USHORT lookahead[] HB_UNUSED,
16330beb66e3a61ae8bb1fa66e54b1ff1abb2f8711e9Behdad Esfahbod						     unsigned int lookupCount HB_UNUSED,
16340beb66e3a61ae8bb1fa66e54b1ff1abb2f8711e9Behdad Esfahbod						     const LookupRecord lookupRecord[] HB_UNUSED,
1635e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod						     ChainContextApplyLookupContext &lookup_context)
1636e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod{
1637d9b204d3d24cde165167714728bf380267903d6aBehdad Esfahbod  return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
16381f2bb172fe9a173ecfd61054f1fdd850943ef059Behdad Esfahbod      && would_match_input (c,
1639e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod			    inputCount, input,
1640e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod			    lookup_context.funcs.match, lookup_context.match_data[1]);
1641e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod}
1642e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
164331081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbodstatic inline bool chain_context_apply_lookup (hb_apply_context_t *c,
164431081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					       unsigned int backtrackCount,
164531081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					       const USHORT backtrack[],
164631081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					       unsigned int inputCount, /* Including the first glyph (not matched) */
164731081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					       const USHORT input[], /* Array of input values--start with second glyph */
164831081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					       unsigned int lookaheadCount,
164931081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					       const USHORT lookahead[],
165031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					       unsigned int lookupCount,
165131081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					       const LookupRecord lookupRecord[],
165231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod					       ChainContextApplyLookupContext &lookup_context)
165302e1e5c63fa4f896053fa3c21e495239e1e9caa2Behdad Esfahbod{
16546b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod  unsigned int match_length = 0;
16556b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod  unsigned int match_positions[MAX_CONTEXT_LENGTH];
1656f19e0b0099ec73b8fedccacff4902403f5eabc42Behdad Esfahbod  return match_input (c,
16574169710911450e0f9bc045fe279bfc8ba9e8457cBehdad Esfahbod		      inputCount, input,
16584169710911450e0f9bc045fe279bfc8ba9e8457cBehdad Esfahbod		      lookup_context.funcs.match, lookup_context.match_data[1],
16596b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod		      &match_length, match_positions)
1660f19e0b0099ec73b8fedccacff4902403f5eabc42Behdad Esfahbod      && match_backtrack (c,
1661f19e0b0099ec73b8fedccacff4902403f5eabc42Behdad Esfahbod			  backtrackCount, backtrack,
1662f19e0b0099ec73b8fedccacff4902403f5eabc42Behdad Esfahbod			  lookup_context.funcs.match, lookup_context.match_data[0])
1663d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod      && match_lookahead (c,
16644169710911450e0f9bc045fe279bfc8ba9e8457cBehdad Esfahbod			  lookaheadCount, lookahead,
16654169710911450e0f9bc045fe279bfc8ba9e8457cBehdad Esfahbod			  lookup_context.funcs.match, lookup_context.match_data[2],
16666b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod			  match_length)
16675df809b655bb1318115651fd87d4555cdd9b41cbBehdad Esfahbod      && apply_lookup (c,
16686b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod		       inputCount, match_positions,
16696b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod		       lookupCount, lookupRecord,
16706b65a76b40522a4f57a6fedcbdfc5a4d736f1d3cBehdad Esfahbod		       match_length);
167102e1e5c63fa4f896053fa3c21e495239e1e9caa2Behdad Esfahbod}
167248f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod
167360d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct ChainRule
167460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
16755caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod  inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
167631081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  {
1677be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_CLOSURE (this);
167831081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
167931081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
168031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
16815caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod    chain_context_closure_lookup (c,
16825caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod				  backtrack.len, backtrack.array,
16835caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod				  input.len, input.array,
16845caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod				  lookahead.len, lookahead.array,
16855caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod				  lookup.len, lookup.array,
16865caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod				  lookup_context);
168731081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  }
168831081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
1689f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
1690f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod  {
1691f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    TRACE_COLLECT_GLYPHS (this);
1692f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
1693f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
1694f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1695f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    chain_context_collect_glyphs_lookup (c,
1696f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod					 backtrack.len, backtrack.array,
1697f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod					 input.len, input.array,
1698f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod					 lookahead.len, lookahead.array,
1699f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod					 lookup.len, lookup.array,
1700f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod					 lookup_context);
1701f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod  }
1702f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod
1703e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
1704e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  {
1705be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_WOULD_APPLY (this);
1706e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
1707e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
1708e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1709e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    return TRACE_RETURN (chain_context_would_apply_lookup (c,
1710e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod							   backtrack.len, backtrack.array,
1711e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod							   input.len, input.array,
1712e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod							   lookahead.len, lookahead.array, lookup.len,
1713e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod							   lookup.array, lookup_context));
1714e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  }
1715e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
171631081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
171760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
1718be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_APPLY (this);
1719e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod    const HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
1720e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod    const ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
1721e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
1722acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod    return TRACE_RETURN (chain_context_apply_lookup (c,
1723acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod						     backtrack.len, backtrack.array,
1724acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod						     input.len, input.array,
1725acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod						     lookahead.len, lookahead.array, lookup.len,
1726acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod						     lookup.array, lookup_context));
1727aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod  }
1728aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod
1729d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
1730be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_SANITIZE (this);
17310ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    if (!backtrack.sanitize (c)) return TRACE_RETURN (false);
1732e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod    HeadlessArrayOf<USHORT> &input = StructAfter<HeadlessArrayOf<USHORT> > (backtrack);
17330ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    if (!input.sanitize (c)) return TRACE_RETURN (false);
1734e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod    ArrayOf<USHORT> &lookahead = StructAfter<ArrayOf<USHORT> > (input);
17350ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    if (!lookahead.sanitize (c)) return TRACE_RETURN (false);
1736e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod    ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
17370ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (lookup.sanitize (c));
173870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
1739ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod
1740ec8d2494694275dfbbac2dd0d33ca2894b0463d6Behdad Esfahbod  protected:
1741dcb6b60254951a2831c03f3196962d229f7e556cBehdad Esfahbod  ArrayOf<USHORT>
1742dcb6b60254951a2831c03f3196962d229f7e556cBehdad Esfahbod		backtrack;		/* Array of backtracking values
1743ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod					 * (to be matched before the input
1744ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod					 * sequence) */
1745e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod  HeadlessArrayOf<USHORT>
1746e8cbaaf6d538036ff9b880b018db402e0895ed01Behdad Esfahbod		inputX;			/* Array of input values (start with
1747ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod					 * second glyph) */
1748dcb6b60254951a2831c03f3196962d229f7e556cBehdad Esfahbod  ArrayOf<USHORT>
1749dcb6b60254951a2831c03f3196962d229f7e556cBehdad Esfahbod		lookaheadX;		/* Array of lookahead values's (to be
175048f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod					 * matched after the input sequence) */
1751dcb6b60254951a2831c03f3196962d229f7e556cBehdad Esfahbod  ArrayOf<LookupRecord>
175202e1e5c63fa4f896053fa3c21e495239e1e9caa2Behdad Esfahbod		lookupX;		/* Array of LookupRecords--in
1753ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod					 * design order) */
1754b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
1755bea34c7cbb583cf7660776e95cab3171590b8427Behdad Esfahbod  DEFINE_SIZE_MIN (8);
1756ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod};
1757ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod
175860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct ChainRuleSet
175960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
17605caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod  inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
176131081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  {
1762be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_CLOSURE (this);
176331081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    unsigned int num_rules = rule.len;
176431081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    for (unsigned int i = 0; i < num_rules; i++)
17655caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod      (this+rule[i]).closure (c, lookup_context);
176631081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  }
176731081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
1768f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod  inline void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
1769f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod  {
1770f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    TRACE_COLLECT_GLYPHS (this);
1771f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    unsigned int num_rules = rule.len;
1772f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    for (unsigned int i = 0; i < num_rules; i++)
1773f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod      (this+rule[i]).collect_glyphs (c, lookup_context);
1774f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod  }
1775f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod
1776e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  inline bool would_apply (hb_would_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
1777e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  {
1778be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_WOULD_APPLY (this);
1779e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    unsigned int num_rules = rule.len;
1780e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    for (unsigned int i = 0; i < num_rules; i++)
1781e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod      if ((this+rule[i]).would_apply (c, lookup_context))
1782e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod        return TRACE_RETURN (true);
1783e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
1784e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    return TRACE_RETURN (false);
1785e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  }
1786e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
178731081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod  inline bool apply (hb_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
178860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
1789be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_APPLY (this);
179048f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod    unsigned int num_rules = rule.len;
179160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod    for (unsigned int i = 0; i < num_rules; i++)
1792d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod      if ((this+rule[i]).apply (c, lookup_context))
1793acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod        return TRACE_RETURN (true);
179448f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod
1795acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod    return TRACE_RETURN (false);
179648f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod  }
1797ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod
1798d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
1799be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_SANITIZE (this);
18000ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (rule.sanitize (c, this));
180170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
180270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
1803ec8d2494694275dfbbac2dd0d33ca2894b0463d6Behdad Esfahbod  protected:
180448f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod  OffsetArrayOf<ChainRule>
180548f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod		rule;			/* Array of ChainRule tables
180648f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod					 * ordered by preference */
1807b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
18080eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod  DEFINE_SIZE_ARRAY (2, rule);
1809ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod};
1810ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod
181160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct ChainContextFormat1
181260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
181344fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  inline void closure (hb_closure_context_t *c) const
1814f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod  {
1815be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_CLOSURE (this);
181631081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    const Coverage &cov = (this+coverage);
181731081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
181831081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    struct ChainContextClosureLookupContext lookup_context = {
181944fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod      {intersects_glyph},
182031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod      {NULL, NULL, NULL}
182131081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    };
182231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
182331081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    unsigned int count = ruleSet.len;
182431081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
182531081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod      if (cov.intersects_coverage (c->glyphs, i)) {
182631081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod	const ChainRuleSet &rule_set = this+ruleSet[i];
18275caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod	rule_set.closure (c, lookup_context);
182831081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod      }
1829f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod  }
1830f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod
183126514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
183226514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  {
1833f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    TRACE_COLLECT_GLYPHS (this);
18348303593ba1db06e402eab52df47f21f13049112dBehdad Esfahbod    (this+coverage).add_coverage (c->input);
1835f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod
1836f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    struct ChainContextCollectGlyphsLookupContext lookup_context = {
1837f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod      {collect_glyph},
1838f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod      {NULL, NULL, NULL}
1839f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    };
1840f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod
1841f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    unsigned int count = ruleSet.len;
1842f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
1843f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
184426514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  }
184526514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod
1846e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  inline bool would_apply (hb_would_apply_context_t *c) const
1847e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  {
1848be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_WOULD_APPLY (this);
1849e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
1850b67881b171a7cf865af58df146da52fc1e27b160Behdad Esfahbod    const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
1851e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    struct ChainContextApplyLookupContext lookup_context = {
1852ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod      {match_glyph},
1853e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod      {NULL, NULL, NULL}
1854e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    };
1855e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
1856e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  }
1857e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
185844fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  inline const Coverage &get_coverage (void) const
185944fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  {
186044fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod    return this+coverage;
186144fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  }
186244fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod
1863ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod  inline bool apply (hb_apply_context_t *c) const
186460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
1865be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_APPLY (this);
1866b67881b171a7cf865af58df146da52fc1e27b160Behdad Esfahbod    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
1867acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
1868ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod
1869aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod    const ChainRuleSet &rule_set = this+ruleSet[index];
187031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    struct ChainContextApplyLookupContext lookup_context = {
1871ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod      {match_glyph},
1872aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod      {NULL, NULL, NULL}
1873aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod    };
1874acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod    return TRACE_RETURN (rule_set.apply (c, lookup_context));
1875aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod  }
187670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
1877d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
1878be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_SANITIZE (this);
18790ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
188070de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
188170de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
1882ec8d2494694275dfbbac2dd0d33ca2894b0463d6Behdad Esfahbod  protected:
1883ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod  USHORT	format;			/* Format identifier--format = 1 */
188448f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod  OffsetTo<Coverage>
188548f16ed96ac7041b511d9e0864623d2aa09c6da3Behdad Esfahbod		coverage;		/* Offset to Coverage table--from
1886ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod					 * beginning of table */
1887aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod  OffsetArrayOf<ChainRuleSet>
1888aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod		ruleSet;		/* Array of ChainRuleSet tables
1889aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod					 * ordered by Coverage Index */
1890b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
18910eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod  DEFINE_SIZE_ARRAY (6, ruleSet);
1892ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod};
1893ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod
189460d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct ChainContextFormat2
189560d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
189644fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  inline void closure (hb_closure_context_t *c) const
1897f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod  {
1898be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_CLOSURE (this);
189931081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    if (!(this+coverage).intersects (c->glyphs))
19005caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod      return;
190131081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
190231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    const ClassDef &backtrack_class_def = this+backtrackClassDef;
190331081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    const ClassDef &input_class_def = this+inputClassDef;
190431081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
190531081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
190631081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    struct ChainContextClosureLookupContext lookup_context = {
190744fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod      {intersects_class},
190831081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod      {&backtrack_class_def,
190931081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod       &input_class_def,
191031081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod       &lookahead_class_def}
191131081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    };
191231081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod
191331081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    unsigned int count = ruleSet.len;
191431081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
191531081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod      if (input_class_def.intersects_class (c->glyphs, i)) {
191631081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod	const ChainRuleSet &rule_set = this+ruleSet[i];
19175caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod	rule_set.closure (c, lookup_context);
191831081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod      }
1919f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod  }
1920f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod
192126514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
192226514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  {
1923f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    TRACE_COLLECT_GLYPHS (this);
19248303593ba1db06e402eab52df47f21f13049112dBehdad Esfahbod    (this+coverage).add_coverage (c->input);
1925f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod
192611fba79ee9383eb995ddf7eb924dd64c67e2df63Behdad Esfahbod    const ClassDef &backtrack_class_def = this+backtrackClassDef;
192711fba79ee9383eb995ddf7eb924dd64c67e2df63Behdad Esfahbod    const ClassDef &input_class_def = this+inputClassDef;
192811fba79ee9383eb995ddf7eb924dd64c67e2df63Behdad Esfahbod    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
192911fba79ee9383eb995ddf7eb924dd64c67e2df63Behdad Esfahbod
1930f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    struct ChainContextCollectGlyphsLookupContext lookup_context = {
1931f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod      {collect_class},
193211fba79ee9383eb995ddf7eb924dd64c67e2df63Behdad Esfahbod      {&backtrack_class_def,
193311fba79ee9383eb995ddf7eb924dd64c67e2df63Behdad Esfahbod       &input_class_def,
193411fba79ee9383eb995ddf7eb924dd64c67e2df63Behdad Esfahbod       &lookahead_class_def}
1935f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    };
1936f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod
1937f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    unsigned int count = ruleSet.len;
1938f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    for (unsigned int i = 0; i < count; i++)
1939f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod      (this+ruleSet[i]).collect_glyphs (c, lookup_context);
194026514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  }
194126514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod
1942e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  inline bool would_apply (hb_would_apply_context_t *c) const
1943e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  {
1944be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_WOULD_APPLY (this);
1945e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
194611fba79ee9383eb995ddf7eb924dd64c67e2df63Behdad Esfahbod    const ClassDef &backtrack_class_def = this+backtrackClassDef;
1947e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    const ClassDef &input_class_def = this+inputClassDef;
194811fba79ee9383eb995ddf7eb924dd64c67e2df63Behdad Esfahbod    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
1949e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
19502dc1141d7d0a9f5818862b09d6b9cfe0a27f1fc1Behdad Esfahbod    unsigned int index = input_class_def.get_class (c->glyphs[0]);
1951e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    const ChainRuleSet &rule_set = this+ruleSet[index];
1952e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    struct ChainContextApplyLookupContext lookup_context = {
1953ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod      {match_class},
195411fba79ee9383eb995ddf7eb924dd64c67e2df63Behdad Esfahbod      {&backtrack_class_def,
195511fba79ee9383eb995ddf7eb924dd64c67e2df63Behdad Esfahbod       &input_class_def,
195611fba79ee9383eb995ddf7eb924dd64c67e2df63Behdad Esfahbod       &lookahead_class_def}
1957e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    };
1958e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    return TRACE_RETURN (rule_set.would_apply (c, lookup_context));
1959e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  }
1960e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
196144fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  inline const Coverage &get_coverage (void) const
196244fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  {
196344fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod    return this+coverage;
196444fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  }
196544fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod
1966ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod  inline bool apply (hb_apply_context_t *c) const
196760d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
1968be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_APPLY (this);
1969b67881b171a7cf865af58df146da52fc1e27b160Behdad Esfahbod    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
1970acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
1971aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod
1972aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod    const ClassDef &backtrack_class_def = this+backtrackClassDef;
1973aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod    const ClassDef &input_class_def = this+inputClassDef;
1974aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
1975aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod
19762dc1141d7d0a9f5818862b09d6b9cfe0a27f1fc1Behdad Esfahbod    index = input_class_def.get_class (c->buffer->cur().codepoint);
1977aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod    const ChainRuleSet &rule_set = this+ruleSet[index];
197831081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    struct ChainContextApplyLookupContext lookup_context = {
1979ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod      {match_class},
198040cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbod      {&backtrack_class_def,
198140cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbod       &input_class_def,
198240cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbod       &lookahead_class_def}
1983aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod    };
1984acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod    return TRACE_RETURN (rule_set.apply (c, lookup_context));
1985ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod  }
1986ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod
1987d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
1988be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_SANITIZE (this);
19890ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (coverage.sanitize (c, this) && backtrackClassDef.sanitize (c, this) &&
19900ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod			 inputClassDef.sanitize (c, this) && lookaheadClassDef.sanitize (c, this) &&
19910ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod			 ruleSet.sanitize (c, this));
199270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
199370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
1994ec8d2494694275dfbbac2dd0d33ca2894b0463d6Behdad Esfahbod  protected:
1995ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod  USHORT	format;			/* Format identifier--format = 2 */
1996aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod  OffsetTo<Coverage>
1997aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod		coverage;		/* Offset to Coverage table--from
1998ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod					 * beginning of table */
1999aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod  OffsetTo<ClassDef>
2000aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod		backtrackClassDef;	/* Offset to glyph ClassDef table
2001ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod					 * containing backtrack sequence
2002ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod					 * data--from beginning of table */
2003aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod  OffsetTo<ClassDef>
2004aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod		inputClassDef;		/* Offset to glyph ClassDef
2005ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod					 * table containing input sequence
2006ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod					 * data--from beginning of table */
2007aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod  OffsetTo<ClassDef>
2008aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod		lookaheadClassDef;	/* Offset to glyph ClassDef table
2009ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod					 * containing lookahead sequence
2010ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod					 * data--from beginning of table */
2011aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod  OffsetArrayOf<ChainRuleSet>
2012aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod		ruleSet;		/* Array of ChainRuleSet tables
2013aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod					 * ordered by class */
2014b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
20150eb9fc6e37935707dba2bf4b3705de2161a08cb7Behdad Esfahbod  DEFINE_SIZE_ARRAY (12, ruleSet);
2016ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod};
2017ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod
201860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct ChainContextFormat3
201960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
202044fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  inline void closure (hb_closure_context_t *c) const
2021f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod  {
2022be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_CLOSURE (this);
20235caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
20245caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod
20255caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod    if (!(this+input[0]).intersects (c->glyphs))
20265caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod      return;
20275caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod
20285caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
20295caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
20305caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod    struct ChainContextClosureLookupContext lookup_context = {
203144fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod      {intersects_coverage},
20325caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod      {this, this, this}
20335caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod    };
20345caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod    chain_context_closure_lookup (c,
20355caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod				  backtrack.len, (const USHORT *) backtrack.array,
20365caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod				  input.len, (const USHORT *) input.array + 1,
20375caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod				  lookahead.len, (const USHORT *) lookahead.array,
20385caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod				  lookup.len, lookup.array,
20395caece67ab9eee322bdcdf6f4b607eadde297e56Behdad Esfahbod				  lookup_context);
2040f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod  }
2041f94b0aa64609654497ced9c00312c9643eb69053Behdad Esfahbod
204226514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
204326514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  {
2044f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    TRACE_COLLECT_GLYPHS (this);
2045f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
2046f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod
20478303593ba1db06e402eab52df47f21f13049112dBehdad Esfahbod    (this+input[0]).add_coverage (c->input);
2048f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod
2049f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2050f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
2051f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    struct ChainContextCollectGlyphsLookupContext lookup_context = {
2052f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod      {collect_coverage},
2053f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod      {this, this, this}
2054f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    };
2055f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod    chain_context_collect_glyphs_lookup (c,
2056f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod					 backtrack.len, (const USHORT *) backtrack.array,
2057f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod					 input.len, (const USHORT *) input.array + 1,
2058f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod					 lookahead.len, (const USHORT *) lookahead.array,
2059f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod					 lookup.len, lookup.array,
2060f1b12781d279a73b5754afee31e930b5cd87aac6Behdad Esfahbod					 lookup_context);
206126514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod  }
206226514d51b6669f092d9ccb7523443a5ece74169aBehdad Esfahbod
2063e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  inline bool would_apply (hb_would_apply_context_t *c) const
2064e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  {
2065be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_WOULD_APPLY (this);
2066e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
2067e6f7479fe34fb4a7cada61d84c2ed70d1fd565c8Behdad Esfahbod    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
2068e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2069e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
2070e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    struct ChainContextApplyLookupContext lookup_context = {
2071ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod      {match_coverage},
2072e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod      {this, this, this}
2073e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    };
2074e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    return TRACE_RETURN (chain_context_would_apply_lookup (c,
2075e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod							   backtrack.len, (const USHORT *) backtrack.array,
2076e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod							   input.len, (const USHORT *) input.array + 1,
2077e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod							   lookahead.len, (const USHORT *) lookahead.array,
2078e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod							   lookup.len, lookup.array, lookup_context));
2079e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  }
2080e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
208144fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  inline const Coverage &get_coverage (void) const
208244fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  {
208344fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
208444fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod    return this+input[0];
208544fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  }
208644fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod
2087ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod  inline bool apply (hb_apply_context_t *c) const
208860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod  {
2089be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_APPLY (this);
2090e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod    const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
209102e1e5c63fa4f896053fa3c21e495239e1e9caa2Behdad Esfahbod
2092b67881b171a7cf865af58df146da52fc1e27b160Behdad Esfahbod    unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
2093acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod    if (likely (index == NOT_COVERED)) return TRACE_RETURN (false);
209402e1e5c63fa4f896053fa3c21e495239e1e9caa2Behdad Esfahbod
2095e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod    const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
2096e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
209731081f7390e5130df72f89acc609ccab5dc77a48Behdad Esfahbod    struct ChainContextApplyLookupContext lookup_context = {
2098ec35a72a44301934b8f123ab2833f59d8c875a09Behdad Esfahbod      {match_coverage},
209940cbefe858192531ed64dd51d402f7ca7b8153a3Behdad Esfahbod      {this, this, this}
2100aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod    };
2101acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod    return TRACE_RETURN (chain_context_apply_lookup (c,
2102acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod						     backtrack.len, (const USHORT *) backtrack.array,
2103acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod						     input.len, (const USHORT *) input.array + 1,
2104acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod						     lookahead.len, (const USHORT *) lookahead.array,
2105acea183e986dd378c6f95120fe0feb0586a8ef36Behdad Esfahbod						     lookup.len, lookup.array, lookup_context));
2106aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod  }
2107aa3d7adca5c821c91a2a1b5380fd6b3d19656ab1Behdad Esfahbod
2108d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
2109be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_SANITIZE (this);
21100ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    if (!backtrack.sanitize (c, this)) return TRACE_RETURN (false);
2111e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod    OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
21120ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    if (!input.sanitize (c, this)) return TRACE_RETURN (false);
21139df0a520306a491f973d42965597bfda6023e508Behdad Esfahbod    if (!input.len) return TRACE_RETURN (false); /* To be consistent with Context. */
2114e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod    OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
21150ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    if (!lookahead.sanitize (c, this)) return TRACE_RETURN (false);
2116e961c86c579fd98ee604342a9c70c4e7f8d4f220Behdad Esfahbod    ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord> > (lookahead);
21170ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (lookup.sanitize (c));
211870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
211970de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
2120ec8d2494694275dfbbac2dd0d33ca2894b0463d6Behdad Esfahbod  protected:
2121ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod  USHORT	format;			/* Format identifier--format = 3 */
2122dcb6b60254951a2831c03f3196962d229f7e556cBehdad Esfahbod  OffsetArrayOf<Coverage>
212313ed4405c558e445b052360f1ed8ee27ecf48e6eBehdad Esfahbod		backtrack;		/* Array of coverage tables
2124ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod					 * in backtracking sequence, in  glyph
2125ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod					 * sequence order */
2126dcb6b60254951a2831c03f3196962d229f7e556cBehdad Esfahbod  OffsetArrayOf<Coverage>
212713ed4405c558e445b052360f1ed8ee27ecf48e6eBehdad Esfahbod		inputX		;	/* Array of coverage
2128ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod					 * tables in input sequence, in glyph
2129ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod					 * sequence order */
2130dcb6b60254951a2831c03f3196962d229f7e556cBehdad Esfahbod  OffsetArrayOf<Coverage>
213113ed4405c558e445b052360f1ed8ee27ecf48e6eBehdad Esfahbod		lookaheadX;		/* Array of coverage tables
2132ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod					 * in lookahead sequence, in glyph
2133ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod					 * sequence order */
2134dcb6b60254951a2831c03f3196962d229f7e556cBehdad Esfahbod  ArrayOf<LookupRecord>
213502e1e5c63fa4f896053fa3c21e495239e1e9caa2Behdad Esfahbod		lookupX;		/* Array of LookupRecords--in
2136dcb6b60254951a2831c03f3196962d229f7e556cBehdad Esfahbod					 * design order) */
2137b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
2138bea34c7cbb583cf7660776e95cab3171590b8427Behdad Esfahbod  DEFINE_SIZE_MIN (10);
2139ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod};
2140ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod
214160d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct ChainContext
214260d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
214344fc237b53ebfbaf8a539de16ad735d2c6afc52bBehdad Esfahbod  template <typename context_t>
21449c5a9ee967120c8a968a1160c420e03620d46c24Behdad Esfahbod  inline typename context_t::return_t dispatch (context_t *c) const
2145e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod  {
214600f6a8e334ec4c586e4e633a95b411ccb50306d3Behdad Esfahbod    TRACE_DISPATCH (this, u.format);
2147e8cfdd7fa8d0fb66e0a261f3547e5824897e5131Behdad Esfahbod    switch (u.format) {
21489c5a9ee967120c8a968a1160c420e03620d46c24Behdad Esfahbod    case 1: return TRACE_RETURN (c->dispatch (u.format1));
21499c5a9ee967120c8a968a1160c420e03620d46c24Behdad Esfahbod    case 2: return TRACE_RETURN (c->dispatch (u.format2));
21509c5a9ee967120c8a968a1160c420e03620d46c24Behdad Esfahbod    case 3: return TRACE_RETURN (c->dispatch (u.format3));
2151f48ec0e83432c038b50d9715a38ba1469e82e1e4Behdad Esfahbod    default:return TRACE_RETURN (c->default_return_value ());
2152e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod    }
2153e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod  }
2154e72b360ac6381b549249b8836fa3e70b909d3437Behdad Esfahbod
2155d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
2156be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_SANITIZE (this);
21570ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
215870de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    switch (u.format) {
21590ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    case 1: return TRACE_RETURN (u.format1.sanitize (c));
21600ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    case 2: return TRACE_RETURN (u.format2.sanitize (c));
21610ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    case 3: return TRACE_RETURN (u.format3.sanitize (c));
21620ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    default:return TRACE_RETURN (true);
216370de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    }
216470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
216570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
2166ec8d2494694275dfbbac2dd0d33ca2894b0463d6Behdad Esfahbod  protected:
2167ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod  union {
2168ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod  USHORT		format;	/* Format identifier */
2169dacebcadae36b35531d635d81df2afb937677b7aBehdad Esfahbod  ChainContextFormat1	format1;
2170dacebcadae36b35531d635d81df2afb937677b7aBehdad Esfahbod  ChainContextFormat2	format2;
2171dacebcadae36b35531d635d81df2afb937677b7aBehdad Esfahbod  ChainContextFormat3	format3;
2172ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod  } u;
2173ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod};
2174ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod
2175ca5290f4994e1b2db4dac03f7a22b7071441ba06Behdad Esfahbod
2176d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbodstruct ExtensionFormat1
2177d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod{
2178d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod  inline unsigned int get_type (void) const { return extensionLookupType; }
21793b2c2df41b90f2a1d9e33b3dc15a92cff58a689aBehdad Esfahbod  inline unsigned int get_offset (void) const { return extensionOffset; }
2180d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod
2181d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
2182be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_SANITIZE (this);
21830ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (c->check_struct (this));
218470de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
218570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
2186ec8d2494694275dfbbac2dd0d33ca2894b0463d6Behdad Esfahbod  protected:
2187d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod  USHORT	format;			/* Format identifier. Set to 1. */
2188d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod  USHORT	extensionLookupType;	/* Lookup type of subtable referenced
2189d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod					 * by ExtensionOffset (i.e. the
2190d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod					 * extension subtable). */
219181f2af40f9afd5bb9695018e6baddcd4aa3361c1Behdad Esfahbod  ULONG		extensionOffset;	/* Offset to the extension subtable,
219281f2af40f9afd5bb9695018e6baddcd4aa3361c1Behdad Esfahbod					 * of lookup type subtable. */
2193b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
2194b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  DEFINE_SIZE_STATIC (8);
2195d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod};
2196d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod
2197653eeb26450053b731b46346606931f5ae88db72Behdad Esfahbodtemplate <typename T>
2198d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbodstruct Extension
2199d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod{
2200d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod  inline unsigned int get_type (void) const
2201d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod  {
2202d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod    switch (u.format) {
2203dacebcadae36b35531d635d81df2afb937677b7aBehdad Esfahbod    case 1: return u.format1.get_type ();
2204d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod    default:return 0;
2205d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod    }
2206d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod  }
22073b2c2df41b90f2a1d9e33b3dc15a92cff58a689aBehdad Esfahbod  inline unsigned int get_offset (void) const
2208d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod  {
2209d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod    switch (u.format) {
2210dacebcadae36b35531d635d81df2afb937677b7aBehdad Esfahbod    case 1: return u.format1.get_offset ();
22113b2c2df41b90f2a1d9e33b3dc15a92cff58a689aBehdad Esfahbod    default:return 0;
2212d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod    }
2213d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod  }
2214d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod
22157dddd4e72bc35be962d93dc1b76c7e26c63aaa6dBehdad Esfahbod  template <typename X>
22167dddd4e72bc35be962d93dc1b76c7e26c63aaa6dBehdad Esfahbod  inline const X& get_subtable (void) const
22177dddd4e72bc35be962d93dc1b76c7e26c63aaa6dBehdad Esfahbod  {
22187dddd4e72bc35be962d93dc1b76c7e26c63aaa6dBehdad Esfahbod    unsigned int offset = get_offset ();
22197dddd4e72bc35be962d93dc1b76c7e26c63aaa6dBehdad Esfahbod    if (unlikely (!offset)) return Null(typename T::LookupSubTable);
22207dddd4e72bc35be962d93dc1b76c7e26c63aaa6dBehdad Esfahbod    return StructAtOffset<typename T::LookupSubTable> (this, offset);
22217dddd4e72bc35be962d93dc1b76c7e26c63aaa6dBehdad Esfahbod  }
22227dddd4e72bc35be962d93dc1b76c7e26c63aaa6dBehdad Esfahbod
2223653eeb26450053b731b46346606931f5ae88db72Behdad Esfahbod  template <typename context_t>
22249c5a9ee967120c8a968a1160c420e03620d46c24Behdad Esfahbod  inline typename context_t::return_t dispatch (context_t *c) const
2225653eeb26450053b731b46346606931f5ae88db72Behdad Esfahbod  {
22269c5a9ee967120c8a968a1160c420e03620d46c24Behdad Esfahbod    return get_subtable<typename T::LookupSubTable> ().dispatch (c, get_type ());
2227653eeb26450053b731b46346606931f5ae88db72Behdad Esfahbod  }
2228653eeb26450053b731b46346606931f5ae88db72Behdad Esfahbod
2229ed2e13594479c6ed7909401509962ea2f03f9a6eBehdad Esfahbod  inline bool sanitize_self (hb_sanitize_context_t *c) {
2230be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_SANITIZE (this);
22310ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
223270de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    switch (u.format) {
22330ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    case 1: return TRACE_RETURN (u.format1.sanitize (c));
22340ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    default:return TRACE_RETURN (true);
223570de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod    }
223670de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod  }
223770de50c11ed7037b20eb6814ff60f6e32a9944e4Behdad Esfahbod
2238ed2e13594479c6ed7909401509962ea2f03f9a6eBehdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
2239ed2e13594479c6ed7909401509962ea2f03f9a6eBehdad Esfahbod    TRACE_SANITIZE (this);
2240ed2e13594479c6ed7909401509962ea2f03f9a6eBehdad Esfahbod    if (!sanitize_self (c)) return TRACE_RETURN (false);
2241ed2e13594479c6ed7909401509962ea2f03f9a6eBehdad Esfahbod    unsigned int offset = get_offset ();
2242ed2e13594479c6ed7909401509962ea2f03f9a6eBehdad Esfahbod    if (unlikely (!offset)) return TRACE_RETURN (true);
2243ed2e13594479c6ed7909401509962ea2f03f9a6eBehdad Esfahbod    return TRACE_RETURN (StructAtOffset<typename T::LookupSubTable> (this, offset).sanitize (c, get_type ()));
2244ed2e13594479c6ed7909401509962ea2f03f9a6eBehdad Esfahbod  }
2245ed2e13594479c6ed7909401509962ea2f03f9a6eBehdad Esfahbod
2246ec8d2494694275dfbbac2dd0d33ca2894b0463d6Behdad Esfahbod  protected:
2247d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod  union {
2248d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod  USHORT		format;		/* Format identifier */
22496d08c7f1b3601095f9a12630045331dd0fe75380Behdad Esfahbod  ExtensionFormat1	format1;
2250d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod  } u;
2251d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod};
2252d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod
2253d468f9af5b9fdc2713b0b86f28129e4190ee5053Behdad Esfahbod
2254f45107fe0904414f1266648a6c42849c494fe611Behdad Esfahbod/*
2255f45107fe0904414f1266648a6c42849c494fe611Behdad Esfahbod * GSUB/GPOS Common
2256f45107fe0904414f1266648a6c42849c494fe611Behdad Esfahbod */
2257f45107fe0904414f1266648a6c42849c494fe611Behdad Esfahbod
225860d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbodstruct GSUBGPOS
225960d77cf05fddc5304b4b1fc19cdedba15cbee1e9Behdad Esfahbod{
2260a328d66e6a8122f7d4d71941449d4d0136203e08Behdad Esfahbod  static const hb_tag_t GSUBTag	= HB_OT_TAG_GSUB;
2261a328d66e6a8122f7d4d71941449d4d0136203e08Behdad Esfahbod  static const hb_tag_t GPOSTag	= HB_OT_TAG_GPOS;
2262f45107fe0904414f1266648a6c42849c494fe611Behdad Esfahbod
2263bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline unsigned int get_script_count (void) const
2264bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return (this+scriptList).len; }
2265bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline const Tag& get_script_tag (unsigned int i) const
2266bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return (this+scriptList).get_tag (i); }
2267e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  inline unsigned int get_script_tags (unsigned int start_offset,
2268e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				       unsigned int *script_count /* IN/OUT */,
2269e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod				       hb_tag_t     *script_tags /* OUT */) const
2270e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
2271bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline const Script& get_script (unsigned int i) const
2272bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return (this+scriptList)[i]; }
2273bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline bool find_script_index (hb_tag_t tag, unsigned int *index) const
2274bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return (this+scriptList).find_index (tag, index); }
2275bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
2276bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline unsigned int get_feature_count (void) const
2277bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return (this+featureList).len; }
2278da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew  inline hb_tag_t get_feature_tag (unsigned int i) const
2279da132937989acb4d8ca9bd41c79f98750e7dda30Jonathan Kew  { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
2280e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  inline unsigned int get_feature_tags (unsigned int start_offset,
2281e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					unsigned int *feature_count /* IN/OUT */,
2282e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod					hb_tag_t     *feature_tags /* OUT */) const
2283e21899bc3593aa0d3adf64cee21c5de2ea219783Behdad Esfahbod  { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
2284bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline const Feature& get_feature (unsigned int i) const
2285bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return (this+featureList)[i]; }
2286bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline bool find_feature_index (hb_tag_t tag, unsigned int *index) const
2287bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return (this+featureList).find_index (tag, index); }
2288bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod
2289bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline unsigned int get_lookup_count (void) const
2290bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return (this+lookupList).len; }
2291bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  inline const Lookup& get_lookup (unsigned int i) const
2292bff3c0fde5da04a70d1f7aeeb9fa2a75fe5c07f6Behdad Esfahbod  { return (this+lookupList)[i]; }
2293f45107fe0904414f1266648a6c42849c494fe611Behdad Esfahbod
2294d7cfb3b2d1dd2e9fdae2b3e540bbe313660895e8Behdad Esfahbod  inline bool sanitize (hb_sanitize_context_t *c) {
2295be218c688cbb037a99c8c64bb835f3c980040c0bBehdad Esfahbod    TRACE_SANITIZE (this);
22960ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod    return TRACE_RETURN (version.sanitize (c) && likely (version.major == 1) &&
22970ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod			 scriptList.sanitize (c, this) &&
22980ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod			 featureList.sanitize (c, this) &&
22990ab8c8621712d33e1e91dfdb4ad0b335e3d2a3fbBehdad Esfahbod			 lookupList.sanitize (c, this));
2300cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod  }
2301cd3827ee567612c5500206b62840702fc956e0f5Behdad Esfahbod
2302212aba6189d7aaac0bab169b77ae6bdab16800a5Behdad Esfahbod  protected:
230387fcdcbe3644da10154688765db2d62eb9ac079aBehdad Esfahbod  FixedVersion	version;	/* Version of the GSUB/GPOS table--initially set
23047627100f428ac0ec8509d961d368d2d25d8f0b6eBehdad Esfahbod				 * to 0x00010000u */
2305f45107fe0904414f1266648a6c42849c494fe611Behdad Esfahbod  OffsetTo<ScriptList>
2306f45107fe0904414f1266648a6c42849c494fe611Behdad Esfahbod		scriptList;  	/* ScriptList table */
2307f45107fe0904414f1266648a6c42849c494fe611Behdad Esfahbod  OffsetTo<FeatureList>
2308f45107fe0904414f1266648a6c42849c494fe611Behdad Esfahbod		featureList; 	/* FeatureList table */
2309f45107fe0904414f1266648a6c42849c494fe611Behdad Esfahbod  OffsetTo<LookupList>
2310f45107fe0904414f1266648a6c42849c494fe611Behdad Esfahbod		lookupList; 	/* LookupList table */
2311b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  public:
2312b3651231bf80bb7009214547a75ed90e21815c68Behdad Esfahbod  DEFINE_SIZE_STATIC (10);
2313f45107fe0904414f1266648a6c42849c494fe611Behdad Esfahbod};
231466bf7ce4e3135535c110a917178b84c4a2b1d11fBehdad Esfahbod
23156f20f72e9c58ba23db2e31afa5d331acfea3d77eBehdad Esfahbod
23167d52e6601f0e695690cd168a288466746cf25300Behdad Esfahbod} /* namespace OT */
23177c8e844d92aa604fc4b396343721ea90eb83adb8Behdad Esfahbod
2318acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod
23195f5b24f99f52bbc922e238b65c06061ba07c8548Behdad Esfahbod#endif /* HB_OT_LAYOUT_GSUBGPOS_PRIVATE_HH */
2320