Coverage Report

Created: 2026-09-28 10:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/workdir/UnpackedTarball/harfbuzz/src/hb-ot-layout-gsubgpos.hh
Line
Count
Source
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
#include "hb-depend-data.hh"
40
41
42
namespace OT {
43
44
45
struct hb_intersects_context_t :
46
       hb_dispatch_context_t<hb_intersects_context_t, bool>
47
{
48
  template <typename T>
49
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&)
50
0
  static return_t default_return_value () { return false; }
51
0
  bool stop_sublookup_iteration (return_t r) const { return r; }
52
53
  const hb_set_t *glyphs;
54
55
  hb_intersects_context_t (const hb_set_t *glyphs_) :
56
0
                            glyphs (glyphs_) {}
57
};
58
59
struct hb_have_non_1to1_context_t :
60
       hb_dispatch_context_t<hb_have_non_1to1_context_t, bool>
61
{
62
  template <typename T>
63
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&)
64
0
  static return_t default_return_value () { return false; }
65
0
  bool stop_sublookup_iteration (return_t r) const { return r; }
66
};
67
68
struct hb_closure_context_t :
69
       hb_dispatch_context_t<hb_closure_context_t>
70
{
71
  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);
72
  template <typename T>
73
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&)
74
0
  static return_t default_return_value () { return hb_empty_t (); }
75
  void recurse (unsigned lookup_index, hb_set_t *covered_seq_indicies, unsigned seq_index, unsigned end_index)
76
0
  {
77
0
    if (unlikely (nesting_level_left == 0 || !recurse_func))
78
0
      return;
79
80
0
    nesting_level_left--;
81
0
    recurse_func (this, lookup_index, covered_seq_indicies, seq_index, end_index);
82
0
    nesting_level_left++;
83
0
  }
84
85
  void reset_lookup_visit_count ()
86
0
  { lookup_count = 0; }
87
88
  bool lookup_limit_exceeded ()
89
0
  { return lookup_count > HB_MAX_LOOKUP_VISIT_COUNT; }
90
91
  bool should_visit_lookup (unsigned int lookup_index)
92
0
  {
93
0
    if (lookup_count++ > HB_MAX_LOOKUP_VISIT_COUNT)
94
0
      return false;
95
96
0
    if (is_lookup_done (lookup_index))
97
0
      return false;
98
99
0
    return true;
100
0
  }
101
102
  bool is_lookup_done (unsigned int lookup_index)
103
0
  {
104
0
    if (unlikely (done_lookups_glyph_count->in_error () ||
105
0
      done_lookups_glyph_set->in_error ()))
106
0
      return true;
107
108
    /* Have we visited this lookup with the current set of glyphs? */
109
0
    unsigned pop = glyphs->get_population ();
110
0
    if (unlikely (pop == HB_MAP_VALUE_INVALID)) // Avoid sentinel interference.
111
0
      pop--;
112
0
    if (done_lookups_glyph_count->get (lookup_index) != pop)
113
0
    {
114
0
      done_lookups_glyph_count->set (lookup_index, pop);
115
116
0
      if (!done_lookups_glyph_set->has (lookup_index))
117
0
      {
118
0
  if (unlikely (!done_lookups_glyph_set->set (lookup_index, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
119
0
    return true;
120
0
      }
121
122
0
      done_lookups_glyph_set->get (lookup_index)->clear ();
123
0
    }
124
125
0
    hb_set_t *covered_glyph_set = done_lookups_glyph_set->get (lookup_index);
126
0
    if (unlikely (covered_glyph_set->in_error ()))
127
0
      return true;
128
0
    if (parent_active_glyphs ().is_subset (*covered_glyph_set))
129
0
      return true;
130
131
0
    covered_glyph_set->union_ (parent_active_glyphs ());
132
0
    return false;
133
0
  }
134
135
0
  const hb_set_t& previous_parent_active_glyphs () {
136
0
    if (active_glyphs_stack.length <= 1)
137
0
      return *glyphs;
138
139
0
    return active_glyphs_stack[active_glyphs_stack.length - 2];
140
0
  }
141
142
  const hb_set_t& parent_active_glyphs ()
143
0
  {
144
0
    if (!active_glyphs_stack)
145
0
      return *glyphs;
146
147
0
    return active_glyphs_stack.tail ();
148
0
  }
149
150
  hb_set_t* push_cur_active_glyphs ()
151
0
  {
152
0
    hb_set_t *s = active_glyphs_stack.push ();
153
0
    if (unlikely (active_glyphs_stack.in_error ()))
154
0
      return nullptr;
155
0
    return s;
156
0
  }
157
158
  bool pop_cur_done_glyphs ()
159
0
  {
160
0
    if (!active_glyphs_stack)
161
0
      return false;
162
163
0
    active_glyphs_stack.pop ();
164
0
    return true;
165
0
  }
166
167
  hb_face_t *face;
168
  hb_set_t *glyphs;
169
  hb_set_t output[1];
170
  hb_vector_t<hb_set_t> active_glyphs_stack;
171
  recurse_func_t recurse_func = nullptr;
172
  unsigned int nesting_level_left;
173
174
  hb_closure_context_t (hb_face_t *face_,
175
      hb_set_t *glyphs_,
176
      hb_map_t *done_lookups_glyph_count_,
177
      hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *done_lookups_glyph_set_,
178
      unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
179
0
        face (face_),
180
0
        glyphs (glyphs_),
181
0
        nesting_level_left (nesting_level_left_),
182
0
        done_lookups_glyph_count (done_lookups_glyph_count_),
183
0
        done_lookups_glyph_set (done_lookups_glyph_set_)
184
0
  {}
185
186
0
  ~hb_closure_context_t () { flush (); }
187
188
0
  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
189
190
  void flush ()
191
0
  {
192
0
    output->del_range (face->get_num_glyphs (), HB_SET_VALUE_INVALID);  /* Remove invalid glyphs. */
193
0
    glyphs->union_ (*output);
194
0
    output->clear ();
195
0
    active_glyphs_stack.pop ();
196
0
    active_glyphs_stack.reset ();
197
0
  }
198
199
  private:
200
  hb_map_t *done_lookups_glyph_count;
201
  hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *done_lookups_glyph_set;
202
  unsigned int lookup_count = 0;
203
};
204
205
206
207
struct hb_closure_lookups_context_t :
208
       hb_dispatch_context_t<hb_closure_lookups_context_t>
209
{
210
  typedef return_t (*recurse_func_t) (hb_closure_lookups_context_t *c, unsigned lookup_index);
211
  template <typename T>
212
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&)
213
0
  static return_t default_return_value () { return hb_empty_t (); }
214
  void recurse (unsigned lookup_index)
215
0
  {
216
0
    if (unlikely (nesting_level_left == 0 || !recurse_func))
217
0
      return;
218
219
    /* Return if new lookup was recursed to before. */
220
0
    if (lookup_limit_exceeded ()
221
0
        || visited_lookups->in_error ()
222
0
        || visited_lookups->has (lookup_index))
223
      // Don't increment lookup count here, that will be done in the call to closure_lookups()
224
      // made by recurse_func.
225
0
      return;
226
227
0
    nesting_level_left--;
228
0
    recurse_func (this, lookup_index);
229
0
    nesting_level_left++;
230
0
  }
231
232
  void set_lookup_visited (unsigned lookup_index)
233
0
  { visited_lookups->add (lookup_index); }
234
235
  void set_lookup_inactive (unsigned lookup_index)
236
0
  { inactive_lookups->add (lookup_index); }
237
238
  bool lookup_limit_exceeded ()
239
0
  {
240
0
    bool ret = lookup_count > HB_MAX_LOOKUP_VISIT_COUNT;
241
0
    if (ret)
242
0
      DEBUG_MSG (SUBSET, nullptr, "lookup visit count limit exceeded in lookup closure!");
243
0
    return ret; }
244
245
  bool is_lookup_visited (unsigned lookup_index)
246
0
  {
247
0
    if (unlikely (lookup_count++ > HB_MAX_LOOKUP_VISIT_COUNT))
248
0
    {
249
0
      DEBUG_MSG (SUBSET, nullptr, "total visited lookup count %u exceeds max limit, lookup %u is dropped.",
250
0
                 lookup_count, lookup_index);
251
0
      return true;
252
0
    }
253
254
0
    if (unlikely (visited_lookups->in_error ()))
255
0
      return true;
256
257
0
    return visited_lookups->has (lookup_index);
258
0
  }
259
260
  hb_face_t *face;
261
  const hb_set_t *glyphs;
262
  recurse_func_t recurse_func;
263
  unsigned int nesting_level_left;
264
265
  hb_closure_lookups_context_t (hb_face_t *face_,
266
        const hb_set_t *glyphs_,
267
        hb_set_t *visited_lookups_,
268
        hb_set_t *inactive_lookups_,
269
        unsigned nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
270
0
        face (face_),
271
0
        glyphs (glyphs_),
272
0
        recurse_func (nullptr),
273
0
        nesting_level_left (nesting_level_left_),
274
0
        visited_lookups (visited_lookups_),
275
0
        inactive_lookups (inactive_lookups_),
276
0
        lookup_count (0) {}
277
278
0
  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
279
280
  private:
281
  hb_set_t *visited_lookups;
282
  hb_set_t *inactive_lookups;
283
  unsigned int lookup_count;
284
};
285
286
struct hb_would_apply_context_t :
287
       hb_dispatch_context_t<hb_would_apply_context_t, bool>
288
{
289
  template <typename T>
290
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&)
291
0
  static return_t default_return_value () { return false; }
292
0
  bool stop_sublookup_iteration (return_t r) const { return r; }
293
294
  hb_face_t *face;
295
  const hb_codepoint_t *glyphs;
296
  unsigned int len;
297
  bool zero_context;
298
299
  hb_would_apply_context_t (hb_face_t *face_,
300
          const hb_codepoint_t *glyphs_,
301
          unsigned int len_,
302
          bool zero_context_) :
303
0
            face (face_),
304
0
            glyphs (glyphs_),
305
0
            len (len_),
306
0
            zero_context (zero_context_) {}
307
};
308
309
struct hb_collect_glyphs_context_t :
310
       hb_dispatch_context_t<hb_collect_glyphs_context_t>
311
{
312
  typedef return_t (*recurse_func_t) (hb_collect_glyphs_context_t *c, unsigned int lookup_index);
313
  template <typename T>
314
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&)
315
0
  static return_t default_return_value () { return hb_empty_t (); }
316
  void recurse (unsigned int lookup_index)
317
0
  {
318
0
    if (unlikely (nesting_level_left == 0 || !recurse_func))
319
0
      return;
320
321
    /* Note that GPOS sets recurse_func to nullptr already, so it doesn't get
322
     * past the previous check.  For GSUB, we only want to collect the output
323
     * glyphs in the recursion.  If output is not requested, we can go home now.
324
     *
325
     * Note further, that the above is not exactly correct.  A recursed lookup
326
     * is allowed to match input that is not matched in the context, but that's
327
     * not how most fonts are built.  It's possible to relax that and recurse
328
     * with all sets here if it proves to be an issue.
329
     */
330
331
0
    if (output == hb_set_get_empty ())
332
0
      return;
333
334
    /* Return if new lookup was recursed to before. */
335
0
    if (recursed_lookups->has (lookup_index))
336
0
      return;
337
338
0
    hb_set_t *old_before = before;
339
0
    hb_set_t *old_input  = input;
340
0
    hb_set_t *old_after  = after;
341
0
    before = input = after = hb_set_get_empty ();
342
343
0
    nesting_level_left--;
344
0
    recurse_func (this, lookup_index);
345
0
    nesting_level_left++;
346
347
0
    before = old_before;
348
0
    input  = old_input;
349
0
    after  = old_after;
350
351
0
    recursed_lookups->add (lookup_index);
352
0
  }
353
354
  hb_face_t *face;
355
  hb_set_t *before;
356
  hb_set_t *input;
357
  hb_set_t *after;
358
  hb_set_t *output;
359
  recurse_func_t recurse_func;
360
  hb_set_t *recursed_lookups;
361
  unsigned int nesting_level_left;
362
363
  hb_collect_glyphs_context_t (hb_face_t *face_,
364
             hb_set_t  *glyphs_before, /* OUT.  May be NULL */
365
             hb_set_t  *glyphs_input,  /* OUT.  May be NULL */
366
             hb_set_t  *glyphs_after,  /* OUT.  May be NULL */
367
             hb_set_t  *glyphs_output, /* OUT.  May be NULL */
368
             unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
369
0
            face (face_),
370
0
            before (glyphs_before ? glyphs_before : hb_set_get_empty ()),
371
0
            input  (glyphs_input  ? glyphs_input  : hb_set_get_empty ()),
372
0
            after  (glyphs_after  ? glyphs_after  : hb_set_get_empty ()),
373
0
            output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
374
0
            recurse_func (nullptr),
375
0
            recursed_lookups (hb_set_create ()),
376
0
            nesting_level_left (nesting_level_left_) {}
377
0
  ~hb_collect_glyphs_context_t () { hb_set_destroy (recursed_lookups); }
378
379
0
  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
380
};
381
382
struct hb_depend_context_t :
383
       hb_dispatch_context_t<hb_depend_context_t>
384
{
385
  enum glyph_set_type_t
386
  {
387
    GLYPH_SET_CLASS,
388
    GLYPH_SET_COVERAGE,
389
    GLYPH_SET_SINGLE
390
  };
391
392
  static constexpr hb_codepoint_t SINGLE_GLYPH_ACTIVE_FLAG = 0x80000000u;
393
394
  struct glyph_set_cache_key_t
395
  {
396
    glyph_set_cache_key_t () = default;
397
    glyph_set_cache_key_t (const void *data_, unsigned value_, glyph_set_type_t type_)
398
0
      : data (data_), value (value_), type (type_) {}
399
400
    bool operator == (const glyph_set_cache_key_t &o) const
401
0
    { return data == o.data && value == o.value && type == o.type; }
402
403
    uint32_t hash () const
404
0
    {
405
0
      uint32_t current = hb_hash ((uintptr_t) data);
406
0
      current = current * 31 + hb_hash (value);
407
0
      return current * 31 + hb_hash ((unsigned) type);
408
0
    }
409
410
    const void *data = nullptr;
411
    unsigned value = 0;
412
    glyph_set_type_t type = GLYPH_SET_CLASS;
413
  };
414
415
  struct context_set_cache_key_t
416
  {
417
    context_set_cache_key_t () = default;
418
    context_set_cache_key_t (const void *rule_,
419
           const void *record_,
420
           const void *data_,
421
           hb_codepoint_t active_glyphs_,
422
           unsigned value_,
423
           unsigned format_)
424
      : rule (rule_), record (record_), data (data_), active_glyphs (active_glyphs_),
425
0
  value (value_), format (format_) {}
426
427
    bool operator == (const context_set_cache_key_t &o) const
428
0
    {
429
0
      return rule == o.rule &&
430
0
       record == o.record &&
431
0
       data == o.data &&
432
0
       active_glyphs == o.active_glyphs &&
433
0
       value == o.value &&
434
0
       format == o.format;
435
0
    }
436
437
    uint32_t hash () const
438
0
    {
439
0
      uint32_t current = hb_hash ((uintptr_t) rule);
440
0
      current = current * 31 + hb_hash ((uintptr_t) record);
441
0
      current = current * 31 + hb_hash ((uintptr_t) data);
442
0
      current = current * 31 + hb_hash (active_glyphs);
443
0
      current = current * 31 + hb_hash (value);
444
0
      return current * 31 + hb_hash (format);
445
0
    }
446
447
    const void *rule = nullptr;
448
    const void *record = nullptr;
449
    const void *data = nullptr;
450
    hb_codepoint_t active_glyphs = HB_CODEPOINT_INVALID;
451
    unsigned value = 0;
452
    unsigned format = 0;
453
  };
454
455
  struct recurse_key_t
456
  {
457
    recurse_key_t () = default;
458
    recurse_key_t (unsigned lookup_index_,
459
                   hb_codepoint_t active_glyphs_,
460
                   hb_codepoint_t recurse_path_,
461
                   hb_codepoint_t context_set_)
462
      : lookup_index (lookup_index_),
463
        active_glyphs (active_glyphs_),
464
        recurse_path (recurse_path_),
465
0
        context_set (context_set_) {}
466
467
    bool operator == (const recurse_key_t &o) const
468
0
    {
469
0
      return lookup_index == o.lookup_index &&
470
0
             active_glyphs == o.active_glyphs &&
471
0
             recurse_path == o.recurse_path &&
472
0
             context_set == o.context_set;
473
0
    }
474
475
    uint32_t hash () const
476
0
    {
477
0
      uint32_t current = 0x84222325;
478
0
      current = (current ^ hb_hash (lookup_index)) * 16777619;
479
0
      current = (current ^ hb_hash (active_glyphs)) * 16777619;
480
0
      current = (current ^ hb_hash (recurse_path)) * 16777619;
481
0
      current = (current ^ hb_hash (context_set)) * 16777619;
482
0
      return current;
483
0
    }
484
485
    unsigned lookup_index = 0;
486
    hb_codepoint_t active_glyphs = 0;
487
    hb_codepoint_t recurse_path = 0;
488
    hb_codepoint_t context_set = HB_CODEPOINT_INVALID;
489
  };
490
491
  typedef return_t (*recurse_func_t) (hb_depend_context_t *c, unsigned lookup_index, hb_bit_page_t *covered_seq_indices, unsigned seq_index, unsigned end_index);
492
  /* return_t is hb_empty_t — dispatch is purely for side-effects, like hb_closure_context_t. */
493
  template <typename T>
494
0
  return_t dispatch (const T &obj) { obj.depend (this); return hb_empty_t (); }
Unexecuted instantiation: hb_empty_t OT::hb_depend_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_depend_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_depend_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_depend_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_depend_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_depend_context_t::dispatch<OT::ContextFormat1_4<OT::Layout::SmallTypes> >(OT::ContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_depend_context_t::dispatch<OT::ContextFormat2_5<OT::Layout::SmallTypes> >(OT::ContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_depend_context_t::dispatch<OT::ContextFormat3>(OT::ContextFormat3 const&)
Unexecuted instantiation: hb_empty_t OT::hb_depend_context_t::dispatch<OT::ChainContextFormat1_4<OT::Layout::SmallTypes> >(OT::ChainContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_depend_context_t::dispatch<OT::ChainContextFormat2_5<OT::Layout::SmallTypes> >(OT::ChainContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_depend_context_t::dispatch<OT::ChainContextFormat3>(OT::ChainContextFormat3 const&)
Unexecuted instantiation: hb_empty_t OT::hb_depend_context_t::dispatch<OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1>(OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1 const&)
495
0
  static return_t default_return_value () { return hb_empty_t (); }
496
497
  void recurse (unsigned lookup_idx, hb_bit_page_t *covered_seq_indices, unsigned seq_index, unsigned end_index)
498
0
  {
499
0
    /* Cycle detection using call-stack semantics: block re-entry of a
500
0
     * lookup that is currently on the execution stack, but allow it again
501
0
     * once it has returned.
502
0
     *
503
0
     * A flat "visited" set would be wrong: the same lookup legitimately
504
0
     * appears more than once when a rule iterates over multiple sequence
505
0
     * positions — each such call is independent and must be processed.
506
0
     *
507
0
     * Cutting an in-progress cycle is safe because the active glyph set
508
0
     * can only stay the same or shrink as we recurse.  If we re-encounter
509
0
     * lookup L while it is still on the stack, L is already executing
510
0
     * with a context at least as broad, so any edges a re-entry would add
511
0
     * are a subset of what L is already in the process of registering.
512
0
     *
513
0
     * lookups_seen is pre-seeded with the top-level lookup index in
514
0
     * GSUB_accelerator_t::depend before the direct depend() call, so
515
0
     * that indirect cycles of the form A→B→A are also caught here. */
516
0
    if (lookups_seen.has (lookup_idx)) return;
517
0
    lookups_seen.add (lookup_idx);
518
0
519
0
    /* Intern the ordered recursion path instead of copying and interning the
520
0
     * lookups_seen set.  Path identity is more specific than set identity but
521
0
     * never merges states with different cycle-detection behavior. */
522
0
    hb_codepoint_t parent_path = recurse_path;
523
0
    uint64_t path_key = (uint64_t) parent_path << 32 | lookup_idx;
524
0
    hb_codepoint_t *path = nullptr;
525
0
    hb_codepoint_t path_index;
526
0
    if (!recurse_path_to_index.has (path_key, &path))
527
0
    {
528
0
      path_index = recurse_path_to_index.get_population () + 1;
529
0
      if (unlikely (!recurse_path_to_index.set (path_key, path_index)))
530
0
      {
531
0
  depend_data->fail ();
532
0
  lookups_seen.del (lookup_idx);
533
0
  return;
534
0
      }
535
0
    }
536
0
    else
537
0
      path_index = *path;
538
0
    recurse_path = path_index;
539
0
    recurse_func (this, lookup_idx, covered_seq_indices, seq_index, end_index);
540
0
    recurse_path = parent_path;
541
0
    lookups_seen.del (lookup_idx);
542
0
  }
543
544
  struct active_glyphs_frame_t
545
  {
546
    hb_set_t glyphs;
547
    hb_codepoint_t active_idx = HB_CODEPOINT_INVALID;
548
    bool use_root = false;
549
  };
550
551
  const hb_set_t& parent_active_glyphs ()
552
0
  {
553
0
    if (!active_glyphs_stack_depth)
554
0
      return *glyphs;
555
0
556
0
    const active_glyphs_frame_t &frame = active_glyphs_stack[active_glyphs_stack_depth - 1];
557
0
    return frame.use_root ? *glyphs : frame.glyphs;
558
0
  }
559
560
  hb_set_t* push_cur_active_glyphs (hb_codepoint_t active_idx = HB_CODEPOINT_INVALID)
561
0
  {
562
0
    if (active_glyphs_stack_depth == active_glyphs_stack.length &&
563
0
  unlikely (!active_glyphs_stack.push_or_fail ()))
564
0
      return nullptr;
565
0
566
0
    active_glyphs_frame_t &frame = active_glyphs_stack[active_glyphs_stack_depth++];
567
0
    frame.glyphs.clear ();
568
0
    frame.active_idx = active_idx;
569
0
    frame.use_root = false;
570
0
    return &frame.glyphs;
571
0
  }
572
573
  bool push_root_active_glyphs ()
574
0
  {
575
0
    if (active_glyphs_stack_depth == active_glyphs_stack.length &&
576
0
  unlikely (!active_glyphs_stack.push_or_fail ()))
577
0
      return false;
578
0
579
0
    active_glyphs_stack[active_glyphs_stack_depth++].use_root = true;
580
0
    return true;
581
0
  }
582
583
  bool pop_cur_done_glyphs ()
584
0
  {
585
0
    if (!active_glyphs_stack_depth)
586
0
      return false;
587
0
588
0
    active_glyphs_stack_depth--;
589
0
    return true;
590
0
  }
591
592
  bool get_parent_active_glyphs_index (hb_codepoint_t *active_idx)
593
0
  {
594
0
    if (!active_glyphs_stack_depth ||
595
0
  active_glyphs_stack[active_glyphs_stack_depth - 1].use_root)
596
0
    {
597
0
      *active_idx = HB_CODEPOINT_INVALID;
598
0
      return true;
599
0
    }
600
0
601
0
    active_glyphs_frame_t &frame = active_glyphs_stack[active_glyphs_stack_depth - 1];
602
0
    *active_idx = frame.active_idx;
603
0
    if (*active_idx != HB_CODEPOINT_INVALID)
604
0
      return true;
605
0
606
0
    hb_codepoint_t glyph;
607
0
    if (frame.glyphs.get_singleton (&glyph) &&
608
0
  likely (glyph < SINGLE_GLYPH_ACTIVE_FLAG))
609
0
      *active_idx = glyph | SINGLE_GLYPH_ACTIVE_FLAG;
610
0
    else if (!find_or_create_recurse_set (frame.glyphs, active_idx))
611
0
      return false;
612
0
613
0
    frame.active_idx = *active_idx;
614
0
    return true;
615
0
  }
616
617
  bool get_context_set_cache_key (const void *rule,
618
          const void *record,
619
          const void *data,
620
          unsigned value,
621
          unsigned format,
622
          context_set_cache_key_t *key)
623
0
  {
624
0
    hb_codepoint_t active_idx;
625
0
    if (!get_parent_active_glyphs_index (&active_idx))
626
0
      return false;
627
0
    *key = context_set_cache_key_t (rule, record, data, active_idx, value, format);
628
0
    return true;
629
0
  }
630
631
  bool get_recurse_key (unsigned lookup_idx, recurse_key_t *key)
632
0
  {
633
0
    /* The active glyphs and in-progress lookup set are part of the state.
634
0
     * Omitting the latter would make memoization incorrect for cyclic lookup
635
0
     * graphs whose available recursive paths depend on their ancestry.
636
0
     * Edge flags are not part of the state: they affect neither traversal nor
637
0
     * edge identity, so revisiting with different flags can only find edges
638
0
     * that the deduplication table already contains. */
639
0
    hb_codepoint_t active_idx;
640
0
    if (!get_parent_active_glyphs_index (&active_idx))
641
0
      return false;
642
0
643
0
    *key = recurse_key_t (lookup_idx,
644
0
                          active_idx,
645
0
                          recurse_path,
646
0
                          depend_data->current_context_set_index);
647
0
    return !completed_recursions.has (*key);
648
0
  }
649
650
  void finish_recurse (const recurse_key_t &key)
651
0
  { depend_data->check_success (completed_recursions.set (key, true)); }
652
653
  void reset_recurse_cache ()
654
0
  {
655
0
    completed_recursions.clear ();
656
0
    recurse_path_to_index.clear ();
657
0
    recurse_path = 0;
658
0
  }
659
660
  bool find_or_create_recurse_set (const hb_set_t &set, hb_codepoint_t *index)
661
0
  {
662
0
    hb_codepoint_t *existing = nullptr;
663
0
    if (recurse_set_to_index.has (&set, &existing))
664
0
    {
665
0
      *index = *existing;
666
0
      return true;
667
0
    }
668
0
669
0
    hb_set_t *copy = hb_object_create<hb_set_t> ();
670
0
    if (unlikely (!copy))
671
0
      return depend_data->fail ();
672
0
    copy->set (set);
673
0
    if (unlikely (copy->in_error ()))
674
0
    {
675
0
      hb_set_destroy (copy);
676
0
      return depend_data->fail ();
677
0
    }
678
0
679
0
    *index = recurse_sets.length;
680
0
    if (unlikely (*index & SINGLE_GLYPH_ACTIVE_FLAG))
681
0
    {
682
0
      hb_set_destroy (copy);
683
0
      return depend_data->fail ();
684
0
    }
685
0
    if (unlikely (!recurse_sets.push_or_fail (hb::unique_ptr<hb_set_t> {copy})))
686
0
      return depend_data->fail ();
687
0
    if (unlikely (!recurse_set_to_index.set (recurse_sets[*index].get (), *index)))
688
0
      return depend_data->fail ();
689
0
    return true;
690
0
  }
691
692
  const hb_set_t *find_or_create_glyph_set (const void *data,
693
                                             unsigned value,
694
                                             glyph_set_type_t type);
695
  hb_codepoint_t find_or_create_cached_context_set (const hb_set_t *set);
696
697
  struct depend_scratch_t
698
  {
699
    void clear ()
700
0
    {
701
0
      preliminary_context.clear ();
702
0
      position_scratch.clear ();
703
0
      pos_glyphs.clear ();
704
0
      position_context.clear ();
705
0
      disjunctive_indices.clear ();
706
0
      filtered_disjunctive_indices.clear ();
707
0
      backtrack_sets.clear ();
708
0
      lookahead_sets.clear ();
709
0
      input_position_glyphs.clear ();
710
0
      cached_context_sets.clear ();
711
0
      compact_workspace.clear ();
712
0
    }
713
714
    hb_set_t preliminary_context;
715
    hb_set_t position_scratch;
716
    hb_set_t pos_glyphs;
717
    hb_set_t position_context;
718
    hb_set_t disjunctive_indices;
719
    hb_set_t filtered_disjunctive_indices;
720
    hb_vector_t<const hb_set_t *> backtrack_sets;
721
    hb_vector_t<const hb_set_t *> lookahead_sets;
722
    hb_vector_t<const hb_set_t *> input_position_glyphs;
723
    hb_vector_t<hb_codepoint_t> cached_context_sets;
724
    hb_vector_t<unsigned> compact_workspace;
725
    depend_scratch_t *next = nullptr;
726
  };
727
728
  depend_scratch_t *acquire_depend_scratch ()
729
0
  {
730
0
    depend_scratch_t *scratch = depend_scratch_pool;
731
0
    if (scratch)
732
0
      depend_scratch_pool = scratch->next;
733
0
    else
734
0
    {
735
0
      scratch = (depend_scratch_t *) hb_malloc (sizeof (depend_scratch_t));
736
0
      if (unlikely (!scratch))
737
0
      {
738
0
        depend_data->fail ();
739
0
        return nullptr;
740
0
      }
741
0
      new (scratch) depend_scratch_t ();
742
0
    }
743
0
744
0
    scratch->next = nullptr;
745
0
    scratch->clear ();
746
0
    return scratch;
747
0
  }
748
749
  void release_depend_scratch (depend_scratch_t *scratch)
750
0
  {
751
0
    scratch->next = depend_scratch_pool;
752
0
    depend_scratch_pool = scratch;
753
0
  }
754
755
  hb_depend_data_builder_t *depend_data;
756
  hb_face_t *face;
757
  hb_set_t *glyphs;
758
  hb_vector_t<active_glyphs_frame_t> active_glyphs_stack;
759
  unsigned active_glyphs_stack_depth = 0;
760
  recurse_func_t recurse_func;
761
  hb_codepoint_t lookup_index = HB_CODEPOINT_INVALID;
762
  hb_bit_set_t lookups_seen;
763
  hb_vector_t<hb::unique_ptr<hb_set_t>> recurse_sets;
764
  hb_hashmap_t<const hb_set_t *, hb_codepoint_t> recurse_set_to_index;
765
  hb_hashmap_t<uint64_t, hb_codepoint_t> recurse_path_to_index;
766
  hb_codepoint_t recurse_path = 0;
767
  hb_hashmap_t<recurse_key_t, bool> completed_recursions;
768
  hb_vector_t<hb::unique_ptr<hb_set_t>> glyph_sets;
769
  hb_hashmap_t<glyph_set_cache_key_t, hb_codepoint_t> glyph_set_to_index;
770
  hb_hashmap_t<uintptr_t, hb_codepoint_t> cached_context_set_indices;
771
  hb_hashmap_t<context_set_cache_key_t, hb_codepoint_t> context_set_cache;
772
  depend_scratch_t *depend_scratch_pool = nullptr;
773
774
  hb_depend_context_t (hb_depend_data_builder_t *depend_data_,
775
                       hb_face_t *face_,
776
                       hb_set_t *glyphs_)
777
                      : depend_data (depend_data_),
778
                        face(face_),
779
                        glyphs (glyphs_),
780
0
                        recurse_func (nullptr) {}
781
  ~hb_depend_context_t ()
782
0
  {
783
0
    while (depend_scratch_pool)
784
0
    {
785
0
      depend_scratch_t *scratch = depend_scratch_pool;
786
0
      depend_scratch_pool = scratch->next;
787
0
      scratch->~depend_scratch_t ();
788
0
      hb_free (scratch);
789
0
    }
790
0
  }
791
0
  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
792
};
793
794
template <typename set_t>
795
struct hb_collect_coverage_context_t :
796
       hb_dispatch_context_t<hb_collect_coverage_context_t<set_t>, const Coverage &>
797
{
798
  typedef const Coverage &return_t; // Stoopid that we have to dupe this here.
799
  template <typename T>
800
  return_t dispatch (const T &obj) { return obj.get_coverage (); }
801
  static return_t default_return_value () { return Null (Coverage); }
802
  bool stop_sublookup_iteration (return_t r) const
803
  {
804
    r.collect_coverage (set);
805
    return false;
806
  }
807
808
  hb_collect_coverage_context_t (set_t *set_) :
809
           set (set_) {}
810
811
  set_t *set;
812
};
813
814
struct matcher_t
815
{
816
  typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data);
817
818
  template <typename context_t>
819
  void init (const context_t *c, bool context_match = false)
820
65.9M
  {
821
65.9M
    set_match_func (nullptr, nullptr);
822
65.9M
    lookup_props = c->lookup_props;
823
    /* Ignore ZWNJ if we are matching GPOS, or matching GSUB context and asked to. */
824
65.9M
    ignore_zwnj = c->table_index == 1 || (context_match && c->auto_zwnj);
825
    /* Ignore ZWJ if we are matching context, or asked to. */
826
65.9M
    ignore_zwj = context_match || c->auto_zwj;
827
    /* Ignore hidden glyphs (like CGJ) during GPOS. */
828
65.9M
    ignore_hidden = c->table_index == 1;
829
65.9M
    mask = context_match ? -1 : c->lookup_mask;
830
    /* Per syllable matching is only for GSUB. */
831
65.9M
    per_syllable = c->table_index == 0 && c->per_syllable;
832
65.9M
    syllable = 0;
833
65.9M
  }
834
835
  void set_match_func (match_func_t match_func_,
836
           const void *match_data_)
837
66.3M
  { match_func = match_func_; match_data = match_data_; }
838
839
  enum may_match_t {
840
    MATCH_NO,
841
    MATCH_YES,
842
    MATCH_MAYBE
843
  };
844
845
#ifndef HB_OPTIMIZE_SIZE
846
  HB_ALWAYS_INLINE
847
#endif
848
  may_match_t may_match (hb_glyph_info_t &info,
849
       hb_codepoint_t glyph_data) const
850
20.8M
  {
851
20.8M
    if (!(info.mask & mask) ||
852
20.8M
  (per_syllable && syllable && syllable != info.syllable ()))
853
0
      return MATCH_NO;
854
855
20.8M
    if (match_func)
856
272k
      return match_func (info, glyph_data, match_data) ? MATCH_YES : MATCH_NO;
857
858
20.5M
    return MATCH_MAYBE;
859
20.8M
  }
860
861
  enum may_skip_t {
862
    SKIP_NO,
863
    SKIP_YES,
864
    SKIP_MAYBE
865
  };
866
867
  template <typename context_t>
868
#ifndef HB_OPTIMIZE_SIZE
869
  HB_ALWAYS_INLINE
870
#endif
871
  may_skip_t may_skip (const context_t *c,
872
           const hb_glyph_info_t &info) const
873
20.8M
  {
874
20.8M
    if (!c->check_glyph_property (&info, lookup_props))
875
14.3k
      return SKIP_YES;
876
877
20.8M
    if (unlikely (_hb_glyph_info_is_default_ignorable (&info) &&
878
20.8M
      (ignore_zwnj || !_hb_glyph_info_is_zwnj (&info)) &&
879
20.8M
      (ignore_zwj || !_hb_glyph_info_is_zwj (&info)) &&
880
20.8M
      (ignore_hidden || !_hb_glyph_info_is_hidden (&info))))
881
5.66k
      return SKIP_MAYBE;
882
883
20.8M
    return SKIP_NO;
884
20.8M
  }
885
886
  public:
887
  unsigned int lookup_props = 0;
888
  hb_mask_t mask = -1;
889
  bool ignore_zwnj = false;
890
  bool ignore_zwj = false;
891
  bool ignore_hidden = false;
892
  bool per_syllable = false;
893
  uint8_t syllable = 0;
894
  match_func_t match_func = nullptr;
895
  const void *match_data = nullptr;
896
};
897
898
template <typename context_t>
899
struct skipping_iterator_t
900
{
901
  void init (context_t *c_, bool context_match = false)
902
65.9M
  {
903
65.9M
    c = c_;
904
65.9M
    end = c->buffer->len;
905
65.9M
    match_glyph_data16 = nullptr;
906
#ifndef HB_NO_BEYOND_64K
907
    match_glyph_data24 = nullptr;
908
#endif
909
65.9M
    matcher.init (c, context_match);
910
65.9M
  }
911
  void set_lookup_props (unsigned int lookup_props)
912
369k
  {
913
369k
    matcher.lookup_props = lookup_props;
914
369k
  }
915
  void set_match_func (matcher_t::match_func_t match_func_,
916
           const void *match_data_)
917
420k
  {
918
420k
    matcher.set_match_func (match_func_, match_data_);
919
420k
  }
920
  void set_glyph_data (const HBUINT16 glyph_data[])
921
420k
  {
922
420k
    match_glyph_data16 = glyph_data;
923
#ifndef HB_NO_BEYOND_64K
924
    match_glyph_data24 = nullptr;
925
#endif
926
420k
  }
927
#ifndef HB_NO_BEYOND_64K
928
  void set_glyph_data (const HBUINT24 glyph_data[])
929
  {
930
    match_glyph_data16 = nullptr;
931
    match_glyph_data24 = glyph_data;
932
  }
933
#endif
934
935
#ifndef HB_OPTIMIZE_SIZE
936
  HB_ALWAYS_INLINE
937
#endif
938
  void reset (unsigned int start_index_)
939
285k
  {
940
    // For GSUB forward iterator
941
285k
    idx = start_index_;
942
285k
    end = c->buffer->len;
943
285k
    matcher.syllable = c->buffer->cur().syllable();
944
285k
  }
945
  void reset_back (unsigned int start_index_, bool from_out_buffer = false)
946
135k
  {
947
    // For GSUB backward iterator
948
135k
    idx = start_index_;
949
135k
    matcher.syllable = c->buffer->cur().syllable();
950
135k
  }
951
952
#ifndef HB_OPTIMIZE_SIZE
953
  HB_ALWAYS_INLINE
954
#endif
955
  void reset_fast (unsigned int start_index_)
956
21.3M
  {
957
    // Doesn't set end or syllable. Used by GPOS which doesn't care / change.
958
21.3M
    idx = start_index_;
959
21.3M
  }
960
961
#ifndef HB_OPTIMIZE_SIZE
962
  HB_ALWAYS_INLINE
963
#endif
964
  matcher_t::may_skip_t may_skip (const hb_glyph_info_t &info) const
965
28.5k
  { return matcher.may_skip (c, info); }
966
967
  enum match_t {
968
    MATCH,
969
    NOT_MATCH,
970
    SKIP
971
  };
972
973
#ifndef HB_OPTIMIZE_SIZE
974
  HB_ALWAYS_INLINE
975
#endif
976
  match_t match (hb_glyph_info_t &info)
977
20.8M
  {
978
20.8M
    matcher_t::may_skip_t skip = matcher.may_skip (c, info);
979
20.8M
    if (unlikely (skip == matcher_t::SKIP_YES))
980
14.3k
      return SKIP;
981
982
20.8M
    matcher_t::may_match_t match = matcher.may_match (info, get_glyph_data ());
983
20.8M
    if (match == matcher_t::MATCH_YES ||
984
20.7M
  (match == matcher_t::MATCH_MAYBE &&
985
20.5M
   skip == matcher_t::SKIP_NO))
986
20.6M
      return MATCH;
987
988
197k
    if (skip == matcher_t::SKIP_NO)
989
191k
      return NOT_MATCH;
990
991
5.63k
    return SKIP;
992
197k
  }
993
994
  bool next (unsigned *unsafe_to = nullptr)
995
21.4M
  {
996
21.4M
    auto *info = c->buffer->info;
997
21.4M
    const signed stop = (signed) end - 1;
998
21.4M
    while ((signed) idx < stop)
999
20.4M
    {
1000
20.4M
      idx++;
1001
20.4M
      switch (match (info[idx]))
1002
20.4M
      {
1003
20.2M
  case MATCH:
1004
20.2M
  {
1005
20.2M
    advance_glyph_data ();
1006
20.2M
    return true;
1007
0
  }
1008
108k
  case NOT_MATCH:
1009
108k
  {
1010
108k
    if (unsafe_to)
1011
108k
      *unsafe_to = idx + 1;
1012
108k
    return false;
1013
0
  }
1014
6.67k
  case SKIP:
1015
6.67k
    continue;
1016
20.4M
      }
1017
20.4M
    }
1018
1.03M
    if (unsafe_to)
1019
1.03M
      *unsafe_to = end;
1020
1.03M
    return false;
1021
21.4M
  }
1022
  bool prev (unsigned *unsafe_from = nullptr)
1023
325k
  {
1024
325k
    auto *out_info = c->buffer->out_info;
1025
325k
    const unsigned stop = 0;
1026
325k
    while (idx > stop)
1027
262k
    {
1028
262k
      idx--;
1029
262k
      switch (match (out_info[idx]))
1030
262k
      {
1031
179k
  case MATCH:
1032
179k
  {
1033
179k
    advance_glyph_data ();
1034
179k
    return true;
1035
0
  }
1036
82.9k
  case NOT_MATCH:
1037
82.9k
  {
1038
82.9k
    if (unsafe_from)
1039
82.9k
      *unsafe_from = hb_max (1u, idx) - 1u;
1040
82.9k
    return false;
1041
0
  }
1042
97
  case SKIP:
1043
97
    continue;
1044
262k
      }
1045
262k
    }
1046
62.9k
    if (unsafe_from)
1047
62.9k
      *unsafe_from = 0;
1048
62.9k
    return false;
1049
325k
  }
1050
1051
  HB_ALWAYS_INLINE
1052
  hb_codepoint_t
1053
  get_glyph_data ()
1054
20.8M
  {
1055
20.8M
    if (match_glyph_data16) return *match_glyph_data16;
1056
#ifndef HB_NO_BEYOND_64K
1057
    else
1058
    if (match_glyph_data24) return *match_glyph_data24;
1059
#endif
1060
20.5M
    return 0;
1061
20.8M
  }
1062
  HB_ALWAYS_INLINE
1063
  void
1064
  advance_glyph_data ()
1065
20.4M
  {
1066
20.4M
    if (match_glyph_data16) match_glyph_data16++;
1067
#ifndef HB_NO_BEYOND_64K
1068
    else
1069
    if (match_glyph_data24) match_glyph_data24++;
1070
#endif
1071
20.4M
  }
1072
1073
  unsigned int idx;
1074
  protected:
1075
  context_t *c;
1076
  matcher_t matcher;
1077
  const HBUINT16 *match_glyph_data16;
1078
#ifndef HB_NO_BEYOND_64K
1079
  const HBUINT24 *match_glyph_data24;
1080
#endif
1081
1082
  unsigned int end;
1083
};
1084
1085
struct hb_ot_apply_context_t :
1086
       hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
1087
{
1088
0
  const char *get_name () { return "APPLY"; }
1089
  typedef return_t (*recurse_func_t) (hb_ot_apply_context_t *c, unsigned int lookup_index);
1090
1091
  template <typename T>
1092
  static inline auto apply_ (const T &obj, hb_ot_apply_context_t *c, hb_priority<1>) HB_RETURN (return_t, obj.apply (c, nullptr) )
1093
  template <typename T>
1094
  static inline auto apply_ (const T &obj, hb_ot_apply_context_t *c, hb_priority<0>) HB_RETURN (return_t, obj.apply (c) )
1095
  template <typename T>
1096
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&)
1097
1098
0
  static return_t default_return_value () { return false; }
1099
0
  bool stop_sublookup_iteration (return_t r) const { return r; }
1100
  return_t recurse (unsigned int sub_lookup_index)
1101
373
  {
1102
373
    assert (recurse_func);
1103
373
    if (unlikely (nesting_level_left == 0))
1104
0
    {
1105
0
      buffer->successful = false;
1106
0
      return default_return_value ();
1107
0
    }
1108
1109
373
    buffer->max_ops--;
1110
373
    if (unlikely (buffer->max_ops < 0))
1111
0
    {
1112
0
      buffer->successful = false;
1113
0
      return default_return_value ();
1114
0
    }
1115
1116
373
    nesting_level_left--;
1117
373
    bool ret = recurse_func (this, sub_lookup_index);
1118
373
    nesting_level_left++;
1119
373
    return ret;
1120
373
  }
1121
1122
  skipping_iterator_t<hb_ot_apply_context_t> iter_input, iter_context;
1123
1124
  unsigned int table_index; /* GSUB/GPOS */
1125
  hb_font_t *font;
1126
  hb_face_t *face;
1127
  hb_buffer_t *buffer;
1128
  hb_sanitize_context_t sanitizer;
1129
  recurse_func_t recurse_func = nullptr;
1130
  const GDEF &gdef;
1131
  const GDEF::accelerator_t &gdef_accel;
1132
  const ItemVariationStore &var_store;
1133
  hb_scalar_cache_t *var_store_cache;
1134
1135
  hb_direction_t direction;
1136
  hb_mask_t lookup_mask = 1;
1137
  unsigned int lookup_index = (unsigned) -1;
1138
  unsigned int lookup_props = 0;
1139
  unsigned int nesting_level_left = HB_MAX_NESTING_LEVEL;
1140
1141
  bool has_glyph_classes;
1142
  bool auto_zwnj = true;
1143
  bool auto_zwj = true;
1144
  bool per_syllable = false;
1145
  bool random = false;
1146
  unsigned new_syllables = (unsigned) -1;
1147
1148
  signed last_base = -1; // GPOS uses
1149
  unsigned last_base_until = 0; // GPOS uses
1150
1151
  hb_vector_t<uint32_t> match_positions;
1152
  uint32_t stack_match_positions[8];
1153
#ifndef HB_NO_BUFFER_MESSAGE
1154
  hb_buffer_t::changed_func_t orig_changed_func = nullptr;
1155
  void *orig_changed_data = nullptr;
1156
#endif
1157
1158
  hb_ot_apply_context_t (unsigned int table_index_,
1159
       hb_font_t *font_,
1160
       hb_buffer_t *buffer_,
1161
       hb_blob_t *table_blob_,
1162
       hb_scalar_cache_t *var_store_cache_ = nullptr) :
1163
28.5M
      table_index (table_index_),
1164
28.5M
      font (font_), face (font->face), buffer (buffer_),
1165
28.5M
      sanitizer (table_blob_),
1166
      gdef (
1167
#ifndef HB_NO_OT_LAYOUT
1168
28.5M
            *face->table.GDEF->table
1169
#else
1170
            Null (GDEF)
1171
#endif
1172
           ),
1173
      gdef_accel (
1174
#ifndef HB_NO_OT_LAYOUT
1175
28.5M
            *face->table.GDEF
1176
#else
1177
            Null (GDEF::accelerator_t)
1178
#endif
1179
           ),
1180
28.5M
      var_store (gdef.get_var_store ()),
1181
28.5M
      var_store_cache (var_store_cache_),
1182
28.5M
      direction (buffer_->props.direction),
1183
28.5M
      has_glyph_classes (gdef.has_glyph_classes ())
1184
28.5M
  {
1185
28.5M
    init_iters ();
1186
28.5M
    match_positions.set_storage (stack_match_positions);
1187
1188
28.5M
#ifndef HB_NO_BUFFER_MESSAGE
1189
28.5M
    if (buffer->messaging ())
1190
0
    {
1191
0
      assert (buffer->changed_func == nullptr ||
1192
0
        buffer->changed_func == buffer_changed_trampoline);
1193
0
      orig_changed_func = buffer->changed_func;
1194
0
      orig_changed_data = buffer->changed_data;
1195
0
      buffer->changed_func = buffer_changed_trampoline;
1196
0
      buffer->changed_data = this;
1197
0
    }
1198
28.5M
#endif
1199
28.5M
  }
1200
  ~hb_ot_apply_context_t ()
1201
28.5M
  {
1202
28.5M
#ifndef HB_NO_BUFFER_MESSAGE
1203
28.5M
    if (buffer->messaging ())
1204
0
    {
1205
0
      assert (buffer->changed_func == buffer_changed_trampoline);
1206
0
      assert (buffer->changed_data == this);
1207
0
      buffer->changed_func = orig_changed_func;
1208
0
      buffer->changed_data = orig_changed_data;
1209
0
    }
1210
28.5M
#endif
1211
28.5M
  }
1212
1213
  void init_iters ()
1214
32.9M
  {
1215
32.9M
    iter_input.init (this, false);
1216
32.9M
    iter_context.init (this, true);
1217
32.9M
  }
1218
1219
3.95M
  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 (); }
1220
3.55M
  void set_auto_zwj (bool auto_zwj_, bool init = true) { auto_zwj = auto_zwj_; if (init) init_iters (); }
1221
3.55M
  void set_auto_zwnj (bool auto_zwnj_, bool init = true) { auto_zwnj = auto_zwnj_; if (init) init_iters (); }
1222
3.55M
  void set_per_syllable (bool per_syllable_, bool init = true) { per_syllable = per_syllable_; if (init) init_iters (); }
1223
3.55M
  void set_random (bool random_) { random = random_; }
1224
27.9M
  void set_recurse_func (recurse_func_t func) { recurse_func = func; }
1225
3.55M
  void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
1226
  void set_lookup_props (unsigned int lookup_props_)
1227
3.95M
  {
1228
3.95M
    lookup_props = gdef_accel.sanitize_lookup_props (lookup_props_);
1229
3.95M
    init_iters ();
1230
3.95M
  }
1231
1232
  uint32_t random_number ()
1233
0
  {
1234
    /* http://www.cplusplus.com/reference/random/minstd_rand/ */
1235
0
    buffer->random_state = buffer->random_state * 48271 % 2147483647;
1236
0
    return buffer->random_state;
1237
0
  }
1238
1239
  static void buffer_changed_trampoline (hb_buffer_t *buffer HB_UNUSED, void *user_data)
1240
0
  {
1241
0
    ((hb_ot_apply_context_t *) user_data)->buffer_changed ();
1242
0
  }
1243
  void buffer_changed ()
1244
0
  {
1245
0
    buffer->update_digest ();
1246
0
    if (likely (has_glyph_classes))
1247
0
      for (unsigned i = 0; i < buffer->len; i++)
1248
0
  _set_glyph_class_props (buffer->info[i]);
1249
0
  }
1250
1251
  HB_ALWAYS_INLINE
1252
  HB_HOT
1253
  bool match_properties_mark (const hb_glyph_info_t *info,
1254
            unsigned int    glyph_props,
1255
            unsigned int    match_props) const
1256
228k
  {
1257
    /* If using mark filtering sets, the high short of
1258
     * match_props has the set index.
1259
     */
1260
228k
    if (match_props & LookupFlag::UseMarkFilteringSet)
1261
0
    {
1262
0
      unsigned set_index = match_props >> 16;
1263
0
      return gdef_accel.mark_set_covers (set_index, info->codepoint);
1264
0
    }
1265
1266
    /* The second byte of match_props has the meaning
1267
     * "ignore marks of attachment type different than
1268
     * the attachment type specified."
1269
     */
1270
228k
    if (match_props & LookupFlag::MarkAttachmentType)
1271
23
      return (match_props & LookupFlag::MarkAttachmentType) == (glyph_props & LookupFlag::MarkAttachmentType);
1272
1273
228k
    return true;
1274
228k
  }
1275
1276
#ifndef HB_OPTIMIZE_SIZE
1277
  HB_ALWAYS_INLINE
1278
#endif
1279
  bool check_glyph_property (const hb_glyph_info_t *info,
1280
           unsigned match_props) const
1281
171M
  {
1282
171M
    unsigned int glyph_props = _hb_glyph_info_get_glyph_props (info);
1283
1284
    /* Not covered, if, for example, glyph class is ligature and
1285
     * match_props includes LookupFlags::IgnoreLigatures
1286
     */
1287
171M
    if (glyph_props & match_props & LookupFlag::IgnoreFlags)
1288
14.3k
      return false;
1289
1290
171M
    if (glyph_props & HB_OT_LAYOUT_GLYPH_PROPS_MARK)
1291
228k
      return match_properties_mark (info, glyph_props, match_props);
1292
1293
171M
    return true;
1294
171M
  }
1295
1296
  void _set_glyph_class (hb_codepoint_t glyph_index,
1297
        unsigned int class_guess = 0,
1298
        bool ligature = false,
1299
        bool component = false)
1300
68
  {
1301
68
    buffer->digest.add (glyph_index);
1302
1303
68
    if (new_syllables != (unsigned) -1)
1304
0
      buffer->cur().syllable() = new_syllables;
1305
1306
68
    unsigned int props = _hb_glyph_info_get_glyph_props (&buffer->cur());
1307
68
    props |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
1308
68
    if (ligature)
1309
68
    {
1310
68
      props |= HB_OT_LAYOUT_GLYPH_PROPS_LIGATED;
1311
      /* In the only place that the MULTIPLIED bit is used, Uniscribe
1312
       * seems to only care about the "last" transformation between
1313
       * Ligature and Multiple substitutions.  Ie. if you ligate, expand,
1314
       * and ligate again, it forgives the multiplication and acts as
1315
       * if only ligation happened.  As such, clear MULTIPLIED bit.
1316
       */
1317
68
      props &= ~HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
1318
68
    }
1319
68
    if (component)
1320
0
      props |= HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED;
1321
68
    if (likely (has_glyph_classes))
1322
68
    {
1323
68
      _set_glyph_class_props (buffer->cur(), props, glyph_index);
1324
68
    }
1325
0
    else if (class_guess)
1326
0
    {
1327
0
      props &= HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
1328
0
      _hb_glyph_info_set_glyph_props (&buffer->cur(), props | class_guess);
1329
0
    }
1330
0
    else
1331
0
      _hb_glyph_info_set_glyph_props (&buffer->cur(), props);
1332
68
  }
1333
  void _set_glyph_class_props (hb_glyph_info_t &info,
1334
             unsigned int props,
1335
             hb_codepoint_t glyph_index)
1336
68
  {
1337
68
    props &= HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE;
1338
68
    _hb_glyph_info_set_glyph_props (&info, props | gdef_accel.get_glyph_props (glyph_index));
1339
68
  }
1340
  void _set_glyph_class_props (hb_glyph_info_t &info)
1341
0
  {
1342
0
    _set_glyph_class_props (info,
1343
0
          _hb_glyph_info_get_glyph_props (&info),
1344
0
          info.codepoint);
1345
0
  }
1346
1347
  void replace_glyph (hb_codepoint_t glyph_index)
1348
0
  {
1349
0
    _set_glyph_class (glyph_index);
1350
0
    (void) buffer->replace_glyph (glyph_index);
1351
0
  }
1352
  void replace_glyph_inplace (hb_codepoint_t glyph_index)
1353
0
  {
1354
0
    _set_glyph_class (glyph_index);
1355
0
    buffer->cur().codepoint = glyph_index;
1356
0
  }
1357
  void replace_glyph_with_ligature (hb_codepoint_t glyph_index,
1358
            unsigned int class_guess)
1359
68
  {
1360
68
    _set_glyph_class (glyph_index, class_guess, true);
1361
68
    (void) buffer->replace_glyph (glyph_index);
1362
68
  }
1363
  void output_glyph_for_component (hb_codepoint_t glyph_index,
1364
           unsigned int class_guess)
1365
0
  {
1366
0
    _set_glyph_class (glyph_index, class_guess, false, true);
1367
0
    (void) buffer->output_glyph (glyph_index);
1368
0
  }
1369
};
1370
1371
enum class hb_ot_subtable_cache_op_t
1372
{
1373
  ENTER,
1374
  LEAVE,
1375
};
1376
1377
struct hb_accelerate_subtables_context_t :
1378
       hb_dispatch_context_t<hb_accelerate_subtables_context_t>
1379
{
1380
  template <typename T>
1381
  static inline auto collect_second_glyphs_ (const T &obj,
1382
               hb_set_digest_t *digest,
1383
               hb_priority<1>) HB_RETURN (void, obj.collect_second_glyphs (digest) )
1384
  template <typename T>
1385
  static inline void collect_second_glyphs_ (const T &obj HB_UNUSED,
1386
               hb_set_digest_t *digest,
1387
               hb_priority<0>)
1388
1
  { *digest = hb_set_digest_t::full (); }
void OT::hb_accelerate_subtables_context_t::collect_second_glyphs_<OT::Layout::GPOS_impl::SinglePosFormat1>(OT::Layout::GPOS_impl::SinglePosFormat1 const&, hb_set_digest_t*, hb_priority<0u>)
Line
Count
Source
1388
1
  { *digest = hb_set_digest_t::full (); }
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::collect_second_glyphs_<OT::Layout::GPOS_impl::SinglePosFormat2>(OT::Layout::GPOS_impl::SinglePosFormat2 const&, hb_set_digest_t*, hb_priority<0u>)
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::collect_second_glyphs_<OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::SmallTypes> >(OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::SmallTypes> const&, hb_set_digest_t*, hb_priority<0u>)
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::collect_second_glyphs_<OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat1_3<OT::Layout::SmallTypes> const&, hb_set_digest_t*, hb_priority<0u>)
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::collect_second_glyphs_<OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::SingleSubstFormat2_4<OT::Layout::SmallTypes> const&, hb_set_digest_t*, hb_priority<0u>)
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::collect_second_glyphs_<OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::MultipleSubstFormat1_2<OT::Layout::SmallTypes> const&, hb_set_digest_t*, hb_priority<0u>)
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::collect_second_glyphs_<OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> >(OT::Layout::GSUB_impl::AlternateSubstFormat1_2<OT::Layout::SmallTypes> const&, hb_set_digest_t*, hb_priority<0u>)
Unexecuted instantiation: void OT::hb_accelerate_subtables_context_t::collect_second_glyphs_<OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1>(OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1 const&, hb_set_digest_t*, hb_priority<0u>)
1389
1390
  template <typename T>
1391
  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) )
1392
  template <typename T>
1393
  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) )
1394
  template <typename T>
1395
  static inline bool apply_to (const void *obj, hb_ot_apply_context_t *c, void *external_cache)
1396
150M
  {
1397
150M
    const T *typed_obj = (const T *) obj;
1398
150M
    return apply_ (typed_obj, c, external_cache, hb_prioritize);
1399
150M
  }
bool OT::hb_accelerate_subtables_context_t::apply_to<OT::Layout::GPOS_impl::SinglePosFormat1>(void const*, OT::hb_ot_apply_context_t*, void*)
Line
Count
Source
1396
4
  {
1397
4
    const T *typed_obj = (const T *) obj;
1398
4
    return apply_ (typed_obj, c, external_cache, hb_prioritize);
1399
4
  }
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*)
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*)
Line
Count
Source
1396
149M
  {
1397
149M
    const T *typed_obj = (const T *) obj;
1398
149M
    return apply_ (typed_obj, c, external_cache, hb_prioritize);
1399
149M
  }
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*)
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*)
Line
Count
Source
1396
248k
  {
1397
248k
    const T *typed_obj = (const T *) obj;
1398
248k
    return apply_ (typed_obj, c, external_cache, hb_prioritize);
1399
248k
  }
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*)
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*)
Line
Count
Source
1396
187k
  {
1397
187k
    const T *typed_obj = (const T *) obj;
1398
187k
    return apply_ (typed_obj, c, external_cache, hb_prioritize);
1399
187k
  }
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*)
bool OT::hb_accelerate_subtables_context_t::apply_to<OT::ChainContextFormat3>(void const*, OT::hb_ot_apply_context_t*, void*)
Line
Count
Source
1396
474k
  {
1397
474k
    const T *typed_obj = (const T *) obj;
1398
474k
    return apply_ (typed_obj, c, external_cache, hb_prioritize);
1399
474k
  }
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*)
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*)
Line
Count
Source
1396
121k
  {
1397
121k
    const T *typed_obj = (const T *) obj;
1398
121k
    return apply_ (typed_obj, c, external_cache, hb_prioritize);
1399
121k
  }
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*)
1400
1401
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1402
  template <typename T>
1403
  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) )
1404
  template <typename T>
1405
  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) )
1406
  template <typename T>
1407
  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) )
1408
  template <typename T>
1409
  static inline bool apply_cached_to (const void *obj, hb_ot_apply_context_t *c, void *external_cache)
1410
0
  {
1411
0
    const T *typed_obj = (const T *) obj;
1412
0
    return apply_cached_ (typed_obj, c, external_cache, hb_prioritize);
1413
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*)
1414
1415
  template <typename T>
1416
  static inline auto cache_func_ (hb_ot_apply_context_t *c,
1417
          hb_ot_subtable_cache_op_t op,
1418
          hb_priority<1>) HB_RETURN (bool, T::cache_func (c, op) )
1419
  template <typename T=void>
1420
  static inline bool cache_func_ (hb_ot_apply_context_t *c,
1421
          hb_ot_subtable_cache_op_t op HB_UNUSED,
1422
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>)
1423
  template <typename Type>
1424
  static inline bool cache_func_to (hb_ot_apply_context_t *c,
1425
            hb_ot_subtable_cache_op_t op)
1426
0
  {
1427
0
    return cache_func_<Type> (c, op, hb_prioritize);
1428
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)
1429
#endif
1430
1431
  typedef bool (*hb_apply_func_t) (const void *obj, hb_ot_apply_context_t *c, void *external_cache);
1432
  typedef bool (*hb_cache_func_t) (hb_ot_apply_context_t *c, hb_ot_subtable_cache_op_t op);
1433
1434
  struct hb_applicable_t
1435
  {
1436
    friend struct hb_accelerate_subtables_context_t;
1437
    friend struct hb_ot_layout_lookup_accelerator_t;
1438
1439
    template <typename T>
1440
    void init (const T &obj_,
1441
         hb_apply_func_t apply_func_
1442
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1443
         , hb_apply_func_t apply_cached_func_
1444
         , hb_cache_func_t cache_func_
1445
         , void *external_cache_
1446
#endif
1447
    )
1448
1.19k
    {
1449
1.19k
      obj = &obj_;
1450
1.19k
      apply_func = apply_func_;
1451
1.19k
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1452
1.19k
      apply_cached_func = apply_cached_func_;
1453
1.19k
      cache_func = cache_func_;
1454
1.19k
      external_cache = external_cache_;
1455
1.19k
#endif
1456
1.19k
      digest.init ();
1457
1.19k
      obj_.get_coverage ().collect_coverage (&digest);
1458
1.19k
    }
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*)
Line
Count
Source
1448
1
    {
1449
1
      obj = &obj_;
1450
1
      apply_func = apply_func_;
1451
1
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1452
1
      apply_cached_func = apply_cached_func_;
1453
1
      cache_func = cache_func_;
1454
1
      external_cache = external_cache_;
1455
1
#endif
1456
1
      digest.init ();
1457
1
      obj_.get_coverage ().collect_coverage (&digest);
1458
1
    }
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*)
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*)
Line
Count
Source
1448
45
    {
1449
45
      obj = &obj_;
1450
45
      apply_func = apply_func_;
1451
45
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1452
45
      apply_cached_func = apply_cached_func_;
1453
45
      cache_func = cache_func_;
1454
45
      external_cache = external_cache_;
1455
45
#endif
1456
45
      digest.init ();
1457
45
      obj_.get_coverage ().collect_coverage (&digest);
1458
45
    }
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
1448
412
    {
1449
412
      obj = &obj_;
1450
412
      apply_func = apply_func_;
1451
412
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1452
412
      apply_cached_func = apply_cached_func_;
1453
412
      cache_func = cache_func_;
1454
412
      external_cache = external_cache_;
1455
412
#endif
1456
412
      digest.init ();
1457
412
      obj_.get_coverage ().collect_coverage (&digest);
1458
412
    }
Unexecuted instantiation: 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*)
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
1448
72
    {
1449
72
      obj = &obj_;
1450
72
      apply_func = apply_func_;
1451
72
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1452
72
      apply_cached_func = apply_cached_func_;
1453
72
      cache_func = cache_func_;
1454
72
      external_cache = external_cache_;
1455
72
#endif
1456
72
      digest.init ();
1457
72
      obj_.get_coverage ().collect_coverage (&digest);
1458
72
    }
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*)
Unexecuted instantiation: 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*)
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*)
Line
Count
Source
1448
615
    {
1449
615
      obj = &obj_;
1450
615
      apply_func = apply_func_;
1451
615
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1452
615
      apply_cached_func = apply_cached_func_;
1453
615
      cache_func = cache_func_;
1454
615
      external_cache = external_cache_;
1455
615
#endif
1456
615
      digest.init ();
1457
615
      obj_.get_coverage ().collect_coverage (&digest);
1458
615
    }
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
1448
54
    {
1449
54
      obj = &obj_;
1450
54
      apply_func = apply_func_;
1451
54
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1452
54
      apply_cached_func = apply_cached_func_;
1453
54
      cache_func = cache_func_;
1454
54
      external_cache = external_cache_;
1455
54
#endif
1456
54
      digest.init ();
1457
54
      obj_.get_coverage ().collect_coverage (&digest);
1458
54
    }
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*)
1459
1460
#ifdef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1461
    bool apply (hb_ot_apply_context_t *c) const
1462
    {
1463
      return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c, nullptr);
1464
    }
1465
    bool apply_no_digest (hb_ot_apply_context_t *c) const
1466
    {
1467
      return apply_func (obj, c, nullptr);
1468
    }
1469
#else
1470
    bool apply (hb_ot_apply_context_t *c) const
1471
445k
    {
1472
445k
      return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c, external_cache);
1473
445k
    }
1474
    bool apply_cached (hb_ot_apply_context_t *c) const
1475
0
    {
1476
0
      return digest.may_have (c->buffer->cur().codepoint) &&  apply_cached_func (obj, c, external_cache);
1477
0
    }
1478
    bool apply_no_digest (hb_ot_apply_context_t *c) const
1479
150M
    {
1480
150M
      return apply_func (obj, c, external_cache);
1481
150M
    }
1482
    bool apply_cached_no_digest (hb_ot_apply_context_t *c) const
1483
0
    {
1484
0
      return apply_cached_func (obj, c, external_cache);
1485
0
    }
1486
1487
    bool cache_enter (hb_ot_apply_context_t *c) const
1488
0
    {
1489
0
      return cache_func (c, hb_ot_subtable_cache_op_t::ENTER);
1490
0
    }
1491
    void cache_leave (hb_ot_apply_context_t *c) const
1492
0
    {
1493
0
      cache_func (c, hb_ot_subtable_cache_op_t::LEAVE);
1494
0
    }
1495
#endif
1496
1497
    private:
1498
    const void *obj;
1499
    hb_apply_func_t apply_func;
1500
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1501
    hb_apply_func_t apply_cached_func;
1502
    hb_cache_func_t cache_func;
1503
    void *external_cache;
1504
#endif
1505
    hb_set_digest_t digest;
1506
  };
1507
1508
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1509
  template <typename T>
1510
  auto cache_cost (const T &obj, hb_priority<1>) HB_AUTO_RETURN ( obj.cache_cost () )
1511
  template <typename T>
1512
  auto cache_cost (const T &obj, hb_priority<0>) HB_AUTO_RETURN ( 0u )
1513
1514
  template <typename T>
1515
  auto external_cache_create (const T &obj, hb_priority<1>) HB_AUTO_RETURN ( obj.external_cache_create () )
1516
  template <typename T>
1517
  auto external_cache_create (const T &obj, hb_priority<0>) HB_AUTO_RETURN ( nullptr )
1518
#endif
1519
1520
  /* Dispatch interface. */
1521
  template <typename T>
1522
  return_t dispatch (const T &obj)
1523
1.19k
  {
1524
1.19k
    collect_second_glyphs_ (obj, &digest_second, hb_prioritize);
1525
1526
1.19k
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1527
1.19k
    void *external_cache = nullptr;
1528
1.19k
    if (i < 8)
1529
1.12k
      external_cache = external_cache_create (obj, hb_prioritize);
1530
1.19k
#endif
1531
1532
1.19k
    hb_applicable_t *entry = &array[i++];
1533
1534
1.19k
    entry->init (obj,
1535
1.19k
     apply_to<T>
1536
1.19k
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1537
1.19k
     , apply_cached_to<T>
1538
1.19k
     , cache_func_to<T>
1539
1.19k
     , external_cache
1540
1.19k
#endif
1541
1.19k
     );
1542
1543
1.19k
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1544
    /* Cache handling
1545
     *
1546
     * We allow one subtable from each lookup to use a cache. The assumption
1547
     * being that multiple subtables of the same lookup cannot use a cache
1548
     * because the resources they would use will collide.  As such, we ask
1549
     * each subtable to tell us how much it costs (which a cache would avoid),
1550
     * and we allocate the cache opportunity to the costliest subtable.
1551
     */
1552
1.19k
    unsigned cost = cache_cost (obj, hb_prioritize);
1553
1.19k
    if (cost > subtable_cache_user_cost)
1554
0
    {
1555
0
      subtable_cache_user_idx = i - 1;
1556
0
      subtable_cache_user_cost = cost;
1557
0
    }
1558
1.19k
#endif
1559
1560
1.19k
    return hb_empty_t ();
1561
1.19k
  }
hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::Layout::GPOS_impl::SinglePosFormat1>(OT::Layout::GPOS_impl::SinglePosFormat1 const&)
Line
Count
Source
1523
1
  {
1524
1
    collect_second_glyphs_ (obj, &digest_second, hb_prioritize);
1525
1526
1
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1527
1
    void *external_cache = nullptr;
1528
1
    if (i < 8)
1529
1
      external_cache = external_cache_create (obj, hb_prioritize);
1530
1
#endif
1531
1532
1
    hb_applicable_t *entry = &array[i++];
1533
1534
1
    entry->init (obj,
1535
1
     apply_to<T>
1536
1
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1537
1
     , apply_cached_to<T>
1538
1
     , cache_func_to<T>
1539
1
     , external_cache
1540
1
#endif
1541
1
     );
1542
1543
1
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1544
    /* Cache handling
1545
     *
1546
     * We allow one subtable from each lookup to use a cache. The assumption
1547
     * being that multiple subtables of the same lookup cannot use a cache
1548
     * because the resources they would use will collide.  As such, we ask
1549
     * each subtable to tell us how much it costs (which a cache would avoid),
1550
     * and we allocate the cache opportunity to the costliest subtable.
1551
     */
1552
1
    unsigned cost = cache_cost (obj, hb_prioritize);
1553
1
    if (cost > subtable_cache_user_cost)
1554
0
    {
1555
0
      subtable_cache_user_idx = i - 1;
1556
0
      subtable_cache_user_cost = cost;
1557
0
    }
1558
1
#endif
1559
1560
1
    return hb_empty_t ();
1561
1
  }
Unexecuted instantiation: hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::Layout::GPOS_impl::SinglePosFormat2>(OT::Layout::GPOS_impl::SinglePosFormat2 const&)
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&)
Line
Count
Source
1523
45
  {
1524
45
    collect_second_glyphs_ (obj, &digest_second, hb_prioritize);
1525
1526
45
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1527
45
    void *external_cache = nullptr;
1528
45
    if (i < 8)
1529
45
      external_cache = external_cache_create (obj, hb_prioritize);
1530
45
#endif
1531
1532
45
    hb_applicable_t *entry = &array[i++];
1533
1534
45
    entry->init (obj,
1535
45
     apply_to<T>
1536
45
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1537
45
     , apply_cached_to<T>
1538
45
     , cache_func_to<T>
1539
45
     , external_cache
1540
45
#endif
1541
45
     );
1542
1543
45
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1544
    /* Cache handling
1545
     *
1546
     * We allow one subtable from each lookup to use a cache. The assumption
1547
     * being that multiple subtables of the same lookup cannot use a cache
1548
     * because the resources they would use will collide.  As such, we ask
1549
     * each subtable to tell us how much it costs (which a cache would avoid),
1550
     * and we allocate the cache opportunity to the costliest subtable.
1551
     */
1552
45
    unsigned cost = cache_cost (obj, hb_prioritize);
1553
45
    if (cost > subtable_cache_user_cost)
1554
0
    {
1555
0
      subtable_cache_user_idx = i - 1;
1556
0
      subtable_cache_user_cost = cost;
1557
0
    }
1558
45
#endif
1559
1560
45
    return hb_empty_t ();
1561
45
  }
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
1523
412
  {
1524
412
    collect_second_glyphs_ (obj, &digest_second, hb_prioritize);
1525
1526
412
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1527
412
    void *external_cache = nullptr;
1528
412
    if (i < 8)
1529
412
      external_cache = external_cache_create (obj, hb_prioritize);
1530
412
#endif
1531
1532
412
    hb_applicable_t *entry = &array[i++];
1533
1534
412
    entry->init (obj,
1535
412
     apply_to<T>
1536
412
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1537
412
     , apply_cached_to<T>
1538
412
     , cache_func_to<T>
1539
412
     , external_cache
1540
412
#endif
1541
412
     );
1542
1543
412
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1544
    /* Cache handling
1545
     *
1546
     * We allow one subtable from each lookup to use a cache. The assumption
1547
     * being that multiple subtables of the same lookup cannot use a cache
1548
     * because the resources they would use will collide.  As such, we ask
1549
     * each subtable to tell us how much it costs (which a cache would avoid),
1550
     * and we allocate the cache opportunity to the costliest subtable.
1551
     */
1552
412
    unsigned cost = cache_cost (obj, hb_prioritize);
1553
412
    if (cost > subtable_cache_user_cost)
1554
0
    {
1555
0
      subtable_cache_user_idx = i - 1;
1556
0
      subtable_cache_user_cost = cost;
1557
0
    }
1558
412
#endif
1559
1560
412
    return hb_empty_t ();
1561
412
  }
Unexecuted instantiation: 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&)
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
1523
72
  {
1524
72
    collect_second_glyphs_ (obj, &digest_second, hb_prioritize);
1525
1526
72
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1527
72
    void *external_cache = nullptr;
1528
72
    if (i < 8)
1529
72
      external_cache = external_cache_create (obj, hb_prioritize);
1530
72
#endif
1531
1532
72
    hb_applicable_t *entry = &array[i++];
1533
1534
72
    entry->init (obj,
1535
72
     apply_to<T>
1536
72
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1537
72
     , apply_cached_to<T>
1538
72
     , cache_func_to<T>
1539
72
     , external_cache
1540
72
#endif
1541
72
     );
1542
1543
72
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1544
    /* Cache handling
1545
     *
1546
     * We allow one subtable from each lookup to use a cache. The assumption
1547
     * being that multiple subtables of the same lookup cannot use a cache
1548
     * because the resources they would use will collide.  As such, we ask
1549
     * each subtable to tell us how much it costs (which a cache would avoid),
1550
     * and we allocate the cache opportunity to the costliest subtable.
1551
     */
1552
72
    unsigned cost = cache_cost (obj, hb_prioritize);
1553
72
    if (cost > subtable_cache_user_cost)
1554
0
    {
1555
0
      subtable_cache_user_idx = i - 1;
1556
0
      subtable_cache_user_cost = cost;
1557
0
    }
1558
72
#endif
1559
1560
72
    return hb_empty_t ();
1561
72
  }
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&)
Unexecuted instantiation: hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::ChainContextFormat2_5<OT::Layout::SmallTypes> >(OT::ChainContextFormat2_5<OT::Layout::SmallTypes> const&)
hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::ChainContextFormat3>(OT::ChainContextFormat3 const&)
Line
Count
Source
1523
615
  {
1524
615
    collect_second_glyphs_ (obj, &digest_second, hb_prioritize);
1525
1526
615
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1527
615
    void *external_cache = nullptr;
1528
615
    if (i < 8)
1529
540
      external_cache = external_cache_create (obj, hb_prioritize);
1530
615
#endif
1531
1532
615
    hb_applicable_t *entry = &array[i++];
1533
1534
615
    entry->init (obj,
1535
615
     apply_to<T>
1536
615
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1537
615
     , apply_cached_to<T>
1538
615
     , cache_func_to<T>
1539
615
     , external_cache
1540
615
#endif
1541
615
     );
1542
1543
615
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1544
    /* Cache handling
1545
     *
1546
     * We allow one subtable from each lookup to use a cache. The assumption
1547
     * being that multiple subtables of the same lookup cannot use a cache
1548
     * because the resources they would use will collide.  As such, we ask
1549
     * each subtable to tell us how much it costs (which a cache would avoid),
1550
     * and we allocate the cache opportunity to the costliest subtable.
1551
     */
1552
615
    unsigned cost = cache_cost (obj, hb_prioritize);
1553
615
    if (cost > subtable_cache_user_cost)
1554
0
    {
1555
0
      subtable_cache_user_idx = i - 1;
1556
0
      subtable_cache_user_cost = cost;
1557
0
    }
1558
615
#endif
1559
1560
615
    return hb_empty_t ();
1561
615
  }
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
1523
54
  {
1524
54
    collect_second_glyphs_ (obj, &digest_second, hb_prioritize);
1525
1526
54
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1527
54
    void *external_cache = nullptr;
1528
54
    if (i < 8)
1529
54
      external_cache = external_cache_create (obj, hb_prioritize);
1530
54
#endif
1531
1532
54
    hb_applicable_t *entry = &array[i++];
1533
1534
54
    entry->init (obj,
1535
54
     apply_to<T>
1536
54
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1537
54
     , apply_cached_to<T>
1538
54
     , cache_func_to<T>
1539
54
     , external_cache
1540
54
#endif
1541
54
     );
1542
1543
54
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1544
    /* Cache handling
1545
     *
1546
     * We allow one subtable from each lookup to use a cache. The assumption
1547
     * being that multiple subtables of the same lookup cannot use a cache
1548
     * because the resources they would use will collide.  As such, we ask
1549
     * each subtable to tell us how much it costs (which a cache would avoid),
1550
     * and we allocate the cache opportunity to the costliest subtable.
1551
     */
1552
54
    unsigned cost = cache_cost (obj, hb_prioritize);
1553
54
    if (cost > subtable_cache_user_cost)
1554
0
    {
1555
0
      subtable_cache_user_idx = i - 1;
1556
0
      subtable_cache_user_cost = cost;
1557
0
    }
1558
54
#endif
1559
1560
54
    return hb_empty_t ();
1561
54
  }
Unexecuted instantiation: hb_empty_t OT::hb_accelerate_subtables_context_t::dispatch<OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1>(OT::Layout::GSUB_impl::ReverseChainSingleSubstFormat1 const&)
1562
719
  static return_t default_return_value () { return hb_empty_t (); }
1563
1564
  hb_accelerate_subtables_context_t (hb_applicable_t *array_) :
1565
719
             array (array_) {}
1566
1567
  hb_applicable_t *array;
1568
  unsigned i = 0;
1569
  hb_set_digest_t digest_second;
1570
1571
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
1572
  unsigned subtable_cache_user_idx = (unsigned) -1;
1573
  unsigned subtable_cache_user_cost = 0;
1574
#endif
1575
};
1576
1577
1578
typedef bool (*intersects_func_t) (const hb_set_t *glyphs, unsigned value, const void *data, void *cache);
1579
typedef void (*intersected_glyphs_func_t) (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, void *cache);
1580
typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, unsigned value, const void *data);
1581
typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data);
1582
typedef unsigned (*get_value_func_t) (hb_glyph_info_t &info, const void *data);
1583
1584
/* One word per RuleSet, summarizing the classes accepted at the first
1585
 * input position after the current glyph.  Collisions only cause extra work. */
1586
struct hb_ot_layout_ruleset_digest_t
1587
{
1588
0
  void init () { mask = 0; }
1589
0
  void set_full () { mask = (uint64_t) -1; }
1590
0
  void add (unsigned value) { mask |= (uint64_t) 1 << (value & 63); }
1591
0
  bool may_have (unsigned value) const { return mask & ((uint64_t) 1 << (value & 63)); }
1592
1593
  uint64_t mask;
1594
};
1595
1596
struct ContextClosureFuncs
1597
{
1598
  intersects_func_t intersects;
1599
  intersected_glyphs_func_t intersected_glyphs;
1600
};
1601
struct ContextCollectGlyphsFuncs
1602
{
1603
  collect_glyphs_func_t collect;
1604
};
1605
struct ContextApplyFuncs
1606
{
1607
  match_func_t match;
1608
};
1609
struct ChainContextApplyFuncs
1610
{
1611
  match_func_t match[3];
1612
};
1613
1614
1615
static inline bool intersects_glyph (const hb_set_t *glyphs, unsigned value, const void *data HB_UNUSED, void *cache HB_UNUSED)
1616
0
{
1617
0
  return glyphs->has (value);
1618
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::intersects_glyph(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-ot-face.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*)
Unexecuted instantiation: hb-subset.cc:OT::intersects_glyph(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::intersects_glyph(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::intersects_glyph(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::intersects_glyph(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::intersects_glyph(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::intersects_glyph(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::intersects_glyph(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: gsubgpos-context.cc:OT::intersects_glyph(hb_set_t const*, unsigned int, void const*, void*)
1619
static inline bool intersects_class (const hb_set_t *glyphs, unsigned value, const void *data, void *cache)
1620
0
{
1621
0
  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
1622
0
  hb_map_t *map = (hb_map_t *) cache;
1623
1624
0
  hb_codepoint_t *cached_v;
1625
0
  if (map->has (value, &cached_v))
1626
0
    return *cached_v;
1627
1628
0
  bool v = class_def.intersects_class (glyphs, value);
1629
0
  map->set (value, v);
1630
1631
0
  return v;
1632
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::intersects_class(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-ot-face.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*)
Unexecuted instantiation: hb-subset.cc:OT::intersects_class(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::intersects_class(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::intersects_class(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::intersects_class(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::intersects_class(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::intersects_class(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::intersects_class(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: gsubgpos-context.cc:OT::intersects_class(hb_set_t const*, unsigned int, void const*, void*)
1633
static inline bool intersects_coverage (const hb_set_t *glyphs, unsigned value, const void *data, void *cache HB_UNUSED)
1634
0
{
1635
0
  Offset16To<Coverage> coverage;
1636
0
  coverage = value;
1637
0
  return (data+coverage).intersects (glyphs);
1638
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::intersects_coverage(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-ot-face.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*)
Unexecuted instantiation: hb-subset.cc:OT::intersects_coverage(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::intersects_coverage(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::intersects_coverage(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::intersects_coverage(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::intersects_coverage(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::intersects_coverage(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::intersects_coverage(hb_set_t const*, unsigned int, void const*, void*)
Unexecuted instantiation: gsubgpos-context.cc:OT::intersects_coverage(hb_set_t const*, unsigned int, void const*, void*)
1639
1640
1641
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)
1642
0
{
1643
0
  unsigned g = reinterpret_cast<const HBUINT16 *>(data)[value];
1644
0
  intersected_glyphs->add (g);
1645
0
}
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-face.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*)
Unexecuted instantiation: hb-subset.cc:OT::intersected_glyph(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::intersected_glyph(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::intersected_glyph(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::intersected_glyph(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::intersected_glyph(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::intersected_glyph(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::intersected_glyph(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: gsubgpos-context.cc:OT::intersected_glyph(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
1646
1647
using intersected_class_cache_t = hb_hashmap_t<unsigned, hb_set_t>;
1648
1649
static inline void intersected_class_glyphs (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs, void *cache)
1650
0
{
1651
0
  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
1652
1653
0
  intersected_class_cache_t *map = (intersected_class_cache_t *) cache;
1654
1655
0
  hb_set_t *cached_v;
1656
0
  if (map->has (value, &cached_v))
1657
0
  {
1658
0
    intersected_glyphs->union_ (*cached_v);
1659
0
    return;
1660
0
  }
1661
1662
0
  hb_set_t v;
1663
0
  class_def.intersected_class_glyphs (glyphs, value, &v);
1664
1665
0
  intersected_glyphs->union_ (v);
1666
1667
0
  map->set (value, std::move (v));
1668
0
}
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-face.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*)
Unexecuted instantiation: hb-subset.cc:OT::intersected_class_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::intersected_class_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::intersected_class_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::intersected_class_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::intersected_class_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::intersected_class_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::intersected_class_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: gsubgpos-context.cc:OT::intersected_class_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
1669
1670
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)
1671
0
{
1672
0
  Offset16To<Coverage> coverage;
1673
0
  coverage = value;
1674
0
  (data+coverage).intersect_set (*glyphs, *intersected_glyphs);
1675
0
}
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-face.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*)
Unexecuted instantiation: hb-subset.cc:OT::intersected_coverage_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::intersected_coverage_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::intersected_coverage_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::intersected_coverage_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::intersected_coverage_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::intersected_coverage_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::intersected_coverage_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
Unexecuted instantiation: gsubgpos-context.cc:OT::intersected_coverage_glyphs(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*)
1676
1677
1678
template <typename HBUINT>
1679
static inline bool array_is_subset_of (const hb_set_t *glyphs,
1680
               unsigned int count,
1681
               const HBUINT values[],
1682
               intersects_func_t intersects_func,
1683
               const void *intersects_data,
1684
               void *cache)
1685
0
{
1686
0
  for (const auto &_ : + hb_iter (values, count))
1687
0
    if (!intersects_func (glyphs, _, intersects_data, cache)) return false;
1688
0
  return true;
1689
0
}
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-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-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*)
Unexecuted instantiation: hb-subset.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-subset-plan-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-subset-table-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-subset-table-var.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-subset-table-cff.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-subset-table-color.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-subset-table-other.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: gsubgpos-context.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*)
1690
1691
1692
static inline void collect_glyph (hb_set_t *glyphs, unsigned value, const void *data HB_UNUSED)
1693
0
{
1694
0
  glyphs->add (value);
1695
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::collect_glyph(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-ot-face.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*)
Unexecuted instantiation: hb-subset.cc:OT::collect_glyph(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::collect_glyph(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::collect_glyph(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::collect_glyph(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::collect_glyph(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::collect_glyph(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::collect_glyph(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: gsubgpos-context.cc:OT::collect_glyph(hb_set_t*, unsigned int, void const*)
1696
static inline void collect_class (hb_set_t *glyphs, unsigned value, const void *data)
1697
0
{
1698
0
  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
1699
0
  class_def.collect_class (glyphs, value);
1700
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::collect_class(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-ot-face.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*)
Unexecuted instantiation: hb-subset.cc:OT::collect_class(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::collect_class(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::collect_class(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::collect_class(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::collect_class(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::collect_class(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::collect_class(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: gsubgpos-context.cc:OT::collect_class(hb_set_t*, unsigned int, void const*)
1701
static inline void collect_coverage (hb_set_t *glyphs, unsigned value, const void *data)
1702
0
{
1703
0
  Offset16To<Coverage> coverage;
1704
0
  coverage = value;
1705
0
  (data+coverage).collect_coverage (glyphs);
1706
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::collect_coverage(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-ot-face.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*)
Unexecuted instantiation: hb-subset.cc:OT::collect_coverage(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::collect_coverage(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::collect_coverage(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::collect_coverage(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::collect_coverage(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::collect_coverage(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::collect_coverage(hb_set_t*, unsigned int, void const*)
Unexecuted instantiation: gsubgpos-context.cc:OT::collect_coverage(hb_set_t*, unsigned int, void const*)
1707
1708
inline const hb_set_t *
1709
hb_depend_context_t::find_or_create_glyph_set (const void *data,
1710
                                                unsigned value,
1711
                                                glyph_set_type_t type)
1712
0
{
1713
0
  /* Class definitions and coverages are immutable for the lifetime of the
1714
0
   * context, so their expanded glyph sets can be shared across traversals. */
1715
0
  glyph_set_cache_key_t key (data, value, type);
1716
0
  hb_codepoint_t *existing = nullptr;
1717
0
  if (glyph_set_to_index.has (key, &existing))
1718
0
    return glyph_sets[*existing].get ();
1719
0
1720
0
  hb_set_t *set = hb_object_create<hb_set_t> ();
1721
0
  if (unlikely (!set))
1722
0
  {
1723
0
    depend_data->fail ();
1724
0
    return nullptr;
1725
0
  }
1726
0
1727
0
  if (type == GLYPH_SET_COVERAGE)
1728
0
    collect_coverage (set, value, data);
1729
0
  else if (type == GLYPH_SET_CLASS)
1730
0
    collect_class (set, value, data);
1731
0
  else
1732
0
    set->add (value);
1733
0
  if (unlikely (set->in_error ()))
1734
0
  {
1735
0
    hb_set_destroy (set);
1736
0
    depend_data->fail ();
1737
0
    return nullptr;
1738
0
  }
1739
0
1740
0
  hb_codepoint_t index = glyph_sets.length;
1741
0
  if (unlikely (!glyph_sets.push_or_fail (hb::unique_ptr<hb_set_t> {set})))
1742
0
  {
1743
0
    depend_data->fail ();
1744
0
    return nullptr;
1745
0
  }
1746
0
  if (unlikely (!glyph_set_to_index.set (key, index)))
1747
0
  {
1748
0
    depend_data->fail ();
1749
0
    return nullptr;
1750
0
  }
1751
0
  return glyph_sets[index].get ();
1752
0
}
1753
1754
inline hb_codepoint_t
1755
hb_depend_context_t::find_or_create_cached_context_set (const hb_set_t *set)
1756
0
{
1757
0
  uintptr_t key = (uintptr_t) set;
1758
0
  hb_codepoint_t *existing = nullptr;
1759
0
  if (cached_context_set_indices.has (key, &existing))
1760
0
    return *existing;
1761
0
1762
0
  hb_codepoint_t index = depend_data->find_or_create_context_set (*set);
1763
0
  if (unlikely (index == HB_CODEPOINT_INVALID))
1764
0
    return HB_CODEPOINT_INVALID;
1765
0
  if (unlikely (!cached_context_set_indices.set (key, index)))
1766
0
    return depend_data->fail_invalid ();
1767
0
  return index;
1768
0
}
1769
1770
template <typename HBUINT>
1771
static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
1772
          hb_set_t *glyphs,
1773
          unsigned int count,
1774
          const HBUINT values[],
1775
          collect_glyphs_func_t collect_func,
1776
          const void *collect_data)
1777
0
{
1778
0
  return
1779
0
  + hb_iter (values, count)
1780
0
  | hb_apply ([&] (const HBUINT &_) { collect_func (glyphs, _, collect_data); })
1781
0
  ;
1782
0
}
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-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-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*)
Unexecuted instantiation: hb-subset.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-subset-plan-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-subset-table-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-subset-table-var.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-subset-table-cff.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-subset-table-color.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-subset-table-other.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: gsubgpos-context.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*)
1783
1784
1785
static inline bool match_always (hb_glyph_info_t &info HB_UNUSED, unsigned value HB_UNUSED, const void *data HB_UNUSED)
1786
28.5k
{
1787
28.5k
  return true;
1788
28.5k
}
Unexecuted instantiation: hb-aat-layout.cc:OT::match_always(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-face.cc:OT::match_always(hb_glyph_info_t&, unsigned int, void const*)
hb-ot-layout.cc:OT::match_always(hb_glyph_info_t&, unsigned int, void const*)
Line
Count
Source
1786
28.5k
{
1787
28.5k
  return true;
1788
28.5k
}
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*)
Unexecuted instantiation: hb-subset.cc:OT::match_always(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::match_always(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::match_always(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::match_always(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::match_always(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::match_always(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::match_always(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: gsubgpos-context.cc:OT::match_always(hb_glyph_info_t&, unsigned int, void const*)
1789
static inline bool match_glyph (hb_glyph_info_t &info, unsigned value, const void *data HB_UNUSED)
1790
64.1k
{
1791
64.1k
  return info.codepoint == value;
1792
64.1k
}
Unexecuted instantiation: hb-aat-layout.cc:OT::match_glyph(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-face.cc:OT::match_glyph(hb_glyph_info_t&, unsigned int, void const*)
hb-ot-layout.cc:OT::match_glyph(hb_glyph_info_t&, unsigned int, void const*)
Line
Count
Source
1790
64.1k
{
1791
64.1k
  return info.codepoint == value;
1792
64.1k
}
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*)
Unexecuted instantiation: hb-subset.cc:OT::match_glyph(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::match_glyph(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::match_glyph(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::match_glyph(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::match_glyph(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::match_glyph(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::match_glyph(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: gsubgpos-context.cc:OT::match_glyph(hb_glyph_info_t&, unsigned int, void const*)
1793
static inline bool match_class (hb_glyph_info_t &info, unsigned value, const void *data)
1794
0
{
1795
0
  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
1796
0
  return class_def.get_class (info.codepoint) == value;
1797
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::match_class(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-face.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*)
Unexecuted instantiation: hb-subset.cc:OT::match_class(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::match_class(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::match_class(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::match_class(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::match_class(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::match_class(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::match_class(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: gsubgpos-context.cc:OT::match_class(hb_glyph_info_t&, unsigned int, void const*)
1798
static inline unsigned get_class_value (hb_glyph_info_t &info, const void *data)
1799
0
{
1800
0
  const ClassDef &class_def = *reinterpret_cast<const ClassDef *> (data);
1801
0
  return class_def.get_class (info.codepoint);
1802
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::get_class_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-ot-face.cc:OT::get_class_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-ot-layout.cc:OT::get_class_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::get_class_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::get_class_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset.cc:OT::get_class_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::get_class_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::get_class_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::get_class_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::get_class_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::get_class_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::get_class_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: gsubgpos-context.cc:OT::get_class_value(hb_glyph_info_t&, void const*)
1803
struct match_class_cache_data_t
1804
{
1805
  const ClassDef *class_def;
1806
  hb_ot_layout_mapping_cache_t *cache;
1807
};
1808
static inline bool match_class_cache (hb_glyph_info_t &info, unsigned value, const void *data)
1809
0
{
1810
0
  const auto &cache_data = *reinterpret_cast<const match_class_cache_data_t *> (data);
1811
0
  return cache_data.class_def->get_class (info.codepoint, cache_data.cache) == value;
1812
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::match_class_cache(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-face.cc:OT::match_class_cache(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-layout.cc:OT::match_class_cache(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::match_class_cache(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::match_class_cache(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset.cc:OT::match_class_cache(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::match_class_cache(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::match_class_cache(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::match_class_cache(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::match_class_cache(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::match_class_cache(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::match_class_cache(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: gsubgpos-context.cc:OT::match_class_cache(hb_glyph_info_t&, unsigned int, void const*)
1813
static inline unsigned get_class_cache_value (hb_glyph_info_t &info, const void *data)
1814
0
{
1815
0
  const auto &cache_data = *reinterpret_cast<const match_class_cache_data_t *> (data);
1816
0
  return cache_data.class_def->get_class (info.codepoint, cache_data.cache);
1817
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::get_class_cache_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-ot-face.cc:OT::get_class_cache_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-ot-layout.cc:OT::get_class_cache_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::get_class_cache_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::get_class_cache_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset.cc:OT::get_class_cache_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::get_class_cache_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::get_class_cache_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::get_class_cache_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::get_class_cache_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::get_class_cache_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::get_class_cache_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: gsubgpos-context.cc:OT::get_class_cache_value(hb_glyph_info_t&, void const*)
1818
static inline unsigned get_class_cached (const ClassDef &class_def, hb_glyph_info_t &info)
1819
0
{
1820
0
  unsigned klass = info.syllable();
1821
0
  if (klass < 255)
1822
0
    return klass;
1823
0
  klass = class_def.get_class (info.codepoint);
1824
0
  if (likely (klass < 255))
1825
0
    info.syllable() = klass;
1826
0
  return klass;
1827
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::get_class_cached(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-ot-face.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&)
Unexecuted instantiation: hb-subset.cc:OT::get_class_cached(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::get_class_cached(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::get_class_cached(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-subset-table-var.cc:OT::get_class_cached(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::get_class_cached(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-subset-table-color.cc:OT::get_class_cached(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-subset-table-other.cc:OT::get_class_cached(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: gsubgpos-context.cc:OT::get_class_cached(OT::ClassDef const&, hb_glyph_info_t&)
1828
static inline bool match_class_cached (hb_glyph_info_t &info, unsigned value, const void *data)
1829
0
{
1830
0
  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
1831
0
  return get_class_cached (class_def, info) == value;
1832
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::match_class_cached(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-face.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*)
Unexecuted instantiation: hb-subset.cc:OT::match_class_cached(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::match_class_cached(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::match_class_cached(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::match_class_cached(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::match_class_cached(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::match_class_cached(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::match_class_cached(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: gsubgpos-context.cc:OT::match_class_cached(hb_glyph_info_t&, unsigned int, void const*)
1833
static inline unsigned get_class_cached_value (hb_glyph_info_t &info, const void *data)
1834
0
{
1835
0
  const ClassDef &class_def = *reinterpret_cast<const ClassDef *> (data);
1836
0
  return get_class_cached (class_def, info);
1837
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::get_class_cached_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-ot-face.cc:OT::get_class_cached_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-ot-layout.cc:OT::get_class_cached_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::get_class_cached_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::get_class_cached_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset.cc:OT::get_class_cached_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::get_class_cached_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::get_class_cached_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::get_class_cached_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::get_class_cached_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::get_class_cached_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::get_class_cached_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: gsubgpos-context.cc:OT::get_class_cached_value(hb_glyph_info_t&, void const*)
1838
static inline unsigned get_class_cached1 (const ClassDef &class_def, hb_glyph_info_t &info)
1839
0
{
1840
0
  unsigned klass = info.syllable() & 0x0F;
1841
0
  if (klass < 15)
1842
0
    return klass;
1843
0
  klass = class_def.get_class (info.codepoint);
1844
0
  if (likely (klass < 15))
1845
0
    info.syllable() = (info.syllable() & 0xF0) | klass;
1846
0
  return klass;
1847
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::get_class_cached1(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-ot-face.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&)
Unexecuted instantiation: hb-subset.cc:OT::get_class_cached1(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::get_class_cached1(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::get_class_cached1(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-subset-table-var.cc:OT::get_class_cached1(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::get_class_cached1(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-subset-table-color.cc:OT::get_class_cached1(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-subset-table-other.cc:OT::get_class_cached1(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: gsubgpos-context.cc:OT::get_class_cached1(OT::ClassDef const&, hb_glyph_info_t&)
1848
static inline bool match_class_cached1 (hb_glyph_info_t &info, unsigned value, const void *data)
1849
0
{
1850
0
  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
1851
0
  return get_class_cached1 (class_def, info) == value;
1852
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::match_class_cached1(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-face.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*)
Unexecuted instantiation: hb-subset.cc:OT::match_class_cached1(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::match_class_cached1(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::match_class_cached1(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::match_class_cached1(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::match_class_cached1(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::match_class_cached1(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::match_class_cached1(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: gsubgpos-context.cc:OT::match_class_cached1(hb_glyph_info_t&, unsigned int, void const*)
1853
static inline unsigned get_class_cached2 (const ClassDef &class_def, hb_glyph_info_t &info)
1854
0
{
1855
0
  unsigned klass = (info.syllable() & 0xF0) >> 4;
1856
0
  if (klass < 15)
1857
0
    return klass;
1858
0
  klass = class_def.get_class (info.codepoint);
1859
0
  if (likely (klass < 15))
1860
0
    info.syllable() = (info.syllable() & 0x0F) | (klass << 4);
1861
0
  return klass;
1862
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::get_class_cached2(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-ot-face.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&)
Unexecuted instantiation: hb-subset.cc:OT::get_class_cached2(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::get_class_cached2(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::get_class_cached2(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-subset-table-var.cc:OT::get_class_cached2(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::get_class_cached2(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-subset-table-color.cc:OT::get_class_cached2(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: hb-subset-table-other.cc:OT::get_class_cached2(OT::ClassDef const&, hb_glyph_info_t&)
Unexecuted instantiation: gsubgpos-context.cc:OT::get_class_cached2(OT::ClassDef const&, hb_glyph_info_t&)
1863
static inline bool match_class_cached2 (hb_glyph_info_t &info, unsigned value, const void *data)
1864
0
{
1865
0
  const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
1866
0
  return get_class_cached2 (class_def, info) == value;
1867
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::match_class_cached2(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-face.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*)
Unexecuted instantiation: hb-subset.cc:OT::match_class_cached2(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::match_class_cached2(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::match_class_cached2(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::match_class_cached2(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::match_class_cached2(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::match_class_cached2(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::match_class_cached2(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: gsubgpos-context.cc:OT::match_class_cached2(hb_glyph_info_t&, unsigned int, void const*)
1868
static inline unsigned get_class_cached2_value (hb_glyph_info_t &info, const void *data)
1869
0
{
1870
0
  const ClassDef &class_def = *reinterpret_cast<const ClassDef *> (data);
1871
0
  return get_class_cached2 (class_def, info);
1872
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::get_class_cached2_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-ot-face.cc:OT::get_class_cached2_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-ot-layout.cc:OT::get_class_cached2_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::get_class_cached2_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::get_class_cached2_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset.cc:OT::get_class_cached2_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::get_class_cached2_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::get_class_cached2_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::get_class_cached2_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::get_class_cached2_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::get_class_cached2_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::get_class_cached2_value(hb_glyph_info_t&, void const*)
Unexecuted instantiation: gsubgpos-context.cc:OT::get_class_cached2_value(hb_glyph_info_t&, void const*)
1873
static inline bool match_coverage (hb_glyph_info_t &info, unsigned value, const void *data)
1874
180k
{
1875
180k
  Offset16To<Coverage> coverage;
1876
180k
  coverage = value;
1877
180k
  return (data+coverage).get_coverage (info.codepoint) != NOT_COVERED;
1878
180k
}
Unexecuted instantiation: hb-aat-layout.cc:OT::match_coverage(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-ot-face.cc:OT::match_coverage(hb_glyph_info_t&, unsigned int, void const*)
hb-ot-layout.cc:OT::match_coverage(hb_glyph_info_t&, unsigned int, void const*)
Line
Count
Source
1874
180k
{
1875
180k
  Offset16To<Coverage> coverage;
1876
180k
  coverage = value;
1877
180k
  return (data+coverage).get_coverage (info.codepoint) != NOT_COVERED;
1878
180k
}
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*)
Unexecuted instantiation: hb-subset.cc:OT::match_coverage(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::match_coverage(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::match_coverage(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::match_coverage(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::match_coverage(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::match_coverage(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::match_coverage(hb_glyph_info_t&, unsigned int, void const*)
Unexecuted instantiation: gsubgpos-context.cc:OT::match_coverage(hb_glyph_info_t&, unsigned int, void const*)
1879
1880
template <typename HBUINT>
1881
static inline bool would_match_input (hb_would_apply_context_t *c,
1882
              unsigned int count, /* Including the first glyph (not matched) */
1883
              const HBUINT input[], /* Array of input values--start with second glyph */
1884
              match_func_t match_func,
1885
              const void *match_data)
1886
0
{
1887
0
  if (count != c->len)
1888
0
    return false;
1889
1890
0
  for (unsigned int i = 1; i < count; i++)
1891
0
  {
1892
0
    hb_glyph_info_t info;
1893
0
    info.codepoint = c->glyphs[i];
1894
0
    if (likely (!match_func (info, input[i - 1], match_data)))
1895
0
      return false;
1896
0
  }
1897
1898
0
  return true;
1899
0
}
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-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-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*)
Unexecuted instantiation: hb-subset.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-subset-plan-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-subset-table-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-subset-table-var.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-subset-table-cff.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-subset-table-color.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-subset-table-other.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: gsubgpos-context.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*)
1900
template <typename HBUINT>
1901
#ifndef HB_OPTIMIZE_SIZE
1902
HB_ALWAYS_INLINE
1903
#endif
1904
static bool match_input (hb_ot_apply_context_t *c,
1905
       unsigned int count, /* Including the first glyph (not matched) */
1906
       const HBUINT input[], /* Array of input values--start with second glyph */
1907
       match_func_t match_func,
1908
       const void *match_data,
1909
       unsigned int *end_position,
1910
       unsigned int *p_total_component_count = nullptr)
1911
360k
{
1912
360k
  TRACE_APPLY (nullptr);
1913
1914
360k
  hb_buffer_t *buffer = c->buffer;
1915
1916
360k
  if (count == 1)
1917
217k
  {
1918
217k
    *end_position = buffer->idx + 1;
1919
217k
    c->match_positions[0] = buffer->idx;
1920
217k
    if (p_total_component_count)
1921
0
      *p_total_component_count = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
1922
217k
    return_trace (true);
1923
217k
  }
1924
1925
143k
  if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
1926
1927
143k
  auto &skippy_iter = c->iter_input;
1928
143k
  skippy_iter.reset (buffer->idx);
1929
143k
  skippy_iter.set_match_func (match_func, match_data);
1930
143k
  skippy_iter.set_glyph_data (input);
1931
1932
  /*
1933
   * This is perhaps the trickiest part of OpenType...  Remarks:
1934
   *
1935
   * - If all components of the ligature were marks, we call this a mark ligature.
1936
   *
1937
   * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
1938
   *   it as a ligature glyph.
1939
   *
1940
   * - Ligatures cannot be formed across glyphs attached to different components
1941
   *   of previous ligatures.  Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
1942
   *   LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
1943
   *   However, it would be wrong to ligate that SHADDA,FATHA sequence.
1944
   *   There are a couple of exceptions to this:
1945
   *
1946
   *   o If a ligature tries ligating with marks that belong to it itself, go ahead,
1947
   *     assuming that the font designer knows what they are doing (otherwise it can
1948
   *     break Indic stuff when a matra wants to ligate with a conjunct,
1949
   *
1950
   *   o If two marks want to ligate and they belong to different components of the
1951
   *     same ligature glyph, and said ligature glyph is to be ignored according to
1952
   *     mark-filtering rules, then allow.
1953
   *     https://github.com/harfbuzz/harfbuzz/issues/545
1954
   */
1955
1956
143k
  unsigned int total_component_count = 0;
1957
1958
143k
  unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
1959
143k
  unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
1960
1961
143k
  enum {
1962
143k
    LIGBASE_NOT_CHECKED,
1963
143k
    LIGBASE_MAY_NOT_SKIP,
1964
143k
    LIGBASE_MAY_SKIP
1965
143k
  } ligbase = LIGBASE_NOT_CHECKED;
1966
1967
143k
  for (unsigned int i = 1; i < count; i++)
1968
143k
  {
1969
143k
    unsigned unsafe_to;
1970
143k
    if (!skippy_iter.next (&unsafe_to))
1971
143k
    {
1972
143k
      *end_position = unsafe_to;
1973
143k
      return_trace (false);
1974
143k
    }
1975
1976
228
    if (unlikely (i + 1 > c->match_positions.length &&
1977
228
      !c->match_positions.resize_dirty  (i + 1)))
1978
0
      return_trace (false);
1979
228
    c->match_positions.arrayZ[i] = skippy_iter.idx;
1980
1981
228
    unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]);
1982
228
    unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]);
1983
1984
228
    if (first_lig_id && first_lig_comp)
1985
0
    {
1986
      /* If first component was attached to a previous ligature component,
1987
       * all subsequent components should be attached to the same ligature
1988
       * component, otherwise we shouldn't ligate them... */
1989
0
      if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
1990
0
      {
1991
  /* ...unless, we are attached to a base ligature and that base
1992
   * ligature is ignorable. */
1993
0
  if (ligbase == LIGBASE_NOT_CHECKED)
1994
0
  {
1995
0
    bool found = false;
1996
0
    const auto *out = buffer->out_info;
1997
0
    unsigned int j = buffer->out_len;
1998
0
    while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id)
1999
0
    {
2000
0
      if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0)
2001
0
      {
2002
0
        j--;
2003
0
        found = true;
2004
0
        break;
2005
0
      }
2006
0
      j--;
2007
0
    }
2008
2009
0
    if (found && skippy_iter.may_skip (out[j]) == matcher_t::SKIP_YES)
2010
0
      ligbase = LIGBASE_MAY_SKIP;
2011
0
    else
2012
0
      ligbase = LIGBASE_MAY_NOT_SKIP;
2013
0
  }
2014
2015
0
  if (ligbase == LIGBASE_MAY_NOT_SKIP)
2016
0
    return_trace (false);
2017
0
      }
2018
0
    }
2019
228
    else
2020
228
    {
2021
      /* If first component was NOT attached to a previous ligature component,
2022
       * all subsequent components should also NOT be attached to any ligature
2023
       * component, unless they are attached to the first component itself! */
2024
228
      if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
2025
0
  return_trace (false);
2026
228
    }
2027
2028
228
    total_component_count += _hb_glyph_info_get_lig_num_comps_in_ligation (&buffer->info[skippy_iter.idx]);
2029
228
  }
2030
2031
200
  *end_position = skippy_iter.idx + 1;
2032
2033
200
  if (p_total_component_count)
2034
68
  {
2035
68
    total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
2036
68
    *p_total_component_count = total_component_count;
2037
68
  }
2038
2039
200
  c->match_positions.arrayZ[0] = buffer->idx;
2040
2041
200
  return_trace (true);
2042
143k
}
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-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*)
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*)
Line
Count
Source
1911
114k
{
1912
114k
  TRACE_APPLY (nullptr);
1913
1914
114k
  hb_buffer_t *buffer = c->buffer;
1915
1916
114k
  if (count == 1)
1917
0
  {
1918
0
    *end_position = buffer->idx + 1;
1919
0
    c->match_positions[0] = buffer->idx;
1920
0
    if (p_total_component_count)
1921
0
      *p_total_component_count = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
1922
0
    return_trace (true);
1923
0
  }
1924
1925
114k
  if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
1926
1927
114k
  auto &skippy_iter = c->iter_input;
1928
114k
  skippy_iter.reset (buffer->idx);
1929
114k
  skippy_iter.set_match_func (match_func, match_data);
1930
114k
  skippy_iter.set_glyph_data (input);
1931
1932
  /*
1933
   * This is perhaps the trickiest part of OpenType...  Remarks:
1934
   *
1935
   * - If all components of the ligature were marks, we call this a mark ligature.
1936
   *
1937
   * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
1938
   *   it as a ligature glyph.
1939
   *
1940
   * - Ligatures cannot be formed across glyphs attached to different components
1941
   *   of previous ligatures.  Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
1942
   *   LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
1943
   *   However, it would be wrong to ligate that SHADDA,FATHA sequence.
1944
   *   There are a couple of exceptions to this:
1945
   *
1946
   *   o If a ligature tries ligating with marks that belong to it itself, go ahead,
1947
   *     assuming that the font designer knows what they are doing (otherwise it can
1948
   *     break Indic stuff when a matra wants to ligate with a conjunct,
1949
   *
1950
   *   o If two marks want to ligate and they belong to different components of the
1951
   *     same ligature glyph, and said ligature glyph is to be ignored according to
1952
   *     mark-filtering rules, then allow.
1953
   *     https://github.com/harfbuzz/harfbuzz/issues/545
1954
   */
1955
1956
114k
  unsigned int total_component_count = 0;
1957
1958
114k
  unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
1959
114k
  unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
1960
1961
114k
  enum {
1962
114k
    LIGBASE_NOT_CHECKED,
1963
114k
    LIGBASE_MAY_NOT_SKIP,
1964
114k
    LIGBASE_MAY_SKIP
1965
114k
  } ligbase = LIGBASE_NOT_CHECKED;
1966
1967
114k
  for (unsigned int i = 1; i < count; i++)
1968
114k
  {
1969
114k
    unsigned unsafe_to;
1970
114k
    if (!skippy_iter.next (&unsafe_to))
1971
114k
    {
1972
114k
      *end_position = unsafe_to;
1973
114k
      return_trace (false);
1974
114k
    }
1975
1976
96
    if (unlikely (i + 1 > c->match_positions.length &&
1977
96
      !c->match_positions.resize_dirty  (i + 1)))
1978
0
      return_trace (false);
1979
96
    c->match_positions.arrayZ[i] = skippy_iter.idx;
1980
1981
96
    unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]);
1982
96
    unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]);
1983
1984
96
    if (first_lig_id && first_lig_comp)
1985
0
    {
1986
      /* If first component was attached to a previous ligature component,
1987
       * all subsequent components should be attached to the same ligature
1988
       * component, otherwise we shouldn't ligate them... */
1989
0
      if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
1990
0
      {
1991
  /* ...unless, we are attached to a base ligature and that base
1992
   * ligature is ignorable. */
1993
0
  if (ligbase == LIGBASE_NOT_CHECKED)
1994
0
  {
1995
0
    bool found = false;
1996
0
    const auto *out = buffer->out_info;
1997
0
    unsigned int j = buffer->out_len;
1998
0
    while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id)
1999
0
    {
2000
0
      if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0)
2001
0
      {
2002
0
        j--;
2003
0
        found = true;
2004
0
        break;
2005
0
      }
2006
0
      j--;
2007
0
    }
2008
2009
0
    if (found && skippy_iter.may_skip (out[j]) == matcher_t::SKIP_YES)
2010
0
      ligbase = LIGBASE_MAY_SKIP;
2011
0
    else
2012
0
      ligbase = LIGBASE_MAY_NOT_SKIP;
2013
0
  }
2014
2015
0
  if (ligbase == LIGBASE_MAY_NOT_SKIP)
2016
0
    return_trace (false);
2017
0
      }
2018
0
    }
2019
96
    else
2020
96
    {
2021
      /* If first component was NOT attached to a previous ligature component,
2022
       * all subsequent components should also NOT be attached to any ligature
2023
       * component, unless they are attached to the first component itself! */
2024
96
      if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
2025
0
  return_trace (false);
2026
96
    }
2027
2028
96
    total_component_count += _hb_glyph_info_get_lig_num_comps_in_ligation (&buffer->info[skippy_iter.idx]);
2029
96
  }
2030
2031
68
  *end_position = skippy_iter.idx + 1;
2032
2033
68
  if (p_total_component_count)
2034
68
  {
2035
68
    total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
2036
68
    *p_total_component_count = total_component_count;
2037
68
  }
2038
2039
68
  c->match_positions.arrayZ[0] = buffer->idx;
2040
2041
68
  return_trace (true);
2042
114k
}
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*)
Line
Count
Source
1911
246k
{
1912
246k
  TRACE_APPLY (nullptr);
1913
1914
246k
  hb_buffer_t *buffer = c->buffer;
1915
1916
246k
  if (count == 1)
1917
217k
  {
1918
217k
    *end_position = buffer->idx + 1;
1919
217k
    c->match_positions[0] = buffer->idx;
1920
217k
    if (p_total_component_count)
1921
0
      *p_total_component_count = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
1922
217k
    return_trace (true);
1923
217k
  }
1924
1925
29.2k
  if (unlikely (count > HB_MAX_CONTEXT_LENGTH)) return_trace (false);
1926
1927
29.2k
  auto &skippy_iter = c->iter_input;
1928
29.2k
  skippy_iter.reset (buffer->idx);
1929
29.2k
  skippy_iter.set_match_func (match_func, match_data);
1930
29.2k
  skippy_iter.set_glyph_data (input);
1931
1932
  /*
1933
   * This is perhaps the trickiest part of OpenType...  Remarks:
1934
   *
1935
   * - If all components of the ligature were marks, we call this a mark ligature.
1936
   *
1937
   * - If there is no GDEF, and the ligature is NOT a mark ligature, we categorize
1938
   *   it as a ligature glyph.
1939
   *
1940
   * - Ligatures cannot be formed across glyphs attached to different components
1941
   *   of previous ligatures.  Eg. the sequence is LAM,SHADDA,LAM,FATHA,HEH, and
1942
   *   LAM,LAM,HEH form a ligature, leaving SHADDA,FATHA next to eachother.
1943
   *   However, it would be wrong to ligate that SHADDA,FATHA sequence.
1944
   *   There are a couple of exceptions to this:
1945
   *
1946
   *   o If a ligature tries ligating with marks that belong to it itself, go ahead,
1947
   *     assuming that the font designer knows what they are doing (otherwise it can
1948
   *     break Indic stuff when a matra wants to ligate with a conjunct,
1949
   *
1950
   *   o If two marks want to ligate and they belong to different components of the
1951
   *     same ligature glyph, and said ligature glyph is to be ignored according to
1952
   *     mark-filtering rules, then allow.
1953
   *     https://github.com/harfbuzz/harfbuzz/issues/545
1954
   */
1955
1956
29.2k
  unsigned int total_component_count = 0;
1957
1958
29.2k
  unsigned int first_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
1959
29.2k
  unsigned int first_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
1960
1961
29.2k
  enum {
1962
29.2k
    LIGBASE_NOT_CHECKED,
1963
29.2k
    LIGBASE_MAY_NOT_SKIP,
1964
29.2k
    LIGBASE_MAY_SKIP
1965
29.2k
  } ligbase = LIGBASE_NOT_CHECKED;
1966
1967
29.3k
  for (unsigned int i = 1; i < count; i++)
1968
29.2k
  {
1969
29.2k
    unsigned unsafe_to;
1970
29.2k
    if (!skippy_iter.next (&unsafe_to))
1971
29.0k
    {
1972
29.0k
      *end_position = unsafe_to;
1973
29.0k
      return_trace (false);
1974
29.0k
    }
1975
1976
132
    if (unlikely (i + 1 > c->match_positions.length &&
1977
132
      !c->match_positions.resize_dirty  (i + 1)))
1978
0
      return_trace (false);
1979
132
    c->match_positions.arrayZ[i] = skippy_iter.idx;
1980
1981
132
    unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]);
1982
132
    unsigned int this_lig_comp = _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]);
1983
1984
132
    if (first_lig_id && first_lig_comp)
1985
0
    {
1986
      /* If first component was attached to a previous ligature component,
1987
       * all subsequent components should be attached to the same ligature
1988
       * component, otherwise we shouldn't ligate them... */
1989
0
      if (first_lig_id != this_lig_id || first_lig_comp != this_lig_comp)
1990
0
      {
1991
  /* ...unless, we are attached to a base ligature and that base
1992
   * ligature is ignorable. */
1993
0
  if (ligbase == LIGBASE_NOT_CHECKED)
1994
0
  {
1995
0
    bool found = false;
1996
0
    const auto *out = buffer->out_info;
1997
0
    unsigned int j = buffer->out_len;
1998
0
    while (j && _hb_glyph_info_get_lig_id (&out[j - 1]) == first_lig_id)
1999
0
    {
2000
0
      if (_hb_glyph_info_get_lig_comp (&out[j - 1]) == 0)
2001
0
      {
2002
0
        j--;
2003
0
        found = true;
2004
0
        break;
2005
0
      }
2006
0
      j--;
2007
0
    }
2008
2009
0
    if (found && skippy_iter.may_skip (out[j]) == matcher_t::SKIP_YES)
2010
0
      ligbase = LIGBASE_MAY_SKIP;
2011
0
    else
2012
0
      ligbase = LIGBASE_MAY_NOT_SKIP;
2013
0
  }
2014
2015
0
  if (ligbase == LIGBASE_MAY_NOT_SKIP)
2016
0
    return_trace (false);
2017
0
      }
2018
0
    }
2019
132
    else
2020
132
    {
2021
      /* If first component was NOT attached to a previous ligature component,
2022
       * all subsequent components should also NOT be attached to any ligature
2023
       * component, unless they are attached to the first component itself! */
2024
132
      if (this_lig_id && this_lig_comp && (this_lig_id != first_lig_id))
2025
0
  return_trace (false);
2026
132
    }
2027
2028
132
    total_component_count += _hb_glyph_info_get_lig_num_comps_in_ligation (&buffer->info[skippy_iter.idx]);
2029
132
  }
2030
2031
132
  *end_position = skippy_iter.idx + 1;
2032
2033
132
  if (p_total_component_count)
2034
0
  {
2035
0
    total_component_count += _hb_glyph_info_get_lig_num_comps (&buffer->cur());
2036
0
    *p_total_component_count = total_component_count;
2037
0
  }
2038
2039
132
  c->match_positions.arrayZ[0] = buffer->idx;
2040
2041
132
  return_trace (true);
2042
29.2k
}
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*)
Unexecuted instantiation: hb-subset.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-subset-plan-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-subset-plan-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-subset-table-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-subset-table-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-subset-table-var.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-subset-table-cff.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-subset-table-color.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-subset-table-other.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: gsubgpos-context.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*)
2043
static inline bool ligate_input (hb_ot_apply_context_t *c,
2044
         unsigned int count, /* Including the first glyph */
2045
         unsigned int match_end,
2046
         hb_codepoint_t lig_glyph,
2047
         unsigned int total_component_count)
2048
68
{
2049
68
  TRACE_APPLY (nullptr);
2050
2051
68
  hb_buffer_t *buffer = c->buffer;
2052
2053
68
  buffer->merge_clusters (buffer->idx, match_end);
2054
2055
  /* - If a base and one or more marks ligate, consider that as a base, NOT
2056
   *   ligature, such that all following marks can still attach to it.
2057
   *   https://github.com/harfbuzz/harfbuzz/issues/1109
2058
   *
2059
   * - If all components of the ligature were marks, we call this a mark ligature.
2060
   *   If it *is* a mark ligature, we don't allocate a new ligature id, and leave
2061
   *   the ligature to keep its old ligature id.  This will allow it to attach to
2062
   *   a base ligature in GPOS.  Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
2063
   *   and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA with a
2064
   *   ligature id and component value of 2.  Then if SHADDA,FATHA form a ligature
2065
   *   later, we don't want them to lose their ligature id/component, otherwise
2066
   *   GPOS will fail to correctly position the mark ligature on top of the
2067
   *   LAM,LAM,HEH ligature.  See:
2068
   *     https://bugzilla.gnome.org/show_bug.cgi?id=676343
2069
   *
2070
   * - If a ligature is formed of components that some of which are also ligatures
2071
   *   themselves, and those ligature components had marks attached to *their*
2072
   *   components, we have to attach the marks to the new ligature component
2073
   *   positions!  Now *that*'s tricky!  And these marks may be following the
2074
   *   last component of the whole sequence, so we should loop forward looking
2075
   *   for them and update them.
2076
   *
2077
   *   Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
2078
   *   'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
2079
   *   id and component == 1.  Now, during 'liga', the LAM and the LAM-HEH ligature
2080
   *   form a LAM-LAM-HEH ligature.  We need to reassign the SHADDA and FATHA to
2081
   *   the new ligature with a component value of 2.
2082
   *
2083
   *   This in fact happened to a font...  See:
2084
   *   https://bugzilla.gnome.org/show_bug.cgi?id=437633
2085
   */
2086
2087
68
  bool is_base_ligature = _hb_glyph_info_is_base_glyph (&buffer->info[c->match_positions.arrayZ[0]]);
2088
68
  bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->info[c->match_positions.arrayZ[0]]);
2089
148
  for (unsigned int i = 1; i < count; i++)
2090
80
    if (!_hb_glyph_info_is_mark (&buffer->info[c->match_positions.arrayZ[i]]))
2091
0
    {
2092
0
      is_base_ligature = false;
2093
0
      is_mark_ligature = false;
2094
0
      break;
2095
0
    }
2096
68
  bool is_ligature = !is_base_ligature && !is_mark_ligature;
2097
2098
68
  unsigned int klass = is_ligature ? HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE : 0;
2099
68
  unsigned int lig_id = is_ligature ? _hb_allocate_lig_id (buffer) : 0;
2100
68
  unsigned int last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
2101
68
  unsigned int last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
2102
68
  unsigned int components_so_far = last_num_components;
2103
2104
68
  if (is_ligature)
2105
0
  {
2106
0
    _hb_glyph_info_set_lig_props_for_ligature (&buffer->cur(), lig_id, total_component_count);
2107
0
    if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
2108
0
    {
2109
0
      _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER);
2110
0
    }
2111
0
  }
2112
68
  c->replace_glyph_with_ligature (lig_glyph, klass);
2113
2114
148
  for (unsigned int i = 1; i < count; i++)
2115
80
  {
2116
80
    while (buffer->idx < c->match_positions.arrayZ[i] && buffer->successful)
2117
0
    {
2118
0
      if (is_ligature)
2119
0
      {
2120
0
  unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
2121
0
  if (this_comp == 0)
2122
0
    this_comp = last_num_components;
2123
0
  assert (components_so_far >= last_num_components);
2124
0
  unsigned int new_lig_comp = components_so_far - last_num_components +
2125
0
            hb_min (this_comp, last_num_components);
2126
0
    _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
2127
0
      }
2128
0
      (void) buffer->next_glyph ();
2129
0
    }
2130
2131
80
    last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
2132
80
    last_num_components = _hb_glyph_info_get_lig_num_comps_in_ligation (&buffer->cur());
2133
80
    components_so_far += last_num_components;
2134
2135
    /* Skip the base glyph */
2136
80
    buffer->idx++;
2137
80
  }
2138
2139
68
  if (!is_mark_ligature && last_lig_id)
2140
0
  {
2141
    /* Re-adjust components for any marks following. */
2142
0
    for (unsigned i = buffer->idx; i < buffer->len; ++i)
2143
0
    {
2144
0
      if (last_lig_id != _hb_glyph_info_get_lig_id (&buffer->info[i])) break;
2145
2146
0
      unsigned this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
2147
0
      if (!this_comp) break;
2148
2149
0
      assert (components_so_far >= last_num_components);
2150
0
      unsigned new_lig_comp = components_so_far - last_num_components +
2151
0
            hb_min (this_comp, last_num_components);
2152
0
      _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
2153
0
    }
2154
0
  }
2155
68
  return_trace (true);
2156
68
}
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-face.cc:OT::ligate_input(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, unsigned int, unsigned int)
hb-ot-layout.cc:OT::ligate_input(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, unsigned int, unsigned int)
Line
Count
Source
2048
68
{
2049
68
  TRACE_APPLY (nullptr);
2050
2051
68
  hb_buffer_t *buffer = c->buffer;
2052
2053
68
  buffer->merge_clusters (buffer->idx, match_end);
2054
2055
  /* - If a base and one or more marks ligate, consider that as a base, NOT
2056
   *   ligature, such that all following marks can still attach to it.
2057
   *   https://github.com/harfbuzz/harfbuzz/issues/1109
2058
   *
2059
   * - If all components of the ligature were marks, we call this a mark ligature.
2060
   *   If it *is* a mark ligature, we don't allocate a new ligature id, and leave
2061
   *   the ligature to keep its old ligature id.  This will allow it to attach to
2062
   *   a base ligature in GPOS.  Eg. if the sequence is: LAM,LAM,SHADDA,FATHA,HEH,
2063
   *   and LAM,LAM,HEH for a ligature, they will leave SHADDA and FATHA with a
2064
   *   ligature id and component value of 2.  Then if SHADDA,FATHA form a ligature
2065
   *   later, we don't want them to lose their ligature id/component, otherwise
2066
   *   GPOS will fail to correctly position the mark ligature on top of the
2067
   *   LAM,LAM,HEH ligature.  See:
2068
   *     https://bugzilla.gnome.org/show_bug.cgi?id=676343
2069
   *
2070
   * - If a ligature is formed of components that some of which are also ligatures
2071
   *   themselves, and those ligature components had marks attached to *their*
2072
   *   components, we have to attach the marks to the new ligature component
2073
   *   positions!  Now *that*'s tricky!  And these marks may be following the
2074
   *   last component of the whole sequence, so we should loop forward looking
2075
   *   for them and update them.
2076
   *
2077
   *   Eg. the sequence is LAM,LAM,SHADDA,FATHA,HEH, and the font first forms a
2078
   *   'calt' ligature of LAM,HEH, leaving the SHADDA and FATHA with a ligature
2079
   *   id and component == 1.  Now, during 'liga', the LAM and the LAM-HEH ligature
2080
   *   form a LAM-LAM-HEH ligature.  We need to reassign the SHADDA and FATHA to
2081
   *   the new ligature with a component value of 2.
2082
   *
2083
   *   This in fact happened to a font...  See:
2084
   *   https://bugzilla.gnome.org/show_bug.cgi?id=437633
2085
   */
2086
2087
68
  bool is_base_ligature = _hb_glyph_info_is_base_glyph (&buffer->info[c->match_positions.arrayZ[0]]);
2088
68
  bool is_mark_ligature = _hb_glyph_info_is_mark (&buffer->info[c->match_positions.arrayZ[0]]);
2089
148
  for (unsigned int i = 1; i < count; i++)
2090
80
    if (!_hb_glyph_info_is_mark (&buffer->info[c->match_positions.arrayZ[i]]))
2091
0
    {
2092
0
      is_base_ligature = false;
2093
0
      is_mark_ligature = false;
2094
0
      break;
2095
0
    }
2096
68
  bool is_ligature = !is_base_ligature && !is_mark_ligature;
2097
2098
68
  unsigned int klass = is_ligature ? HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE : 0;
2099
68
  unsigned int lig_id = is_ligature ? _hb_allocate_lig_id (buffer) : 0;
2100
68
  unsigned int last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
2101
68
  unsigned int last_num_components = _hb_glyph_info_get_lig_num_comps (&buffer->cur());
2102
68
  unsigned int components_so_far = last_num_components;
2103
2104
68
  if (is_ligature)
2105
0
  {
2106
0
    _hb_glyph_info_set_lig_props_for_ligature (&buffer->cur(), lig_id, total_component_count);
2107
0
    if (_hb_glyph_info_get_general_category (&buffer->cur()) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
2108
0
    {
2109
0
      _hb_glyph_info_set_general_category (&buffer->cur(), HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER);
2110
0
    }
2111
0
  }
2112
68
  c->replace_glyph_with_ligature (lig_glyph, klass);
2113
2114
148
  for (unsigned int i = 1; i < count; i++)
2115
80
  {
2116
80
    while (buffer->idx < c->match_positions.arrayZ[i] && buffer->successful)
2117
0
    {
2118
0
      if (is_ligature)
2119
0
      {
2120
0
  unsigned int this_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
2121
0
  if (this_comp == 0)
2122
0
    this_comp = last_num_components;
2123
0
  assert (components_so_far >= last_num_components);
2124
0
  unsigned int new_lig_comp = components_so_far - last_num_components +
2125
0
            hb_min (this_comp, last_num_components);
2126
0
    _hb_glyph_info_set_lig_props_for_mark (&buffer->cur(), lig_id, new_lig_comp);
2127
0
      }
2128
0
      (void) buffer->next_glyph ();
2129
0
    }
2130
2131
80
    last_lig_id = _hb_glyph_info_get_lig_id (&buffer->cur());
2132
80
    last_num_components = _hb_glyph_info_get_lig_num_comps_in_ligation (&buffer->cur());
2133
80
    components_so_far += last_num_components;
2134
2135
    /* Skip the base glyph */
2136
80
    buffer->idx++;
2137
80
  }
2138
2139
68
  if (!is_mark_ligature && last_lig_id)
2140
0
  {
2141
    /* Re-adjust components for any marks following. */
2142
0
    for (unsigned i = buffer->idx; i < buffer->len; ++i)
2143
0
    {
2144
0
      if (last_lig_id != _hb_glyph_info_get_lig_id (&buffer->info[i])) break;
2145
2146
0
      unsigned this_comp = _hb_glyph_info_get_lig_comp (&buffer->info[i]);
2147
0
      if (!this_comp) break;
2148
2149
0
      assert (components_so_far >= last_num_components);
2150
0
      unsigned new_lig_comp = components_so_far - last_num_components +
2151
0
            hb_min (this_comp, last_num_components);
2152
0
      _hb_glyph_info_set_lig_props_for_mark (&buffer->info[i], lig_id, new_lig_comp);
2153
0
    }
2154
0
  }
2155
68
  return_trace (true);
2156
68
}
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)
Unexecuted instantiation: hb-subset.cc:OT::ligate_input(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::ligate_input(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::ligate_input(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset-table-var.cc:OT::ligate_input(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::ligate_input(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset-table-color.cc:OT::ligate_input(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset-table-other.cc:OT::ligate_input(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: gsubgpos-context.cc:OT::ligate_input(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, unsigned int, unsigned int)
2157
2158
template <typename HBUINT>
2159
#ifndef HB_OPTIMIZE_SIZE
2160
HB_ALWAYS_INLINE
2161
#endif
2162
static bool match_backtrack (hb_ot_apply_context_t *c,
2163
           unsigned int count,
2164
           const HBUINT backtrack[],
2165
           match_func_t match_func,
2166
           const void *match_data,
2167
           unsigned int *match_start)
2168
135k
{
2169
135k
  TRACE_APPLY (nullptr);
2170
2171
135k
  if (!count)
2172
79
  {
2173
79
    *match_start = c->buffer->backtrack_len ();
2174
79
    return_trace (true);
2175
79
  }
2176
2177
135k
  auto &skippy_iter = c->iter_context;
2178
135k
  skippy_iter.reset_back (c->buffer->backtrack_len ());
2179
135k
  skippy_iter.set_match_func (match_func, match_data);
2180
135k
  skippy_iter.set_glyph_data (backtrack);
2181
2182
160k
  for (unsigned int i = 0; i < count; i++)
2183
160k
  {
2184
160k
    unsigned unsafe_from;
2185
160k
    if (!skippy_iter.prev (&unsafe_from))
2186
134k
    {
2187
134k
      *match_start = unsafe_from;
2188
134k
      return_trace (false);
2189
134k
    }
2190
160k
  }
2191
2192
294
  *match_start = skippy_iter.idx;
2193
294
  return_trace (true);
2194
135k
}
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-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*)
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*)
Line
Count
Source
2168
135k
{
2169
135k
  TRACE_APPLY (nullptr);
2170
2171
135k
  if (!count)
2172
79
  {
2173
79
    *match_start = c->buffer->backtrack_len ();
2174
79
    return_trace (true);
2175
79
  }
2176
2177
135k
  auto &skippy_iter = c->iter_context;
2178
135k
  skippy_iter.reset_back (c->buffer->backtrack_len ());
2179
135k
  skippy_iter.set_match_func (match_func, match_data);
2180
135k
  skippy_iter.set_glyph_data (backtrack);
2181
2182
160k
  for (unsigned int i = 0; i < count; i++)
2183
160k
  {
2184
160k
    unsigned unsafe_from;
2185
160k
    if (!skippy_iter.prev (&unsafe_from))
2186
134k
    {
2187
134k
      *match_start = unsafe_from;
2188
134k
      return_trace (false);
2189
134k
    }
2190
160k
  }
2191
2192
294
  *match_start = skippy_iter.idx;
2193
294
  return_trace (true);
2194
135k
}
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*)
Unexecuted instantiation: hb-subset.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-subset-plan-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-subset-table-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-subset-table-var.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-subset-table-cff.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-subset-table-color.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-subset-table-other.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: gsubgpos-context.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*)
2195
2196
template <typename HBUINT>
2197
#ifndef HB_OPTIMIZE_SIZE
2198
HB_ALWAYS_INLINE
2199
#endif
2200
static bool match_lookahead (hb_ot_apply_context_t *c,
2201
           unsigned int count,
2202
           const HBUINT lookahead[],
2203
           match_func_t match_func,
2204
           const void *match_data,
2205
           unsigned int start_index,
2206
           unsigned int *end_index)
2207
217k
{
2208
217k
  TRACE_APPLY (nullptr);
2209
2210
217k
  if (!count)
2211
109k
  {
2212
109k
    *end_index = start_index;
2213
109k
    return_trace (true);
2214
109k
  }
2215
2216
107k
  auto &skippy_iter = c->iter_context;
2217
107k
  assert (start_index >= 1);
2218
107k
  skippy_iter.reset (start_index - 1);
2219
107k
  skippy_iter.set_match_func (match_func, match_data);
2220
107k
  skippy_iter.set_glyph_data (lookahead);
2221
2222
132k
  for (unsigned int i = 0; i < count; i++)
2223
107k
  {
2224
107k
    unsigned unsafe_to;
2225
107k
    if (!skippy_iter.next (&unsafe_to))
2226
82.3k
    {
2227
82.3k
      *end_index = unsafe_to;
2228
82.3k
      return_trace (false);
2229
82.3k
    }
2230
107k
  }
2231
2232
25.2k
  *end_index = skippy_iter.idx + 1;
2233
25.2k
  return_trace (true);
2234
107k
}
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-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*)
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*)
Line
Count
Source
2207
217k
{
2208
217k
  TRACE_APPLY (nullptr);
2209
2210
217k
  if (!count)
2211
109k
  {
2212
109k
    *end_index = start_index;
2213
109k
    return_trace (true);
2214
109k
  }
2215
2216
107k
  auto &skippy_iter = c->iter_context;
2217
107k
  assert (start_index >= 1);
2218
107k
  skippy_iter.reset (start_index - 1);
2219
107k
  skippy_iter.set_match_func (match_func, match_data);
2220
107k
  skippy_iter.set_glyph_data (lookahead);
2221
2222
132k
  for (unsigned int i = 0; i < count; i++)
2223
107k
  {
2224
107k
    unsigned unsafe_to;
2225
107k
    if (!skippy_iter.next (&unsafe_to))
2226
82.3k
    {
2227
82.3k
      *end_index = unsafe_to;
2228
82.3k
      return_trace (false);
2229
82.3k
    }
2230
107k
  }
2231
2232
25.2k
  *end_index = skippy_iter.idx + 1;
2233
25.2k
  return_trace (true);
2234
107k
}
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*)
Unexecuted instantiation: hb-subset.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-subset-plan-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-subset-table-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-subset-table-var.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-subset-table-cff.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-subset-table-color.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-subset-table-other.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: gsubgpos-context.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*)
2235
2236
2237
2238
struct LookupRecord
2239
{
2240
  bool serialize (hb_serialize_context_t *c,
2241
      const hb_map_t         *lookup_map) const
2242
0
  {
2243
0
    TRACE_SERIALIZE (this);
2244
0
    auto *out = c->embed (*this);
2245
0
    if (unlikely (!out)) return_trace (false);
2246
2247
0
    return_trace (c->check_assign (out->lookupListIndex, lookup_map->get (lookupListIndex), HB_SERIALIZE_ERROR_INT_OVERFLOW));
2248
0
  }
2249
2250
  bool sanitize (hb_sanitize_context_t *c) const
2251
0
  {
2252
0
    TRACE_SANITIZE (this);
2253
0
    return_trace (c->check_struct (this));
2254
0
  }
2255
2256
  HBUINT16  sequenceIndex;    /* Index into current glyph
2257
           * sequence--first glyph = 0 */
2258
  HBUINT16  lookupListIndex;  /* Lookup to apply to that
2259
           * position--zero--based */
2260
  public:
2261
  DEFINE_SIZE_STATIC (4);
2262
};
2263
2264
static unsigned serialize_lookuprecord_array (hb_serialize_context_t *c,
2265
                const hb_array_t<const LookupRecord> lookupRecords,
2266
                const hb_map_t *lookup_map)
2267
0
{
2268
0
  unsigned count = 0;
2269
0
  for (const LookupRecord& r : lookupRecords)
2270
0
  {
2271
0
    if (!lookup_map->has (r.lookupListIndex))
2272
0
      continue;
2273
2274
0
    if (!r.serialize (c, lookup_map))
2275
0
      return 0;
2276
2277
0
    count++;
2278
0
  }
2279
0
  return count;
2280
0
}
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-face.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*)
Unexecuted instantiation: hb-subset.cc:OT::serialize_lookuprecord_array(hb_serialize_context_t*, hb_array_t<OT::LookupRecord const>, hb_map_t const*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::serialize_lookuprecord_array(hb_serialize_context_t*, hb_array_t<OT::LookupRecord const>, hb_map_t const*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::serialize_lookuprecord_array(hb_serialize_context_t*, hb_array_t<OT::LookupRecord const>, hb_map_t const*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::serialize_lookuprecord_array(hb_serialize_context_t*, hb_array_t<OT::LookupRecord const>, hb_map_t const*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::serialize_lookuprecord_array(hb_serialize_context_t*, hb_array_t<OT::LookupRecord const>, hb_map_t const*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::serialize_lookuprecord_array(hb_serialize_context_t*, hb_array_t<OT::LookupRecord const>, hb_map_t const*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::serialize_lookuprecord_array(hb_serialize_context_t*, hb_array_t<OT::LookupRecord const>, hb_map_t const*)
Unexecuted instantiation: gsubgpos-context.cc:OT::serialize_lookuprecord_array(hb_serialize_context_t*, hb_array_t<OT::LookupRecord const>, hb_map_t const*)
2281
2282
enum ContextFormat { SimpleContext = 1, ClassBasedContext = 2, CoverageBasedContext = 3 };
2283
2284
static inline const hb_set_t *
2285
depend_position_glyphs (hb_depend_context_t *c,
2286
      ContextFormat context_format,
2287
      const void *data,
2288
      unsigned value,
2289
      bool filter_class_by_parent,
2290
      hb_set_t *scratch,
2291
      hb_vector_t<unsigned> *compact_workspace = nullptr)
2292
0
{
2293
0
  switch (context_format)
2294
0
  {
2295
0
    case ContextFormat::SimpleContext:
2296
0
      return c->find_or_create_glyph_set (nullptr, value,
2297
0
                                           hb_depend_context_t::GLYPH_SET_SINGLE);
2298
0
    case ContextFormat::ClassBasedContext:
2299
0
    {
2300
0
      const hb_set_t *class_set = c->find_or_create_glyph_set (
2301
0
        data, value, hb_depend_context_t::GLYPH_SET_CLASS);
2302
0
      if (unlikely (!class_set))
2303
0
  return nullptr;
2304
0
      if (!filter_class_by_parent)
2305
0
  return class_set;
2306
0
      scratch->set (*class_set);
2307
0
      scratch->intersect (c->parent_active_glyphs (), compact_workspace);
2308
0
      break;
2309
0
    }
2310
0
    case ContextFormat::CoverageBasedContext:
2311
0
      return c->find_or_create_glyph_set (
2312
0
        data, value, hb_depend_context_t::GLYPH_SET_COVERAGE);
2313
0
  }
2314
0
2315
0
  if (unlikely (scratch->in_error ()))
2316
0
  {
2317
0
    c->depend_data->fail ();
2318
0
    return nullptr;
2319
0
  }
2320
0
  return scratch;
2321
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::depend_position_glyphs(OT::hb_depend_context_t*, OT::ContextFormat, void const*, unsigned int, bool, hb_set_t*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-ot-face.cc:OT::depend_position_glyphs(OT::hb_depend_context_t*, OT::ContextFormat, void const*, unsigned int, bool, hb_set_t*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-ot-layout.cc:OT::depend_position_glyphs(OT::hb_depend_context_t*, OT::ContextFormat, void const*, unsigned int, bool, hb_set_t*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::depend_position_glyphs(OT::hb_depend_context_t*, OT::ContextFormat, void const*, unsigned int, bool, hb_set_t*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::depend_position_glyphs(OT::hb_depend_context_t*, OT::ContextFormat, void const*, unsigned int, bool, hb_set_t*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-subset.cc:OT::depend_position_glyphs(OT::hb_depend_context_t*, OT::ContextFormat, void const*, unsigned int, bool, hb_set_t*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::depend_position_glyphs(OT::hb_depend_context_t*, OT::ContextFormat, void const*, unsigned int, bool, hb_set_t*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::depend_position_glyphs(OT::hb_depend_context_t*, OT::ContextFormat, void const*, unsigned int, bool, hb_set_t*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::depend_position_glyphs(OT::hb_depend_context_t*, OT::ContextFormat, void const*, unsigned int, bool, hb_set_t*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::depend_position_glyphs(OT::hb_depend_context_t*, OT::ContextFormat, void const*, unsigned int, bool, hb_set_t*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::depend_position_glyphs(OT::hb_depend_context_t*, OT::ContextFormat, void const*, unsigned int, bool, hb_set_t*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::depend_position_glyphs(OT::hb_depend_context_t*, OT::ContextFormat, void const*, unsigned int, bool, hb_set_t*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: gsubgpos-context.cc:OT::depend_position_glyphs(OT::hb_depend_context_t*, OT::ContextFormat, void const*, unsigned int, bool, hb_set_t*, hb_vector_t<unsigned int, false>*)
2322
2323
template <typename HBUINT>
2324
static void context_closure_recurse_lookups (hb_closure_context_t *c,
2325
               unsigned inputCount, const HBUINT input[],
2326
               unsigned lookupCount,
2327
               const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */,
2328
               unsigned value,
2329
               ContextFormat context_format,
2330
               const void *data,
2331
               intersected_glyphs_func_t intersected_glyphs_func,
2332
               void *cache)
2333
0
{
2334
0
  hb_set_t covered_seq_indicies;
2335
0
  hb_set_t pos_glyphs;
2336
0
  for (unsigned int i = 0; i < lookupCount; i++)
2337
0
  {
2338
0
    unsigned seqIndex = lookupRecord[i].sequenceIndex;
2339
0
    if (seqIndex >= inputCount) continue;
2340
2341
0
    bool has_pos_glyphs = false;
2342
2343
0
    if (!covered_seq_indicies.has (seqIndex))
2344
0
    {
2345
0
      has_pos_glyphs = true;
2346
0
      pos_glyphs.clear ();
2347
0
      if (seqIndex == 0)
2348
0
      {
2349
0
        switch (context_format) {
2350
0
        case ContextFormat::SimpleContext:
2351
0
          pos_glyphs.add (value);
2352
0
          break;
2353
0
        case ContextFormat::ClassBasedContext:
2354
0
          intersected_glyphs_func (&c->parent_active_glyphs (), data, value, &pos_glyphs, cache);
2355
0
          break;
2356
0
        case ContextFormat::CoverageBasedContext:
2357
0
          pos_glyphs.set (c->parent_active_glyphs ());
2358
0
          break;
2359
0
        }
2360
0
      }
2361
0
      else
2362
0
      {
2363
0
        const void *input_data = input;
2364
0
        unsigned input_value = seqIndex - 1;
2365
0
        if (context_format != ContextFormat::SimpleContext)
2366
0
        {
2367
0
          input_data = data;
2368
0
          input_value = input[seqIndex - 1];
2369
0
        }
2370
2371
0
        intersected_glyphs_func (c->glyphs, input_data, input_value, &pos_glyphs, cache);
2372
0
      }
2373
0
    }
2374
2375
0
    covered_seq_indicies.add (seqIndex);
2376
0
    hb_set_t *cur_active_glyphs = c->push_cur_active_glyphs ();
2377
0
    if (unlikely (!cur_active_glyphs))
2378
0
      return;
2379
0
    if (has_pos_glyphs) {
2380
0
      *cur_active_glyphs = std::move (pos_glyphs);
2381
0
    } else {
2382
0
      *cur_active_glyphs = *c->glyphs;
2383
0
    }
2384
2385
0
    unsigned endIndex = inputCount;
2386
0
    if (context_format == ContextFormat::CoverageBasedContext)
2387
0
      endIndex += 1;
2388
2389
0
    c->recurse (lookupRecord[i].lookupListIndex, &covered_seq_indicies, seqIndex, endIndex);
2390
2391
0
    c->pop_cur_done_glyphs ();
2392
0
  }
2393
0
}
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-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-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*)
Unexecuted instantiation: hb-subset.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-subset-plan-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-subset-table-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-subset-table-var.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-subset-table-cff.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-subset-table-color.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-subset-table-other.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: gsubgpos-context.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*)
2394
2395
static bool
2396
context_depend_sets_are_cached (hb_depend_context_t *c,
2397
        unsigned input_count,
2398
        unsigned lookup_count,
2399
        const LookupRecord lookup_records[],
2400
        const void *rule,
2401
        unsigned value,
2402
        ContextFormat context_format,
2403
        const void *data,
2404
        hb_vector_t<hb_codepoint_t> *cached_context_sets)
2405
0
{
2406
0
  hb_codepoint_t active_idx = HB_CODEPOINT_INVALID;
2407
0
  bool have_active_idx = false;
2408
0
  for (unsigned i = 0; i < lookup_count; i++)
2409
0
  {
2410
0
    if (lookup_records[i].sequenceIndex >= input_count)
2411
0
      continue;
2412
0
2413
0
    if (!have_active_idx)
2414
0
    {
2415
0
      if (unlikely (!c->get_parent_active_glyphs_index (&active_idx)))
2416
0
  return false;
2417
0
      have_active_idx = true;
2418
0
    }
2419
0
2420
0
    hb_depend_context_t::context_set_cache_key_t key (
2421
0
      rule, &lookup_records[i], data, active_idx, value, context_format);
2422
0
    hb_codepoint_t *cached_context_set = nullptr;
2423
0
    if (!c->context_set_cache.has (key, &cached_context_set))
2424
0
      return false;
2425
0
    if (unlikely (!cached_context_sets->push_or_fail (*cached_context_set)))
2426
0
      return c->depend_data->fail ();
2427
0
  }
2428
0
  /* A rule with no valid records has no cache entries, and its preparation
2429
0
   * can still allocate dependency sets in an observable order. */
2430
0
  return have_active_idx;
2431
0
}
Unexecuted instantiation: hb-aat-layout.cc:OT::context_depend_sets_are_cached(OT::hb_depend_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-ot-face.cc:OT::context_depend_sets_are_cached(OT::hb_depend_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-ot-layout.cc:OT::context_depend_sets_are_cached(OT::hb_depend_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::context_depend_sets_are_cached(OT::hb_depend_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::context_depend_sets_are_cached(OT::hb_depend_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-subset.cc:OT::context_depend_sets_are_cached(OT::hb_depend_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::context_depend_sets_are_cached(OT::hb_depend_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::context_depend_sets_are_cached(OT::hb_depend_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-subset-table-var.cc:OT::context_depend_sets_are_cached(OT::hb_depend_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::context_depend_sets_are_cached(OT::hb_depend_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-subset-table-color.cc:OT::context_depend_sets_are_cached(OT::hb_depend_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: hb-subset-table-other.cc:OT::context_depend_sets_are_cached(OT::hb_depend_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, hb_vector_t<unsigned int, false>*)
Unexecuted instantiation: gsubgpos-context.cc:OT::context_depend_sets_are_cached(OT::hb_depend_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, hb_vector_t<unsigned int, false>*)
2432
2433
template <typename HBUINT>
2434
static void context_depend_recurse_lookups (hb_depend_context_t *c,
2435
               unsigned inputCount, const HBUINT input[],
2436
               unsigned lookupCount,
2437
               const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */,
2438
               const void *rule,
2439
               unsigned value,
2440
               ContextFormat context_format,
2441
               const void *data,
2442
               intersected_glyphs_func_t intersected_glyphs_func,
2443
               void *cache,
2444
               const hb_set_t &preliminary_context,
2445
               const hb_vector_t<const hb_set_t *> *input_position_glyphs,
2446
               const hb_vector_t<hb_codepoint_t> *cached_context_sets,
2447
               hb_depend_context_t::depend_scratch_t *scratch)
2448
0
{
2449
0
  /* For depend graph extraction, we filter active glyphs by InputCoverage constraints
2450
0
   * (same as closure), but we do NOT do sequential accumulation of outputs.
2451
0
   *
2452
0
   * - Position filtering (InputCoverage): Required. The contextual rule can only match
2453
0
   *   glyphs in its InputCoverage. Edges for other glyphs are spurious.
2454
0
   * - Sequential accumulation: Not done. We want ALL possible edges, so we don't
2455
0
   *   limit later lookups based on outputs from earlier lookups in the same rule. */
2456
0
2457
0
  /* Sequence positions are tracked in one allocation-free bit page below.
2458
0
   * A rule longer than HB_MAX_CONTEXT_LENGTH never applies during shaping
2459
0
   * (the apply path rejects it), so skip it here instead of running past
2460
0
   * the fixed page in add_range(). */
2461
0
  if (unlikely (inputCount > HB_MAX_CONTEXT_LENGTH))
2462
0
    return;
2463
0
2464
0
  hb_bit_page_t covered_seq_indices;
2465
0
  hb_set_t &pos_glyphs = scratch->pos_glyphs;
2466
0
  hb_set_t &position_context = scratch->position_context;
2467
0
  hb_set_t &disjunctive_indices = scratch->disjunctive_indices;
2468
0
  hb_set_t &filtered_disjunctive_indices = scratch->filtered_disjunctive_indices;
2469
0
  unsigned cached_context_index = 0;
2470
0
  for (unsigned int i = 0; i < lookupCount; i++)
2471
0
  {
2472
0
    unsigned seqIndex = lookupRecord[i].sequenceIndex;
2473
0
    if (seqIndex >= inputCount)
2474
0
      continue;
2475
0
2476
0
    hb_depend_context_t::context_set_cache_key_t context_cache_key;
2477
0
    if (unlikely (!c->get_context_set_cache_key (rule, &lookupRecord[i], data, value,
2478
0
             context_format, &context_cache_key)))
2479
0
      return;
2480
0
2481
0
    hb_codepoint_t context_set_idx;
2482
0
    hb_codepoint_t *cached_context_set_idx;
2483
0
    if (cached_context_sets)
2484
0
      context_set_idx = (*cached_context_sets)[cached_context_index++];
2485
0
    else if (c->context_set_cache.has (context_cache_key, &cached_context_set_idx))
2486
0
      context_set_idx = *cached_context_set_idx;
2487
0
    else
2488
0
    {
2489
0
      if (unlikely (!input_position_glyphs))
2490
0
      {
2491
0
  c->depend_data->fail ();
2492
0
  return;
2493
0
      }
2494
0
2495
0
      /* Build position-specific context_set for this lookup. */
2496
0
      position_context.clear ();  // Will hold direct glyphs
2497
0
      disjunctive_indices.clear ();  // Will hold encoded set references
2498
0
      filtered_disjunctive_indices.clear ();
2499
0
2500
0
      /* Process preliminary_context in one pass. */
2501
0
      hb_codepoint_t elem = HB_SET_VALUE_INVALID;
2502
0
      while (preliminary_context.next (&elem)) {
2503
0
  if (!(elem & HB_DEPEND_CONTEXT_SET_FLAG)) {
2504
0
    /* Direct glyph */
2505
0
    position_context.add (elem);
2506
0
  } else {
2507
0
    /* Encoded set reference - defer processing until we have all direct requirements */
2508
0
    disjunctive_indices.add (elem);
2509
0
  }
2510
0
      }
2511
0
2512
0
      /* Add singleton glyphs from OTHER input positions. */
2513
0
      for (unsigned j = 0; j < input_position_glyphs->length; j++) {
2514
0
  if (j != seqIndex && (*input_position_glyphs)[j]->get_population () == 1) {
2515
0
    position_context.add ((*input_position_glyphs)[j]->get_min ());
2516
0
  }
2517
0
      }
2518
0
2519
0
      /* Now position_context has all direct requirements.
2520
0
       * Process deferred encoded sets and filter them. */
2521
0
      elem = HB_SET_VALUE_INVALID;
2522
0
      while (disjunctive_indices.next (&elem)) {
2523
0
  hb_codepoint_t set_idx = elem & 0x7FFFFFFF;
2524
0
  const hb_set_t *original_set = c->depend_data->get_set_from_index (set_idx);
2525
0
  if (unlikely (!original_set)) continue;
2526
0
2527
0
  /* Dependency context sets are never inverted. */
2528
0
  if (!original_set->intersects (position_context)) {
2529
0
    /* No overlap with position_context - add full requirement */
2530
0
    filtered_disjunctive_indices.add (elem);
2531
0
  }
2532
0
  /* Otherwise: position_context intersects with original_set.
2533
0
   * Since disjunctive requirements need only ONE glyph from the set,
2534
0
   * and position_context already has a glyph from this set, the
2535
0
   * requirement is satisfied - no need to add anything. */
2536
0
      }
2537
0
2538
0
      /* Process non-singleton input positions. */
2539
0
      for (unsigned j = 0; j < input_position_glyphs->length; j++) {
2540
0
  if (j != seqIndex && (*input_position_glyphs)[j]->get_population () > 1) {
2541
0
    /* Input-position sets are also never inverted. */
2542
0
    if (!(*input_position_glyphs)[j]->intersects (position_context)) {
2543
0
      /* No overlap with position_context - add full requirement */
2544
0
      bool cached_set = context_format == ContextFormat::CoverageBasedContext ||
2545
0
            (context_format == ContextFormat::ClassBasedContext && j != 0);
2546
0
      hb_codepoint_t idx = cached_set
2547
0
        ? c->find_or_create_cached_context_set ((*input_position_glyphs)[j])
2548
0
        : c->depend_data->find_or_create_context_set (*(*input_position_glyphs)[j]);
2549
0
      if (unlikely (idx == HB_CODEPOINT_INVALID))
2550
0
        return;
2551
0
      filtered_disjunctive_indices.add (HB_DEPEND_CONTEXT_SET_FLAG | idx);
2552
0
    }
2553
0
    /* Otherwise: position_context intersects, requirement satisfied */
2554
0
  }
2555
0
      }
2556
0
2557
0
      /* Combine direct + disjunctive. */
2558
0
      position_context.union_ (filtered_disjunctive_indices);
2559
0
      if (unlikely (position_context.in_error () ||
2560
0
        filtered_disjunctive_indices.in_error ()))
2561
0
      {
2562
0
  c->depend_data->fail ();
2563
0
  return;
2564
0
      }
2565
0
2566
0
      context_set_idx = position_context.is_empty ()
2567
0
  ? HB_CODEPOINT_INVALID
2568
0
  : c->depend_data->find_or_create_context_set (position_context);
2569
0
      if (unlikely (!position_context.is_empty () &&
2570
0
        context_set_idx == HB_CODEPOINT_INVALID))
2571
0
  return;
2572
0
2573
0
      if (unlikely (!c->context_set_cache.set (context_cache_key, context_set_idx)))
2574
0
      {
2575
0
  c->depend_data->fail ();
2576
0
  return;
2577
0
      }
2578
0
    }
2579
0
2580
0
    /* Save outer context to restore after this lookup. When a contextual lookup
2581
0
     * calls another contextual lookup, we want each lookup in this rule to see
2582
0
     * the same outer context, not context from a sibling lookup. */
2583
0
    hb_codepoint_t saved_context_set_index = c->depend_data->current_context_set_index;
2584
0
    hb_subset_depend_edge_flags_t saved_edge_flags = c->depend_data->current_edge_flags;
2585
0
2586
0
    /* Detect nested contextual: if we already have a context set, we're inside
2587
0
     * an outer contextual rule that called this one. The outer context will be
2588
0
     * lost, so edges created here may over-approximate. */
2589
0
    bool nested_contextual = (saved_context_set_index != HB_CODEPOINT_INVALID);
2590
0
2591
0
    /* Set for this position's edges */
2592
0
    c->depend_data->current_context_set_index = context_set_idx;
2593
0
2594
0
    /* Mark edges from multi-position rules (inputCount > 1) as potentially
2595
0
     * over-approximate. Depend extraction records edges based on what glyphs
2596
0
     * COULD be at each position per the static input coverage/class. But during
2597
0
     * closure computation, lookups within the rule are applied sequentially:
2598
0
     * lookups at earlier positions may transform later positions, and multiple
2599
0
     * lookups at the same position may interact (one produces a glyph, another
2600
0
     * immediately consumes it as an "intermediate"). So a glyph matching the
2601
0
     * coverage might not persist at that position when closure traverses. */
2602
0
    c->depend_data->current_edge_flags = HB_SUBSET_DEPEND_EDGE_FLAG_NONE;
2603
0
    if (inputCount > 1) {
2604
0
      c->depend_data->current_edge_flags |= HB_SUBSET_DEPEND_EDGE_FLAG_FROM_CONTEXT_POSITION;
2605
0
    }
2606
0
    if (nested_contextual) {
2607
0
      c->depend_data->current_edge_flags |= HB_SUBSET_DEPEND_EDGE_FLAG_FROM_NESTED_CONTEXT;
2608
0
    }
2609
0
2610
0
    bool has_pos_glyphs = false;
2611
0
2612
0
    if (!covered_seq_indices.has (seqIndex))
2613
0
    {
2614
0
      has_pos_glyphs = true;
2615
0
      pos_glyphs.clear ();
2616
0
      if (seqIndex == 0)
2617
0
      {
2618
0
        switch (context_format) {
2619
0
        case ContextFormat::SimpleContext:
2620
0
          pos_glyphs.add (value);
2621
0
          break;
2622
0
        case ContextFormat::ClassBasedContext:
2623
0
          intersected_glyphs_func (&c->parent_active_glyphs (), data, value, &pos_glyphs, cache);
2624
0
          break;
2625
0
        case ContextFormat::CoverageBasedContext:
2626
0
          pos_glyphs.set (c->parent_active_glyphs ());
2627
0
          break;
2628
0
        }
2629
0
      }
2630
0
      else
2631
0
      {
2632
0
        const void *input_data = input;
2633
0
        unsigned input_value = seqIndex - 1;
2634
0
        if (context_format != ContextFormat::SimpleContext)
2635
0
        {
2636
0
          input_data = data;
2637
0
          input_value = input[seqIndex - 1];
2638
0
        }
2639
0
2640
0
        intersected_glyphs_func (c->glyphs, input_data, input_value, &pos_glyphs, cache);
2641
0
      }
2642
0
    }
2643
0
2644
0
    covered_seq_indices.add (seqIndex);
2645
0
    if (has_pos_glyphs)
2646
0
    {
2647
0
      hb_codepoint_t active_idx = HB_CODEPOINT_INVALID;
2648
0
      if (context_format == ContextFormat::SimpleContext)
2649
0
      {
2650
0
  hb_codepoint_t glyph = seqIndex ? pos_glyphs.get_min () : value;
2651
0
  if (likely (glyph < hb_depend_context_t::SINGLE_GLYPH_ACTIVE_FLAG))
2652
0
    active_idx = glyph | hb_depend_context_t::SINGLE_GLYPH_ACTIVE_FLAG;
2653
0
      }
2654
0
      hb_set_t *cur_active_glyphs = c->push_cur_active_glyphs (active_idx);
2655
0
      if (unlikely (!cur_active_glyphs))
2656
0
      {
2657
0
  c->depend_data->current_context_set_index = saved_context_set_index;
2658
0
  c->depend_data->current_edge_flags = saved_edge_flags;
2659
0
  return;
2660
0
      }
2661
0
      *cur_active_glyphs = std::move (pos_glyphs);
2662
0
    }
2663
0
    else if (unlikely (!c->push_root_active_glyphs ()))
2664
0
    {
2665
0
      c->depend_data->current_context_set_index = saved_context_set_index;
2666
0
      c->depend_data->current_edge_flags = saved_edge_flags;
2667
0
      return;
2668
0
    }
2669
0
2670
0
    unsigned endIndex = inputCount;
2671
0
    if (context_format == ContextFormat::CoverageBasedContext)
2672
0
      endIndex += 1;
2673
0
2674
0
    c->recurse (lookupRecord[i].lookupListIndex, &covered_seq_indices, seqIndex, endIndex);
2675
0
    c->pop_cur_done_glyphs ();
2676
0
2677
0
    /* Restore outer context after this lookup, so subsequent lookups in this
2678
0
     * rule see the original context rather than this lookup's context. */
2679
0
    c->depend_data->current_context_set_index = saved_context_set_index;
2680
0
    c->depend_data->current_edge_flags = saved_edge_flags;
2681
0
  }
2682
0
}
Unexecuted instantiation: hb-aat-layout.cc:void OT::context_depend_recurse_lookups<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, void (*)(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*), void*, hb_set_t const&, hb_vector_t<hb_set_t const*, false> const*, hb_vector_t<unsigned int, false> const*, OT::hb_depend_context_t::depend_scratch_t*)
Unexecuted instantiation: hb-ot-face.cc:void OT::context_depend_recurse_lookups<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, void (*)(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*), void*, hb_set_t const&, hb_vector_t<hb_set_t const*, false> const*, hb_vector_t<unsigned int, false> const*, OT::hb_depend_context_t::depend_scratch_t*)
Unexecuted instantiation: hb-ot-layout.cc:void OT::context_depend_recurse_lookups<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, void (*)(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*), void*, hb_set_t const&, hb_vector_t<hb_set_t const*, false> const*, hb_vector_t<unsigned int, false> const*, OT::hb_depend_context_t::depend_scratch_t*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:void OT::context_depend_recurse_lookups<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, void (*)(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*), void*, hb_set_t const&, hb_vector_t<hb_set_t const*, false> const*, hb_vector_t<unsigned int, false> const*, OT::hb_depend_context_t::depend_scratch_t*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:void OT::context_depend_recurse_lookups<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, void (*)(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*), void*, hb_set_t const&, hb_vector_t<hb_set_t const*, false> const*, hb_vector_t<unsigned int, false> const*, OT::hb_depend_context_t::depend_scratch_t*)
Unexecuted instantiation: hb-subset.cc:void OT::context_depend_recurse_lookups<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, void (*)(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*), void*, hb_set_t const&, hb_vector_t<hb_set_t const*, false> const*, hb_vector_t<unsigned int, false> const*, OT::hb_depend_context_t::depend_scratch_t*)
Unexecuted instantiation: hb-subset-plan-layout.cc:void OT::context_depend_recurse_lookups<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, void (*)(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*), void*, hb_set_t const&, hb_vector_t<hb_set_t const*, false> const*, hb_vector_t<unsigned int, false> const*, OT::hb_depend_context_t::depend_scratch_t*)
Unexecuted instantiation: hb-subset-table-layout.cc:void OT::context_depend_recurse_lookups<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, void (*)(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*), void*, hb_set_t const&, hb_vector_t<hb_set_t const*, false> const*, hb_vector_t<unsigned int, false> const*, OT::hb_depend_context_t::depend_scratch_t*)
Unexecuted instantiation: hb-subset-table-var.cc:void OT::context_depend_recurse_lookups<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, void (*)(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*), void*, hb_set_t const&, hb_vector_t<hb_set_t const*, false> const*, hb_vector_t<unsigned int, false> const*, OT::hb_depend_context_t::depend_scratch_t*)
Unexecuted instantiation: hb-subset-table-cff.cc:void OT::context_depend_recurse_lookups<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, void (*)(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*), void*, hb_set_t const&, hb_vector_t<hb_set_t const*, false> const*, hb_vector_t<unsigned int, false> const*, OT::hb_depend_context_t::depend_scratch_t*)
Unexecuted instantiation: hb-subset-table-color.cc:void OT::context_depend_recurse_lookups<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, void (*)(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*), void*, hb_set_t const&, hb_vector_t<hb_set_t const*, false> const*, hb_vector_t<unsigned int, false> const*, OT::hb_depend_context_t::depend_scratch_t*)
Unexecuted instantiation: hb-subset-table-other.cc:void OT::context_depend_recurse_lookups<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, void (*)(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*), void*, hb_set_t const&, hb_vector_t<hb_set_t const*, false> const*, hb_vector_t<unsigned int, false> const*, OT::hb_depend_context_t::depend_scratch_t*)
Unexecuted instantiation: gsubgpos-context.cc:void OT::context_depend_recurse_lookups<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextFormat, void const*, void (*)(hb_set_t const*, void const*, unsigned int, hb_set_t*, void*), void*, hb_set_t const&, hb_vector_t<hb_set_t const*, false> const*, hb_vector_t<unsigned int, false> const*, OT::hb_depend_context_t::depend_scratch_t*)
2683
2684
template <typename context_t>
2685
static inline void recurse_lookups (context_t *c,
2686
                                    unsigned int lookupCount,
2687
                                    const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */)
2688
0
{
2689
0
  for (unsigned int i = 0; i < lookupCount; i++)
2690
0
    c->recurse (lookupRecord[i].lookupListIndex);
2691
0
}
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-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-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*)
Unexecuted instantiation: hb-subset.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-subset.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-subset-plan-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-subset-plan-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-subset-table-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-subset-table-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-subset-table-var.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-subset-table-var.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-subset-table-cff.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-subset-table-cff.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-subset-table-color.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-subset-table-color.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-subset-table-other.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-subset-table-other.cc:void OT::recurse_lookups<OT::hb_collect_glyphs_context_t>(OT::hb_collect_glyphs_context_t*, unsigned int, OT::LookupRecord const*)
Unexecuted instantiation: gsubgpos-context.cc:void OT::recurse_lookups<OT::hb_closure_lookups_context_t>(OT::hb_closure_lookups_context_t*, unsigned int, OT::LookupRecord const*)
Unexecuted instantiation: gsubgpos-context.cc:void OT::recurse_lookups<OT::hb_collect_glyphs_context_t>(OT::hb_collect_glyphs_context_t*, unsigned int, OT::LookupRecord const*)
2692
2693
static inline void apply_lookup (hb_ot_apply_context_t *c,
2694
         unsigned int count, /* Including the first glyph */
2695
         unsigned int lookupCount,
2696
         const LookupRecord lookupRecord[], /* Array of LookupRecords--in design order */
2697
         unsigned int match_end)
2698
373
{
2699
373
  hb_buffer_t *buffer = c->buffer;
2700
373
  int end;
2701
2702
  /* All positions are distance from beginning of *output* buffer.
2703
   * Adjust. */
2704
373
  {
2705
373
    unsigned int bl = buffer->backtrack_len ();
2706
373
    end = bl + match_end - buffer->idx;
2707
2708
373
    int delta = bl - buffer->idx;
2709
    /* Convert positions to new indexing. */
2710
825
    for (unsigned int j = 0; j < count; j++)
2711
452
      c->match_positions.arrayZ[j] += delta;
2712
373
  }
2713
2714
746
  for (unsigned int i = 0; i < lookupCount && buffer->successful; i++)
2715
373
  {
2716
373
    unsigned int idx = lookupRecord[i].sequenceIndex;
2717
373
    if (idx >= count)
2718
0
      continue;
2719
2720
373
    unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
2721
2722
    /* This can happen if earlier recursed lookups deleted many entries. */
2723
373
    if (unlikely (c->match_positions.arrayZ[idx] >= orig_len))
2724
0
      continue;
2725
2726
373
    if (unlikely (!buffer->move_to (c->match_positions.arrayZ[idx])))
2727
0
      break;
2728
2729
373
    if (unlikely (buffer->max_ops <= 0))
2730
0
      break;
2731
2732
373
    if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
2733
0
    {
2734
0
      if (buffer->have_output)
2735
0
        c->buffer->sync_so_far ();
2736
0
      c->buffer->message (c->font,
2737
0
        "start recursing to lookup %u at %u",
2738
0
        (unsigned) lookupRecord[i].lookupListIndex,
2739
0
        buffer->idx);
2740
0
    }
2741
2742
373
    bool ret = c->recurse (lookupRecord[i].lookupListIndex);
2743
2744
373
    if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
2745
0
    {
2746
0
      if (buffer->have_output)
2747
0
        c->buffer->sync_so_far ();
2748
0
      c->buffer->message (c->font,
2749
0
        "end recursing to lookup %u",
2750
0
        (unsigned) lookupRecord[i].lookupListIndex);
2751
0
    }
2752
2753
373
    if (!ret)
2754
77
      continue;
2755
2756
296
    unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
2757
296
    int delta = new_len - orig_len;
2758
2759
296
    if (!delta)
2760
294
      continue;
2761
2762
    /* Recursed lookup changed buffer len.  Adjust.
2763
     *
2764
     * TODO:
2765
     *
2766
     * Right now, if buffer length increased by n, we assume n new glyphs
2767
     * were added right after the current position, and if buffer length
2768
     * was decreased by n, we assume n match positions after the current
2769
     * one where removed.  The former (buffer length increased) case is
2770
     * fine, but the decrease case can be improved in at least two ways,
2771
     * both of which are significant:
2772
     *
2773
     *   - If recursed-to lookup is MultipleSubst and buffer length
2774
     *     decreased, then it's current match position that was deleted,
2775
     *     NOT the one after it.
2776
     *
2777
     *   - If buffer length was decreased by n, it does not necessarily
2778
     *     mean that n match positions where removed, as there recursed-to
2779
     *     lookup might had a different LookupFlag.  Here's a constructed
2780
     *     case of that:
2781
     *     https://github.com/harfbuzz/harfbuzz/discussions/3538
2782
     *
2783
     * It should be possible to construct tests for both of these cases.
2784
     */
2785
2786
2
    end += delta;
2787
2
    if (end < int (c->match_positions.arrayZ[idx]))
2788
0
    {
2789
      /* End might end up being smaller than match_positions.arrayZ[idx] if the recursed
2790
       * lookup ended up removing many items.
2791
       * Just never rewind end beyond start of current position, since that is
2792
       * not possible in the recursed lookup.  Also adjust delta as such.
2793
       *
2794
       * https://bugs.chromium.org/p/chromium/issues/detail?id=659496
2795
       * https://github.com/harfbuzz/harfbuzz/issues/1611
2796
       */
2797
0
      delta += c->match_positions.arrayZ[idx] - end;
2798
0
      end = c->match_positions.arrayZ[idx];
2799
0
    }
2800
2801
2
    unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
2802
2803
2
    if (delta > 0)
2804
0
    {
2805
0
      if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
2806
0
  break;
2807
0
      if (unlikely (count + delta > c->match_positions.length &&
2808
0
        !c->match_positions.resize_dirty  (count + delta)))
2809
0
        return;
2810
0
    }
2811
2
    else
2812
2
    {
2813
      /* NOTE: delta is non-positive. */
2814
2
      delta = hb_max (delta, (int) next - (int) count);
2815
2
      next -= delta;
2816
2
    }
2817
2818
    /* Shift! */
2819
2
    memmove (c->match_positions + next + delta, c->match_positions + next,
2820
2
       (count - next) * sizeof (c->match_positions.arrayZ[0]));
2821
2
    next += delta;
2822
2
    count += delta;
2823
2824
    /* Fill in new entries. */
2825
2
    for (unsigned int j = idx + 1; j < next; j++)
2826
0
      c->match_positions.arrayZ[j] = c->match_positions.arrayZ[j - 1] + 1;
2827
2828
    /* And fixup the rest. */
2829
2
    for (; next < count; next++)
2830
0
      c->match_positions.arrayZ[next] += delta;
2831
2
  }
2832
2833
373
  assert (end >= 0);
2834
373
  (void) buffer->move_to (end);
2835
373
}
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-face.cc:OT::apply_lookup(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, unsigned int)
hb-ot-layout.cc:OT::apply_lookup(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, unsigned int)
Line
Count
Source
2698
373
{
2699
373
  hb_buffer_t *buffer = c->buffer;
2700
373
  int end;
2701
2702
  /* All positions are distance from beginning of *output* buffer.
2703
   * Adjust. */
2704
373
  {
2705
373
    unsigned int bl = buffer->backtrack_len ();
2706
373
    end = bl + match_end - buffer->idx;
2707
2708
373
    int delta = bl - buffer->idx;
2709
    /* Convert positions to new indexing. */
2710
825
    for (unsigned int j = 0; j < count; j++)
2711
452
      c->match_positions.arrayZ[j] += delta;
2712
373
  }
2713
2714
746
  for (unsigned int i = 0; i < lookupCount && buffer->successful; i++)
2715
373
  {
2716
373
    unsigned int idx = lookupRecord[i].sequenceIndex;
2717
373
    if (idx >= count)
2718
0
      continue;
2719
2720
373
    unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
2721
2722
    /* This can happen if earlier recursed lookups deleted many entries. */
2723
373
    if (unlikely (c->match_positions.arrayZ[idx] >= orig_len))
2724
0
      continue;
2725
2726
373
    if (unlikely (!buffer->move_to (c->match_positions.arrayZ[idx])))
2727
0
      break;
2728
2729
373
    if (unlikely (buffer->max_ops <= 0))
2730
0
      break;
2731
2732
373
    if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
2733
0
    {
2734
0
      if (buffer->have_output)
2735
0
        c->buffer->sync_so_far ();
2736
0
      c->buffer->message (c->font,
2737
0
        "start recursing to lookup %u at %u",
2738
0
        (unsigned) lookupRecord[i].lookupListIndex,
2739
0
        buffer->idx);
2740
0
    }
2741
2742
373
    bool ret = c->recurse (lookupRecord[i].lookupListIndex);
2743
2744
373
    if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
2745
0
    {
2746
0
      if (buffer->have_output)
2747
0
        c->buffer->sync_so_far ();
2748
0
      c->buffer->message (c->font,
2749
0
        "end recursing to lookup %u",
2750
0
        (unsigned) lookupRecord[i].lookupListIndex);
2751
0
    }
2752
2753
373
    if (!ret)
2754
77
      continue;
2755
2756
296
    unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
2757
296
    int delta = new_len - orig_len;
2758
2759
296
    if (!delta)
2760
294
      continue;
2761
2762
    /* Recursed lookup changed buffer len.  Adjust.
2763
     *
2764
     * TODO:
2765
     *
2766
     * Right now, if buffer length increased by n, we assume n new glyphs
2767
     * were added right after the current position, and if buffer length
2768
     * was decreased by n, we assume n match positions after the current
2769
     * one where removed.  The former (buffer length increased) case is
2770
     * fine, but the decrease case can be improved in at least two ways,
2771
     * both of which are significant:
2772
     *
2773
     *   - If recursed-to lookup is MultipleSubst and buffer length
2774
     *     decreased, then it's current match position that was deleted,
2775
     *     NOT the one after it.
2776
     *
2777
     *   - If buffer length was decreased by n, it does not necessarily
2778
     *     mean that n match positions where removed, as there recursed-to
2779
     *     lookup might had a different LookupFlag.  Here's a constructed
2780
     *     case of that:
2781
     *     https://github.com/harfbuzz/harfbuzz/discussions/3538
2782
     *
2783
     * It should be possible to construct tests for both of these cases.
2784
     */
2785
2786
2
    end += delta;
2787
2
    if (end < int (c->match_positions.arrayZ[idx]))
2788
0
    {
2789
      /* End might end up being smaller than match_positions.arrayZ[idx] if the recursed
2790
       * lookup ended up removing many items.
2791
       * Just never rewind end beyond start of current position, since that is
2792
       * not possible in the recursed lookup.  Also adjust delta as such.
2793
       *
2794
       * https://bugs.chromium.org/p/chromium/issues/detail?id=659496
2795
       * https://github.com/harfbuzz/harfbuzz/issues/1611
2796
       */
2797
0
      delta += c->match_positions.arrayZ[idx] - end;
2798
0
      end = c->match_positions.arrayZ[idx];
2799
0
    }
2800
2801
2
    unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
2802
2803
2
    if (delta > 0)
2804
0
    {
2805
0
      if (unlikely (delta + count > HB_MAX_CONTEXT_LENGTH))
2806
0
  break;
2807
0
      if (unlikely (count + delta > c->match_positions.length &&
2808
0
        !c->match_positions.resize_dirty  (count + delta)))
2809
0
        return;
2810
0
    }
2811
2
    else
2812
2
    {
2813
      /* NOTE: delta is non-positive. */
2814
2
      delta = hb_max (delta, (int) next - (int) count);
2815
2
      next -= delta;
2816
2
    }
2817
2818
    /* Shift! */
2819
2
    memmove (c->match_positions + next + delta, c->match_positions + next,
2820
2
       (count - next) * sizeof (c->match_positions.arrayZ[0]));
2821
2
    next += delta;
2822
2
    count += delta;
2823
2824
    /* Fill in new entries. */
2825
2
    for (unsigned int j = idx + 1; j < next; j++)
2826
0
      c->match_positions.arrayZ[j] = c->match_positions.arrayZ[j - 1] + 1;
2827
2828
    /* And fixup the rest. */
2829
2
    for (; next < count; next++)
2830
0
      c->match_positions.arrayZ[next] += delta;
2831
2
  }
2832
2833
373
  assert (end >= 0);
2834
373
  (void) buffer->move_to (end);
2835
373
}
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)
Unexecuted instantiation: hb-subset.cc:OT::apply_lookup(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, unsigned int)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::apply_lookup(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, unsigned int)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::apply_lookup(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, unsigned int)
Unexecuted instantiation: hb-subset-table-var.cc:OT::apply_lookup(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, unsigned int)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::apply_lookup(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, unsigned int)
Unexecuted instantiation: hb-subset-table-color.cc:OT::apply_lookup(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, unsigned int)
Unexecuted instantiation: hb-subset-table-other.cc:OT::apply_lookup(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, unsigned int)
Unexecuted instantiation: gsubgpos-context.cc:OT::apply_lookup(OT::hb_ot_apply_context_t*, unsigned int, unsigned int, OT::LookupRecord const*, unsigned int)
2836
2837
2838
2839
/* Contextual lookups */
2840
2841
struct ContextClosureLookupContext
2842
{
2843
  ContextClosureFuncs funcs;
2844
  ContextFormat context_format;
2845
  const void *intersects_data;
2846
  void *intersects_cache;
2847
  void *intersected_glyphs_cache;
2848
};
2849
2850
typedef ContextClosureLookupContext ContextDependLookupContext;
2851
2852
struct ContextCollectGlyphsLookupContext
2853
{
2854
  ContextCollectGlyphsFuncs funcs;
2855
  const void *collect_data;
2856
};
2857
2858
struct ContextApplyLookupContext
2859
{
2860
  ContextApplyFuncs funcs;
2861
  const void *match_data;
2862
  get_value_func_t get_value;
2863
};
2864
2865
template <typename HBUINT>
2866
static inline bool context_intersects (const hb_set_t *glyphs,
2867
               unsigned int inputCount, /* Including the first glyph (not matched) */
2868
               const HBUINT input[], /* Array of input values--start with second glyph */
2869
               ContextClosureLookupContext &lookup_context)
2870
0
{
2871
0
  return array_is_subset_of (glyphs,
2872
0
           inputCount ? inputCount - 1 : 0, input,
2873
0
           lookup_context.funcs.intersects,
2874
0
           lookup_context.intersects_data,
2875
0
           lookup_context.intersects_cache);
2876
0
}
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-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-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&)
Unexecuted instantiation: hb-subset.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-subset-plan-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-subset-table-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-subset-table-var.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-subset-table-cff.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-subset-table-color.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-subset-table-other.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: gsubgpos-context.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&)
2877
2878
template <typename HBUINT>
2879
static inline void context_closure_lookup (hb_closure_context_t *c,
2880
             unsigned int inputCount, /* Including the first glyph (not matched) */
2881
             const HBUINT input[], /* Array of input values--start with second glyph */
2882
             unsigned int lookupCount,
2883
             const LookupRecord lookupRecord[],
2884
             unsigned value, /* Index of first glyph in Coverage or Class value in ClassDef table */
2885
             ContextClosureLookupContext &lookup_context)
2886
0
{
2887
0
  if (context_intersects (c->glyphs,
2888
0
        inputCount, input,
2889
0
        lookup_context))
2890
0
    context_closure_recurse_lookups (c,
2891
0
             inputCount, input,
2892
0
             lookupCount, lookupRecord,
2893
0
             value,
2894
0
             lookup_context.context_format,
2895
0
             lookup_context.intersects_data,
2896
0
             lookup_context.funcs.intersected_glyphs,
2897
0
             lookup_context.intersected_glyphs_cache);
2898
0
}
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-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-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&)
Unexecuted instantiation: hb-subset.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-subset-plan-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-subset-table-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-subset-table-var.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-subset-table-cff.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-subset-table-color.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-subset-table-other.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: gsubgpos-context.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&)
2899
2900
template <typename HBUINT>
2901
static inline void context_depend_lookup (hb_depend_context_t *c,
2902
            unsigned int inputCount, /* Including the first glyph (not matched) */
2903
            const HBUINT input[], /* Array of input values--start with second glyph */
2904
            unsigned int lookupCount,
2905
            const LookupRecord lookupRecord[],
2906
            const void *rule,
2907
            unsigned value, /* Index of first glyph in Coverage or Class value in ClassDef table */
2908
            ContextDependLookupContext &lookup_context)
2909
0
{
2910
0
  if (!context_intersects (c->glyphs,
2911
0
         inputCount, input,
2912
0
         lookup_context))
2913
0
    return;
2914
0
2915
0
  hb_depend_context_t::depend_scratch_t *scratch = c->acquire_depend_scratch ();
2916
0
  if (unlikely (!scratch))
2917
0
    return;
2918
0
  HB_SCOPE_GUARD (c->release_depend_scratch (scratch));
2919
0
2920
0
  bool context_sets_cached = context_depend_sets_are_cached (
2921
0
    c, inputCount, lookupCount, lookupRecord, rule, value,
2922
0
    lookup_context.context_format, lookup_context.intersects_data,
2923
0
    &scratch->cached_context_sets);
2924
0
  if (unlikely (!c->depend_data->successful))
2925
0
    return;
2926
0
2927
0
  /* Build preliminary_context (empty for ContextSubst - no backtrack/lookahead) */
2928
0
  hb_set_t &preliminary_context = scratch->preliminary_context;
2929
0
2930
0
  /* Build glyph sets for ALL input positions */
2931
0
  hb_set_t &position_scratch = scratch->position_scratch;
2932
0
  hb_vector_t<const hb_set_t *> &input_position_glyphs = scratch->input_position_glyphs;
2933
0
2934
0
  /* Cached labels no longer need the expanded input-position sets. */
2935
0
  if (!context_sets_cached)
2936
0
  {
2937
0
    /* Position 0 (Coverage glyph) — must be in both the class AND the
2938
0
     * coverage, so intersect with parent_active_glyphs (= coverage ∩ glyphs
2939
0
     * set by the ContextFormat2/3 caller). */
2940
0
    const hb_set_t *pos0_glyphs = depend_position_glyphs (
2941
0
      c, lookup_context.context_format, lookup_context.intersects_data, value,
2942
0
      true, &position_scratch, &scratch->compact_workspace);
2943
0
    if (unlikely (!pos0_glyphs ||
2944
0
      !input_position_glyphs.push_or_fail (pos0_glyphs)))
2945
0
    {
2946
0
      c->depend_data->fail ();
2947
0
      return;
2948
0
    }
2949
0
2950
0
    /* Positions 1+ (Input array) */
2951
0
    for (unsigned i = 0; i + 1 < inputCount; i++)
2952
0
    {
2953
0
      const hb_set_t *pos_glyphs = depend_position_glyphs (
2954
0
  c, lookup_context.context_format, lookup_context.intersects_data,
2955
0
  input[i], false, &position_scratch);
2956
0
      if (unlikely (!pos_glyphs ||
2957
0
        !input_position_glyphs.push_or_fail (pos_glyphs)))
2958
0
      {
2959
0
  c->depend_data->fail ();
2960
0
  return;
2961
0
      }
2962
0
    }
2963
0
  }
2964
0
2965
0
  context_depend_recurse_lookups (c,
2966
0
          inputCount, input,
2967
0
          lookupCount, lookupRecord,
2968
0
          rule,
2969
0
          value,
2970
0
          lookup_context.context_format,
2971
0
          lookup_context.intersects_data,
2972
0
          lookup_context.funcs.intersected_glyphs,
2973
0
          lookup_context.intersected_glyphs_cache,
2974
0
          preliminary_context,
2975
0
          context_sets_cached ? nullptr : &input_position_glyphs,
2976
0
          context_sets_cached ? &scratch->cached_context_sets : nullptr,
2977
0
          scratch);
2978
0
}
Unexecuted instantiation: hb-aat-layout.cc:void OT::context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-face.cc:void OT::context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-layout.cc:void OT::context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:void OT::context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-shape-fallback.cc:void OT::context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-subset.cc:void OT::context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-subset-plan-layout.cc:void OT::context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-subset-table-layout.cc:void OT::context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-subset-table-var.cc:void OT::context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-subset-table-cff.cc:void OT::context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-subset-table-color.cc:void OT::context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextClosureLookupContext&)
Unexecuted instantiation: hb-subset-table-other.cc:void OT::context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextClosureLookupContext&)
Unexecuted instantiation: gsubgpos-context.cc:void OT::context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_context_t*, unsigned int, OT::NumType<true, unsigned short, 2u> const*, unsigned int, OT::LookupRecord const*, void const*, unsigned int, OT::ContextClosureLookupContext&)
2979
2980
template <typename HBUINT>
2981
static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
2982
              unsigned int inputCount, /* Including the first glyph (not matched) */
2983
              const HBUINT input[], /* Array of input values--start with second glyph */
2984
              unsigned int lookupCount,
2985
              const LookupRecord lookupRecord[],
2986
              ContextCollectGlyphsLookupContext &lookup_context)
2987
0
{
2988
0
  collect_array (c, c->input,
2989
0
     inputCount ? inputCount - 1 : 0, input,
2990
0
     lookup_context.funcs.collect, lookup_context.collect_data);
2991
0
  recurse_lookups (c,
2992
0
       lookupCount, lookupRecord);
2993
0
}
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-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-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&)
Unexecuted instantiation: hb-subset.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-subset-plan-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-subset-table-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-subset-table-var.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-subset-table-cff.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-subset-table-color.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-subset-table-other.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: gsubgpos-context.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&)
2994
2995
template <typename HBUINT>
2996
static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
2997
                 unsigned int inputCount, /* Including the first glyph (not matched) */
2998
                 const HBUINT input[], /* Array of input values--start with second glyph */
2999
                 unsigned int lookupCount HB_UNUSED,
3000
                 const LookupRecord lookupRecord[] HB_UNUSED,
3001
                 const ContextApplyLookupContext &lookup_context)
3002
0
{
3003
0
  return would_match_input (c,
3004
0
          inputCount, input,
3005
0
          lookup_context.funcs.match, lookup_context.match_data);
3006
0
}
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-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-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&)
Unexecuted instantiation: hb-subset.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-subset-plan-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-subset-table-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-subset-table-var.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-subset-table-cff.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-subset-table-color.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-subset-table-other.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: gsubgpos-context.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&)
3007
3008
template <typename HBUINT>
3009
static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
3010
           unsigned int inputCount, /* Including the first glyph (not matched) */
3011
           const HBUINT input[], /* Array of input values--start with second glyph */
3012
           unsigned int lookupCount,
3013
           const LookupRecord lookupRecord[],
3014
           const ContextApplyLookupContext &lookup_context)
3015
0
{
3016
0
  if (unlikely (inputCount > HB_MAX_CONTEXT_LENGTH)) return false;
3017
3018
0
  unsigned match_end = 0;
3019
0
  bool ret = false;
3020
0
  if (match_input (c,
3021
0
       inputCount, input,
3022
0
       lookup_context.funcs.match, lookup_context.match_data,
3023
0
       &match_end))
3024
0
  {
3025
0
    c->buffer->unsafe_to_break (c->buffer->idx, match_end);
3026
0
    apply_lookup (c,
3027
0
      inputCount,
3028
0
      lookupCount, lookupRecord,
3029
0
      match_end);
3030
0
    ret = true;
3031
0
  }
3032
0
  else
3033
0
  {
3034
0
    c->buffer->unsafe_to_concat (c->buffer->idx, match_end);
3035
0
    ret = false;
3036
0
  }
3037
3038
0
  return ret;
3039
0
}
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-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-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&)
Unexecuted instantiation: hb-subset.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-subset-plan-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-subset-table-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-subset-table-var.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-subset-table-cff.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-subset-table-color.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-subset-table-other.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: gsubgpos-context.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&)
3040
3041
static inline bool context_cache_func (hb_ot_apply_context_t *c, hb_ot_subtable_cache_op_t op)
3042
0
{
3043
0
  switch (op)
3044
0
  {
3045
0
    case hb_ot_subtable_cache_op_t::ENTER:
3046
0
    {
3047
0
      if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
3048
0
  return false;
3049
0
      auto &info = c->buffer->info;
3050
0
      unsigned count = c->buffer->len;
3051
0
      for (unsigned i = 0; i < count; i++)
3052
0
  info[i].syllable() = 255;
3053
0
      c->new_syllables = 255;
3054
0
      return true;
3055
0
    }
3056
0
    case hb_ot_subtable_cache_op_t::LEAVE:
3057
0
    {
3058
0
      c->new_syllables = (unsigned) -1;
3059
0
      HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
3060
0
      break;
3061
0
    }
3062
0
  }
3063
0
  return false;
3064
0
}
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-face.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)
Unexecuted instantiation: hb-subset.cc:OT::context_cache_func(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: hb-subset-plan-layout.cc:OT::context_cache_func(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: hb-subset-table-layout.cc:OT::context_cache_func(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: hb-subset-table-var.cc:OT::context_cache_func(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: hb-subset-table-cff.cc:OT::context_cache_func(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: hb-subset-table-color.cc:OT::context_cache_func(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: hb-subset-table-other.cc:OT::context_cache_func(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
Unexecuted instantiation: gsubgpos-context.cc:OT::context_cache_func(OT::hb_ot_apply_context_t*, OT::hb_ot_subtable_cache_op_t)
3065
3066
template <typename Types>
3067
struct Rule
3068
{
3069
  template <typename T>
3070
  friend struct RuleSet;
3071
3072
  bool intersects (const hb_set_t *glyphs, ContextClosureLookupContext &lookup_context) const
3073
0
  {
3074
0
    return context_intersects (glyphs,
3075
0
             inputCount, inputZ.arrayZ,
3076
0
             lookup_context);
3077
0
  }
3078
3079
  void depend (hb_depend_context_t *c, unsigned value, ContextDependLookupContext &lookup_context) const
3080
0
  {
3081
0
    const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
3082
0
             (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
3083
0
    context_depend_lookup (c,
3084
0
         inputCount, inputZ.arrayZ,
3085
0
         lookupCount, lookupRecord.arrayZ,
3086
0
         this,
3087
0
         value, lookup_context);
3088
0
  }
3089
3090
  void closure (hb_closure_context_t *c, unsigned value, ContextClosureLookupContext &lookup_context) const
3091
0
  {
3092
0
    if (unlikely (c->lookup_limit_exceeded ())) return;
3093
3094
0
    const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
3095
0
             (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
3096
0
    context_closure_lookup (c,
3097
0
          inputCount, inputZ.arrayZ,
3098
0
          lookupCount, lookupRecord.arrayZ,
3099
0
          value, lookup_context);
3100
0
  }
3101
3102
  void closure_lookups (hb_closure_lookups_context_t *c,
3103
                        ContextClosureLookupContext &lookup_context) const
3104
0
  {
3105
0
    if (unlikely (c->lookup_limit_exceeded ())) return;
3106
0
    if (!intersects (c->glyphs, lookup_context)) return;
3107
3108
0
    const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
3109
0
             (inputZ.as_array (inputCount ? inputCount - 1 : 0));
3110
0
    recurse_lookups (c, lookupCount, lookupRecord.arrayZ);
3111
0
  }
3112
3113
  void collect_glyphs (hb_collect_glyphs_context_t *c,
3114
           ContextCollectGlyphsLookupContext &lookup_context) const
3115
0
  {
3116
0
    const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
3117
0
             (inputZ.as_array (inputCount ? inputCount - 1 : 0));
3118
0
    context_collect_glyphs_lookup (c,
3119
0
           inputCount, inputZ.arrayZ,
3120
0
           lookupCount, lookupRecord.arrayZ,
3121
0
           lookup_context);
3122
0
  }
3123
3124
  void collect_second_glyphs (hb_set_digest_t *digest,
3125
            const ClassDef *class_def = nullptr) const
3126
0
  {
3127
0
    if (inputCount <= 1)
3128
0
    {
3129
0
      *digest = hb_set_digest_t::full ();
3130
0
      return;
3131
0
    }
3132
3133
0
    unsigned second = inputZ.arrayZ[0];
3134
0
    if (!class_def)
3135
0
      digest->add (second);
3136
0
    else if (!second)
3137
0
      *digest = hb_set_digest_t::full ();
3138
0
    else
3139
0
      class_def->collect_class (digest, second);
3140
0
  }
3141
3142
  bool would_apply (hb_would_apply_context_t *c,
3143
        const ContextApplyLookupContext &lookup_context) const
3144
0
  {
3145
0
    const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
3146
0
             (inputZ.as_array (inputCount ? inputCount - 1 : 0));
3147
0
    return context_would_apply_lookup (c,
3148
0
               inputCount, inputZ.arrayZ,
3149
0
               lookupCount, lookupRecord.arrayZ,
3150
0
               lookup_context);
3151
0
  }
3152
3153
  bool apply (hb_ot_apply_context_t *c,
3154
        const ContextApplyLookupContext &lookup_context) const
3155
0
  {
3156
0
    TRACE_APPLY (this);
3157
0
    const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
3158
0
             (inputZ.as_array (inputCount ? inputCount - 1 : 0));
3159
0
    return_trace (context_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
3160
0
  }
3161
3162
  bool serialize (hb_serialize_context_t *c,
3163
      const hb_map_t *input_mapping, /* old->new glyphid or class mapping */
3164
      const hb_map_t *lookup_map) const
3165
0
  {
3166
0
    TRACE_SERIALIZE (this);
3167
0
    auto *out = c->start_embed (this);
3168
0
    if (unlikely (!c->extend_min (out))) return_trace (false);
3169
3170
0
    out->inputCount = inputCount;
3171
0
    const auto input = inputZ.as_array (inputCount - 1);
3172
0
    for (const auto org : input)
3173
0
    {
3174
0
      HBUINT16 d;
3175
0
      d = input_mapping->get (org);
3176
0
      c->copy (d);
3177
0
    }
3178
3179
0
    const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
3180
0
             (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
3181
3182
0
    unsigned count = serialize_lookuprecord_array (c, lookupRecord.as_array (lookupCount), lookup_map);
3183
0
    return_trace (c->check_assign (out->lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
3184
0
  }
3185
3186
  bool subset (hb_subset_context_t *c,
3187
         const hb_map_t *lookup_map,
3188
         const hb_map_t *klass_map = nullptr) const
3189
0
  {
3190
0
    TRACE_SUBSET (this);
3191
0
    if (unlikely (!inputCount)) return_trace (false);
3192
0
    const auto input = inputZ.as_array (inputCount - 1);
3193
3194
0
    const hb_map_t *mapping = klass_map == nullptr ? c->plan->glyph_map : klass_map;
3195
0
    if (!hb_all (input, mapping)) return_trace (false);
3196
0
    return_trace (serialize (c->serializer, mapping, lookup_map));
3197
0
  }
3198
3199
  public:
3200
  bool sanitize (hb_sanitize_context_t *c) const
3201
0
  {
3202
0
    TRACE_SANITIZE (this);
3203
0
    return_trace (c->check_struct (this) &&
3204
0
      hb_barrier () &&
3205
0
      c->check_range (inputZ.arrayZ,
3206
0
          inputZ.item_size * (inputCount ? inputCount - 1 : 0) +
3207
0
          LookupRecord::static_size * lookupCount));
3208
0
  }
3209
3210
  protected:
3211
  HBUINT16  inputCount;   /* Total number of glyphs in input
3212
           * glyph sequence--includes the first
3213
           * glyph */
3214
  HBUINT16  lookupCount;    /* Number of LookupRecords */
3215
  UnsizedArrayOf<typename Types::HBUINT>
3216
    inputZ;     /* Array of match inputs--start with
3217
           * second glyph */
3218
/*UnsizedArrayOf<LookupRecord>
3219
    lookupRecordX;*/  /* Array of LookupRecords--in
3220
           * design order */
3221
  public:
3222
  DEFINE_SIZE_ARRAY (4, inputZ);
3223
};
3224
3225
template <typename Types>
3226
struct RuleSet
3227
{
3228
  using Rule = OT::Rule<Types>;
3229
3230
  bool intersects (const hb_set_t *glyphs,
3231
       ContextClosureLookupContext &lookup_context) const
3232
0
  {
3233
0
    return
3234
0
    + hb_iter (rule)
3235
0
    | hb_map (hb_add (this))
3236
0
    | hb_map ([&] (const Rule &_) { return _.intersects (glyphs, lookup_context); })
3237
0
    | hb_any
3238
0
    ;
3239
0
  }
3240
3241
  void collect_first_input_classes (hb_ot_layout_ruleset_digest_t *digest) const
3242
0
  {
3243
0
    digest->init ();
3244
0
    for (unsigned i = 0; i < rule.len; i++)
3245
0
    {
3246
0
      const Rule &r = this+rule.arrayZ[i];
3247
0
      if (r.inputCount <= 1)
3248
0
      {
3249
0
  digest->set_full ();
3250
0
  return;
3251
0
      }
3252
0
      digest->add (r.inputZ.arrayZ[0]);
3253
0
    }
3254
0
  }
3255
3256
  void depend (hb_depend_context_t *c, unsigned value, ContextDependLookupContext &lookup_context) const
3257
0
  {
3258
0
    + hb_iter (rule)
3259
0
    | hb_map (hb_add (this))
3260
0
    | hb_apply ([&] (const Rule &_) { _.depend (c, value, lookup_context); })
3261
0
    ;
3262
0
  }
3263
3264
  void closure (hb_closure_context_t *c, unsigned value,
3265
    ContextClosureLookupContext &lookup_context) const
3266
0
  {
3267
0
    if (unlikely (c->lookup_limit_exceeded ())) return;
3268
3269
0
    return
3270
0
    + hb_iter (rule)
3271
0
    | hb_map (hb_add (this))
3272
0
    | hb_apply ([&] (const Rule &_) { _.closure (c, value, lookup_context); })
3273
0
    ;
3274
0
  }
3275
3276
  void closure_lookups (hb_closure_lookups_context_t *c,
3277
                        ContextClosureLookupContext &lookup_context) const
3278
0
  {
3279
0
    if (unlikely (c->lookup_limit_exceeded ())) return;
3280
0
    + hb_iter (rule)
3281
0
    | hb_map (hb_add (this))
3282
0
    | hb_apply ([&] (const Rule &_) { _.closure_lookups (c, lookup_context); })
3283
0
    ;
3284
0
  }
3285
3286
  void collect_glyphs (hb_collect_glyphs_context_t *c,
3287
           ContextCollectGlyphsLookupContext &lookup_context) const
3288
0
  {
3289
0
    return
3290
0
    + hb_iter (rule)
3291
0
    | hb_map (hb_add (this))
3292
0
    | hb_apply ([&] (const Rule &_) { _.collect_glyphs (c, lookup_context); })
3293
0
    ;
3294
0
  }
3295
3296
  void collect_second_glyphs (hb_set_digest_t *digest,
3297
            const ClassDef *class_def = nullptr) const
3298
0
  {
3299
0
    + hb_iter (rule)
3300
0
    | hb_map (hb_add (this))
3301
0
    | hb_apply ([=] (const Rule &_) { _.collect_second_glyphs (digest, class_def); })
3302
0
    ;
3303
0
  }
3304
3305
  bool would_apply (hb_would_apply_context_t *c,
3306
        const ContextApplyLookupContext &lookup_context) const
3307
0
  {
3308
0
    return
3309
0
    + hb_iter (rule)
3310
0
    | hb_map (hb_add (this))
3311
0
    | hb_map ([&] (const Rule &_) { return _.would_apply (c, lookup_context); })
3312
0
    | hb_any
3313
0
    ;
3314
0
  }
3315
3316
  bool apply (hb_ot_apply_context_t *c,
3317
        const ContextApplyLookupContext &lookup_context,
3318
        const hb_ot_layout_ruleset_digest_t *digest = nullptr) const
3319
0
  {
3320
0
    TRACE_APPLY (this);
3321
3322
0
    unsigned num_rules = rule.len;
3323
3324
0
#ifndef HB_NO_OT_RULESETS_FAST_PATH
3325
0
    if (HB_OPTIMIZE_SIZE_VAL || num_rules <= 4)
3326
0
#endif
3327
0
    {
3328
0
    slow:
3329
0
      return_trace (
3330
0
      + hb_iter (rule)
3331
0
      | hb_map (hb_add (this))
3332
0
      | hb_map ([&] (const Rule &_) { return _.apply (c, lookup_context); })
3333
0
      | hb_any
3334
0
      )
3335
0
      ;
3336
0
    }
3337
3338
    /* This version is optimized for speed by matching the first & second
3339
     * components of the rule here, instead of calling into the matching code.
3340
     *
3341
     * Replicated from LigatureSet::apply(). */
3342
3343
    /* We use the iter_context instead of iter_input, to avoid skipping
3344
     * default-ignorables and such.
3345
     *
3346
     * Related: https://github.com/harfbuzz/harfbuzz/issues/4813
3347
     */
3348
0
    auto &skippy_iter = c->iter_context;
3349
0
    skippy_iter.reset (c->buffer->idx);
3350
0
    skippy_iter.set_match_func (match_always, nullptr);
3351
0
    skippy_iter.set_glyph_data ((HBUINT16 *) nullptr);
3352
0
    unsigned unsafe_to = (unsigned) -1, unsafe_to1, unsafe_to2 = 0;
3353
0
    hb_glyph_info_t *first = nullptr, *second = nullptr;
3354
0
    bool matched = skippy_iter.next (&unsafe_to1);
3355
0
    if (likely (matched))
3356
0
    {
3357
0
      if (skippy_iter.may_skip (c->buffer->info[skippy_iter.idx]))
3358
0
      {
3359
  /* Can't use the fast path if eg. the next char is a default-ignorable
3360
   * or other skippable. */
3361
0
        goto slow;
3362
0
      }
3363
3364
0
      first = &c->buffer->info[skippy_iter.idx];
3365
0
      unsafe_to1 = skippy_iter.idx + 1;
3366
3367
0
      if (digest && lookup_context.get_value &&
3368
0
    !digest->may_have (lookup_context.get_value (*first, lookup_context.match_data)))
3369
0
  {
3370
0
    c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to1);
3371
0
    return_trace (false);
3372
0
  }
3373
0
    }
3374
0
    else
3375
0
    {
3376
0
      bool unsafe_to_concat = false;
3377
0
      bool ret =
3378
0
      + hb_iter (rule)
3379
0
      | hb_map (hb_add (this))
3380
0
      | hb_filter ([&] (const Rule &_)
3381
0
       {
3382
0
         if (_.inputCount <= 1) return true;
3383
0
         unsafe_to_concat = true;
3384
0
         return false;
3385
0
       })
3386
0
      | hb_map ([&] (const Rule &_) { return _.apply (c, lookup_context); })
3387
0
      | hb_any
3388
0
      ;
3389
0
      if (unsafe_to_concat)
3390
0
  c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to1);
3391
0
      return_trace (ret);
3392
0
    }
3393
0
    matched = skippy_iter.next ();
3394
0
    if (likely (matched))
3395
0
    {
3396
0
      if (skippy_iter.may_skip (c->buffer->info[skippy_iter.idx]))
3397
0
      {
3398
  /* Can't use the fast path if eg. the next char is a default-ignorable
3399
   * or other skippable. */
3400
0
        goto slow;
3401
0
      }
3402
3403
0
      second = &c->buffer->info[skippy_iter.idx];
3404
0
      unsafe_to2 = skippy_iter.idx + 1;
3405
0
    }
3406
3407
0
    auto match_input = lookup_context.funcs.match;
3408
0
    auto *input_data = lookup_context.match_data;
3409
0
    for (unsigned int i = 0; i < num_rules; i++)
3410
0
    {
3411
0
      const auto &r = this+rule.arrayZ[i];
3412
3413
0
      const auto &input = r.inputZ;
3414
3415
0
      if (r.inputCount <= 1 ||
3416
0
    (!match_input ||
3417
0
     match_input (*first, input.arrayZ[0], input_data)))
3418
0
      {
3419
0
        if (!second ||
3420
0
      (r.inputCount <= 2 ||
3421
0
       (!match_input ||
3422
0
        match_input (*second, input.arrayZ[1], input_data)))
3423
0
     )
3424
0
  {
3425
0
    if (r.apply (c, lookup_context))
3426
0
    {
3427
0
      if (unsafe_to != (unsigned) -1)
3428
0
        c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to);
3429
0
      return_trace (true);
3430
0
    }
3431
0
  }
3432
0
  else
3433
0
    unsafe_to = unsafe_to2;
3434
0
      }
3435
0
      else
3436
0
      {
3437
0
  if (unsafe_to == (unsigned) -1)
3438
0
    unsafe_to = unsafe_to1;
3439
3440
  // Skip ahead to next possible first glyph match.
3441
0
  for (; i + 1 < num_rules; i++)
3442
0
  {
3443
0
    const auto &r2 = this+rule.arrayZ[i + 1];
3444
0
    const auto &input2 = r2.inputZ;
3445
0
    if (r2.inputCount <= 1 || input2.arrayZ[0] != input.arrayZ[0])
3446
0
      break;
3447
0
  }
3448
0
      }
3449
0
    }
3450
0
    if (likely (unsafe_to != (unsigned) -1))
3451
0
      c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to);
3452
3453
0
    return_trace (false);
3454
0
  }
3455
3456
  bool subset (hb_subset_context_t *c,
3457
         const hb_map_t *lookup_map,
3458
         const hb_map_t *klass_map = nullptr) const
3459
0
  {
3460
0
    TRACE_SUBSET (this);
3461
3462
0
    auto snap = c->serializer->snapshot ();
3463
0
    auto *out = c->serializer->start_embed (*this);
3464
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
3465
3466
0
    for (const Offset16To<Rule>& _ : rule)
3467
0
    {
3468
0
      if (!_) continue;
3469
0
      auto o_snap = c->serializer->snapshot ();
3470
0
      auto *o = out->rule.serialize_append (c->serializer);
3471
0
      if (unlikely (!o)) continue;
3472
3473
0
      if (!o->serialize_subset (c, _, this, lookup_map, klass_map))
3474
0
      {
3475
0
  out->rule.pop ();
3476
0
  c->serializer->revert (o_snap);
3477
0
      }
3478
0
    }
3479
3480
0
    bool ret = bool (out->rule);
3481
0
    if (!ret) c->serializer->revert (snap);
3482
3483
0
    return_trace (ret);
3484
0
  }
3485
3486
  bool sanitize (hb_sanitize_context_t *c) const
3487
0
  {
3488
0
    TRACE_SANITIZE (this);
3489
0
    return_trace (rule.sanitize (c, this));
3490
0
  }
3491
3492
  protected:
3493
  Array16OfOffset16To<Rule>
3494
    rule;     /* Array of Rule tables
3495
           * ordered by preference */
3496
  public:
3497
  DEFINE_SIZE_ARRAY (2, rule);
3498
};
3499
3500
3501
template <typename Types>
3502
struct ContextFormat1_4
3503
{
3504
  using RuleSet = OT::RuleSet<Types>;
3505
3506
  bool intersects (const hb_set_t *glyphs) const
3507
0
  {
3508
0
    struct ContextClosureLookupContext lookup_context = {
3509
0
      {intersects_glyph, intersected_glyph},
3510
0
      ContextFormat::SimpleContext,
3511
0
      nullptr
3512
0
    };
3513
3514
0
    return
3515
0
    + hb_zip (this+coverage, ruleSet)
3516
0
    | hb_filter (*glyphs, hb_first)
3517
0
    | hb_map (hb_second)
3518
0
    | hb_map (hb_add (this))
3519
0
    | hb_map ([&] (const RuleSet &_) { return _.intersects (glyphs, lookup_context); })
3520
0
    | hb_any
3521
0
    ;
3522
0
  }
3523
3524
  bool may_have_non_1to1 () const
3525
0
  { return true; }
3526
3527
  void depend (hb_depend_context_t *c) const
3528
0
  {
3529
0
    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
3530
0
    if (unlikely (!cur_active_glyphs)) return;
3531
0
    get_coverage ().intersect_set (*c->glyphs, *cur_active_glyphs);
3532
0
3533
0
    ContextDependLookupContext lookup_context = {
3534
0
      {intersects_glyph, intersected_glyph},
3535
0
      ContextFormat::SimpleContext,
3536
0
      nullptr,
3537
0
      nullptr,  /* intersects_cache */
3538
0
      nullptr   /* intersected_glyphs_cache */
3539
0
    };
3540
0
3541
0
    + hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len))
3542
0
    | hb_filter ([&] (hb_codepoint_t _) {
3543
0
      return c->parent_active_glyphs ().has (_);
3544
0
    }, hb_first)
3545
0
    | hb_map ([&](const hb_pair_t<hb_codepoint_t, unsigned> _) { return hb_pair_t<unsigned, const RuleSet&> (_.first, this+ruleSet[_.second]); })
3546
0
    | hb_apply ([&] (const hb_pair_t<unsigned, const RuleSet&>& _) { _.second.depend (c, _.first, lookup_context); })
3547
0
    ;
3548
0
3549
0
    c->pop_cur_done_glyphs ();
3550
0
  }
3551
3552
  void closure (hb_closure_context_t *c) const
3553
0
  {
3554
0
    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
3555
0
    if (unlikely (!cur_active_glyphs)) return;
3556
0
    get_coverage ().intersect_set (c->previous_parent_active_glyphs (), *cur_active_glyphs);
3557
3558
0
    struct ContextClosureLookupContext lookup_context = {
3559
0
      {intersects_glyph, intersected_glyph},
3560
0
      ContextFormat::SimpleContext,
3561
0
      nullptr
3562
0
    };
3563
3564
0
    + hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len))
3565
0
    | hb_filter ([&] (hb_codepoint_t _) {
3566
0
      return c->previous_parent_active_glyphs ().has (_);
3567
0
    }, hb_first)
3568
0
    | hb_map ([&](const hb_pair_t<hb_codepoint_t, unsigned> _) { return hb_pair_t<unsigned, const RuleSet&> (_.first, this+ruleSet[_.second]); })
3569
0
    | hb_apply ([&] (const hb_pair_t<unsigned, const RuleSet&>& _) { _.second.closure (c, _.first, lookup_context); })
3570
0
    ;
3571
3572
0
    c->pop_cur_done_glyphs ();
3573
0
  }
3574
3575
  void closure_lookups (hb_closure_lookups_context_t *c) const
3576
0
  {
3577
0
    struct ContextClosureLookupContext lookup_context = {
3578
0
      {intersects_glyph, nullptr},
3579
0
      ContextFormat::SimpleContext,
3580
0
      nullptr
3581
0
    };
3582
3583
0
    + hb_zip (this+coverage, ruleSet)
3584
0
    | hb_filter (*c->glyphs, hb_first)
3585
0
    | hb_map (hb_second)
3586
0
    | hb_map (hb_add (this))
3587
0
    | hb_apply ([&] (const RuleSet &_) { _.closure_lookups (c, lookup_context); })
3588
0
    ;
3589
0
  }
3590
3591
0
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
3592
3593
  void collect_glyphs (hb_collect_glyphs_context_t *c) const
3594
0
  {
3595
0
    (this+coverage).collect_coverage (c->input);
3596
3597
0
    struct ContextCollectGlyphsLookupContext lookup_context = {
3598
0
      {collect_glyph},
3599
0
      nullptr
3600
0
    };
3601
3602
0
    + hb_iter (ruleSet)
3603
0
    | hb_map (hb_add (this))
3604
0
    | hb_apply ([&] (const RuleSet &_) { _.collect_glyphs (c, lookup_context); })
3605
0
    ;
3606
0
  }
3607
3608
  void collect_second_glyphs (hb_set_digest_t *digest) const
3609
0
  {
3610
0
    + hb_iter (ruleSet)
3611
0
    | hb_map (hb_add (this))
3612
0
    | hb_apply ([digest] (const RuleSet &_) { _.collect_second_glyphs (digest); })
3613
0
    ;
3614
0
  }
3615
3616
  bool would_apply (hb_would_apply_context_t *c) const
3617
0
  {
3618
0
    const RuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
3619
0
    struct ContextApplyLookupContext lookup_context = {
3620
0
      {match_glyph},
3621
0
      nullptr
3622
0
    };
3623
0
    return rule_set.would_apply (c, lookup_context);
3624
0
  }
3625
3626
0
  const Coverage &get_coverage () const { return this+coverage; }
3627
3628
  bool apply (hb_ot_apply_context_t *c) const
3629
0
  {
3630
0
    TRACE_APPLY (this);
3631
0
    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
3632
0
    if (likely (index == NOT_COVERED))
3633
0
      return_trace (false);
3634
3635
0
    const RuleSet &rule_set = this+ruleSet[index];
3636
0
    struct ContextApplyLookupContext lookup_context = {
3637
0
      {match_glyph},
3638
0
      nullptr
3639
0
    };
3640
0
    return_trace (rule_set.apply (c, lookup_context));
3641
0
  }
3642
3643
  bool subset (hb_subset_context_t *c) const
3644
0
  {
3645
0
    TRACE_SUBSET (this);
3646
0
    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
3647
0
    const hb_map_t &glyph_map = *c->plan->glyph_map;
3648
3649
0
    auto *out = c->serializer->start_embed (*this);
3650
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
3651
0
    out->format = format;
3652
3653
0
    const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? &c->plan->gsub_lookups : &c->plan->gpos_lookups;
3654
0
    hb_sorted_vector_t<hb_codepoint_t> new_coverage;
3655
0
    + hb_zip (this+coverage, ruleSet)
3656
0
    | hb_filter (glyphset, hb_first)
3657
0
    | hb_filter (subset_offset_array (c, out->ruleSet, this, lookup_map), hb_second)
3658
0
    | hb_map (hb_first)
3659
0
    | hb_map (glyph_map)
3660
0
    | hb_sink (new_coverage)
3661
0
    ;
3662
3663
0
    out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
3664
0
    return_trace (bool (new_coverage));
3665
0
  }
3666
3667
  bool sanitize (hb_sanitize_context_t *c) const
3668
0
  {
3669
0
    TRACE_SANITIZE (this);
3670
0
    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
3671
0
  }
3672
3673
  protected:
3674
  HBUINT16  format;     /* Format identifier--format = 1 */
3675
  typename Types::template OffsetTo<Coverage>
3676
    coverage;   /* Offset to Coverage table--from
3677
           * beginning of table */
3678
  Array16Of<typename Types::template OffsetTo<RuleSet>>
3679
    ruleSet;    /* Array of RuleSet tables
3680
           * ordered by Coverage Index */
3681
  public:
3682
  DEFINE_SIZE_ARRAY (2 + 2 * Types::size, ruleSet);
3683
};
3684
3685
3686
template <typename Types>
3687
struct ContextFormat2_5
3688
{
3689
  using RuleSet = OT::RuleSet<SmallTypes>;
3690
3691
  bool intersects (const hb_set_t *glyphs) const
3692
0
  {
3693
0
    if (!(this+coverage).intersects (glyphs))
3694
0
      return false;
3695
3696
0
    const ClassDef &class_def = this+classDef;
3697
3698
0
    hb_map_t cache;
3699
0
    struct ContextClosureLookupContext lookup_context = {
3700
0
      {intersects_class, nullptr},
3701
0
      ContextFormat::ClassBasedContext,
3702
0
      &class_def,
3703
0
      &cache
3704
0
    };
3705
3706
0
    hb_set_t retained_coverage_glyphs;
3707
0
    (this+coverage).intersect_set (*glyphs, retained_coverage_glyphs);
3708
3709
0
    hb_set_t coverage_glyph_classes;
3710
0
    class_def.intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
3711
3712
3713
0
    return
3714
0
    + hb_iter (ruleSet)
3715
0
    | hb_map (hb_add (this))
3716
0
    | hb_enumerate
3717
0
    | hb_map ([&] (const hb_pair_t<unsigned, const RuleSet &> p)
3718
0
        { return class_def.intersects_class (glyphs, p.first) &&
3719
0
           coverage_glyph_classes.has (p.first) &&
3720
0
           p.second.intersects (glyphs, lookup_context); })
3721
0
    | hb_any
3722
0
    ;
3723
0
  }
3724
3725
  bool may_have_non_1to1 () const
3726
0
  { return true; }
3727
3728
  void depend (hb_depend_context_t *c) const
3729
0
  {
3730
0
    if (!(this+coverage).intersects (c->glyphs))
3731
0
      return;
3732
0
3733
0
    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
3734
0
    if (unlikely (!cur_active_glyphs)) return;
3735
0
    get_coverage ().intersect_set (*c->glyphs, *cur_active_glyphs);
3736
0
3737
0
    const ClassDef &class_def = this+classDef;
3738
0
3739
0
    hb_map_t cache;
3740
0
    intersected_class_cache_t intersected_cache;
3741
0
    ContextDependLookupContext lookup_context = {
3742
0
      {intersects_class, intersected_class_glyphs},
3743
0
      ContextFormat::ClassBasedContext,
3744
0
      &class_def,
3745
0
      &cache,
3746
0
      &intersected_cache
3747
0
    };
3748
0
3749
0
    + hb_enumerate (ruleSet)
3750
0
    | hb_filter ([&] (unsigned _)
3751
0
    { return class_def.intersects_class (&c->parent_active_glyphs (), _); },
3752
0
     hb_first)
3753
0
    | hb_apply ([&] (const hb_pair_t<unsigned, const typename Types::template OffsetTo<RuleSet>&> _)
3754
0
                {
3755
0
                  const RuleSet& rule_set = this+_.second;
3756
0
                  rule_set.depend (c, _.first, lookup_context);
3757
0
                })
3758
0
    ;
3759
0
3760
0
    c->pop_cur_done_glyphs ();
3761
0
  }
3762
3763
  void closure (hb_closure_context_t *c) const
3764
0
  {
3765
0
    if (!(this+coverage).intersects (c->glyphs))
3766
0
      return;
3767
3768
0
    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
3769
0
    if (unlikely (!cur_active_glyphs)) return;
3770
0
    get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
3771
0
           *cur_active_glyphs);
3772
3773
0
    const ClassDef &class_def = this+classDef;
3774
3775
0
    hb_map_t cache;
3776
0
    intersected_class_cache_t intersected_cache;
3777
0
    struct ContextClosureLookupContext lookup_context = {
3778
0
      {intersects_class, intersected_class_glyphs},
3779
0
      ContextFormat::ClassBasedContext,
3780
0
      &class_def,
3781
0
      &cache,
3782
0
      &intersected_cache
3783
0
    };
3784
3785
0
    + hb_enumerate (ruleSet)
3786
0
    | hb_filter ([&] (unsigned _)
3787
0
    { return class_def.intersects_class (&c->parent_active_glyphs (), _); },
3788
0
     hb_first)
3789
0
    | hb_apply ([&] (const hb_pair_t<unsigned, const typename Types::template OffsetTo<RuleSet>&> _)
3790
0
                {
3791
0
                  const RuleSet& rule_set = this+_.second;
3792
0
                  rule_set.closure (c, _.first, lookup_context);
3793
0
                })
3794
0
    ;
3795
3796
0
    c->pop_cur_done_glyphs ();
3797
0
  }
3798
3799
  void closure_lookups (hb_closure_lookups_context_t *c) const
3800
0
  {
3801
0
    if (!(this+coverage).intersects (c->glyphs))
3802
0
      return;
3803
3804
0
    const ClassDef &class_def = this+classDef;
3805
3806
0
    hb_map_t cache;
3807
0
    struct ContextClosureLookupContext lookup_context = {
3808
0
      {intersects_class, nullptr},
3809
0
      ContextFormat::ClassBasedContext,
3810
0
      &class_def,
3811
0
      &cache
3812
0
    };
3813
3814
0
    + hb_iter (ruleSet)
3815
0
    | hb_map (hb_add (this))
3816
0
    | hb_enumerate
3817
0
    | hb_filter ([&] (const hb_pair_t<unsigned, const RuleSet &> p)
3818
0
    { return class_def.intersects_class (c->glyphs, p.first); })
3819
0
    | hb_map (hb_second)
3820
0
    | hb_apply ([&] (const RuleSet & _)
3821
0
    { _.closure_lookups (c, lookup_context); });
3822
0
  }
3823
3824
0
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
3825
3826
  void collect_glyphs (hb_collect_glyphs_context_t *c) const
3827
0
  {
3828
0
    (this+coverage).collect_coverage (c->input);
3829
3830
0
    const ClassDef &class_def = this+classDef;
3831
0
    struct ContextCollectGlyphsLookupContext lookup_context = {
3832
0
      {collect_class},
3833
0
      &class_def
3834
0
    };
3835
3836
0
    + hb_iter (ruleSet)
3837
0
    | hb_map (hb_add (this))
3838
0
    | hb_apply ([&] (const RuleSet &_) { _.collect_glyphs (c, lookup_context); })
3839
0
    ;
3840
0
  }
3841
3842
  void collect_second_glyphs (hb_set_digest_t *digest) const
3843
0
  {
3844
0
    const ClassDef &class_def = this+classDef;
3845
0
    + hb_iter (ruleSet)
3846
0
    | hb_map (hb_add (this))
3847
0
    | hb_apply ([=, &class_def] (const RuleSet &_) { _.collect_second_glyphs (digest, &class_def); })
3848
0
    ;
3849
0
  }
3850
3851
  bool would_apply (hb_would_apply_context_t *c) const
3852
0
  {
3853
0
    const ClassDef &class_def = this+classDef;
3854
0
    unsigned int index = class_def.get_class (c->glyphs[0]);
3855
0
    const RuleSet &rule_set = this+ruleSet[index];
3856
0
    struct ContextApplyLookupContext lookup_context = {
3857
0
      {match_class},
3858
0
      &class_def
3859
0
    };
3860
0
    return rule_set.would_apply (c, lookup_context);
3861
0
  }
3862
3863
0
  const Coverage &get_coverage () const { return this+coverage; }
3864
3865
  unsigned cache_cost () const
3866
0
  {
3867
0
    return (this+classDef).cost ();
3868
0
  }
3869
  static bool cache_func (hb_ot_apply_context_t *c, hb_ot_subtable_cache_op_t op)
3870
0
  {
3871
0
    return context_cache_func (c, op);
3872
0
  }
3873
3874
  struct external_cache_t
3875
  {
3876
    hb_ot_layout_binary_cache_t coverage;
3877
    hb_ot_layout_ruleset_digest_t rule_sets[HB_VAR_ARRAY];
3878
  };
3879
  void *external_cache_create () const
3880
0
  {
3881
0
    unsigned count = ruleSet.len;
3882
0
    unsigned size = sizeof (external_cache_t) -
3883
0
        HB_VAR_ARRAY * sizeof (hb_ot_layout_ruleset_digest_t) +
3884
0
        count * sizeof (hb_ot_layout_ruleset_digest_t);
3885
0
    external_cache_t *cache = (external_cache_t *) hb_malloc (size);
3886
0
    if (likely (cache))
3887
0
    {
3888
0
      cache->coverage.clear ();
3889
0
      for (unsigned i = 0; i < count; i++)
3890
0
  (this+ruleSet[i]).collect_first_input_classes (&cache->rule_sets[i]);
3891
0
    }
3892
0
    return cache;
3893
0
  }
3894
0
  bool apply_cached (hb_ot_apply_context_t *c, void *external_cache) const { return _apply (c, true, external_cache); }
3895
0
  bool apply (hb_ot_apply_context_t *c, void *external_cache) const { return _apply (c, false, external_cache); }
3896
  bool _apply (hb_ot_apply_context_t *c, bool cached, void *external_cache) const
3897
0
  {
3898
0
    TRACE_APPLY (this);
3899
0
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
3900
0
    external_cache_t *cache = (external_cache_t *) external_cache;
3901
0
    unsigned int index = (this+coverage).get_coverage_binary (c->buffer->cur().codepoint, cache ? &cache->coverage : nullptr);
3902
#else
3903
    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
3904
#endif
3905
0
    if (index == NOT_COVERED) return_trace (false);
3906
3907
0
    const ClassDef &class_def = this+classDef;
3908
3909
0
    struct ContextApplyLookupContext lookup_context = {
3910
0
      {cached ? match_class_cached : match_class},
3911
0
      &class_def,
3912
0
      cached ? get_class_cached_value : get_class_value
3913
0
    };
3914
3915
0
    index = cached ? get_class_cached (class_def, c->buffer->cur()) : class_def.get_class (c->buffer->cur().codepoint);
3916
0
    const RuleSet &rule_set = this+ruleSet[index];
3917
0
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
3918
0
    const hb_ot_layout_ruleset_digest_t *digest = cache && index < ruleSet.len ? &cache->rule_sets[index] : nullptr;
3919
#else
3920
    const hb_ot_layout_ruleset_digest_t *digest = nullptr;
3921
#endif
3922
0
    return_trace (rule_set.apply (c, lookup_context, digest));
3923
0
  }
3924
3925
  bool subset (hb_subset_context_t *c) const
3926
0
  {
3927
0
    TRACE_SUBSET (this);
3928
0
    auto *out = c->serializer->start_embed (*this);
3929
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
3930
0
    out->format = format;
3931
0
    if (unlikely (!out->coverage.serialize_subset (c, coverage, this)))
3932
0
      return_trace (false);
3933
3934
0
    hb_map_t klass_map;
3935
0
    out->classDef.serialize_subset (c, classDef, this, &klass_map);
3936
3937
0
    const hb_set_t* glyphset = c->plan->glyphset_gsub ();
3938
0
    hb_set_t retained_coverage_glyphs;
3939
0
    (this+coverage).intersect_set (*glyphset, retained_coverage_glyphs);
3940
3941
0
    hb_set_t coverage_glyph_classes;
3942
0
    (this+classDef).intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
3943
3944
0
    const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? &c->plan->gsub_lookups : &c->plan->gpos_lookups;
3945
0
    bool ret = true;
3946
0
    int non_zero_index = -1, index = 0;
3947
0
    auto snapshot = c->serializer->snapshot();
3948
0
    for (const auto& _ : + hb_enumerate (ruleSet)
3949
0
       | hb_filter (klass_map, hb_first))
3950
0
    {
3951
0
      auto *o = out->ruleSet.serialize_append (c->serializer);
3952
0
      if (unlikely (!o))
3953
0
      {
3954
0
  ret = false;
3955
0
  break;
3956
0
      }
3957
3958
0
      if (coverage_glyph_classes.has (_.first) &&
3959
0
    o->serialize_subset (c, _.second, this, lookup_map, &klass_map)) {
3960
0
  non_zero_index = index;
3961
0
        snapshot = c->serializer->snapshot();
3962
0
      }
3963
3964
0
      index++;
3965
0
    }
3966
3967
0
    if (!ret || non_zero_index == -1) return_trace (false);
3968
3969
    //prune empty trailing ruleSets
3970
0
    --index;
3971
0
    while (index > non_zero_index)
3972
0
    {
3973
0
      out->ruleSet.pop ();
3974
0
      index--;
3975
0
    }
3976
0
    c->serializer->revert (snapshot);
3977
3978
0
    return_trace (bool (out->ruleSet));
3979
0
  }
3980
3981
  bool sanitize (hb_sanitize_context_t *c) const
3982
0
  {
3983
0
    TRACE_SANITIZE (this);
3984
0
    return_trace (coverage.sanitize (c, this) && classDef.sanitize (c, this) && ruleSet.sanitize (c, this));
3985
0
  }
3986
3987
  protected:
3988
  HBUINT16  format;     /* Format identifier--format = 2 */
3989
  typename Types::template OffsetTo<Coverage>
3990
    coverage;   /* Offset to Coverage table--from
3991
           * beginning of table */
3992
  typename Types::template OffsetTo<ClassDef>
3993
    classDef;   /* Offset to glyph ClassDef table--from
3994
           * beginning of table */
3995
  Array16Of<typename Types::template OffsetTo<RuleSet>>
3996
    ruleSet;    /* Array of RuleSet tables
3997
           * ordered by class */
3998
  public:
3999
  DEFINE_SIZE_ARRAY (4 + 2 * Types::size, ruleSet);
4000
};
4001
4002
4003
struct ContextFormat3
4004
{
4005
  using RuleSet = OT::RuleSet<SmallTypes>;
4006
4007
  bool intersects (const hb_set_t *glyphs) const
4008
0
  {
4009
0
    if (!(this+coverageZ[0]).intersects (glyphs))
4010
0
      return false;
4011
4012
0
    struct ContextClosureLookupContext lookup_context = {
4013
0
      {intersects_coverage, nullptr},
4014
0
      ContextFormat::CoverageBasedContext,
4015
0
      this
4016
0
    };
4017
0
    return context_intersects (glyphs,
4018
0
             glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
4019
0
             lookup_context);
4020
0
  }
4021
4022
  bool may_have_non_1to1 () const
4023
0
  { return true; }
4024
4025
  void depend (hb_depend_context_t *c) const
4026
0
  {
4027
0
    if (!(this+coverageZ[0]).intersects (c->glyphs))
4028
0
      return;
4029
0
4030
0
    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
4031
0
    if (unlikely (!cur_active_glyphs)) return;
4032
0
    get_coverage ().intersect_set (*c->glyphs, *cur_active_glyphs);
4033
0
4034
0
    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
4035
0
    ContextDependLookupContext lookup_context = {
4036
0
      {intersects_coverage, intersected_coverage_glyphs},
4037
0
      ContextFormat::CoverageBasedContext,
4038
0
      this,
4039
0
      nullptr,  /* intersects_cache */
4040
0
      nullptr   /* intersected_glyphs_cache */
4041
0
    };
4042
0
    context_depend_lookup (c,
4043
0
         glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
4044
0
         lookupCount, lookupRecord,
4045
0
         this,
4046
0
         coverageZ[0], lookup_context);
4047
0
4048
0
    c->pop_cur_done_glyphs ();
4049
0
  }
4050
4051
  void closure (hb_closure_context_t *c) const
4052
0
  {
4053
0
    if (!(this+coverageZ[0]).intersects (c->glyphs))
4054
0
      return;
4055
4056
0
    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
4057
0
    if (unlikely (!cur_active_glyphs)) return;
4058
0
    get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
4059
0
           *cur_active_glyphs);
4060
4061
0
    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
4062
0
    struct ContextClosureLookupContext lookup_context = {
4063
0
      {intersects_coverage, intersected_coverage_glyphs},
4064
0
      ContextFormat::CoverageBasedContext,
4065
0
      this
4066
0
    };
4067
0
    context_closure_lookup (c,
4068
0
          glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
4069
0
          lookupCount, lookupRecord,
4070
0
          0, lookup_context);
4071
4072
0
    c->pop_cur_done_glyphs ();
4073
0
  }
4074
4075
  void closure_lookups (hb_closure_lookups_context_t *c) const
4076
0
  {
4077
0
    if (!intersects (c->glyphs))
4078
0
      return;
4079
0
    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
4080
0
    recurse_lookups (c, lookupCount, lookupRecord);
4081
0
  }
4082
4083
0
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
4084
4085
  void collect_glyphs (hb_collect_glyphs_context_t *c) const
4086
0
  {
4087
0
    (this+coverageZ[0]).collect_coverage (c->input);
4088
4089
0
    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
4090
0
    struct ContextCollectGlyphsLookupContext lookup_context = {
4091
0
      {collect_coverage},
4092
0
      this
4093
0
    };
4094
4095
0
    context_collect_glyphs_lookup (c,
4096
0
           glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
4097
0
           lookupCount, lookupRecord,
4098
0
           lookup_context);
4099
0
  }
4100
4101
  void collect_second_glyphs (hb_set_digest_t *digest) const
4102
0
  {
4103
0
    if (glyphCount <= 1)
4104
0
      *digest = hb_set_digest_t::full ();
4105
0
    else
4106
0
      (this+coverageZ[1]).collect_coverage (digest);
4107
0
  }
4108
4109
  bool would_apply (hb_would_apply_context_t *c) const
4110
0
  {
4111
0
    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
4112
0
    struct ContextApplyLookupContext lookup_context = {
4113
0
      {match_coverage},
4114
0
      this
4115
0
    };
4116
0
    return context_would_apply_lookup (c,
4117
0
               glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1),
4118
0
               lookupCount, lookupRecord,
4119
0
               lookup_context);
4120
0
  }
4121
4122
0
  const Coverage &get_coverage () const { return this+coverageZ[0]; }
4123
4124
  bool apply (hb_ot_apply_context_t *c) const
4125
0
  {
4126
0
    TRACE_APPLY (this);
4127
0
    unsigned int index = (this+coverageZ[0]).get_coverage (c->buffer->cur().codepoint);
4128
0
    if (index == NOT_COVERED) return_trace (false);
4129
4130
0
    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
4131
0
    struct ContextApplyLookupContext lookup_context = {
4132
0
      {match_coverage},
4133
0
      this
4134
0
    };
4135
0
    return_trace (context_apply_lookup (c, glyphCount, (const HBUINT16 *) (coverageZ.arrayZ + 1), lookupCount, lookupRecord, lookup_context));
4136
0
  }
4137
4138
  bool subset (hb_subset_context_t *c) const
4139
0
  {
4140
0
    TRACE_SUBSET (this);
4141
0
    auto *out = c->serializer->start_embed (this);
4142
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
4143
4144
0
    out->format = format;
4145
0
    out->glyphCount = glyphCount;
4146
4147
0
    auto coverages = coverageZ.as_array (glyphCount);
4148
4149
0
    for (const Offset16To<Coverage>& offset : coverages)
4150
0
    {
4151
      /* TODO(subset) This looks like should not be necessary to write this way. */
4152
0
      auto *o = c->serializer->allocate_size<Offset16To<Coverage>> (Offset16To<Coverage>::static_size);
4153
0
      if (unlikely (!o)) return_trace (false);
4154
0
      if (!o->serialize_subset (c, offset, this)) return_trace (false);
4155
0
    }
4156
4157
0
    const auto& lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> (coverageZ.as_array (glyphCount));
4158
0
    const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? &c->plan->gsub_lookups : &c->plan->gpos_lookups;
4159
4160
4161
0
    unsigned count = serialize_lookuprecord_array (c->serializer, lookupRecord.as_array (lookupCount), lookup_map);
4162
0
    return_trace (c->serializer->check_assign (out->lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
4163
0
  }
4164
4165
  bool sanitize (hb_sanitize_context_t *c) const
4166
0
  {
4167
0
    TRACE_SANITIZE (this);
4168
0
    if (unlikely (!c->check_struct (this))) return_trace (false);
4169
0
    hb_barrier ();
4170
0
    unsigned int count = glyphCount;
4171
0
    if (unlikely (!count)) return_trace (false); /* We want to access coverageZ[0] freely. */
4172
0
    if (unlikely (!c->check_array (coverageZ.arrayZ, count))) return_trace (false);
4173
0
    for (unsigned int i = 0; i < count; i++)
4174
0
      if (unlikely (!coverageZ[i].sanitize (c, this))) return_trace (false);
4175
0
    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
4176
0
    return_trace (likely (c->check_array (lookupRecord, lookupCount)));
4177
0
  }
4178
4179
  protected:
4180
  HBUINT16  format;     /* Format identifier--format = 3 */
4181
  HBUINT16  glyphCount;   /* Number of glyphs in the input glyph
4182
           * sequence */
4183
  HBUINT16  lookupCount;    /* Number of LookupRecords */
4184
  UnsizedArrayOf<Offset16To<Coverage>>
4185
    coverageZ;    /* Array of offsets to Coverage
4186
           * table in glyph sequence order */
4187
/*UnsizedArrayOf<LookupRecord>
4188
    lookupRecordX;*/  /* Array of LookupRecords--in
4189
           * design order */
4190
  public:
4191
  DEFINE_SIZE_ARRAY (6, coverageZ);
4192
};
4193
4194
struct Context
4195
{
4196
  template <typename context_t, typename ...Ts>
4197
  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
4198
0
  {
4199
0
    if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
4200
0
    TRACE_DISPATCH (this, u.format.v);
4201
0
    switch (u.format.v) {
4202
0
    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
4203
0
    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
4204
0
    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
4205
#ifndef HB_NO_BEYOND_64K
4206
    case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
4207
    case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
4208
#endif
4209
0
    default:return_trace (c->default_return_value ());
4210
0
    }
4211
0
  }
Unexecuted instantiation: hb_sanitize_context_t::return_t OT::Context::dispatch<hb_sanitize_context_t>(hb_sanitize_context_t*) const
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: 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_depend_context_t::return_t OT::Context::dispatch<OT::hb_depend_context_t>(OT::hb_depend_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_collect_glyph_alternates_dispatch_t::return_t OT::Context::dispatch<hb_collect_glyph_alternates_dispatch_t, hb_map_t*&, hb_map_t*&>(hb_collect_glyph_alternates_dispatch_t*, hb_map_t*&, hb_map_t*&) 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
4212
4213
  protected:
4214
  union {
4215
  struct { HBUINT16 v; }  format;   /* Format identifier */
4216
  ContextFormat1_4<SmallTypes>  format1;
4217
  ContextFormat2_5<SmallTypes>  format2;
4218
  ContextFormat3    format3;
4219
#ifndef HB_NO_BEYOND_64K
4220
  ContextFormat1_4<MediumTypes> format4;
4221
  ContextFormat2_5<MediumTypes> format5;
4222
#endif
4223
  } u;
4224
};
4225
4226
4227
/* Chaining Contextual lookups */
4228
4229
struct ChainContextClosureLookupContext
4230
{
4231
  ContextClosureFuncs funcs;
4232
  ContextFormat context_format;
4233
  const void *intersects_data[3];
4234
  void *intersects_cache[3];
4235
  void *intersected_glyphs_cache;
4236
};
4237
4238
typedef ChainContextClosureLookupContext ChainContextDependLookupContext;
4239
4240
struct ChainContextCollectGlyphsLookupContext
4241
{
4242
  ContextCollectGlyphsFuncs funcs;
4243
  const void *collect_data[3];
4244
};
4245
4246
struct ChainContextApplyLookupContext
4247
{
4248
  ChainContextApplyFuncs funcs;
4249
  const void *match_data[3];
4250
  get_value_func_t get_input_value;
4251
};
4252
4253
template <typename HBUINT>
4254
static inline bool chain_context_intersects (const hb_set_t *glyphs,
4255
               unsigned int backtrackCount,
4256
               const HBUINT backtrack[],
4257
               unsigned int inputCount, /* Including the first glyph (not matched) */
4258
               const HBUINT input[], /* Array of input values--start with second glyph */
4259
               unsigned int lookaheadCount,
4260
               const HBUINT lookahead[],
4261
               ChainContextClosureLookupContext &lookup_context)
4262
0
{
4263
0
  bool bt_ok = array_is_subset_of (glyphs,
4264
0
           backtrackCount, backtrack,
4265
0
           lookup_context.funcs.intersects,
4266
0
           lookup_context.intersects_data[0],
4267
0
           lookup_context.intersects_cache[0]);
4268
0
  bool in_ok = array_is_subset_of (glyphs,
4269
0
           inputCount ? inputCount - 1 : 0, input,
4270
0
           lookup_context.funcs.intersects,
4271
0
           lookup_context.intersects_data[1],
4272
0
           lookup_context.intersects_cache[1]);
4273
0
  bool la_ok = array_is_subset_of (glyphs,
4274
0
           lookaheadCount, lookahead,
4275
0
           lookup_context.funcs.intersects,
4276
0
           lookup_context.intersects_data[2],
4277
0
           lookup_context.intersects_cache[2]);
4278
4279
0
  return bt_ok && in_ok && la_ok;
4280
0
}
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-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-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&)
Unexecuted instantiation: hb-subset.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-subset-plan-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-subset-table-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-subset-table-var.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-subset-table-cff.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-subset-table-color.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-subset-table-other.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: gsubgpos-context.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&)
4281
4282
template <typename HBUINT>
4283
static inline void chain_context_closure_lookup (hb_closure_context_t *c,
4284
             unsigned int backtrackCount,
4285
             const HBUINT backtrack[],
4286
             unsigned int inputCount, /* Including the first glyph (not matched) */
4287
             const HBUINT input[], /* Array of input values--start with second glyph */
4288
             unsigned int lookaheadCount,
4289
             const HBUINT lookahead[],
4290
             unsigned int lookupCount,
4291
             const LookupRecord lookupRecord[],
4292
             unsigned value,
4293
             ChainContextClosureLookupContext &lookup_context)
4294
0
{
4295
0
  if (chain_context_intersects (c->glyphs,
4296
0
        backtrackCount, backtrack,
4297
0
        inputCount, input,
4298
0
        lookaheadCount, lookahead,
4299
0
        lookup_context))
4300
0
    context_closure_recurse_lookups (c,
4301
0
         inputCount, input,
4302
0
         lookupCount, lookupRecord,
4303
0
         value,
4304
0
         lookup_context.context_format,
4305
0
         lookup_context.intersects_data[1],
4306
0
         lookup_context.funcs.intersected_glyphs,
4307
0
         lookup_context.intersected_glyphs_cache);
4308
0
}
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-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-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&)
Unexecuted instantiation: hb-subset.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-subset-plan-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-subset-table-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-subset-table-var.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-subset-table-cff.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-subset-table-color.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-subset-table-other.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: gsubgpos-context.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&)
4309
4310
template <typename HBUINT>
4311
static inline void chain_context_depend_lookup (hb_depend_context_t *c,
4312
            unsigned int backtrackCount,
4313
            const HBUINT backtrack[],
4314
            unsigned int inputCount, /* Including the first glyph (not matched) */
4315
            const HBUINT input[], /* Array of input values--start with second glyph */
4316
            unsigned int lookaheadCount,
4317
            const HBUINT lookahead[],
4318
            unsigned int lookupCount,
4319
            const LookupRecord lookupRecord[],
4320
            const void *rule,
4321
            unsigned value,
4322
            ChainContextDependLookupContext &lookup_context)
4323
0
{
4324
0
  if (!chain_context_intersects (c->glyphs,
4325
0
         backtrackCount, backtrack,
4326
0
         inputCount, input,
4327
0
         lookaheadCount, lookahead,
4328
0
         lookup_context))
4329
0
    return;
4330
0
4331
0
  hb_depend_context_t::depend_scratch_t *scratch = c->acquire_depend_scratch ();
4332
0
  if (unlikely (!scratch))
4333
0
    return;
4334
0
  HB_SCOPE_GUARD (c->release_depend_scratch (scratch));
4335
0
4336
0
  bool context_sets_cached = context_depend_sets_are_cached (
4337
0
    c, inputCount, lookupCount, lookupRecord, rule, value,
4338
0
    lookup_context.context_format, lookup_context.intersects_data[1],
4339
0
    &scratch->cached_context_sets);
4340
0
  if (unlikely (!c->depend_data->successful))
4341
0
    return;
4342
0
  if (context_sets_cached)
4343
0
  {
4344
0
    context_depend_recurse_lookups (c,
4345
0
            inputCount, input,
4346
0
            lookupCount, lookupRecord,
4347
0
            rule,
4348
0
            value,
4349
0
            lookup_context.context_format,
4350
0
            lookup_context.intersects_data[1],
4351
0
            lookup_context.funcs.intersected_glyphs,
4352
0
            lookup_context.intersected_glyphs_cache,
4353
0
            scratch->preliminary_context,
4354
0
            nullptr,
4355
0
            &scratch->cached_context_sets,
4356
0
            scratch);
4357
0
    return;
4358
0
  }
4359
0
4360
0
  /* Cache misses and rules without valid records still perform the original
4361
0
   * dependency-set interning in its observable order. */
4362
0
  hb_set_t &position_scratch = scratch->position_scratch;
4363
0
  hb_vector_t<const hb_set_t *> &backtrack_sets = scratch->backtrack_sets;
4364
0
  hb_vector_t<const hb_set_t *> &lookahead_sets = scratch->lookahead_sets;
4365
0
4366
0
  /* Extract backtrack glyphs */
4367
0
  for (unsigned i = 0; i < backtrackCount; i++)
4368
0
  {
4369
0
    const hb_set_t *pos_glyphs = depend_position_glyphs (
4370
0
      c, lookup_context.context_format, lookup_context.intersects_data[0],
4371
0
      backtrack[i], false, &position_scratch);
4372
0
    if (unlikely (!pos_glyphs))
4373
0
      return;
4374
0
    if (!pos_glyphs->is_empty ())
4375
0
    {
4376
0
      if (unlikely (!backtrack_sets.push_or_fail (pos_glyphs)))
4377
0
      {
4378
0
        c->depend_data->fail ();
4379
0
        return;
4380
0
      }
4381
0
    }
4382
0
  }
4383
0
4384
0
  /* Extract lookahead glyphs */
4385
0
  for (unsigned i = 0; i < lookaheadCount; i++)
4386
0
  {
4387
0
    const hb_set_t *pos_glyphs = depend_position_glyphs (
4388
0
      c, lookup_context.context_format, lookup_context.intersects_data[2],
4389
0
      lookahead[i], false, &position_scratch);
4390
0
    if (unlikely (!pos_glyphs))
4391
0
      return;
4392
0
    if (!pos_glyphs->is_empty ())
4393
0
    {
4394
0
      if (unlikely (!lookahead_sets.push_or_fail (pos_glyphs)))
4395
0
      {
4396
0
        c->depend_data->fail ();
4397
0
        return;
4398
0
      }
4399
0
    }
4400
0
  }
4401
0
4402
0
  /* Build preliminary_context with backtrack + lookahead encoded */
4403
0
  hb_set_t &preliminary_context = scratch->preliminary_context;
4404
0
  for (const hb_set_t *back_set : backtrack_sets)
4405
0
  {
4406
0
    if (back_set->get_population () == 1) {
4407
0
      preliminary_context.add (back_set->get_min ());  // Direct glyph
4408
0
    } else if (back_set->get_population () > 1) {
4409
0
      hb_codepoint_t set_idx = lookup_context.context_format == ContextFormat::SimpleContext
4410
0
        ? c->depend_data->find_or_create_context_set (*back_set)
4411
0
        : c->find_or_create_cached_context_set (back_set);
4412
0
      if (unlikely (set_idx == HB_CODEPOINT_INVALID))
4413
0
        return;
4414
0
      preliminary_context.add (HB_DEPEND_CONTEXT_SET_FLAG | set_idx);  // Encoded set reference
4415
0
    }
4416
0
  }
4417
0
  for (const hb_set_t *look_set : lookahead_sets)
4418
0
  {
4419
0
    if (look_set->get_population () == 1) {
4420
0
      preliminary_context.add (look_set->get_min ());  // Direct glyph
4421
0
    } else if (look_set->get_population () > 1) {
4422
0
      hb_codepoint_t set_idx = lookup_context.context_format == ContextFormat::SimpleContext
4423
0
        ? c->depend_data->find_or_create_context_set (*look_set)
4424
0
        : c->find_or_create_cached_context_set (look_set);
4425
0
      if (unlikely (set_idx == HB_CODEPOINT_INVALID))
4426
0
        return;
4427
0
      preliminary_context.add (HB_DEPEND_CONTEXT_SET_FLAG | set_idx);  // Encoded set reference
4428
0
    }
4429
0
  }
4430
0
  if (unlikely (preliminary_context.in_error ()))
4431
0
  {
4432
0
    c->depend_data->fail ();
4433
0
    return;
4434
0
  }
4435
0
4436
0
  /* Build glyph sets for ALL input positions */
4437
0
  hb_vector_t<const hb_set_t *> &input_position_glyphs = scratch->input_position_glyphs;
4438
0
4439
0
  if (!context_sets_cached)
4440
0
  {
4441
0
    /* Position 0 (first input coverage/class/glyph) — must be in both the
4442
0
     * class AND the coverage, so intersect with parent_active_glyphs. */
4443
0
    const hb_set_t *pos0_glyphs = depend_position_glyphs (
4444
0
      c, lookup_context.context_format, lookup_context.intersects_data[1], value,
4445
0
      true, &position_scratch, &scratch->compact_workspace);
4446
0
    if (unlikely (!pos0_glyphs ||
4447
0
      !input_position_glyphs.push_or_fail (pos0_glyphs)))
4448
0
    {
4449
0
      c->depend_data->fail ();
4450
0
      return;
4451
0
    }
4452
0
4453
0
    /* Positions 1+ (Input array) */
4454
0
    for (unsigned i = 0; i + 1 < inputCount; i++)
4455
0
    {
4456
0
      const hb_set_t *pos_glyphs = depend_position_glyphs (
4457
0
  c, lookup_context.context_format, lookup_context.intersects_data[1],
4458
0
  input[i], false, &position_scratch);
4459
0
      if (unlikely (!pos_glyphs ||
4460
0
        !input_position_glyphs.push_or_fail (pos_glyphs)))
4461
0
      {
4462
0
  c->depend_data->fail ();
4463
0
  return;
4464
0
      }
4465
0
    }
4466
0
  }
4467
0
4468
0
  context_depend_recurse_lookups (c,
4469
0
          inputCount, input,
4470
0
          lookupCount, lookupRecord,
4471
0
          rule,
4472
0
          value,
4473
0
          lookup_context.context_format,
4474
0
          lookup_context.intersects_data[1],
4475
0
          lookup_context.funcs.intersected_glyphs,
4476
0
          lookup_context.intersected_glyphs_cache,
4477
0
          preliminary_context,
4478
0
          context_sets_cached ? nullptr : &input_position_glyphs,
4479
0
          context_sets_cached ? &scratch->cached_context_sets : nullptr,
4480
0
          scratch);
4481
0
}
Unexecuted instantiation: hb-aat-layout.cc:void OT::chain_context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_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*, void const*, unsigned int, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-face.cc:void OT::chain_context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_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*, void const*, unsigned int, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-layout.cc:void OT::chain_context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_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*, void const*, unsigned int, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:void OT::chain_context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_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*, void const*, unsigned int, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-ot-shape-fallback.cc:void OT::chain_context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_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*, void const*, unsigned int, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-subset.cc:void OT::chain_context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_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*, void const*, unsigned int, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-subset-plan-layout.cc:void OT::chain_context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_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*, void const*, unsigned int, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-subset-table-layout.cc:void OT::chain_context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_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*, void const*, unsigned int, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-subset-table-var.cc:void OT::chain_context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_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*, void const*, unsigned int, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-subset-table-cff.cc:void OT::chain_context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_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*, void const*, unsigned int, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-subset-table-color.cc:void OT::chain_context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_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*, void const*, unsigned int, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: hb-subset-table-other.cc:void OT::chain_context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_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*, void const*, unsigned int, OT::ChainContextClosureLookupContext&)
Unexecuted instantiation: gsubgpos-context.cc:void OT::chain_context_depend_lookup<OT::NumType<true, unsigned short, 2u> >(OT::hb_depend_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*, void const*, unsigned int, OT::ChainContextClosureLookupContext&)
4482
4483
template <typename HBUINT>
4484
static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
4485
              unsigned int backtrackCount,
4486
              const HBUINT backtrack[],
4487
              unsigned int inputCount, /* Including the first glyph (not matched) */
4488
              const HBUINT input[], /* Array of input values--start with second glyph */
4489
              unsigned int lookaheadCount,
4490
              const HBUINT lookahead[],
4491
              unsigned int lookupCount,
4492
              const LookupRecord lookupRecord[],
4493
              ChainContextCollectGlyphsLookupContext &lookup_context)
4494
0
{
4495
0
  collect_array (c, c->before,
4496
0
     backtrackCount, backtrack,
4497
0
     lookup_context.funcs.collect, lookup_context.collect_data[0]);
4498
0
  collect_array (c, c->input,
4499
0
     inputCount ? inputCount - 1 : 0, input,
4500
0
     lookup_context.funcs.collect, lookup_context.collect_data[1]);
4501
0
  collect_array (c, c->after,
4502
0
     lookaheadCount, lookahead,
4503
0
     lookup_context.funcs.collect, lookup_context.collect_data[2]);
4504
0
  recurse_lookups (c,
4505
0
       lookupCount, lookupRecord);
4506
0
}
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-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-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&)
Unexecuted instantiation: hb-subset.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-subset-plan-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-subset-table-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-subset-table-var.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-subset-table-cff.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-subset-table-color.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-subset-table-other.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: gsubgpos-context.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&)
4507
4508
template <typename HBUINT>
4509
static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
4510
                 unsigned int backtrackCount,
4511
                 const HBUINT backtrack[] HB_UNUSED,
4512
                 unsigned int inputCount, /* Including the first glyph (not matched) */
4513
                 const HBUINT input[], /* Array of input values--start with second glyph */
4514
                 unsigned int lookaheadCount,
4515
                 const HBUINT lookahead[] HB_UNUSED,
4516
                 unsigned int lookupCount HB_UNUSED,
4517
                 const LookupRecord lookupRecord[] HB_UNUSED,
4518
                 const ChainContextApplyLookupContext &lookup_context)
4519
0
{
4520
0
  return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
4521
0
      && would_match_input (c,
4522
0
          inputCount, input,
4523
0
          lookup_context.funcs.match[1], lookup_context.match_data[1]);
4524
0
}
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-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-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&)
Unexecuted instantiation: hb-subset.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-subset-plan-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-subset-table-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-subset-table-var.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-subset-table-cff.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-subset-table-color.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-subset-table-other.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: gsubgpos-context.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&)
4525
4526
template <typename HBUINT>
4527
static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
4528
                 unsigned int backtrackCount,
4529
                 const HBUINT backtrack[],
4530
                 unsigned int inputCount, /* Including the first glyph (not matched) */
4531
                 const HBUINT input[], /* Array of input values--start with second glyph */
4532
                 unsigned int lookaheadCount,
4533
                 const HBUINT lookahead[],
4534
                 unsigned int lookupCount,
4535
                 const LookupRecord lookupRecord[],
4536
                 const ChainContextApplyLookupContext &lookup_context)
4537
246k
{
4538
246k
  if (unlikely (inputCount > HB_MAX_CONTEXT_LENGTH)) return false;
4539
4540
246k
  unsigned start_index = c->buffer->out_len;
4541
246k
  unsigned end_index = c->buffer->idx;
4542
246k
  unsigned match_end = 0;
4543
246k
  bool ret = true;
4544
246k
  if (!(match_input (c,
4545
246k
         inputCount, input,
4546
246k
         lookup_context.funcs.match[1], lookup_context.match_data[1],
4547
246k
         &match_end) && (end_index = match_end)
4548
217k
       && match_lookahead (c,
4549
217k
         lookaheadCount, lookahead,
4550
217k
         lookup_context.funcs.match[2], lookup_context.match_data[2],
4551
217k
         match_end, &end_index)))
4552
111k
  {
4553
111k
    c->buffer->unsafe_to_concat (c->buffer->idx, end_index);
4554
111k
    return false;
4555
111k
  }
4556
4557
135k
  if (!match_backtrack (c,
4558
135k
      backtrackCount, backtrack,
4559
135k
      lookup_context.funcs.match[0], lookup_context.match_data[0],
4560
135k
      &start_index))
4561
134k
  {
4562
134k
    c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index);
4563
134k
    return false;
4564
134k
  }
4565
4566
373
  c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
4567
373
  apply_lookup (c,
4568
373
    inputCount,
4569
373
    lookupCount, lookupRecord,
4570
373
    match_end);
4571
4572
373
  return ret;
4573
135k
}
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-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&)
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&)
Line
Count
Source
4537
246k
{
4538
246k
  if (unlikely (inputCount > HB_MAX_CONTEXT_LENGTH)) return false;
4539
4540
246k
  unsigned start_index = c->buffer->out_len;
4541
246k
  unsigned end_index = c->buffer->idx;
4542
246k
  unsigned match_end = 0;
4543
246k
  bool ret = true;
4544
246k
  if (!(match_input (c,
4545
246k
         inputCount, input,
4546
246k
         lookup_context.funcs.match[1], lookup_context.match_data[1],
4547
246k
         &match_end) && (end_index = match_end)
4548
217k
       && match_lookahead (c,
4549
217k
         lookaheadCount, lookahead,
4550
217k
         lookup_context.funcs.match[2], lookup_context.match_data[2],
4551
217k
         match_end, &end_index)))
4552
111k
  {
4553
111k
    c->buffer->unsafe_to_concat (c->buffer->idx, end_index);
4554
111k
    return false;
4555
111k
  }
4556
4557
135k
  if (!match_backtrack (c,
4558
135k
      backtrackCount, backtrack,
4559
135k
      lookup_context.funcs.match[0], lookup_context.match_data[0],
4560
135k
      &start_index))
4561
134k
  {
4562
134k
    c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index);
4563
134k
    return false;
4564
134k
  }
4565
4566
373
  c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
4567
373
  apply_lookup (c,
4568
373
    inputCount,
4569
373
    lookupCount, lookupRecord,
4570
373
    match_end);
4571
4572
373
  return ret;
4573
135k
}
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&)
Unexecuted instantiation: hb-subset.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-subset-plan-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-subset-table-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-subset-table-var.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-subset-table-cff.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-subset-table-color.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-subset-table-other.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: gsubgpos-context.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&)
4574
4575
template <typename Types>
4576
struct ChainRule
4577
{
4578
  template <typename T>
4579
  friend struct ChainRuleSet;
4580
4581
  bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
4582
0
  {
4583
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4584
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4585
0
    return chain_context_intersects (glyphs,
4586
0
             backtrack.len, backtrack.arrayZ,
4587
0
             input.lenP1, input.arrayZ,
4588
0
             lookahead.len, lookahead.arrayZ,
4589
0
             lookup_context);
4590
0
  }
4591
4592
  void depend (hb_depend_context_t *c, unsigned value, ChainContextDependLookupContext &lookup_context) const
4593
0
  {
4594
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4595
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4596
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
4597
0
    chain_context_depend_lookup (c,
4598
0
         backtrack.len, backtrack.arrayZ,
4599
0
         input.lenP1, input.arrayZ,
4600
0
         lookahead.len, lookahead.arrayZ,
4601
0
         lookup.len, lookup.arrayZ,
4602
0
         this,
4603
0
         value,
4604
0
         lookup_context);
4605
0
  }
4606
4607
  void closure (hb_closure_context_t *c, unsigned value,
4608
    ChainContextClosureLookupContext &lookup_context) const
4609
0
  {
4610
0
    if (unlikely (c->lookup_limit_exceeded ())) return;
4611
4612
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4613
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4614
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
4615
0
    chain_context_closure_lookup (c,
4616
0
          backtrack.len, backtrack.arrayZ,
4617
0
          input.lenP1, input.arrayZ,
4618
0
          lookahead.len, lookahead.arrayZ,
4619
0
          lookup.len, lookup.arrayZ,
4620
0
          value,
4621
0
          lookup_context);
4622
0
  }
4623
4624
  void closure_lookups (hb_closure_lookups_context_t *c,
4625
                        ChainContextClosureLookupContext &lookup_context) const
4626
0
  {
4627
0
    if (unlikely (c->lookup_limit_exceeded ())) return;
4628
0
    if (!intersects (c->glyphs, lookup_context)) return;
4629
4630
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4631
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4632
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
4633
0
    recurse_lookups (c, lookup.len, lookup.arrayZ);
4634
0
  }
4635
4636
  void collect_glyphs (hb_collect_glyphs_context_t *c,
4637
           ChainContextCollectGlyphsLookupContext &lookup_context) const
4638
0
  {
4639
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4640
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4641
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
4642
0
    chain_context_collect_glyphs_lookup (c,
4643
0
           backtrack.len, backtrack.arrayZ,
4644
0
           input.lenP1, input.arrayZ,
4645
0
           lookahead.len, lookahead.arrayZ,
4646
0
           lookup.len, lookup.arrayZ,
4647
0
           lookup_context);
4648
0
  }
4649
4650
  void collect_second_glyphs (hb_set_digest_t *digest,
4651
            const ClassDef *input_class_def = nullptr,
4652
            const ClassDef *lookahead_class_def = nullptr) const
4653
0
  {
4654
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4655
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4656
4657
0
    unsigned second;
4658
0
    const ClassDef *class_def;
4659
0
    if (input.lenP1 > 1)
4660
0
    {
4661
0
      second = input.arrayZ[0];
4662
0
      class_def = input_class_def;
4663
0
    }
4664
0
    else if (lookahead.len)
4665
0
    {
4666
0
      second = lookahead.arrayZ[0];
4667
0
      class_def = lookahead_class_def;
4668
0
    }
4669
0
    else
4670
0
    {
4671
0
      *digest = hb_set_digest_t::full ();
4672
0
      return;
4673
0
    }
4674
4675
0
    if (!class_def)
4676
0
      digest->add (second);
4677
0
    else if (!second)
4678
0
      *digest = hb_set_digest_t::full ();
4679
0
    else
4680
0
      class_def->collect_class (digest, second);
4681
0
  }
4682
4683
  bool would_apply (hb_would_apply_context_t *c,
4684
        const ChainContextApplyLookupContext &lookup_context) const
4685
0
  {
4686
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4687
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4688
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
4689
0
    return chain_context_would_apply_lookup (c,
4690
0
               backtrack.len, backtrack.arrayZ,
4691
0
               input.lenP1, input.arrayZ,
4692
0
               lookahead.len, lookahead.arrayZ, lookup.len,
4693
0
               lookup.arrayZ, lookup_context);
4694
0
  }
4695
4696
  bool apply (hb_ot_apply_context_t *c,
4697
        const ChainContextApplyLookupContext &lookup_context) const
4698
0
  {
4699
0
    TRACE_APPLY (this);
4700
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4701
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4702
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
4703
0
    return_trace (chain_context_apply_lookup (c,
4704
0
                backtrack.len, backtrack.arrayZ,
4705
0
                input.lenP1, input.arrayZ,
4706
0
                lookahead.len, lookahead.arrayZ, lookup.len,
4707
0
                lookup.arrayZ, lookup_context));
4708
0
  }
4709
4710
  template<typename Iterator,
4711
     hb_requires (hb_is_iterator (Iterator))>
4712
  void serialize_array (hb_serialize_context_t *c,
4713
      HBUINT16 len,
4714
      Iterator it) const
4715
0
  {
4716
0
    c->copy (len);
4717
0
    for (const auto g : it)
4718
0
      c->copy ((HBUINT16) g);
4719
0
  }
4720
4721
  bool serialize (hb_serialize_context_t *c,
4722
      const hb_map_t *lookup_map,
4723
      const hb_map_t *backtrack_map,
4724
      const hb_map_t *input_map = nullptr,
4725
      const hb_map_t *lookahead_map = nullptr) const
4726
0
  {
4727
0
    TRACE_SERIALIZE (this);
4728
4729
0
    const hb_map_t *mapping = backtrack_map;
4730
0
    serialize_array (c, backtrack.len, + backtrack.iter ()
4731
0
               | hb_map (mapping));
4732
4733
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4734
0
    if (input_map) mapping = input_map;
4735
0
    serialize_array (c, input.lenP1, + input.iter ()
4736
0
             | hb_map (mapping));
4737
4738
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4739
0
    if (lookahead_map) mapping = lookahead_map;
4740
0
    serialize_array (c, lookahead.len, + lookahead.iter ()
4741
0
               | hb_map (mapping));
4742
4743
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
4744
4745
0
    HBUINT16* lookupCount = c->embed (&(lookup.len));
4746
0
    if (!lookupCount) return_trace (false);
4747
4748
0
    unsigned count = serialize_lookuprecord_array (c, lookup.as_array (), lookup_map);
4749
0
    return_trace (c->check_assign (*lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
4750
0
  }
4751
4752
  bool subset (hb_subset_context_t *c,
4753
         const hb_map_t *lookup_map,
4754
         const hb_map_t *backtrack_map = nullptr,
4755
         const hb_map_t *input_map = nullptr,
4756
         const hb_map_t *lookahead_map = nullptr) const
4757
0
  {
4758
0
    TRACE_SUBSET (this);
4759
4760
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4761
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4762
4763
0
    if (!backtrack_map)
4764
0
    {
4765
0
      const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
4766
0
      if (!hb_all (backtrack, glyphset) ||
4767
0
    !hb_all (input, glyphset) ||
4768
0
    !hb_all (lookahead, glyphset))
4769
0
  return_trace (false);
4770
4771
0
      serialize (c->serializer, lookup_map, c->plan->glyph_map);
4772
0
    }
4773
0
    else
4774
0
    {
4775
0
      if (!hb_all (backtrack, backtrack_map) ||
4776
0
    !hb_all (input, input_map) ||
4777
0
    !hb_all (lookahead, lookahead_map))
4778
0
  return_trace (false);
4779
4780
0
      serialize (c->serializer, lookup_map, backtrack_map, input_map, lookahead_map);
4781
0
    }
4782
4783
0
    return_trace (true);
4784
0
  }
4785
4786
  bool sanitize (hb_sanitize_context_t *c) const
4787
0
  {
4788
0
    TRACE_SANITIZE (this);
4789
    /* Hyper-optimized sanitized because this is really hot. */
4790
0
    if (unlikely (!backtrack.len.sanitize (c))) return_trace (false);
4791
0
    hb_barrier ();
4792
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
4793
0
    if (unlikely (!input.lenP1.sanitize (c))) return_trace (false);
4794
0
    hb_barrier ();
4795
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
4796
0
    if (unlikely (!lookahead.len.sanitize (c))) return_trace (false);
4797
0
    hb_barrier ();
4798
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
4799
0
    return_trace (likely (lookup.sanitize (c)));
4800
0
  }
4801
4802
  protected:
4803
  Array16Of<typename Types::HBUINT>
4804
    backtrack;    /* Array of backtracking values
4805
           * (to be matched before the input
4806
           * sequence) */
4807
  HeadlessArray16Of<typename Types::HBUINT>
4808
    inputX;     /* Array of input values (start with
4809
           * second glyph) */
4810
  Array16Of<typename Types::HBUINT>
4811
    lookaheadX;   /* Array of lookahead values's (to be
4812
           * matched after the input sequence) */
4813
  Array16Of<LookupRecord>
4814
    lookupX;    /* Array of LookupRecords--in
4815
           * design order) */
4816
  public:
4817
  DEFINE_SIZE_MIN (8);
4818
};
4819
4820
template <typename Types>
4821
struct ChainRuleSet
4822
{
4823
  using ChainRule = OT::ChainRule<Types>;
4824
4825
  bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
4826
0
  {
4827
0
    return
4828
0
    + hb_iter (rule)
4829
0
    | hb_map (hb_add (this))
4830
0
    | hb_map ([&] (const ChainRule &_) { return _.intersects (glyphs, lookup_context); })
4831
0
    | hb_any
4832
0
    ;
4833
0
  }
4834
4835
  void collect_first_input_classes (hb_ot_layout_ruleset_digest_t *digest) const
4836
0
  {
4837
0
    digest->init ();
4838
0
    for (unsigned i = 0; i < rule.len; i++)
4839
0
    {
4840
0
      const ChainRule &r = this+rule.arrayZ[i];
4841
0
      const auto &input = StructAfter<decltype (r.inputX)> (r.backtrack);
4842
0
      if (input.lenP1 <= 1)
4843
0
      {
4844
0
  digest->set_full ();
4845
0
  return;
4846
0
      }
4847
0
      digest->add (input.arrayZ[0]);
4848
0
    }
4849
0
  }
4850
  void depend (hb_depend_context_t *c, unsigned value, ChainContextDependLookupContext &lookup_context) const
4851
0
  {
4852
0
    + hb_iter (rule)
4853
0
    | hb_map (hb_add (this))
4854
0
    | hb_apply ([&] (const ChainRule &_) { _.depend (c, value, lookup_context); })
4855
0
    ;
4856
0
  }
4857
  void closure (hb_closure_context_t *c, unsigned value, ChainContextClosureLookupContext &lookup_context) const
4858
0
  {
4859
0
    if (unlikely (c->lookup_limit_exceeded ())) return;
4860
4861
0
    return
4862
0
    + hb_iter (rule)
4863
0
    | hb_map (hb_add (this))
4864
0
    | hb_apply ([&] (const ChainRule &_) { _.closure (c, value, lookup_context); })
4865
0
    ;
4866
0
  }
4867
4868
  void closure_lookups (hb_closure_lookups_context_t *c,
4869
                        ChainContextClosureLookupContext &lookup_context) const
4870
0
  {
4871
0
    if (unlikely (c->lookup_limit_exceeded ())) return;
4872
4873
0
    + hb_iter (rule)
4874
0
    | hb_map (hb_add (this))
4875
0
    | hb_apply ([&] (const ChainRule &_) { _.closure_lookups (c, lookup_context); })
4876
0
    ;
4877
0
  }
4878
4879
  void collect_glyphs (hb_collect_glyphs_context_t *c, ChainContextCollectGlyphsLookupContext &lookup_context) const
4880
0
  {
4881
0
    return
4882
0
    + hb_iter (rule)
4883
0
    | hb_map (hb_add (this))
4884
0
    | hb_apply ([&] (const ChainRule &_) { _.collect_glyphs (c, lookup_context); })
4885
0
    ;
4886
0
  }
4887
4888
  void collect_second_glyphs (hb_set_digest_t *digest,
4889
            const ClassDef *input_class_def = nullptr,
4890
            const ClassDef *lookahead_class_def = nullptr) const
4891
0
  {
4892
0
    + hb_iter (rule)
4893
0
    | hb_map (hb_add (this))
4894
0
    | hb_apply ([=] (const ChainRule &_)
4895
0
    { _.collect_second_glyphs (digest, input_class_def, lookahead_class_def); })
4896
0
    ;
4897
0
  }
4898
4899
  bool would_apply (hb_would_apply_context_t *c,
4900
        const ChainContextApplyLookupContext &lookup_context) const
4901
0
  {
4902
0
    return
4903
0
    + hb_iter (rule)
4904
0
    | hb_map (hb_add (this))
4905
0
    | hb_map ([&] (const ChainRule &_) { return _.would_apply (c, lookup_context); })
4906
0
    | hb_any
4907
0
    ;
4908
0
  }
4909
4910
  bool apply (hb_ot_apply_context_t *c,
4911
        const ChainContextApplyLookupContext &lookup_context,
4912
        const hb_ot_layout_ruleset_digest_t *digest = nullptr) const
4913
0
  {
4914
0
    TRACE_APPLY (this);
4915
4916
0
    unsigned num_rules = rule.len;
4917
4918
0
#ifndef HB_NO_OT_RULESETS_FAST_PATH
4919
0
    if (HB_OPTIMIZE_SIZE_VAL || num_rules <= 4)
4920
0
#endif
4921
0
    {
4922
0
    slow:
4923
0
      return_trace (
4924
0
      + hb_iter (rule)
4925
0
      | hb_map (hb_add (this))
4926
0
      | hb_map ([&] (const ChainRule &_) { return _.apply (c, lookup_context); })
4927
0
      | hb_any
4928
0
      )
4929
0
      ;
4930
0
    }
4931
4932
    /* This version is optimized for speed by matching the first & second
4933
     * components of the rule here, instead of calling into the matching code.
4934
     *
4935
     * Replicated from LigatureSet::apply(). */
4936
4937
    /* We use the iter_context instead of iter_input, to avoid skipping
4938
     * default-ignorables and such.
4939
     *
4940
     * Related: https://github.com/harfbuzz/harfbuzz/issues/4813
4941
     */
4942
0
    auto &skippy_iter = c->iter_context;
4943
0
    skippy_iter.reset (c->buffer->idx);
4944
0
    skippy_iter.set_match_func (match_always, nullptr);
4945
0
    skippy_iter.set_glyph_data ((HBUINT16 *) nullptr);
4946
0
    unsigned unsafe_to = (unsigned) -1, unsafe_to1, unsafe_to2 = 0;
4947
0
    hb_glyph_info_t *first = nullptr, *second = nullptr;
4948
0
    bool matched = skippy_iter.next (&unsafe_to1);
4949
0
    if (likely (matched))
4950
0
    {
4951
0
      if (skippy_iter.may_skip (c->buffer->info[skippy_iter.idx]))
4952
0
      {
4953
  /* Can't use the fast path if eg. the next char is a default-ignorable
4954
   * or other skippable. */
4955
0
        goto slow;
4956
0
      }
4957
4958
0
      first = &c->buffer->info[skippy_iter.idx];
4959
0
      unsafe_to1 = skippy_iter.idx + 1;
4960
4961
0
      if (digest && lookup_context.get_input_value &&
4962
0
    !digest->may_have (lookup_context.get_input_value (*first, lookup_context.match_data[1])))
4963
0
  {
4964
0
    c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to1);
4965
0
    return_trace (false);
4966
0
  }
4967
0
    }
4968
0
    else
4969
0
    {
4970
0
      bool unsafe_to_concat = false;
4971
0
      bool ret =
4972
0
      + hb_iter (rule)
4973
0
      | hb_map (hb_add (this))
4974
0
      | hb_filter ([&] (const ChainRule &_)
4975
0
       {
4976
0
         const auto &input = StructAfter<decltype (_.inputX)> (_.backtrack);
4977
0
         const auto &lookahead = StructAfter<decltype (_.lookaheadX)> (input);
4978
0
         if (input.lenP1 <= 1 && lookahead.len == 0) return true;
4979
0
         unsafe_to_concat = true;
4980
0
         return false;
4981
0
       })
4982
0
      | hb_map ([&] (const ChainRule &_) { return _.apply (c, lookup_context); })
4983
0
      | hb_any
4984
0
      ;
4985
0
      if (unsafe_to_concat)
4986
0
  c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to1);
4987
0
      return_trace (ret);
4988
0
    }
4989
0
    matched = skippy_iter.next ();
4990
0
    if (likely (matched))
4991
0
    {
4992
0
      if (skippy_iter.may_skip (c->buffer->info[skippy_iter.idx]))
4993
0
      {
4994
  /* Can't use the fast path if eg. the next char is a default-ignorable
4995
   * or other skippable. */
4996
0
        goto slow;
4997
0
      }
4998
4999
0
      second = &c->buffer->info[skippy_iter.idx];
5000
0
      unsafe_to2 = skippy_iter.idx + 1;
5001
0
    }
5002
5003
0
    auto match_input = lookup_context.funcs.match[1];
5004
0
    auto match_lookahead = lookup_context.funcs.match[2];
5005
0
    auto *input_data = lookup_context.match_data[1];
5006
0
    auto *lookahead_data = lookup_context.match_data[2];
5007
0
    for (unsigned int i = 0; i < num_rules; i++)
5008
0
    {
5009
0
      const auto &r = this+rule.arrayZ[i];
5010
5011
0
      const auto &input = StructAfter<decltype (r.inputX)> (r.backtrack);
5012
0
      const auto &lookahead = StructAfter<decltype (r.lookaheadX)> (input);
5013
5014
0
      unsigned lenP1 = input.lenP1;
5015
0
      if (lenP1 > 1 ?
5016
0
     (!match_input ||
5017
0
      match_input (*first, input.arrayZ[0], input_data))
5018
0
    :
5019
0
     (!lookahead.len || !match_lookahead ||
5020
0
      match_lookahead (*first, lookahead.arrayZ[0], lookahead_data)))
5021
0
      {
5022
0
  lenP1 = hb_max (lenP1, 1u);
5023
0
        if (!second ||
5024
0
      (lenP1 > 2 ?
5025
0
       (!match_input ||
5026
0
        match_input (*second, input.arrayZ[1], input_data))
5027
0
       :
5028
0
       (lookahead.len <= 2 - lenP1 || !match_lookahead ||
5029
0
        match_lookahead (*second, lookahead.arrayZ[2 - lenP1], lookahead_data))))
5030
0
  {
5031
0
    if (r.apply (c, lookup_context))
5032
0
    {
5033
0
      if (unsafe_to != (unsigned) -1)
5034
0
        c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to);
5035
0
      return_trace (true);
5036
0
    }
5037
0
  }
5038
0
  else
5039
0
    unsafe_to = unsafe_to2;
5040
0
      }
5041
0
      else
5042
0
      {
5043
0
  if (unsafe_to == (unsigned) -1)
5044
0
    unsafe_to = unsafe_to1;
5045
5046
0
  if (lenP1 > 1)
5047
0
  {
5048
    // Skip ahead to next possible first glyph match.
5049
0
    for (; i + 1 < num_rules; i++)
5050
0
    {
5051
0
      const auto &r2 = this+rule.arrayZ[i + 1];
5052
0
      const auto &input2 = StructAfter<decltype (r2.inputX)> (r2.backtrack);
5053
0
      if (input2.lenP1 <= 1 || input2.arrayZ[0] != input.arrayZ[0])
5054
0
        break;
5055
0
    }
5056
0
  }
5057
0
      }
5058
0
    }
5059
0
    if (likely (unsafe_to != (unsigned) -1))
5060
0
      c->buffer->unsafe_to_concat (c->buffer->idx, unsafe_to);
5061
5062
0
    return_trace (false);
5063
0
  }
5064
5065
  bool subset (hb_subset_context_t *c,
5066
         const hb_map_t *lookup_map,
5067
         const hb_map_t *backtrack_klass_map = nullptr,
5068
         const hb_map_t *input_klass_map = nullptr,
5069
         const hb_map_t *lookahead_klass_map = nullptr) const
5070
0
  {
5071
0
    TRACE_SUBSET (this);
5072
5073
0
    auto snap = c->serializer->snapshot ();
5074
0
    auto *out = c->serializer->start_embed (*this);
5075
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
5076
5077
0
    for (const Offset16To<ChainRule>& _ : rule)
5078
0
    {
5079
0
      if (!_) continue;
5080
0
      auto o_snap = c->serializer->snapshot ();
5081
0
      auto *o = out->rule.serialize_append (c->serializer);
5082
0
      if (unlikely (!o)) continue;
5083
5084
0
      if (!o->serialize_subset (c, _, this,
5085
0
        lookup_map,
5086
0
        backtrack_klass_map,
5087
0
        input_klass_map,
5088
0
        lookahead_klass_map))
5089
0
      {
5090
0
  out->rule.pop ();
5091
0
  c->serializer->revert (o_snap);
5092
0
      }
5093
0
    }
5094
5095
0
    bool ret = bool (out->rule);
5096
0
    if (!ret) c->serializer->revert (snap);
5097
5098
0
    return_trace (ret);
5099
0
  }
5100
5101
  bool sanitize (hb_sanitize_context_t *c) const
5102
0
  {
5103
0
    TRACE_SANITIZE (this);
5104
0
    return_trace (rule.sanitize (c, this));
5105
0
  }
5106
5107
  protected:
5108
  Array16OfOffset16To<ChainRule>
5109
    rule;     /* Array of ChainRule tables
5110
           * ordered by preference */
5111
  public:
5112
  DEFINE_SIZE_ARRAY (2, rule);
5113
};
5114
5115
template <typename Types>
5116
struct ChainContextFormat1_4
5117
{
5118
  using ChainRuleSet = OT::ChainRuleSet<Types>;
5119
5120
  bool intersects (const hb_set_t *glyphs) const
5121
0
  {
5122
0
    struct ChainContextClosureLookupContext lookup_context = {
5123
0
      {intersects_glyph, intersected_glyph},
5124
0
      ContextFormat::SimpleContext,
5125
0
      {nullptr, nullptr, nullptr}
5126
0
    };
5127
5128
0
    return
5129
0
    + hb_zip (this+coverage, ruleSet)
5130
0
    | hb_filter (*glyphs, hb_first)
5131
0
    | hb_map (hb_second)
5132
0
    | hb_map (hb_add (this))
5133
0
    | hb_map ([&] (const ChainRuleSet &_) { return _.intersects (glyphs, lookup_context); })
5134
0
    | hb_any
5135
0
    ;
5136
0
  }
5137
5138
  bool may_have_non_1to1 () const
5139
0
  { return true; }
5140
5141
  void depend (hb_depend_context_t *c) const
5142
0
  {
5143
0
    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
5144
0
    if (unlikely (!cur_active_glyphs)) return;
5145
0
    get_coverage ().intersect_set (*c->glyphs, *cur_active_glyphs);
5146
0
5147
0
    ChainContextDependLookupContext lookup_context = {
5148
0
      {intersects_glyph, intersected_glyph},
5149
0
      ContextFormat::SimpleContext,
5150
0
      {nullptr, nullptr, nullptr},
5151
0
      {nullptr, nullptr, nullptr},  /* intersects_cache */
5152
0
      nullptr                        /* intersected_glyphs_cache */
5153
0
    };
5154
0
5155
0
    + hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len))
5156
0
    | hb_filter ([&] (hb_codepoint_t _) {
5157
0
      return c->parent_active_glyphs ().has (_);
5158
0
    }, hb_first)
5159
0
    | hb_map ([&](const hb_pair_t<hb_codepoint_t, unsigned> _) { return hb_pair_t<unsigned, const ChainRuleSet&> (_.first, this+ruleSet[_.second]); })
5160
0
    | hb_apply ([&] (const hb_pair_t<unsigned, const ChainRuleSet&>& _) { _.second.depend (c, _.first, lookup_context); })
5161
0
    ;
5162
0
5163
0
    c->pop_cur_done_glyphs ();
5164
0
  }
5165
5166
  void closure (hb_closure_context_t *c) const
5167
0
  {
5168
0
    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
5169
0
    if (unlikely (!cur_active_glyphs)) return;
5170
0
    get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
5171
0
           *cur_active_glyphs);
5172
5173
0
    struct ChainContextClosureLookupContext lookup_context = {
5174
0
      {intersects_glyph, intersected_glyph},
5175
0
      ContextFormat::SimpleContext,
5176
0
      {nullptr, nullptr, nullptr}
5177
0
    };
5178
5179
0
    + hb_zip (this+coverage, hb_range ((unsigned) ruleSet.len))
5180
0
    | hb_filter ([&] (hb_codepoint_t _) {
5181
0
      return c->previous_parent_active_glyphs ().has (_);
5182
0
    }, hb_first)
5183
0
    | hb_map ([&](const hb_pair_t<hb_codepoint_t, unsigned> _) { return hb_pair_t<unsigned, const ChainRuleSet&> (_.first, this+ruleSet[_.second]); })
5184
0
    | hb_apply ([&] (const hb_pair_t<unsigned, const ChainRuleSet&>& _) { _.second.closure (c, _.first, lookup_context); })
5185
0
    ;
5186
5187
0
    c->pop_cur_done_glyphs ();
5188
0
  }
5189
5190
  void closure_lookups (hb_closure_lookups_context_t *c) const
5191
0
  {
5192
0
    struct ChainContextClosureLookupContext lookup_context = {
5193
0
      {intersects_glyph, nullptr},
5194
0
      ContextFormat::SimpleContext,
5195
0
      {nullptr, nullptr, nullptr}
5196
0
    };
5197
5198
0
    + hb_zip (this+coverage, ruleSet)
5199
0
    | hb_filter (*c->glyphs, hb_first)
5200
0
    | hb_map (hb_second)
5201
0
    | hb_map (hb_add (this))
5202
0
    | hb_apply ([&] (const ChainRuleSet &_) { _.closure_lookups (c, lookup_context); })
5203
0
    ;
5204
0
  }
5205
5206
0
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
5207
5208
  void collect_glyphs (hb_collect_glyphs_context_t *c) const
5209
0
  {
5210
0
    (this+coverage).collect_coverage (c->input);
5211
5212
0
    struct ChainContextCollectGlyphsLookupContext lookup_context = {
5213
0
      {collect_glyph},
5214
0
      {nullptr, nullptr, nullptr}
5215
0
    };
5216
5217
0
    + hb_iter (ruleSet)
5218
0
    | hb_map (hb_add (this))
5219
0
    | hb_apply ([&] (const ChainRuleSet &_) { _.collect_glyphs (c, lookup_context); })
5220
0
    ;
5221
0
  }
5222
5223
  void collect_second_glyphs (hb_set_digest_t *digest) const
5224
0
  {
5225
0
    + hb_iter (ruleSet)
5226
0
    | hb_map (hb_add (this))
5227
0
    | hb_apply ([digest] (const ChainRuleSet &_) { _.collect_second_glyphs (digest); })
5228
0
    ;
5229
0
  }
5230
5231
  bool would_apply (hb_would_apply_context_t *c) const
5232
0
  {
5233
0
    const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
5234
0
    struct ChainContextApplyLookupContext lookup_context = {
5235
0
      {{match_glyph, match_glyph, match_glyph}},
5236
0
      {nullptr, nullptr, nullptr}
5237
0
    };
5238
0
    return rule_set.would_apply (c, lookup_context);
5239
0
  }
5240
5241
0
  const Coverage &get_coverage () const { return this+coverage; }
5242
5243
  bool apply (hb_ot_apply_context_t *c) const
5244
0
  {
5245
0
    TRACE_APPLY (this);
5246
0
    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
5247
0
    if (index == NOT_COVERED) return_trace (false);
5248
5249
0
    const ChainRuleSet &rule_set = this+ruleSet[index];
5250
0
    struct ChainContextApplyLookupContext lookup_context = {
5251
0
      {{match_glyph, match_glyph, match_glyph}},
5252
0
      {nullptr, nullptr, nullptr}
5253
0
    };
5254
0
    return_trace (rule_set.apply (c, lookup_context));
5255
0
  }
5256
5257
  bool subset (hb_subset_context_t *c) const
5258
0
  {
5259
0
    TRACE_SUBSET (this);
5260
0
    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
5261
0
    const hb_map_t &glyph_map = *c->plan->glyph_map;
5262
5263
0
    auto *out = c->serializer->start_embed (*this);
5264
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
5265
0
    out->format = format;
5266
5267
0
    const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? &c->plan->gsub_lookups : &c->plan->gpos_lookups;
5268
0
    hb_sorted_vector_t<hb_codepoint_t> new_coverage;
5269
0
    + hb_zip (this+coverage, ruleSet)
5270
0
    | hb_filter (glyphset, hb_first)
5271
0
    | hb_filter (subset_offset_array (c, out->ruleSet, this, lookup_map), hb_second)
5272
0
    | hb_map (hb_first)
5273
0
    | hb_map (glyph_map)
5274
0
    | hb_sink (new_coverage)
5275
0
    ;
5276
5277
0
    out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
5278
0
    return_trace (bool (new_coverage));
5279
0
  }
5280
5281
  bool sanitize (hb_sanitize_context_t *c) const
5282
0
  {
5283
0
    TRACE_SANITIZE (this);
5284
0
    return_trace (coverage.sanitize (c, this) && ruleSet.sanitize (c, this));
5285
0
  }
5286
5287
  protected:
5288
  HBUINT16  format;     /* Format identifier--format = 1 */
5289
  typename Types::template OffsetTo<Coverage>
5290
    coverage;   /* Offset to Coverage table--from
5291
           * beginning of table */
5292
  Array16Of<typename Types::template OffsetTo<ChainRuleSet>>
5293
    ruleSet;    /* Array of ChainRuleSet tables
5294
           * ordered by Coverage Index */
5295
  public:
5296
  DEFINE_SIZE_ARRAY (2 + 2 * Types::size, ruleSet);
5297
};
5298
5299
template <typename Types>
5300
struct ChainContextFormat2_5
5301
{
5302
  using ChainRuleSet = OT::ChainRuleSet<SmallTypes>;
5303
5304
  bool intersects (const hb_set_t *glyphs) const
5305
0
  {
5306
0
    if (!(this+coverage).intersects (glyphs))
5307
0
      return false;
5308
5309
0
    const ClassDef &backtrack_class_def = this+backtrackClassDef;
5310
0
    const ClassDef &input_class_def = this+inputClassDef;
5311
0
    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
5312
5313
0
    hb_map_t caches[3] = {};
5314
0
    struct ChainContextClosureLookupContext lookup_context = {
5315
0
      {intersects_class, nullptr},
5316
0
      ContextFormat::ClassBasedContext,
5317
0
      {&backtrack_class_def,
5318
0
       &input_class_def,
5319
0
       &lookahead_class_def},
5320
0
      {&caches[0], &caches[1], &caches[2]}
5321
0
    };
5322
5323
0
    hb_set_t retained_coverage_glyphs;
5324
0
    (this+coverage).intersect_set (*glyphs, retained_coverage_glyphs);
5325
5326
0
    hb_set_t coverage_glyph_classes;
5327
0
    input_class_def.intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
5328
5329
0
    return
5330
0
    + hb_iter (ruleSet)
5331
0
    | hb_map (hb_add (this))
5332
0
    | hb_enumerate
5333
0
    | hb_map ([&] (const hb_pair_t<unsigned, const ChainRuleSet &> p)
5334
0
        { return input_class_def.intersects_class (glyphs, p.first) &&
5335
0
           coverage_glyph_classes.has (p.first) &&
5336
0
           p.second.intersects (glyphs, lookup_context); })
5337
0
    | hb_any
5338
0
    ;
5339
0
  }
5340
5341
  bool may_have_non_1to1 () const
5342
0
  { return true; }
5343
5344
  void depend (hb_depend_context_t *c) const
5345
0
  {
5346
0
    if (!(this+coverage).intersects (c->glyphs))
5347
0
      return;
5348
0
5349
0
    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
5350
0
    if (unlikely (!cur_active_glyphs)) return;
5351
0
    get_coverage ().intersect_set (*c->glyphs, *cur_active_glyphs);
5352
0
5353
0
    const ClassDef &backtrack_class_def = this+backtrackClassDef;
5354
0
    const ClassDef &input_class_def = this+inputClassDef;
5355
0
    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
5356
0
5357
0
    hb_map_t caches[3] = {};
5358
0
    intersected_class_cache_t intersected_cache;
5359
0
    ChainContextDependLookupContext lookup_context = {
5360
0
      {intersects_class, intersected_class_glyphs},
5361
0
      ContextFormat::ClassBasedContext,
5362
0
      {&backtrack_class_def,
5363
0
       &input_class_def,
5364
0
       &lookahead_class_def},
5365
0
      {&caches[0], &caches[1], &caches[2]},
5366
0
      &intersected_cache
5367
0
    };
5368
0
5369
0
    + hb_enumerate (ruleSet)
5370
0
    | hb_filter ([&] (unsigned _)
5371
0
    { return input_class_def.intersects_class (&c->parent_active_glyphs (), _); },
5372
0
     hb_first)
5373
0
    | hb_apply ([&] (const hb_pair_t<unsigned, const typename Types::template OffsetTo<ChainRuleSet>&> _)
5374
0
                {
5375
0
                  const ChainRuleSet& chainrule_set = this+_.second;
5376
0
                  chainrule_set.depend (c, _.first, lookup_context);
5377
0
                })
5378
0
    ;
5379
0
5380
0
    c->pop_cur_done_glyphs ();
5381
0
  }
5382
5383
  void closure (hb_closure_context_t *c) const
5384
0
  {
5385
0
    if (!(this+coverage).intersects (c->glyphs))
5386
0
      return;
5387
5388
0
    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
5389
0
    if (unlikely (!cur_active_glyphs)) return;
5390
0
    get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
5391
0
           *cur_active_glyphs);
5392
5393
0
    const ClassDef &backtrack_class_def = this+backtrackClassDef;
5394
0
    const ClassDef &input_class_def = this+inputClassDef;
5395
0
    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
5396
5397
0
    hb_map_t caches[3] = {};
5398
0
    intersected_class_cache_t intersected_cache;
5399
0
    struct ChainContextClosureLookupContext lookup_context = {
5400
0
      {intersects_class, intersected_class_glyphs},
5401
0
      ContextFormat::ClassBasedContext,
5402
0
      {&backtrack_class_def,
5403
0
       &input_class_def,
5404
0
       &lookahead_class_def},
5405
0
      {&caches[0], &caches[1], &caches[2]},
5406
0
      &intersected_cache
5407
0
    };
5408
5409
0
    + hb_enumerate (ruleSet)
5410
0
    | hb_filter ([&] (unsigned _)
5411
0
    { return input_class_def.intersects_class (&c->parent_active_glyphs (), _); },
5412
0
     hb_first)
5413
0
    | hb_apply ([&] (const hb_pair_t<unsigned, const typename Types::template OffsetTo<ChainRuleSet>&> _)
5414
0
                {
5415
0
                  const ChainRuleSet& chainrule_set = this+_.second;
5416
0
                  chainrule_set.closure (c, _.first, lookup_context);
5417
0
                })
5418
0
    ;
5419
5420
0
    c->pop_cur_done_glyphs ();
5421
0
  }
5422
5423
  void closure_lookups (hb_closure_lookups_context_t *c) const
5424
0
  {
5425
0
    if (!(this+coverage).intersects (c->glyphs))
5426
0
      return;
5427
5428
0
    const ClassDef &backtrack_class_def = this+backtrackClassDef;
5429
0
    const ClassDef &input_class_def = this+inputClassDef;
5430
0
    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
5431
5432
0
    hb_map_t caches[3] = {};
5433
0
    struct ChainContextClosureLookupContext lookup_context = {
5434
0
      {intersects_class, nullptr},
5435
0
      ContextFormat::ClassBasedContext,
5436
0
      {&backtrack_class_def,
5437
0
       &input_class_def,
5438
0
       &lookahead_class_def},
5439
0
      {&caches[0], &caches[1], &caches[2]}
5440
0
    };
5441
5442
0
    + hb_iter (ruleSet)
5443
0
    | hb_map (hb_add (this))
5444
0
    | hb_enumerate
5445
0
    | hb_filter([&] (unsigned klass)
5446
0
    { return input_class_def.intersects_class (c->glyphs, klass); }, hb_first)
5447
0
    | hb_map (hb_second)
5448
0
    | hb_apply ([&] (const ChainRuleSet &_)
5449
0
    { _.closure_lookups (c, lookup_context); })
5450
0
    ;
5451
0
  }
5452
5453
0
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
5454
5455
  void collect_glyphs (hb_collect_glyphs_context_t *c) const
5456
0
  {
5457
0
    (this+coverage).collect_coverage (c->input);
5458
5459
0
    const ClassDef &backtrack_class_def = this+backtrackClassDef;
5460
0
    const ClassDef &input_class_def = this+inputClassDef;
5461
0
    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
5462
5463
0
    struct ChainContextCollectGlyphsLookupContext lookup_context = {
5464
0
      {collect_class},
5465
0
      {&backtrack_class_def,
5466
0
       &input_class_def,
5467
0
       &lookahead_class_def}
5468
0
    };
5469
5470
0
    + hb_iter (ruleSet)
5471
0
    | hb_map (hb_add (this))
5472
0
    | hb_apply ([&] (const ChainRuleSet &_) { _.collect_glyphs (c, lookup_context); })
5473
0
    ;
5474
0
  }
5475
5476
  void collect_second_glyphs (hb_set_digest_t *digest) const
5477
0
  {
5478
0
    const ClassDef &input_class_def = this+inputClassDef;
5479
0
    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
5480
0
    + hb_iter (ruleSet)
5481
0
    | hb_map (hb_add (this))
5482
0
    | hb_apply ([digest, &input_class_def, &lookahead_class_def] (const ChainRuleSet &_)
5483
0
    { _.collect_second_glyphs (digest, &input_class_def, &lookahead_class_def); })
5484
0
    ;
5485
0
  }
5486
5487
  bool would_apply (hb_would_apply_context_t *c) const
5488
0
  {
5489
0
    const ClassDef &backtrack_class_def = this+backtrackClassDef;
5490
0
    const ClassDef &input_class_def = this+inputClassDef;
5491
0
    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
5492
5493
0
    unsigned int index = input_class_def.get_class (c->glyphs[0]);
5494
0
    const ChainRuleSet &rule_set = this+ruleSet[index];
5495
0
    struct ChainContextApplyLookupContext lookup_context = {
5496
0
      {{match_class, match_class, match_class}},
5497
0
      {&backtrack_class_def,
5498
0
       &input_class_def,
5499
0
       &lookahead_class_def}
5500
0
    };
5501
0
    return rule_set.would_apply (c, lookup_context);
5502
0
  }
5503
5504
0
  const Coverage &get_coverage () const { return this+coverage; }
5505
5506
  unsigned cache_cost () const
5507
0
  {
5508
0
    return (this+inputClassDef).cost () + (this+lookaheadClassDef).cost ();
5509
0
  }
5510
  static bool cache_func (hb_ot_apply_context_t *c, hb_ot_subtable_cache_op_t op)
5511
0
  {
5512
0
    return context_cache_func (c, op);
5513
0
  }
5514
5515
  struct external_cache_t
5516
  {
5517
    hb_ot_layout_binary_cache_t coverage;
5518
    hb_ot_layout_mapping_cache_t input_class;
5519
    hb_ot_layout_mapping_cache_t lookahead_class;
5520
    hb_ot_layout_ruleset_digest_t rule_sets[HB_VAR_ARRAY];
5521
  };
5522
  void *external_cache_create () const
5523
0
  {
5524
0
    unsigned count = ruleSet.len;
5525
0
    unsigned size = sizeof (external_cache_t) -
5526
0
        HB_VAR_ARRAY * sizeof (hb_ot_layout_ruleset_digest_t) +
5527
0
        count * sizeof (hb_ot_layout_ruleset_digest_t);
5528
0
    external_cache_t *cache = (external_cache_t *) hb_malloc (size);
5529
0
    if (likely (cache))
5530
0
    {
5531
0
      cache->coverage.clear ();
5532
0
      cache->input_class.clear ();
5533
0
      cache->lookahead_class.clear ();
5534
0
      for (unsigned i = 0; i < count; i++)
5535
0
  (this+ruleSet[i]).collect_first_input_classes (&cache->rule_sets[i]);
5536
0
    }
5537
0
    return cache;
5538
0
  }
5539
0
  bool apply_cached (hb_ot_apply_context_t *c, void *external_cache) const { return _apply (c, true, external_cache); }
5540
0
  bool apply (hb_ot_apply_context_t *c, void *external_cache) const { return _apply (c, false, external_cache); }
5541
  bool _apply (hb_ot_apply_context_t *c, bool cached, void *external_cache) const
5542
0
  {
5543
0
    TRACE_APPLY (this);
5544
0
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
5545
0
    external_cache_t *cache = (external_cache_t *) external_cache;
5546
0
    unsigned int index = (this+coverage).get_coverage_binary (c->buffer->cur().codepoint, cache ? &cache->coverage : nullptr);
5547
#else
5548
    unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
5549
#endif
5550
0
    if (index == NOT_COVERED) return_trace (false);
5551
5552
0
    const ClassDef &backtrack_class_def = this+backtrackClassDef;
5553
0
    const ClassDef &input_class_def = this+inputClassDef;
5554
0
    const ClassDef &lookahead_class_def = this+lookaheadClassDef;
5555
5556
0
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
5557
0
    match_class_cache_data_t input_cache_data = {
5558
0
      &input_class_def,
5559
0
      cache ? &cache->input_class : nullptr
5560
0
    };
5561
0
    match_class_cache_data_t lookahead_cache_data = {
5562
0
      &lookahead_class_def,
5563
0
      cache ? &cache->lookahead_class : nullptr
5564
0
    };
5565
0
    const void *input_match_data = cached
5566
0
      ? static_cast<const void *> (&input_class_def)
5567
0
      : static_cast<const void *> (&input_cache_data);
5568
0
    const void *lookahead_match_data = cached
5569
0
      ? static_cast<const void *> (&lookahead_class_def)
5570
0
      : static_cast<const void *> (&lookahead_cache_data);
5571
0
    bool backtrack_uses_lookahead_cache =
5572
0
      !cached && &backtrack_class_def == &lookahead_class_def;
5573
0
    const void *backtrack_match_data = backtrack_uses_lookahead_cache
5574
0
      ? static_cast<const void *> (&lookahead_cache_data)
5575
0
      : static_cast<const void *> (&backtrack_class_def);
5576
0
#endif
5577
5578
    /* match_class_caches1 is slightly faster. Use it for lookahead,
5579
     * which is typically longer. */
5580
0
    struct ChainContextApplyLookupContext lookup_context = {
5581
0
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
5582
0
      {{cached && &backtrack_class_def == &lookahead_class_def ? match_class_cached1 :
5583
0
        backtrack_uses_lookahead_cache ? match_class_cache : match_class,
5584
0
        cached ? match_class_cached2 : match_class_cache,
5585
0
        cached ? match_class_cached1 : match_class_cache}},
5586
0
      {backtrack_match_data,
5587
0
       input_match_data,
5588
0
       lookahead_match_data},
5589
0
      cached ? get_class_cached2_value : get_class_cache_value
5590
#else
5591
      {{cached && &backtrack_class_def == &lookahead_class_def ? match_class_cached1 : match_class,
5592
        cached ? match_class_cached2 : match_class,
5593
        cached ? match_class_cached1 : match_class}},
5594
      {&backtrack_class_def,
5595
       &input_class_def,
5596
       &lookahead_class_def},
5597
      cached ? get_class_cached2_value : get_class_value
5598
#endif
5599
0
    };
5600
5601
0
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
5602
0
    index = cached
5603
0
         ? get_class_cached2 (input_class_def, c->buffer->cur())
5604
0
         : input_class_def.get_class (c->buffer->cur().codepoint, input_cache_data.cache);
5605
#else
5606
    index = cached
5607
         ? get_class_cached2 (input_class_def, c->buffer->cur())
5608
          : input_class_def.get_class (c->buffer->cur().codepoint);
5609
#endif
5610
0
    const ChainRuleSet &rule_set = this+ruleSet[index];
5611
0
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
5612
0
    const hb_ot_layout_ruleset_digest_t *digest = cache && index < ruleSet.len ? &cache->rule_sets[index] : nullptr;
5613
#else
5614
    const hb_ot_layout_ruleset_digest_t *digest = nullptr;
5615
#endif
5616
0
    return_trace (rule_set.apply (c, lookup_context, digest));
5617
0
  }
5618
5619
  bool subset (hb_subset_context_t *c) const
5620
0
  {
5621
0
    TRACE_SUBSET (this);
5622
0
    auto *out = c->serializer->start_embed (*this);
5623
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
5624
0
    out->format = format;
5625
0
    out->coverage.serialize_subset (c, coverage, this);
5626
5627
0
    hb_map_t backtrack_klass_map;
5628
0
    hb_map_t input_klass_map;
5629
0
    hb_map_t lookahead_klass_map;
5630
5631
0
    out->backtrackClassDef.serialize_subset (c, backtrackClassDef, this, &backtrack_klass_map);
5632
    // TODO: subset inputClassDef based on glyphs survived in Coverage subsetting
5633
0
    out->inputClassDef.serialize_subset (c, inputClassDef, this, &input_klass_map);
5634
0
    out->lookaheadClassDef.serialize_subset (c, lookaheadClassDef, this, &lookahead_klass_map);
5635
5636
0
    if (unlikely (!c->serializer->propagate_error (backtrack_klass_map,
5637
0
               input_klass_map,
5638
0
               lookahead_klass_map)))
5639
0
      return_trace (false);
5640
5641
0
    const hb_set_t* glyphset = c->plan->glyphset_gsub ();
5642
0
    hb_set_t retained_coverage_glyphs;
5643
0
    (this+coverage).intersect_set (*glyphset, retained_coverage_glyphs);
5644
5645
0
    hb_set_t coverage_glyph_classes;
5646
0
    (this+inputClassDef).intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
5647
5648
0
    int non_zero_index = -1, index = 0;
5649
0
    bool ret = true;
5650
0
    const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? &c->plan->gsub_lookups : &c->plan->gpos_lookups;
5651
0
    auto last_non_zero = c->serializer->snapshot ();
5652
0
    for (const auto& _ : + hb_enumerate (ruleSet)
5653
0
       | hb_filter (input_klass_map, hb_first))
5654
0
    {
5655
0
      auto *o = out->ruleSet.serialize_append (c->serializer);
5656
0
      if (unlikely (!o))
5657
0
      {
5658
0
  ret = false;
5659
0
  break;
5660
0
      }
5661
0
      if (coverage_glyph_classes.has (_.first) &&
5662
0
          o->serialize_subset (c, _.second, this,
5663
0
             lookup_map,
5664
0
             &backtrack_klass_map,
5665
0
             &input_klass_map,
5666
0
             &lookahead_klass_map))
5667
0
      {
5668
0
        last_non_zero = c->serializer->snapshot ();
5669
0
  non_zero_index = index;
5670
0
      }
5671
5672
0
      index++;
5673
0
    }
5674
5675
0
    if (!ret || non_zero_index == -1) return_trace (false);
5676
5677
    // prune empty trailing ruleSets
5678
0
    if (index > non_zero_index) {
5679
0
      c->serializer->revert (last_non_zero);
5680
0
      out->ruleSet.len = non_zero_index + 1;
5681
0
    }
5682
5683
0
    return_trace (bool (out->ruleSet));
5684
0
  }
5685
5686
  bool sanitize (hb_sanitize_context_t *c) const
5687
0
  {
5688
0
    TRACE_SANITIZE (this);
5689
0
    return_trace (coverage.sanitize (c, this) &&
5690
0
      backtrackClassDef.sanitize (c, this) &&
5691
0
      inputClassDef.sanitize (c, this) &&
5692
0
      lookaheadClassDef.sanitize (c, this) &&
5693
0
      ruleSet.sanitize (c, this));
5694
0
  }
5695
5696
  protected:
5697
  HBUINT16  format;     /* Format identifier--format = 2 */
5698
  typename Types::template OffsetTo<Coverage>
5699
    coverage;   /* Offset to Coverage table--from
5700
           * beginning of table */
5701
  typename Types::template OffsetTo<ClassDef>
5702
    backtrackClassDef;  /* Offset to glyph ClassDef table
5703
           * containing backtrack sequence
5704
           * data--from beginning of table */
5705
  typename Types::template OffsetTo<ClassDef>
5706
    inputClassDef;    /* Offset to glyph ClassDef
5707
           * table containing input sequence
5708
           * data--from beginning of table */
5709
  typename Types::template OffsetTo<ClassDef>
5710
    lookaheadClassDef;  /* Offset to glyph ClassDef table
5711
           * containing lookahead sequence
5712
           * data--from beginning of table */
5713
  Array16Of<typename Types::template OffsetTo<ChainRuleSet>>
5714
    ruleSet;    /* Array of ChainRuleSet tables
5715
           * ordered by class */
5716
  public:
5717
  DEFINE_SIZE_ARRAY (4 + 4 * Types::size, ruleSet);
5718
};
5719
5720
struct ChainContextFormat3
5721
{
5722
  using RuleSet = OT::RuleSet<SmallTypes>;
5723
5724
  bool intersects (const hb_set_t *glyphs) const
5725
0
  {
5726
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
5727
5728
0
    if (!(this+input[0]).intersects (glyphs))
5729
0
      return false;
5730
5731
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
5732
0
    struct ChainContextClosureLookupContext lookup_context = {
5733
0
      {intersects_coverage, nullptr},
5734
0
      ContextFormat::CoverageBasedContext,
5735
0
      {this, this, this}
5736
0
    };
5737
0
    return chain_context_intersects (glyphs,
5738
0
             backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
5739
0
             input.len, (const HBUINT16 *) input.arrayZ + 1,
5740
0
             lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
5741
0
             lookup_context);
5742
0
  }
5743
5744
  bool may_have_non_1to1 () const
5745
0
  { return true; }
5746
5747
  void depend (hb_depend_context_t *c) const
5748
0
  {
5749
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
5750
0
5751
0
    if (!(this+input[0]).intersects (c->glyphs))
5752
0
      return;
5753
0
5754
0
    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
5755
0
    if (unlikely (!cur_active_glyphs))
5756
0
      return;
5757
0
    get_coverage ().intersect_set (*c->glyphs, *cur_active_glyphs);
5758
0
5759
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
5760
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
5761
0
    ChainContextDependLookupContext lookup_context = {
5762
0
      {intersects_coverage, intersected_coverage_glyphs},
5763
0
      ContextFormat::CoverageBasedContext,
5764
0
      {this, this, this},
5765
0
      {nullptr, nullptr, nullptr},  /* intersects_cache */
5766
0
      nullptr                        /* intersected_glyphs_cache */
5767
0
    };
5768
0
    chain_context_depend_lookup (c,
5769
0
         backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
5770
0
         input.len, (const HBUINT16 *) input.arrayZ + 1,
5771
0
         lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
5772
0
         lookup.len, lookup.arrayZ,
5773
0
         this,
5774
0
         input[0], lookup_context);
5775
0
5776
0
    c->pop_cur_done_glyphs ();
5777
0
  }
5778
5779
  void closure (hb_closure_context_t *c) const
5780
0
  {
5781
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
5782
5783
0
    if (!(this+input[0]).intersects (c->glyphs))
5784
0
      return;
5785
5786
0
    hb_set_t* cur_active_glyphs = c->push_cur_active_glyphs ();
5787
0
    if (unlikely (!cur_active_glyphs))
5788
0
      return;
5789
0
    get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
5790
0
           *cur_active_glyphs);
5791
5792
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
5793
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
5794
0
    struct ChainContextClosureLookupContext lookup_context = {
5795
0
      {intersects_coverage, intersected_coverage_glyphs},
5796
0
      ContextFormat::CoverageBasedContext,
5797
0
      {this, this, this}
5798
0
    };
5799
0
    chain_context_closure_lookup (c,
5800
0
          backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
5801
0
          input.len, (const HBUINT16 *) input.arrayZ + 1,
5802
0
          lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
5803
0
          lookup.len, lookup.arrayZ,
5804
0
          0, lookup_context);
5805
5806
0
    c->pop_cur_done_glyphs ();
5807
0
  }
5808
5809
  void closure_lookups (hb_closure_lookups_context_t *c) const
5810
0
  {
5811
0
    if (!intersects (c->glyphs))
5812
0
      return;
5813
5814
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
5815
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
5816
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
5817
0
    recurse_lookups (c, lookup.len, lookup.arrayZ);
5818
0
  }
5819
5820
0
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const {}
5821
5822
  void collect_glyphs (hb_collect_glyphs_context_t *c) const
5823
0
  {
5824
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
5825
5826
0
    (this+input[0]).collect_coverage (c->input);
5827
5828
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
5829
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
5830
5831
0
    struct ChainContextCollectGlyphsLookupContext lookup_context = {
5832
0
      {collect_coverage},
5833
0
      {this, this, this}
5834
0
    };
5835
0
    chain_context_collect_glyphs_lookup (c,
5836
0
           backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
5837
0
           input.len, (const HBUINT16 *) input.arrayZ + 1,
5838
0
           lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
5839
0
           lookup.len, lookup.arrayZ,
5840
0
           lookup_context);
5841
0
  }
5842
5843
  void collect_second_glyphs (hb_set_digest_t *digest) const
5844
615
  {
5845
615
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
5846
615
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
5847
615
    if (input.len > 1)
5848
45
      (this+input[1]).collect_coverage (digest);
5849
570
    else if (lookahead.len)
5850
120
      (this+lookahead[0]).collect_coverage (digest);
5851
450
    else
5852
450
      *digest = hb_set_digest_t::full ();
5853
615
  }
5854
5855
  bool would_apply (hb_would_apply_context_t *c) const
5856
0
  {
5857
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
5858
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
5859
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
5860
0
    struct ChainContextApplyLookupContext lookup_context = {
5861
0
      {{match_coverage, match_coverage, match_coverage}},
5862
0
      {this, this, this}
5863
0
    };
5864
0
    return chain_context_would_apply_lookup (c,
5865
0
               backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
5866
0
               input.len, (const HBUINT16 *) input.arrayZ + 1,
5867
0
               lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
5868
0
               lookup.len, lookup.arrayZ, lookup_context);
5869
0
  }
5870
5871
  const Coverage &get_coverage () const
5872
615
  {
5873
615
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
5874
615
    return this+input[0];
5875
615
  }
5876
5877
  bool apply (hb_ot_apply_context_t *c) const
5878
474k
  {
5879
474k
    TRACE_APPLY (this);
5880
474k
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
5881
5882
474k
    unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
5883
474k
    if (index == NOT_COVERED) return_trace (false);
5884
5885
246k
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
5886
246k
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
5887
246k
    struct ChainContextApplyLookupContext lookup_context = {
5888
246k
      {{match_coverage, match_coverage, match_coverage}},
5889
246k
      {this, this, this}
5890
246k
    };
5891
246k
    return_trace (chain_context_apply_lookup (c,
5892
474k
                backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
5893
474k
                input.len, (const HBUINT16 *) input.arrayZ + 1,
5894
474k
                lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
5895
474k
                lookup.len, lookup.arrayZ, lookup_context));
5896
474k
  }
5897
5898
  template<typename Iterator,
5899
     hb_requires (hb_is_iterator (Iterator))>
5900
  bool serialize_coverage_offsets (hb_subset_context_t *c, Iterator it, const void* base) const
5901
0
  {
5902
0
    TRACE_SERIALIZE (this);
5903
0
    auto *out = c->serializer->start_embed<Array16OfOffset16To<Coverage>> ();
5904
5905
0
    if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size)))
5906
0
      return_trace (false);
5907
5908
0
    for (auto& offset : it) {
5909
0
      auto *o = out->serialize_append (c->serializer);
5910
0
      if (unlikely (!o) || !o->serialize_subset (c, offset, base))
5911
0
        return_trace (false);
5912
0
    }
5913
5914
0
    return_trace (true);
5915
0
  }
5916
5917
  bool subset (hb_subset_context_t *c) const
5918
0
  {
5919
0
    TRACE_SUBSET (this);
5920
5921
0
    if (unlikely (!c->serializer->embed (this->format))) return_trace (false);
5922
5923
0
    if (!serialize_coverage_offsets (c, backtrack.iter (), this))
5924
0
      return_trace (false);
5925
5926
0
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
5927
0
    if (!serialize_coverage_offsets (c, input.iter (), this))
5928
0
      return_trace (false);
5929
5930
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
5931
0
    if (!serialize_coverage_offsets (c, lookahead.iter (), this))
5932
0
      return_trace (false);
5933
5934
0
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
5935
0
    const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? &c->plan->gsub_lookups : &c->plan->gpos_lookups;
5936
5937
0
    HBUINT16 *lookupCount = c->serializer->copy<HBUINT16> (lookup.len);
5938
0
    if (!lookupCount) return_trace (false);
5939
5940
0
    unsigned count = serialize_lookuprecord_array (c->serializer, lookup.as_array (), lookup_map);
5941
0
    return_trace (c->serializer->check_assign (*lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
5942
0
  }
5943
5944
  bool sanitize (hb_sanitize_context_t *c) const
5945
1.96k
  {
5946
1.96k
    TRACE_SANITIZE (this);
5947
1.96k
    if (unlikely (!backtrack.sanitize (c, this))) return_trace (false);
5948
1.96k
    hb_barrier ();
5949
1.96k
    const auto &input = StructAfter<decltype (inputX)> (backtrack);
5950
1.96k
    if (unlikely (!input.sanitize (c, this))) return_trace (false);
5951
1.96k
    hb_barrier ();
5952
1.96k
    if (unlikely (!input.len)) return_trace (false); /* To be consistent with Context. */
5953
1.96k
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
5954
1.96k
    if (unlikely (!lookahead.sanitize (c, this))) return_trace (false);
5955
1.96k
    hb_barrier ();
5956
1.96k
    const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
5957
1.96k
    return_trace (likely (lookup.sanitize (c)));
5958
1.96k
  }
5959
5960
  protected:
5961
  HBUINT16  format;     /* Format identifier--format = 3 */
5962
  Array16OfOffset16To<Coverage>
5963
    backtrack;    /* Array of coverage tables
5964
           * in backtracking sequence, in  glyph
5965
           * sequence order */
5966
  Array16OfOffset16To<Coverage>
5967
    inputX    ; /* Array of coverage
5968
           * tables in input sequence, in glyph
5969
           * sequence order */
5970
  Array16OfOffset16To<Coverage>
5971
    lookaheadX;   /* Array of coverage tables
5972
           * in lookahead sequence, in glyph
5973
           * sequence order */
5974
  Array16Of<LookupRecord>
5975
    lookupX;    /* Array of LookupRecords--in
5976
           * design order) */
5977
  public:
5978
  DEFINE_SIZE_MIN (10);
5979
};
5980
5981
struct ChainContext
5982
{
5983
  template <typename context_t, typename ...Ts>
5984
  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
5985
2.58k
  {
5986
2.58k
    if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
5987
2.58k
    TRACE_DISPATCH (this, u.format.v);
5988
2.58k
    switch (u.format.v) {
5989
0
    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
5990
0
    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
5991
2.58k
    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
5992
#ifndef HB_NO_BEYOND_64K
5993
    case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
5994
    case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
5995
#endif
5996
0
    default:return_trace (c->default_return_value ());
5997
2.58k
    }
5998
2.58k
  }
hb_sanitize_context_t::return_t OT::ChainContext::dispatch<hb_sanitize_context_t>(hb_sanitize_context_t*) const
Line
Count
Source
5985
1.96k
  {
5986
1.96k
    if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
5987
1.96k
    TRACE_DISPATCH (this, u.format.v);
5988
1.96k
    switch (u.format.v) {
5989
0
    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
5990
0
    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
5991
1.96k
    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
5992
#ifndef HB_NO_BEYOND_64K
5993
    case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
5994
    case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
5995
#endif
5996
0
    default:return_trace (c->default_return_value ());
5997
1.96k
    }
5998
1.96k
  }
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
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
5985
615
  {
5986
615
    if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
5987
615
    TRACE_DISPATCH (this, u.format.v);
5988
615
    switch (u.format.v) {
5989
0
    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
5990
0
    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
5991
615
    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
5992
#ifndef HB_NO_BEYOND_64K
5993
    case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
5994
    case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
5995
#endif
5996
0
    default:return_trace (c->default_return_value ());
5997
615
    }
5998
615
  }
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_depend_context_t::return_t OT::ChainContext::dispatch<OT::hb_depend_context_t>(OT::hb_depend_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_collect_glyph_alternates_dispatch_t::return_t OT::ChainContext::dispatch<hb_collect_glyph_alternates_dispatch_t, hb_map_t*&, hb_map_t*&>(hb_collect_glyph_alternates_dispatch_t*, hb_map_t*&, hb_map_t*&) 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
5999
6000
  protected:
6001
  union {
6002
  struct { HBUINT16 v; }    format; /* Format identifier */
6003
  ChainContextFormat1_4<SmallTypes> format1;
6004
  ChainContextFormat2_5<SmallTypes> format2;
6005
  ChainContextFormat3     format3;
6006
#ifndef HB_NO_BEYOND_64K
6007
  ChainContextFormat1_4<MediumTypes>  format4;
6008
  ChainContextFormat2_5<MediumTypes>  format5;
6009
#endif
6010
  } u;
6011
};
6012
6013
6014
template <typename T>
6015
struct ExtensionFormat1
6016
{
6017
0
  unsigned int get_type () const { return extensionLookupType; }
Unexecuted instantiation: OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::get_type() const
Unexecuted instantiation: OT::ExtensionFormat1<OT::Layout::GPOS_impl::ExtensionPos>::get_type() const
6018
6019
  template <typename X>
6020
  const X& get_subtable () const
6021
0
  { return this + reinterpret_cast<const Offset32To<typename T::SubTable> &> (extensionOffset); }
Unexecuted instantiation: OT::Layout::GSUB_impl::SubstLookupSubTable const& OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::get_subtable<OT::Layout::GSUB_impl::SubstLookupSubTable>() const
Unexecuted instantiation: OT::Layout::GPOS_impl::PosLookupSubTable const& OT::ExtensionFormat1<OT::Layout::GPOS_impl::ExtensionPos>::get_subtable<OT::Layout::GPOS_impl::PosLookupSubTable>() const
6022
6023
  template <typename context_t, typename ...Ts>
6024
  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
6025
0
  {
6026
0
    if (unlikely (!c->may_dispatch (this, this))) return c->no_dispatch_return_value ();
6027
0
    TRACE_DISPATCH (this, format);
6028
0
    return_trace (get_subtable<typename T::SubTable> ().dispatch (c, get_type (), std::forward<Ts> (ds)...));
6029
0
  }
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_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: 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_depend_context_t::return_t OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<OT::hb_depend_context_t>(OT::hb_depend_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_collect_glyph_alternates_dispatch_t::return_t OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<hb_collect_glyph_alternates_dispatch_t, hb_map_t*&, hb_map_t*&>(hb_collect_glyph_alternates_dispatch_t*, hb_map_t*&, hb_map_t*&) 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
6030
6031
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
6032
  { dispatch (c); }
6033
6034
  /* This is called from may_dispatch() above with hb_sanitize_context_t. */
6035
  bool sanitize (hb_sanitize_context_t *c) const
6036
0
  {
6037
0
    TRACE_SANITIZE (this);
6038
0
    return_trace (c->check_struct (this) &&
6039
0
      hb_barrier () &&
6040
0
      extensionLookupType != T::SubTable::Extension);
6041
0
  }
Unexecuted instantiation: OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::sanitize(hb_sanitize_context_t*) const
Unexecuted instantiation: OT::ExtensionFormat1<OT::Layout::GPOS_impl::ExtensionPos>::sanitize(hb_sanitize_context_t*) const
6042
6043
  bool subset (hb_subset_context_t *c) const
6044
0
  {
6045
0
    TRACE_SUBSET (this);
6046
6047
0
    auto *out = c->serializer->start_embed (this);
6048
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
6049
6050
0
    out->format = format;
6051
0
    out->extensionLookupType = extensionLookupType;
6052
6053
0
    const auto& src_offset =
6054
0
        reinterpret_cast<const Offset32To<typename T::SubTable> &> (extensionOffset);
6055
0
    auto& dest_offset =
6056
0
        reinterpret_cast<Offset32To<typename T::SubTable> &> (out->extensionOffset);
6057
6058
0
    return_trace (dest_offset.serialize_subset (c, src_offset, this, get_type ()));
6059
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
6060
6061
  protected:
6062
  HBUINT16  format;     /* Format identifier. Set to 1. */
6063
  HBUINT16  extensionLookupType;  /* Lookup type of subtable referenced
6064
           * by ExtensionOffset (i.e. the
6065
           * extension subtable). */
6066
  Offset32  extensionOffset;  /* Offset to the extension subtable,
6067
           * of lookup type subtable. */
6068
  public:
6069
  DEFINE_SIZE_STATIC (8);
6070
};
6071
6072
template <typename T>
6073
struct Extension
6074
{
6075
  unsigned int get_type () const
6076
0
  {
6077
0
    switch (u.format.v) {
6078
0
    case 1: hb_barrier (); return u.format1.get_type ();
6079
0
    default:return 0;
6080
0
    }
6081
0
  }
Unexecuted instantiation: OT::Extension<OT::Layout::GSUB_impl::ExtensionSubst>::get_type() const
Unexecuted instantiation: OT::Extension<OT::Layout::GPOS_impl::ExtensionPos>::get_type() const
6082
  template <typename X>
6083
  const X& get_subtable () const
6084
  {
6085
    switch (u.format.v) {
6086
    case 1: hb_barrier (); return u.format1.template get_subtable<typename T::SubTable> ();
6087
    default:return Null (typename T::SubTable);
6088
    }
6089
  }
6090
6091
  // Specialization of dispatch for subset. dispatch() normally just
6092
  // dispatches to the sub table this points too, but for subset
6093
  // we need to run subset on this subtable too.
6094
  template <typename ...Ts>
6095
  typename hb_subset_context_t::return_t dispatch (hb_subset_context_t *c, Ts&&... ds) const
6096
0
  {
6097
0
    switch (u.format.v) {
6098
0
    case 1: hb_barrier (); return u.format1.subset (c);
6099
0
    default: return c->default_return_value ();
6100
0
    }
6101
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
6102
6103
  template <typename context_t, typename ...Ts>
6104
  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
6105
0
  {
6106
0
    if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
6107
0
    TRACE_DISPATCH (this, u.format.v);
6108
0
    switch (u.format.v) {
6109
0
    case 1: hb_barrier (); return_trace (u.format1.dispatch (c, std::forward<Ts> (ds)...));
6110
0
    default:return_trace (c->default_return_value ());
6111
0
    }
6112
0
  }
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_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: 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_depend_context_t::return_t OT::Extension<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<OT::hb_depend_context_t>(OT::hb_depend_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_collect_glyph_alternates_dispatch_t::return_t OT::Extension<OT::Layout::GSUB_impl::ExtensionSubst>::dispatch<hb_collect_glyph_alternates_dispatch_t, hb_map_t*&, hb_map_t*&>(hb_collect_glyph_alternates_dispatch_t*, hb_map_t*&, hb_map_t*&) 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
6113
6114
  protected:
6115
  union {
6116
  struct { HBUINT16 v; }  format;   /* Format identifier */
6117
  ExtensionFormat1<T> format1;
6118
  } u;
6119
};
6120
6121
6122
/*
6123
 * GSUB/GPOS Common
6124
 */
6125
6126
struct hb_ot_layout_lookup_accelerator_t
6127
{
6128
  template <typename TLookup>
6129
  static hb_ot_layout_lookup_accelerator_t *create (const TLookup &lookup)
6130
719
  {
6131
719
    unsigned count = lookup.get_subtable_count ();
6132
6133
719
    unsigned size = sizeof (hb_ot_layout_lookup_accelerator_t) -
6134
719
        HB_VAR_ARRAY * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t) +
6135
719
        count * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t);
6136
6137
    /* The following is a calloc because when we are collecting subtables,
6138
     * some of them might be invalid and hence not collect; as a result,
6139
     * we might not fill in all the count entries of the subtables array.
6140
     * Zeroing it allows the set digest to gatekeep it without having to
6141
     * initialize it further. */
6142
719
    auto *thiz = (hb_ot_layout_lookup_accelerator_t *) hb_calloc (1, size);
6143
719
    if (unlikely (!thiz))
6144
0
      return nullptr;
6145
6146
719
    hb_accelerate_subtables_context_t c_accelerate_subtables (thiz->subtables);
6147
719
    lookup.dispatch (&c_accelerate_subtables);
6148
6149
    /* Invalid subtables do not collect and leave zeroed tail entries
6150
     * (see the calloc note above); trim them so the apply paths never
6151
     * see a null apply func. */
6152
719
    while (count && !thiz->subtables[count - 1].apply_func)
6153
0
      count--;
6154
6155
719
    thiz->digest.init ();
6156
719
    for (auto& subtable : hb_iter (thiz->subtables, count))
6157
1.19k
      thiz->digest.union_ (subtable.digest);
6158
719
    thiz->digest_second = c_accelerate_subtables.digest_second;
6159
6160
719
    thiz->count = count;
6161
6162
719
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
6163
719
    thiz->subtable_cache_user_idx = c_accelerate_subtables.subtable_cache_user_idx;
6164
6165
1.91k
    for (unsigned i = 0; i < count; i++)
6166
1.19k
      if (i != thiz->subtable_cache_user_idx)
6167
1.19k
       thiz->subtables[i].apply_cached_func = thiz->subtables[i].apply_func;
6168
719
#endif
6169
6170
719
    return thiz;
6171
719
  }
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
6130
650
  {
6131
650
    unsigned count = lookup.get_subtable_count ();
6132
6133
650
    unsigned size = sizeof (hb_ot_layout_lookup_accelerator_t) -
6134
650
        HB_VAR_ARRAY * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t) +
6135
650
        count * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t);
6136
6137
    /* The following is a calloc because when we are collecting subtables,
6138
     * some of them might be invalid and hence not collect; as a result,
6139
     * we might not fill in all the count entries of the subtables array.
6140
     * Zeroing it allows the set digest to gatekeep it without having to
6141
     * initialize it further. */
6142
650
    auto *thiz = (hb_ot_layout_lookup_accelerator_t *) hb_calloc (1, size);
6143
650
    if (unlikely (!thiz))
6144
0
      return nullptr;
6145
6146
650
    hb_accelerate_subtables_context_t c_accelerate_subtables (thiz->subtables);
6147
650
    lookup.dispatch (&c_accelerate_subtables);
6148
6149
    /* Invalid subtables do not collect and leave zeroed tail entries
6150
     * (see the calloc note above); trim them so the apply paths never
6151
     * see a null apply func. */
6152
650
    while (count && !thiz->subtables[count - 1].apply_func)
6153
0
      count--;
6154
6155
650
    thiz->digest.init ();
6156
650
    for (auto& subtable : hb_iter (thiz->subtables, count))
6157
1.13k
      thiz->digest.union_ (subtable.digest);
6158
650
    thiz->digest_second = c_accelerate_subtables.digest_second;
6159
6160
650
    thiz->count = count;
6161
6162
650
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
6163
650
    thiz->subtable_cache_user_idx = c_accelerate_subtables.subtable_cache_user_idx;
6164
6165
1.78k
    for (unsigned i = 0; i < count; i++)
6166
1.13k
      if (i != thiz->subtable_cache_user_idx)
6167
1.13k
       thiz->subtables[i].apply_cached_func = thiz->subtables[i].apply_func;
6168
650
#endif
6169
6170
650
    return thiz;
6171
650
  }
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
6130
69
  {
6131
69
    unsigned count = lookup.get_subtable_count ();
6132
6133
69
    unsigned size = sizeof (hb_ot_layout_lookup_accelerator_t) -
6134
69
        HB_VAR_ARRAY * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t) +
6135
69
        count * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t);
6136
6137
    /* The following is a calloc because when we are collecting subtables,
6138
     * some of them might be invalid and hence not collect; as a result,
6139
     * we might not fill in all the count entries of the subtables array.
6140
     * Zeroing it allows the set digest to gatekeep it without having to
6141
     * initialize it further. */
6142
69
    auto *thiz = (hb_ot_layout_lookup_accelerator_t *) hb_calloc (1, size);
6143
69
    if (unlikely (!thiz))
6144
0
      return nullptr;
6145
6146
69
    hb_accelerate_subtables_context_t c_accelerate_subtables (thiz->subtables);
6147
69
    lookup.dispatch (&c_accelerate_subtables);
6148
6149
    /* Invalid subtables do not collect and leave zeroed tail entries
6150
     * (see the calloc note above); trim them so the apply paths never
6151
     * see a null apply func. */
6152
69
    while (count && !thiz->subtables[count - 1].apply_func)
6153
0
      count--;
6154
6155
69
    thiz->digest.init ();
6156
69
    for (auto& subtable : hb_iter (thiz->subtables, count))
6157
69
      thiz->digest.union_ (subtable.digest);
6158
69
    thiz->digest_second = c_accelerate_subtables.digest_second;
6159
6160
69
    thiz->count = count;
6161
6162
69
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
6163
69
    thiz->subtable_cache_user_idx = c_accelerate_subtables.subtable_cache_user_idx;
6164
6165
138
    for (unsigned i = 0; i < count; i++)
6166
69
      if (i != thiz->subtable_cache_user_idx)
6167
69
       thiz->subtables[i].apply_cached_func = thiz->subtables[i].apply_func;
6168
69
#endif
6169
6170
69
    return thiz;
6171
69
  }
6172
6173
  void fini ()
6174
0
  {
6175
0
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
6176
0
    for (unsigned i = 0; i < count; i++)
6177
0
      hb_free (subtables[i].external_cache);
6178
0
#endif
6179
0
  }
6180
6181
  bool may_have (hb_codepoint_t g) const
6182
0
  { return digest.may_have (g); }
6183
6184
#ifndef HB_OPTIMIZE_SIZE
6185
  HB_ALWAYS_INLINE
6186
#endif
6187
  bool apply (hb_ot_apply_context_t *c, bool use_cache) const
6188
150M
  {
6189
150M
    if (count == 1)
6190
150M
    {
6191
      /* The accelerator digest is the union of the subtable digests, so
6192
       * for a single subtable it equals that subtable's digest, which the
6193
       * caller has already tested; skip the redundant retest. Zeroed
6194
       * invalid entries were trimmed at create time, so the subtable is
6195
       * always valid here. */
6196
150M
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
6197
150M
      if (use_cache)
6198
0
  return subtables[0].apply_cached_no_digest (c);
6199
150M
#endif
6200
150M
      return subtables[0].apply_no_digest (c);
6201
150M
    }
6202
111k
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
6203
111k
    if (use_cache)
6204
0
    {
6205
0
      return
6206
0
      + hb_iter (hb_iter (subtables, count))
6207
0
      | hb_map ([&c] (const hb_accelerate_subtables_context_t::hb_applicable_t &_) { return _.apply_cached (c); })
6208
0
      | hb_any
6209
0
      ;
6210
0
    }
6211
111k
    else
6212
111k
#endif
6213
111k
    {
6214
111k
      return
6215
111k
      + hb_iter (hb_iter (subtables, count))
6216
445k
      | hb_map ([&c] (const hb_accelerate_subtables_context_t::hb_applicable_t &_) { return _.apply (c); })
6217
111k
      | hb_any
6218
111k
      ;
6219
111k
    }
6220
0
    return false;
6221
111k
  }
6222
6223
  bool cache_enter (hb_ot_apply_context_t *c) const
6224
3.55M
  {
6225
3.55M
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
6226
3.55M
    return subtable_cache_user_idx != (unsigned) -1 &&
6227
0
     subtables[subtable_cache_user_idx].cache_enter (c);
6228
#else
6229
    return false;
6230
#endif
6231
3.55M
  }
6232
  void cache_leave (hb_ot_apply_context_t *c) const
6233
0
  {
6234
0
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
6235
0
    subtables[subtable_cache_user_idx].cache_leave (c);
6236
0
#endif
6237
0
  }
6238
6239
6240
  hb_set_digest_t digest;
6241
  hb_set_digest_t digest_second;
6242
  private:
6243
  unsigned count = 0; /* Number of subtables in the array. */
6244
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
6245
  unsigned subtable_cache_user_idx = (unsigned) -1;
6246
#endif
6247
  hb_accelerate_subtables_context_t::hb_applicable_t subtables[HB_VAR_ARRAY];
6248
};
6249
6250
template <typename Types>
6251
struct GSUBGPOSVersion1_2
6252
{
6253
  friend struct GSUBGPOS;
6254
6255
  protected:
6256
  FixedVersion<>version;  /* Version of the GSUB/GPOS table--initially set
6257
         * to 0x00010000u */
6258
  typename Types:: template OffsetTo<ScriptList>
6259
    scriptList; /* ScriptList table */
6260
  typename Types::template OffsetTo<FeatureList>
6261
    featureList;  /* FeatureList table */
6262
  typename Types::template OffsetTo<LookupList<Types>>
6263
    lookupList; /* LookupList table */
6264
  Offset32To<FeatureVariations>
6265
    featureVars;  /* Offset to Feature Variations
6266
           table--from beginning of table
6267
         * (may be NULL).  Introduced
6268
         * in version 0x00010001. */
6269
  public:
6270
  DEFINE_SIZE_MIN (4 + 3 * Types::size);
6271
6272
  size_t get_size () const
6273
0
  {
6274
0
    return min_size +
6275
0
     (version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
6276
0
  }
6277
6278
  const typename Types::template OffsetTo<LookupList<Types>>* get_lookup_list_offset () const
6279
0
  {
6280
0
    return &lookupList;
6281
0
  }
6282
6283
  template <typename TLookup>
6284
  bool sanitize (hb_sanitize_context_t *c) const
6285
96
  {
6286
96
    TRACE_SANITIZE (this);
6287
96
    typedef List16OfOffsetTo<TLookup, typename Types::HBUINT> TLookupList;
6288
96
    if (unlikely (!(scriptList.sanitize (c, this) &&
6289
96
        featureList.sanitize (c, this) &&
6290
96
        reinterpret_cast<const typename Types::template OffsetTo<TLookupList> &> (lookupList).sanitize (c, this))))
6291
0
      return_trace (false);
6292
6293
96
#ifndef HB_NO_VAR
6294
96
    if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this))))
6295
0
      return_trace (false);
6296
96
#endif
6297
6298
96
    return_trace (true);
6299
96
  }
bool OT::GSUBGPOSVersion1_2<OT::Layout::SmallTypes>::sanitize<OT::Layout::GSUB_impl::SubstLookup>(hb_sanitize_context_t*) const
Line
Count
Source
6285
48
  {
6286
48
    TRACE_SANITIZE (this);
6287
48
    typedef List16OfOffsetTo<TLookup, typename Types::HBUINT> TLookupList;
6288
48
    if (unlikely (!(scriptList.sanitize (c, this) &&
6289
48
        featureList.sanitize (c, this) &&
6290
48
        reinterpret_cast<const typename Types::template OffsetTo<TLookupList> &> (lookupList).sanitize (c, this))))
6291
0
      return_trace (false);
6292
6293
48
#ifndef HB_NO_VAR
6294
48
    if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this))))
6295
0
      return_trace (false);
6296
48
#endif
6297
6298
48
    return_trace (true);
6299
48
  }
bool OT::GSUBGPOSVersion1_2<OT::Layout::SmallTypes>::sanitize<OT::Layout::GPOS_impl::PosLookup>(hb_sanitize_context_t*) const
Line
Count
Source
6285
48
  {
6286
48
    TRACE_SANITIZE (this);
6287
48
    typedef List16OfOffsetTo<TLookup, typename Types::HBUINT> TLookupList;
6288
48
    if (unlikely (!(scriptList.sanitize (c, this) &&
6289
48
        featureList.sanitize (c, this) &&
6290
48
        reinterpret_cast<const typename Types::template OffsetTo<TLookupList> &> (lookupList).sanitize (c, this))))
6291
0
      return_trace (false);
6292
6293
48
#ifndef HB_NO_VAR
6294
48
    if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this))))
6295
0
      return_trace (false);
6296
48
#endif
6297
6298
48
    return_trace (true);
6299
48
  }
6300
6301
  template <typename TLookup>
6302
  bool subset (hb_subset_layout_context_t *c) const
6303
0
  {
6304
0
    TRACE_SUBSET (this);
6305
6306
0
    auto *out = c->subset_context->serializer->start_embed (this);
6307
0
    if (unlikely (!c->subset_context->serializer->extend_min (out))) return_trace (false);
6308
6309
0
    out->version = version;
6310
6311
0
    typedef LookupOffsetList<TLookup, typename Types::HBUINT> TLookupList;
6312
0
    reinterpret_cast<typename Types::template OffsetTo<TLookupList> &> (out->lookupList)
6313
0
  .serialize_subset (c->subset_context,
6314
0
         reinterpret_cast<const typename Types::template OffsetTo<TLookupList> &> (lookupList),
6315
0
         this,
6316
0
         c);
6317
6318
0
    reinterpret_cast<typename Types::template OffsetTo<RecordListOfFeature> &> (out->featureList)
6319
0
  .serialize_subset (c->subset_context,
6320
0
         reinterpret_cast<const typename Types::template OffsetTo<RecordListOfFeature> &> (featureList),
6321
0
         this,
6322
0
         c);
6323
6324
0
    out->scriptList.serialize_subset (c->subset_context,
6325
0
              scriptList,
6326
0
              this,
6327
0
              c);
6328
6329
0
#ifndef HB_NO_VAR
6330
0
    if (version.to_int () >= 0x00010001u)
6331
0
    {
6332
0
      auto snapshot = c->subset_context->serializer->snapshot ();
6333
0
      if (!c->subset_context->serializer->extend_min (&out->featureVars))
6334
0
        return_trace (false);
6335
6336
      // if all axes are pinned all feature vars are dropped.
6337
0
      bool ret = !c->subset_context->plan->all_axes_pinned
6338
0
                 && out->featureVars.serialize_subset (c->subset_context, featureVars, this, c);
6339
0
      if (!ret && version.major == 1)
6340
0
      {
6341
0
        c->subset_context->serializer->revert (snapshot);
6342
0
  out->version.major = 1;
6343
0
  out->version.minor = 0;
6344
0
      }
6345
0
    }
6346
0
#endif
6347
6348
0
    return_trace (true);
6349
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
6350
};
6351
6352
struct GSUBGPOS
6353
{
6354
  size_t get_size () const
6355
0
  {
6356
0
    switch (u.version.major) {
6357
0
    case 1: hb_barrier (); return u.version1.get_size ();
6358
#ifndef HB_NO_BEYOND_64K
6359
    case 2: hb_barrier (); return u.version2.get_size ();
6360
#endif
6361
0
    default: return u.version.static_size;
6362
0
    }
6363
0
  }
6364
6365
  template <typename TLookup>
6366
  bool sanitize (hb_sanitize_context_t *c) const
6367
96
  {
6368
96
    TRACE_SANITIZE (this);
6369
96
    if (unlikely (!u.version.sanitize (c))) return_trace (false);
6370
96
    hb_barrier ();
6371
96
    switch (u.version.major) {
6372
96
    case 1: hb_barrier (); return_trace (u.version1.sanitize<TLookup> (c));
6373
#ifndef HB_NO_BEYOND_64K
6374
    case 2: hb_barrier (); return_trace (u.version2.sanitize<TLookup> (c));
6375
#endif
6376
0
    default: return_trace (true);
6377
96
    }
6378
96
  }
bool OT::GSUBGPOS::sanitize<OT::Layout::GSUB_impl::SubstLookup>(hb_sanitize_context_t*) const
Line
Count
Source
6367
48
  {
6368
48
    TRACE_SANITIZE (this);
6369
48
    if (unlikely (!u.version.sanitize (c))) return_trace (false);
6370
48
    hb_barrier ();
6371
48
    switch (u.version.major) {
6372
48
    case 1: hb_barrier (); return_trace (u.version1.sanitize<TLookup> (c));
6373
#ifndef HB_NO_BEYOND_64K
6374
    case 2: hb_barrier (); return_trace (u.version2.sanitize<TLookup> (c));
6375
#endif
6376
0
    default: return_trace (true);
6377
48
    }
6378
48
  }
bool OT::GSUBGPOS::sanitize<OT::Layout::GPOS_impl::PosLookup>(hb_sanitize_context_t*) const
Line
Count
Source
6367
48
  {
6368
48
    TRACE_SANITIZE (this);
6369
48
    if (unlikely (!u.version.sanitize (c))) return_trace (false);
6370
48
    hb_barrier ();
6371
48
    switch (u.version.major) {
6372
48
    case 1: hb_barrier (); return_trace (u.version1.sanitize<TLookup> (c));
6373
#ifndef HB_NO_BEYOND_64K
6374
    case 2: hb_barrier (); return_trace (u.version2.sanitize<TLookup> (c));
6375
#endif
6376
0
    default: return_trace (true);
6377
48
    }
6378
48
  }
6379
6380
  template <typename TLookup>
6381
  bool subset (hb_subset_layout_context_t *c) const
6382
0
  {
6383
0
    switch (u.version.major) {
6384
0
    case 1: hb_barrier (); return u.version1.subset<TLookup> (c);
6385
#ifndef HB_NO_BEYOND_64K
6386
    case 2: hb_barrier (); return u.version2.subset<TLookup> (c);
6387
#endif
6388
0
    default: return false;
6389
0
    }
6390
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
6391
6392
  const ScriptList &get_script_list () const
6393
51.6k
  {
6394
51.6k
    switch (u.version.major) {
6395
51.6k
    case 1: hb_barrier (); return this+u.version1.scriptList;
6396
#ifndef HB_NO_BEYOND_64K
6397
    case 2: hb_barrier (); return this+u.version2.scriptList;
6398
#endif
6399
0
    default: return Null (ScriptList);
6400
51.6k
    }
6401
51.6k
  }
6402
  const FeatureList &get_feature_list () const
6403
31.7k
  {
6404
31.7k
    switch (u.version.major) {
6405
31.7k
    case 1: hb_barrier (); return this+u.version1.featureList;
6406
#ifndef HB_NO_BEYOND_64K
6407
    case 2: hb_barrier (); return this+u.version2.featureList;
6408
#endif
6409
0
    default: return Null (FeatureList);
6410
31.7k
    }
6411
31.7k
  }
6412
  unsigned int get_lookup_count () const
6413
14.1k
  {
6414
14.1k
    switch (u.version.major) {
6415
14.1k
    case 1: hb_barrier (); return (this+u.version1.lookupList).len;
6416
#ifndef HB_NO_BEYOND_64K
6417
    case 2: hb_barrier (); return (this+u.version2.lookupList).len;
6418
#endif
6419
0
    default: return 0;
6420
14.1k
    }
6421
14.1k
  }
6422
  const Lookup& get_lookup (unsigned int i) const
6423
3.55M
  {
6424
3.55M
    switch (u.version.major) {
6425
3.55M
    case 1: hb_barrier (); return (this+u.version1.lookupList)[i];
6426
#ifndef HB_NO_BEYOND_64K
6427
    case 2: hb_barrier (); return (this+u.version2.lookupList)[i];
6428
#endif
6429
0
    default: return Null (Lookup);
6430
3.55M
    }
6431
3.55M
  }
6432
  const FeatureVariations &get_feature_variations () const
6433
27.9M
  {
6434
27.9M
    switch (u.version.major) {
6435
27.9M
    case 1: hb_barrier (); return (u.version.to_int () >= 0x00010001u && hb_barrier () ? this+u.version1.featureVars : Null (FeatureVariations));
6436
#ifndef HB_NO_BEYOND_64K
6437
    case 2: hb_barrier (); return this+u.version2.featureVars;
6438
#endif
6439
0
    default: return Null (FeatureVariations);
6440
27.9M
    }
6441
27.9M
  }
6442
6443
10.2k
  bool has_data () const { return u.version.to_int (); }
6444
  unsigned int get_script_count () const
6445
65
  { return get_script_list ().len; }
6446
  const Tag& get_script_tag (unsigned int i) const
6447
0
  { return get_script_list ().get_tag (i); }
6448
  unsigned int get_script_tags (unsigned int start_offset,
6449
        unsigned int *script_count /* IN/OUT */,
6450
        hb_tag_t     *script_tags /* OUT */) const
6451
0
  { return get_script_list ().get_tags (start_offset, script_count, script_tags); }
6452
  const Script& get_script (unsigned int i) const
6453
31.5k
  { return get_script_list ()[i]; }
6454
  bool find_script_index (hb_tag_t tag, unsigned int *index) const
6455
20.0k
  { return get_script_list ().find_index (tag, index); }
6456
6457
  unsigned int get_feature_count () const
6458
812
  { return get_feature_list ().len; }
6459
  hb_tag_t get_feature_tag (unsigned int i) const
6460
27.1k
  { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : get_feature_list ().get_tag (i); }
6461
  unsigned int get_feature_tags (unsigned int start_offset,
6462
         unsigned int *feature_count /* IN/OUT */,
6463
         hb_tag_t     *feature_tags /* OUT */) const
6464
0
  { return get_feature_list ().get_tags (start_offset, feature_count, feature_tags); }
6465
  const Feature& get_feature (unsigned int i) const
6466
14.0k
  { return get_feature_list ()[i]; }
6467
  bool find_feature_index (hb_tag_t tag, unsigned int *index) const
6468
0
  { return get_feature_list ().find_index (tag, index); }
6469
6470
  bool find_variations_index (const int *coords, unsigned int num_coords,
6471
            unsigned int *index,
6472
            ItemVarStoreInstancer *instancer) const
6473
27.9M
  {
6474
#ifdef HB_NO_VAR
6475
    *index = FeatureVariations::NOT_FOUND_INDEX;
6476
    return false;
6477
#endif
6478
27.9M
    return get_feature_variations ().find_index (coords, num_coords, index, instancer);
6479
27.9M
  }
6480
  const Feature& get_feature_variation (unsigned int feature_index,
6481
          unsigned int variations_index) const
6482
14.0k
  {
6483
14.0k
#ifndef HB_NO_VAR
6484
14.0k
    if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
6485
0
  u.version.to_int () >= 0x00010001u)
6486
0
    {
6487
0
      const Feature *feature = get_feature_variations ().find_substitute (variations_index,
6488
0
                    feature_index);
6489
0
      if (feature)
6490
0
  return *feature;
6491
0
    }
6492
14.0k
#endif
6493
14.0k
    return get_feature (feature_index);
6494
14.0k
  }
6495
6496
  void feature_variation_collect_lookups (const hb_set_t *feature_indexes,
6497
            const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
6498
            hb_set_t       *lookup_indexes /* OUT */) const
6499
65
  {
6500
65
#ifndef HB_NO_VAR
6501
65
    get_feature_variations ().collect_lookups (feature_indexes, feature_record_cond_idx_map, lookup_indexes);
6502
65
#endif
6503
65
  }
6504
6505
#ifndef HB_NO_VAR
6506
  void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
6507
0
  { get_feature_variations ().collect_feature_substitutes_with_variations (c); }
6508
#endif
6509
6510
  template <typename TLookup>
6511
  void closure_lookups (hb_face_t      *face,
6512
      const hb_set_t *glyphs,
6513
      hb_set_t       *lookup_indexes /* IN/OUT */) const
6514
0
  {
6515
0
    hb_set_t visited_lookups, inactive_lookups;
6516
0
    hb_closure_lookups_context_t c (face, glyphs, &visited_lookups, &inactive_lookups);
6517
6518
0
    c.set_recurse_func (TLookup::template dispatch_recurse_func<hb_closure_lookups_context_t>);
6519
6520
0
    for (unsigned lookup_index : *lookup_indexes)
6521
0
      reinterpret_cast<const TLookup &> (get_lookup (lookup_index)).closure_lookups (&c, lookup_index);
6522
6523
0
    hb_set_union (lookup_indexes, &visited_lookups);
6524
0
    hb_set_subtract (lookup_indexes, &inactive_lookups);
6525
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
6526
6527
  void prune_langsys (const hb_map_t *duplicate_feature_map,
6528
                      const hb_set_t *layout_scripts,
6529
                      hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map,
6530
                      hb_set_t       *new_feature_indexes /* OUT */) const
6531
0
  {
6532
0
    hb_prune_langsys_context_t c (this, script_langsys_map, duplicate_feature_map, new_feature_indexes);
6533
6534
0
    unsigned count = get_script_count ();
6535
0
    for (unsigned script_index = 0; script_index < count; script_index++)
6536
0
    {
6537
0
      const Tag& tag = get_script_tag (script_index);
6538
0
      if (!layout_scripts->has (tag)) continue;
6539
0
      const Script& s = get_script (script_index);
6540
0
      s.prune_langsys (&c, script_index);
6541
0
    }
6542
0
  }
6543
6544
  void prune_features (const hb_map_t *lookup_indices, /* IN */
6545
           const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, /* IN */
6546
           const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map, /* IN */
6547
           hb_set_t       *feature_indices /* IN/OUT */) const
6548
0
  {
6549
0
#ifndef HB_NO_VAR
6550
    // This is the set of feature indices which have alternate versions defined
6551
    // if the FeatureVariation's table and the alternate version(s) intersect the
6552
    // set of lookup indices.
6553
0
    hb_set_t alternate_feature_indices;
6554
0
    get_feature_variations ().closure_features (lookup_indices, feature_record_cond_idx_map, &alternate_feature_indices);
6555
0
    if (unlikely (alternate_feature_indices.in_error()))
6556
0
    {
6557
0
      feature_indices->err ();
6558
0
      return;
6559
0
    }
6560
0
#endif
6561
6562
0
    for (unsigned i : hb_iter (feature_indices))
6563
0
    {
6564
0
      hb_tag_t tag =  get_feature_tag (i);
6565
0
      if (tag == HB_TAG ('p', 'r', 'e', 'f'))
6566
        // Note: Never ever drop feature 'pref', even if it's empty.
6567
        // HarfBuzz chooses shaper for Khmer based on presence of this
6568
        // feature. See thread at:
6569
  // http://lists.freedesktop.org/archives/harfbuzz/2012-November/002660.html
6570
0
        continue;
6571
6572
6573
0
      const Feature *f = &(get_feature (i));
6574
0
      const Feature** p = nullptr;
6575
0
      if (feature_substitutes_map->has (i, &p))
6576
0
        f = *p;
6577
6578
0
      if (!f->featureParams.is_null () &&
6579
0
          tag == HB_TAG ('s', 'i', 'z', 'e'))
6580
0
        continue;
6581
6582
0
      if (!f->intersects_lookup_indexes (lookup_indices)
6583
0
#ifndef HB_NO_VAR
6584
0
          && !alternate_feature_indices.has (i)
6585
0
#endif
6586
0
    )
6587
0
  feature_indices->del (i);
6588
0
    }
6589
0
  }
6590
6591
  void collect_name_ids (const hb_map_t *feature_index_map,
6592
                         hb_set_t *nameids_to_retain /* OUT */) const
6593
0
  {
6594
0
    unsigned count = get_feature_count ();
6595
0
    for (unsigned i = 0 ; i < count; i++)
6596
0
    {
6597
0
      if (!feature_index_map->has (i)) continue;
6598
0
      hb_tag_t tag = get_feature_tag (i);
6599
0
      get_feature (i).collect_name_ids (tag, nameids_to_retain);
6600
0
    }
6601
0
  }
6602
6603
  template <typename T>
6604
  struct accelerator_t
6605
  {
6606
    accelerator_t (hb_face_t *face)
6607
96
    {
6608
96
      hb_sanitize_context_t sc;
6609
96
      sc.lazy_some_gpos = true;
6610
96
      this->table = sc.reference_table<T> (face);
6611
6612
96
      if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face)))
6613
0
      {
6614
0
  hb_blob_destroy (this->table.get_blob ());
6615
0
  this->table = hb_blob_get_empty ();
6616
0
      }
6617
6618
96
      this->lookup_count = table->get_lookup_count ();
6619
6620
96
      this->accels = (hb_atomic_t<hb_ot_layout_lookup_accelerator_t *> *) hb_calloc (this->lookup_count, sizeof (*accels));
6621
96
      if (unlikely (!this->accels))
6622
0
      {
6623
0
  this->lookup_count = 0;
6624
0
  this->table.destroy ();
6625
0
  this->table = hb_blob_get_empty ();
6626
0
      }
6627
96
    }
OT::GSUBGPOS::accelerator_t<OT::Layout::GSUB>::accelerator_t(hb_face_t*)
Line
Count
Source
6607
48
    {
6608
48
      hb_sanitize_context_t sc;
6609
48
      sc.lazy_some_gpos = true;
6610
48
      this->table = sc.reference_table<T> (face);
6611
6612
48
      if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face)))
6613
0
      {
6614
0
  hb_blob_destroy (this->table.get_blob ());
6615
0
  this->table = hb_blob_get_empty ();
6616
0
      }
6617
6618
48
      this->lookup_count = table->get_lookup_count ();
6619
6620
48
      this->accels = (hb_atomic_t<hb_ot_layout_lookup_accelerator_t *> *) hb_calloc (this->lookup_count, sizeof (*accels));
6621
48
      if (unlikely (!this->accels))
6622
0
      {
6623
0
  this->lookup_count = 0;
6624
0
  this->table.destroy ();
6625
0
  this->table = hb_blob_get_empty ();
6626
0
      }
6627
48
    }
OT::GSUBGPOS::accelerator_t<OT::Layout::GPOS>::accelerator_t(hb_face_t*)
Line
Count
Source
6607
48
    {
6608
48
      hb_sanitize_context_t sc;
6609
48
      sc.lazy_some_gpos = true;
6610
48
      this->table = sc.reference_table<T> (face);
6611
6612
48
      if (unlikely (this->table->is_blocklisted (this->table.get_blob (), face)))
6613
0
      {
6614
0
  hb_blob_destroy (this->table.get_blob ());
6615
0
  this->table = hb_blob_get_empty ();
6616
0
      }
6617
6618
48
      this->lookup_count = table->get_lookup_count ();
6619
6620
48
      this->accels = (hb_atomic_t<hb_ot_layout_lookup_accelerator_t *> *) hb_calloc (this->lookup_count, sizeof (*accels));
6621
48
      if (unlikely (!this->accels))
6622
0
      {
6623
0
  this->lookup_count = 0;
6624
0
  this->table.destroy ();
6625
0
  this->table = hb_blob_get_empty ();
6626
0
      }
6627
48
    }
6628
    ~accelerator_t ()
6629
0
    {
6630
0
      for (unsigned int i = 0; i < this->lookup_count; i++)
6631
0
      {
6632
0
  auto *accel = this->accels[i].get_relaxed ();
6633
0
  if (accel)
6634
0
    accel->fini ();
6635
0
  hb_free (accel);
6636
0
      }
6637
0
      hb_free (this->accels);
6638
0
      this->table.destroy ();
6639
0
    }
Unexecuted instantiation: OT::GSUBGPOS::accelerator_t<OT::Layout::GSUB>::~accelerator_t()
Unexecuted instantiation: OT::GSUBGPOS::accelerator_t<OT::Layout::GPOS>::~accelerator_t()
6640
6641
27.9M
    hb_blob_t *get_blob () const { return table.get_blob (); }
OT::GSUBGPOS::accelerator_t<OT::Layout::GSUB>::get_blob() const
Line
Count
Source
6641
13.9M
    hb_blob_t *get_blob () const { return table.get_blob (); }
OT::GSUBGPOS::accelerator_t<OT::Layout::GPOS>::get_blob() const
Line
Count
Source
6641
13.9M
    hb_blob_t *get_blob () const { return table.get_blob (); }
6642
6643
    hb_ot_layout_lookup_accelerator_t *get_accel (unsigned lookup_index) const
6644
90.5M
    {
6645
90.5M
      if (unlikely (lookup_index >= lookup_count)) return nullptr;
6646
6647
90.5M
    retry:
6648
90.5M
      auto *accel = accels[lookup_index].get_acquire ();
6649
90.5M
      if (unlikely (!accel))
6650
719
      {
6651
719
  accel = hb_ot_layout_lookup_accelerator_t::create (table->get_lookup (lookup_index));
6652
719
  if (unlikely (!accel))
6653
0
    return nullptr;
6654
6655
719
  if (unlikely (!accels[lookup_index].cmpexch (nullptr, accel)))
6656
0
  {
6657
0
    accel->fini ();
6658
0
    hb_free (accel);
6659
0
    goto retry;
6660
0
  }
6661
719
      }
6662
6663
90.5M
      return accel;
6664
90.5M
    }
OT::GSUBGPOS::accelerator_t<OT::Layout::GPOS>::get_accel(unsigned int) const
Line
Count
Source
6644
82.6M
    {
6645
82.6M
      if (unlikely (lookup_index >= lookup_count)) return nullptr;
6646
6647
82.6M
    retry:
6648
82.6M
      auto *accel = accels[lookup_index].get_acquire ();
6649
82.6M
      if (unlikely (!accel))
6650
650
      {
6651
650
  accel = hb_ot_layout_lookup_accelerator_t::create (table->get_lookup (lookup_index));
6652
650
  if (unlikely (!accel))
6653
0
    return nullptr;
6654
6655
650
  if (unlikely (!accels[lookup_index].cmpexch (nullptr, accel)))
6656
0
  {
6657
0
    accel->fini ();
6658
0
    hb_free (accel);
6659
0
    goto retry;
6660
0
  }
6661
650
      }
6662
6663
82.6M
      return accel;
6664
82.6M
    }
OT::GSUBGPOS::accelerator_t<OT::Layout::GSUB>::get_accel(unsigned int) const
Line
Count
Source
6644
7.86M
    {
6645
7.86M
      if (unlikely (lookup_index >= lookup_count)) return nullptr;
6646
6647
7.86M
    retry:
6648
7.86M
      auto *accel = accels[lookup_index].get_acquire ();
6649
7.86M
      if (unlikely (!accel))
6650
69
      {
6651
69
  accel = hb_ot_layout_lookup_accelerator_t::create (table->get_lookup (lookup_index));
6652
69
  if (unlikely (!accel))
6653
0
    return nullptr;
6654
6655
69
  if (unlikely (!accels[lookup_index].cmpexch (nullptr, accel)))
6656
0
  {
6657
0
    accel->fini ();
6658
0
    hb_free (accel);
6659
0
    goto retry;
6660
0
  }
6661
69
      }
6662
6663
7.86M
      return accel;
6664
7.86M
    }
6665
6666
    hb_blob_ptr_t<T> table;
6667
    unsigned int lookup_count;
6668
    hb_atomic_t<hb_ot_layout_lookup_accelerator_t *> *accels;
6669
  };
6670
6671
  protected:
6672
  union {
6673
  FixedVersion<>      version;  /* Version identifier */
6674
  GSUBGPOSVersion1_2<SmallTypes>  version1;
6675
#ifndef HB_NO_BEYOND_64K
6676
  GSUBGPOSVersion1_2<MediumTypes> version2;
6677
#endif
6678
  } u;
6679
  public:
6680
  DEFINE_SIZE_MIN (4);
6681
};
6682
6683
6684
} /* namespace OT */
6685
6686
6687
#endif /* HB_OT_LAYOUT_GSUBGPOS_HH */