Coverage Report

Created: 2026-10-14 09:33

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