Coverage Report

Created: 2025-08-29 06:20

/src/harfbuzz/src/hb-ot-layout-gsubgpos.hh
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright © 2007,2008,2009,2010  Red Hat, Inc.
3
 * Copyright © 2010,2012  Google, Inc.
4
 *
5
 *  This is part of HarfBuzz, a text shaping library.
6
 *
7
 * Permission is hereby granted, without written agreement and without
8
 * license or royalty fees, to use, copy, modify, and distribute this
9
 * software and its documentation for any purpose, provided that the
10
 * above copyright notice and the following two paragraphs appear in
11
 * all copies of this software.
12
 *
13
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17
 * DAMAGE.
18
 *
19
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
22
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24
 *
25
 * Red Hat Author(s): Behdad Esfahbod
26
 * Google Author(s): Behdad Esfahbod
27
 */
28
29
#ifndef HB_OT_LAYOUT_GSUBGPOS_HH
30
#define HB_OT_LAYOUT_GSUBGPOS_HH
31
32
#include "hb.hh"
33
#include "hb-buffer.hh"
34
#include "hb-map.hh"
35
#include "hb-set.hh"
36
#include "hb-ot-map.hh"
37
#include "hb-ot-layout-common.hh"
38
#include "hb-ot-layout-gdef-table.hh"
39
40
41
namespace OT {
42
43
44
struct hb_intersects_context_t :
45
       hb_dispatch_context_t<hb_intersects_context_t, bool>
46
{
47
  template <typename T>
48
0
  return_t dispatch (const T &obj) { return obj.intersects (this->glyphs); }
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::Layout::GPOS_impl::SinglePosFormat1>(OT::Layout::GPOS_impl::SinglePosFormat1 const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::Layout::GPOS_impl::SinglePosFormat2>(OT::Layout::GPOS_impl::SinglePosFormat2 const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::Layout::GPOS_impl::PairPosFormat1_3<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::PairPosFormat1_3<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::Layout::GPOS_impl::CursivePosFormat1>(OT::Layout::GPOS_impl::CursivePosFormat1 const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::Layout::GPOS_impl::MarkBasePosFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::MarkBasePosFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::Layout::GPOS_impl::MarkLigPosFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::MarkLigPosFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::ContextFormat1_4<OT::Layout::SmallTypes> >(OT::ContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::ContextFormat2_5<OT::Layout::SmallTypes> >(OT::ContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::ContextFormat3>(OT::ContextFormat3 const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::ChainContextFormat1_4<OT::Layout::SmallTypes> >(OT::ChainContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::ChainContextFormat2_5<OT::Layout::SmallTypes> >(OT::ChainContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::ChainContextFormat3>(OT::ChainContextFormat3 const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_intersects_context_t::dispatch<OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1>(OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1 const&)
49
0
  static return_t default_return_value () { return false; }
50
0
  bool stop_sublookup_iteration (return_t r) const { return r; }
51
52
  const hb_set_t *glyphs;
53
54
  hb_intersects_context_t (const hb_set_t *glyphs_) :
55
0
                            glyphs (glyphs_) {}
56
};
57
58
struct hb_have_non_1to1_context_t :
59
       hb_dispatch_context_t<hb_have_non_1to1_context_t, bool>
60
{
61
  template <typename T>
62
0
  return_t dispatch (const T &obj) { return obj.may_have_non_1to1 (); }
Unexecuted instantiation: bool OT::hb_have_non_1to1_context_t::dispatch<OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_have_non_1to1_context_t::dispatch<OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_have_non_1to1_context_t::dispatch<OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_have_non_1to1_context_t::dispatch<OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_have_non_1to1_context_t::dispatch<OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_have_non_1to1_context_t::dispatch<OT::ContextFormat1_4<OT::Layout::SmallTypes> >(OT::ContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_have_non_1to1_context_t::dispatch<OT::ContextFormat2_5<OT::Layout::SmallTypes> >(OT::ContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_have_non_1to1_context_t::dispatch<OT::ContextFormat3>(OT::ContextFormat3 const&)
Unexecuted instantiation: bool OT::hb_have_non_1to1_context_t::dispatch<OT::ChainContextFormat1_4<OT::Layout::SmallTypes> >(OT::ChainContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_have_non_1to1_context_t::dispatch<OT::ChainContextFormat2_5<OT::Layout::SmallTypes> >(OT::ChainContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_have_non_1to1_context_t::dispatch<OT::ChainContextFormat3>(OT::ChainContextFormat3 const&)
Unexecuted instantiation: bool OT::hb_have_non_1to1_context_t::dispatch<OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1>(OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1 const&)
63
0
  static return_t default_return_value () { return false; }
64
0
  bool stop_sublookup_iteration (return_t r) const { return r; }
65
};
66
67
struct hb_closure_context_t :
68
       hb_dispatch_context_t<hb_closure_context_t>
69
{
70
  typedef return_t (*recurse_func_t) (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indicies, unsigned seq_index, unsigned end_index);
71
  template <typename T>
72
0
  return_t dispatch (const T &obj) { obj.closure (this); return hb_empty_t (); }
Unexecuted instantiation: hb_empty_t OT::hb_closure_context_t::dispatch<OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_context_t::dispatch<OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_context_t::dispatch<OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_context_t::dispatch<OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_context_t::dispatch<OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_context_t::dispatch<OT::ContextFormat1_4<OT::Layout::SmallTypes> >(OT::ContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_context_t::dispatch<OT::ContextFormat2_5<OT::Layout::SmallTypes> >(OT::ContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_context_t::dispatch<OT::ContextFormat3>(OT::ContextFormat3 const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_context_t::dispatch<OT::ChainContextFormat1_4<OT::Layout::SmallTypes> >(OT::ChainContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_context_t::dispatch<OT::ChainContextFormat2_5<OT::Layout::SmallTypes> >(OT::ChainContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_context_t::dispatch<OT::ChainContextFormat3>(OT::ChainContextFormat3 const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_context_t::dispatch<OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1>(OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1 const&)
73
0
  static return_t default_return_value () { return hb_empty_t (); }
74
  void recurse (unsigned lookup_index, hb_set_t *covered_seq_indicies, unsigned seq_index, unsigned end_index)
75
0
  {
76
0
    if (unlikely (nesting_level_left == 0 || !recurse_func))
77
0
      return;
78
79
0
    nesting_level_left--;
80
0
    recurse_func (this, lookup_index, covered_seq_indicies, seq_index, end_index);
81
0
    nesting_level_left++;
82
0
  }
83
84
  void reset_lookup_visit_count ()
85
0
  { lookup_count = 0; }
86
87
  bool lookup_limit_exceeded ()
88
0
  { return lookup_count > HB_MAX_LOOKUP_VISIT_COUNT; }
89
90
  bool should_visit_lookup (unsigned int lookup_index)
91
0
  {
92
0
    if (lookup_count++ > HB_MAX_LOOKUP_VISIT_COUNT)
93
0
      return false;
94
95
0
    if (is_lookup_done (lookup_index))
96
0
      return false;
97
98
0
    return true;
99
0
  }
100
101
  bool is_lookup_done (unsigned int lookup_index)
102
0
  {
103
0
    if (unlikely (done_lookups_glyph_count->in_error () ||
104
0
      done_lookups_glyph_set->in_error ()))
105
0
      return true;
106
107
    /* Have we visited this lookup with the current set of glyphs? */
108
0
    if (done_lookups_glyph_count->get (lookup_index) != glyphs->get_population ())
109
0
    {
110
0
      done_lookups_glyph_count->set (lookup_index, glyphs->get_population ());
111
112
0
      if (!done_lookups_glyph_set->has (lookup_index))
113
0
      {
114
0
  if (unlikely (!done_lookups_glyph_set->set (lookup_index, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
115
0
    return true;
116
0
      }
117
118
0
      done_lookups_glyph_set->get (lookup_index)->clear ();
119
0
    }
120
121
0
    hb_set_t *covered_glyph_set = done_lookups_glyph_set->get (lookup_index);
122
0
    if (unlikely (covered_glyph_set->in_error ()))
123
0
      return true;
124
0
    if (parent_active_glyphs ().is_subset (*covered_glyph_set))
125
0
      return true;
126
127
0
    covered_glyph_set->union_ (parent_active_glyphs ());
128
0
    return false;
129
0
  }
130
131
0
  const hb_set_t& previous_parent_active_glyphs () {
132
0
    if (active_glyphs_stack.length <= 1)
133
0
      return *glyphs;
134
135
0
    return active_glyphs_stack[active_glyphs_stack.length - 2];
136
0
  }
137
138
  const hb_set_t& parent_active_glyphs ()
139
0
  {
140
0
    if (!active_glyphs_stack)
141
0
      return *glyphs;
142
143
0
    return active_glyphs_stack.tail ();
144
0
  }
145
146
  hb_set_t* push_cur_active_glyphs ()
147
0
  {
148
0
    hb_set_t *s = active_glyphs_stack.push ();
149
0
    if (unlikely (active_glyphs_stack.in_error ()))
150
0
      return nullptr;
151
0
    return s;
152
0
  }
153
154
  bool pop_cur_done_glyphs ()
155
0
  {
156
0
    if (!active_glyphs_stack)
157
0
      return false;
158
159
0
    active_glyphs_stack.pop ();
160
0
    return true;
161
0
  }
162
163
  hb_face_t *face;
164
  hb_set_t *glyphs;
165
  hb_set_t output[1];
166
  hb_vector_t<hb_set_t> active_glyphs_stack;
167
  recurse_func_t recurse_func = nullptr;
168
  unsigned int nesting_level_left;
169
170
  hb_closure_context_t (hb_face_t *face_,
171
      hb_set_t *glyphs_,
172
      hb_map_t *done_lookups_glyph_count_,
173
      hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *done_lookups_glyph_set_,
174
      unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
175
0
        face (face_),
176
0
        glyphs (glyphs_),
177
0
        nesting_level_left (nesting_level_left_),
178
0
        done_lookups_glyph_count (done_lookups_glyph_count_),
179
0
        done_lookups_glyph_set (done_lookups_glyph_set_)
180
0
  {}
181
182
0
  ~hb_closure_context_t () { flush (); }
183
184
0
  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
185
186
  void flush ()
187
0
  {
188
0
    output->del_range (face->get_num_glyphs (), HB_SET_VALUE_INVALID);  /* Remove invalid glyphs. */
189
0
    glyphs->union_ (*output);
190
0
    output->clear ();
191
0
    active_glyphs_stack.pop ();
192
0
    active_glyphs_stack.reset ();
193
0
  }
194
195
  private:
196
  hb_map_t *done_lookups_glyph_count;
197
  hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *done_lookups_glyph_set;
198
  unsigned int lookup_count = 0;
199
};
200
201
202
203
struct hb_closure_lookups_context_t :
204
       hb_dispatch_context_t<hb_closure_lookups_context_t>
205
{
206
  typedef return_t (*recurse_func_t) (hb_closure_lookups_context_t *c, unsigned lookup_index);
207
  template <typename T>
208
0
  return_t dispatch (const T &obj) { obj.closure_lookups (this); return hb_empty_t (); }
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::Layout::GPOS_impl::SinglePosFormat1>(OT::Layout::GPOS_impl::SinglePosFormat1 const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::Layout::GPOS_impl::SinglePosFormat2>(OT::Layout::GPOS_impl::SinglePosFormat2 const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::Layout::GPOS_impl::PairPosFormat1_3<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::PairPosFormat1_3<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::Layout::GPOS_impl::CursivePosFormat1>(OT::Layout::GPOS_impl::CursivePosFormat1 const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::Layout::GPOS_impl::MarkBasePosFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::MarkBasePosFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::Layout::GPOS_impl::MarkLigPosFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::MarkLigPosFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::ContextFormat1_4<OT::Layout::SmallTypes> >(OT::ContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::ContextFormat2_5<OT::Layout::SmallTypes> >(OT::ContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::ContextFormat3>(OT::ContextFormat3 const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::ChainContextFormat1_4<OT::Layout::SmallTypes> >(OT::ChainContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::ChainContextFormat2_5<OT::Layout::SmallTypes> >(OT::ChainContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::ChainContextFormat3>(OT::ChainContextFormat3 const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_closure_lookups_context_t::dispatch<OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1>(OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1 const&)
209
0
  static return_t default_return_value () { return hb_empty_t (); }
210
  void recurse (unsigned lookup_index)
211
0
  {
212
0
    if (unlikely (nesting_level_left == 0 || !recurse_func))
213
0
      return;
214
0
215
0
    /* Return if new lookup was recursed to before. */
216
0
    if (lookup_limit_exceeded ()
217
0
        || visited_lookups->in_error ()
218
0
        || visited_lookups->has (lookup_index))
219
0
      // Don't increment lookup count here, that will be done in the call to closure_lookups()
220
0
      // made by recurse_func.
221
0
      return;
222
0
223
0
    nesting_level_left--;
224
0
    recurse_func (this, lookup_index);
225
0
    nesting_level_left++;
226
0
  }
227
228
  void set_lookup_visited (unsigned lookup_index)
229
0
  { visited_lookups->add (lookup_index); }
230
231
  void set_lookup_inactive (unsigned lookup_index)
232
0
  { inactive_lookups->add (lookup_index); }
233
234
  bool lookup_limit_exceeded ()
235
0
  {
236
0
    bool ret = lookup_count > HB_MAX_LOOKUP_VISIT_COUNT;
237
0
    if (ret)
238
0
      DEBUG_MSG (SUBSET, nullptr, "lookup visit count limit exceeded in lookup closure!");
239
0
    return ret; }
240
241
  bool is_lookup_visited (unsigned lookup_index)
242
0
  {
243
0
    if (unlikely (lookup_count++ > HB_MAX_LOOKUP_VISIT_COUNT))
244
0
    {
245
0
      DEBUG_MSG (SUBSET, nullptr, "total visited lookup count %u exceeds max limit, lookup %u is dropped.",
246
0
                 lookup_count, lookup_index);
247
0
      return true;
248
0
    }
249
0
250
0
    if (unlikely (visited_lookups->in_error ()))
251
0
      return true;
252
0
253
0
    return visited_lookups->has (lookup_index);
254
0
  }
255
256
  hb_face_t *face;
257
  const hb_set_t *glyphs;
258
  recurse_func_t recurse_func;
259
  unsigned int nesting_level_left;
260
261
  hb_closure_lookups_context_t (hb_face_t *face_,
262
        const hb_set_t *glyphs_,
263
        hb_set_t *visited_lookups_,
264
        hb_set_t *inactive_lookups_,
265
        unsigned nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
266
        face (face_),
267
        glyphs (glyphs_),
268
        recurse_func (nullptr),
269
        nesting_level_left (nesting_level_left_),
270
        visited_lookups (visited_lookups_),
271
        inactive_lookups (inactive_lookups_),
272
0
        lookup_count (0) {}
273
274
0
  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
275
276
  private:
277
  hb_set_t *visited_lookups;
278
  hb_set_t *inactive_lookups;
279
  unsigned int lookup_count;
280
};
281
282
struct hb_would_apply_context_t :
283
       hb_dispatch_context_t<hb_would_apply_context_t, bool>
284
{
285
  template <typename T>
286
0
  return_t dispatch (const T &obj) { return obj.would_apply (this); }
Unexecuted instantiation: bool OT::hb_would_apply_context_t::dispatch<OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_would_apply_context_t::dispatch<OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_would_apply_context_t::dispatch<OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_would_apply_context_t::dispatch<OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_would_apply_context_t::dispatch<OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_would_apply_context_t::dispatch<OT::ContextFormat1_4<OT::Layout::SmallTypes> >(OT::ContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_would_apply_context_t::dispatch<OT::ContextFormat2_5<OT::Layout::SmallTypes> >(OT::ContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_would_apply_context_t::dispatch<OT::ContextFormat3>(OT::ContextFormat3 const&)
Unexecuted instantiation: bool OT::hb_would_apply_context_t::dispatch<OT::ChainContextFormat1_4<OT::Layout::SmallTypes> >(OT::ChainContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_would_apply_context_t::dispatch<OT::ChainContextFormat2_5<OT::Layout::SmallTypes> >(OT::ChainContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_would_apply_context_t::dispatch<OT::ChainContextFormat3>(OT::ChainContextFormat3 const&)
Unexecuted instantiation: bool OT::hb_would_apply_context_t::dispatch<OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1>(OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1 const&)
287
0
  static return_t default_return_value () { return false; }
288
0
  bool stop_sublookup_iteration (return_t r) const { return r; }
289
290
  hb_face_t *face;
291
  const hb_codepoint_t *glyphs;
292
  unsigned int len;
293
  bool zero_context;
294
295
  hb_would_apply_context_t (hb_face_t *face_,
296
          const hb_codepoint_t *glyphs_,
297
          unsigned int len_,
298
          bool zero_context_) :
299
0
            face (face_),
300
0
            glyphs (glyphs_),
301
0
            len (len_),
302
0
            zero_context (zero_context_) {}
303
};
304
305
struct hb_collect_glyphs_context_t :
306
       hb_dispatch_context_t<hb_collect_glyphs_context_t>
307
{
308
  typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
309
  template <typename T>
310
0
  return_t dispatch (const T &obj) { obj.collect_glyphs (this); return hb_empty_t (); }
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::Layout::GPOS_impl::SinglePosFormat1>(OT::Layout::GPOS_impl::SinglePosFormat1 const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::Layout::GPOS_impl::SinglePosFormat2>(OT::Layout::GPOS_impl::SinglePosFormat2 const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::Layout::GPOS_impl::PairPosFormat1_3<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::PairPosFormat1_3<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::Layout::GPOS_impl::CursivePosFormat1>(OT::Layout::GPOS_impl::CursivePosFormat1 const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::Layout::GPOS_impl::MarkBasePosFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::MarkBasePosFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::Layout::GPOS_impl::MarkLigPosFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::MarkLigPosFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::ContextFormat1_4<OT::Layout::SmallTypes> >(OT::ContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::ContextFormat2_5<OT::Layout::SmallTypes> >(OT::ContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::ContextFormat3>(OT::ContextFormat3 const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::ChainContextFormat1_4<OT::Layout::SmallTypes> >(OT::ChainContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::ChainContextFormat2_5<OT::Layout::SmallTypes> >(OT::ChainContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::ChainContextFormat3>(OT::ChainContextFormat3 const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_glyphs_context_t::dispatch<OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1>(OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1 const&)
311
0
  static return_t default_return_value () { return hb_empty_t (); }
312
  void recurse (unsigned int lookup_index)
313
0
  {
314
0
    if (unlikely (nesting_level_left == 0 || !recurse_func))
315
0
      return;
316
317
    /* Note that GPOS sets recurse_func to nullptr already, so it doesn't get
318
     * past the previous check.  For GSUB, we only want to collect the output
319
     * glyphs in the recursion.  If output is not requested, we can go home now.
320
     *
321
     * Note further, that the above is not exactly correct.  A recursed lookup
322
     * is allowed to match input that is not matched in the context, but that's
323
     * not how most fonts are built.  It's possible to relax that and recurse
324
     * with all sets here if it proves to be an issue.
325
     */
326
327
0
    if (output == hb_set_get_empty ())
328
0
      return;
329
330
    /* Return if new lookup was recursed to before. */
331
0
    if (recursed_lookups->has (lookup_index))
332
0
      return;
333
334
0
    hb_set_t *old_before = before;
335
0
    hb_set_t *old_input  = input;
336
0
    hb_set_t *old_after  = after;
337
0
    before = input = after = hb_set_get_empty ();
338
339
0
    nesting_level_left--;
340
0
    recurse_func (this, lookup_index);
341
0
    nesting_level_left++;
342
343
0
    before = old_before;
344
0
    input  = old_input;
345
0
    after  = old_after;
346
347
0
    recursed_lookups->add (lookup_index);
348
0
  }
349
350
  hb_face_t *face;
351
  hb_set_t *before;
352
  hb_set_t *input;
353
  hb_set_t *after;
354
  hb_set_t *output;
355
  recurse_func_t recurse_func;
356
  hb_set_t *recursed_lookups;
357
  unsigned int nesting_level_left;
358
359
  hb_collect_glyphs_context_t (hb_face_t *face_,
360
             hb_set_t  *glyphs_before, /* OUT.  May be NULL */
361
             hb_set_t  *glyphs_input,  /* OUT.  May be NULL */
362
             hb_set_t  *glyphs_after,  /* OUT.  May be NULL */
363
             hb_set_t  *glyphs_output, /* OUT.  May be NULL */
364
             unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
365
0
            face (face_),
366
0
            before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
367
0
            input  (glyphs_input  ? glyphs_input  : hb_set_get_empty ()),
368
0
            after  (glyphs_after  ? glyphs_after  : hb_set_get_empty ()),
369
0
            output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
370
0
            recurse_func (nullptr),
371
0
            recursed_lookups (hb_set_create ()),
372
0
            nesting_level_left (nesting_level_left_) {}
373
0
  ~hb_collect_glyphs_context_t () { hb_set_destroy (recursed_lookups); }
374
375
0
  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
376
};
377
378
379
380
template <typename set_t>
381
struct hb_collect_coverage_context_t :
382
       hb_dispatch_context_t<hb_collect_coverage_context_t<set_t>, const Coverage &>
383
{
384
  typedef const Coverage &return_t; // Stoopid that we have to dupe this here.
385
  template <typename T>
386
  return_t dispatch (const T &obj) { return obj.get_coverage (); }
387
  static return_t default_return_value () { return Null (Coverage); }
388
  bool stop_sublookup_iteration (return_t r) const
389
  {
390
    r.collect_coverage (set);
391
    return false;
392
  }
393
394
  hb_collect_coverage_context_t (set_t *set_) :
395
           set (set_) {}
396
397
  set_t *set;
398
};
399
400
struct matcher_t
401
{
402
  typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data);
403
404
  template <typename context_t>
405
  void init (const context_t *c, bool context_match = false)
406
493k
  {
407
493k
    set_match_func (nullptr, nullptr);
408
493k
    lookup_props = c->lookup_props;
409
    /* Ignore ZWNJ if we are matching GPOS, or matching GSUB context and asked to. */
410
493k
    ignore_zwnj = c->table_index == 1 || (context_match && c->auto_zwnj);
411
    /* Ignore ZWJ if we are matching context, or asked to. */
412
493k
    ignore_zwj = context_match || c->auto_zwj;
413
    /* Ignore hidden glyphs (like CGJ) during GPOS. */
414
493k
    ignore_hidden = c->table_index == 1;
415
493k
    mask = context_match ? -1 : c->lookup_mask;
416
    /* Per syllable matching is only for GSUB. */
417
493k
    per_syllable = c->table_index == 0 && c->per_syllable;
418
493k
    syllable = 0;
419
493k
  }
420
421
  void set_match_func (match_func_t match_func_,
422
           const void *match_data_)
423
493k
  { match_func = match_func_; match_data = match_data_; }
424
425
  enum may_match_t {
426
    MATCH_NO,
427
    MATCH_YES,
428
    MATCH_MAYBE
429
  };
430
431
#ifndef HB_OPTIMIZE_SIZE
432
  HB_ALWAYS_INLINE
433
#endif
434
  may_match_t may_match (hb_glyph_info_t &info,
435
       hb_codepoint_t glyph_data) const
436
0
  {
437
0
    if (!(info.mask & mask) ||
438
0
  (per_syllable && syllable && syllable != info.syllable ()))
439
0
      return MATCH_NO;
440
441
0
    if (match_func)
442
0
      return match_func (info, glyph_data, match_data) ? MATCH_YES : MATCH_NO;
443
444
0
    return MATCH_MAYBE;
445
0
  }
446
447
  enum may_skip_t {
448
    SKIP_NO,
449
    SKIP_YES,
450
    SKIP_MAYBE
451
  };
452
453
  template <typename context_t>
454
#ifndef HB_OPTIMIZE_SIZE
455
  HB_ALWAYS_INLINE
456
#endif
457
  may_skip_t may_skip (const context_t *c,
458
           const hb_glyph_info_t &info) const
459
0
  {
460
0
    if (!c->check_glyph_property (&info, lookup_props))
461
0
      return SKIP_YES;
462
463
0
    if (unlikely (_hb_glyph_info_is_default_ignorable (&info) &&
464
0
      (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
465
0
      (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) &&
466
0
      (ignore_hidden || !_hb_glyph_info_is_hidden (&info))))
467
0
      return SKIP_MAYBE;
468
469
0
    return SKIP_NO;
470
0
  }
471
472
  public:
473
  unsigned int lookup_props = 0;
474
  hb_mask_t mask = -1;
475
  bool ignore_zwnj = false;
476
  bool ignore_zwj = false;
477
  bool ignore_hidden = false;
478
  bool per_syllable = false;
479
  uint8_t syllable = 0;
480
  match_func_t match_func = nullptr;
481
  const void *match_data = nullptr;
482
};
483
484
template <typename context_t>
485
struct skipping_iterator_t
486
{
487
  void init (context_t *c_, bool context_match = false)
488
493k
  {
489
493k
    c = c_;
490
493k
    end = c->buffer->len;
491
493k
    match_glyph_data16 = nullptr;
492
#ifndef HB_NO_BEYOND_64K
493
    match_glyph_data24 = nullptr;
494
#endif
495
493k
    matcher.init (c, context_match);
496
493k
  }
497
  void set_lookup_props (unsigned int lookup_props)
498
0
  {
499
0
    matcher.lookup_props = lookup_props;
500
0
  }
501
  void set_match_func (matcher_t::match_func_t match_func_,
502
           const void *match_data_)
503
0
  {
504
0
    matcher.set_match_func (match_func_, match_data_);
505
0
  }
506
  void set_glyph_data (const HBUINT16 glyph_data[])
507
0
  {
508
0
    match_glyph_data16 = glyph_data;
509
#ifndef HB_NO_BEYOND_64K
510
    match_glyph_data24 = nullptr;
511
#endif
512
0
  }
513
#ifndef HB_NO_BEYOND_64K
514
  void set_glyph_data (const HBUINT24 glyph_data[])
515
  {
516
    match_glyph_data16 = nullptr;
517
    match_glyph_data24 = glyph_data;
518
  }
519
#endif
520
521
#ifndef HB_OPTIMIZE_SIZE
522
  HB_ALWAYS_INLINE
523
#endif
524
  void reset (unsigned int start_index_)
525
0
  {
526
0
    idx = start_index_;
527
0
    end = c->buffer->len;
528
0
    matcher.syllable = start_index_ == c->buffer->idx ? c->buffer->cur().syllable () : 0;
529
0
  }
530
531
#ifndef HB_OPTIMIZE_SIZE
532
  HB_ALWAYS_INLINE
533
#endif
534
  void reset_fast (unsigned int start_index_)
535
0
  {
536
    // Doesn't set end or syllable. Used by GPOS which doesn't care / change.
537
0
    idx = start_index_;
538
0
  }
539
540
#ifndef HB_OPTIMIZE_SIZE
541
  HB_ALWAYS_INLINE
542
#endif
543
  matcher_t::may_skip_t may_skip (const hb_glyph_info_t &info) const
544
0
  { return matcher.may_skip (c, info); }
545
546
  enum match_t {
547
    MATCH,
548
    NOT_MATCH,
549
    SKIP
550
  };
551
552
#ifndef HB_OPTIMIZE_SIZE
553
  HB_ALWAYS_INLINE
554
#endif
555
  match_t match (hb_glyph_info_t &info)
556
0
  {
557
0
    matcher_t::may_skip_t skip = matcher.may_skip (c, info);
558
0
    if (unlikely (skip == matcher_t::SKIP_YES))
559
0
      return SKIP;
560
561
0
    matcher_t::may_match_t match = matcher.may_match (info, get_glyph_data ());
562
0
    if (match == matcher_t::MATCH_YES ||
563
0
  (match == matcher_t::MATCH_MAYBE &&
564
0
   skip == matcher_t::SKIP_NO))
565
0
      return MATCH;
566
567
0
    if (skip == matcher_t::SKIP_NO)
568
0
      return NOT_MATCH;
569
570
0
    return SKIP;
571
0
  }
572
573
#ifndef HB_OPTIMIZE_SIZE
574
  HB_ALWAYS_INLINE
575
#endif
576
  bool next (unsigned *unsafe_to = nullptr)
577
0
  {
578
0
    const signed stop = (signed) end - 1;
579
0
    while ((signed) idx < stop)
580
0
    {
581
0
      idx++;
582
0
      switch (match (c->buffer->info[idx]))
583
0
      {
584
0
  case MATCH:
585
0
  {
586
0
    advance_glyph_data ();
587
0
    return true;
588
0
  }
589
0
  case NOT_MATCH:
590
0
  {
591
0
    if (unsafe_to)
592
0
      *unsafe_to = idx + 1;
593
0
    return false;
594
0
  }
595
0
  case SKIP:
596
0
    continue;
597
0
      }
598
0
    }
599
0
    if (unsafe_to)
600
0
      *unsafe_to = end;
601
0
    return false;
602
0
  }
603
#ifndef HB_OPTIMIZE_SIZE
604
  HB_ALWAYS_INLINE
605
#endif
606
  bool prev (unsigned *unsafe_from = nullptr)
607
0
  {
608
0
    const unsigned stop = 0;
609
0
    while (idx > stop)
610
0
    {
611
0
      idx--;
612
0
      switch (match (c->buffer->out_info[idx]))
613
0
      {
614
0
  case MATCH:
615
0
  {
616
0
    advance_glyph_data ();
617
0
    return true;
618
0
  }
619
0
  case NOT_MATCH:
620
0
  {
621
0
    if (unsafe_from)
622
0
      *unsafe_from = hb_max (1u, idx) - 1u;
623
0
    return false;
624
0
  }
625
0
  case SKIP:
626
0
    continue;
627
0
      }
628
0
    }
629
0
    if (unsafe_from)
630
0
      *unsafe_from = 0;
631
0
    return false;
632
0
  }
633
634
  HB_ALWAYS_INLINE
635
  hb_codepoint_t
636
  get_glyph_data ()
637
0
  {
638
0
    if (match_glyph_data16) return *match_glyph_data16;
639
#ifndef HB_NO_BEYOND_64K
640
    else
641
    if (match_glyph_data24) return *match_glyph_data24;
642
#endif
643
0
    return 0;
644
0
  }
645
  HB_ALWAYS_INLINE
646
  void
647
  advance_glyph_data ()
648
0
  {
649
0
    if (match_glyph_data16) match_glyph_data16++;
650
#ifndef HB_NO_BEYOND_64K
651
    else
652
    if (match_glyph_data24) match_glyph_data24++;
653
#endif
654
0
  }
655
656
  unsigned int idx;
657
  protected:
658
  context_t *c;
659
  matcher_t matcher;
660
  const HBUINT16 *match_glyph_data16;
661
#ifndef HB_NO_BEYOND_64K
662
  const HBUINT24 *match_glyph_data24;
663
#endif
664
665
  unsigned int end;
666
};
667
668
struct hb_ot_apply_context_t :
669
       hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
670
{
671
0
  const char *get_name () { return "APPLY"; }
672
  typedef return_t (*recurse_func_t) (hb_ot_apply_context_t *c, unsigned int lookup_index);
673
674
  template <typename T>
675
  static inline auto apply_ (const T &obj, hb_ot_apply_context_t *c, hb_priority<1>) HB_RETURN (return_t, obj.apply (c, nullptr) )
676
  template <typename T>
677
  static inline auto apply_ (const T &obj, hb_ot_apply_context_t *c, hb_priority<0>) HB_RETURN (return_t, obj.apply (c) )
678
  template <typename T>
679
0
  return_t dispatch (const T &obj) { return apply_(obj, this, hb_prioritize); }
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::Layout::GPOS_impl::SinglePosFormat1>(OT::Layout::GPOS_impl::SinglePosFormat1 const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::Layout::GPOS_impl::SinglePosFormat2>(OT::Layout::GPOS_impl::SinglePosFormat2 const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::Layout::GPOS_impl::PairPosFormat1_3<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::PairPosFormat1_3<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::Layout::GPOS_impl::CursivePosFormat1>(OT::Layout::GPOS_impl::CursivePosFormat1 const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::Layout::GPOS_impl::MarkBasePosFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::MarkBasePosFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::Layout::GPOS_impl::MarkLigPosFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::MarkLigPosFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::ContextFormat1_4<OT::Layout::SmallTypes> >(OT::ContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::ContextFormat2_5<OT::Layout::SmallTypes> >(OT::ContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::ContextFormat3>(OT::ContextFormat3 const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::ChainContextFormat1_4<OT::Layout::SmallTypes> >(OT::ChainContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::ChainContextFormat2_5<OT::Layout::SmallTypes> >(OT::ChainContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::ChainContextFormat3>(OT::ChainContextFormat3 const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: bool OT::hb_ot_apply_context_t::dispatch<OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1>(OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1 const&)
680
681
0
  static return_t default_return_value () { return false; }
682
0
  bool stop_sublookup_iteration (return_t r) const { return r; }
683
  return_t recurse (unsigned int sub_lookup_index)
684
0
  {
685
0
    assert (recurse_func);
686
0
    if (unlikely (nesting_level_left == 0))
687
0
    {
688
0
      buffer->successful = false;
689
0
      return default_return_value ();
690
0
    }
691
692
0
    buffer->max_ops--;
693
0
    if (unlikely (buffer->max_ops < 0))
694
0
    {
695
0
      buffer->successful = false;
696
0
      return default_return_value ();
697
0
    }
698
699
0
    nesting_level_left--;
700
0
    bool ret = recurse_func (this, sub_lookup_index);
701
0
    nesting_level_left++;
702
0
    return ret;
703
0
  }
704
705
  skipping_iterator_t<hb_ot_apply_context_t> iter_input, iter_context;
706
707
  unsigned int table_index; /* GSUB/GPOS */
708
  hb_font_t *font;
709
  hb_face_t *face;
710
  hb_buffer_t *buffer;
711
  hb_sanitize_context_t sanitizer;
712
  recurse_func_t recurse_func = nullptr;
713
  const GDEF &gdef;
714
  const GDEF::accelerator_t &gdef_accel;
715
  const hb_ot_layout_lookup_accelerator_t *lookup_accel = nullptr;
716
  const ItemVariationStore &var_store;
717
  hb_scalar_cache_t *var_store_cache;
718
  hb_set_digest_t digest;
719
720
  hb_direction_t direction;
721
  hb_mask_t lookup_mask = 1;
722
  unsigned int lookup_index = (unsigned) -1;
723
  unsigned int lookup_props = 0;
724
  unsigned int nesting_level_left = HB_MAX_NESTING_LEVEL;
725
726
  bool has_glyph_classes;
727
  bool auto_zwnj = true;
728
  bool auto_zwj = true;
729
  bool per_syllable = false;
730
  bool random = false;
731
  unsigned new_syllables = (unsigned) -1;
732
733
  signed last_base = -1; // GPOS uses
734
  unsigned last_base_until = 0; // GPOS uses
735
736
  hb_vector_t<uint32_t> match_positions;
737
  uint32_t stack_match_positions[8];
738
739
  hb_ot_apply_context_t (unsigned int table_index_,
740
       hb_font_t *font_,
741
       hb_buffer_t *buffer_,
742
       hb_blob_t *table_blob_,
743
       hb_scalar_cache_t *var_store_cache_ = nullptr) :
744
246k
      table_index (table_index_),
745
246k
      font (font_), face (font->face), buffer (buffer_),
746
246k
      sanitizer (table_blob_),
747
      gdef (
748
#ifndef HB_NO_OT_LAYOUT
749
246k
            *face->table.GDEF->table
750
#else
751
            Null (GDEF)
752
#endif
753
           ),
754
      gdef_accel (
755
#ifndef HB_NO_OT_LAYOUT
756
246k
            *face->table.GDEF
757
#else
758
            Null (GDEF::accelerator_t)
759
#endif
760
           ),
761
246k
      var_store (gdef.get_var_store ()),
762
246k
      var_store_cache (var_store_cache_),
763
246k
      direction (buffer_->props.direction),
764
246k
      has_glyph_classes (gdef.has_glyph_classes ())
765
246k
  {
766
246k
    init_iters ();
767
246k
    buffer->collect_codepoints (digest);
768
246k
    match_positions.set_storage (stack_match_positions);
769
246k
  }
770
771
  void init_iters ()
772
246k
  {
773
246k
    iter_input.init (this, false);
774
246k
    iter_context.init (this, true);
775
246k
  }
776
777
32
  void set_lookup_mask (hb_mask_t mask, bool init = true) { lookup_mask = mask; last_base = -1; last_base_until = 0; if (init) init_iters (); }
778
0
  void set_auto_zwj (bool auto_zwj_, bool init = true) { auto_zwj = auto_zwj_; if (init) init_iters (); }
779
0
  void set_auto_zwnj (bool auto_zwnj_, bool init = true) { auto_zwnj = auto_zwnj_; if (init) init_iters (); }
780
0
  void set_per_syllable (bool per_syllable_, bool init = true) { per_syllable = per_syllable_; if (init) init_iters (); }
781
0
  void set_random (bool random_) { random = random_; }
782
246k
  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
783
0
  void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
784
32
  void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; init_iters (); }
785
786
  uint32_t random_number ()
787
0
  {
788
    /* http://www.cplusplus.com/reference/random/minstd_rand/ */
789
0
    buffer->random_state = buffer->random_state * 48271 % 2147483647;
790
0
    return buffer->random_state;
791
0
  }
792
793
  HB_ALWAYS_INLINE
794
  HB_HOT
795
  bool match_properties_mark (const hb_glyph_info_t *info,
796
            unsigned int    glyph_props,
797
            unsigned int    match_props) const
798
0
  {
799
    /* If using mark filtering sets, the high short of
800
     * match_props has the set index.
801
     */
802
0
    if (match_props & LookupFlag::UseMarkFilteringSet)
803
0
      return gdef_accel.mark_set_covers (match_props >> 16, info->codepoint);
804
805
    /* The second byte of match_props has the meaning
806
     * "ignore marks of attachment type different than
807
     * the attachment type specified."
808
     */
809
0
    if (match_props & LookupFlag::MarkAttachmentType)
810
0
      return (match_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
811
812
0
    return true;
813
0
  }
814
815
#ifndef HB_OPTIMIZE_SIZE
816
  HB_ALWAYS_INLINE
817
#endif
818
  bool check_glyph_property (const hb_glyph_info_t *info,
819
           unsigned match_props) const
820
0
  {
821
0
    unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info);
822
823
    /* Not covered, if, for example, glyph class is ligature and
824
     * match_props includes LookupFlags::IgnoreLigatures
825
     */
826
0
    if (glyph_props & match_props & LookupFlag::IgnoreFlags)
827
0
      return false;
828
829
0
    if (unlikely (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK))
830
0
      return match_properties_mark (info, glyph_props, match_props);
831
832
0
    return true;
833
0
  }
834
835
  void _set_glyph_class (hb_codepoint_t glyph_index,
836
        unsigned int class_guess = 0,
837
        bool ligature = false,
838
        bool component = false)
839
0
  {
840
0
    digest.add (glyph_index);
841
842
0
    if (new_syllables != (unsigned) -1)
843
0
      buffer->cur().syllable() = new_syllables;
844
845
0
    unsigned int props = _hb_glyph_info_get_glyph_props (&buffer->cur());
846
0
    props |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
847
0
    if (ligature)
848
0
    {
849
0
      props |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
850
      /* In the only place that the MULTIPLIED bit is used, Uniscribe
851
       * seems to only care about the "last" transformation between
852
       * Ligature and Multiple substitutions.  Ie. if you ligate, expand,
853
       * and ligate again, it forgives the multiplication and acts as
854
       * if only ligation happened.  As such, clear MULTIPLIED bit.
855
       */
856
0
      props &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
857
0
    }
858
0
    if (component)
859
0
      props |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
860
0
    if (likely (has_glyph_classes))
861
0
    {
862
0
      props &= HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
863
0
      _hb_glyph_info_set_glyph_props (&buffer->cur(), props | gdef_accel.get_glyph_props (glyph_index));
864
0
    }
865
0
    else if (class_guess)
866
0
    {
867
0
      props &= HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
868
0
      _hb_glyph_info_set_glyph_props (&buffer->cur(), props | class_guess);
869
0
    }
870
0
    else
871
0
      _hb_glyph_info_set_glyph_props (&buffer->cur(), props);
872
0
  }
873
874
  void replace_glyph (hb_codepoint_t glyph_index)
875
0
  {
876
0
    _set_glyph_class (glyph_index);
877
0
    (void) buffer->replace_glyph (glyph_index);
878
0
  }
879
  void replace_glyph_inplace (hb_codepoint_t glyph_index)
880
0
  {
881
0
    _set_glyph_class (glyph_index);
882
0
    buffer->cur().codepoint = glyph_index;
883
0
  }
884
  void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
885
            unsigned int class_guess)
886
0
  {
887
0
    _set_glyph_class (glyph_index, class_guess, true);
888
0
    (void) buffer->replace_glyph (glyph_index);
889
0
  }
890
  void output_glyph_for_component (hb_codepoint_t glyph_index,
891
           unsigned int class_guess)
892
0
  {
893
0
    _set_glyph_class (glyph_index, class_guess, false, true);
894
0
    (void) buffer->output_glyph (glyph_index);
895
0
  }
896
};
897
898
enum class hb_ot_subtable_cache_op_t
899
{
900
  ENTER,
901
  LEAVE,
902
};
903
904
struct hb_accelerate_subtables_context_t :
905
       hb_dispatch_context_t<hb_accelerate_subtables_context_t>
906
{
907
  template <typename T>
908
  static inline auto apply_ (const T *obj, hb_ot_apply_context_t *c, void *external_cache, hb_priority<1>) HB_RETURN (bool, obj->apply (c, external_cache) )
909
  template <typename T>
910
  static inline auto apply_ (const T *obj, hb_ot_apply_context_t *c, void *external_cache, hb_priority<0>) HB_RETURN (bool, obj->apply (c) )
911
  template <typename T>
912
  static inline bool apply_to (const void *obj, hb_ot_apply_context_t *c, void *external_cache)
913
0
  {
914
0
    const T *typed_obj = (const T *) obj;
915
0
    return apply_ (typed_obj, c, external_cache, hb_prioritize);
916
0
  }
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::Layout::GPOS_impl::SinglePosFormat1>(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::Layout::GPOS_impl::SinglePosFormat2>(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::Layout::GPOS_impl::PairPosFormat1_3<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::Layout::GPOS_impl::CursivePosFormat1>(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::Layout::GPOS_impl::MarkBasePosFormat1_2<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::Layout::GPOS_impl::MarkLigPosFormat1_2<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::ContextFormat1_4<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::ContextFormat2_5<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::ContextFormat3>(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::ChainContextFormat1_4<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::ChainContextFormat2_5<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::ChainContextFormat3>(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_to<OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1>(void const*, OT::hb_ot_apply_context_t*, void*)
917
918
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
919
  template <typename T>
920
  static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, void *external_cache, hb_priority<2>) HB_RETURN (bool, obj->apply_cached (c, external_cache) )
921
  template <typename T>
922
  static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, void *external_cache, hb_priority<1>) HB_RETURN (bool, obj->apply (c, external_cache) )
923
  template <typename T>
924
  static inline auto apply_cached_ (const T *obj, hb_ot_apply_context_t *c, void *external_cache, hb_priority<0>) HB_RETURN (bool, obj->apply (c) )
925
  template <typename T>
926
  static inline bool apply_cached_to (const void *obj, hb_ot_apply_context_t *c, void *external_cache)
927
0
  {
928
0
    const T *typed_obj = (const T *) obj;
929
0
    return apply_cached_ (typed_obj, c, external_cache, hb_prioritize);
930
0
  }
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::Layout::GPOS_impl::SinglePosFormat1>(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::Layout::GPOS_impl::SinglePosFormat2>(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::Layout::GPOS_impl::PairPosFormat1_3<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::Layout::GPOS_impl::CursivePosFormat1>(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::Layout::GPOS_impl::MarkBasePosFormat1_2<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::Layout::GPOS_impl::MarkLigPosFormat1_2<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::ContextFormat1_4<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::ContextFormat2_5<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::ContextFormat3>(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::ChainContextFormat1_4<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::ChainContextFormat2_5<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::ChainContextFormat3>(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> >(void const*, OT::hb_ot_apply_context_t*, void*)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::apply_cached_to<OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1>(void const*, OT::hb_ot_apply_context_t*, void*)
931
932
  template <typename T>
933
  static inline auto cache_func_ (hb_ot_apply_context_t *c,
934
          hb_ot_subtable_cache_op_t op,
935
          hb_priority<1>) HB_RETURN (bool, T::cache_func (c, op) )
936
  template <typename T=void>
937
  static inline bool cache_func_ (hb_ot_apply_context_t *c,
938
          hb_ot_subtable_cache_op_t op HB_UNUSED,
939
0
          hb_priority<0>) { return false; }
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_<OT::Layout::GPOS_impl::SinglePosFormat1>(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t, hb_priority<0u>)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_<OT::Layout::GPOS_impl::SinglePosFormat2>(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t, hb_priority<0u>)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_<OT::Layout::GPOS_impl::PairPosFormat1_3<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t, hb_priority<0u>)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_<OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t, hb_priority<0u>)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_<OT::Layout::GPOS_impl::CursivePosFormat1>(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t, hb_priority<0u>)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_<OT::Layout::GPOS_impl::MarkBasePosFormat1_2<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t, hb_priority<0u>)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_<OT::Layout::GPOS_impl::MarkLigPosFormat1_2<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t, hb_priority<0u>)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_<OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t, hb_priority<0u>)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_<OT::ContextFormat1_4<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t, hb_priority<0u>)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_<OT::ContextFormat3>(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t, hb_priority<0u>)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_<OT::ChainContextFormat1_4<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t, hb_priority<0u>)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_<OT::ChainContextFormat3>(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t, hb_priority<0u>)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_<OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t, hb_priority<0u>)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_<OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t, hb_priority<0u>)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_<OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t, hb_priority<0u>)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_<OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t, hb_priority<0u>)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_<OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t, hb_priority<0u>)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_<OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1>(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t, hb_priority<0u>)
940
  template <typename Type>
941
  static inline bool cache_func_to (hb_ot_apply_context_t *c,
942
            hb_ot_subtable_cache_op_t op)
943
0
  {
944
0
    return cache_func_<Type> (c, op, hb_prioritize);
945
0
  }
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::Layout::GPOS_impl::SinglePosFormat1>(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::Layout::GPOS_impl::SinglePosFormat2>(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::Layout::GPOS_impl::PairPosFormat1_3<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::Layout::GPOS_impl::CursivePosFormat1>(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::Layout::GPOS_impl::MarkBasePosFormat1_2<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::Layout::GPOS_impl::MarkLigPosFormat1_2<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::ContextFormat1_4<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::ContextFormat2_5<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::ContextFormat3>(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::ChainContextFormat1_4<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::ChainContextFormat2_5<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::ChainContextFormat3>(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> >(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: bool OT::hb_accelerate_subtables_context_t::cache_func_to<OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1>(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
946
#endif
947
948
  typedef bool (*hb_apply_func_t) (const void *obj, hb_ot_apply_context_t *c, void *external_cache);
949
  typedef bool (*hb_cache_func_t) (hb_ot_apply_context_t *c, hb_ot_subtable_cache_op_t op);
950
951
  struct hb_applicable_t
952
  {
953
    friend struct hb_accelerate_subtables_context_t;
954
    friend struct hb_ot_layout_lookup_accelerator_t;
955
956
    template <typename T>
957
    void init (const T &obj_,
958
         hb_apply_func_t apply_func_
959
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
960
         , hb_apply_func_t apply_cached_func_
961
         , hb_cache_func_t cache_func_
962
         , void *external_cache_
963
#endif
964
    )
965
155
    {
966
155
      obj = &obj_;
967
155
      apply_func = apply_func_;
968
155
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
969
155
      apply_cached_func = apply_cached_func_;
970
155
      cache_func = cache_func_;
971
155
      external_cache = external_cache_;
972
155
#endif
973
155
      digest.init ();
974
155
      obj_.get_coverage ().collect_coverage (&digest);
975
155
    }
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::Layout::GPOS_impl::SinglePosFormat1>(OT::Layout::GPOS_impl::SinglePosFormat1 const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::Layout::GPOS_impl::SinglePosFormat2>(OT::Layout::GPOS_impl::SinglePosFormat2 const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::Layout::GPOS_impl::PairPosFormat1_3<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::PairPosFormat1_3<OT::Layout::SmallTypes> const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::SmallTypes> const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::Layout::GPOS_impl::CursivePosFormat1>(OT::Layout::GPOS_impl::CursivePosFormat1 const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::Layout::GPOS_impl::MarkBasePosFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::MarkBasePosFormat1_2<OT::Layout::SmallTypes> const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
Line
Count
Source
965
54
    {
966
54
      obj = &obj_;
967
54
      apply_func = apply_func_;
968
54
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
969
54
      apply_cached_func = apply_cached_func_;
970
54
      cache_func = cache_func_;
971
54
      external_cache = external_cache_;
972
54
#endif
973
54
      digest.init ();
974
54
      obj_.get_coverage ().collect_coverage (&digest);
975
54
    }
void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::Layout::GPOS_impl::MarkLigPosFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::MarkLigPosFormat1_2<OT::Layout::SmallTypes> const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
Line
Count
Source
965
12
    {
966
12
      obj = &obj_;
967
12
      apply_func = apply_func_;
968
12
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
969
12
      apply_cached_func = apply_cached_func_;
970
12
      cache_func = cache_func_;
971
12
      external_cache = external_cache_;
972
12
#endif
973
12
      digest.init ();
974
12
      obj_.get_coverage ().collect_coverage (&digest);
975
12
    }
void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes> const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
Line
Count
Source
965
15
    {
966
15
      obj = &obj_;
967
15
      apply_func = apply_func_;
968
15
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
969
15
      apply_cached_func = apply_cached_func_;
970
15
      cache_func = cache_func_;
971
15
      external_cache = external_cache_;
972
15
#endif
973
15
      digest.init ();
974
15
      obj_.get_coverage ().collect_coverage (&digest);
975
15
    }
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::ContextFormat1_4<OT::Layout::SmallTypes> >(OT::ContextFormat1_4<OT::Layout::SmallTypes> const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::ContextFormat2_5<OT::Layout::SmallTypes> >(OT::ContextFormat2_5<OT::Layout::SmallTypes> const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::ContextFormat3>(OT::ContextFormat3 const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::ChainContextFormat1_4<OT::Layout::SmallTypes> >(OT::ChainContextFormat1_4<OT::Layout::SmallTypes> const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::ChainContextFormat2_5<OT::Layout::SmallTypes> >(OT::ChainContextFormat2_5<OT::Layout::SmallTypes> const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
Line
Count
Source
965
64
    {
966
64
      obj = &obj_;
967
64
      apply_func = apply_func_;
968
64
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
969
64
      apply_cached_func = apply_cached_func_;
970
64
      cache_func = cache_func_;
971
64
      external_cache = external_cache_;
972
64
#endif
973
64
      digest.init ();
974
64
      obj_.get_coverage ().collect_coverage (&digest);
975
64
    }
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::ChainContextFormat3>(OT::ChainContextFormat3 const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
Line
Count
Source
965
10
    {
966
10
      obj = &obj_;
967
10
      apply_func = apply_func_;
968
10
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
969
10
      apply_cached_func = apply_cached_func_;
970
10
      cache_func = cache_func_;
971
10
      external_cache = external_cache_;
972
10
#endif
973
10
      digest.init ();
974
10
      obj_.get_coverage ().collect_coverage (&digest);
975
10
    }
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::hb_applicable_t::init<OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1>(OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1 const&, bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(void const*, OT::hb_ot_apply_context_t*, void*), bool (*)(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t), void*)
976
977
#ifdef HB_NO_OT_LAYOUT_LOOKUP_CACHE
978
    bool apply (hb_ot_apply_context_t *c) const
979
    {
980
      return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c, nullptr);
981
    }
982
#else
983
    bool apply (hb_ot_apply_context_t *c) const
984
0
    {
985
0
      return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c, external_cache);
986
0
    }
987
    bool apply_cached (hb_ot_apply_context_t *c) const
988
0
    {
989
0
      return digest.may_have (c->buffer->cur().codepoint) &&  apply_cached_func (obj, c, external_cache);
990
0
    }
991
992
    bool cache_enter (hb_ot_apply_context_t *c) const
993
0
    {
994
0
      return cache_func (c, hb_ot_subtable_cache_op_t::ENTER);
995
0
    }
996
    void cache_leave (hb_ot_apply_context_t *c) const
997
0
    {
998
0
      cache_func (c, hb_ot_subtable_cache_op_t::LEAVE);
999
0
    }
1000
#endif
1001
1002
    private:
1003
    const void *obj;
1004
    hb_apply_func_t apply_func;
1005
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1006
    hb_apply_func_t apply_cached_func;
1007
    hb_cache_func_t cache_func;
1008
    void *external_cache;
1009
#endif
1010
    hb_set_digest_t digest;
1011
  };
1012
1013
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1014
  template <typename T>
1015
  auto cache_cost (const T &obj, hb_priority<1>) HB_AUTO_RETURN ( obj.cache_cost () )
1016
  template <typename T>
1017
  auto cache_cost (const T &obj, hb_priority<0>) HB_AUTO_RETURN ( 0u )
1018
1019
  template <typename T>
1020
  auto external_cache_create (const T &obj, hb_priority<1>) HB_AUTO_RETURN ( obj.external_cache_create () )
1021
  template <typename T>
1022
  auto external_cache_create (const T &obj, hb_priority<0>) HB_AUTO_RETURN ( nullptr )
1023
#endif
1024
1025
  /* Dispatch interface. */
1026
  template <typename T>
1027
  return_t dispatch (const T &obj)
1028
155
  {
1029
155
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1030
155
    void *external_cache = nullptr;
1031
155
    if (i < 8)
1032
145
      external_cache = external_cache_create (obj, hb_prioritize);
1033
155
#endif
1034
1035
155
    hb_applicable_t *entry = &array[i++];
1036
1037
155
    entry->init (obj,
1038
155
     apply_to<T>
1039
155
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1040
155
     , apply_cached_to<T>
1041
155
     , cache_func_to<T>
1042
155
     , external_cache
1043
155
#endif
1044
155
     );
1045
1046
155
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1047
    /* Cache handling
1048
     *
1049
     * We allow one subtable from each lookup to use a cache. The assumption
1050
     * being that multiple subtables of the same lookup cannot use a cache
1051
     * because the resources they would use will collide.  As such, we ask
1052
     * each subtable to tell us how much it costs (which a cache would avoid),
1053
     * and we allocate the cache opportunity to the costliest subtable.
1054
     */
1055
155
    unsigned cost = cache_cost (obj, hb_prioritize);
1056
155
    if (cost > subtable_cache_user_cost)
1057
19
    {
1058
19
      subtable_cache_user_idx = i - 1;
1059
19
      subtable_cache_user_cost = cost;
1060
19
    }
1061
155
#endif
1062
1063
155
    return hb_empty_t ();
1064
155
  }
Unexecuted instantiation: hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::Layout::GPOS_impl::SinglePosFormat1>(OT::Layout::GPOS_impl::SinglePosFormat1 const&)
Unexecuted instantiation: hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::Layout::GPOS_impl::SinglePosFormat2>(OT::Layout::GPOS_impl::SinglePosFormat2 const&)
Unexecuted instantiation: hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::Layout::GPOS_impl::PairPosFormat1_3<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::PairPosFormat1_3<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::Layout::GPOS_impl::CursivePosFormat1>(OT::Layout::GPOS_impl::CursivePosFormat1 const&)
hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::Layout::GPOS_impl::MarkBasePosFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::MarkBasePosFormat1_2<OT::Layout::SmallTypes> const&)
Line
Count
Source
1028
54
  {
1029
54
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1030
54
    void *external_cache = nullptr;
1031
54
    if (i < 8)
1032
54
      external_cache = external_cache_create (obj, hb_prioritize);
1033
54
#endif
1034
1035
54
    hb_applicable_t *entry = &array[i++];
1036
1037
54
    entry->init (obj,
1038
54
     apply_to<T>
1039
54
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1040
54
     , apply_cached_to<T>
1041
54
     , cache_func_to<T>
1042
54
     , external_cache
1043
54
#endif
1044
54
     );
1045
1046
54
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1047
    /* Cache handling
1048
     *
1049
     * We allow one subtable from each lookup to use a cache. The assumption
1050
     * being that multiple subtables of the same lookup cannot use a cache
1051
     * because the resources they would use will collide.  As such, we ask
1052
     * each subtable to tell us how much it costs (which a cache would avoid),
1053
     * and we allocate the cache opportunity to the costliest subtable.
1054
     */
1055
54
    unsigned cost = cache_cost (obj, hb_prioritize);
1056
54
    if (cost > subtable_cache_user_cost)
1057
0
    {
1058
0
      subtable_cache_user_idx = i - 1;
1059
0
      subtable_cache_user_cost = cost;
1060
0
    }
1061
54
#endif
1062
1063
54
    return hb_empty_t ();
1064
54
  }
hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::Layout::GPOS_impl::MarkLigPosFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::MarkLigPosFormat1_2<OT::Layout::SmallTypes> const&)
Line
Count
Source
1028
12
  {
1029
12
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1030
12
    void *external_cache = nullptr;
1031
12
    if (i < 8)
1032
12
      external_cache = external_cache_create (obj, hb_prioritize);
1033
12
#endif
1034
1035
12
    hb_applicable_t *entry = &array[i++];
1036
1037
12
    entry->init (obj,
1038
12
     apply_to<T>
1039
12
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1040
12
     , apply_cached_to<T>
1041
12
     , cache_func_to<T>
1042
12
     , external_cache
1043
12
#endif
1044
12
     );
1045
1046
12
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1047
    /* Cache handling
1048
     *
1049
     * We allow one subtable from each lookup to use a cache. The assumption
1050
     * being that multiple subtables of the same lookup cannot use a cache
1051
     * because the resources they would use will collide.  As such, we ask
1052
     * each subtable to tell us how much it costs (which a cache would avoid),
1053
     * and we allocate the cache opportunity to the costliest subtable.
1054
     */
1055
12
    unsigned cost = cache_cost (obj, hb_prioritize);
1056
12
    if (cost > subtable_cache_user_cost)
1057
0
    {
1058
0
      subtable_cache_user_idx = i - 1;
1059
0
      subtable_cache_user_cost = cost;
1060
0
    }
1061
12
#endif
1062
1063
12
    return hb_empty_t ();
1064
12
  }
hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes> const&)
Line
Count
Source
1028
15
  {
1029
15
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1030
15
    void *external_cache = nullptr;
1031
15
    if (i < 8)
1032
15
      external_cache = external_cache_create (obj, hb_prioritize);
1033
15
#endif
1034
1035
15
    hb_applicable_t *entry = &array[i++];
1036
1037
15
    entry->init (obj,
1038
15
     apply_to<T>
1039
15
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1040
15
     , apply_cached_to<T>
1041
15
     , cache_func_to<T>
1042
15
     , external_cache
1043
15
#endif
1044
15
     );
1045
1046
15
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1047
    /* Cache handling
1048
     *
1049
     * We allow one subtable from each lookup to use a cache. The assumption
1050
     * being that multiple subtables of the same lookup cannot use a cache
1051
     * because the resources they would use will collide.  As such, we ask
1052
     * each subtable to tell us how much it costs (which a cache would avoid),
1053
     * and we allocate the cache opportunity to the costliest subtable.
1054
     */
1055
15
    unsigned cost = cache_cost (obj, hb_prioritize);
1056
15
    if (cost > subtable_cache_user_cost)
1057
0
    {
1058
0
      subtable_cache_user_idx = i - 1;
1059
0
      subtable_cache_user_cost = cost;
1060
0
    }
1061
15
#endif
1062
1063
15
    return hb_empty_t ();
1064
15
  }
Unexecuted instantiation: hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::ContextFormat1_4<OT::Layout::SmallTypes> >(OT::ContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::ContextFormat2_5<OT::Layout::SmallTypes> >(OT::ContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::ContextFormat3>(OT::ContextFormat3 const&)
Unexecuted instantiation: hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::ChainContextFormat1_4<OT::Layout::SmallTypes> >(OT::ChainContextFormat1_4<OT::Layout::SmallTypes> const&)
hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::ChainContextFormat2_5<OT::Layout::SmallTypes> >(OT::ChainContextFormat2_5<OT::Layout::SmallTypes> const&)
Line
Count
Source
1028
64
  {
1029
64
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1030
64
    void *external_cache = nullptr;
1031
64
    if (i < 8)
1032
54
      external_cache = external_cache_create (obj, hb_prioritize);
1033
64
#endif
1034
1035
64
    hb_applicable_t *entry = &array[i++];
1036
1037
64
    entry->init (obj,
1038
64
     apply_to<T>
1039
64
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1040
64
     , apply_cached_to<T>
1041
64
     , cache_func_to<T>
1042
64
     , external_cache
1043
64
#endif
1044
64
     );
1045
1046
64
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1047
    /* Cache handling
1048
     *
1049
     * We allow one subtable from each lookup to use a cache. The assumption
1050
     * being that multiple subtables of the same lookup cannot use a cache
1051
     * because the resources they would use will collide.  As such, we ask
1052
     * each subtable to tell us how much it costs (which a cache would avoid),
1053
     * and we allocate the cache opportunity to the costliest subtable.
1054
     */
1055
64
    unsigned cost = cache_cost (obj, hb_prioritize);
1056
64
    if (cost > subtable_cache_user_cost)
1057
19
    {
1058
19
      subtable_cache_user_idx = i - 1;
1059
19
      subtable_cache_user_cost = cost;
1060
19
    }
1061
64
#endif
1062
1063
64
    return hb_empty_t ();
1064
64
  }
Unexecuted instantiation: hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::ChainContextFormat3>(OT::ChainContextFormat3 const&)
Unexecuted instantiation: hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> const&)
hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::LigatureSubstFormat1_2<OT::Layout::SmallTypes> const&)
Line
Count
Source
1028
10
  {
1029
10
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1030
10
    void *external_cache = nullptr;
1031
10
    if (i < 8)
1032
10
      external_cache = external_cache_create (obj, hb_prioritize);
1033
10
#endif
1034
1035
10
    hb_applicable_t *entry = &array[i++];
1036
1037
10
    entry->init (obj,
1038
10
     apply_to<T>
1039
10
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1040
10
     , apply_cached_to<T>
1041
10
     , cache_func_to<T>
1042
10
     , external_cache
1043
10
#endif
1044
10
     );
1045
1046
10
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1047
    /* Cache handling
1048
     *
1049
     * We allow one subtable from each lookup to use a cache. The assumption
1050
     * being that multiple subtables of the same lookup cannot use a cache
1051
     * because the resources they would use will collide.  As such, we ask
1052
     * each subtable to tell us how much it costs (which a cache would avoid),
1053
     * and we allocate the cache opportunity to the costliest subtable.
1054
     */
1055
10
    unsigned cost = cache_cost (obj, hb_prioritize);
1056
10
    if (cost > subtable_cache_user_cost)
1057
0
    {
1058
0
      subtable_cache_user_idx = i - 1;
1059
0
      subtable_cache_user_cost = cost;
1060
0
    }
1061
10
#endif
1062
1063
10
    return hb_empty_t ();
1064
10
  }
Unexecuted instantiation: hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1>(OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1 const&)
1065
65
  static return_t default_return_value () { return hb_empty_t (); }
1066
1067
  hb_accelerate_subtables_context_t (hb_applicable_t *array_) :
1068
65
             array (array_) {}
1069
1070
  hb_applicable_t *array;
1071
  unsigned i = 0;
1072
1073
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1074
  unsigned subtable_cache_user_idx = (unsigned) -1;
1075
  unsigned subtable_cache_user_cost = 0;
1076
#endif
1077
};
1078
1079
1080
typedef bool (*intersects_func_t) (const hb_set_t *glyphs, unsigned value, const void *data, void *cache);
1081
typedef void (*intersected_glyphs_func_t) (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, void *cache);
1082
typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, unsigned value, const void *data);
1083
typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data);
1084
1085
struct ContextClosureFuncs
1086
{
1087
  intersects_func_t intersects;
1088
  intersected_glyphs_func_t intersected_glyphs;
1089
};
1090
struct ContextCollectGlyphsFuncs
1091
{
1092
  collect_glyphs_func_t collect;
1093
};
1094
struct ContextApplyFuncs
1095
{
1096
  match_func_t match;
1097
};
1098
struct ChainContextApplyFuncs
1099
{
1100
  match_func_t match[3];
1101
};
1102
1103
1104
static inline bool intersects_glyph (const hb_set_t *glyphs, unsigned value, const void *data HB_UNUSED, void *cache HB_UNUSED)
1105
0
{
1106
0
  return glyphs->has (value);
1107
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::intersects_glyph(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-aat-layout.cc:OT::intersects_glyph(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-ot-layout.cc:OT::intersects_glyph(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::intersects_glyph(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::intersects_glyph(hb_set_t const*, unsigned int, void const*, void*)
1108
static inline bool intersects_class (const hb_set_t *glyphs, unsigned value, const void *data, void *cache)
1109
0
{
1110
0
  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
1111
0
  hb_map_t *map = (hb_map_t *) cache;
1112
1113
0
  hb_codepoint_t *cached_v;
1114
0
  if (map->has (value, &cached_v))
1115
0
    return *cached_v;
1116
1117
0
  bool v = class_def.intersects_class (glyphs, value);
1118
0
  map->set (value, v);
1119
1120
0
  return v;
1121
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::intersects_class(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-aat-layout.cc:OT::intersects_class(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-ot-layout.cc:OT::intersects_class(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::intersects_class(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::intersects_class(hb_set_t const*, unsigned int, void const*, void*)
1122
static inline bool intersects_coverage (const hb_set_t *glyphs, unsigned value, const void *data, void *cache HB_UNUSED)
1123
0
{
1124
0
  Offset16To<Coverage> coverage;
1125
0
  coverage = value;
1126
0
  return (data+coverage).intersects (glyphs);
1127
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::intersects_coverage(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-aat-layout.cc:OT::intersects_coverage(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-ot-layout.cc:OT::intersects_coverage(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::intersects_coverage(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::intersects_coverage(hb_set_t const*, unsigned int, void const*, void*)
1128
1129
1130
static inline void intersected_glyph (const hb_set_t *glyphs HB_UNUSED, const void *data, unsigned value, hb_set_t *intersected_glyphs, HB_UNUSED void *cache)
1131
0
{
1132
0
  unsigned g = reinterpret_cast<const HBUINT16 *>(data)[value];
1133
0
  intersected_glyphs->add (g);
1134
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::intersected_glyph(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-aat-layout.cc:OT::intersected_glyph(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-ot-layout.cc:OT::intersected_glyph(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::intersected_glyph(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::intersected_glyph(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
1135
1136
using intersected_class_cache_t = hb_hashmap_t<unsigned, hb_set_t>;
1137
1138
static inline void intersected_class_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, void *cache)
1139
0
{
1140
0
  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
1141
1142
0
  intersected_class_cache_t *map = (intersected_class_cache_t *) cache;
1143
1144
0
  hb_set_t *cached_v;
1145
0
  if (map->has (value, &cached_v))
1146
0
  {
1147
0
    intersected_glyphs->union_ (*cached_v);
1148
0
    return;
1149
0
  }
1150
1151
0
  hb_set_t v;
1152
0
  class_def.intersected_class_glyphs (glyphs, value, &v);
1153
1154
0
  intersected_glyphs->union_ (v);
1155
1156
0
  map->set (value, std::move (v));
1157
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::intersected_class_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-aat-layout.cc:OT::intersected_class_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-ot-layout.cc:OT::intersected_class_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::intersected_class_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::intersected_class_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
1158
1159
static inline void intersected_coverage_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, HB_UNUSED void *cache)
1160
0
{
1161
0
  Offset16To<Coverage> coverage;
1162
0
  coverage = value;
1163
0
  (data+coverage).intersect_set (*glyphs, *intersected_glyphs);
1164
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::intersected_coverage_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-aat-layout.cc:OT::intersected_coverage_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-ot-layout.cc:OT::intersected_coverage_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::intersected_coverage_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::intersected_coverage_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
1165
1166
1167
template <typename HBUINT>
1168
static inline bool array_is_subset_of (const hb_set_t *glyphs,
1169
               unsigned int count,
1170
               const HBUINT values[],
1171
               intersects_func_t intersects_func,
1172
               const void *intersects_data,
1173
               void *cache)
1174
0
{
1175
0
  for (const auto &_ : + hb_iter (values, count))
1176
0
    if (!intersects_func (glyphs, _, intersects_data, cache)) return false;
1177
0
  return true;
1178
0
}
Unexecuted instantiation: hb-ot-face.cc:bool OT::array_is_subset_of<OT::NumType<true, unsigned short, 2u> >(hb_set_t const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_set_t const*, unsigned int, void const*, void*), void const*, void*)
Unexecuted instantiation: hb-aat-layout.cc:bool OT::array_is_subset_of<OT::NumType<true, unsigned short, 2u> >(hb_set_t const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_set_t const*, unsigned int, void const*, void*), void const*, void*)
Unexecuted instantiation: hb-ot-layout.cc:bool OT::array_is_subset_of<OT::NumType<true, unsigned short, 2u> >(hb_set_t const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_set_t const*, unsigned int, void const*, void*), void const*, void*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:bool OT::array_is_subset_of<OT::NumType<true, unsigned short, 2u> >(hb_set_t const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_set_t const*, unsigned int, void const*, void*), void const*, void*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:bool OT::array_is_subset_of<OT::NumType<true, unsigned short, 2u> >(hb_set_t const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_set_t const*, unsigned int, void const*, void*), void const*, void*)
1179
1180
1181
static inline void collect_glyph (hb_set_t *glyphs, unsigned value, const void *data HB_UNUSED)
1182
0
{
1183
0
  glyphs->add (value);
1184
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::collect_glyph(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-aat-layout.cc:OT::collect_glyph(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-ot-layout.cc:OT::collect_glyph(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::collect_glyph(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::collect_glyph(hb_set_t*, unsigned int, void const*)
1185
static inline void collect_class (hb_set_t *glyphs, unsigned value, const void *data)
1186
0
{
1187
0
  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
1188
0
  class_def.collect_class (glyphs, value);
1189
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::collect_class(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-aat-layout.cc:OT::collect_class(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-ot-layout.cc:OT::collect_class(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::collect_class(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::collect_class(hb_set_t*, unsigned int, void const*)
1190
static inline void collect_coverage (hb_set_t *glyphs, unsigned value, const void *data)
1191
0
{
1192
0
  Offset16To<Coverage> coverage;
1193
0
  coverage = value;
1194
0
  (data+coverage).collect_coverage (glyphs);
1195
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::collect_coverage(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-aat-layout.cc:OT::collect_coverage(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-ot-layout.cc:OT::collect_coverage(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::collect_coverage(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::collect_coverage(hb_set_t*, unsigned int, void const*)
1196
template <typename HBUINT>
1197
static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
1198
          hb_set_t *glyphs,
1199
          unsigned int count,
1200
          const HBUINT values[],
1201
          collect_glyphs_func_t collect_func,
1202
          const void *collect_data)
1203
0
{
1204
0
  return
1205
0
  + hb_iter (values, count)
1206
0
  | hb_apply ([&] (const HBUINT &_) { collect_func (glyphs, _, collect_data); })
1207
0
  ;
1208
0
}
Unexecuted instantiation: hb-ot-face.cc:void OT::collect_array<OT::NumType<true, unsigned short, 2u> >(OT::hb_collect_glyphs_context_t*, hb_set_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, void (*)(hb_set_t*, unsigned int, void const*), void const*)
Unexecuted instantiation: hb-aat-layout.cc:void OT::collect_array<OT::NumType<true, unsigned short, 2u> >(OT::hb_collect_glyphs_context_t*, hb_set_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, void (*)(hb_set_t*, unsigned int, void const*), void const*)
Unexecuted instantiation: hb-ot-layout.cc:void OT::collect_array<OT::NumType<true, unsigned short, 2u> >(OT::hb_collect_glyphs_context_t*, hb_set_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, void (*)(hb_set_t*, unsigned int, void const*), void const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:void OT::collect_array<OT::NumType<true, unsigned short, 2u> >(OT::hb_collect_glyphs_context_t*, hb_set_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, void (*)(hb_set_t*, unsigned int, void const*), void const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:void OT::collect_array<OT::NumType<true, unsigned short, 2u> >(OT::hb_collect_glyphs_context_t*, hb_set_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, void (*)(hb_set_t*, unsigned int, void const*), void const*)
1209
1210
1211
static inline bool match_always (hb_glyph_info_t &info HB_UNUSED, unsigned value HB_UNUSED, const void *data HB_UNUSED)
1212
0
{
1213
0
  return true;
1214
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::match_always(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-aat-layout.cc:OT::match_always(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-layout.cc:OT::match_always(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::match_always(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::match_always(hb_glyph_info_t&, unsigned int, void const*)
1215
static inline bool match_glyph (hb_glyph_info_t &info, unsigned value, const void *data HB_UNUSED)
1216
0
{
1217
0
  return info.codepoint == value;
1218
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::match_glyph(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-aat-layout.cc:OT::match_glyph(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-layout.cc:OT::match_glyph(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::match_glyph(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::match_glyph(hb_glyph_info_t&, unsigned int, void const*)
1219
static inline bool match_class (hb_glyph_info_t &info, unsigned value, const void *data)
1220
0
{
1221
0
  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
1222
0
  return class_def.get_class (info.codepoint) == value;
1223
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::match_class(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-aat-layout.cc:OT::match_class(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-layout.cc:OT::match_class(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::match_class(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::match_class(hb_glyph_info_t&, unsigned int, void const*)
1224
static inline unsigned get_class_cached (const ClassDef &class_def, hb_glyph_info_t &info)
1225
0
{
1226
0
  unsigned klass = info.syllable();
1227
0
  if (klass < 255)
1228
0
    return klass;
1229
0
  klass = class_def.get_class (info.codepoint);
1230
0
  if (likely (klass < 255))
1231
0
    info.syllable() = klass;
1232
0
  return klass;
1233
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::get_class_cached(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-aat-layout.cc:OT::get_class_cached(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-ot-layout.cc:OT::get_class_cached(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::get_class_cached(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::get_class_cached(OT::ClassDef const&, hb_glyph_info_t&)
1234
static inline bool match_class_cached (hb_glyph_info_t &info, unsigned value, const void *data)
1235
0
{
1236
0
  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
1237
0
  return get_class_cached (class_def, info) == value;
1238
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::match_class_cached(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-aat-layout.cc:OT::match_class_cached(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-layout.cc:OT::match_class_cached(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::match_class_cached(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::match_class_cached(hb_glyph_info_t&, unsigned int, void const*)
1239
static inline unsigned get_class_cached1 (const ClassDef &class_def, hb_glyph_info_t &info)
1240
0
{
1241
0
  unsigned klass = info.syllable() & 0x0F;
1242
0
  if (klass < 15)
1243
0
    return klass;
1244
0
  klass = class_def.get_class (info.codepoint);
1245
0
  if (likely (klass < 15))
1246
0
    info.syllable() = (info.syllable() & 0xF0) | klass;
1247
0
  return klass;
1248
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::get_class_cached1(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-aat-layout.cc:OT::get_class_cached1(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-ot-layout.cc:OT::get_class_cached1(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::get_class_cached1(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::get_class_cached1(OT::ClassDef const&, hb_glyph_info_t&)
1249
static inline bool match_class_cached1 (hb_glyph_info_t &info, unsigned value, const void *data)
1250
0
{
1251
0
  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
1252
0
  return get_class_cached1 (class_def, info) == value;
1253
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::match_class_cached1(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-aat-layout.cc:OT::match_class_cached1(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-layout.cc:OT::match_class_cached1(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::match_class_cached1(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::match_class_cached1(hb_glyph_info_t&, unsigned int, void const*)
1254
static inline unsigned get_class_cached2 (const ClassDef &class_def, hb_glyph_info_t &info)
1255
0
{
1256
0
  unsigned klass = (info.syllable() & 0xF0) >> 4;
1257
0
  if (klass < 15)
1258
0
    return klass;
1259
0
  klass = class_def.get_class (info.codepoint);
1260
0
  if (likely (klass < 15))
1261
0
    info.syllable() = (info.syllable() & 0x0F) | (klass << 4);
1262
0
  return klass;
1263
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::get_class_cached2(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-aat-layout.cc:OT::get_class_cached2(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-ot-layout.cc:OT::get_class_cached2(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::get_class_cached2(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::get_class_cached2(OT::ClassDef const&, hb_glyph_info_t&)
1264
static inline bool match_class_cached2 (hb_glyph_info_t &info, unsigned value, const void *data)
1265
0
{
1266
0
  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
1267
0
  return get_class_cached2 (class_def, info) == value;
1268
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::match_class_cached2(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-aat-layout.cc:OT::match_class_cached2(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-layout.cc:OT::match_class_cached2(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::match_class_cached2(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::match_class_cached2(hb_glyph_info_t&, unsigned int, void const*)
1269
static inline bool match_coverage (hb_glyph_info_t &info, unsigned value, const void *data)
1270
0
{
1271
0
  Offset16To<Coverage> coverage;
1272
0
  coverage = value;
1273
0
  return (data+coverage).get_coverage (info.codepoint) != NOT_COVERED;
1274
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::match_coverage(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-aat-layout.cc:OT::match_coverage(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-layout.cc:OT::match_coverage(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::match_coverage(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::match_coverage(hb_glyph_info_t&, unsigned int, void const*)
1275
1276
template <typename HBUINT>
1277
static inline bool would_match_input (hb_would_apply_context_t *c,
1278
              unsigned int count, /* Including the first glyph (not matched) */
1279
              const HBUINT input[], /* Array of input values--start with second glyph */
1280
              match_func_t match_func,
1281
              const void *match_data)
1282
0
{
1283
0
  if (count != c->len)
1284
0
    return false;
1285
1286
0
  for (unsigned int i = 1; i < count; i++)
1287
0
  {
1288
0
    hb_glyph_info_t info;
1289
0
    info.codepoint = c->glyphs[i];
1290
0
    if (likely (!match_func (info, input[i - 1], match_data)))
1291
0
      return false;
1292
0
  }
1293
1294
0
  return true;
1295
0
}
Unexecuted instantiation: hb-ot-face.cc:bool OT::would_match_input<OT::NumType<true, unsigned short, 2u> >(OT::hb_would_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*)
Unexecuted instantiation: hb-aat-layout.cc:bool OT::would_match_input<OT::NumType<true, unsigned short, 2u> >(OT::hb_would_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*)
Unexecuted instantiation: hb-ot-layout.cc:bool OT::would_match_input<OT::NumType<true, unsigned short, 2u> >(OT::hb_would_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:bool OT::would_match_input<OT::NumType<true, unsigned short, 2u> >(OT::hb_would_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:bool OT::would_match_input<OT::NumType<true, unsigned short, 2u> >(OT::hb_would_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*)
1296
template <typename HBUINT>
1297
#ifndef HB_OPTIMIZE_SIZE
1298
HB_ALWAYS_INLINE
1299
#endif
1300
static bool match_input (hb_ot_apply_context_t *c,
1301
       unsigned int count, /* Including the first glyph (not matched) */
1302
       const HBUINT input[], /* Array of input values--start with second glyph */
1303
       match_func_t match_func,
1304
       const void *match_data,
1305
       unsigned int *end_position,
1306
       unsigned int *p_total_component_count = nullptr)
1307
0
{
1308
0
  TRACE_APPLY (nullptr);
1309
1310
0
  if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
1311
1312
0
  hb_buffer_t *buffer = c->buffer;
1313
1314
0
  auto &skippy_iter = c->iter_input;
1315
0
  skippy_iter.reset (buffer->idx);
1316
0
  skippy_iter.set_match_func (match_func, match_data);
1317
0
  skippy_iter.set_glyph_data (input);
1318
1319
  /*
1320
   * This is perhaps the trickiest part of OpenType...  Remarks:
1321
   *
1322
   * - If all components of the ligature were marks, we call this a mark ligature.
1323
   *
1324
   * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
1325
   *   it as a ligature glyph.
1326
   *
1327
   * - Ligatures cannot be formed across glyphs attached to different components
1328
   *   of previous ligatures.  Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
1329
   *   LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
1330
   *   However, it would be wrong to ligate that SHADDA,FATHA sequence.
1331
   *   There are a couple of exceptions to this:
1332
   *
1333
   *   o If a ligature tries ligating with marks that belong to it itself, go ahead,
1334
   *     assuming that the font designer knows what they are doing (otherwise it can
1335
   *     break Indic stuff when a matra wants to ligate with a conjunct,
1336
   *
1337
   *   o If two marks want to ligate and they belong to different components of the
1338
   *     same ligature glyph, and said ligature glyph is to be ignored according to
1339
   *     mark-filtering rules, then allow.
1340
   *     https://github.com/harfbuzz/harfbuzz/issues/545
1341
   */
1342
1343
0
  unsigned int total_component_count = 0;
1344
1345
0
  unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
1346
0
  unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
1347
1348
0
  enum {
1349
0
    LIGBASE_NOT_CHECKED,
1350
0
    LIGBASE_MAY_NOT_SKIP,
1351
0
    LIGBASE_MAY_SKIP
1352
0
  } ligbase = LIGBASE_NOT_CHECKED;
1353
1354
0
  for (unsigned int i = 1; i < count; i++)
1355
0
  {
1356
0
    unsigned unsafe_to;
1357
0
    if (!skippy_iter.next (&unsafe_to))
1358
0
    {
1359
0
      *end_position = unsafe_to;
1360
0
      return_trace (false);
1361
0
    }
1362
1363
0
    if (unlikely (i + 1 > c->match_positions.length &&
1364
0
      !c->match_positions.resize (i + 1, false)))
1365
0
      return_trace (false);
1366
0
    c->match_positions.arrayZ[i] = skippy_iter.idx;
1367
1368
0
    unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]);
1369
0
    unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]);
1370
1371
0
    if (first_lig_id && first_lig_comp)
1372
0
    {
1373
      /* If first component was attached to a previous ligature component,
1374
       * all subsequent components should be attached to the same ligature
1375
       * component, otherwise we shouldn't ligate them... */
1376
0
      if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
1377
0
      {
1378
  /* ...unless, we are attached to a base ligature and that base
1379
   * ligature is ignorable. */
1380
0
  if (ligbase == LIGBASE_NOT_CHECKED)
1381
0
  {
1382
0
    bool found = false;
1383
0
    const auto *out = buffer->out_info;
1384
0
    unsigned int j = buffer->out_len;
1385
0
    while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id)
1386
0
    {
1387
0
      if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0)
1388
0
      {
1389
0
        j--;
1390
0
        found = true;
1391
0
        break;
1392
0
      }
1393
0
      j--;
1394
0
    }
1395
1396
0
    if (found && skippy_iter.may_skip (out[j]) == matcher_t::SKIP_YES)
1397
0
      ligbase = LIGBASE_MAY_SKIP;
1398
0
    else
1399
0
      ligbase = LIGBASE_MAY_NOT_SKIP;
1400
0
  }
1401
1402
0
  if (ligbase == LIGBASE_MAY_NOT_SKIP)
1403
0
    return_trace (false);
1404
0
      }
1405
0
    }
1406
0
    else
1407
0
    {
1408
      /* If first component was NOT attached to a previous ligature component,
1409
       * all subsequent components should also NOT be attached to any ligature
1410
       * component, unless they are attached to the first component itself! */
1411
0
      if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
1412
0
  return_trace (false);
1413
0
    }
1414
1415
0
    total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->info[skippy_iter.idx]);
1416
0
  }
1417
1418
0
  *end_position = skippy_iter.idx + 1;
1419
1420
0
  if (p_total_component_count)
1421
0
  {
1422
0
    total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
1423
0
    *p_total_component_count = total_component_count;
1424
0
  }
1425
1426
0
  c->match_positions.arrayZ[0] = buffer->idx;
1427
1428
0
  return_trace (true);
1429
0
}
Unexecuted instantiation: hb-ot-face.cc:bool OT::match_input<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int*, unsigned int*)
Unexecuted instantiation: hb-ot-face.cc:bool OT::match_input<OT::HBGlyphID16>(OT::hb_ot_apply_context_t*, unsigned int, OT::HBGlyphID16 const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int*, unsigned int*)
Unexecuted instantiation: hb-aat-layout.cc:bool OT::match_input<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int*, unsigned int*)
Unexecuted instantiation: hb-aat-layout.cc:bool OT::match_input<OT::HBGlyphID16>(OT::hb_ot_apply_context_t*, unsigned int, OT::HBGlyphID16 const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int*, unsigned int*)
Unexecuted instantiation: hb-ot-layout.cc:bool OT::match_input<OT::HBGlyphID16>(OT::hb_ot_apply_context_t*, unsigned int, OT::HBGlyphID16 const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int*, unsigned int*)
Unexecuted instantiation: hb-ot-layout.cc:bool OT::match_input<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int*, unsigned int*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:bool OT::match_input<OT::HBGlyphID16>(OT::hb_ot_apply_context_t*, unsigned int, OT::HBGlyphID16 const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int*, unsigned int*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:bool OT::match_input<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int*, unsigned int*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:bool OT::match_input<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int*, unsigned int*)
1430
static inline bool ligate_input (hb_ot_apply_context_t *c,
1431
         unsigned int count, /* Including the first glyph */
1432
         unsigned int match_end,
1433
         hb_codepoint_t lig_glyph,
1434
         unsigned int total_component_count)
1435
0
{
1436
0
  TRACE_APPLY (nullptr);
1437
1438
0
  hb_buffer_t *buffer = c->buffer;
1439
1440
0
  buffer->merge_clusters (buffer->idx, match_end);
1441
1442
  /* - If a base and one or more marks ligate, consider that as a base, NOT
1443
   *   ligature, such that all following marks can still attach to it.
1444
   *   https://github.com/harfbuzz/harfbuzz/issues/1109
1445
   *
1446
   * - If all components of the ligature were marks, we call this a mark ligature.
1447
   *   If it *is* a mark ligature, we don't allocate a new ligature id, and leave
1448
   *   the ligature to keep its old ligature id.  This will allow it to attach to
1449
   *   a base ligature in GPOS.  Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
1450
   *   and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA with a
1451
   *   ligature id and component value of 2.  Then if SHADDA,FATHA form a ligature
1452
   *   later, we don't want them to lose their ligature id/component, otherwise
1453
   *   GPOS will fail to correctly position the mark ligature on top of the
1454
   *   LAM,LAM,HEH ligature.  See:
1455
   *     https://bugzilla.gnome.org/show_bug.cgi?id=676343
1456
   *
1457
   * - If a ligature is formed of components that some of which are also ligatures
1458
   *   themselves, and those ligature components had marks attached to *their*
1459
   *   components, we have to attach the marks to the new ligature component
1460
   *   positions!  Now *that*'s tricky!  And these marks may be following the
1461
   *   last component of the whole sequence, so we should loop forward looking
1462
   *   for them and update them.
1463
   *
1464
   *   Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
1465
   *   'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
1466
   *   id and component == 1.  Now, during 'liga', the LAM and the LAM-HEH ligature
1467
   *   form a LAM-LAM-HEH ligature.  We need to reassign the SHADDA and FATHA to
1468
   *   the new ligature with a component value of 2.
1469
   *
1470
   *   This in fact happened to a font...  See:
1471
   *   https://bugzilla.gnome.org/show_bug.cgi?id=437633
1472
   */
1473
1474
0
  bool is_base_ligature = _hb_glyph_info_is_base_glyph (&buffer->info[c->match_positions.arrayZ[0]]);
1475
0
  bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->info[c->match_positions.arrayZ[0]]);
1476
0
  for (unsigned int i = 1; i < count; i++)
1477
0
    if (!_hb_glyph_info_is_mark (&buffer->info[c->match_positions.arrayZ[i]]))
1478
0
    {
1479
0
      is_base_ligature = false;
1480
0
      is_mark_ligature = false;
1481
0
      break;
1482
0
    }
1483
0
  bool is_ligature = !is_base_ligature && !is_mark_ligature;
1484
1485
0
  unsigned int klass = is_ligature ? HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE : 0;
1486
0
  unsigned int lig_id = is_ligature ? _hb_allocate_lig_id (buffer) : 0;
1487
0
  unsigned int last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
1488
0
  unsigned int last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
1489
0
  unsigned int components_so_far = last_num_components;
1490
1491
0
  if (is_ligature)
1492
0
  {
1493
0
    _hb_glyph_info_set_lig_props_for_ligature (&buffer->cur(), lig_id, total_component_count);
1494
0
    if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
1495
0
    {
1496
0
      _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER);
1497
0
    }
1498
0
  }
1499
0
  c->replace_glyph_with_ligature (lig_glyph, klass);
1500
1501
0
  for (unsigned int i = 1; i < count; i++)
1502
0
  {
1503
0
    while (buffer->idx < c->match_positions.arrayZ[i] && buffer->successful)
1504
0
    {
1505
0
      if (is_ligature)
1506
0
      {
1507
0
  unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
1508
0
  if (this_comp == 0)
1509
0
    this_comp = last_num_components;
1510
0
  assert (components_so_far >= last_num_components);
1511
0
  unsigned int new_lig_comp = components_so_far - last_num_components +
1512
0
            hb_min (this_comp, last_num_components);
1513
0
    _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
1514
0
      }
1515
0
      (void) buffer->next_glyph ();
1516
0
    }
1517
1518
0
    last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
1519
0
    last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
1520
0
    components_so_far += last_num_components;
1521
1522
    /* Skip the base glyph */
1523
0
    buffer->idx++;
1524
0
  }
1525
1526
0
  if (!is_mark_ligature && last_lig_id)
1527
0
  {
1528
    /* Re-adjust components for any marks following. */
1529
0
    for (unsigned i = buffer->idx; i < buffer->len; ++i)
1530
0
    {
1531
0
      if (last_lig_id != _hb_glyph_info_get_lig_id (&buffer->info[i])) break;
1532
1533
0
      unsigned this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
1534
0
      if (!this_comp) break;
1535
1536
0
      assert (components_so_far >= last_num_components);
1537
0
      unsigned new_lig_comp = components_so_far - last_num_components +
1538
0
            hb_min (this_comp, last_num_components);
1539
0
      _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
1540
0
    }
1541
0
  }
1542
0
  return_trace (true);
1543
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::ligate_input(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: hb-aat-layout.cc:OT::ligate_input(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: hb-ot-layout.cc:OT::ligate_input(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::ligate_input(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::ligate_input(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, unsigned int, unsigned int)
1544
1545
template <typename HBUINT>
1546
#ifndef HB_OPTIMIZE_SIZE
1547
HB_ALWAYS_INLINE
1548
#endif
1549
static bool match_backtrack (hb_ot_apply_context_t *c,
1550
           unsigned int count,
1551
           const HBUINT backtrack[],
1552
           match_func_t match_func,
1553
           const void *match_data,
1554
           unsigned int *match_start)
1555
0
{
1556
0
  TRACE_APPLY (nullptr);
1557
1558
0
  auto &skippy_iter = c->iter_context;
1559
0
  skippy_iter.reset (c->buffer->backtrack_len ());
1560
0
  skippy_iter.set_match_func (match_func, match_data);
1561
0
  skippy_iter.set_glyph_data (backtrack);
1562
1563
0
  for (unsigned int i = 0; i < count; i++)
1564
0
  {
1565
0
    unsigned unsafe_from;
1566
0
    if (!skippy_iter.prev (&unsafe_from))
1567
0
    {
1568
0
      *match_start = unsafe_from;
1569
0
      return_trace (false);
1570
0
    }
1571
0
  }
1572
1573
0
  *match_start = skippy_iter.idx;
1574
0
  return_trace (true);
1575
0
}
Unexecuted instantiation: hb-ot-face.cc:bool OT::match_backtrack<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int*)
Unexecuted instantiation: hb-aat-layout.cc:bool OT::match_backtrack<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int*)
Unexecuted instantiation: hb-ot-layout.cc:bool OT::match_backtrack<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:bool OT::match_backtrack<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:bool OT::match_backtrack<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int*)
1576
1577
template <typename HBUINT>
1578
#ifndef HB_OPTIMIZE_SIZE
1579
HB_ALWAYS_INLINE
1580
#endif
1581
static bool match_lookahead (hb_ot_apply_context_t *c,
1582
           unsigned int count,
1583
           const HBUINT lookahead[],
1584
           match_func_t match_func,
1585
           const void *match_data,
1586
           unsigned int start_index,
1587
           unsigned int *end_index)
1588
0
{
1589
0
  TRACE_APPLY (nullptr);
1590
1591
0
  auto &skippy_iter = c->iter_context;
1592
0
  assert (start_index >= 1);
1593
0
  skippy_iter.reset (start_index - 1);
1594
0
  skippy_iter.set_match_func (match_func, match_data);
1595
0
  skippy_iter.set_glyph_data (lookahead);
1596
1597
0
  for (unsigned int i = 0; i < count; i++)
1598
0
  {
1599
0
    unsigned unsafe_to;
1600
0
    if (!skippy_iter.next (&unsafe_to))
1601
0
    {
1602
0
      *end_index = unsafe_to;
1603
0
      return_trace (false);
1604
0
    }
1605
0
  }
1606
1607
0
  *end_index = skippy_iter.idx + 1;
1608
0
  return_trace (true);
1609
0
}
Unexecuted instantiation: hb-ot-face.cc:bool OT::match_lookahead<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-aat-layout.cc:bool OT::match_lookahead<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-ot-layout.cc:bool OT::match_lookahead<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:bool OT::match_lookahead<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:bool OT::match_lookahead<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, bool (*)(hb_glyph_info_t&, unsigned int, void const*), void const*, unsigned int, unsigned int*)
1610
1611
1612
1613
struct LookupRecord
1614
{
1615
  bool serialize (hb_serialize_context_t *c,
1616
      const hb_map_t         *lookup_map) const
1617
0
  {
1618
0
    TRACE_SERIALIZE (this);
1619
0
    auto *out = c->embed (*this);
1620
0
    if (unlikely (!out)) return_trace (false);
1621
0
1622
0
    return_trace (c->check_assign (out->lookupListIndex, lookup_map->get (lookupListIndex), HB_SERIALIZE_ERROR_INT_OVERFLOW));
1623
0
  }
1624
1625
  bool sanitize (hb_sanitize_context_t *c) const
1626
0
  {
1627
0
    TRACE_SANITIZE (this);
1628
0
    return_trace (c->check_struct (this));
1629
0
  }
1630
1631
  HBUINT16  sequenceIndex;    /* Index into current glyph
1632
           * sequence--first glyph = 0 */
1633
  HBUINT16  lookupListIndex;  /* Lookup to apply to that
1634
           * position--zero--based */
1635
  public:
1636
  DEFINE_SIZE_STATIC (4);
1637
};
1638
1639
static unsigned serialize_lookuprecord_array (hb_serialize_context_t *c,
1640
                const hb_array_t<const LookupRecord> lookupRecords,
1641
                const hb_map_t *lookup_map)
1642
0
{
1643
0
  unsigned count = 0;
1644
0
  for (const LookupRecord& r : lookupRecords)
1645
0
  {
1646
0
    if (!lookup_map->has (r.lookupListIndex))
1647
0
      continue;
1648
0
1649
0
    if (!r.serialize (c, lookup_map))
1650
0
      return 0;
1651
0
1652
0
    count++;
1653
0
  }
1654
0
  return count;
1655
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::serialize_lookuprecord_array(hb_serialize_context_t*, hb_array_t<OT::LookupRecord const>, hb_map_t const*)
Unexecuted instantiation: hb-aat-layout.cc:OT::serialize_lookuprecord_array(hb_serialize_context_t*, hb_array_t<OT::LookupRecord const>, hb_map_t const*)
Unexecuted instantiation: hb-ot-layout.cc:OT::serialize_lookuprecord_array(hb_serialize_context_t*, hb_array_t<OT::LookupRecord const>, hb_map_t const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::serialize_lookuprecord_array(hb_serialize_context_t*, hb_array_t<OT::LookupRecord const>, hb_map_t const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::serialize_lookuprecord_array(hb_serialize_context_t*, hb_array_t<OT::LookupRecord const>, hb_map_t const*)
1656
1657
enum ContextFormat { SimpleContext = 1, ClassBasedContext = 2, CoverageBasedContext = 3 };
1658
1659
template <typename HBUINT>
1660
static void context_closure_recurse_lookups (hb_closure_context_t *c,
1661
               unsigned inputCount, const HBUINT input[],
1662
               unsigned lookupCount,
1663
               const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */,
1664
               unsigned value,
1665
               ContextFormat context_format,
1666
               const void *data,
1667
               intersected_glyphs_func_t intersected_glyphs_func,
1668
               void *cache)
1669
0
{
1670
0
  hb_set_t covered_seq_indicies;
1671
0
  hb_set_t pos_glyphs;
1672
0
  for (unsigned int i = 0; i < lookupCount; i++)
1673
0
  {
1674
0
    unsigned seqIndex = lookupRecord[i].sequenceIndex;
1675
0
    if (seqIndex >= inputCount) continue;
1676
1677
0
    bool has_pos_glyphs = false;
1678
1679
0
    if (!covered_seq_indicies.has (seqIndex))
1680
0
    {
1681
0
      has_pos_glyphs = true;
1682
0
      pos_glyphs.clear ();
1683
0
      if (seqIndex == 0)
1684
0
      {
1685
0
        switch (context_format) {
1686
0
        case ContextFormat::SimpleContext:
1687
0
          pos_glyphs.add (value);
1688
0
          break;
1689
0
        case ContextFormat::ClassBasedContext:
1690
0
          intersected_glyphs_func (&c->parent_active_glyphs (), data, value, &pos_glyphs, cache);
1691
0
          break;
1692
0
        case ContextFormat::CoverageBasedContext:
1693
0
          pos_glyphs.set (c->parent_active_glyphs ());
1694
0
          break;
1695
0
        }
1696
0
      }
1697
0
      else
1698
0
      {
1699
0
        const void *input_data = input;
1700
0
        unsigned input_value = seqIndex - 1;
1701
0
        if (context_format != ContextFormat::SimpleContext)
1702
0
        {
1703
0
          input_data = data;
1704
0
          input_value = input[seqIndex - 1];
1705
0
        }
1706
1707
0
        intersected_glyphs_func (c->glyphs, input_data, input_value, &pos_glyphs, cache);
1708
0
      }
1709
0
    }
1710
1711
0
    covered_seq_indicies.add (seqIndex);
1712
0
    hb_set_t *cur_active_glyphs = c->push_cur_active_glyphs ();
1713
0
    if (unlikely (!cur_active_glyphs))
1714
0
      return;
1715
0
    if (has_pos_glyphs) {
1716
0
      *cur_active_glyphs = std::move (pos_glyphs);
1717
0
    } else {
1718
0
      *cur_active_glyphs = *c->glyphs;
1719
0
    }
1720
1721
0
    unsigned endIndex = inputCount;
1722
0
    if (context_format == ContextFormat::CoverageBasedContext)
1723
0
      endIndex += 1;
1724
1725
0
    c->recurse (lookupRecord[i].lookupListIndex, &covered_seq_indicies, seqIndex, endIndex);
1726
1727
0
    c->pop_cur_done_glyphs ();
1728
0
  }
1729
0
}
Unexecuted instantiation: hb-ot-face.cc:void OT::context_closure_recurse_lookups<OT::NumType<true, unsigned short, 2u> >(OT::hb_closure_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, unsigned int, OT::ContextFormat, void const*, void (*)(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*), void*)
Unexecuted instantiation: hb-aat-layout.cc:void OT::context_closure_recurse_lookups<OT::NumType<true, unsigned short, 2u> >(OT::hb_closure_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, unsigned int, OT::ContextFormat, void const*, void (*)(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*), void*)
Unexecuted instantiation: hb-ot-layout.cc:void OT::context_closure_recurse_lookups<OT::NumType<true, unsigned short, 2u> >(OT::hb_closure_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, unsigned int, OT::ContextFormat, void const*, void (*)(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*), void*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:void OT::context_closure_recurse_lookups<OT::NumType<true, unsigned short, 2u> >(OT::hb_closure_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, unsigned int, OT::ContextFormat, void const*, void (*)(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*), void*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:void OT::context_closure_recurse_lookups<OT::NumType<true, unsigned short, 2u> >(OT::hb_closure_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, unsigned int, OT::ContextFormat, void const*, void (*)(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*), void*)
1730
1731
template <typename context_t>
1732
static inline void recurse_lookups (context_t *c,
1733
                                    unsigned int lookupCount,
1734
                                    const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
1735
0
{
1736
0
  for (unsigned int i = 0; i < lookupCount; i++)
1737
0
    c->recurse (lookupRecord[i].lookupListIndex);
1738
0
}
Unexecuted instantiation: hb-ot-face.cc:void OT::recurse_lookups<OT::hb_closure_lookups_context_t>(OT::hb_closure_lookups_context_t*, unsigned int, OT::LookupRecord const*)
Unexecuted instantiation: hb-ot-face.cc:void OT::recurse_lookups<OT::hb_collect_glyphs_context_t>(OT::hb_collect_glyphs_context_t*, unsigned int, OT::LookupRecord const*)
Unexecuted instantiation: hb-aat-layout.cc:void OT::recurse_lookups<OT::hb_closure_lookups_context_t>(OT::hb_closure_lookups_context_t*, unsigned int, OT::LookupRecord const*)
Unexecuted instantiation: hb-aat-layout.cc:void OT::recurse_lookups<OT::hb_collect_glyphs_context_t>(OT::hb_collect_glyphs_context_t*, unsigned int, OT::LookupRecord const*)
Unexecuted instantiation: hb-ot-layout.cc:void OT::recurse_lookups<OT::hb_collect_glyphs_context_t>(OT::hb_collect_glyphs_context_t*, unsigned int, OT::LookupRecord const*)
Unexecuted instantiation: hb-ot-layout.cc:void OT::recurse_lookups<OT::hb_closure_lookups_context_t>(OT::hb_closure_lookups_context_t*, unsigned int, OT::LookupRecord const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:void OT::recurse_lookups<OT::hb_closure_lookups_context_t>(OT::hb_closure_lookups_context_t*, unsigned int, OT::LookupRecord const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:void OT::recurse_lookups<OT::hb_collect_glyphs_context_t>(OT::hb_collect_glyphs_context_t*, unsigned int, OT::LookupRecord const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:void OT::recurse_lookups<OT::hb_closure_lookups_context_t>(OT::hb_closure_lookups_context_t*, unsigned int, OT::LookupRecord const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:void OT::recurse_lookups<OT::hb_collect_glyphs_context_t>(OT::hb_collect_glyphs_context_t*, unsigned int, OT::LookupRecord const*)
1739
1740
static inline void apply_lookup (hb_ot_apply_context_t *c,
1741
         unsigned int count, /* Including the first glyph */
1742
         unsigned int lookupCount,
1743
         const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
1744
         unsigned int match_end)
1745
0
{
1746
0
  hb_buffer_t *buffer = c->buffer;
1747
0
  int end;
1748
1749
  /* All positions are distance from beginning of *output* buffer.
1750
   * Adjust. */
1751
0
  {
1752
0
    unsigned int bl = buffer->backtrack_len ();
1753
0
    end = bl + match_end - buffer->idx;
1754
1755
0
    int delta = bl - buffer->idx;
1756
    /* Convert positions to new indexing. */
1757
0
    for (unsigned int j = 0; j < count; j++)
1758
0
      c->match_positions.arrayZ[j] += delta;
1759
0
  }
1760
1761
0
  for (unsigned int i = 0; i < lookupCount && buffer->successful; i++)
1762
0
  {
1763
0
    unsigned int idx = lookupRecord[i].sequenceIndex;
1764
0
    if (idx >= count)
1765
0
      continue;
1766
1767
0
    unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
1768
1769
    /* This can happen if earlier recursed lookups deleted many entries. */
1770
0
    if (unlikely (c->match_positions.arrayZ[idx] >= orig_len))
1771
0
      continue;
1772
1773
0
    if (unlikely (!buffer->move_to (c->match_positions.arrayZ[idx])))
1774
0
      break;
1775
1776
0
    if (unlikely (buffer->max_ops <= 0))
1777
0
      break;
1778
1779
0
    if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
1780
0
    {
1781
0
      if (buffer->have_output)
1782
0
        c->buffer->sync_so_far ();
1783
0
      c->buffer->message (c->font,
1784
0
        "recursing to lookup %u at %u",
1785
0
        (unsigned) lookupRecord[i].lookupListIndex,
1786
0
        buffer->idx);
1787
0
    }
1788
1789
0
    if (!c->recurse (lookupRecord[i].lookupListIndex))
1790
0
      continue;
1791
1792
0
    if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
1793
0
    {
1794
0
      if (buffer->have_output)
1795
0
        c->buffer->sync_so_far ();
1796
0
      c->buffer->message (c->font,
1797
0
        "recursed to lookup %u",
1798
0
        (unsigned) lookupRecord[i].lookupListIndex);
1799
0
    }
1800
1801
0
    unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
1802
0
    int delta = new_len - orig_len;
1803
1804
0
    if (!delta)
1805
0
      continue;
1806
1807
    /* Recursed lookup changed buffer len.  Adjust.
1808
     *
1809
     * TODO:
1810
     *
1811
     * Right now, if buffer length increased by n, we assume n new glyphs
1812
     * were added right after the current position, and if buffer length
1813
     * was decreased by n, we assume n match positions after the current
1814
     * one where removed.  The former (buffer length increased) case is
1815
     * fine, but the decrease case can be improved in at least two ways,
1816
     * both of which are significant:
1817
     *
1818
     *   - If recursed-to lookup is MultipleSubst and buffer length
1819
     *     decreased, then it's current match position that was deleted,
1820
     *     NOT the one after it.
1821
     *
1822
     *   - If buffer length was decreased by n, it does not necessarily
1823
     *     mean that n match positions where removed, as there recursed-to
1824
     *     lookup might had a different LookupFlag.  Here's a constructed
1825
     *     case of that:
1826
     *     https://github.com/harfbuzz/harfbuzz/discussions/3538
1827
     *
1828
     * It should be possible to construct tests for both of these cases.
1829
     */
1830
1831
0
    end += delta;
1832
0
    if (end < int (c->match_positions.arrayZ[idx]))
1833
0
    {
1834
      /* End might end up being smaller than match_positions.arrayZ[idx] if the recursed
1835
       * lookup ended up removing many items.
1836
       * Just never rewind end beyond start of current position, since that is
1837
       * not possible in the recursed lookup.  Also adjust delta as such.
1838
       *
1839
       * https://bugs.chromium.org/p/chromium/issues/detail?id=659496
1840
       * https://github.com/harfbuzz/harfbuzz/issues/1611
1841
       */
1842
0
      delta += c->match_positions.arrayZ[idx] - end;
1843
0
      end = c->match_positions.arrayZ[idx];
1844
0
    }
1845
1846
0
    unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
1847
1848
0
    if (delta > 0)
1849
0
    {
1850
0
      if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
1851
0
  break;
1852
0
      if (unlikely (count + delta > c->match_positions.length &&
1853
0
        !c->match_positions.resize (count + delta, false)))
1854
0
        return;
1855
0
    }
1856
0
    else
1857
0
    {
1858
      /* NOTE: delta is non-positive. */
1859
0
      delta = hb_max (delta, (int) next - (int) count);
1860
0
      next -= delta;
1861
0
    }
1862
1863
    /* Shift! */
1864
0
    memmove (c->match_positions + next + delta, c->match_positions + next,
1865
0
       (count - next) * sizeof (c->match_positions.arrayZ[0]));
1866
0
    next += delta;
1867
0
    count += delta;
1868
1869
    /* Fill in new entries. */
1870
0
    for (unsigned int j = idx + 1; j < next; j++)
1871
0
      c->match_positions.arrayZ[j] = c->match_positions.arrayZ[j - 1] + 1;
1872
1873
    /* And fixup the rest. */
1874
0
    for (; next < count; next++)
1875
0
      c->match_positions.arrayZ[next] += delta;
1876
0
  }
1877
1878
0
  assert (end >= 0);
1879
0
  (void) buffer->move_to (end);
1880
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::apply_lookup(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, unsigned int)
Unexecuted instantiation: hb-aat-layout.cc:OT::apply_lookup(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, unsigned int)
Unexecuted instantiation: hb-ot-layout.cc:OT::apply_lookup(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, unsigned int)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::apply_lookup(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, unsigned int)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::apply_lookup(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, unsigned int)
1881
1882
1883
1884
/* Contextual lookups */
1885
1886
struct ContextClosureLookupContext
1887
{
1888
  ContextClosureFuncs funcs;
1889
  ContextFormat context_format;
1890
  const void *intersects_data;
1891
  void *intersects_cache;
1892
  void *intersected_glyphs_cache;
1893
};
1894
1895
struct ContextCollectGlyphsLookupContext
1896
{
1897
  ContextCollectGlyphsFuncs funcs;
1898
  const void *collect_data;
1899
};
1900
1901
struct ContextApplyLookupContext
1902
{
1903
  ContextApplyFuncs funcs;
1904
  const void *match_data;
1905
};
1906
1907
template <typename HBUINT>
1908
static inline bool context_intersects (const hb_set_t *glyphs,
1909
               unsigned int inputCount, /* Including the first glyph (not matched) */
1910
               const HBUINT input[], /* Array of input values--start with second glyph */
1911
               ContextClosureLookupContext &lookup_context)
1912
0
{
1913
0
  return array_is_subset_of (glyphs,
1914
0
           inputCount ? inputCount - 1 : 0, input,
1915
0
           lookup_context.funcs.intersects,
1916
0
           lookup_context.intersects_data,
1917
0
           lookup_context.intersects_cache);
1918
0
}
Unexecuted instantiation: hb-ot-face.cc:bool OT::context_intersects<OT::NumType<true, unsigned short, 2u> >(hb_set_t const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-aat-layout.cc:bool OT::context_intersects<OT::NumType<true, unsigned short, 2u> >(hb_set_t const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-layout.cc:bool OT::context_intersects<OT::NumType<true, unsigned short, 2u> >(hb_set_t const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:bool OT::context_intersects<OT::NumType<true, unsigned short, 2u> >(hb_set_t const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-shape-fallback.cc:bool OT::context_intersects<OT::NumType<true, unsigned short, 2u> >(hb_set_t const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, OT::ContextClosureLookupContext&)
1919
1920
template <typename HBUINT>
1921
static inline void context_closure_lookup (hb_closure_context_t *c,
1922
             unsigned int inputCount, /* Including the first glyph (not matched) */
1923
             const HBUINT input[], /* Array of input values--start with second glyph */
1924
             unsigned int lookupCount,
1925
             const LookupRecord lookupRecord[],
1926
             unsigned value, /* Index of first glyph in Coverage or Class value in ClassDef table */
1927
             ContextClosureLookupContext &lookup_context)
1928
0
{
1929
0
  if (context_intersects (c->glyphs,
1930
0
        inputCount, input,
1931
0
        lookup_context))
1932
0
    context_closure_recurse_lookups (c,
1933
0
             inputCount, input,
1934
0
             lookupCount, lookupRecord,
1935
0
             value,
1936
0
             lookup_context.context_format,
1937
0
             lookup_context.intersects_data,
1938
0
             lookup_context.funcs.intersected_glyphs,
1939
0
             lookup_context.intersected_glyphs_cache);
1940
0
}
Unexecuted instantiation: hb-ot-face.cc:void OT::context_closure_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_closure_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, unsigned int, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-aat-layout.cc:void OT::context_closure_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_closure_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, unsigned int, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-layout.cc:void OT::context_closure_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_closure_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, unsigned int, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:void OT::context_closure_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_closure_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, unsigned int, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-shape-fallback.cc:void OT::context_closure_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_closure_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, unsigned int, OT::ContextClosureLookupContext&)
1941
1942
template <typename HBUINT>
1943
static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
1944
              unsigned int inputCount, /* Including the first glyph (not matched) */
1945
              const HBUINT input[], /* Array of input values--start with second glyph */
1946
              unsigned int lookupCount,
1947
              const LookupRecord lookupRecord[],
1948
              ContextCollectGlyphsLookupContext &lookup_context)
1949
0
{
1950
0
  collect_array (c, c->input,
1951
0
     inputCount ? inputCount - 1 : 0, input,
1952
0
     lookup_context.funcs.collect, lookup_context.collect_data);
1953
0
  recurse_lookups (c,
1954
0
       lookupCount, lookupRecord);
1955
0
}
Unexecuted instantiation: hb-ot-face.cc:void OT::context_collect_glyphs_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_collect_glyphs_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ContextCollectGlyphsLookupContext&)
Unexecuted instantiation: hb-aat-layout.cc:void OT::context_collect_glyphs_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_collect_glyphs_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ContextCollectGlyphsLookupContext&)
Unexecuted instantiation: hb-ot-layout.cc:void OT::context_collect_glyphs_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_collect_glyphs_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ContextCollectGlyphsLookupContext&)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:void OT::context_collect_glyphs_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_collect_glyphs_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ContextCollectGlyphsLookupContext&)
Unexecuted instantiation: hb-ot-shape-fallback.cc:void OT::context_collect_glyphs_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_collect_glyphs_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ContextCollectGlyphsLookupContext&)
1956
1957
template <typename HBUINT>
1958
static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
1959
                 unsigned int inputCount, /* Including the first glyph (not matched) */
1960
                 const HBUINT input[], /* Array of input values--start with second glyph */
1961
                 unsigned int lookupCount HB_UNUSED,
1962
                 const LookupRecord lookupRecord[] HB_UNUSED,
1963
                 const ContextApplyLookupContext &lookup_context)
1964
0
{
1965
0
  return would_match_input (c,
1966
0
          inputCount, input,
1967
0
          lookup_context.funcs.match, lookup_context.match_data);
1968
0
}
Unexecuted instantiation: hb-ot-face.cc:bool OT::context_would_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_would_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ContextApplyLookupContext const&)
Unexecuted instantiation: hb-aat-layout.cc:bool OT::context_would_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_would_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ContextApplyLookupContext const&)
Unexecuted instantiation: hb-ot-layout.cc:bool OT::context_would_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_would_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ContextApplyLookupContext const&)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:bool OT::context_would_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_would_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ContextApplyLookupContext const&)
Unexecuted instantiation: hb-ot-shape-fallback.cc:bool OT::context_would_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_would_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ContextApplyLookupContext const&)
1969
1970
template <typename HBUINT>
1971
HB_ALWAYS_INLINE
1972
static bool context_apply_lookup (hb_ot_apply_context_t *c,
1973
          unsigned int inputCount, /* Including the first glyph (not matched) */
1974
          const HBUINT input[], /* Array of input values--start with second glyph */
1975
          unsigned int lookupCount,
1976
          const LookupRecord lookupRecord[],
1977
          const ContextApplyLookupContext &lookup_context)
1978
0
{
1979
0
  if (unlikely (inputCount > HB_MAX_CONTEXT_LENGTH)) return false;
1980
1981
0
  unsigned match_end = 0;
1982
0
  bool ret = false;
1983
0
  if (match_input (c,
1984
0
       inputCount, input,
1985
0
       lookup_context.funcs.match, lookup_context.match_data,
1986
0
       &match_end))
1987
0
  {
1988
0
    c->buffer->unsafe_to_break (c->buffer->idx, match_end);
1989
0
    apply_lookup (c,
1990
0
      inputCount,
1991
0
      lookupCount, lookupRecord,
1992
0
      match_end);
1993
0
    ret = true;
1994
0
  }
1995
0
  else
1996
0
  {
1997
0
    c->buffer->unsafe_to_concat (c->buffer->idx, match_end);
1998
0
    ret = false;
1999
0
  }
2000
2001
0
  return ret;
2002
0
}
Unexecuted instantiation: hb-ot-face.cc:bool OT::context_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ContextApplyLookupContext const&)
Unexecuted instantiation: hb-aat-layout.cc:bool OT::context_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ContextApplyLookupContext const&)
Unexecuted instantiation: hb-ot-layout.cc:bool OT::context_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ContextApplyLookupContext const&)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:bool OT::context_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ContextApplyLookupContext const&)
Unexecuted instantiation: hb-ot-shape-fallback.cc:bool OT::context_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ContextApplyLookupContext const&)
2003
2004
static inline bool context_cache_func (hb_ot_apply_context_t *c, hb_ot_subtable_cache_op_t op)
2005
0
{
2006
0
  switch (op)
2007
0
  {
2008
0
    case hb_ot_subtable_cache_op_t::ENTER:
2009
0
    {
2010
0
      if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
2011
0
  return false;
2012
0
      auto &info = c->buffer->info;
2013
0
      unsigned count = c->buffer->len;
2014
0
      for (unsigned i = 0; i < count; i++)
2015
0
  info[i].syllable() = 255;
2016
0
      c->new_syllables = 255;
2017
0
      return true;
2018
0
    }
2019
0
    case hb_ot_subtable_cache_op_t::LEAVE:
2020
0
    {
2021
0
      c->new_syllables = (unsigned) -1;
2022
0
      HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
2023
0
      break;
2024
0
    }
2025
0
  }
2026
0
  return false;
2027
0
}
Unexecuted instantiation: hb-ot-face.cc:OT::context_cache_func(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: hb-aat-layout.cc:OT::context_cache_func(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: hb-ot-layout.cc:OT::context_cache_func(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::context_cache_func(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::context_cache_func(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
2028
2029
template <typename Types>
2030
struct Rule
2031
{
2032
  template <typename T>
2033
  friend struct RuleSet;
2034
2035
  bool intersects (const hb_set_t *glyphs, ContextClosureLookupContext &lookup_context) const
2036
0
  {
2037
0
    return context_intersects (glyphs,
2038
0
             inputCount, inputZ.arrayZ,
2039
0
             lookup_context);
2040
0
  }
2041
2042
  void closure (hb_closure_context_t *c, unsigned value, ContextClosureLookupContext &lookup_context) const
2043
0
  {
2044
0
    if (unlikely (c->lookup_limit_exceeded ())) return;
2045
2046
0
    const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
2047
0
             (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
2048
0
    context_closure_lookup (c,
2049
0
          inputCount, inputZ.arrayZ,
2050
0
          lookupCount, lookupRecord.arrayZ,
2051
0
          value, lookup_context);
2052
0
  }
2053
2054
  void closure_lookups (hb_closure_lookups_context_t *c,
2055
                        ContextClosureLookupContext &lookup_context) const
2056
0
  {
2057
0
    if (unlikely (c->lookup_limit_exceeded ())) return;
2058
0
    if (!intersects (c->glyphs, lookup_context)) return;
2059
0
2060
0
    const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
2061
0
             (inputZ.as_array (inputCount ? inputCount - 1 : 0));
2062
0
    recurse_lookups (c, lookupCount, lookupRecord.arrayZ);
2063
0
  }
2064
2065
  void collect_glyphs (hb_collect_glyphs_context_t *c,
2066
           ContextCollectGlyphsLookupContext &lookup_context) const
2067
0
  {
2068
0
    const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
2069
0
             (inputZ.as_array (inputCount ? inputCount - 1 : 0));
2070
0
    context_collect_glyphs_lookup (c,
2071
0
           inputCount, inputZ.arrayZ,
2072
0
           lookupCount, lookupRecord.arrayZ,
2073
0
           lookup_context);
2074
0
  }
2075
2076
  bool would_apply (hb_would_apply_context_t *c,
2077
        const ContextApplyLookupContext &lookup_context) const
2078
0
  {
2079
0
    const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
2080
0
             (inputZ.as_array (inputCount ? inputCount - 1 : 0));
2081
0
    return context_would_apply_lookup (c,
2082
0
               inputCount, inputZ.arrayZ,
2083
0
               lookupCount, lookupRecord.arrayZ,
2084
0
               lookup_context);
2085
0
  }
2086
2087
  bool apply (hb_ot_apply_context_t *c,
2088
        const ContextApplyLookupContext &lookup_context) const
2089
0
  {
2090
0
    TRACE_APPLY (this);
2091
0
    const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
2092
0
             (inputZ.as_array (inputCount ? inputCount - 1 : 0));
2093
0
    return_trace (context_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
2094
0
  }
2095
2096
  bool serialize (hb_serialize_context_t *c,
2097
      const hb_map_t *input_mapping, /* old->new glyphid or class mapping */
2098
      const hb_map_t *lookup_map) const
2099
0
  {
2100
0
    TRACE_SERIALIZE (this);
2101
0
    auto *out = c->start_embed (this);
2102
0
    if (unlikely (!c->extend_min (out))) return_trace (false);
2103
0
2104
0
    out->inputCount = inputCount;
2105
0
    const auto input = inputZ.as_array (inputCount - 1);
2106
0
    for (const auto org : input)
2107
0
    {
2108
0
      HBUINT16 d;
2109
0
      d = input_mapping->get (org);
2110
0
      c->copy (d);
2111
0
    }
2112
0
2113
0
    const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
2114
0
             (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
2115
0
2116
0
    unsigned count = serialize_lookuprecord_array (c, lookupRecord.as_array (lookupCount), lookup_map);
2117
0
    return_trace (c->check_assign (out->lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
2118
0
  }
2119
2120
  bool subset (hb_subset_context_t *c,
2121
         const hb_map_t *lookup_map,
2122
         const hb_map_t *klass_map = nullptr) const
2123
0
  {
2124
0
    TRACE_SUBSET (this);
2125
0
    if (unlikely (!inputCount)) return_trace (false);
2126
0
    const auto input = inputZ.as_array (inputCount - 1);
2127
0
2128
0
    const hb_map_t *mapping = klass_map == nullptr ? c->plan->glyph_map : klass_map;
2129
0
    if (!hb_all (input, mapping)) return_trace (false);
2130
0
    return_trace (serialize (c->serializer, mapping, lookup_map));
2131
0
  }
2132
2133
  public:
2134
  bool sanitize (hb_sanitize_context_t *c) const
2135
0
  {
2136
0
    TRACE_SANITIZE (this);
2137
0
    return_trace (c->check_struct (this) &&
2138
0
      hb_barrier () &&
2139
0
      c->check_range (inputZ.arrayZ,
2140
0
          inputZ.item_size * (inputCount ? inputCount - 1 : 0) +
2141
0
          LookupRecord::static_size * lookupCount));
2142
0
  }
2143
2144
  protected:
2145
  HBUINT16  inputCount;   /* Total number of glyphs in input
2146
           * glyph sequence--includes the first
2147
           * glyph */
2148
  HBUINT16  lookupCount;    /* Number of LookupRecords */
2149
  UnsizedArrayOf<typename Types::HBUINT>
2150
    inputZ;     /* Array of match inputs--start with
2151
           * second glyph */
2152
/*UnsizedArrayOf<LookupRecord>
2153
    lookupRecordX;*/  /* Array of LookupRecords--in
2154
           * design order */
2155
  public:
2156
  DEFINE_SIZE_ARRAY (4, inputZ);
2157
};
2158
2159
template <typename Types>
2160
struct RuleSet
2161
{
2162
  using Rule = OT::Rule<Types>;
2163
2164
  bool intersects (const hb_set_t *glyphs,
2165
       ContextClosureLookupContext &lookup_context) const
2166
0
  {
2167
0
    return
2168
0
    + hb_iter (rule)
2169
0
    | hb_map (hb_add (this))
2170
0
    | hb_map ([&] (const Rule &_) { return _.intersects (glyphs, lookup_context); })
2171
0
    | hb_any
2172
0
    ;
2173
0
  }
2174
2175
  void closure (hb_closure_context_t *c, unsigned value,
2176
    ContextClosureLookupContext &lookup_context) const
2177
0
  {
2178
0
    if (unlikely (c->lookup_limit_exceeded ())) return;
2179
2180
0
    return
2181
0
    + hb_iter (rule)
2182
0
    | hb_map (hb_add (this))
2183
0
    | hb_apply ([&] (const Rule &_) { _.closure (c, value, lookup_context); })
2184
0
    ;
2185
0
  }
2186
2187
  void closure_lookups (hb_closure_lookups_context_t *c,
2188
                        ContextClosureLookupContext &lookup_context) const
2189
0
  {
2190
0
    if (unlikely (c->lookup_limit_exceeded ())) return;
2191
0
    + hb_iter (rule)
2192
0
    | hb_map (hb_add (this))
2193
0
    | hb_apply ([&] (const Rule &_) { _.closure_lookups (c, lookup_context); })
2194
0
    ;
2195
0
  }
2196
2197
  void collect_glyphs (hb_collect_glyphs_context_t *c,
2198
           ContextCollectGlyphsLookupContext &lookup_context) const
2199
0
  {
2200
0
    return
2201
0
    + hb_iter (rule)
2202
0
    | hb_map (hb_add (this))
2203
0
    | hb_apply ([&] (const Rule &_) { _.collect_glyphs (c, lookup_context); })
2204
0
    ;
2205
0
  }
2206
2207
  bool would_apply (hb_would_apply_context_t *c,
2208
        const ContextApplyLookupContext &lookup_context) const
2209
0
  {
2210
0
    return
2211
0
    + hb_iter (rule)
2212
0
    | hb_map (hb_add (this))
2213
0
    | hb_map ([&] (const Rule &_) { return _.would_apply (c, lookup_context); })
2214
0
    | hb_any
2215
0
    ;
2216
0
  }
2217
2218
  bool apply (hb_ot_apply_context_t *c,
2219
        const ContextApplyLookupContext &lookup_context) const
2220
0
  {
2221
0
    TRACE_APPLY (this);
2222
2223
0
    unsigned num_rules = rule.len;
2224
2225
0
#ifndef HB_NO_OT_RULESETS_FAST_PATH
2226
0
    if (HB_OPTIMIZE_SIZE_VAL || num_rules <= 4)
2227
0
#endif
2228
0
    {
2229
0
    slow:
2230
0
      return_trace (
2231
0
      + hb_iter (rule)
2232
0
      | hb_map (hb_add (this))
2233
0
      | hb_map ([&] (const Rule &_) { return _.apply (c, lookup_context); })
2234
0
      | hb_any
2235
0
      )
2236
0
      ;
2237
0
    }
2238
2239
    /* This version is optimized for speed by matching the first & second
2240
     * components of the rule here, instead of calling into the matching code.
2241
     *
2242
     * Replicated from LigatureSet::apply(). */
2243
2244
0
    auto &skippy_iter = c->iter_input;
2245
0
    skippy_iter.reset (c->buffer->idx);
2246
0
    skippy_iter.set_match_func (match_always, nullptr);
2247
0
    skippy_iter.set_glyph_data ((HBUINT16 *) nullptr);
2248
0
    unsigned unsafe_to = (unsigned) -1, unsafe_to1 = 0, unsafe_to2 = 0;
2249
0
    hb_glyph_info_t *first = nullptr, *second = nullptr;
2250
0
    bool matched = skippy_iter.next ();
2251
0
    if (likely (matched))
2252
0
    {
2253
0
      first = &c->buffer->info[skippy_iter.idx];
2254
0
      unsafe_to = skippy_iter.idx + 1;
2255
2256
0
      if (skippy_iter.may_skip (c->buffer->info[skippy_iter.idx]))
2257
0
      {
2258
  /* Can't use the fast path if eg. the next char is a default-ignorable
2259
   * or other skippable. */
2260
0
        goto slow;
2261
0
      }
2262
0
    }
2263
0
    else
2264
0
    {
2265
      /* Failed to match a next glyph. Only try applying rules that have
2266
       * no further input. */
2267
0
      return_trace (
2268
0
      + hb_iter (rule)
2269
0
      | hb_map (hb_add (this))
2270
0
      | hb_filter ([&] (const Rule &_) { return _.inputCount <= 1; })
2271
0
      | hb_map ([&] (const Rule &_) { return _.apply (c, lookup_context); })
2272
0
      | hb_any
2273
0
      )
2274
0
      ;
2275
0
    }
2276
0
    matched = skippy_iter.next ();
2277
0
    if (likely (matched && !skippy_iter.may_skip (c->buffer->info[skippy_iter.idx])))
2278
0
    {
2279
0
      second = &c->buffer->info[skippy_iter.idx];
2280
0
      unsafe_to2 = skippy_iter.idx + 1;
2281
0
    }
2282
2283
0
    auto match_input = lookup_context.funcs.match;
2284
0
    auto *input_data = lookup_context.match_data;
2285
0
    for (unsigned int i = 0; i < num_rules; i++)
2286
0
    {
2287
0
      const auto &r = this+rule.arrayZ[i];
2288
2289
0
      const auto &input = r.inputZ;
2290
2291
0
      if (r.inputCount <= 1 ||
2292
0
    (!match_input ||
2293
0
     match_input (*first, input.arrayZ[0], input_data)))
2294
0
      {
2295
0
        if (!second ||
2296
0
      (r.inputCount <= 2 ||
2297
0
       (!match_input ||
2298
0
        match_input (*second, input.arrayZ[1], input_data)))
2299
0
     )
2300
0
  {
2301
0
    if (r.apply (c, lookup_context))
2302
0
    {
2303
0
      if (unsafe_to != (unsigned) -1)
2304
0
        c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to);
2305
0
      return_trace (true);
2306
0
    }
2307
0
  }
2308
0
  else
2309
0
    unsafe_to = unsafe_to2;
2310
0
      }
2311
0
      else
2312
0
      {
2313
0
  if (unsafe_to == (unsigned) -1)
2314
0
    unsafe_to = unsafe_to1;
2315
0
      }
2316
0
    }
2317
0
    if (likely (unsafe_to != (unsigned) -1))
2318
0
      c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to);
2319
2320
0
    return_trace (false);
2321
0
  }
2322
2323
  bool subset (hb_subset_context_t *c,
2324
         const hb_map_t *lookup_map,
2325
         const hb_map_t *klass_map = nullptr) const
2326
0
  {
2327
0
    TRACE_SUBSET (this);
2328
0
2329
0
    auto snap = c->serializer->snapshot ();
2330
0
    auto *out = c->serializer->start_embed (*this);
2331
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
2332
0
2333
0
    for (const Offset16To<Rule>& _ : rule)
2334
0
    {
2335
0
      if (!_) continue;
2336
0
      auto o_snap = c->serializer->snapshot ();
2337
0
      auto *o = out->rule.serialize_append (c->serializer);
2338
0
      if (unlikely (!o)) continue;
2339
0
2340
0
      if (!o->serialize_subset (c, _, this, lookup_map, klass_map))
2341
0
      {
2342
0
  out->rule.pop ();
2343
0
  c->serializer->revert (o_snap);
2344
0
      }
2345
0
    }
2346
0
2347
0
    bool ret = bool (out->rule);
2348
0
    if (!ret) c->serializer->revert (snap);
2349
0
2350
0
    return_trace (ret);
2351
0
  }
2352
2353
  bool sanitize (hb_sanitize_context_t *c) const
2354
0
  {
2355
0
    TRACE_SANITIZE (this);
2356
0
    return_trace (rule.sanitize (c, this));
2357
0
  }
2358
2359
  protected:
2360
  Array16OfOffset16To<Rule>
2361
    rule;     /* Array of Rule tables
2362
           * ordered by preference */
2363
  public:
2364
  DEFINE_SIZE_ARRAY (2, rule);
2365
};
2366
2367
2368
template <typename Types>
2369
struct ContextFormat1_4
2370
{
2371
  using RuleSet = OT::RuleSet<Types>;
2372
2373
  bool intersects (const hb_set_t *glyphs) const
2374
0
  {
2375
0
    struct ContextClosureLookupContext lookup_context = {
2376
0
      {intersects_glyph, intersected_glyph},
2377
0
      ContextFormat::SimpleContext,
2378
0
      nullptr
2379
0
    };
2380
0
2381
0
    return
2382
0
    + hb_zip (this+coverage, ruleSet)
2383
0
    | hb_filter (*glyphs, hb_first)
2384
0
    | hb_map (hb_second)
2385
0
    | hb_map (hb_add (this))
2386
0
    | hb_map ([&] (const RuleSet &_) { return _.intersects (glyphs, lookup_context); })
2387
0
    | hb_any
2388
0
    ;
2389
0
  }
2390
2391
  bool may_have_non_1to1 () const
2392
0
  { return true; }
2393
2394
  void closure (hb_closure_context_t *c) const
2395
0
  {
2396
0
    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
2397
0
    if (unlikely (!cur_active_glyphs)) return;
2398
0
    get_coverage ().intersect_set (c->previous_parent_active_glyphs (), *cur_active_glyphs);
2399
2400
0
    struct ContextClosureLookupContext lookup_context = {
2401
0
      {intersects_glyph, intersected_glyph},
2402
0
      ContextFormat::SimpleContext,
2403
0
      nullptr
2404
0
    };
2405
2406
0
    + hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len))
2407
0
    | hb_filter ([&] (hb_codepoint_t _) {
2408
0
      return c->previous_parent_active_glyphs ().has (_);
2409
0
    }, hb_first)
2410
0
    | hb_map ([&](const hb_pair_t<hb_codepoint_t, unsigned> _) { return hb_pair_t<unsigned, const RuleSet&> (_.first, this+ruleSet[_.second]); })
2411
0
    | hb_apply ([&] (const hb_pair_t<unsigned, const RuleSet&>& _) { _.second.closure (c, _.first, lookup_context); })
2412
0
    ;
2413
2414
0
    c->pop_cur_done_glyphs ();
2415
0
  }
2416
2417
  void closure_lookups (hb_closure_lookups_context_t *c) const
2418
0
  {
2419
0
    struct ContextClosureLookupContext lookup_context = {
2420
0
      {intersects_glyph, nullptr},
2421
0
      ContextFormat::SimpleContext,
2422
0
      nullptr
2423
0
    };
2424
0
2425
0
    + hb_zip (this+coverage, ruleSet)
2426
0
    | hb_filter (*c->glyphs, hb_first)
2427
0
    | hb_map (hb_second)
2428
0
    | hb_map (hb_add (this))
2429
0
    | hb_apply ([&] (const RuleSet &_) { _.closure_lookups (c, lookup_context); })
2430
0
    ;
2431
0
  }
2432
2433
0
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
2434
2435
  void collect_glyphs (hb_collect_glyphs_context_t *c) const
2436
0
  {
2437
0
    (this+coverage).collect_coverage (c->input);
2438
2439
0
    struct ContextCollectGlyphsLookupContext lookup_context = {
2440
0
      {collect_glyph},
2441
0
      nullptr
2442
0
    };
2443
2444
0
    + hb_iter (ruleSet)
2445
0
    | hb_map (hb_add (this))
2446
0
    | hb_apply ([&] (const RuleSet &_) { _.collect_glyphs (c, lookup_context); })
2447
0
    ;
2448
0
  }
2449
2450
  bool would_apply (hb_would_apply_context_t *c) const
2451
0
  {
2452
0
    const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
2453
0
    struct ContextApplyLookupContext lookup_context = {
2454
0
      {match_glyph},
2455
0
      nullptr
2456
0
    };
2457
0
    return rule_set.would_apply (c, lookup_context);
2458
0
  }
2459
2460
0
  const Coverage &get_coverage () const { return this+coverage; }
2461
2462
  bool apply (hb_ot_apply_context_t *c) const
2463
0
  {
2464
0
    TRACE_APPLY (this);
2465
0
    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
2466
0
    if (likely (index == NOT_COVERED))
2467
0
      return_trace (false);
2468
2469
0
    const RuleSet &rule_set = this+ruleSet[index];
2470
0
    struct ContextApplyLookupContext lookup_context = {
2471
0
      {match_glyph},
2472
0
      nullptr
2473
0
    };
2474
0
    return_trace (rule_set.apply (c, lookup_context));
2475
0
  }
2476
2477
  bool subset (hb_subset_context_t *c) const
2478
0
  {
2479
0
    TRACE_SUBSET (this);
2480
0
    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
2481
0
    const hb_map_t &glyph_map = *c->plan->glyph_map;
2482
0
2483
0
    auto *out = c->serializer->start_embed (*this);
2484
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
2485
0
    out->format = format;
2486
0
2487
0
    const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? &c->plan->gsub_lookups : &c->plan->gpos_lookups;
2488
0
    hb_sorted_vector_t<hb_codepoint_t> new_coverage;
2489
0
    + hb_zip (this+coverage, ruleSet)
2490
0
    | hb_filter (glyphset, hb_first)
2491
0
    | hb_filter (subset_offset_array (c, out->ruleSet, this, lookup_map), hb_second)
2492
0
    | hb_map (hb_first)
2493
0
    | hb_map (glyph_map)
2494
0
    | hb_sink (new_coverage)
2495
0
    ;
2496
0
2497
0
    out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
2498
0
    return_trace (bool (new_coverage));
2499
0
  }
2500
2501
  bool sanitize (hb_sanitize_context_t *c) const
2502
0
  {
2503
0
    TRACE_SANITIZE (this);
2504
0
    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
2505
0
  }
2506
2507
  protected:
2508
  HBUINT16  format;     /* Format identifier--format = 1 */
2509
  typename Types::template OffsetTo<Coverage>
2510
    coverage;   /* Offset to Coverage table--from
2511
           * beginning of table */
2512
  Array16Of<typename Types::template OffsetTo<RuleSet>>
2513
    ruleSet;    /* Array of RuleSet tables
2514
           * ordered by Coverage Index */
2515
  public:
2516
  DEFINE_SIZE_ARRAY (2 + 2 * Types::size, ruleSet);
2517
};
2518
2519
2520
template <typename Types>
2521
struct ContextFormat2_5
2522
{
2523
  using RuleSet = OT::RuleSet<SmallTypes>;
2524
2525
  bool intersects (const hb_set_t *glyphs) const
2526
0
  {
2527
0
    if (!(this+coverage).intersects (glyphs))
2528
0
      return false;
2529
0
2530
0
    const ClassDef &class_def = this+classDef;
2531
0
2532
0
    hb_map_t cache;
2533
0
    struct ContextClosureLookupContext lookup_context = {
2534
0
      {intersects_class, nullptr},
2535
0
      ContextFormat::ClassBasedContext,
2536
0
      &class_def,
2537
0
      &cache
2538
0
    };
2539
0
2540
0
    hb_set_t retained_coverage_glyphs;
2541
0
    (this+coverage).intersect_set (*glyphs, retained_coverage_glyphs);
2542
0
2543
0
    hb_set_t coverage_glyph_classes;
2544
0
    class_def.intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
2545
0
2546
0
2547
0
    return
2548
0
    + hb_iter (ruleSet)
2549
0
    | hb_map (hb_add (this))
2550
0
    | hb_enumerate
2551
0
    | hb_map ([&] (const hb_pair_t<unsigned, const RuleSet &> p)
2552
0
        { return class_def.intersects_class (glyphs, p.first) &&
2553
0
           coverage_glyph_classes.has (p.first) &&
2554
0
           p.second.intersects (glyphs, lookup_context); })
2555
0
    | hb_any
2556
0
    ;
2557
0
  }
2558
2559
  bool may_have_non_1to1 () const
2560
0
  { return true; }
2561
2562
  void closure (hb_closure_context_t *c) const
2563
0
  {
2564
0
    if (!(this+coverage).intersects (c->glyphs))
2565
0
      return;
2566
2567
0
    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
2568
0
    if (unlikely (!cur_active_glyphs)) return;
2569
0
    get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
2570
0
           *cur_active_glyphs);
2571
2572
0
    const ClassDef &class_def = this+classDef;
2573
2574
0
    hb_map_t cache;
2575
0
    intersected_class_cache_t intersected_cache;
2576
0
    struct ContextClosureLookupContext lookup_context = {
2577
0
      {intersects_class, intersected_class_glyphs},
2578
0
      ContextFormat::ClassBasedContext,
2579
0
      &class_def,
2580
0
      &cache,
2581
0
      &intersected_cache
2582
0
    };
2583
2584
0
    + hb_enumerate (ruleSet)
2585
0
    | hb_filter ([&] (unsigned _)
2586
0
    { return class_def.intersects_class (&c->parent_active_glyphs (), _); },
2587
0
     hb_first)
2588
0
    | hb_apply ([&] (const hb_pair_t<unsigned, const typename Types::template OffsetTo<RuleSet>&> _)
2589
0
                {
2590
0
                  const RuleSet& rule_set = this+_.second;
2591
0
                  rule_set.closure (c, _.first, lookup_context);
2592
0
                })
2593
0
    ;
2594
2595
0
    c->pop_cur_done_glyphs ();
2596
0
  }
2597
2598
  void closure_lookups (hb_closure_lookups_context_t *c) const
2599
0
  {
2600
0
    if (!(this+coverage).intersects (c->glyphs))
2601
0
      return;
2602
0
2603
0
    const ClassDef &class_def = this+classDef;
2604
0
2605
0
    hb_map_t cache;
2606
0
    struct ContextClosureLookupContext lookup_context = {
2607
0
      {intersects_class, nullptr},
2608
0
      ContextFormat::ClassBasedContext,
2609
0
      &class_def,
2610
0
      &cache
2611
0
    };
2612
0
2613
0
    + hb_iter (ruleSet)
2614
0
    | hb_map (hb_add (this))
2615
0
    | hb_enumerate
2616
0
    | hb_filter ([&] (const hb_pair_t<unsigned, const RuleSet &> p)
2617
0
    { return class_def.intersects_class (c->glyphs, p.first); })
2618
0
    | hb_map (hb_second)
2619
0
    | hb_apply ([&] (const RuleSet & _)
2620
0
    { _.closure_lookups (c, lookup_context); });
2621
0
  }
2622
2623
0
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
2624
2625
  void collect_glyphs (hb_collect_glyphs_context_t *c) const
2626
0
  {
2627
0
    (this+coverage).collect_coverage (c->input);
2628
2629
0
    const ClassDef &class_def = this+classDef;
2630
0
    struct ContextCollectGlyphsLookupContext lookup_context = {
2631
0
      {collect_class},
2632
0
      &class_def
2633
0
    };
2634
2635
0
    + hb_iter (ruleSet)
2636
0
    | hb_map (hb_add (this))
2637
0
    | hb_apply ([&] (const RuleSet &_) { _.collect_glyphs (c, lookup_context); })
2638
0
    ;
2639
0
  }
2640
2641
  bool would_apply (hb_would_apply_context_t *c) const
2642
0
  {
2643
0
    const ClassDef &class_def = this+classDef;
2644
0
    unsigned int index = class_def.get_class (c->glyphs[0]);
2645
0
    const RuleSet &rule_set = this+ruleSet[index];
2646
0
    struct ContextApplyLookupContext lookup_context = {
2647
0
      {match_class},
2648
0
      &class_def
2649
0
    };
2650
0
    return rule_set.would_apply (c, lookup_context);
2651
0
  }
2652
2653
0
  const Coverage &get_coverage () const { return this+coverage; }
2654
2655
  unsigned cache_cost () const
2656
0
  {
2657
0
    return (this+classDef).cost ();
2658
0
  }
2659
  static bool cache_func (hb_ot_apply_context_t *c, hb_ot_subtable_cache_op_t op)
2660
0
  {
2661
0
    return context_cache_func (c, op);
2662
0
  }
2663
2664
0
  bool apply_cached (hb_ot_apply_context_t *c, void *external_cache HB_UNUSED) const { return _apply (c, true); }
2665
0
  bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
2666
  bool _apply (hb_ot_apply_context_t *c, bool cached) const
2667
0
  {
2668
0
    TRACE_APPLY (this);
2669
0
    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
2670
0
    if (index == NOT_COVERED) return_trace (false);
2671
2672
0
    const ClassDef &class_def = this+classDef;
2673
2674
0
    struct ContextApplyLookupContext lookup_context = {
2675
0
      {cached ? match_class_cached : match_class},
2676
0
      &class_def
2677
0
    };
2678
2679
0
    index = cached ? get_class_cached (class_def, c->buffer->cur()) : class_def.get_class (c->buffer->cur().codepoint);
2680
0
    const RuleSet &rule_set = this+ruleSet[index];
2681
0
    return_trace (rule_set.apply (c, lookup_context));
2682
0
  }
2683
2684
  bool subset (hb_subset_context_t *c) const
2685
0
  {
2686
0
    TRACE_SUBSET (this);
2687
0
    auto *out = c->serializer->start_embed (*this);
2688
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
2689
0
    out->format = format;
2690
0
    if (unlikely (!out->coverage.serialize_subset (c, coverage, this)))
2691
0
      return_trace (false);
2692
0
2693
0
    hb_map_t klass_map;
2694
0
    out->classDef.serialize_subset (c, classDef, this, &klass_map);
2695
0
2696
0
    const hb_set_t* glyphset = c->plan->glyphset_gsub ();
2697
0
    hb_set_t retained_coverage_glyphs;
2698
0
    (this+coverage).intersect_set (*glyphset, retained_coverage_glyphs);
2699
0
2700
0
    hb_set_t coverage_glyph_classes;
2701
0
    (this+classDef).intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
2702
0
2703
0
    const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? &c->plan->gsub_lookups : &c->plan->gpos_lookups;
2704
0
    bool ret = true;
2705
0
    int non_zero_index = -1, index = 0;
2706
0
    auto snapshot = c->serializer->snapshot();
2707
0
    for (const auto& _ : + hb_enumerate (ruleSet)
2708
0
       | hb_filter (klass_map, hb_first))
2709
0
    {
2710
0
      auto *o = out->ruleSet.serialize_append (c->serializer);
2711
0
      if (unlikely (!o))
2712
0
      {
2713
0
  ret = false;
2714
0
  break;
2715
0
      }
2716
0
2717
0
      if (coverage_glyph_classes.has (_.first) &&
2718
0
    o->serialize_subset (c, _.second, this, lookup_map, &klass_map)) {
2719
0
  non_zero_index = index;
2720
0
        snapshot = c->serializer->snapshot();
2721
0
      }
2722
0
2723
0
      index++;
2724
0
    }
2725
0
2726
0
    if (!ret || non_zero_index == -1) return_trace (false);
2727
0
2728
0
    //prune empty trailing ruleSets
2729
0
    --index;
2730
0
    while (index > non_zero_index)
2731
0
    {
2732
0
      out->ruleSet.pop ();
2733
0
      index--;
2734
0
    }
2735
0
    c->serializer->revert (snapshot);
2736
0
2737
0
    return_trace (bool (out->ruleSet));
2738
0
  }
2739
2740
  bool sanitize (hb_sanitize_context_t *c) const
2741
0
  {
2742
0
    TRACE_SANITIZE (this);
2743
0
    return_trace (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
2744
0
  }
2745
2746
  protected:
2747
  HBUINT16  format;     /* Format identifier--format = 2 */
2748
  typename Types::template OffsetTo<Coverage>
2749
    coverage;   /* Offset to Coverage table--from
2750
           * beginning of table */
2751
  typename Types::template OffsetTo<ClassDef>
2752
    classDef;   /* Offset to glyph ClassDef table--from
2753
           * beginning of table */
2754
  Array16Of<typename Types::template OffsetTo<RuleSet>>
2755
    ruleSet;    /* Array of RuleSet tables
2756
           * ordered by class */
2757
  public:
2758
  DEFINE_SIZE_ARRAY (4 + 2 * Types::size, ruleSet);
2759
};
2760
2761
2762
struct ContextFormat3
2763
{
2764
  using RuleSet = OT::RuleSet<SmallTypes>;
2765
2766
  bool intersects (const hb_set_t *glyphs) const
2767
0
  {
2768
0
    if (!(this+coverageZ[0]).intersects (glyphs))
2769
0
      return false;
2770
0
2771
0
    struct ContextClosureLookupContext lookup_context = {
2772
0
      {intersects_coverage, nullptr},
2773
0
      ContextFormat::CoverageBasedContext,
2774
0
      this
2775
0
    };
2776
0
    return context_intersects (glyphs,
2777
0
             glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
2778
0
             lookup_context);
2779
0
  }
2780
2781
  bool may_have_non_1to1 () const
2782
0
  { return true; }
2783
2784
  void closure (hb_closure_context_t *c) const
2785
0
  {
2786
0
    if (!(this+coverageZ[0]).intersects (c->glyphs))
2787
0
      return;
2788
2789
0
    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
2790
0
    if (unlikely (!cur_active_glyphs)) return;
2791
0
    get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
2792
0
           *cur_active_glyphs);
2793
2794
0
    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
2795
0
    struct ContextClosureLookupContext lookup_context = {
2796
0
      {intersects_coverage, intersected_coverage_glyphs},
2797
0
      ContextFormat::CoverageBasedContext,
2798
0
      this
2799
0
    };
2800
0
    context_closure_lookup (c,
2801
0
          glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
2802
0
          lookupCount, lookupRecord,
2803
0
          0, lookup_context);
2804
2805
0
    c->pop_cur_done_glyphs ();
2806
0
  }
2807
2808
  void closure_lookups (hb_closure_lookups_context_t *c) const
2809
0
  {
2810
0
    if (!intersects (c->glyphs))
2811
0
      return;
2812
0
    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
2813
0
    recurse_lookups (c, lookupCount, lookupRecord);
2814
0
  }
2815
2816
0
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
2817
2818
  void collect_glyphs (hb_collect_glyphs_context_t *c) const
2819
0
  {
2820
0
    (this+coverageZ[0]).collect_coverage (c->input);
2821
2822
0
    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
2823
0
    struct ContextCollectGlyphsLookupContext lookup_context = {
2824
0
      {collect_coverage},
2825
0
      this
2826
0
    };
2827
2828
0
    context_collect_glyphs_lookup (c,
2829
0
           glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
2830
0
           lookupCount, lookupRecord,
2831
0
           lookup_context);
2832
0
  }
2833
2834
  bool would_apply (hb_would_apply_context_t *c) const
2835
0
  {
2836
0
    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
2837
0
    struct ContextApplyLookupContext lookup_context = {
2838
0
      {match_coverage},
2839
0
      this
2840
0
    };
2841
0
    return context_would_apply_lookup (c,
2842
0
               glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
2843
0
               lookupCount, lookupRecord,
2844
0
               lookup_context);
2845
0
  }
2846
2847
0
  const Coverage &get_coverage () const { return this+coverageZ[0]; }
2848
2849
  bool apply (hb_ot_apply_context_t *c) const
2850
0
  {
2851
0
    TRACE_APPLY (this);
2852
0
    unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
2853
0
    if (index == NOT_COVERED) return_trace (false);
2854
2855
0
    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
2856
0
    struct ContextApplyLookupContext lookup_context = {
2857
0
      {match_coverage},
2858
0
      this
2859
0
    };
2860
0
    return_trace (context_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1), lookupCount, lookupRecord, lookup_context));
2861
0
  }
2862
2863
  bool subset (hb_subset_context_t *c) const
2864
0
  {
2865
0
    TRACE_SUBSET (this);
2866
0
    auto *out = c->serializer->start_embed (this);
2867
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
2868
0
2869
0
    out->format = format;
2870
0
    out->glyphCount = glyphCount;
2871
0
2872
0
    auto coverages = coverageZ.as_array (glyphCount);
2873
0
2874
0
    for (const Offset16To<Coverage>& offset : coverages)
2875
0
    {
2876
0
      /* TODO(subset) This looks like should not be necessary to write this way. */
2877
0
      auto *o = c->serializer->allocate_size<Offset16To<Coverage>> (Offset16To<Coverage>::static_size);
2878
0
      if (unlikely (!o)) return_trace (false);
2879
0
      if (!o->serialize_subset (c, offset, this)) return_trace (false);
2880
0
    }
2881
0
2882
0
    const auto& lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> (coverageZ.as_array (glyphCount));
2883
0
    const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? &c->plan->gsub_lookups : &c->plan->gpos_lookups;
2884
0
2885
0
2886
0
    unsigned count = serialize_lookuprecord_array (c->serializer, lookupRecord.as_array (lookupCount), lookup_map);
2887
0
    return_trace (c->serializer->check_assign (out->lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
2888
0
  }
2889
2890
  bool sanitize (hb_sanitize_context_t *c) const
2891
0
  {
2892
0
    TRACE_SANITIZE (this);
2893
0
    if (unlikely (!c->check_struct (this))) return_trace (false);
2894
0
    hb_barrier ();
2895
0
    unsigned int count = glyphCount;
2896
0
    if (unlikely (!count)) return_trace (false); /* We want to access coverageZ[0] freely. */
2897
0
    if (unlikely (!c->check_array (coverageZ.arrayZ, count))) return_trace (false);
2898
0
    for (unsigned int i = 0; i < count; i++)
2899
0
      if (unlikely (!coverageZ[i].sanitize (c, this))) return_trace (false);
2900
0
    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
2901
0
    return_trace (likely (c->check_array (lookupRecord, lookupCount)));
2902
0
  }
2903
2904
  protected:
2905
  HBUINT16  format;     /* Format identifier--format = 3 */
2906
  HBUINT16  glyphCount;   /* Number of glyphs in the input glyph
2907
           * sequence */
2908
  HBUINT16  lookupCount;    /* Number of LookupRecords */
2909
  UnsizedArrayOf<Offset16To<Coverage>>
2910
    coverageZ;    /* Array of offsets to Coverage
2911
           * table in glyph sequence order */
2912
/*UnsizedArrayOf<LookupRecord>
2913
    lookupRecordX;*/  /* Array of LookupRecords--in
2914
           * design order */
2915
  public:
2916
  DEFINE_SIZE_ARRAY (6, coverageZ);
2917
};
2918
2919
struct Context
2920
{
2921
  template <typename context_t, typename ...Ts>
2922
  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
2923
0
  {
2924
0
    if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
2925
0
    TRACE_DISPATCH (this, u.format);
2926
0
    switch (u.format) {
2927
0
    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
2928
0
    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
2929
0
    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
2930
#ifndef HB_NO_BEYOND_64K
2931
    case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
2932
    case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
2933
#endif
2934
0
    default:return_trace (c->default_return_value ());
2935
0
    }
2936
0
  }
Unexecuted instantiation: OT::hb_intersects_context_t::return_t OT::Context::dispatch<OT::hb_intersects_context_t>(OT::hb_intersects_context_t*) const
Unexecuted instantiation: OT::hb_ot_apply_context_t::return_t OT::Context::dispatch<OT::hb_ot_apply_context_t>(OT::hb_ot_apply_context_t*) const
Unexecuted instantiation: OT::hb_collect_glyphs_context_t::return_t OT::Context::dispatch<OT::hb_collect_glyphs_context_t>(OT::hb_collect_glyphs_context_t*) const
Unexecuted instantiation: OT::hb_closure_lookups_context_t::return_t OT::Context::dispatch<OT::hb_closure_lookups_context_t>(OT::hb_closure_lookups_context_t*) const
Unexecuted instantiation: hb_subset_context_t::return_t OT::Context::dispatch<hb_subset_context_t>(hb_subset_context_t*) const
Unexecuted instantiation: hb_sanitize_context_t::return_t OT::Context::dispatch<hb_sanitize_context_t>(hb_sanitize_context_t*) const
Unexecuted instantiation: OT::hb_collect_variation_indices_context_t::return_t OT::Context::dispatch<OT::hb_collect_variation_indices_context_t>(OT::hb_collect_variation_indices_context_t*) const
Unexecuted instantiation: OT::hb_accelerate_subtables_context_t::return_t OT::Context::dispatch<OT::hb_accelerate_subtables_context_t>(OT::hb_accelerate_subtables_context_t*) const
Unexecuted instantiation: OT::hb_have_non_1to1_context_t::return_t OT::Context::dispatch<OT::hb_have_non_1to1_context_t>(OT::hb_have_non_1to1_context_t*) const
Unexecuted instantiation: OT::hb_closure_context_t::return_t OT::Context::dispatch<OT::hb_closure_context_t>(OT::hb_closure_context_t*) const
Unexecuted instantiation: OT::hb_would_apply_context_t::return_t OT::Context::dispatch<OT::hb_would_apply_context_t>(OT::hb_would_apply_context_t*) const
Unexecuted instantiation: hb_get_glyph_alternates_dispatch_t::return_t OT::Context::dispatch<hb_get_glyph_alternates_dispatch_t, unsigned int&, unsigned int&, unsigned int*&, unsigned int*&>(hb_get_glyph_alternates_dispatch_t*, unsigned int&, unsigned int&, unsigned int*&, unsigned int*&) const
Unexecuted instantiation: hb_position_single_dispatch_t::return_t OT::Context::dispatch<hb_position_single_dispatch_t, hb_font_t*&, hb_blob_t*&, hb_direction_t&, unsigned int&, hb_glyph_position_t&>(hb_position_single_dispatch_t*, hb_font_t*&, hb_blob_t*&, hb_direction_t&, unsigned int&, hb_glyph_position_t&) const
2937
2938
  protected:
2939
  union {
2940
  HBUINT16      format;   /* Format identifier */
2941
  ContextFormat1_4<SmallTypes>  format1;
2942
  ContextFormat2_5<SmallTypes>  format2;
2943
  ContextFormat3    format3;
2944
#ifndef HB_NO_BEYOND_64K
2945
  ContextFormat1_4<MediumTypes> format4;
2946
  ContextFormat2_5<MediumTypes> format5;
2947
#endif
2948
  } u;
2949
};
2950
2951
2952
/* Chaining Contextual lookups */
2953
2954
struct ChainContextClosureLookupContext
2955
{
2956
  ContextClosureFuncs funcs;
2957
  ContextFormat context_format;
2958
  const void *intersects_data[3];
2959
  void *intersects_cache[3];
2960
  void *intersected_glyphs_cache;
2961
};
2962
2963
struct ChainContextCollectGlyphsLookupContext
2964
{
2965
  ContextCollectGlyphsFuncs funcs;
2966
  const void *collect_data[3];
2967
};
2968
2969
struct ChainContextApplyLookupContext
2970
{
2971
  ChainContextApplyFuncs funcs;
2972
  const void *match_data[3];
2973
};
2974
2975
template <typename HBUINT>
2976
static inline bool chain_context_intersects (const hb_set_t *glyphs,
2977
               unsigned int backtrackCount,
2978
               const HBUINT backtrack[],
2979
               unsigned int inputCount, /* Including the first glyph (not matched) */
2980
               const HBUINT input[], /* Array of input values--start with second glyph */
2981
               unsigned int lookaheadCount,
2982
               const HBUINT lookahead[],
2983
               ChainContextClosureLookupContext &lookup_context)
2984
0
{
2985
0
  return array_is_subset_of (glyphs,
2986
0
           backtrackCount, backtrack,
2987
0
           lookup_context.funcs.intersects,
2988
0
           lookup_context.intersects_data[0],
2989
0
           lookup_context.intersects_cache[0])
2990
0
      && array_is_subset_of (glyphs,
2991
0
           inputCount ? inputCount - 1 : 0, input,
2992
0
           lookup_context.funcs.intersects,
2993
0
           lookup_context.intersects_data[1],
2994
0
           lookup_context.intersects_cache[1])
2995
0
      && array_is_subset_of (glyphs,
2996
0
           lookaheadCount, lookahead,
2997
0
           lookup_context.funcs.intersects,
2998
0
           lookup_context.intersects_data[2],
2999
0
           lookup_context.intersects_cache[2]);
3000
0
}
Unexecuted instantiation: hb-ot-face.cc:bool OT::chain_context_intersects<OT::NumType<true, unsigned short, 2u> >(hb_set_t const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-aat-layout.cc:bool OT::chain_context_intersects<OT::NumType<true, unsigned short, 2u> >(hb_set_t const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-layout.cc:bool OT::chain_context_intersects<OT::NumType<true, unsigned short, 2u> >(hb_set_t const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:bool OT::chain_context_intersects<OT::NumType<true, unsigned short, 2u> >(hb_set_t const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-shape-fallback.cc:bool OT::chain_context_intersects<OT::NumType<true, unsigned short, 2u> >(hb_set_t const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, OT::ChainContextClosureLookupContext&)
3001
3002
template <typename HBUINT>
3003
static inline void chain_context_closure_lookup (hb_closure_context_t *c,
3004
             unsigned int backtrackCount,
3005
             const HBUINT backtrack[],
3006
             unsigned int inputCount, /* Including the first glyph (not matched) */
3007
             const HBUINT input[], /* Array of input values--start with second glyph */
3008
             unsigned int lookaheadCount,
3009
             const HBUINT lookahead[],
3010
             unsigned int lookupCount,
3011
             const LookupRecord lookupRecord[],
3012
             unsigned value,
3013
             ChainContextClosureLookupContext &lookup_context)
3014
0
{
3015
0
  if (chain_context_intersects (c->glyphs,
3016
0
        backtrackCount, backtrack,
3017
0
        inputCount, input,
3018
0
        lookaheadCount, lookahead,
3019
0
        lookup_context))
3020
0
    context_closure_recurse_lookups (c,
3021
0
         inputCount, input,
3022
0
         lookupCount, lookupRecord,
3023
0
         value,
3024
0
         lookup_context.context_format,
3025
0
         lookup_context.intersects_data[1],
3026
0
         lookup_context.funcs.intersected_glyphs,
3027
0
         lookup_context.intersected_glyphs_cache);
3028
0
}
Unexecuted instantiation: hb-ot-face.cc:void OT::chain_context_closure_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_closure_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, unsigned int, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-aat-layout.cc:void OT::chain_context_closure_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_closure_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, unsigned int, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-layout.cc:void OT::chain_context_closure_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_closure_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, unsigned int, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:void OT::chain_context_closure_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_closure_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, unsigned int, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-shape-fallback.cc:void OT::chain_context_closure_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_closure_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, unsigned int, OT::ChainContextClosureLookupContext&)
3029
3030
template <typename HBUINT>
3031
static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
3032
              unsigned int backtrackCount,
3033
              const HBUINT backtrack[],
3034
              unsigned int inputCount, /* Including the first glyph (not matched) */
3035
              const HBUINT input[], /* Array of input values--start with second glyph */
3036
              unsigned int lookaheadCount,
3037
              const HBUINT lookahead[],
3038
              unsigned int lookupCount,
3039
              const LookupRecord lookupRecord[],
3040
              ChainContextCollectGlyphsLookupContext &lookup_context)
3041
0
{
3042
0
  collect_array (c, c->before,
3043
0
     backtrackCount, backtrack,
3044
0
     lookup_context.funcs.collect, lookup_context.collect_data[0]);
3045
0
  collect_array (c, c->input,
3046
0
     inputCount ? inputCount - 1 : 0, input,
3047
0
     lookup_context.funcs.collect, lookup_context.collect_data[1]);
3048
0
  collect_array (c, c->after,
3049
0
     lookaheadCount, lookahead,
3050
0
     lookup_context.funcs.collect, lookup_context.collect_data[2]);
3051
0
  recurse_lookups (c,
3052
0
       lookupCount, lookupRecord);
3053
0
}
Unexecuted instantiation: hb-ot-face.cc:void OT::chain_context_collect_glyphs_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_collect_glyphs_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ChainContextCollectGlyphsLookupContext&)
Unexecuted instantiation: hb-aat-layout.cc:void OT::chain_context_collect_glyphs_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_collect_glyphs_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ChainContextCollectGlyphsLookupContext&)
Unexecuted instantiation: hb-ot-layout.cc:void OT::chain_context_collect_glyphs_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_collect_glyphs_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ChainContextCollectGlyphsLookupContext&)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:void OT::chain_context_collect_glyphs_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_collect_glyphs_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ChainContextCollectGlyphsLookupContext&)
Unexecuted instantiation: hb-ot-shape-fallback.cc:void OT::chain_context_collect_glyphs_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_collect_glyphs_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ChainContextCollectGlyphsLookupContext&)
3054
3055
template <typename HBUINT>
3056
static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
3057
                 unsigned int backtrackCount,
3058
                 const HBUINT backtrack[] HB_UNUSED,
3059
                 unsigned int inputCount, /* Including the first glyph (not matched) */
3060
                 const HBUINT input[], /* Array of input values--start with second glyph */
3061
                 unsigned int lookaheadCount,
3062
                 const HBUINT lookahead[] HB_UNUSED,
3063
                 unsigned int lookupCount HB_UNUSED,
3064
                 const LookupRecord lookupRecord[] HB_UNUSED,
3065
                 const ChainContextApplyLookupContext &lookup_context)
3066
0
{
3067
0
  return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
3068
0
      && would_match_input (c,
3069
0
          inputCount, input,
3070
0
          lookup_context.funcs.match[1], lookup_context.match_data[1]);
3071
0
}
Unexecuted instantiation: hb-ot-face.cc:bool OT::chain_context_would_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_would_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ChainContextApplyLookupContext const&)
Unexecuted instantiation: hb-aat-layout.cc:bool OT::chain_context_would_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_would_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ChainContextApplyLookupContext const&)
Unexecuted instantiation: hb-ot-layout.cc:bool OT::chain_context_would_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_would_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ChainContextApplyLookupContext const&)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:bool OT::chain_context_would_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_would_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ChainContextApplyLookupContext const&)
Unexecuted instantiation: hb-ot-shape-fallback.cc:bool OT::chain_context_would_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_would_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ChainContextApplyLookupContext const&)
3072
3073
template <typename HBUINT>
3074
HB_ALWAYS_INLINE
3075
static bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
3076
          unsigned int backtrackCount,
3077
          const HBUINT backtrack[],
3078
          unsigned int inputCount, /* Including the first glyph (not matched) */
3079
          const HBUINT input[], /* Array of input values--start with second glyph */
3080
          unsigned int lookaheadCount,
3081
          const HBUINT lookahead[],
3082
          unsigned int lookupCount,
3083
          const LookupRecord lookupRecord[],
3084
          const ChainContextApplyLookupContext &lookup_context)
3085
0
{
3086
0
  if (unlikely (inputCount > HB_MAX_CONTEXT_LENGTH)) return false;
3087
3088
0
  unsigned start_index = c->buffer->out_len;
3089
0
  unsigned end_index = c->buffer->idx;
3090
0
  unsigned match_end = 0;
3091
0
  bool ret = true;
3092
0
  if (!(match_input (c,
3093
0
         inputCount, input,
3094
0
         lookup_context.funcs.match[1], lookup_context.match_data[1],
3095
0
         &match_end) && (end_index = match_end)
3096
0
       && match_lookahead (c,
3097
0
         lookaheadCount, lookahead,
3098
0
         lookup_context.funcs.match[2], lookup_context.match_data[2],
3099
0
         match_end, &end_index)))
3100
0
  {
3101
0
    c->buffer->unsafe_to_concat (c->buffer->idx, end_index);
3102
0
    return false;
3103
0
  }
3104
3105
0
  if (!match_backtrack (c,
3106
0
      backtrackCount, backtrack,
3107
0
      lookup_context.funcs.match[0], lookup_context.match_data[0],
3108
0
      &start_index))
3109
0
  {
3110
0
    c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index);
3111
0
    return false;
3112
0
  }
3113
3114
0
  c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
3115
0
  apply_lookup (c,
3116
0
    inputCount,
3117
0
    lookupCount, lookupRecord,
3118
0
    match_end);
3119
3120
0
  return ret;
3121
0
}
Unexecuted instantiation: hb-ot-face.cc:bool OT::chain_context_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ChainContextApplyLookupContext const&)
Unexecuted instantiation: hb-aat-layout.cc:bool OT::chain_context_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ChainContextApplyLookupContext const&)
Unexecuted instantiation: hb-ot-layout.cc:bool OT::chain_context_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ChainContextApplyLookupContext const&)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:bool OT::chain_context_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ChainContextApplyLookupContext const&)
Unexecuted instantiation: hb-ot-shape-fallback.cc:bool OT::chain_context_apply_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_ot_apply_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, OT::ChainContextApplyLookupContext const&)
3122
3123
template <typename Types>
3124
struct ChainRule
3125
{
3126
  template <typename T>
3127
  friend struct ChainRuleSet;
3128
3129
  bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
3130
0
  {
3131
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
3132
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
3133
0
    return chain_context_intersects (glyphs,
3134
0
             backtrack.len, backtrack.arrayZ,
3135
0
             input.lenP1, input.arrayZ,
3136
0
             lookahead.len, lookahead.arrayZ,
3137
0
             lookup_context);
3138
0
  }
3139
3140
  void closure (hb_closure_context_t *c, unsigned value,
3141
    ChainContextClosureLookupContext &lookup_context) const
3142
0
  {
3143
0
    if (unlikely (c->lookup_limit_exceeded ())) return;
3144
3145
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
3146
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
3147
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
3148
0
    chain_context_closure_lookup (c,
3149
0
          backtrack.len, backtrack.arrayZ,
3150
0
          input.lenP1, input.arrayZ,
3151
0
          lookahead.len, lookahead.arrayZ,
3152
0
          lookup.len, lookup.arrayZ,
3153
0
          value,
3154
0
          lookup_context);
3155
0
  }
3156
3157
  void closure_lookups (hb_closure_lookups_context_t *c,
3158
                        ChainContextClosureLookupContext &lookup_context) const
3159
0
  {
3160
0
    if (unlikely (c->lookup_limit_exceeded ())) return;
3161
0
    if (!intersects (c->glyphs, lookup_context)) return;
3162
0
3163
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
3164
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
3165
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
3166
0
    recurse_lookups (c, lookup.len, lookup.arrayZ);
3167
0
  }
3168
3169
  void collect_glyphs (hb_collect_glyphs_context_t *c,
3170
           ChainContextCollectGlyphsLookupContext &lookup_context) const
3171
0
  {
3172
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
3173
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
3174
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
3175
0
    chain_context_collect_glyphs_lookup (c,
3176
0
           backtrack.len, backtrack.arrayZ,
3177
0
           input.lenP1, input.arrayZ,
3178
0
           lookahead.len, lookahead.arrayZ,
3179
0
           lookup.len, lookup.arrayZ,
3180
0
           lookup_context);
3181
0
  }
3182
3183
  bool would_apply (hb_would_apply_context_t *c,
3184
        const ChainContextApplyLookupContext &lookup_context) const
3185
0
  {
3186
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
3187
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
3188
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
3189
0
    return chain_context_would_apply_lookup (c,
3190
0
               backtrack.len, backtrack.arrayZ,
3191
0
               input.lenP1, input.arrayZ,
3192
0
               lookahead.len, lookahead.arrayZ, lookup.len,
3193
0
               lookup.arrayZ, lookup_context);
3194
0
  }
3195
3196
  bool apply (hb_ot_apply_context_t *c,
3197
        const ChainContextApplyLookupContext &lookup_context) const
3198
0
  {
3199
0
    TRACE_APPLY (this);
3200
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
3201
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
3202
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
3203
0
    return_trace (chain_context_apply_lookup (c,
3204
0
                backtrack.len, backtrack.arrayZ,
3205
0
                input.lenP1, input.arrayZ,
3206
0
                lookahead.len, lookahead.arrayZ, lookup.len,
3207
0
                lookup.arrayZ, lookup_context));
3208
0
  }
3209
3210
  template<typename Iterator,
3211
     hb_requires (hb_is_iterator (Iterator))>
3212
  void serialize_array (hb_serialize_context_t *c,
3213
      HBUINT16 len,
3214
      Iterator it) const
3215
0
  {
3216
0
    c->copy (len);
3217
0
    for (const auto g : it)
3218
0
      c->copy ((HBUINT16) g);
3219
0
  }
3220
3221
  bool serialize (hb_serialize_context_t *c,
3222
      const hb_map_t *lookup_map,
3223
      const hb_map_t *backtrack_map,
3224
      const hb_map_t *input_map = nullptr,
3225
      const hb_map_t *lookahead_map = nullptr) const
3226
0
  {
3227
0
    TRACE_SERIALIZE (this);
3228
0
3229
0
    const hb_map_t *mapping = backtrack_map;
3230
0
    serialize_array (c, backtrack.len, + backtrack.iter ()
3231
0
               | hb_map (mapping));
3232
0
3233
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
3234
0
    if (input_map) mapping = input_map;
3235
0
    serialize_array (c, input.lenP1, + input.iter ()
3236
0
             | hb_map (mapping));
3237
0
3238
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
3239
0
    if (lookahead_map) mapping = lookahead_map;
3240
0
    serialize_array (c, lookahead.len, + lookahead.iter ()
3241
0
               | hb_map (mapping));
3242
0
3243
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
3244
0
3245
0
    HBUINT16* lookupCount = c->embed (&(lookup.len));
3246
0
    if (!lookupCount) return_trace (false);
3247
0
3248
0
    unsigned count = serialize_lookuprecord_array (c, lookup.as_array (), lookup_map);
3249
0
    return_trace (c->check_assign (*lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
3250
0
  }
3251
3252
  bool subset (hb_subset_context_t *c,
3253
         const hb_map_t *lookup_map,
3254
         const hb_map_t *backtrack_map = nullptr,
3255
         const hb_map_t *input_map = nullptr,
3256
         const hb_map_t *lookahead_map = nullptr) const
3257
0
  {
3258
0
    TRACE_SUBSET (this);
3259
0
3260
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
3261
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
3262
0
3263
0
    if (!backtrack_map)
3264
0
    {
3265
0
      const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
3266
0
      if (!hb_all (backtrack, glyphset) ||
3267
0
    !hb_all (input, glyphset) ||
3268
0
    !hb_all (lookahead, glyphset))
3269
0
  return_trace (false);
3270
0
3271
0
      serialize (c->serializer, lookup_map, c->plan->glyph_map);
3272
0
    }
3273
0
    else
3274
0
    {
3275
0
      if (!hb_all (backtrack, backtrack_map) ||
3276
0
    !hb_all (input, input_map) ||
3277
0
    !hb_all (lookahead, lookahead_map))
3278
0
  return_trace (false);
3279
0
3280
0
      serialize (c->serializer, lookup_map, backtrack_map, input_map, lookahead_map);
3281
0
    }
3282
0
3283
0
    return_trace (true);
3284
0
  }
3285
3286
  bool sanitize (hb_sanitize_context_t *c) const
3287
215
  {
3288
215
    TRACE_SANITIZE (this);
3289
    /* Hyper-optimized sanitized because this is really hot. */
3290
215
    if (unlikely (!backtrack.len.sanitize (c))) return_trace (false);
3291
215
    hb_barrier ();
3292
215
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
3293
215
    if (unlikely (!input.lenP1.sanitize (c))) return_trace (false);
3294
215
    hb_barrier ();
3295
215
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
3296
215
    if (unlikely (!lookahead.len.sanitize (c))) return_trace (false);
3297
215
    hb_barrier ();
3298
215
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
3299
215
    return_trace (likely (lookup.sanitize (c)));
3300
215
  }
3301
3302
  protected:
3303
  Array16Of<typename Types::HBUINT>
3304
    backtrack;    /* Array of backtracking values
3305
           * (to be matched before the input
3306
           * sequence) */
3307
  HeadlessArray16Of<typename Types::HBUINT>
3308
    inputX;     /* Array of input values (start with
3309
           * second glyph) */
3310
  Array16Of<typename Types::HBUINT>
3311
    lookaheadX;   /* Array of lookahead values's (to be
3312
           * matched after the input sequence) */
3313
  Array16Of<LookupRecord>
3314
    lookupX;    /* Array of LookupRecords--in
3315
           * design order) */
3316
  public:
3317
  DEFINE_SIZE_MIN (8);
3318
};
3319
3320
template <typename Types>
3321
struct ChainRuleSet
3322
{
3323
  using ChainRule = OT::ChainRule<Types>;
3324
3325
  bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
3326
0
  {
3327
0
    return
3328
0
    + hb_iter (rule)
3329
0
    | hb_map (hb_add (this))
3330
0
    | hb_map ([&] (const ChainRule &_) { return _.intersects (glyphs, lookup_context); })
3331
0
    | hb_any
3332
0
    ;
3333
0
  }
3334
  void closure (hb_closure_context_t *c, unsigned value, ChainContextClosureLookupContext &lookup_context) const
3335
0
  {
3336
0
    if (unlikely (c->lookup_limit_exceeded ())) return;
3337
3338
0
    return
3339
0
    + hb_iter (rule)
3340
0
    | hb_map (hb_add (this))
3341
0
    | hb_apply ([&] (const ChainRule &_) { _.closure (c, value, lookup_context); })
3342
0
    ;
3343
0
  }
3344
3345
  void closure_lookups (hb_closure_lookups_context_t *c,
3346
                        ChainContextClosureLookupContext &lookup_context) const
3347
0
  {
3348
0
    if (unlikely (c->lookup_limit_exceeded ())) return;
3349
0
3350
0
    + hb_iter (rule)
3351
0
    | hb_map (hb_add (this))
3352
0
    | hb_apply ([&] (const ChainRule &_) { _.closure_lookups (c, lookup_context); })
3353
0
    ;
3354
0
  }
3355
3356
  void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
3357
0
  {
3358
0
    return
3359
0
    + hb_iter (rule)
3360
0
    | hb_map (hb_add (this))
3361
0
    | hb_apply ([&] (const ChainRule &_) { _.collect_glyphs (c, lookup_context); })
3362
0
    ;
3363
0
  }
3364
3365
  bool would_apply (hb_would_apply_context_t *c,
3366
        const ChainContextApplyLookupContext &lookup_context) const
3367
0
  {
3368
0
    return
3369
0
    + hb_iter (rule)
3370
0
    | hb_map (hb_add (this))
3371
0
    | hb_map ([&] (const ChainRule &_) { return _.would_apply (c, lookup_context); })
3372
0
    | hb_any
3373
0
    ;
3374
0
  }
3375
3376
  bool apply (hb_ot_apply_context_t *c,
3377
        const ChainContextApplyLookupContext &lookup_context) const
3378
0
  {
3379
0
    TRACE_APPLY (this);
3380
3381
0
    unsigned num_rules = rule.len;
3382
3383
0
#ifndef HB_NO_OT_RULESETS_FAST_PATH
3384
0
    if (HB_OPTIMIZE_SIZE_VAL || num_rules <= 4)
3385
0
#endif
3386
0
    {
3387
0
    slow:
3388
0
      return_trace (
3389
0
      + hb_iter (rule)
3390
0
      | hb_map (hb_add (this))
3391
0
      | hb_map ([&] (const ChainRule &_) { return _.apply (c, lookup_context); })
3392
0
      | hb_any
3393
0
      )
3394
0
      ;
3395
0
    }
3396
3397
    /* This version is optimized for speed by matching the first & second
3398
     * components of the rule here, instead of calling into the matching code.
3399
     *
3400
     * Replicated from LigatureSet::apply(). */
3401
3402
    /* If the input skippy has non-auto joiners behavior (as in Indic shapers),
3403
     * skip this fast path, as we don't distinguish between input & lookahead
3404
     * matching in the fast path.
3405
     *
3406
     * https://github.com/harfbuzz/harfbuzz/issues/4813
3407
     */
3408
0
    if (!c->auto_zwnj || !c->auto_zwj)
3409
0
      goto slow;
3410
3411
0
    auto &skippy_iter = c->iter_input;
3412
0
    skippy_iter.reset (c->buffer->idx);
3413
0
    skippy_iter.set_match_func (match_always, nullptr);
3414
0
    skippy_iter.set_glyph_data ((HBUINT16 *) nullptr);
3415
0
    unsigned unsafe_to = (unsigned) -1, unsafe_to1 = 0, unsafe_to2 = 0;
3416
0
    hb_glyph_info_t *first = nullptr, *second = nullptr;
3417
0
    bool matched = skippy_iter.next ();
3418
0
    if (likely (matched))
3419
0
    {
3420
0
      first = &c->buffer->info[skippy_iter.idx];
3421
0
      unsafe_to1 = skippy_iter.idx + 1;
3422
3423
0
      if (skippy_iter.may_skip (c->buffer->info[skippy_iter.idx]))
3424
0
      {
3425
  /* Can't use the fast path if eg. the next char is a default-ignorable
3426
   * or other skippable. */
3427
0
        goto slow;
3428
0
      }
3429
0
    }
3430
0
    else
3431
0
    {
3432
      /* Failed to match a next glyph. Only try applying rules that have
3433
       * no further input and lookahead. */
3434
0
      return_trace (
3435
0
      + hb_iter (rule)
3436
0
      | hb_map (hb_add (this))
3437
0
      | hb_filter ([&] (const ChainRule &_)
3438
0
       {
3439
0
         const auto &input = StructAfter<decltype (_.inputX)> (_.backtrack);
3440
0
         const auto &lookahead = StructAfter<decltype (_.lookaheadX)> (input);
3441
0
         return input.lenP1 <= 1 && lookahead.len == 0;
3442
0
       })
3443
0
      | hb_map ([&] (const ChainRule &_) { return _.apply (c, lookup_context); })
3444
0
      | hb_any
3445
0
      )
3446
0
      ;
3447
0
    }
3448
0
    matched = skippy_iter.next ();
3449
0
    if (likely (matched && !skippy_iter.may_skip (c->buffer->info[skippy_iter.idx])))
3450
0
    {
3451
0
      second = &c->buffer->info[skippy_iter.idx];
3452
0
      unsafe_to2 = skippy_iter.idx + 1;
3453
0
    }
3454
3455
0
    auto match_input = lookup_context.funcs.match[1];
3456
0
    auto match_lookahead = lookup_context.funcs.match[2];
3457
0
    auto *input_data = lookup_context.match_data[1];
3458
0
    auto *lookahead_data = lookup_context.match_data[2];
3459
0
    for (unsigned int i = 0; i < num_rules; i++)
3460
0
    {
3461
0
      const auto &r = this+rule.arrayZ[i];
3462
3463
0
      const auto &input = StructAfter<decltype (r.inputX)> (r.backtrack);
3464
0
      const auto &lookahead = StructAfter<decltype (r.lookaheadX)> (input);
3465
3466
0
      unsigned lenP1 = hb_max ((unsigned) input.lenP1, 1u);
3467
0
      if (lenP1 > 1 ?
3468
0
     (!match_input ||
3469
0
      match_input (*first, input.arrayZ[0], input_data))
3470
0
    :
3471
0
     (!lookahead.len || !match_lookahead ||
3472
0
      match_lookahead (*first, lookahead.arrayZ[0], lookahead_data)))
3473
0
      {
3474
0
        if (!second ||
3475
0
      (lenP1 > 2 ?
3476
0
       (!match_input ||
3477
0
        match_input (*second, input.arrayZ[1], input_data))
3478
0
       :
3479
0
       (lookahead.len <= 2 - lenP1 || !match_lookahead ||
3480
0
        match_lookahead (*second, lookahead.arrayZ[2 - lenP1], lookahead_data))))
3481
0
  {
3482
0
    if (r.apply (c, lookup_context))
3483
0
    {
3484
0
      if (unsafe_to != (unsigned) -1)
3485
0
        c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to);
3486
0
      return_trace (true);
3487
0
    }
3488
0
  }
3489
0
  else
3490
0
    unsafe_to = unsafe_to2;
3491
0
      }
3492
0
      else
3493
0
      {
3494
0
  if (unsafe_to == (unsigned) -1)
3495
0
    unsafe_to = unsafe_to1;
3496
0
      }
3497
0
    }
3498
0
    if (likely (unsafe_to != (unsigned) -1))
3499
0
      c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to);
3500
3501
0
    return_trace (false);
3502
0
  }
3503
3504
  bool subset (hb_subset_context_t *c,
3505
         const hb_map_t *lookup_map,
3506
         const hb_map_t *backtrack_klass_map = nullptr,
3507
         const hb_map_t *input_klass_map = nullptr,
3508
         const hb_map_t *lookahead_klass_map = nullptr) const
3509
0
  {
3510
0
    TRACE_SUBSET (this);
3511
0
3512
0
    auto snap = c->serializer->snapshot ();
3513
0
    auto *out = c->serializer->start_embed (*this);
3514
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
3515
0
3516
0
    for (const Offset16To<ChainRule>& _ : rule)
3517
0
    {
3518
0
      if (!_) continue;
3519
0
      auto o_snap = c->serializer->snapshot ();
3520
0
      auto *o = out->rule.serialize_append (c->serializer);
3521
0
      if (unlikely (!o)) continue;
3522
0
3523
0
      if (!o->serialize_subset (c, _, this,
3524
0
        lookup_map,
3525
0
        backtrack_klass_map,
3526
0
        input_klass_map,
3527
0
        lookahead_klass_map))
3528
0
      {
3529
0
  out->rule.pop ();
3530
0
  c->serializer->revert (o_snap);
3531
0
      }
3532
0
    }
3533
0
3534
0
    bool ret = bool (out->rule);
3535
0
    if (!ret) c->serializer->revert (snap);
3536
0
3537
0
    return_trace (ret);
3538
0
  }
3539
3540
  bool sanitize (hb_sanitize_context_t *c) const
3541
125
  {
3542
125
    TRACE_SANITIZE (this);
3543
125
    return_trace (rule.sanitize (c, this));
3544
125
  }
3545
3546
  protected:
3547
  Array16OfOffset16To<ChainRule>
3548
    rule;     /* Array of ChainRule tables
3549
           * ordered by preference */
3550
  public:
3551
  DEFINE_SIZE_ARRAY (2, rule);
3552
};
3553
3554
template <typename Types>
3555
struct ChainContextFormat1_4
3556
{
3557
  using ChainRuleSet = OT::ChainRuleSet<Types>;
3558
3559
  bool intersects (const hb_set_t *glyphs) const
3560
0
  {
3561
0
    struct ChainContextClosureLookupContext lookup_context = {
3562
0
      {intersects_glyph, intersected_glyph},
3563
0
      ContextFormat::SimpleContext,
3564
0
      {nullptr, nullptr, nullptr}
3565
0
    };
3566
0
3567
0
    return
3568
0
    + hb_zip (this+coverage, ruleSet)
3569
0
    | hb_filter (*glyphs, hb_first)
3570
0
    | hb_map (hb_second)
3571
0
    | hb_map (hb_add (this))
3572
0
    | hb_map ([&] (const ChainRuleSet &_) { return _.intersects (glyphs, lookup_context); })
3573
0
    | hb_any
3574
0
    ;
3575
0
  }
3576
3577
  bool may_have_non_1to1 () const
3578
0
  { return true; }
3579
3580
  void closure (hb_closure_context_t *c) const
3581
0
  {
3582
0
    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
3583
0
    if (unlikely (!cur_active_glyphs)) return;
3584
0
    get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
3585
0
           *cur_active_glyphs);
3586
3587
0
    struct ChainContextClosureLookupContext lookup_context = {
3588
0
      {intersects_glyph, intersected_glyph},
3589
0
      ContextFormat::SimpleContext,
3590
0
      {nullptr, nullptr, nullptr}
3591
0
    };
3592
3593
0
    + hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len))
3594
0
    | hb_filter ([&] (hb_codepoint_t _) {
3595
0
      return c->previous_parent_active_glyphs ().has (_);
3596
0
    }, hb_first)
3597
0
    | hb_map ([&](const hb_pair_t<hb_codepoint_t, unsigned> _) { return hb_pair_t<unsigned, const ChainRuleSet&> (_.first, this+ruleSet[_.second]); })
3598
0
    | hb_apply ([&] (const hb_pair_t<unsigned, const ChainRuleSet&>& _) { _.second.closure (c, _.first, lookup_context); })
3599
0
    ;
3600
3601
0
    c->pop_cur_done_glyphs ();
3602
0
  }
3603
3604
  void closure_lookups (hb_closure_lookups_context_t *c) const
3605
0
  {
3606
0
    struct ChainContextClosureLookupContext lookup_context = {
3607
0
      {intersects_glyph, nullptr},
3608
0
      ContextFormat::SimpleContext,
3609
0
      {nullptr, nullptr, nullptr}
3610
0
    };
3611
0
3612
0
    + hb_zip (this+coverage, ruleSet)
3613
0
    | hb_filter (*c->glyphs, hb_first)
3614
0
    | hb_map (hb_second)
3615
0
    | hb_map (hb_add (this))
3616
0
    | hb_apply ([&] (const ChainRuleSet &_) { _.closure_lookups (c, lookup_context); })
3617
0
    ;
3618
0
  }
3619
3620
0
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
3621
3622
  void collect_glyphs (hb_collect_glyphs_context_t *c) const
3623
0
  {
3624
0
    (this+coverage).collect_coverage (c->input);
3625
3626
0
    struct ChainContextCollectGlyphsLookupContext lookup_context = {
3627
0
      {collect_glyph},
3628
0
      {nullptr, nullptr, nullptr}
3629
0
    };
3630
3631
0
    + hb_iter (ruleSet)
3632
0
    | hb_map (hb_add (this))
3633
0
    | hb_apply ([&] (const ChainRuleSet &_) { _.collect_glyphs (c, lookup_context); })
3634
0
    ;
3635
0
  }
3636
3637
  bool would_apply (hb_would_apply_context_t *c) const
3638
0
  {
3639
0
    const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
3640
0
    struct ChainContextApplyLookupContext lookup_context = {
3641
0
      {{match_glyph, match_glyph, match_glyph}},
3642
0
      {nullptr, nullptr, nullptr}
3643
0
    };
3644
0
    return rule_set.would_apply (c, lookup_context);
3645
0
  }
3646
3647
0
  const Coverage &get_coverage () const { return this+coverage; }
3648
3649
  bool apply (hb_ot_apply_context_t *c) const
3650
0
  {
3651
0
    TRACE_APPLY (this);
3652
0
    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
3653
0
    if (index == NOT_COVERED) return_trace (false);
3654
3655
0
    const ChainRuleSet &rule_set = this+ruleSet[index];
3656
0
    struct ChainContextApplyLookupContext lookup_context = {
3657
0
      {{match_glyph, match_glyph, match_glyph}},
3658
0
      {nullptr, nullptr, nullptr}
3659
0
    };
3660
0
    return_trace (rule_set.apply (c, lookup_context));
3661
0
  }
3662
3663
  bool subset (hb_subset_context_t *c) const
3664
0
  {
3665
0
    TRACE_SUBSET (this);
3666
0
    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
3667
0
    const hb_map_t &glyph_map = *c->plan->glyph_map;
3668
0
3669
0
    auto *out = c->serializer->start_embed (*this);
3670
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
3671
0
    out->format = format;
3672
0
3673
0
    const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? &c->plan->gsub_lookups : &c->plan->gpos_lookups;
3674
0
    hb_sorted_vector_t<hb_codepoint_t> new_coverage;
3675
0
    + hb_zip (this+coverage, ruleSet)
3676
0
    | hb_filter (glyphset, hb_first)
3677
0
    | hb_filter (subset_offset_array (c, out->ruleSet, this, lookup_map), hb_second)
3678
0
    | hb_map (hb_first)
3679
0
    | hb_map (glyph_map)
3680
0
    | hb_sink (new_coverage)
3681
0
    ;
3682
0
3683
0
    out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
3684
0
    return_trace (bool (new_coverage));
3685
0
  }
3686
3687
  bool sanitize (hb_sanitize_context_t *c) const
3688
0
  {
3689
0
    TRACE_SANITIZE (this);
3690
0
    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
3691
0
  }
3692
3693
  protected:
3694
  HBUINT16  format;     /* Format identifier--format = 1 */
3695
  typename Types::template OffsetTo<Coverage>
3696
    coverage;   /* Offset to Coverage table--from
3697
           * beginning of table */
3698
  Array16Of<typename Types::template OffsetTo<ChainRuleSet>>
3699
    ruleSet;    /* Array of ChainRuleSet tables
3700
           * ordered by Coverage Index */
3701
  public:
3702
  DEFINE_SIZE_ARRAY (2 + 2 * Types::size, ruleSet);
3703
};
3704
3705
template <typename Types>
3706
struct ChainContextFormat2_5
3707
{
3708
  using ChainRuleSet = OT::ChainRuleSet<SmallTypes>;
3709
3710
  bool intersects (const hb_set_t *glyphs) const
3711
0
  {
3712
0
    if (!(this+coverage).intersects (glyphs))
3713
0
      return false;
3714
0
3715
0
    const ClassDef &backtrack_class_def = this+backtrackClassDef;
3716
0
    const ClassDef &input_class_def = this+inputClassDef;
3717
0
    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
3718
0
3719
0
    hb_map_t caches[3] = {};
3720
0
    struct ChainContextClosureLookupContext lookup_context = {
3721
0
      {intersects_class, nullptr},
3722
0
      ContextFormat::ClassBasedContext,
3723
0
      {&backtrack_class_def,
3724
0
       &input_class_def,
3725
0
       &lookahead_class_def},
3726
0
      {&caches[0], &caches[1], &caches[2]}
3727
0
    };
3728
0
3729
0
    hb_set_t retained_coverage_glyphs;
3730
0
    (this+coverage).intersect_set (*glyphs, retained_coverage_glyphs);
3731
0
3732
0
    hb_set_t coverage_glyph_classes;
3733
0
    input_class_def.intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
3734
0
3735
0
    return
3736
0
    + hb_iter (ruleSet)
3737
0
    | hb_map (hb_add (this))
3738
0
    | hb_enumerate
3739
0
    | hb_map ([&] (const hb_pair_t<unsigned, const ChainRuleSet &> p)
3740
0
        { return input_class_def.intersects_class (glyphs, p.first) &&
3741
0
           coverage_glyph_classes.has (p.first) &&
3742
0
           p.second.intersects (glyphs, lookup_context); })
3743
0
    | hb_any
3744
0
    ;
3745
0
  }
3746
3747
  bool may_have_non_1to1 () const
3748
0
  { return true; }
3749
3750
  void closure (hb_closure_context_t *c) const
3751
0
  {
3752
0
    if (!(this+coverage).intersects (c->glyphs))
3753
0
      return;
3754
3755
0
    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
3756
0
    if (unlikely (!cur_active_glyphs)) return;
3757
0
    get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
3758
0
           *cur_active_glyphs);
3759
3760
0
    const ClassDef &backtrack_class_def = this+backtrackClassDef;
3761
0
    const ClassDef &input_class_def = this+inputClassDef;
3762
0
    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
3763
3764
0
    hb_map_t caches[3] = {};
3765
0
    intersected_class_cache_t intersected_cache;
3766
0
    struct ChainContextClosureLookupContext lookup_context = {
3767
0
      {intersects_class, intersected_class_glyphs},
3768
0
      ContextFormat::ClassBasedContext,
3769
0
      {&backtrack_class_def,
3770
0
       &input_class_def,
3771
0
       &lookahead_class_def},
3772
0
      {&caches[0], &caches[1], &caches[2]},
3773
0
      &intersected_cache
3774
0
    };
3775
3776
0
    + hb_enumerate (ruleSet)
3777
0
    | hb_filter ([&] (unsigned _)
3778
0
    { return input_class_def.intersects_class (&c->parent_active_glyphs (), _); },
3779
0
     hb_first)
3780
0
    | hb_apply ([&] (const hb_pair_t<unsigned, const typename Types::template OffsetTo<ChainRuleSet>&> _)
3781
0
                {
3782
0
                  const ChainRuleSet& chainrule_set = this+_.second;
3783
0
                  chainrule_set.closure (c, _.first, lookup_context);
3784
0
                })
3785
0
    ;
3786
3787
0
    c->pop_cur_done_glyphs ();
3788
0
  }
3789
3790
  void closure_lookups (hb_closure_lookups_context_t *c) const
3791
0
  {
3792
0
    if (!(this+coverage).intersects (c->glyphs))
3793
0
      return;
3794
0
3795
0
    const ClassDef &backtrack_class_def = this+backtrackClassDef;
3796
0
    const ClassDef &input_class_def = this+inputClassDef;
3797
0
    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
3798
0
3799
0
    hb_map_t caches[3] = {};
3800
0
    struct ChainContextClosureLookupContext lookup_context = {
3801
0
      {intersects_class, nullptr},
3802
0
      ContextFormat::ClassBasedContext,
3803
0
      {&backtrack_class_def,
3804
0
       &input_class_def,
3805
0
       &lookahead_class_def},
3806
0
      {&caches[0], &caches[1], &caches[2]}
3807
0
    };
3808
0
3809
0
    + hb_iter (ruleSet)
3810
0
    | hb_map (hb_add (this))
3811
0
    | hb_enumerate
3812
0
    | hb_filter([&] (unsigned klass)
3813
0
    { return input_class_def.intersects_class (c->glyphs, klass); }, hb_first)
3814
0
    | hb_map (hb_second)
3815
0
    | hb_apply ([&] (const ChainRuleSet &_)
3816
0
    { _.closure_lookups (c, lookup_context); })
3817
0
    ;
3818
0
  }
3819
3820
0
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
3821
3822
  void collect_glyphs (hb_collect_glyphs_context_t *c) const
3823
0
  {
3824
0
    (this+coverage).collect_coverage (c->input);
3825
3826
0
    const ClassDef &backtrack_class_def = this+backtrackClassDef;
3827
0
    const ClassDef &input_class_def = this+inputClassDef;
3828
0
    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
3829
3830
0
    struct ChainContextCollectGlyphsLookupContext lookup_context = {
3831
0
      {collect_class},
3832
0
      {&backtrack_class_def,
3833
0
       &input_class_def,
3834
0
       &lookahead_class_def}
3835
0
    };
3836
3837
0
    + hb_iter (ruleSet)
3838
0
    | hb_map (hb_add (this))
3839
0
    | hb_apply ([&] (const ChainRuleSet &_) { _.collect_glyphs (c, lookup_context); })
3840
0
    ;
3841
0
  }
3842
3843
  bool would_apply (hb_would_apply_context_t *c) const
3844
0
  {
3845
0
    const ClassDef &backtrack_class_def = this+backtrackClassDef;
3846
0
    const ClassDef &input_class_def = this+inputClassDef;
3847
0
    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
3848
3849
0
    unsigned int index = input_class_def.get_class (c->glyphs[0]);
3850
0
    const ChainRuleSet &rule_set = this+ruleSet[index];
3851
0
    struct ChainContextApplyLookupContext lookup_context = {
3852
0
      {{match_class, match_class, match_class}},
3853
0
      {&backtrack_class_def,
3854
0
       &input_class_def,
3855
0
       &lookahead_class_def}
3856
0
    };
3857
0
    return rule_set.would_apply (c, lookup_context);
3858
0
  }
3859
3860
64
  const Coverage &get_coverage () const { return this+coverage; }
3861
3862
  unsigned cache_cost () const
3863
64
  {
3864
64
    return (this+inputClassDef).cost () + (this+lookaheadClassDef).cost ();
3865
64
  }
3866
  static bool cache_func (hb_ot_apply_context_t *c, hb_ot_subtable_cache_op_t op)
3867
0
  {
3868
0
    return context_cache_func (c, op);
3869
0
  }
3870
3871
0
  bool apply_cached (hb_ot_apply_context_t *c, void *external_cache HB_UNUSED) const { return _apply (c, true); }
3872
0
  bool apply (hb_ot_apply_context_t *c) const { return _apply (c, false); }
3873
  bool _apply (hb_ot_apply_context_t *c, bool cached) const
3874
0
  {
3875
0
    TRACE_APPLY (this);
3876
0
    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
3877
0
    if (index == NOT_COVERED) return_trace (false);
3878
3879
0
    const ClassDef &backtrack_class_def = this+backtrackClassDef;
3880
0
    const ClassDef &input_class_def = this+inputClassDef;
3881
0
    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
3882
3883
    /* match_class_caches1 is slightly faster. Use it for lookahead,
3884
     * which is typically longer. */
3885
0
    struct ChainContextApplyLookupContext lookup_context = {
3886
0
      {{cached && &backtrack_class_def == &lookahead_class_def ? match_class_cached1 : match_class,
3887
0
        cached ? match_class_cached2 : match_class,
3888
0
        cached ? match_class_cached1 : match_class}},
3889
0
      {&backtrack_class_def,
3890
0
       &input_class_def,
3891
0
       &lookahead_class_def}
3892
0
    };
3893
3894
0
    index = cached
3895
0
         ? get_class_cached2 (input_class_def, c->buffer->cur())
3896
0
          : input_class_def.get_class (c->buffer->cur().codepoint);
3897
0
    const ChainRuleSet &rule_set = this+ruleSet[index];
3898
0
    return_trace (rule_set.apply (c, lookup_context));
3899
0
  }
3900
3901
  bool subset (hb_subset_context_t *c) const
3902
0
  {
3903
0
    TRACE_SUBSET (this);
3904
0
    auto *out = c->serializer->start_embed (*this);
3905
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
3906
0
    out->format = format;
3907
0
    out->coverage.serialize_subset (c, coverage, this);
3908
0
3909
0
    hb_map_t backtrack_klass_map;
3910
0
    hb_map_t input_klass_map;
3911
0
    hb_map_t lookahead_klass_map;
3912
0
3913
0
    out->backtrackClassDef.serialize_subset (c, backtrackClassDef, this, &backtrack_klass_map);
3914
0
    // TODO: subset inputClassDef based on glyphs survived in Coverage subsetting
3915
0
    out->inputClassDef.serialize_subset (c, inputClassDef, this, &input_klass_map);
3916
0
    out->lookaheadClassDef.serialize_subset (c, lookaheadClassDef, this, &lookahead_klass_map);
3917
0
3918
0
    if (unlikely (!c->serializer->propagate_error (backtrack_klass_map,
3919
0
               input_klass_map,
3920
0
               lookahead_klass_map)))
3921
0
      return_trace (false);
3922
0
3923
0
    const hb_set_t* glyphset = c->plan->glyphset_gsub ();
3924
0
    hb_set_t retained_coverage_glyphs;
3925
0
    (this+coverage).intersect_set (*glyphset, retained_coverage_glyphs);
3926
0
3927
0
    hb_set_t coverage_glyph_classes;
3928
0
    (this+inputClassDef).intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
3929
0
3930
0
    int non_zero_index = -1, index = 0;
3931
0
    bool ret = true;
3932
0
    const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? &c->plan->gsub_lookups : &c->plan->gpos_lookups;
3933
0
    auto last_non_zero = c->serializer->snapshot ();
3934
0
    for (const auto& _ : + hb_enumerate (ruleSet)
3935
0
       | hb_filter (input_klass_map, hb_first))
3936
0
    {
3937
0
      auto *o = out->ruleSet.serialize_append (c->serializer);
3938
0
      if (unlikely (!o))
3939
0
      {
3940
0
  ret = false;
3941
0
  break;
3942
0
      }
3943
0
      if (coverage_glyph_classes.has (_.first) &&
3944
0
          o->serialize_subset (c, _.second, this,
3945
0
             lookup_map,
3946
0
             &backtrack_klass_map,
3947
0
             &input_klass_map,
3948
0
             &lookahead_klass_map))
3949
0
      {
3950
0
        last_non_zero = c->serializer->snapshot ();
3951
0
  non_zero_index = index;
3952
0
      }
3953
0
3954
0
      index++;
3955
0
    }
3956
0
3957
0
    if (!ret || non_zero_index == -1) return_trace (false);
3958
0
3959
0
    // prune empty trailing ruleSets
3960
0
    if (index > non_zero_index) {
3961
0
      c->serializer->revert (last_non_zero);
3962
0
      out->ruleSet.len = non_zero_index + 1;
3963
0
    }
3964
0
3965
0
    return_trace (bool (out->ruleSet));
3966
0
  }
3967
3968
  bool sanitize (hb_sanitize_context_t *c) const
3969
80
  {
3970
80
    TRACE_SANITIZE (this);
3971
80
    return_trace (coverage.sanitize (c, this) &&
3972
80
      backtrackClassDef.sanitize (c, this) &&
3973
80
      inputClassDef.sanitize (c, this) &&
3974
80
      lookaheadClassDef.sanitize (c, this) &&
3975
80
      ruleSet.sanitize (c, this));
3976
80
  }
3977
3978
  protected:
3979
  HBUINT16  format;     /* Format identifier--format = 2 */
3980
  typename Types::template OffsetTo<Coverage>
3981
    coverage;   /* Offset to Coverage table--from
3982
           * beginning of table */
3983
  typename Types::template OffsetTo<ClassDef>
3984
    backtrackClassDef;  /* Offset to glyph ClassDef table
3985
           * containing backtrack sequence
3986
           * data--from beginning of table */
3987
  typename Types::template OffsetTo<ClassDef>
3988
    inputClassDef;    /* Offset to glyph ClassDef
3989
           * table containing input sequence
3990
           * data--from beginning of table */
3991
  typename Types::template OffsetTo<ClassDef>
3992
    lookaheadClassDef;  /* Offset to glyph ClassDef table
3993
           * containing lookahead sequence
3994
           * data--from beginning of table */
3995
  Array16Of<typename Types::template OffsetTo<ChainRuleSet>>
3996
    ruleSet;    /* Array of ChainRuleSet tables
3997
           * ordered by class */
3998
  public:
3999
  DEFINE_SIZE_ARRAY (4 + 4 * Types::size, ruleSet);
4000
};
4001
4002
struct ChainContextFormat3
4003
{
4004
  using RuleSet = OT::RuleSet<SmallTypes>;
4005
4006
  bool intersects (const hb_set_t *glyphs) const
4007
0
  {
4008
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4009
0
4010
0
    if (!(this+input[0]).intersects (glyphs))
4011
0
      return false;
4012
0
4013
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4014
0
    struct ChainContextClosureLookupContext lookup_context = {
4015
0
      {intersects_coverage, nullptr},
4016
0
      ContextFormat::CoverageBasedContext,
4017
0
      {this, this, this}
4018
0
    };
4019
0
    return chain_context_intersects (glyphs,
4020
0
             backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
4021
0
             input.len, (const HBUINT16 *) input.arrayZ + 1,
4022
0
             lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
4023
0
             lookup_context);
4024
0
  }
4025
4026
  bool may_have_non_1to1 () const
4027
0
  { return true; }
4028
4029
  void closure (hb_closure_context_t *c) const
4030
0
  {
4031
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4032
4033
0
    if (!(this+input[0]).intersects (c->glyphs))
4034
0
      return;
4035
4036
0
    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
4037
0
    if (unlikely (!cur_active_glyphs))
4038
0
      return;
4039
0
    get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
4040
0
           *cur_active_glyphs);
4041
4042
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4043
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
4044
0
    struct ChainContextClosureLookupContext lookup_context = {
4045
0
      {intersects_coverage, intersected_coverage_glyphs},
4046
0
      ContextFormat::CoverageBasedContext,
4047
0
      {this, this, this}
4048
0
    };
4049
0
    chain_context_closure_lookup (c,
4050
0
          backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
4051
0
          input.len, (const HBUINT16 *) input.arrayZ + 1,
4052
0
          lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
4053
0
          lookup.len, lookup.arrayZ,
4054
0
          0, lookup_context);
4055
4056
0
    c->pop_cur_done_glyphs ();
4057
0
  }
4058
4059
  void closure_lookups (hb_closure_lookups_context_t *c) const
4060
0
  {
4061
0
    if (!intersects (c->glyphs))
4062
0
      return;
4063
0
4064
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4065
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4066
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
4067
0
    recurse_lookups (c, lookup.len, lookup.arrayZ);
4068
0
  }
4069
4070
0
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
4071
4072
  void collect_glyphs (hb_collect_glyphs_context_t *c) const
4073
0
  {
4074
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4075
4076
0
    (this+input[0]).collect_coverage (c->input);
4077
4078
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4079
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
4080
4081
0
    struct ChainContextCollectGlyphsLookupContext lookup_context = {
4082
0
      {collect_coverage},
4083
0
      {this, this, this}
4084
0
    };
4085
0
    chain_context_collect_glyphs_lookup (c,
4086
0
           backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
4087
0
           input.len, (const HBUINT16 *) input.arrayZ + 1,
4088
0
           lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
4089
0
           lookup.len, lookup.arrayZ,
4090
0
           lookup_context);
4091
0
  }
4092
4093
  bool would_apply (hb_would_apply_context_t *c) const
4094
0
  {
4095
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4096
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4097
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
4098
0
    struct ChainContextApplyLookupContext lookup_context = {
4099
0
      {{match_coverage, match_coverage, match_coverage}},
4100
0
      {this, this, this}
4101
0
    };
4102
0
    return chain_context_would_apply_lookup (c,
4103
0
               backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
4104
0
               input.len, (const HBUINT16 *) input.arrayZ + 1,
4105
0
               lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
4106
0
               lookup.len, lookup.arrayZ, lookup_context);
4107
0
  }
4108
4109
  const Coverage &get_coverage () const
4110
0
  {
4111
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4112
0
    return this+input[0];
4113
0
  }
4114
4115
  bool apply (hb_ot_apply_context_t *c) const
4116
0
  {
4117
0
    TRACE_APPLY (this);
4118
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4119
4120
0
    unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
4121
0
    if (index == NOT_COVERED) return_trace (false);
4122
4123
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4124
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
4125
0
    struct ChainContextApplyLookupContext lookup_context = {
4126
0
      {{match_coverage, match_coverage, match_coverage}},
4127
0
      {this, this, this}
4128
0
    };
4129
0
    return_trace (chain_context_apply_lookup (c,
4130
0
                backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
4131
0
                input.len, (const HBUINT16 *) input.arrayZ + 1,
4132
0
                lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
4133
0
                lookup.len, lookup.arrayZ, lookup_context));
4134
0
  }
4135
4136
  template<typename Iterator,
4137
     hb_requires (hb_is_iterator (Iterator))>
4138
  bool serialize_coverage_offsets (hb_subset_context_t *c, Iterator it, const void* base) const
4139
0
  {
4140
0
    TRACE_SERIALIZE (this);
4141
0
    auto *out = c->serializer->start_embed<Array16OfOffset16To<Coverage>> ();
4142
0
4143
0
    if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size)))
4144
0
      return_trace (false);
4145
0
4146
0
    for (auto& offset : it) {
4147
0
      auto *o = out->serialize_append (c->serializer);
4148
0
      if (unlikely (!o) || !o->serialize_subset (c, offset, base))
4149
0
        return_trace (false);
4150
0
    }
4151
0
4152
0
    return_trace (true);
4153
0
  }
4154
4155
  bool subset (hb_subset_context_t *c) const
4156
0
  {
4157
0
    TRACE_SUBSET (this);
4158
0
4159
0
    if (unlikely (!c->serializer->embed (this->format))) return_trace (false);
4160
0
4161
0
    if (!serialize_coverage_offsets (c, backtrack.iter (), this))
4162
0
      return_trace (false);
4163
0
4164
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4165
0
    if (!serialize_coverage_offsets (c, input.iter (), this))
4166
0
      return_trace (false);
4167
0
4168
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4169
0
    if (!serialize_coverage_offsets (c, lookahead.iter (), this))
4170
0
      return_trace (false);
4171
0
4172
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
4173
0
    const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? &c->plan->gsub_lookups : &c->plan->gpos_lookups;
4174
0
4175
0
    HBUINT16 *lookupCount = c->serializer->copy<HBUINT16> (lookup.len);
4176
0
    if (!lookupCount) return_trace (false);
4177
0
4178
0
    unsigned count = serialize_lookuprecord_array (c->serializer, lookup.as_array (), lookup_map);
4179
0
    return_trace (c->serializer->check_assign (*lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
4180
0
  }
4181
4182
  bool sanitize (hb_sanitize_context_t *c) const
4183
0
  {
4184
0
    TRACE_SANITIZE (this);
4185
0
    if (unlikely (!backtrack.sanitize (c, this))) return_trace (false);
4186
0
    hb_barrier ();
4187
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4188
0
    if (unlikely (!input.sanitize (c, this))) return_trace (false);
4189
0
    hb_barrier ();
4190
0
    if (unlikely (!input.len)) return_trace (false); /* To be consistent with Context. */
4191
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4192
0
    if (unlikely (!lookahead.sanitize (c, this))) return_trace (false);
4193
0
    hb_barrier ();
4194
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
4195
0
    return_trace (likely (lookup.sanitize (c)));
4196
0
  }
4197
4198
  protected:
4199
  HBUINT16  format;     /* Format identifier--format = 3 */
4200
  Array16OfOffset16To<Coverage>
4201
    backtrack;    /* Array of coverage tables
4202
           * in backtracking sequence, in  glyph
4203
           * sequence order */
4204
  Array16OfOffset16To<Coverage>
4205
    inputX    ; /* Array of coverage
4206
           * tables in input sequence, in glyph
4207
           * sequence order */
4208
  Array16OfOffset16To<Coverage>
4209
    lookaheadX;   /* Array of coverage tables
4210
           * in lookahead sequence, in glyph
4211
           * sequence order */
4212
  Array16Of<LookupRecord>
4213
    lookupX;    /* Array of LookupRecords--in
4214
           * design order) */
4215
  public:
4216
  DEFINE_SIZE_MIN (10);
4217
};
4218
4219
struct ChainContext
4220
{
4221
  template <typename context_t, typename ...Ts>
4222
  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
4223
144
  {
4224
144
    if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
4225
144
    TRACE_DISPATCH (this, u.format);
4226
144
    switch (u.format) {
4227
0
    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
4228
144
    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
4229
0
    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
4230
#ifndef HB_NO_BEYOND_64K
4231
    case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
4232
    case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
4233
#endif
4234
0
    default:return_trace (c->default_return_value ());
4235
144
    }
4236
144
  }
Unexecuted instantiation: OT::hb_intersects_context_t::return_t OT::ChainContext::dispatch<OT::hb_intersects_context_t>(OT::hb_intersects_context_t*) const
Unexecuted instantiation: OT::hb_ot_apply_context_t::return_t OT::ChainContext::dispatch<OT::hb_ot_apply_context_t>(OT::hb_ot_apply_context_t*) const
Unexecuted instantiation: OT::hb_collect_glyphs_context_t::return_t OT::ChainContext::dispatch<OT::hb_collect_glyphs_context_t>(OT::hb_collect_glyphs_context_t*) const
Unexecuted instantiation: OT::hb_closure_lookups_context_t::return_t OT::ChainContext::dispatch<OT::hb_closure_lookups_context_t>(OT::hb_closure_lookups_context_t*) const
Unexecuted instantiation: hb_subset_context_t::return_t OT::ChainContext::dispatch<hb_subset_context_t>(hb_subset_context_t*) const
hb_sanitize_context_t::return_t OT::ChainContext::dispatch<hb_sanitize_context_t>(hb_sanitize_context_t*) const
Line
Count
Source
4223
80
  {
4224
80
    if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
4225
80
    TRACE_DISPATCH (this, u.format);
4226
80
    switch (u.format) {
4227
0
    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
4228
80
    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
4229
0
    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
4230
#ifndef HB_NO_BEYOND_64K
4231
    case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
4232
    case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
4233
#endif
4234
0
    default:return_trace (c->default_return_value ());
4235
80
    }
4236
80
  }
Unexecuted instantiation: OT::hb_collect_variation_indices_context_t::return_t OT::ChainContext::dispatch<OT::hb_collect_variation_indices_context_t>(OT::hb_collect_variation_indices_context_t*) const
OT::hb_accelerate_subtables_context_t::return_t OT::ChainContext::dispatch<OT::hb_accelerate_subtables_context_t>(OT::hb_accelerate_subtables_context_t*) const
Line
Count
Source
4223
64
  {
4224
64
    if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
4225
64
    TRACE_DISPATCH (this, u.format);
4226
64
    switch (u.format) {
4227
0
    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
4228
64
    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
4229
0
    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
4230
#ifndef HB_NO_BEYOND_64K
4231
    case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
4232
    case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
4233
#endif
4234
0
    default:return_trace (c->default_return_value ());
4235
64
    }
4236
64
  }
Unexecuted instantiation: OT::hb_have_non_1to1_context_t::return_t OT::ChainContext::dispatch<OT::hb_have_non_1to1_context_t>(OT::hb_have_non_1to1_context_t*) const
Unexecuted instantiation: OT::hb_closure_context_t::return_t OT::ChainContext::dispatch<OT::hb_closure_context_t>(OT::hb_closure_context_t*) const
Unexecuted instantiation: OT::hb_would_apply_context_t::return_t OT::ChainContext::dispatch<OT::hb_would_apply_context_t>(OT::hb_would_apply_context_t*) const
Unexecuted instantiation: hb_get_glyph_alternates_dispatch_t::return_t OT::ChainContext::dispatch<hb_get_glyph_alternates_dispatch_t, unsigned int&, unsigned int&, unsigned int*&, unsigned int*&>(hb_get_glyph_alternates_dispatch_t*, unsigned int&, unsigned int&, unsigned int*&, unsigned int*&) const
Unexecuted instantiation: hb_position_single_dispatch_t::return_t OT::ChainContext::dispatch<hb_position_single_dispatch_t, hb_font_t*&, hb_blob_t*&, hb_direction_t&, unsigned int&, hb_glyph_position_t&>(hb_position_single_dispatch_t*, hb_font_t*&, hb_blob_t*&, hb_direction_t&, unsigned int&, hb_glyph_position_t&) const
4237
4238
  protected:
4239
  union {
4240
  HBUINT16        format; /* Format identifier */
4241
  ChainContextFormat1_4<SmallTypes> format1;
4242
  ChainContextFormat2_5<SmallTypes> format2;
4243
  ChainContextFormat3     format3;
4244
#ifndef HB_NO_BEYOND_64K
4245
  ChainContextFormat1_4<MediumTypes>  format4;
4246
  ChainContextFormat2_5<MediumTypes>  format5;
4247
#endif
4248
  } u;
4249
};
4250
4251
4252
template <typename T>
4253
struct ExtensionFormat1
4254
{
4255
0
  unsigned int get_type () const { return extensionLookupType; }
Unexecuted instantiation: OT::ExtensionFormat1<OT::Layout::GPOS_impl::ExtensionPos>::get_type() const
Unexecuted instantiation: OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::get_type() const
4256
4257
  template <typename X>
4258
  const X& get_subtable () const
4259
0
  { return this + reinterpret_cast<const Offset32To<typename T::SubTable> &> (extensionOffset); }
Unexecuted instantiation: OT::Layout::GPOS_impl::PosLookupSubTable const& OT::ExtensionFormat1<OT::Layout::GPOS_impl::ExtensionPos>::get_subtable<OT::Layout::GPOS_impl::PosLookupSubTable>() const
Unexecuted instantiation: OT::Layout::GSUB_impl::SubstLookupSubTable const& OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::get_subtable<OT::Layout::GSUB_impl::SubstLookupSubTable>() const
4260
4261
  template <typename context_t, typename ...Ts>
4262
  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
4263
0
  {
4264
0
    if (unlikely (!c->may_dispatch (this, this))) return c->no_dispatch_return_value ();
4265
0
    TRACE_DISPATCH (this, format);
4266
0
    return_trace (get_subtable<typename T::SubTable> ().dispatch (c, get_type (), std::forward<Ts> (ds)...));
4267
0
  }
Unexecuted instantiation: OT::hb_intersects_context_t::return_t OT::ExtensionFormat1<OT::Layout::GPOS_impl::ExtensionPos>::dispatch<OT::hb_intersects_context_t>(OT::hb_intersects_context_t*) const
Unexecuted instantiation: OT::hb_ot_apply_context_t::return_t OT::ExtensionFormat1<OT::Layout::GPOS_impl::ExtensionPos>::dispatch<OT::hb_ot_apply_context_t>(OT::hb_ot_apply_context_t*) const
Unexecuted instantiation: OT::hb_collect_glyphs_context_t::return_t OT::ExtensionFormat1<OT::Layout::GPOS_impl::ExtensionPos>::dispatch<OT::hb_collect_glyphs_context_t>(OT::hb_collect_glyphs_context_t*) const
Unexecuted instantiation: OT::hb_closure_lookups_context_t::return_t OT::ExtensionFormat1<OT::Layout::GPOS_impl::ExtensionPos>::dispatch<OT::hb_closure_lookups_context_t>(OT::hb_closure_lookups_context_t*) const
Unexecuted instantiation: hb_sanitize_context_t::return_t OT::ExtensionFormat1<OT::Layout::GPOS_impl::ExtensionPos>::dispatch<hb_sanitize_context_t>(hb_sanitize_context_t*) const
Unexecuted instantiation: OT::hb_collect_variation_indices_context_t::return_t OT::ExtensionFormat1<OT::Layout::GPOS_impl::ExtensionPos>::dispatch<OT::hb_collect_variation_indices_context_t>(OT::hb_collect_variation_indices_context_t*) const
Unexecuted instantiation: OT::hb_accelerate_subtables_context_t::return_t OT::ExtensionFormat1<OT::Layout::GPOS_impl::ExtensionPos>::dispatch<OT::hb_accelerate_subtables_context_t>(OT::hb_accelerate_subtables_context_t*) const
Unexecuted instantiation: OT::hb_intersects_context_t::return_t OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<OT::hb_intersects_context_t>(OT::hb_intersects_context_t*) const
Unexecuted instantiation: hb_sanitize_context_t::return_t OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<hb_sanitize_context_t>(hb_sanitize_context_t*) const
Unexecuted instantiation: OT::hb_have_non_1to1_context_t::return_t OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<OT::hb_have_non_1to1_context_t>(OT::hb_have_non_1to1_context_t*) const
Unexecuted instantiation: OT::hb_ot_apply_context_t::return_t OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<OT::hb_ot_apply_context_t>(OT::hb_ot_apply_context_t*) const
Unexecuted instantiation: OT::hb_closure_context_t::return_t OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<OT::hb_closure_context_t>(OT::hb_closure_context_t*) const
Unexecuted instantiation: OT::hb_closure_lookups_context_t::return_t OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<OT::hb_closure_lookups_context_t>(OT::hb_closure_lookups_context_t*) const
Unexecuted instantiation: OT::hb_collect_glyphs_context_t::return_t OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<OT::hb_collect_glyphs_context_t>(OT::hb_collect_glyphs_context_t*) const
Unexecuted instantiation: OT::hb_would_apply_context_t::return_t OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<OT::hb_would_apply_context_t>(OT::hb_would_apply_context_t*) const
Unexecuted instantiation: OT::hb_accelerate_subtables_context_t::return_t OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<OT::hb_accelerate_subtables_context_t>(OT::hb_accelerate_subtables_context_t*) const
Unexecuted instantiation: hb_get_glyph_alternates_dispatch_t::return_t OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<hb_get_glyph_alternates_dispatch_t, unsigned int&, unsigned int&, unsigned int*&, unsigned int*&>(hb_get_glyph_alternates_dispatch_t*, unsigned int&, unsigned int&, unsigned int*&, unsigned int*&) const
Unexecuted instantiation: hb_position_single_dispatch_t::return_t OT::ExtensionFormat1<OT::Layout::GPOS_impl::ExtensionPos>::dispatch<hb_position_single_dispatch_t, hb_font_t*&, hb_blob_t*&, hb_direction_t&, unsigned int&, hb_glyph_position_t&>(hb_position_single_dispatch_t*, hb_font_t*&, hb_blob_t*&, hb_direction_t&, unsigned int&, hb_glyph_position_t&) const
4268
4269
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
4270
  { dispatch (c); }
4271
4272
  /* This is called from may_dispatch() above with hb_sanitize_context_t. */
4273
  bool sanitize (hb_sanitize_context_t *c) const
4274
0
  {
4275
0
    TRACE_SANITIZE (this);
4276
0
    return_trace (c->check_struct (this) &&
4277
0
      hb_barrier () &&
4278
0
      extensionLookupType != T::SubTable::Extension);
4279
0
  }
Unexecuted instantiation: OT::ExtensionFormat1<OT::Layout::GPOS_impl::ExtensionPos>::sanitize(hb_sanitize_context_t*) const
Unexecuted instantiation: OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::sanitize(hb_sanitize_context_t*) const
4280
4281
  bool subset (hb_subset_context_t *c) const
4282
0
  {
4283
0
    TRACE_SUBSET (this);
4284
0
4285
0
    auto *out = c->serializer->start_embed (this);
4286
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
4287
0
4288
0
    out->format = format;
4289
0
    out->extensionLookupType = extensionLookupType;
4290
0
4291
0
    const auto& src_offset =
4292
0
        reinterpret_cast<const Offset32To<typename T::SubTable> &> (extensionOffset);
4293
0
    auto& dest_offset =
4294
0
        reinterpret_cast<Offset32To<typename T::SubTable> &> (out->extensionOffset);
4295
0
4296
0
    return_trace (dest_offset.serialize_subset (c, src_offset, this, get_type ()));
4297
0
  }
Unexecuted instantiation: OT::ExtensionFormat1<OT::Layout::GPOS_impl::ExtensionPos>::subset(hb_subset_context_t*) const
Unexecuted instantiation: OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::subset(hb_subset_context_t*) const
4298
4299
  protected:
4300
  HBUINT16  format;     /* Format identifier. Set to 1. */
4301
  HBUINT16  extensionLookupType;  /* Lookup type of subtable referenced
4302
           * by ExtensionOffset (i.e. the
4303
           * extension subtable). */
4304
  Offset32  extensionOffset;  /* Offset to the extension subtable,
4305
           * of lookup type subtable. */
4306
  public:
4307
  DEFINE_SIZE_STATIC (8);
4308
};
4309
4310
template <typename T>
4311
struct Extension
4312
{
4313
  unsigned int get_type () const
4314
0
  {
4315
0
    switch (u.format) {
4316
0
    case 1: hb_barrier (); return u.format1.get_type ();
4317
0
    default:return 0;
4318
0
    }
4319
0
  }
Unexecuted instantiation: OT::Extension<OT::Layout::GPOS_impl::ExtensionPos>::get_type() const
Unexecuted instantiation: OT::Extension<OT::Layout::GSUB_impl::ExtensionSubst>::get_type() const
4320
  template <typename X>
4321
  const X& get_subtable () const
4322
  {
4323
    switch (u.format) {
4324
    case 1: hb_barrier (); return u.format1.template get_subtable<typename T::SubTable> ();
4325
    default:return Null (typename T::SubTable);
4326
    }
4327
  }
4328
4329
  // Specialization of dispatch for subset. dispatch() normally just
4330
  // dispatches to the sub table this points too, but for subset
4331
  // we need to run subset on this subtable too.
4332
  template <typename ...Ts>
4333
  typename hb_subset_context_t::return_t dispatch (hb_subset_context_t *c, Ts&&... ds) const
4334
0
  {
4335
0
    switch (u.format) {
4336
0
    case 1: hb_barrier (); return u.format1.subset (c);
4337
0
    default: return c->default_return_value ();
4338
0
    }
4339
0
  }
Unexecuted instantiation: bool OT::Extension<OT::Layout::GPOS_impl::ExtensionPos>::dispatch<>(hb_subset_context_t*) const
Unexecuted instantiation: bool OT::Extension<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<>(hb_subset_context_t*) const
4340
4341
  template <typename context_t, typename ...Ts>
4342
  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
4343
0
  {
4344
0
    if (unlikely (!c->may_dispatch (this, &u.format))) return c->no_dispatch_return_value ();
4345
0
    TRACE_DISPATCH (this, u.format);
4346
0
    switch (u.format) {
4347
0
    case 1: hb_barrier (); return_trace (u.format1.dispatch (c, std::forward<Ts> (ds)...));
4348
0
    default:return_trace (c->default_return_value ());
4349
0
    }
4350
0
  }
Unexecuted instantiation: OT::hb_intersects_context_t::return_t OT::Extension<OT::Layout::GPOS_impl::ExtensionPos>::dispatch<OT::hb_intersects_context_t>(OT::hb_intersects_context_t*) const
Unexecuted instantiation: OT::hb_ot_apply_context_t::return_t OT::Extension<OT::Layout::GPOS_impl::ExtensionPos>::dispatch<OT::hb_ot_apply_context_t>(OT::hb_ot_apply_context_t*) const
Unexecuted instantiation: OT::hb_collect_glyphs_context_t::return_t OT::Extension<OT::Layout::GPOS_impl::ExtensionPos>::dispatch<OT::hb_collect_glyphs_context_t>(OT::hb_collect_glyphs_context_t*) const
Unexecuted instantiation: OT::hb_closure_lookups_context_t::return_t OT::Extension<OT::Layout::GPOS_impl::ExtensionPos>::dispatch<OT::hb_closure_lookups_context_t>(OT::hb_closure_lookups_context_t*) const
Unexecuted instantiation: hb_sanitize_context_t::return_t OT::Extension<OT::Layout::GPOS_impl::ExtensionPos>::dispatch<hb_sanitize_context_t>(hb_sanitize_context_t*) const
Unexecuted instantiation: OT::hb_collect_variation_indices_context_t::return_t OT::Extension<OT::Layout::GPOS_impl::ExtensionPos>::dispatch<OT::hb_collect_variation_indices_context_t>(OT::hb_collect_variation_indices_context_t*) const
Unexecuted instantiation: OT::hb_accelerate_subtables_context_t::return_t OT::Extension<OT::Layout::GPOS_impl::ExtensionPos>::dispatch<OT::hb_accelerate_subtables_context_t>(OT::hb_accelerate_subtables_context_t*) const
Unexecuted instantiation: OT::hb_intersects_context_t::return_t OT::Extension<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<OT::hb_intersects_context_t>(OT::hb_intersects_context_t*) const
Unexecuted instantiation: hb_sanitize_context_t::return_t OT::Extension<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<hb_sanitize_context_t>(hb_sanitize_context_t*) const
Unexecuted instantiation: OT::hb_have_non_1to1_context_t::return_t OT::Extension<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<OT::hb_have_non_1to1_context_t>(OT::hb_have_non_1to1_context_t*) const
Unexecuted instantiation: OT::hb_ot_apply_context_t::return_t OT::Extension<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<OT::hb_ot_apply_context_t>(OT::hb_ot_apply_context_t*) const
Unexecuted instantiation: OT::hb_closure_context_t::return_t OT::Extension<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<OT::hb_closure_context_t>(OT::hb_closure_context_t*) const
Unexecuted instantiation: OT::hb_closure_lookups_context_t::return_t OT::Extension<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<OT::hb_closure_lookups_context_t>(OT::hb_closure_lookups_context_t*) const
Unexecuted instantiation: OT::hb_collect_glyphs_context_t::return_t OT::Extension<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<OT::hb_collect_glyphs_context_t>(OT::hb_collect_glyphs_context_t*) const
Unexecuted instantiation: OT::hb_would_apply_context_t::return_t OT::Extension<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<OT::hb_would_apply_context_t>(OT::hb_would_apply_context_t*) const
Unexecuted instantiation: OT::hb_accelerate_subtables_context_t::return_t OT::Extension<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<OT::hb_accelerate_subtables_context_t>(OT::hb_accelerate_subtables_context_t*) const
Unexecuted instantiation: hb_get_glyph_alternates_dispatch_t::return_t OT::Extension<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<hb_get_glyph_alternates_dispatch_t, unsigned int&, unsigned int&, unsigned int*&, unsigned int*&>(hb_get_glyph_alternates_dispatch_t*, unsigned int&, unsigned int&, unsigned int*&, unsigned int*&) const
Unexecuted instantiation: hb_position_single_dispatch_t::return_t OT::Extension<OT::Layout::GPOS_impl::ExtensionPos>::dispatch<hb_position_single_dispatch_t, hb_font_t*&, hb_blob_t*&, hb_direction_t&, unsigned int&, hb_glyph_position_t&>(hb_position_single_dispatch_t*, hb_font_t*&, hb_blob_t*&, hb_direction_t&, unsigned int&, hb_glyph_position_t&) const
4351
4352
  protected:
4353
  union {
4354
  HBUINT16    format;   /* Format identifier */
4355
  ExtensionFormat1<T> format1;
4356
  } u;
4357
};
4358
4359
4360
/*
4361
 * GSUB/GPOS Common
4362
 */
4363
4364
struct hb_ot_layout_lookup_accelerator_t
4365
{
4366
  template <typename TLookup>
4367
  static hb_ot_layout_lookup_accelerator_t *create (const TLookup &lookup)
4368
65
  {
4369
65
    unsigned count = lookup.get_subtable_count ();
4370
4371
65
    unsigned size = sizeof (hb_ot_layout_lookup_accelerator_t) -
4372
65
        HB_VAR_ARRAY * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t) +
4373
65
        count * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t);
4374
4375
    /* The following is a calloc because when we are collecting subtables,
4376
     * some of them might be invalid and hence not collect; as a result,
4377
     * we might not fill in all the count entries of the subtables array.
4378
     * Zeroing it allows the set digest to gatekeep it without having to
4379
     * initialize it further. */
4380
65
    auto *thiz = (hb_ot_layout_lookup_accelerator_t *) hb_calloc (1, size);
4381
65
    if (unlikely (!thiz))
4382
0
      return nullptr;
4383
4384
65
    hb_accelerate_subtables_context_t c_accelerate_subtables (thiz->subtables);
4385
65
    lookup.dispatch (&c_accelerate_subtables);
4386
4387
65
    thiz->digest.init ();
4388
65
    for (auto& subtable : hb_iter (thiz->subtables, count))
4389
155
      thiz->digest.union_ (subtable.digest);
4390
4391
65
    thiz->count = count;
4392
4393
65
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
4394
65
    thiz->subtable_cache_user_idx = c_accelerate_subtables.subtable_cache_user_idx;
4395
4396
220
    for (unsigned i = 0; i < count; i++)
4397
155
      if (i != thiz->subtable_cache_user_idx)
4398
136
       thiz->subtables[i].apply_cached_func = thiz->subtables[i].apply_func;
4399
65
#endif
4400
4401
65
    return thiz;
4402
65
  }
OT::hb_ot_layout_lookup_accelerator_t* OT::hb_ot_layout_lookup_accelerator_t::create<OT::Layout::GPOS_impl::PosLookup>(OT::Layout::GPOS_impl::PosLookup const&)
Line
Count
Source
4368
36
  {
4369
36
    unsigned count = lookup.get_subtable_count ();
4370
4371
36
    unsigned size = sizeof (hb_ot_layout_lookup_accelerator_t) -
4372
36
        HB_VAR_ARRAY * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t) +
4373
36
        count * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t);
4374
4375
    /* The following is a calloc because when we are collecting subtables,
4376
     * some of them might be invalid and hence not collect; as a result,
4377
     * we might not fill in all the count entries of the subtables array.
4378
     * Zeroing it allows the set digest to gatekeep it without having to
4379
     * initialize it further. */
4380
36
    auto *thiz = (hb_ot_layout_lookup_accelerator_t *) hb_calloc (1, size);
4381
36
    if (unlikely (!thiz))
4382
0
      return nullptr;
4383
4384
36
    hb_accelerate_subtables_context_t c_accelerate_subtables (thiz->subtables);
4385
36
    lookup.dispatch (&c_accelerate_subtables);
4386
4387
36
    thiz->digest.init ();
4388
36
    for (auto& subtable : hb_iter (thiz->subtables, count))
4389
81
      thiz->digest.union_ (subtable.digest);
4390
4391
36
    thiz->count = count;
4392
4393
36
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
4394
36
    thiz->subtable_cache_user_idx = c_accelerate_subtables.subtable_cache_user_idx;
4395
4396
117
    for (unsigned i = 0; i < count; i++)
4397
81
      if (i != thiz->subtable_cache_user_idx)
4398
81
       thiz->subtables[i].apply_cached_func = thiz->subtables[i].apply_func;
4399
36
#endif
4400
4401
36
    return thiz;
4402
36
  }
OT::hb_ot_layout_lookup_accelerator_t* OT::hb_ot_layout_lookup_accelerator_t::create<OT::Layout::GSUB_impl::SubstLookup>(OT::Layout::GSUB_impl::SubstLookup const&)
Line
Count
Source
4368
29
  {
4369
29
    unsigned count = lookup.get_subtable_count ();
4370
4371
29
    unsigned size = sizeof (hb_ot_layout_lookup_accelerator_t) -
4372
29
        HB_VAR_ARRAY * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t) +
4373
29
        count * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t);
4374
4375
    /* The following is a calloc because when we are collecting subtables,
4376
     * some of them might be invalid and hence not collect; as a result,
4377
     * we might not fill in all the count entries of the subtables array.
4378
     * Zeroing it allows the set digest to gatekeep it without having to
4379
     * initialize it further. */
4380
29
    auto *thiz = (hb_ot_layout_lookup_accelerator_t *) hb_calloc (1, size);
4381
29
    if (unlikely (!thiz))
4382
0
      return nullptr;
4383
4384
29
    hb_accelerate_subtables_context_t c_accelerate_subtables (thiz->subtables);
4385
29
    lookup.dispatch (&c_accelerate_subtables);
4386
4387
29
    thiz->digest.init ();
4388
29
    for (auto& subtable : hb_iter (thiz->subtables, count))
4389
74
      thiz->digest.union_ (subtable.digest);
4390
4391
29
    thiz->count = count;
4392
4393
29
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
4394
29
    thiz->subtable_cache_user_idx = c_accelerate_subtables.subtable_cache_user_idx;
4395
4396
103
    for (unsigned i = 0; i < count; i++)
4397
74
      if (i != thiz->subtable_cache_user_idx)
4398
55
       thiz->subtables[i].apply_cached_func = thiz->subtables[i].apply_func;
4399
29
#endif
4400
4401
29
    return thiz;
4402
29
  }
4403
4404
  void fini ()
4405
65
  {
4406
65
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
4407
220
    for (unsigned i = 0; i < count; i++)
4408
155
      hb_free (subtables[i].external_cache);
4409
65
#endif
4410
65
  }
4411
4412
  bool may_have (hb_codepoint_t g) const
4413
0
  { return digest.may_have (g); }
4414
4415
#ifndef HB_OPTIMIZE_SIZE
4416
  HB_ALWAYS_INLINE
4417
#endif
4418
  bool apply (hb_ot_apply_context_t *c, bool use_cache) const
4419
0
  {
4420
0
    c->lookup_accel = this;
4421
0
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
4422
0
    if (use_cache)
4423
0
    {
4424
0
      return
4425
0
      + hb_iter (hb_iter (subtables, count))
4426
0
      | hb_map ([&c] (const hb_accelerate_subtables_context_t::hb_applicable_t &_) { return _.apply_cached (c); })
4427
0
      | hb_any
4428
0
      ;
4429
0
    }
4430
0
    else
4431
0
#endif
4432
0
    {
4433
0
      return
4434
0
      + hb_iter (hb_iter (subtables, count))
4435
0
      | hb_map ([&c] (const hb_accelerate_subtables_context_t::hb_applicable_t &_) { return _.apply (c); })
4436
0
      | hb_any
4437
0
      ;
4438
0
    }
4439
0
    return false;
4440
0
  }
4441
4442
  bool cache_enter (hb_ot_apply_context_t *c) const
4443
0
  {
4444
0
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
4445
0
    return subtable_cache_user_idx != (unsigned) -1 &&
4446
0
     subtables[subtable_cache_user_idx].cache_enter (c);
4447
#else
4448
    return false;
4449
#endif
4450
0
  }
4451
  void cache_leave (hb_ot_apply_context_t *c) const
4452
0
  {
4453
0
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
4454
0
    subtables[subtable_cache_user_idx].cache_leave (c);
4455
0
#endif
4456
0
  }
4457
4458
4459
  hb_set_digest_t digest;
4460
  private:
4461
  unsigned count = 0; /* Number of subtables in the array. */
4462
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
4463
  unsigned subtable_cache_user_idx = (unsigned) -1;
4464
#endif
4465
  hb_accelerate_subtables_context_t::hb_applicable_t subtables[HB_VAR_ARRAY];
4466
};
4467
4468
template <typename Types>
4469
struct GSUBGPOSVersion1_2
4470
{
4471
  friend struct GSUBGPOS;
4472
4473
  protected:
4474
  FixedVersion<>version;  /* Version of the GSUB/GPOS table--initially set
4475
         * to 0x00010000u */
4476
  typename Types:: template OffsetTo<ScriptList>
4477
    scriptList; /* ScriptList table */
4478
  typename Types::template OffsetTo<FeatureList>
4479
    featureList;  /* FeatureList table */
4480
  typename Types::template OffsetTo<LookupList<Types>>
4481
    lookupList; /* LookupList table */
4482
  Offset32To<FeatureVariations>
4483
    featureVars;  /* Offset to Feature Variations
4484
           table--from beginning of table
4485
         * (may be NULL).  Introduced
4486
         * in version 0x00010001. */
4487
  public:
4488
  DEFINE_SIZE_MIN (4 + 3 * Types::size);
4489
4490
  unsigned int get_size () const
4491
0
  {
4492
0
    return min_size +
4493
0
     (version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
4494
0
  }
4495
4496
  const typename Types::template OffsetTo<LookupList<Types>>* get_lookup_list_offset () const
4497
  {
4498
    return &lookupList;
4499
  }
4500
4501
  template <typename TLookup>
4502
  bool sanitize (hb_sanitize_context_t *c) const
4503
3.76k
  {
4504
3.76k
    TRACE_SANITIZE (this);
4505
3.76k
    typedef List16OfOffsetTo<TLookup, typename Types::HBUINT> TLookupList;
4506
3.76k
    if (unlikely (!(scriptList.sanitize (c, this) &&
4507
3.76k
        featureList.sanitize (c, this) &&
4508
3.76k
        reinterpret_cast<const typename Types::template OffsetTo<TLookupList> &> (lookupList).sanitize (c, this))))
4509
0
      return_trace (false);
4510
4511
3.76k
#ifndef HB_NO_VAR
4512
3.76k
    if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this))))
4513
0
      return_trace (false);
4514
3.76k
#endif
4515
4516
3.76k
    return_trace (true);
4517
3.76k
  }
bool OT::GSUBGPOSVersion1_2<OT::Layout::SmallTypes>::sanitize<OT::Layout::GPOS_impl::PosLookup>(hb_sanitize_context_t*) const
Line
Count
Source
4503
1.88k
  {
4504
1.88k
    TRACE_SANITIZE (this);
4505
1.88k
    typedef List16OfOffsetTo<TLookup, typename Types::HBUINT> TLookupList;
4506
1.88k
    if (unlikely (!(scriptList.sanitize (c, this) &&
4507
1.88k
        featureList.sanitize (c, this) &&
4508
1.88k
        reinterpret_cast<const typename Types::template OffsetTo<TLookupList> &> (lookupList).sanitize (c, this))))
4509
0
      return_trace (false);
4510
4511
1.88k
#ifndef HB_NO_VAR
4512
1.88k
    if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this))))
4513
0
      return_trace (false);
4514
1.88k
#endif
4515
4516
1.88k
    return_trace (true);
4517
1.88k
  }
bool OT::GSUBGPOSVersion1_2<OT::Layout::SmallTypes>::sanitize<OT::Layout::GSUB_impl::SubstLookup>(hb_sanitize_context_t*) const
Line
Count
Source
4503
1.88k
  {
4504
1.88k
    TRACE_SANITIZE (this);
4505
1.88k
    typedef List16OfOffsetTo<TLookup, typename Types::HBUINT> TLookupList;
4506
1.88k
    if (unlikely (!(scriptList.sanitize (c, this) &&
4507
1.88k
        featureList.sanitize (c, this) &&
4508
1.88k
        reinterpret_cast<const typename Types::template OffsetTo<TLookupList> &> (lookupList).sanitize (c, this))))
4509
0
      return_trace (false);
4510
4511
1.88k
#ifndef HB_NO_VAR
4512
1.88k
    if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this))))
4513
0
      return_trace (false);
4514
1.88k
#endif
4515
4516
1.88k
    return_trace (true);
4517
1.88k
  }
4518
4519
  template <typename TLookup>
4520
  bool subset (hb_subset_layout_context_t *c) const
4521
0
  {
4522
0
    TRACE_SUBSET (this);
4523
0
4524
0
    auto *out = c->subset_context->serializer->start_embed (this);
4525
0
    if (unlikely (!c->subset_context->serializer->extend_min (out))) return_trace (false);
4526
0
4527
0
    out->version = version;
4528
0
4529
0
    typedef LookupOffsetList<TLookup, typename Types::HBUINT> TLookupList;
4530
0
    reinterpret_cast<typename Types::template OffsetTo<TLookupList> &> (out->lookupList)
4531
0
  .serialize_subset (c->subset_context,
4532
0
         reinterpret_cast<const typename Types::template OffsetTo<TLookupList> &> (lookupList),
4533
0
         this,
4534
0
         c);
4535
0
4536
0
    reinterpret_cast<typename Types::template OffsetTo<RecordListOfFeature> &> (out->featureList)
4537
0
  .serialize_subset (c->subset_context,
4538
0
         reinterpret_cast<const typename Types::template OffsetTo<RecordListOfFeature> &> (featureList),
4539
0
         this,
4540
0
         c);
4541
0
4542
0
    out->scriptList.serialize_subset (c->subset_context,
4543
0
              scriptList,
4544
0
              this,
4545
0
              c);
4546
0
4547
0
#ifndef HB_NO_VAR
4548
0
    if (version.to_int () >= 0x00010001u)
4549
0
    {
4550
0
      auto snapshot = c->subset_context->serializer->snapshot ();
4551
0
      if (!c->subset_context->serializer->extend_min (&out->featureVars))
4552
0
        return_trace (false);
4553
0
4554
0
      // if all axes are pinned all feature vars are dropped.
4555
0
      bool ret = !c->subset_context->plan->all_axes_pinned
4556
0
                 && out->featureVars.serialize_subset (c->subset_context, featureVars, this, c);
4557
0
      if (!ret && version.major == 1)
4558
0
      {
4559
0
        c->subset_context->serializer->revert (snapshot);
4560
0
  out->version.major = 1;
4561
0
  out->version.minor = 0;
4562
0
      }
4563
0
    }
4564
0
#endif
4565
0
4566
0
    return_trace (true);
4567
0
  }
Unexecuted instantiation: bool OT::GSUBGPOSVersion1_2<OT::Layout::SmallTypes>::subset<OT::Layout::GPOS_impl::PosLookup>(OT::hb_subset_layout_context_t*) const
Unexecuted instantiation: bool OT::GSUBGPOSVersion1_2<OT::Layout::SmallTypes>::subset<OT::Layout::GSUB_impl::SubstLookup>(OT::hb_subset_layout_context_t*) const
4568
};
4569
4570
struct GSUBGPOS
4571
{
4572
  unsigned int get_size () const
4573
0
  {
4574
0
    switch (u.version.major) {
4575
0
    case 1: hb_barrier (); return u.version1.get_size ();
4576
0
#ifndef HB_NO_BEYOND_64K
4577
0
    case 2: hb_barrier (); return u.version2.get_size ();
4578
0
#endif
4579
0
    default: return u.version.static_size;
4580
0
    }
4581
0
  }
4582
4583
  template <typename TLookup>
4584
  bool sanitize (hb_sanitize_context_t *c) const
4585
3.76k
  {
4586
3.76k
    TRACE_SANITIZE (this);
4587
3.76k
    if (unlikely (!u.version.sanitize (c))) return_trace (false);
4588
3.76k
    hb_barrier ();
4589
3.76k
    switch (u.version.major) {
4590
3.76k
    case 1: hb_barrier (); return_trace (u.version1.sanitize<TLookup> (c));
4591
#ifndef HB_NO_BEYOND_64K
4592
    case 2: hb_barrier (); return_trace (u.version2.sanitize<TLookup> (c));
4593
#endif
4594
0
    default: return_trace (true);
4595
3.76k
    }
4596
3.76k
  }
bool OT::GSUBGPOS::sanitize<OT::Layout::GPOS_impl::PosLookup>(hb_sanitize_context_t*) const
Line
Count
Source
4585
1.88k
  {
4586
1.88k
    TRACE_SANITIZE (this);
4587
1.88k
    if (unlikely (!u.version.sanitize (c))) return_trace (false);
4588
1.88k
    hb_barrier ();
4589
1.88k
    switch (u.version.major) {
4590
1.88k
    case 1: hb_barrier (); return_trace (u.version1.sanitize<TLookup> (c));
4591
#ifndef HB_NO_BEYOND_64K
4592
    case 2: hb_barrier (); return_trace (u.version2.sanitize<TLookup> (c));
4593
#endif
4594
0
    default: return_trace (true);
4595
1.88k
    }
4596
1.88k
  }
bool OT::GSUBGPOS::sanitize<OT::Layout::GSUB_impl::SubstLookup>(hb_sanitize_context_t*) const
Line
Count
Source
4585
1.88k
  {
4586
1.88k
    TRACE_SANITIZE (this);
4587
1.88k
    if (unlikely (!u.version.sanitize (c))) return_trace (false);
4588
1.88k
    hb_barrier ();
4589
1.88k
    switch (u.version.major) {
4590
1.88k
    case 1: hb_barrier (); return_trace (u.version1.sanitize<TLookup> (c));
4591
#ifndef HB_NO_BEYOND_64K
4592
    case 2: hb_barrier (); return_trace (u.version2.sanitize<TLookup> (c));
4593
#endif
4594
0
    default: return_trace (true);
4595
1.88k
    }
4596
1.88k
  }
4597
4598
  template <typename TLookup>
4599
  bool subset (hb_subset_layout_context_t *c) const
4600
0
  {
4601
0
    switch (u.version.major) {
4602
0
    case 1: hb_barrier (); return u.version1.subset<TLookup> (c);
4603
0
#ifndef HB_NO_BEYOND_64K
4604
0
    case 2: hb_barrier (); return u.version2.subset<TLookup> (c);
4605
0
#endif
4606
0
    default: return false;
4607
0
    }
4608
0
  }
Unexecuted instantiation: bool OT::GSUBGPOS::subset<OT::Layout::GPOS_impl::PosLookup>(OT::hb_subset_layout_context_t*) const
Unexecuted instantiation: bool OT::GSUBGPOS::subset<OT::Layout::GSUB_impl::SubstLookup>(OT::hb_subset_layout_context_t*) const
4609
4610
  const ScriptList &get_script_list () const
4611
30.5k
  {
4612
30.5k
    switch (u.version.major) {
4613
30.5k
    case 1: hb_barrier (); return this+u.version1.scriptList;
4614
#ifndef HB_NO_BEYOND_64K
4615
    case 2: hb_barrier (); return this+u.version2.scriptList;
4616
#endif
4617
0
    default: return Null (ScriptList);
4618
30.5k
    }
4619
30.5k
  }
4620
  const FeatureList &get_feature_list () const
4621
231
  {
4622
231
    switch (u.version.major) {
4623
231
    case 1: hb_barrier (); return this+u.version1.featureList;
4624
#ifndef HB_NO_BEYOND_64K
4625
    case 2: hb_barrier (); return this+u.version2.featureList;
4626
#endif
4627
0
    default: return Null (FeatureList);
4628
231
    }
4629
231
  }
4630
  unsigned int get_lookup_count () const
4631
3.88k
  {
4632
3.88k
    switch (u.version.major) {
4633
3.88k
    case 1: hb_barrier (); return (this+u.version1.lookupList).len;
4634
#ifndef HB_NO_BEYOND_64K
4635
    case 2: hb_barrier (); return (this+u.version2.lookupList).len;
4636
#endif
4637
0
    default: return 0;
4638
3.88k
    }
4639
3.88k
  }
4640
  const Lookup& get_lookup (unsigned int i) const
4641
65
  {
4642
65
    switch (u.version.major) {
4643
65
    case 1: hb_barrier (); return (this+u.version1.lookupList)[i];
4644
#ifndef HB_NO_BEYOND_64K
4645
    case 2: hb_barrier (); return (this+u.version2.lookupList)[i];
4646
#endif
4647
0
    default: return Null (Lookup);
4648
65
    }
4649
65
  }
4650
  const FeatureVariations &get_feature_variations () const
4651
251k
  {
4652
251k
    switch (u.version.major) {
4653
251k
    case 1: hb_barrier (); return (u.version.to_int () >= 0x00010001u && hb_barrier () ? this+u.version1.featureVars : Null (FeatureVariations));
4654
#ifndef HB_NO_BEYOND_64K
4655
    case 2: hb_barrier (); return this+u.version2.featureVars;
4656
#endif
4657
0
    default: return Null (FeatureVariations);
4658
251k
    }
4659
251k
  }
4660
4661
4.38k
  bool has_data () const { return u.version.to_int (); }
4662
  unsigned int get_script_count () const
4663
0
  { return get_script_list ().len; }
4664
  const Tag& get_script_tag (unsigned int i) const
4665
0
  { return get_script_list ().get_tag (i); }
4666
  unsigned int get_script_tags (unsigned int start_offset,
4667
        unsigned int *script_count /* IN/OUT */,
4668
        hb_tag_t     *script_tags /* OUT */) const
4669
0
  { return get_script_list ().get_tags (start_offset, script_count, script_tags); }
4670
  const Script& get_script (unsigned int i) const
4671
13.1k
  { return get_script_list ()[i]; }
4672
  bool find_script_index (hb_tag_t tag, unsigned int *index) const
4673
17.4k
  { return get_script_list ().find_index (tag, index); }
4674
4675
  unsigned int get_feature_count () const
4676
0
  { return get_feature_list ().len; }
4677
  hb_tag_t get_feature_tag (unsigned int i) const
4678
4.49k
  { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : get_feature_list ().get_tag (i); }
4679
  unsigned int get_feature_tags (unsigned int start_offset,
4680
         unsigned int *feature_count /* IN/OUT */,
4681
         hb_tag_t     *feature_tags /* OUT */) const
4682
0
  { return get_feature_list ().get_tags (start_offset, feature_count, feature_tags); }
4683
  const Feature& get_feature (unsigned int i) const
4684
118
  { return get_feature_list ()[i]; }
4685
  bool find_feature_index (hb_tag_t tag, unsigned int *index) const
4686
0
  { return get_feature_list ().find_index (tag, index); }
4687
4688
  bool find_variations_index (const int *coords, unsigned int num_coords,
4689
            unsigned int *index,
4690
            ItemVarStoreInstancer *instancer) const
4691
251k
  {
4692
#ifdef HB_NO_VAR
4693
    *index = FeatureVariations::NOT_FOUND_INDEX;
4694
    return false;
4695
#endif
4696
251k
    return get_feature_variations ().find_index (coords, num_coords, index, instancer);
4697
251k
  }
4698
  const Feature& get_feature_variation (unsigned int feature_index,
4699
          unsigned int variations_index) const
4700
118
  {
4701
118
#ifndef HB_NO_VAR
4702
118
    if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
4703
118
  u.version.to_int () >= 0x00010001u)
4704
0
    {
4705
0
      const Feature *feature = get_feature_variations ().find_substitute (variations_index,
4706
0
                    feature_index);
4707
0
      if (feature)
4708
0
  return *feature;
4709
0
    }
4710
118
#endif
4711
118
    return get_feature (feature_index);
4712
118
  }
4713
4714
  void feature_variation_collect_lookups (const hb_set_t *feature_indexes,
4715
            const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
4716
            hb_set_t       *lookup_indexes /* OUT */) const
4717
0
  {
4718
0
#ifndef HB_NO_VAR
4719
0
    get_feature_variations ().collect_lookups (feature_indexes, feature_record_cond_idx_map, lookup_indexes);
4720
0
#endif
4721
0
  }
4722
4723
#ifndef HB_NO_VAR
4724
  void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
4725
0
  { get_feature_variations ().collect_feature_substitutes_with_variations (c); }
4726
#endif
4727
4728
  template <typename TLookup>
4729
  void closure_lookups (hb_face_t      *face,
4730
      const hb_set_t *glyphs,
4731
      hb_set_t       *lookup_indexes /* IN/OUT */) const
4732
0
  {
4733
0
    hb_set_t visited_lookups, inactive_lookups;
4734
0
    hb_closure_lookups_context_t c (face, glyphs, &visited_lookups, &inactive_lookups);
4735
0
4736
0
    c.set_recurse_func (TLookup::template dispatch_recurse_func<hb_closure_lookups_context_t>);
4737
0
4738
0
    for (unsigned lookup_index : *lookup_indexes)
4739
0
      reinterpret_cast<const TLookup &> (get_lookup (lookup_index)).closure_lookups (&c, lookup_index);
4740
0
4741
0
    hb_set_union (lookup_indexes, &visited_lookups);
4742
0
    hb_set_subtract (lookup_indexes, &inactive_lookups);
4743
0
  }
Unexecuted instantiation: void OT::GSUBGPOS::closure_lookups<OT::Layout::GPOS_impl::PosLookup>(hb_face_t*, hb_set_t const*, hb_set_t*) const
Unexecuted instantiation: void OT::GSUBGPOS::closure_lookups<OT::Layout::GSUB_impl::SubstLookup>(hb_face_t*, hb_set_t const*, hb_set_t*) const
4744
4745
  void prune_langsys (const hb_map_t *duplicate_feature_map,
4746
                      const hb_set_t *layout_scripts,
4747
                      hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map,
4748
                      hb_set_t       *new_feature_indexes /* OUT */) const
4749
0
  {
4750
0
    hb_prune_langsys_context_t c (this, script_langsys_map, duplicate_feature_map, new_feature_indexes);
4751
0
4752
0
    unsigned count = get_script_count ();
4753
0
    for (unsigned script_index = 0; script_index < count; script_index++)
4754
0
    {
4755
0
      const Tag& tag = get_script_tag (script_index);
4756
0
      if (!layout_scripts->has (tag)) continue;
4757
0
      const Script& s = get_script (script_index);
4758
0
      s.prune_langsys (&c, script_index);
4759
0
    }
4760
0
  }
4761
4762
  void prune_features (const hb_map_t *lookup_indices, /* IN */
4763
           const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, /* IN */
4764
           const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map, /* IN */
4765
           hb_set_t       *feature_indices /* IN/OUT */) const
4766
0
  {
4767
0
#ifndef HB_NO_VAR
4768
0
    // This is the set of feature indices which have alternate versions defined
4769
0
    // if the FeatureVariation's table and the alternate version(s) intersect the
4770
0
    // set of lookup indices.
4771
0
    hb_set_t alternate_feature_indices;
4772
0
    get_feature_variations ().closure_features (lookup_indices, feature_record_cond_idx_map, &alternate_feature_indices);
4773
0
    if (unlikely (alternate_feature_indices.in_error()))
4774
0
    {
4775
0
      feature_indices->err ();
4776
0
      return;
4777
0
    }
4778
0
#endif
4779
0
4780
0
    for (unsigned i : hb_iter (feature_indices))
4781
0
    {
4782
0
      hb_tag_t tag =  get_feature_tag (i);
4783
0
      if (tag == HB_TAG ('p', 'r', 'e', 'f'))
4784
0
        // Note: Never ever drop feature 'pref', even if it's empty.
4785
0
        // HarfBuzz chooses shaper for Khmer based on presence of this
4786
0
        // feature. See thread at:
4787
0
  // http://lists.freedesktop.org/archives/harfbuzz/2012-November/002660.html
4788
0
        continue;
4789
0
4790
0
4791
0
      const Feature *f = &(get_feature (i));
4792
0
      const Feature** p = nullptr;
4793
0
      if (feature_substitutes_map->has (i, &p))
4794
0
        f = *p;
4795
0
4796
0
      if (!f->featureParams.is_null () &&
4797
0
          tag == HB_TAG ('s', 'i', 'z', 'e'))
4798
0
        continue;
4799
0
4800
0
      if (!f->intersects_lookup_indexes (lookup_indices)
4801
0
#ifndef HB_NO_VAR
4802
0
          && !alternate_feature_indices.has (i)
4803
0
#endif
4804
0
    )
4805
0
  feature_indices->del (i);
4806
0
    }
4807
0
  }
4808
4809
  void collect_name_ids (const hb_map_t *feature_index_map,
4810
                         hb_set_t *nameids_to_retain /* OUT */) const
4811
0
  {
4812
0
    unsigned count = get_feature_count ();
4813
0
    for (unsigned i = 0 ; i < count; i++)
4814
0
    {
4815
0
      if (!feature_index_map->has (i)) continue;
4816
0
      hb_tag_t tag = get_feature_tag (i);
4817
0
      get_feature (i).collect_name_ids (tag, nameids_to_retain);
4818
0
    }
4819
0
  }
4820
4821
  template <typename T>
4822
  struct accelerator_t
4823
  {
4824
    accelerator_t (hb_face_t *face)
4825
3.76k
    {
4826
3.76k
      hb_sanitize_context_t sc;
4827
3.76k
      sc.lazy_some_gpos = true;
4828
3.76k
      this->table = sc.reference_table<T> (face);
4829
4830
3.76k
      if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face)))
4831
0
      {
4832
0
  hb_blob_destroy (this->table.get_blob ());
4833
0
  this->table = hb_blob_get_empty ();
4834
0
      }
4835
4836
3.76k
      this->lookup_count = table->get_lookup_count ();
4837
4838
3.76k
      this->accels = (hb_atomic_t<hb_ot_layout_lookup_accelerator_t *> *) hb_calloc (this->lookup_count, sizeof (*accels));
4839
3.76k
      if (unlikely (!this->accels))
4840
0
      {
4841
0
  this->lookup_count = 0;
4842
0
  this->table.destroy ();
4843
0
  this->table = hb_blob_get_empty ();
4844
0
      }
4845
3.76k
    }
OT::GSUBGPOS::accelerator_t<OT::Layout::GSUB>::accelerator_t(hb_face_t*)
Line
Count
Source
4825
1.88k
    {
4826
1.88k
      hb_sanitize_context_t sc;
4827
1.88k
      sc.lazy_some_gpos = true;
4828
1.88k
      this->table = sc.reference_table<T> (face);
4829
4830
1.88k
      if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face)))
4831
0
      {
4832
0
  hb_blob_destroy (this->table.get_blob ());
4833
0
  this->table = hb_blob_get_empty ();
4834
0
      }
4835
4836
1.88k
      this->lookup_count = table->get_lookup_count ();
4837
4838
1.88k
      this->accels = (hb_atomic_t<hb_ot_layout_lookup_accelerator_t *> *) hb_calloc (this->lookup_count, sizeof (*accels));
4839
1.88k
      if (unlikely (!this->accels))
4840
0
      {
4841
0
  this->lookup_count = 0;
4842
0
  this->table.destroy ();
4843
0
  this->table = hb_blob_get_empty ();
4844
0
      }
4845
1.88k
    }
OT::GSUBGPOS::accelerator_t<OT::Layout::GPOS>::accelerator_t(hb_face_t*)
Line
Count
Source
4825
1.88k
    {
4826
1.88k
      hb_sanitize_context_t sc;
4827
1.88k
      sc.lazy_some_gpos = true;
4828
1.88k
      this->table = sc.reference_table<T> (face);
4829
4830
1.88k
      if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face)))
4831
0
      {
4832
0
  hb_blob_destroy (this->table.get_blob ());
4833
0
  this->table = hb_blob_get_empty ();
4834
0
      }
4835
4836
1.88k
      this->lookup_count = table->get_lookup_count ();
4837
4838
1.88k
      this->accels = (hb_atomic_t<hb_ot_layout_lookup_accelerator_t *> *) hb_calloc (this->lookup_count, sizeof (*accels));
4839
1.88k
      if (unlikely (!this->accels))
4840
0
      {
4841
0
  this->lookup_count = 0;
4842
0
  this->table.destroy ();
4843
0
  this->table = hb_blob_get_empty ();
4844
0
      }
4845
1.88k
    }
4846
    ~accelerator_t ()
4847
3.76k
    {
4848
9.81k
      for (unsigned int i = 0; i < this->lookup_count; i++)
4849
6.04k
      {
4850
6.04k
  auto *accel = this->accels[i].get_relaxed ();
4851
6.04k
  if (accel)
4852
65
    accel->fini ();
4853
6.04k
  hb_free (accel);
4854
6.04k
      }
4855
3.76k
      hb_free (this->accels);
4856
3.76k
      this->table.destroy ();
4857
3.76k
    }
OT::GSUBGPOS::accelerator_t<OT::Layout::GSUB>::~accelerator_t()
Line
Count
Source
4847
1.88k
    {
4848
7.79k
      for (unsigned int i = 0; i < this->lookup_count; i++)
4849
5.90k
      {
4850
5.90k
  auto *accel = this->accels[i].get_relaxed ();
4851
5.90k
  if (accel)
4852
29
    accel->fini ();
4853
5.90k
  hb_free (accel);
4854
5.90k
      }
4855
1.88k
      hb_free (this->accels);
4856
1.88k
      this->table.destroy ();
4857
1.88k
    }
OT::GSUBGPOS::accelerator_t<OT::Layout::GPOS>::~accelerator_t()
Line
Count
Source
4847
1.88k
    {
4848
2.02k
      for (unsigned int i = 0; i < this->lookup_count; i++)
4849
139
      {
4850
139
  auto *accel = this->accels[i].get_relaxed ();
4851
139
  if (accel)
4852
36
    accel->fini ();
4853
139
  hb_free (accel);
4854
139
      }
4855
1.88k
      hb_free (this->accels);
4856
1.88k
      this->table.destroy ();
4857
1.88k
    }
4858
4859
246k
    hb_blob_t *get_blob () const { return table.get_blob (); }
OT::GSUBGPOS::accelerator_t<OT::Layout::GSUB>::get_blob() const
Line
Count
Source
4859
123k
    hb_blob_t *get_blob () const { return table.get_blob (); }
OT::GSUBGPOS::accelerator_t<OT::Layout::GPOS>::get_blob() const
Line
Count
Source
4859
123k
    hb_blob_t *get_blob () const { return table.get_blob (); }
4860
4861
    hb_ot_layout_lookup_accelerator_t *get_accel (unsigned lookup_index) const
4862
4.68k
    {
4863
4.68k
      if (unlikely (lookup_index >= lookup_count)) return nullptr;
4864
4865
4.68k
    retry:
4866
4.68k
      auto *accel = accels[lookup_index].get_acquire ();
4867
4.68k
      if (unlikely (!accel))
4868
65
      {
4869
65
  accel = hb_ot_layout_lookup_accelerator_t::create (table->get_lookup (lookup_index));
4870
65
  if (unlikely (!accel))
4871
0
    return nullptr;
4872
4873
65
  if (unlikely (!accels[lookup_index].cmpexch (nullptr, accel)))
4874
0
  {
4875
0
    accel->fini ();
4876
0
    hb_free (accel);
4877
0
    goto retry;
4878
0
  }
4879
65
      }
4880
4881
4.68k
      return accel;
4882
4.68k
    }
OT::GSUBGPOS::accelerator_t<OT::Layout::GPOS>::get_accel(unsigned int) const
Line
Count
Source
4862
2.48k
    {
4863
2.48k
      if (unlikely (lookup_index >= lookup_count)) return nullptr;
4864
4865
2.48k
    retry:
4866
2.48k
      auto *accel = accels[lookup_index].get_acquire ();
4867
2.48k
      if (unlikely (!accel))
4868
36
      {
4869
36
  accel = hb_ot_layout_lookup_accelerator_t::create (table->get_lookup (lookup_index));
4870
36
  if (unlikely (!accel))
4871
0
    return nullptr;
4872
4873
36
  if (unlikely (!accels[lookup_index].cmpexch (nullptr, accel)))
4874
0
  {
4875
0
    accel->fini ();
4876
0
    hb_free (accel);
4877
0
    goto retry;
4878
0
  }
4879
36
      }
4880
4881
2.48k
      return accel;
4882
2.48k
    }
OT::GSUBGPOS::accelerator_t<OT::Layout::GSUB>::get_accel(unsigned int) const
Line
Count
Source
4862
2.20k
    {
4863
2.20k
      if (unlikely (lookup_index >= lookup_count)) return nullptr;
4864
4865
2.20k
    retry:
4866
2.20k
      auto *accel = accels[lookup_index].get_acquire ();
4867
2.20k
      if (unlikely (!accel))
4868
29
      {
4869
29
  accel = hb_ot_layout_lookup_accelerator_t::create (table->get_lookup (lookup_index));
4870
29
  if (unlikely (!accel))
4871
0
    return nullptr;
4872
4873
29
  if (unlikely (!accels[lookup_index].cmpexch (nullptr, accel)))
4874
0
  {
4875
0
    accel->fini ();
4876
0
    hb_free (accel);
4877
0
    goto retry;
4878
0
  }
4879
29
      }
4880
4881
2.20k
      return accel;
4882
2.20k
    }
4883
4884
    hb_blob_ptr_t<T> table;
4885
    unsigned int lookup_count;
4886
    hb_atomic_t<hb_ot_layout_lookup_accelerator_t *> *accels;
4887
  };
4888
4889
  protected:
4890
  union {
4891
  FixedVersion<>      version;  /* Version identifier */
4892
  GSUBGPOSVersion1_2<SmallTypes>  version1;
4893
#ifndef HB_NO_BEYOND_64K
4894
  GSUBGPOSVersion1_2<MediumTypes> version2;
4895
#endif
4896
  } u;
4897
  public:
4898
  DEFINE_SIZE_MIN (4);
4899
};
4900
4901
4902
} /* namespace OT */
4903
4904
4905
#endif /* HB_OT_LAYOUT_GSUBGPOS_HH */