Coverage Report

Created: 2026-10-30 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/harfbuzz/src/hb-ot-layout-common.hh
Line
Count
Source
1
/*
2
 * Copyright © 2007,2008,2009  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_COMMON_HH
30
#define HB_OT_LAYOUT_COMMON_HH
31
32
#include "hb.hh"
33
#include "hb-ot-layout.hh"
34
#include "hb-open-type.hh"
35
#include "hb-set.hh"
36
#include "hb-bimap.hh"
37
#include "hb-cache.hh"
38
#include "hb-ot-dual.hh"
39
40
using hb_ot_layout_mapping_cache_t = hb_cache_t<16, 8, 8>;
41
static_assert (sizeof (hb_ot_layout_mapping_cache_t) == 512, "");
42
43
using hb_ot_layout_binary_cache_t = hb_cache_t<14, 1, 8>;
44
static_assert (sizeof (hb_ot_layout_binary_cache_t) == 256, "");
45
46
#include "OT/Layout/Common/Coverage.hh"
47
48
// TODO(garretrieger): cleanup these after migration.
49
using OT::Layout::Common::Coverage;
50
using OT::Layout::Common::RangeRecord;
51
using OT::Layout::SmallTypes;
52
using OT::Layout::MediumTypes;
53
54
55
namespace OT {
56
57
template<typename Iterator>
58
static inline bool ClassDef_serialize (hb_serialize_context_t *c,
59
               Iterator it);
60
61
static bool ClassDef_remap_and_serialize (
62
    hb_serialize_context_t *c,
63
    const hb_set_t &klasses,
64
    bool use_class_zero,
65
    hb_sorted_vector_t<hb_codepoint_pair_t> &glyph_and_klass, /* IN/OUT */
66
    hb_map_t *klass_map /*IN/OUT*/);
67
68
struct ItemVarStoreInstancer;
69
70
struct hb_collect_feature_substitutes_with_var_context_t
71
{
72
  const hb_map_t *axes_index_tag_map;
73
  const hb_hashmap_t<hb_tag_t, Triple> *axes_location;
74
  hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *record_cond_idx_map;
75
  hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map;
76
  hb_set_t& catch_all_record_feature_idxes;
77
78
  // not stored in subset_plan
79
  hb_set_t *feature_indices;
80
  bool apply;
81
  bool variation_applied;
82
  bool universal;
83
  unsigned cur_record_idx;
84
  hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> *conditionset_map;
85
  ItemVarStoreInstancer *instancer;
86
  bool all_axes_pinned;
87
};
88
89
struct hb_prune_langsys_context_t
90
{
91
  hb_prune_langsys_context_t (const void         *table_,
92
                              hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map_,
93
                              const hb_map_t     *duplicate_feature_map_,
94
                              hb_set_t           *new_collected_feature_indexes_)
95
      :table (table_),
96
      script_langsys_map (script_langsys_map_),
97
      duplicate_feature_map (duplicate_feature_map_),
98
      new_feature_indexes (new_collected_feature_indexes_),
99
0
      script_count (0),langsys_feature_count (0) {}
100
101
  bool visitScript ()
102
0
  { return script_count++ < HB_MAX_SCRIPTS; }
103
104
  bool visitLangsys (unsigned feature_count)
105
0
  {
106
0
    langsys_feature_count += feature_count;
107
0
    return langsys_feature_count < HB_MAX_LANGSYS_FEATURE_COUNT;
108
0
  }
109
110
  public:
111
  const void *table;
112
  hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map;
113
  const hb_map_t     *duplicate_feature_map;
114
  hb_set_t           *new_feature_indexes;
115
116
  private:
117
  unsigned script_count;
118
  unsigned langsys_feature_count;
119
};
120
121
struct hb_subset_layout_context_t :
122
  hb_dispatch_context_t<hb_subset_layout_context_t, hb_empty_t, HB_DEBUG_SUBSET>
123
{
124
0
  const char *get_name () { return "SUBSET_LAYOUT"; }
125
0
  static return_t default_return_value () { return hb_empty_t (); }
126
127
  bool visitScript ()
128
0
  {
129
0
    return script_count++ < HB_MAX_SCRIPTS;
130
0
  }
131
132
  bool visitLangSys ()
133
0
  {
134
0
    return langsys_count++ < HB_MAX_LANGSYS;
135
0
  }
136
137
  bool visitFeatureIndex (int count)
138
0
  {
139
0
    feature_index_count += count;
140
0
    return feature_index_count < HB_MAX_FEATURE_INDICES;
141
0
  }
142
143
  bool visitLookupIndex()
144
0
  {
145
0
    lookup_index_count++;
146
0
    return lookup_index_count < HB_MAX_LOOKUP_VISIT_COUNT;
147
0
  }
148
149
  hb_subset_context_t *subset_context;
150
  const hb_tag_t table_tag;
151
  const hb_map_t *lookup_index_map;
152
  const hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map;
153
  const hb_map_t *feature_index_map;
154
  const hb_map_t *feature_map_w_duplicates;
155
  const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map;
156
  const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *lookup_variations;
157
  hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map;
158
  const hb_set_t *catch_all_record_feature_idxes;
159
  const hb_hashmap_t<unsigned, hb_pair_t<const void*, const void*>> *feature_idx_tag_map;
160
161
  unsigned cur_script_index;
162
  unsigned cur_feature_index;
163
  unsigned cur_feature_var_record_idx;
164
165
  hb_subset_layout_context_t (hb_subset_context_t *c_,
166
            hb_tag_t tag_) :
167
        subset_context (c_),
168
        table_tag (tag_),
169
        cur_script_index (0xFFFFu),
170
        cur_feature_index (Index::NOT_FOUND_INDEX),
171
        cur_feature_var_record_idx (0u),
172
        script_count (0),
173
        langsys_count (0),
174
        feature_index_count (0),
175
        lookup_index_count (0)
176
0
  {
177
0
    if (tag_ == HB_OT_TAG_GSUB)
178
0
    {
179
0
      lookup_index_map = &c_->plan->gsub_lookups;
180
0
      script_langsys_map = &c_->plan->gsub_langsys;
181
0
      feature_index_map = &c_->plan->gsub_features;
182
0
      feature_map_w_duplicates = &c_->plan->gsub_features_w_duplicates;
183
0
      feature_substitutes_map = &c_->plan->gsub_feature_substitutes_map;
184
0
      lookup_variations = &c_->plan->gsub_lookup_variations;
185
0
      feature_record_cond_idx_map = c_->plan->user_axes_location.is_empty () ? nullptr : &c_->plan->gsub_feature_record_cond_idx_map;
186
0
      catch_all_record_feature_idxes = &c_->plan->gsub_old_features;
187
0
      feature_idx_tag_map = &c_->plan->gsub_old_feature_idx_tag_map;
188
0
    }
189
0
    else
190
0
    {
191
0
      lookup_index_map = &c_->plan->gpos_lookups;
192
0
      script_langsys_map = &c_->plan->gpos_langsys;
193
0
      feature_index_map = &c_->plan->gpos_features;
194
0
      feature_map_w_duplicates = &c_->plan->gpos_features_w_duplicates;
195
0
      feature_substitutes_map = &c_->plan->gpos_feature_substitutes_map;
196
0
      lookup_variations = &c_->plan->gpos_lookup_variations;
197
0
      feature_record_cond_idx_map = c_->plan->user_axes_location.is_empty () ? nullptr : &c_->plan->gpos_feature_record_cond_idx_map;
198
0
      catch_all_record_feature_idxes = &c_->plan->gpos_old_features;
199
0
      feature_idx_tag_map = &c_->plan->gpos_old_feature_idx_tag_map;
200
0
    }
201
0
  }
202
203
  private:
204
  unsigned script_count;
205
  unsigned langsys_count;
206
  unsigned feature_index_count;
207
  unsigned lookup_index_count;
208
};
209
210
struct ItemVariationStore;
211
struct hb_collect_variation_indices_context_t :
212
       hb_dispatch_context_t<hb_collect_variation_indices_context_t>
213
{
214
  template <typename T>
215
0
  return_t dispatch (const T &obj) { obj.collect_variation_indices (this); return hb_empty_t (); }
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_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_variation_indices_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_variation_indices_context_t::dispatch<OT::Layout::GPOS_impl::SinglePosFormat1_3<OT::Layout::MediumTypes> >(OT::Layout::GPOS_impl::SinglePosFormat1_3<OT::Layout::MediumTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_context_t::dispatch<OT::Layout::GPOS_impl::SinglePosFormat2_4<OT::Layout::MediumTypes> >(OT::Layout::GPOS_impl::SinglePosFormat2_4<OT::Layout::MediumTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_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_variation_indices_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_variation_indices_context_t::dispatch<OT::Layout::GPOS_impl::PairPosFormat1_3<OT::Layout::MediumTypes> >(OT::Layout::GPOS_impl::PairPosFormat1_3<OT::Layout::MediumTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_context_t::dispatch<OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::MediumTypes> >(OT::Layout::GPOS_impl::PairPosFormat2_4<OT::Layout::MediumTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_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_variation_indices_context_t::dispatch<OT::Layout::GPOS_impl::CursivePosFormat1_2<OT::Layout::MediumTypes> >(OT::Layout::GPOS_impl::CursivePosFormat1_2<OT::Layout::MediumTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_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_variation_indices_context_t::dispatch<OT::Layout::GPOS_impl::MarkBasePosFormat1_2<OT::Layout::MediumTypes> >(OT::Layout::GPOS_impl::MarkBasePosFormat1_2<OT::Layout::MediumTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_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_variation_indices_context_t::dispatch<OT::Layout::GPOS_impl::MarkLigPosFormat1_2<OT::Layout::MediumTypes> >(OT::Layout::GPOS_impl::MarkLigPosFormat1_2<OT::Layout::MediumTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_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_variation_indices_context_t::dispatch<OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes> >(OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_context_t::dispatch<OT::ContextFormat1_4<OT::Layout::SmallTypes> >(OT::ContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_context_t::dispatch<OT::ContextFormat2_5<OT::Layout::SmallTypes> >(OT::ContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_context_t::dispatch<OT::ContextFormat3_6<OT::Layout::SmallTypes> >(OT::ContextFormat3_6<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_context_t::dispatch<OT::ContextFormat1_4<OT::Layout::MediumTypes> >(OT::ContextFormat1_4<OT::Layout::MediumTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_context_t::dispatch<OT::ContextFormat2_5<OT::Layout::MediumTypes> >(OT::ContextFormat2_5<OT::Layout::MediumTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_context_t::dispatch<OT::ContextFormat3_6<OT::Layout::MediumTypes> >(OT::ContextFormat3_6<OT::Layout::MediumTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_context_t::dispatch<OT::ChainContextFormat1_4<OT::Layout::SmallTypes> >(OT::ChainContextFormat1_4<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_context_t::dispatch<OT::ChainContextFormat2_5<OT::Layout::SmallTypes> >(OT::ChainContextFormat2_5<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_context_t::dispatch<OT::ChainContextFormat3<OT::Layout::SmallTypes> >(OT::ChainContextFormat3<OT::Layout::SmallTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_context_t::dispatch<OT::ChainContextFormat1_4<OT::Layout::MediumTypes> >(OT::ChainContextFormat1_4<OT::Layout::MediumTypes> const&)
Unexecuted instantiation: hb_empty_t OT::hb_collect_variation_indices_context_t::dispatch<OT::ChainContextFormat2_5<OT::Layout::MediumTypes> >(OT::ChainContextFormat2_5<OT::Layout::MediumTypes> const&)
216
0
  static return_t default_return_value () { return hb_empty_t (); }
217
218
  hb_set_t *layout_variation_indices;
219
  const hb_set_t *glyph_set;
220
  const hb_map_t *gpos_lookups;
221
  hb_hashmap_t<uintptr_t, hb_pair_t<unsigned, int>> *condition_values = nullptr;
222
223
  hb_collect_variation_indices_context_t (hb_set_t *layout_variation_indices_,
224
            const hb_set_t *glyph_set_,
225
            const hb_map_t *gpos_lookups_) :
226
          layout_variation_indices (layout_variation_indices_),
227
          glyph_set (glyph_set_),
228
0
          gpos_lookups (gpos_lookups_) {}
229
};
230
231
template<typename OutputArray>
232
struct subset_offset_array_t
233
{
234
  subset_offset_array_t (hb_subset_context_t *subset_context_,
235
       OutputArray& out_,
236
       const void *base_) : subset_context (subset_context_),
237
                out (out_), base (base_) {}
238
239
  template <typename T>
240
  bool operator () (T&& offset)
241
0
  {
242
0
    auto snap = subset_context->serializer->snapshot ();
243
0
    auto *o = out.serialize_append (subset_context->serializer);
244
0
    if (unlikely (!o)) return false;
245
0
    bool ret = o->serialize_subset (subset_context, offset, base);
246
0
    if (!ret)
247
0
    {
248
0
      out.pop ();
249
0
      subset_context->serializer->revert (snap);
250
0
    }
251
0
    return ret;
252
0
  }
Unexecuted instantiation: bool OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > >::operator()<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true> const&>(OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > >::operator()<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true> const&>(OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >::operator()<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true> const&>(OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >::operator()<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true> const&>(OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >::operator()<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true> const&>(OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >::operator()<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true> const&>(OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned int, 4u> > >::operator()<OT::OffsetTo<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned int, 4u>, void, true> const&>(OT::OffsetTo<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned int, 4u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned short, 2u> > >::operator()<OT::OffsetTo<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned short, 2u>, void, true> const&>(OT::OffsetTo<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned short, 2u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >::operator()<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true> const&>(OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >::operator()<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true> const&>(OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >::operator()<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true> const&>(OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >::operator()<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true> const&>(OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned int, 4u> > >::operator()<OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned int, 4u>, void, true> const&>(OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned int, 4u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned short, 2u> > >::operator()<OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned short, 2u>, void, true> const&>(OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned short, 2u>, void, true> const&)
253
254
  private:
255
  hb_subset_context_t *subset_context;
256
  OutputArray &out;
257
  const void *base;
258
};
259
260
261
template<typename OutputArray, typename Arg>
262
struct subset_offset_array_arg_t
263
{
264
  subset_offset_array_arg_t (hb_subset_context_t *subset_context_,
265
           OutputArray& out_,
266
           const void *base_,
267
           Arg &&arg_) : subset_context (subset_context_), out (out_),
268
            base (base_), arg (arg_) {}
269
270
  template <typename T>
271
  bool operator () (T&& offset)
272
0
  {
273
0
    auto snap = subset_context->serializer->snapshot ();
274
0
    auto *o = out.serialize_append (subset_context->serializer);
275
0
    if (unlikely (!o)) return false;
276
0
    bool ret = o->serialize_subset (subset_context, offset, base, arg);
277
0
    if (!ret)
278
0
    {
279
0
      out.pop ();
280
0
      subset_context->serializer->revert (snap);
281
0
    }
282
0
    return ret;
283
0
  }
Unexecuted instantiation: bool OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GPOS_impl::PosLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>::operator()<OT::OffsetTo<OT::Layout::GPOS_impl::PosLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true> const&>(OT::OffsetTo<OT::Layout::GPOS_impl::PosLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&>::operator()<OT::OffsetTo<OT::RuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true> const&>(OT::OffsetTo<OT::RuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&>::operator()<OT::OffsetTo<OT::RuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true> const&>(OT::OffsetTo<OT::RuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&>::operator()<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true> const&>(OT::OffsetTo<OT::ChainRuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&>::operator()<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true> const&>(OT::OffsetTo<OT::ChainRuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>::operator()<OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true> const&>(OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>::operator()<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true> const&>(OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>::operator()<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true> const&>(OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, unsigned int&>::operator()<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true> const&>(OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true> const&)
Unexecuted instantiation: bool OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>::operator()<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true> const&>(OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true> const&)
284
285
  private:
286
  hb_subset_context_t *subset_context;
287
  OutputArray &out;
288
  const void *base;
289
  Arg &&arg;
290
};
291
292
/*
293
 * Helper to subset an array of offsets. Subsets the thing pointed to by each offset
294
 * and discards the offset in the array if the subset operation results in an empty
295
 * thing.
296
 */
297
struct
298
{
299
  template<typename OutputArray>
300
  subset_offset_array_t<OutputArray>
301
  operator () (hb_subset_context_t *subset_context, OutputArray& out,
302
         const void *base) const
303
0
  { return subset_offset_array_t<OutputArray> (subset_context, out, base); }
Unexecuted instantiation: hb-face.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> >&, void const*) const
Unexecuted instantiation: hb-face.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-font.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> >&, void const*) const
Unexecuted instantiation: hb-font.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> >&, void const*) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned int, 4u> > > OT::$_39::operator()<OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned int, 4u> > >(hb_subset_context_t*, OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned int, 4u> >&, void const*) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned int, 4u> > > OT::$_39::operator()<OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned int, 4u> > >(hb_subset_context_t*, OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned int, 4u> >&, void const*) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-font.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> >&, void const*) const
Unexecuted instantiation: hb-ot-font.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: VARC.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> >&, void const*) const
Unexecuted instantiation: VARC.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: VARC.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: VARC.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: VARC.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*) const
Unexecuted instantiation: VARC.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-metrics.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> >&, void const*) const
Unexecuted instantiation: hb-ot-metrics.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-shape.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> >&, void const*) const
Unexecuted instantiation: hb-ot-shape.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-shape.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-shape.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-shape.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*) const
Unexecuted instantiation: hb-ot-shape.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-var.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> >&, void const*) const
Unexecuted instantiation: hb-ot-var.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-static.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> >&, void const*) const
Unexecuted instantiation: hb-static.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-static.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-static.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-static.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*) const
Unexecuted instantiation: hb-static.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ft.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> >&, void const*) const
Unexecuted instantiation: hb-ft.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> >&, void const*) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned int, 4u> > > OT::$_39::operator()<OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned int, 4u> > >(hb_subset_context_t*, OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned int, 4u> >&, void const*) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned int, 4u> > > OT::$_39::operator()<OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned int, 4u> > >(hb_subset_context_t*, OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned int, 4u> >&, void const*) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-aat-map.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> >&, void const*) const
Unexecuted instantiation: hb-aat-map.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-aat-map.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-aat-map.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-aat-map.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*) const
Unexecuted instantiation: hb-aat-map.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-cff1-table.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> >&, void const*) const
Unexecuted instantiation: hb-ot-cff1-table.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-cff2-table.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> >&, void const*) const
Unexecuted instantiation: hb-ot-cff2-table.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> >&, void const*) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned int, 4u> > > OT::$_39::operator()<OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned int, 4u> > >(hb_subset_context_t*, OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned int, 4u> >&, void const*) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned int, 4u> > > OT::$_39::operator()<OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned int, 4u> > >(hb_subset_context_t*, OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned int, 4u> >&, void const*) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> >&, void const*) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Sequence<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::AlternateSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned int, 4u> > > OT::$_39::operator()<OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned int, 4u> > >(hb_subset_context_t*, OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned int, 4u> >&, void const*) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned char, 1u> >&, void const*) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Condition, OT::NumType<true, unsigned int, 4u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::AttachPoint, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::CaretValue, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_offset_array_t<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::LigGlyph, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned int, 4u> > > OT::$_39::operator()<OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned int, 4u> > >(hb_subset_context_t*, OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned int, 4u> >&, void const*) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_offset_array_t<OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned short, 2u> > > OT::$_39::operator()<OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned short, 2u> > >(hb_subset_context_t*, OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned short, 2u> >&, void const*) const
304
305
  /* Variant with one extra argument passed to serialize_subset */
306
  template<typename OutputArray, typename Arg>
307
  subset_offset_array_arg_t<OutputArray, Arg>
308
  operator () (hb_subset_context_t *subset_context, OutputArray& out,
309
         const void *base, Arg &&arg) const
310
0
  { return subset_offset_array_arg_t<OutputArray, Arg> (subset_context, out, base, arg); }
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GPOS_impl::PosLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GPOS_impl::PosLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GPOS_impl::PosLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GPOS_impl::PosLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GPOS_impl::PosLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GPOS_impl::PosLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GPOS_impl::PosLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GPOS_impl::PosLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GPOS_impl::PosLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::LigatureSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::Ligature<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::Layout::GPOS_impl::PosLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::Layout::GPOS_impl::PosLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, unsigned int&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::Layout::GPOS_impl::PosLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, unsigned int&) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::RuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::SmallTypes>, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >&, void const*, hb_map_t const*&) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_offset_array_arg_t<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&> OT::$_39::operator()<OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >, hb_map_t const*&>(hb_subset_context_t*, OT::ArrayOf<OT::OffsetTo<OT::ChainRuleSet<OT::Layout::MediumTypes>, OT::NumType<true, unsigned int, 3u>, void, true>, OT::NumType<true, unsigned int, 3u> >&, void const*, hb_map_t const*&) const
311
}
312
HB_FUNCOBJ (subset_offset_array);
313
314
template<typename OutputArray>
315
struct subset_record_array_t
316
{
317
  subset_record_array_t (hb_subset_layout_context_t *c_, OutputArray* out_,
318
       const void *base_) : subset_layout_context (c_),
319
                out (out_), base (base_) {}
320
321
  template <typename T>
322
  void
323
  operator () (T&& record)
324
0
  {
325
0
    auto snap = subset_layout_context->subset_context->serializer->snapshot ();
326
0
    bool ret = record.subset (subset_layout_context, base);
327
0
    if (!ret) subset_layout_context->subset_context->serializer->revert (snap);
328
0
    else out->len++;
329
0
  }
Unexecuted instantiation: void OT::subset_record_array_t<OT::RecordArrayOf<OT::LangSys> >::operator()<OT::Record<OT::LangSys> const&>(OT::Record<OT::LangSys> const&)
Unexecuted instantiation: void OT::subset_record_array_t<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > >::operator()<OT::FeatureTableSubstitutionRecord const&>(OT::FeatureTableSubstitutionRecord const&)
Unexecuted instantiation: void OT::subset_record_array_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > >::operator()<OT::FeatureVariationRecord const&>(OT::FeatureVariationRecord const&)
Unexecuted instantiation: void OT::subset_record_array_t<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > >::operator()<OT::LookupVariationRecord const&>(OT::LookupVariationRecord const&)
330
331
  private:
332
  hb_subset_layout_context_t *subset_layout_context;
333
  OutputArray *out;
334
  const void *base;
335
};
336
337
template<typename OutputArray, typename Arg>
338
struct subset_record_array_arg_t
339
{
340
  subset_record_array_arg_t (hb_subset_layout_context_t *c_, OutputArray* out_,
341
           const void *base_,
342
           Arg &&arg_) : subset_layout_context (c_),
343
             out (out_), base (base_), arg (arg_) {}
344
345
  template <typename T>
346
  void
347
  operator () (T&& record)
348
0
  {
349
0
    auto snap = subset_layout_context->subset_context->serializer->snapshot ();
350
0
    bool ret = record.subset (subset_layout_context, base, arg);
351
0
    if (!ret) subset_layout_context->subset_context->serializer->revert (snap);
352
0
    else out->len++;
353
0
  }
Unexecuted instantiation: void OT::subset_record_array_arg_t<OT::RecordListOfFeature, OT::Feature const*&>::operator()<OT::Record<OT::Feature> const&>(OT::Record<OT::Feature> const&)
Unexecuted instantiation: void OT::subset_record_array_arg_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&>::operator()<OT::FeatureVariationRecord const&>(OT::FeatureVariationRecord const&)
354
355
  private:
356
  hb_subset_layout_context_t *subset_layout_context;
357
  OutputArray *out;
358
  const void *base;
359
  Arg &&arg;
360
};
361
362
/*
363
 * Helper to subset a RecordList/record array. Subsets each Record in the array and
364
 * discards the record if the subset operation returns false.
365
 */
366
struct
367
{
368
  template<typename OutputArray>
369
  subset_record_array_t<OutputArray>
370
  operator () (hb_subset_layout_context_t *c, OutputArray* out,
371
         const void *base) const
372
0
  { return subset_record_array_t<OutputArray> (c, out, base); }
Unexecuted instantiation: hb-face.cc:OT::subset_record_array_t<OT::RecordArrayOf<OT::LangSys> > OT::$_37::operator()<OT::RecordArrayOf<OT::LangSys> >(OT::hb_subset_layout_context_t*, OT::RecordArrayOf<OT::LangSys>*, void const*) const
Unexecuted instantiation: hb-face.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> >*, void const*) const
Unexecuted instantiation: hb-face.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-face.cc:OT::subset_record_array_t<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-font.cc:OT::subset_record_array_t<OT::RecordArrayOf<OT::LangSys> > OT::$_37::operator()<OT::RecordArrayOf<OT::LangSys> >(OT::hb_subset_layout_context_t*, OT::RecordArrayOf<OT::LangSys>*, void const*) const
Unexecuted instantiation: hb-font.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> >*, void const*) const
Unexecuted instantiation: hb-font.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-font.cc:OT::subset_record_array_t<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_record_array_t<OT::RecordArrayOf<OT::LangSys> > OT::$_36::operator()<OT::RecordArrayOf<OT::LangSys> >(OT::hb_subset_layout_context_t*, OT::RecordArrayOf<OT::LangSys>*, void const*) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > > OT::$_36::operator()<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> >*, void const*) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_36::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_record_array_t<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_36::operator()<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-font.cc:OT::subset_record_array_t<OT::RecordArrayOf<OT::LangSys> > OT::$_36::operator()<OT::RecordArrayOf<OT::LangSys> >(OT::hb_subset_layout_context_t*, OT::RecordArrayOf<OT::LangSys>*, void const*) const
Unexecuted instantiation: hb-ot-font.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > > OT::$_36::operator()<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> >*, void const*) const
Unexecuted instantiation: hb-ot-font.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_36::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-font.cc:OT::subset_record_array_t<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_36::operator()<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: VARC.cc:OT::subset_record_array_t<OT::RecordArrayOf<OT::LangSys> > OT::$_37::operator()<OT::RecordArrayOf<OT::LangSys> >(OT::hb_subset_layout_context_t*, OT::RecordArrayOf<OT::LangSys>*, void const*) const
Unexecuted instantiation: VARC.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> >*, void const*) const
Unexecuted instantiation: VARC.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: VARC.cc:OT::subset_record_array_t<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-metrics.cc:OT::subset_record_array_t<OT::RecordArrayOf<OT::LangSys> > OT::$_37::operator()<OT::RecordArrayOf<OT::LangSys> >(OT::hb_subset_layout_context_t*, OT::RecordArrayOf<OT::LangSys>*, void const*) const
Unexecuted instantiation: hb-ot-metrics.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> >*, void const*) const
Unexecuted instantiation: hb-ot-metrics.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-metrics.cc:OT::subset_record_array_t<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-shape.cc:OT::subset_record_array_t<OT::RecordArrayOf<OT::LangSys> > OT::$_37::operator()<OT::RecordArrayOf<OT::LangSys> >(OT::hb_subset_layout_context_t*, OT::RecordArrayOf<OT::LangSys>*, void const*) const
Unexecuted instantiation: hb-ot-shape.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> >*, void const*) const
Unexecuted instantiation: hb-ot-shape.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-shape.cc:OT::subset_record_array_t<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-var.cc:OT::subset_record_array_t<OT::RecordArrayOf<OT::LangSys> > OT::$_37::operator()<OT::RecordArrayOf<OT::LangSys> >(OT::hb_subset_layout_context_t*, OT::RecordArrayOf<OT::LangSys>*, void const*) const
Unexecuted instantiation: hb-ot-var.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> >*, void const*) const
Unexecuted instantiation: hb-ot-var.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-var.cc:OT::subset_record_array_t<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-static.cc:OT::subset_record_array_t<OT::RecordArrayOf<OT::LangSys> > OT::$_36::operator()<OT::RecordArrayOf<OT::LangSys> >(OT::hb_subset_layout_context_t*, OT::RecordArrayOf<OT::LangSys>*, void const*) const
Unexecuted instantiation: hb-static.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > > OT::$_36::operator()<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> >*, void const*) const
Unexecuted instantiation: hb-static.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_36::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-static.cc:OT::subset_record_array_t<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_36::operator()<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ft.cc:OT::subset_record_array_t<OT::RecordArrayOf<OT::LangSys> > OT::$_37::operator()<OT::RecordArrayOf<OT::LangSys> >(OT::hb_subset_layout_context_t*, OT::RecordArrayOf<OT::LangSys>*, void const*) const
Unexecuted instantiation: hb-ft.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> >*, void const*) const
Unexecuted instantiation: hb-ft.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ft.cc:OT::subset_record_array_t<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_record_array_t<OT::RecordArrayOf<OT::LangSys> > OT::$_36::operator()<OT::RecordArrayOf<OT::LangSys> >(OT::hb_subset_layout_context_t*, OT::RecordArrayOf<OT::LangSys>*, void const*) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > > OT::$_36::operator()<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> >*, void const*) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_36::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_record_array_t<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_36::operator()<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-aat-map.cc:OT::subset_record_array_t<OT::RecordArrayOf<OT::LangSys> > OT::$_37::operator()<OT::RecordArrayOf<OT::LangSys> >(OT::hb_subset_layout_context_t*, OT::RecordArrayOf<OT::LangSys>*, void const*) const
Unexecuted instantiation: hb-aat-map.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> >*, void const*) const
Unexecuted instantiation: hb-aat-map.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-aat-map.cc:OT::subset_record_array_t<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-cff1-table.cc:OT::subset_record_array_t<OT::RecordArrayOf<OT::LangSys> > OT::$_37::operator()<OT::RecordArrayOf<OT::LangSys> >(OT::hb_subset_layout_context_t*, OT::RecordArrayOf<OT::LangSys>*, void const*) const
Unexecuted instantiation: hb-ot-cff1-table.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> >*, void const*) const
Unexecuted instantiation: hb-ot-cff1-table.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-cff1-table.cc:OT::subset_record_array_t<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-cff2-table.cc:OT::subset_record_array_t<OT::RecordArrayOf<OT::LangSys> > OT::$_37::operator()<OT::RecordArrayOf<OT::LangSys> >(OT::hb_subset_layout_context_t*, OT::RecordArrayOf<OT::LangSys>*, void const*) const
Unexecuted instantiation: hb-ot-cff2-table.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> >*, void const*) const
Unexecuted instantiation: hb-ot-cff2-table.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-cff2-table.cc:OT::subset_record_array_t<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_record_array_t<OT::RecordArrayOf<OT::LangSys> > OT::$_36::operator()<OT::RecordArrayOf<OT::LangSys> >(OT::hb_subset_layout_context_t*, OT::RecordArrayOf<OT::LangSys>*, void const*) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > > OT::$_36::operator()<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> >*, void const*) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_36::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_record_array_t<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_36::operator()<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_record_array_t<OT::RecordArrayOf<OT::LangSys> > OT::$_37::operator()<OT::RecordArrayOf<OT::LangSys> >(OT::hb_subset_layout_context_t*, OT::RecordArrayOf<OT::LangSys>*, void const*) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> >*, void const*) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_record_array_t<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_37::operator()<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_record_array_t<OT::RecordArrayOf<OT::LangSys> > OT::$_36::operator()<OT::RecordArrayOf<OT::LangSys> >(OT::hb_subset_layout_context_t*, OT::RecordArrayOf<OT::LangSys>*, void const*) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > > OT::$_36::operator()<OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureTableSubstitutionRecord, OT::NumType<true, unsigned short, 2u> >*, void const*) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_record_array_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_36::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_record_array_t<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > > OT::$_36::operator()<OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> > >(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::LookupVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*) const
373
374
  /* Variant with one extra argument passed to subset */
375
  template<typename OutputArray, typename Arg>
376
  subset_record_array_arg_t<OutputArray, Arg>
377
  operator () (hb_subset_layout_context_t *c, OutputArray* out,
378
               const void *base, Arg &&arg) const
379
0
  { return subset_record_array_arg_t<OutputArray, Arg> (c, out, base, arg); }
Unexecuted instantiation: hb-face.cc:OT::subset_record_array_arg_t<OT::RecordListOfFeature, OT::Feature const*&> OT::$_37::operator()<OT::RecordListOfFeature, OT::Feature const*&>(OT::hb_subset_layout_context_t*, OT::RecordListOfFeature*, void const*, OT::Feature const*&) const
Unexecuted instantiation: hb-face.cc:OT::subset_record_array_arg_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&> OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&>(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*, bool&) const
Unexecuted instantiation: hb-font.cc:OT::subset_record_array_arg_t<OT::RecordListOfFeature, OT::Feature const*&> OT::$_37::operator()<OT::RecordListOfFeature, OT::Feature const*&>(OT::hb_subset_layout_context_t*, OT::RecordListOfFeature*, void const*, OT::Feature const*&) const
Unexecuted instantiation: hb-font.cc:OT::subset_record_array_arg_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&> OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&>(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*, bool&) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_record_array_arg_t<OT::RecordListOfFeature, OT::Feature const*&> OT::$_36::operator()<OT::RecordListOfFeature, OT::Feature const*&>(OT::hb_subset_layout_context_t*, OT::RecordListOfFeature*, void const*, OT::Feature const*&) const
Unexecuted instantiation: hb-ot-face.cc:OT::subset_record_array_arg_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&> OT::$_36::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&>(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*, bool&) const
Unexecuted instantiation: hb-ot-font.cc:OT::subset_record_array_arg_t<OT::RecordListOfFeature, OT::Feature const*&> OT::$_36::operator()<OT::RecordListOfFeature, OT::Feature const*&>(OT::hb_subset_layout_context_t*, OT::RecordListOfFeature*, void const*, OT::Feature const*&) const
Unexecuted instantiation: hb-ot-font.cc:OT::subset_record_array_arg_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&> OT::$_36::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&>(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*, bool&) const
Unexecuted instantiation: VARC.cc:OT::subset_record_array_arg_t<OT::RecordListOfFeature, OT::Feature const*&> OT::$_37::operator()<OT::RecordListOfFeature, OT::Feature const*&>(OT::hb_subset_layout_context_t*, OT::RecordListOfFeature*, void const*, OT::Feature const*&) const
Unexecuted instantiation: VARC.cc:OT::subset_record_array_arg_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&> OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&>(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*, bool&) const
Unexecuted instantiation: hb-ot-metrics.cc:OT::subset_record_array_arg_t<OT::RecordListOfFeature, OT::Feature const*&> OT::$_37::operator()<OT::RecordListOfFeature, OT::Feature const*&>(OT::hb_subset_layout_context_t*, OT::RecordListOfFeature*, void const*, OT::Feature const*&) const
Unexecuted instantiation: hb-ot-metrics.cc:OT::subset_record_array_arg_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&> OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&>(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*, bool&) const
Unexecuted instantiation: hb-ot-shape.cc:OT::subset_record_array_arg_t<OT::RecordListOfFeature, OT::Feature const*&> OT::$_37::operator()<OT::RecordListOfFeature, OT::Feature const*&>(OT::hb_subset_layout_context_t*, OT::RecordListOfFeature*, void const*, OT::Feature const*&) const
Unexecuted instantiation: hb-ot-shape.cc:OT::subset_record_array_arg_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&> OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&>(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*, bool&) const
Unexecuted instantiation: hb-ot-var.cc:OT::subset_record_array_arg_t<OT::RecordListOfFeature, OT::Feature const*&> OT::$_37::operator()<OT::RecordListOfFeature, OT::Feature const*&>(OT::hb_subset_layout_context_t*, OT::RecordListOfFeature*, void const*, OT::Feature const*&) const
Unexecuted instantiation: hb-ot-var.cc:OT::subset_record_array_arg_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&> OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&>(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*, bool&) const
Unexecuted instantiation: hb-static.cc:OT::subset_record_array_arg_t<OT::RecordListOfFeature, OT::Feature const*&> OT::$_36::operator()<OT::RecordListOfFeature, OT::Feature const*&>(OT::hb_subset_layout_context_t*, OT::RecordListOfFeature*, void const*, OT::Feature const*&) const
Unexecuted instantiation: hb-static.cc:OT::subset_record_array_arg_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&> OT::$_36::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&>(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*, bool&) const
Unexecuted instantiation: hb-ft.cc:OT::subset_record_array_arg_t<OT::RecordListOfFeature, OT::Feature const*&> OT::$_37::operator()<OT::RecordListOfFeature, OT::Feature const*&>(OT::hb_subset_layout_context_t*, OT::RecordListOfFeature*, void const*, OT::Feature const*&) const
Unexecuted instantiation: hb-ft.cc:OT::subset_record_array_arg_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&> OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&>(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*, bool&) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_record_array_arg_t<OT::RecordListOfFeature, OT::Feature const*&> OT::$_36::operator()<OT::RecordListOfFeature, OT::Feature const*&>(OT::hb_subset_layout_context_t*, OT::RecordListOfFeature*, void const*, OT::Feature const*&) const
Unexecuted instantiation: hb-aat-layout.cc:OT::subset_record_array_arg_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&> OT::$_36::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&>(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*, bool&) const
Unexecuted instantiation: hb-aat-map.cc:OT::subset_record_array_arg_t<OT::RecordListOfFeature, OT::Feature const*&> OT::$_37::operator()<OT::RecordListOfFeature, OT::Feature const*&>(OT::hb_subset_layout_context_t*, OT::RecordListOfFeature*, void const*, OT::Feature const*&) const
Unexecuted instantiation: hb-aat-map.cc:OT::subset_record_array_arg_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&> OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&>(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*, bool&) const
Unexecuted instantiation: hb-ot-cff1-table.cc:OT::subset_record_array_arg_t<OT::RecordListOfFeature, OT::Feature const*&> OT::$_37::operator()<OT::RecordListOfFeature, OT::Feature const*&>(OT::hb_subset_layout_context_t*, OT::RecordListOfFeature*, void const*, OT::Feature const*&) const
Unexecuted instantiation: hb-ot-cff1-table.cc:OT::subset_record_array_arg_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&> OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&>(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*, bool&) const
Unexecuted instantiation: hb-ot-cff2-table.cc:OT::subset_record_array_arg_t<OT::RecordListOfFeature, OT::Feature const*&> OT::$_37::operator()<OT::RecordListOfFeature, OT::Feature const*&>(OT::hb_subset_layout_context_t*, OT::RecordListOfFeature*, void const*, OT::Feature const*&) const
Unexecuted instantiation: hb-ot-cff2-table.cc:OT::subset_record_array_arg_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&> OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&>(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*, bool&) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_record_array_arg_t<OT::RecordListOfFeature, OT::Feature const*&> OT::$_36::operator()<OT::RecordListOfFeature, OT::Feature const*&>(OT::hb_subset_layout_context_t*, OT::RecordListOfFeature*, void const*, OT::Feature const*&) const
Unexecuted instantiation: hb-ot-layout.cc:OT::subset_record_array_arg_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&> OT::$_36::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&>(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*, bool&) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_record_array_arg_t<OT::RecordListOfFeature, OT::Feature const*&> OT::$_37::operator()<OT::RecordListOfFeature, OT::Feature const*&>(OT::hb_subset_layout_context_t*, OT::RecordListOfFeature*, void const*, OT::Feature const*&) const
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::subset_record_array_arg_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&> OT::$_37::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&>(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*, bool&) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_record_array_arg_t<OT::RecordListOfFeature, OT::Feature const*&> OT::$_36::operator()<OT::RecordListOfFeature, OT::Feature const*&>(OT::hb_subset_layout_context_t*, OT::RecordListOfFeature*, void const*, OT::Feature const*&) const
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::subset_record_array_arg_t<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&> OT::$_36::operator()<OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >, bool&>(OT::hb_subset_layout_context_t*, OT::ArrayOf<OT::FeatureVariationRecord, OT::NumType<true, unsigned int, 4u> >*, void const*, bool&) const
380
}
381
HB_FUNCOBJ (subset_record_array);
382
383
384
template<typename OutputArray>
385
struct serialize_math_record_array_t
386
{
387
  serialize_math_record_array_t (hb_serialize_context_t *serialize_context_,
388
                         OutputArray& out_,
389
                         const void *base_,
390
                         const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *variation_map_) :
391
                                              serialize_context (serialize_context_),
392
                                              out (out_), base (base_), variation_map (variation_map_) {}
393
394
  template <typename T>
395
  bool operator () (T&& record)
396
  {
397
    if (!serialize_context->copy (record, base, variation_map)) return false;
398
    out.len++;
399
    return true;
400
  }
401
402
  private:
403
  hb_serialize_context_t *serialize_context;
404
  OutputArray &out;
405
  const void *base;
406
  const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *variation_map;
407
};
408
409
/*
410
 * Helper to serialize an array of MATH records.
411
 */
412
struct
413
{
414
  template<typename OutputArray>
415
  serialize_math_record_array_t<OutputArray>
416
  operator () (hb_serialize_context_t *serialize_context, OutputArray& out,
417
               const void *base,
418
               const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *variation_map) const
419
  { return serialize_math_record_array_t<OutputArray> (serialize_context, out, base, variation_map); }
420
421
}
422
HB_FUNCOBJ (serialize_math_record_array);
423
424
/*
425
 *
426
 * OpenType Layout Common Table Formats
427
 *
428
 */
429
430
431
/*
432
 * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
433
 */
434
435
struct IndexArray : Array16Of<Index>
436
{
437
  bool intersects (const hb_map_t *indexes) const
438
0
  { return hb_any (*this, indexes); }
439
440
  template <typename Iterator,
441
      hb_requires (hb_is_iterator (Iterator))>
442
  void serialize (hb_serialize_context_t *c,
443
      hb_subset_layout_context_t *l,
444
      Iterator it)
445
0
  {
446
0
    if (!it) return;
447
0
    if (unlikely (!c->extend_min ((*this)))) return;
448
0
449
0
    for (const auto _ : it)
450
0
    {
451
0
      if (!l->visitLookupIndex()) break;
452
0
453
0
      Index i;
454
0
      i = _;
455
0
      c->copy (i);
456
0
      this->len++;
457
0
    }
458
0
  }
Unexecuted instantiation: hb-face.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tIN23hb_bit_set_invertible_t6iter_tERPK8hb_map_tRK4$_17LPv0EES9_L24hb_function_sortedness_t0ELSD_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSD_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESI_
Unexecuted instantiation: hb-face.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tI10hb_array_tIKNS_5IndexEERPK8hb_map_tRK4$_17LPv0EESB_L24hb_function_sortedness_t0ELSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSK_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESK_
Unexecuted instantiation: hb-font.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tIN23hb_bit_set_invertible_t6iter_tERPK8hb_map_tRK4$_17LPv0EES9_L24hb_function_sortedness_t0ELSD_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSD_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESI_
Unexecuted instantiation: hb-font.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tI10hb_array_tIKNS_5IndexEERPK8hb_map_tRK4$_17LPv0EESB_L24hb_function_sortedness_t0ELSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSK_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESK_
Unexecuted instantiation: hb-ot-face.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tIN23hb_bit_set_invertible_t6iter_tERPK8hb_map_tRK4$_17LPv0EES9_L24hb_function_sortedness_t0ELSD_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSD_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESI_
Unexecuted instantiation: hb-ot-face.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tI10hb_array_tIKNS_5IndexEERPK8hb_map_tRK4$_17LPv0EESB_L24hb_function_sortedness_t0ELSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSK_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESK_
Unexecuted instantiation: hb-ot-font.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tIN23hb_bit_set_invertible_t6iter_tERPK8hb_map_tRK4$_17LPv0EES9_L24hb_function_sortedness_t0ELSD_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSD_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESI_
Unexecuted instantiation: hb-ot-font.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tI10hb_array_tIKNS_5IndexEERPK8hb_map_tRK4$_17LPv0EESB_L24hb_function_sortedness_t0ELSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSK_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESK_
Unexecuted instantiation: VARC.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tIN23hb_bit_set_invertible_t6iter_tERPK8hb_map_tRK4$_20LPv0EES9_L24hb_function_sortedness_t0ELSD_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSD_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESI_
Unexecuted instantiation: VARC.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tI10hb_array_tIKNS_5IndexEERPK8hb_map_tRK4$_20LPv0EESB_L24hb_function_sortedness_t0ELSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSK_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESK_
Unexecuted instantiation: hb-ot-metrics.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tIN23hb_bit_set_invertible_t6iter_tERPK8hb_map_tRK4$_17LPv0EES9_L24hb_function_sortedness_t0ELSD_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSD_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESI_
Unexecuted instantiation: hb-ot-metrics.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tI10hb_array_tIKNS_5IndexEERPK8hb_map_tRK4$_17LPv0EESB_L24hb_function_sortedness_t0ELSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSK_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESK_
Unexecuted instantiation: hb-ot-shape.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tIN23hb_bit_set_invertible_t6iter_tERPK8hb_map_tRK4$_17LPv0EES9_L24hb_function_sortedness_t0ELSD_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSD_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESI_
Unexecuted instantiation: hb-ot-shape.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tI10hb_array_tIKNS_5IndexEERPK8hb_map_tRK4$_17LPv0EESB_L24hb_function_sortedness_t0ELSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSK_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESK_
Unexecuted instantiation: hb-ot-var.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tIN23hb_bit_set_invertible_t6iter_tERPK8hb_map_tRK4$_17LPv0EES9_L24hb_function_sortedness_t0ELSD_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSD_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESI_
Unexecuted instantiation: hb-ot-var.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tI10hb_array_tIKNS_5IndexEERPK8hb_map_tRK4$_17LPv0EESB_L24hb_function_sortedness_t0ELSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSK_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESK_
Unexecuted instantiation: hb-static.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tIN23hb_bit_set_invertible_t6iter_tERPK8hb_map_tRK4$_17LPv0EES9_L24hb_function_sortedness_t0ELSD_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSD_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESI_
Unexecuted instantiation: hb-static.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tI10hb_array_tIKNS_5IndexEERPK8hb_map_tRK4$_17LPv0EESB_L24hb_function_sortedness_t0ELSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSK_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESK_
Unexecuted instantiation: hb-ft.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tIN23hb_bit_set_invertible_t6iter_tERPK8hb_map_tRK4$_17LPv0EES9_L24hb_function_sortedness_t0ELSD_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSD_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESI_
Unexecuted instantiation: hb-ft.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tI10hb_array_tIKNS_5IndexEERPK8hb_map_tRK4$_17LPv0EESB_L24hb_function_sortedness_t0ELSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSK_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESK_
Unexecuted instantiation: hb-aat-layout.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tIN23hb_bit_set_invertible_t6iter_tERPK8hb_map_tRK4$_17LPv0EES9_L24hb_function_sortedness_t0ELSD_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSD_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESI_
Unexecuted instantiation: hb-aat-layout.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tI10hb_array_tIKNS_5IndexEERPK8hb_map_tRK4$_17LPv0EESB_L24hb_function_sortedness_t0ELSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSK_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESK_
Unexecuted instantiation: hb-aat-map.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tIN23hb_bit_set_invertible_t6iter_tERPK8hb_map_tRK4$_17LPv0EES9_L24hb_function_sortedness_t0ELSD_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSD_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESI_
Unexecuted instantiation: hb-aat-map.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tI10hb_array_tIKNS_5IndexEERPK8hb_map_tRK4$_17LPv0EESB_L24hb_function_sortedness_t0ELSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSK_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESK_
Unexecuted instantiation: hb-ot-cff1-table.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tIN23hb_bit_set_invertible_t6iter_tERPK8hb_map_tRK4$_17LPv0EES9_L24hb_function_sortedness_t0ELSD_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSD_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESI_
Unexecuted instantiation: hb-ot-cff1-table.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tI10hb_array_tIKNS_5IndexEERPK8hb_map_tRK4$_17LPv0EESB_L24hb_function_sortedness_t0ELSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSK_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESK_
Unexecuted instantiation: hb-ot-cff2-table.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tIN23hb_bit_set_invertible_t6iter_tERPK8hb_map_tRK4$_17LPv0EES9_L24hb_function_sortedness_t0ELSD_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSD_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESI_
Unexecuted instantiation: hb-ot-cff2-table.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tI10hb_array_tIKNS_5IndexEERPK8hb_map_tRK4$_17LPv0EESB_L24hb_function_sortedness_t0ELSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSK_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESK_
Unexecuted instantiation: hb-ot-layout.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tIN23hb_bit_set_invertible_t6iter_tERPK8hb_map_tRK4$_17LPv0EES9_L24hb_function_sortedness_t0ELSD_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSD_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESI_
Unexecuted instantiation: hb-ot-layout.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tI10hb_array_tIKNS_5IndexEERPK8hb_map_tRK4$_17LPv0EESB_L24hb_function_sortedness_t0ELSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSK_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESK_
Unexecuted instantiation: hb-ot-shaper-arabic.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tIN23hb_bit_set_invertible_t6iter_tERPK8hb_map_tRK4$_17LPv0EES9_L24hb_function_sortedness_t0ELSD_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSD_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESI_
Unexecuted instantiation: hb-ot-shaper-arabic.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tI10hb_array_tIKNS_5IndexEERPK8hb_map_tRK4$_17LPv0EESB_L24hb_function_sortedness_t0ELSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSK_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESK_
Unexecuted instantiation: hb-ot-shape-fallback.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tIN23hb_bit_set_invertible_t6iter_tERPK8hb_map_tRK4$_17LPv0EES9_L24hb_function_sortedness_t0ELSD_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSD_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESI_
Unexecuted instantiation: hb-ot-shape-fallback.cc:_ZN2OT10IndexArray9serializeI13hb_map_iter_tI16hb_filter_iter_tI10hb_array_tIKNS_5IndexEERPK8hb_map_tRK4$_17LPv0EESB_L24hb_function_sortedness_t0ELSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSK_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tPNS_26hb_subset_layout_context_tESK_
459
460
  unsigned int get_indexes (unsigned int start_offset,
461
          unsigned int *_count /* IN/OUT */,
462
          unsigned int *_indexes /* OUT */) const
463
3.67k
  {
464
3.67k
    if (_count && _indexes)
465
237
    {
466
237
      + this->as_array ().sub_array (start_offset, _count)
467
237
      | hb_sink (hb_array (_indexes, *_count))
468
237
      ;
469
237
    }
470
3.67k
    return this->len;
471
3.67k
  }
472
473
  void add_indexes_to (hb_set_t* output /* OUT */) const
474
0
  {
475
0
    output->add_array (as_array ());
476
0
  }
477
};
478
479
480
/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
481
struct FeatureParamsSize
482
{
483
  bool sanitize (hb_sanitize_context_t *c) const
484
0
  {
485
0
    TRACE_SANITIZE (this);
486
0
    if (unlikely (!c->check_struct (this))) return_trace (false);
487
0
    hb_barrier ();
488
489
    /* This subtable has some "history", if you will.  Some earlier versions of
490
     * Adobe tools calculated the offset of the FeatureParams subtable from the
491
     * beginning of the FeatureList table!  Now, that is dealt with in the
492
     * Feature implementation.  But we still need to be able to tell junk from
493
     * real data.  Note: We don't check that the nameID actually exists.
494
     *
495
     * Read Roberts wrote on 9/15/06 on opentype-list@indx.co.uk :
496
     *
497
     * Yes, it is correct that a new version of the AFDKO (version 2.0) will be
498
     * coming out soon, and that the makeotf program will build a font with a
499
     * 'size' feature that is correct by the specification.
500
     *
501
     * The specification for this feature tag is in the "OpenType Layout Tag
502
     * Registry". You can see a copy of this at:
503
     * https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size
504
     *
505
     * Here is one set of rules to determine if the 'size' feature is built
506
     * correctly, or as by the older versions of MakeOTF. You may be able to do
507
     * better.
508
     *
509
     * Assume that the offset to the size feature is according to specification,
510
     * and make the following value checks. If it fails, assume the size
511
     * feature is calculated as versions of MakeOTF before the AFDKO 2.0 built it.
512
     * If this fails, reject the 'size' feature. The older makeOTF's calculated the
513
     * offset from the beginning of the FeatureList table, rather than from the
514
     * beginning of the 'size' Feature table.
515
     *
516
     * If "design size" == 0:
517
     *     fails check
518
     *
519
     * Else if ("subfamily identifier" == 0 and
520
     *     "range start" == 0 and
521
     *     "range end" == 0 and
522
     *     "range start" == 0 and
523
     *     "menu name ID" == 0)
524
     *     passes check: this is the format used when there is a design size
525
     * specified, but there is no recommended size range.
526
     *
527
     * Else if ("design size" <  "range start" or
528
     *     "design size" >   "range end" or
529
     *     "range end" <= "range start" or
530
     *     "menu name ID"  < 256 or
531
     *     "menu name ID"  > 32767 or
532
     *     menu name ID is not a name ID which is actually in the name table)
533
     *     fails test
534
     * Else
535
     *     passes test.
536
     */
537
538
0
    if (!designSize)
539
0
      return_trace (false);
540
0
    else if (subfamilyID == 0 &&
541
0
       subfamilyNameID == 0 &&
542
0
       rangeStart == 0 &&
543
0
       rangeEnd == 0)
544
0
      return_trace (true);
545
0
    else if (designSize < rangeStart ||
546
0
       designSize > rangeEnd ||
547
0
       subfamilyNameID < 256 ||
548
0
       subfamilyNameID > 32767)
549
0
      return_trace (false);
550
0
    else
551
0
      return_trace (true);
552
0
  }
553
554
  void collect_name_ids (hb_set_t *nameids_to_retain /* OUT */) const
555
0
  { nameids_to_retain->add (subfamilyNameID); }
556
557
  bool subset (hb_subset_context_t *c) const
558
0
  {
559
0
    TRACE_SUBSET (this);
560
0
    return_trace ((bool) c->serializer->embed (*this));
561
0
  }
562
563
  HBUINT16  designSize; /* Represents the design size in 720/inch
564
         * units (decipoints).  The design size entry
565
         * must be non-zero.  When there is a design
566
         * size but no recommended size range, the
567
         * rest of the array will consist of zeros. */
568
  HBUINT16  subfamilyID;  /* Has no independent meaning, but serves
569
         * as an identifier that associates fonts
570
         * in a subfamily. All fonts which share a
571
         * Preferred or Font Family name and which
572
         * differ only by size range shall have the
573
         * same subfamily value, and no fonts which
574
         * differ in weight or style shall have the
575
         * same subfamily value. If this value is
576
         * zero, the remaining fields in the array
577
         * will be ignored. */
578
  NameID  subfamilyNameID;/* If the preceding value is non-zero, this
579
         * value must be set in the range 256 - 32767
580
         * (inclusive). It records the value of a
581
         * field in the name table, which must
582
         * contain English-language strings encoded
583
         * in Windows Unicode and Macintosh Roman,
584
         * and may contain additional strings
585
         * localized to other scripts and languages.
586
         * Each of these strings is the name an
587
         * application should use, in combination
588
         * with the family name, to represent the
589
         * subfamily in a menu.  Applications will
590
         * choose the appropriate version based on
591
         * their selection criteria. */
592
  HBUINT16  rangeStart; /* Large end of the recommended usage range
593
         * (inclusive), stored in 720/inch units
594
         * (decipoints). */
595
  HBUINT16  rangeEnd; /* Small end of the recommended usage range
596
           (exclusive), stored in 720/inch units
597
         * (decipoints). */
598
  public:
599
  DEFINE_SIZE_STATIC (10);
600
};
601
602
/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#ssxx */
603
struct FeatureParamsStylisticSet
604
{
605
  bool sanitize (hb_sanitize_context_t *c) const
606
0
  {
607
0
    TRACE_SANITIZE (this);
608
    /* Right now minorVersion is at zero.  Which means, any table supports
609
     * the uiNameID field. */
610
0
    return_trace (c->check_struct (this));
611
0
  }
612
613
  void collect_name_ids (hb_set_t *nameids_to_retain /* OUT */) const
614
0
  { nameids_to_retain->add (uiNameID); }
615
616
  bool subset (hb_subset_context_t *c) const
617
0
  {
618
0
    TRACE_SUBSET (this);
619
0
    return_trace ((bool) c->serializer->embed (*this));
620
0
  }
621
622
  HBUINT16  version;  /* (set to 0): This corresponds to a “minor”
623
         * version number. Additional data may be
624
         * added to the end of this Feature Parameters
625
         * table in the future. */
626
627
  NameID  uiNameID; /* The 'name' table name ID that specifies a
628
         * string (or strings, for multiple languages)
629
         * for a user-interface label for this
630
         * feature.  The values of uiLabelNameId and
631
         * sampleTextNameId are expected to be in the
632
         * font-specific name ID range (256-32767),
633
         * though that is not a requirement in this
634
         * Feature Parameters specification. The
635
         * user-interface label for the feature can
636
         * be provided in multiple languages. An
637
         * English string should be included as a
638
         * fallback. The string should be kept to a
639
         * minimal length to fit comfortably with
640
         * different application interfaces. */
641
  public:
642
  DEFINE_SIZE_STATIC (4);
643
};
644
645
/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_ae#cv01-cv99 */
646
struct FeatureParamsCharacterVariants
647
{
648
  unsigned
649
  get_characters (unsigned start_offset, unsigned *char_count, hb_codepoint_t *chars) const
650
0
  {
651
0
    if (char_count && chars)
652
0
    {
653
0
      + characters.as_array ().sub_array (start_offset, char_count)
654
0
      | hb_sink (hb_array (chars, *char_count))
655
0
      ;
656
0
    }
657
0
    return characters.len;
658
0
  }
659
660
  size_t get_size () const
661
0
  { return hb_unsigned_mul_add_saturate (characters.len, HBUINT24::static_size, min_size); }
662
663
  void collect_name_ids (hb_set_t *nameids_to_retain /* OUT */) const
664
0
  {
665
0
    if (featUILableNameID) nameids_to_retain->add (featUILableNameID);
666
0
    if (featUITooltipTextNameID) nameids_to_retain->add (featUITooltipTextNameID);
667
0
    if (sampleTextNameID) nameids_to_retain->add (sampleTextNameID);
668
0
669
0
    if (!firstParamUILabelNameID || !numNamedParameters || numNamedParameters >= 0x7FFF)
670
0
      return;
671
0
672
0
    unsigned last_name_id = (unsigned) firstParamUILabelNameID + (unsigned) numNamedParameters - 1;
673
0
    nameids_to_retain->add_range (firstParamUILabelNameID, last_name_id);
674
0
  }
675
676
  bool subset (hb_subset_context_t *c) const
677
0
  {
678
0
    TRACE_SUBSET (this);
679
0
    return_trace ((bool) c->serializer->embed (*this));
680
0
  }
681
682
  bool sanitize (hb_sanitize_context_t *c) const
683
0
  {
684
0
    TRACE_SANITIZE (this);
685
0
    return_trace (c->check_struct (this) &&
686
0
      characters.sanitize (c));
687
0
  }
688
689
  HBUINT16  format;     /* Format number is set to 0. */
690
  NameID  featUILableNameID;  /* The ‘name’ table name ID that
691
           * specifies a string (or strings,
692
           * for multiple languages) for a
693
           * user-interface label for this
694
           * feature. (May be NULL.) */
695
  NameID  featUITooltipTextNameID;/* The ‘name’ table name ID that
696
           * specifies a string (or strings,
697
           * for multiple languages) that an
698
           * application can use for tooltip
699
           * text for this feature. (May be
700
           * nullptr.) */
701
  NameID  sampleTextNameID; /* The ‘name’ table name ID that
702
           * specifies sample text that
703
           * illustrates the effect of this
704
           * feature. (May be NULL.) */
705
  HBUINT16  numNamedParameters; /* Number of named parameters. (May
706
           * be zero.) */
707
  NameID  firstParamUILabelNameID;/* The first ‘name’ table name ID
708
           * used to specify strings for
709
           * user-interface labels for the
710
           * feature parameters. (Must be zero
711
           * if numParameters is zero.) */
712
  Array16Of<HBUINT24>
713
    characters;   /* Array of the Unicode Scalar Value
714
           * of the characters for which this
715
           * feature provides glyph variants.
716
           * (May be zero.) */
717
  public:
718
  DEFINE_SIZE_ARRAY (14, characters);
719
};
720
721
struct FeatureParams
722
{
723
  bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) const
724
0
  {
725
#ifdef HB_NO_LAYOUT_FEATURE_PARAMS
726
    return true;
727
#endif
728
0
    TRACE_SANITIZE (this);
729
0
    if (tag == HB_TAG ('s','i','z','e') && hb_barrier ())
730
0
      return_trace (u.size.sanitize (c));
731
0
    if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
732
0
      return_trace (u.stylisticSet.sanitize (c));
733
0
    if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
734
0
      return_trace (u.characterVariants.sanitize (c));
735
0
    return_trace (true);
736
0
  }
737
738
  void collect_name_ids (hb_tag_t tag, hb_set_t *nameids_to_retain /* OUT */) const
739
0
  {
740
0
#ifdef HB_NO_LAYOUT_FEATURE_PARAMS
741
0
    return;
742
0
#endif
743
0
    if (tag == HB_TAG ('s','i','z','e') && hb_barrier ())
744
0
      return (u.size.collect_name_ids (nameids_to_retain));
745
0
    if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
746
0
      return (u.stylisticSet.collect_name_ids (nameids_to_retain));
747
0
    if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
748
0
      return (u.characterVariants.collect_name_ids (nameids_to_retain));
749
0
  }
750
751
  bool subset (hb_subset_context_t *c, const Tag* tag) const
752
0
  {
753
0
#ifdef HB_NO_LAYOUT_FEATURE_PARAMS
754
0
    return false;
755
0
#endif
756
0
    TRACE_SUBSET (this);
757
0
    if (!tag) return_trace (false);
758
0
    if (*tag == HB_TAG ('s','i','z','e') && hb_barrier ())
759
0
      return_trace (u.size.subset (c));
760
0
    if ((*tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
761
0
      return_trace (u.stylisticSet.subset (c));
762
0
    if ((*tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
763
0
      return_trace (u.characterVariants.subset (c));
764
0
    return_trace (false);
765
0
  }
766
767
#ifndef HB_NO_LAYOUT_FEATURE_PARAMS
768
  const FeatureParamsSize& get_size_params (hb_tag_t tag) const
769
0
  {
770
0
    if (tag == HB_TAG ('s','i','z','e') && hb_barrier ())
771
0
      return u.size;
772
0
    return Null (FeatureParamsSize);
773
0
  }
774
  const FeatureParamsStylisticSet& get_stylistic_set_params (hb_tag_t tag) const
775
0
  {
776
0
    if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
777
0
      return u.stylisticSet;
778
0
    return Null (FeatureParamsStylisticSet);
779
0
  }
780
  const FeatureParamsCharacterVariants& get_character_variants_params (hb_tag_t tag) const
781
0
  {
782
0
    if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
783
0
      return u.characterVariants;
784
0
    return Null (FeatureParamsCharacterVariants);
785
0
  }
786
#endif
787
788
  private:
789
  union {
790
  FeatureParamsSize     size;
791
  FeatureParamsStylisticSet   stylisticSet;
792
  FeatureParamsCharacterVariants  characterVariants;
793
  } u;
794
  public:
795
  DEFINE_SIZE_MIN (0);
796
};
797
798
struct Record_sanitize_closure_t {
799
  hb_tag_t tag;
800
  const void *list_base;
801
};
802
803
struct Feature
804
{
805
  unsigned int get_lookup_count () const
806
0
  { return lookupIndex.len; }
807
  hb_tag_t get_lookup_index (unsigned int i) const
808
0
  { return lookupIndex[i]; }
809
  unsigned int get_lookup_indexes (unsigned int start_index,
810
           unsigned int *lookup_count /* IN/OUT */,
811
           unsigned int *lookup_tags /* OUT */) const
812
109
  { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
813
  void add_lookup_indexes_to (hb_set_t *lookup_indexes) const
814
0
  { lookupIndex.add_indexes_to (lookup_indexes); }
815
816
  const FeatureParams &get_feature_params () const
817
0
  { return this+featureParams; }
818
819
  bool intersects_lookup_indexes (const hb_map_t *lookup_indexes) const
820
0
  { return lookupIndex.intersects (lookup_indexes); }
821
822
  void collect_name_ids (hb_tag_t tag, hb_set_t *nameids_to_retain /* OUT */) const
823
0
  {
824
0
    if (featureParams)
825
0
      get_feature_params ().collect_name_ids (tag, nameids_to_retain);
826
0
  }
827
828
  bool subset (hb_subset_context_t         *c,
829
         hb_subset_layout_context_t  *l,
830
         const Tag                   *tag = nullptr) const
831
0
  {
832
0
    TRACE_SUBSET (this);
833
0
    auto *out = c->serializer->start_embed (*this);
834
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
835
0
836
0
    out->featureParams.serialize_subset (c, featureParams, this, tag);
837
0
838
0
    hb::shared_ptr<hb_set_t> *lookup_variations;
839
0
    if (l->cur_feature_index != Index::NOT_FOUND_INDEX &&
840
0
  l->lookup_variations->has (l->cur_feature_index, &lookup_variations))
841
0
    {
842
0
      auto it =
843
0
      + hb_iter (**lookup_variations)
844
0
      | hb_filter (l->lookup_index_map)
845
0
      | hb_map (l->lookup_index_map)
846
0
      ;
847
0
      out->lookupIndex.serialize (c->serializer, l, it);
848
0
    }
849
0
    else
850
0
    {
851
0
      auto it =
852
0
      + hb_iter (lookupIndex)
853
0
      | hb_filter (l->lookup_index_map)
854
0
      | hb_map (l->lookup_index_map)
855
0
      ;
856
0
      out->lookupIndex.serialize (c->serializer, l, it);
857
0
    }
858
0
    // The decision to keep or drop this feature is already made before we get here
859
0
    // so always retain it.
860
0
    return_trace (true);
861
0
  }
862
863
  bool sanitize (hb_sanitize_context_t *c,
864
     const Record_sanitize_closure_t *closure = nullptr) const
865
4.83k
  {
866
4.83k
    TRACE_SANITIZE (this);
867
4.83k
    return_trace (c->check_struct (this) &&
868
4.83k
      featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE) &&
869
4.83k
      lookupIndex.sanitize (c));
870
4.83k
  }
871
872
  Offset16To<FeatureParams>
873
     featureParams; /* Offset to Feature Parameters table (if one
874
         * has been defined for the feature), relative
875
         * to the beginning of the Feature Table; = Null
876
         * if not required */
877
  IndexArray   lookupIndex; /* Array of LookupList indices */
878
  public:
879
  DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex);
880
};
881
882
template <typename Type>
883
struct Record
884
{
885
13.9k
  int cmp (hb_tag_t a) const { return tag.cmp (a); }
OT::Record<OT::LangSys>::cmp(unsigned int) const
Line
Count
Source
885
138
  int cmp (hb_tag_t a) const { return tag.cmp (a); }
OT::Record<OT::Script>::cmp(unsigned int) const
Line
Count
Source
885
13.8k
  int cmp (hb_tag_t a) const { return tag.cmp (a); }
Unexecuted instantiation: OT::Record<OT::Feature>::cmp(unsigned int) const
886
887
  bool subset (hb_subset_layout_context_t *c, const void *base, const void *f_sub = nullptr) const
888
0
  {
889
0
    TRACE_SUBSET (this);
890
0
    auto *out = c->subset_context->serializer->embed (this);
891
0
    if (unlikely (!out)) return_trace (false);
892
0
893
0
    if (!f_sub)
894
0
      return_trace (out->offset.serialize_subset (c->subset_context, offset, base, c, &tag));
895
0
896
0
    const Feature& f = *reinterpret_cast<const Feature *> (f_sub);
897
0
    auto *s = c->subset_context->serializer;
898
0
    s->push ();
899
0
900
0
    out->offset = 0;
901
0
    bool ret = f.subset (c->subset_context, c, &tag);
902
0
    if (ret)
903
0
      s->add_link (out->offset, s->pop_pack ());
904
0
    else
905
0
      s->pop_discard ();
906
0
907
0
    return_trace (ret);
908
0
  }
Unexecuted instantiation: OT::Record<OT::Feature>::subset(OT::hb_subset_layout_context_t*, void const*, void const*) const
Unexecuted instantiation: OT::Record<OT::LangSys>::subset(OT::hb_subset_layout_context_t*, void const*, void const*) const
Unexecuted instantiation: OT::Record<OT::Script>::subset(OT::hb_subset_layout_context_t*, void const*, void const*) const
909
910
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
911
8.62k
  {
912
8.62k
    TRACE_SANITIZE (this);
913
8.62k
    const Record_sanitize_closure_t closure = {tag, base};
914
8.62k
    return_trace (c->check_struct (this) &&
915
8.62k
      offset.sanitize (c, base, &closure));
916
8.62k
  }
OT::Record<OT::LangSys>::sanitize(hb_sanitize_context_t*, void const*) const
Line
Count
Source
911
396
  {
912
396
    TRACE_SANITIZE (this);
913
396
    const Record_sanitize_closure_t closure = {tag, base};
914
396
    return_trace (c->check_struct (this) &&
915
396
      offset.sanitize (c, base, &closure));
916
396
  }
OT::Record<OT::Script>::sanitize(hb_sanitize_context_t*, void const*) const
Line
Count
Source
911
3.39k
  {
912
3.39k
    TRACE_SANITIZE (this);
913
3.39k
    const Record_sanitize_closure_t closure = {tag, base};
914
3.39k
    return_trace (c->check_struct (this) &&
915
3.39k
      offset.sanitize (c, base, &closure));
916
3.39k
  }
OT::Record<OT::Feature>::sanitize(hb_sanitize_context_t*, void const*) const
Line
Count
Source
911
4.83k
  {
912
4.83k
    TRACE_SANITIZE (this);
913
4.83k
    const Record_sanitize_closure_t closure = {tag, base};
914
4.83k
    return_trace (c->check_struct (this) &&
915
4.83k
      offset.sanitize (c, base, &closure));
916
4.83k
  }
Unexecuted instantiation: OT::Record<OT::JstfLangSys>::sanitize(hb_sanitize_context_t*, void const*) const
917
918
  Tag           tag;            /* 4-byte Tag identifier */
919
  Offset16To<Type>
920
                offset;         /* Offset from beginning of object holding
921
                                 * the Record */
922
  public:
923
  DEFINE_SIZE_STATIC (6);
924
};
925
926
template <typename Type>
927
struct RecordArrayOf : SortedArray16Of<Record<Type>>
928
{
929
  const Offset16To<Type>& get_offset (unsigned int i) const
930
10.5k
  { return (*this)[i].offset; }
OT::RecordArrayOf<OT::Script>::get_offset(unsigned int) const
Line
Count
Source
930
10.3k
  { return (*this)[i].offset; }
OT::RecordArrayOf<OT::Feature>::get_offset(unsigned int) const
Line
Count
Source
930
218
  { return (*this)[i].offset; }
931
  Offset16To<Type>& get_offset (unsigned int i)
932
  { return (*this)[i].offset; }
933
  const Tag& get_tag (unsigned int i) const
934
133
  { return (*this)[i].tag; }
Unexecuted instantiation: OT::RecordArrayOf<OT::LangSys>::get_tag(unsigned int) const
OT::RecordArrayOf<OT::Feature>::get_tag(unsigned int) const
Line
Count
Source
934
133
  { return (*this)[i].tag; }
Unexecuted instantiation: OT::RecordArrayOf<OT::Script>::get_tag(unsigned int) const
935
  unsigned int get_tags (unsigned int start_offset,
936
                         unsigned int *record_count /* IN/OUT */,
937
                         hb_tag_t     *record_tags /* OUT */) const
938
0
  {
939
0
    if (record_count && record_tags)
940
0
    {
941
0
      + this->as_array ().sub_array (start_offset, record_count)
942
0
      | hb_map (&Record<Type>::tag)
943
0
      | hb_sink (hb_array (record_tags, *record_count))
944
0
      ;
945
0
    }
946
0
    return this->len;
947
0
  }
Unexecuted instantiation: OT::RecordArrayOf<OT::LangSys>::get_tags(unsigned int, unsigned int*, unsigned int*) const
Unexecuted instantiation: OT::RecordArrayOf<OT::Script>::get_tags(unsigned int, unsigned int*, unsigned int*) const
Unexecuted instantiation: OT::RecordArrayOf<OT::Feature>::get_tags(unsigned int, unsigned int*, unsigned int*) const
948
  bool find_index (hb_tag_t tag, unsigned int *index) const
949
19.0k
  {
950
19.0k
    return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
951
19.0k
  }
OT::RecordArrayOf<OT::LangSys>::find_index(unsigned int, unsigned int*) const
Line
Count
Source
949
5.34k
  {
950
5.34k
    return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
951
5.34k
  }
OT::RecordArrayOf<OT::Script>::find_index(unsigned int, unsigned int*) const
Line
Count
Source
949
13.6k
  {
950
13.6k
    return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
951
13.6k
  }
Unexecuted instantiation: OT::RecordArrayOf<OT::Feature>::find_index(unsigned int, unsigned int*) const
952
};
953
954
template <typename Type>
955
struct RecordListOf : RecordArrayOf<Type>
956
{
957
  const Type& operator [] (unsigned int i) const
958
10.5k
  { return this+this->get_offset (i); }
OT::RecordListOf<OT::Script>::operator[](unsigned int) const
Line
Count
Source
958
10.3k
  { return this+this->get_offset (i); }
OT::RecordListOf<OT::Feature>::operator[](unsigned int) const
Line
Count
Source
958
218
  { return this+this->get_offset (i); }
959
960
  bool subset (hb_subset_context_t *c,
961
               hb_subset_layout_context_t *l) const
962
  {
963
    TRACE_SUBSET (this);
964
    auto *out = c->serializer->start_embed (*this);
965
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
966
967
    + this->iter ()
968
    | hb_apply (subset_record_array (l, out, this))
969
    ;
970
    return_trace (true);
971
  }
972
973
  bool sanitize (hb_sanitize_context_t *c) const
974
5.87k
  {
975
5.87k
    TRACE_SANITIZE (this);
976
5.87k
    return_trace (RecordArrayOf<Type>::sanitize (c, this));
977
5.87k
  }
OT::RecordListOf<OT::Script>::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
974
2.93k
  {
975
2.93k
    TRACE_SANITIZE (this);
976
2.93k
    return_trace (RecordArrayOf<Type>::sanitize (c, this));
977
2.93k
  }
OT::RecordListOf<OT::Feature>::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
974
2.93k
  {
975
2.93k
    TRACE_SANITIZE (this);
976
2.93k
    return_trace (RecordArrayOf<Type>::sanitize (c, this));
977
2.93k
  }
978
};
979
980
struct RecordListOfFeature : RecordListOf<Feature>
981
{
982
  bool subset (hb_subset_context_t *c,
983
         hb_subset_layout_context_t *l) const
984
0
  {
985
0
    TRACE_SUBSET (this);
986
0
    auto *out = c->serializer->start_embed (*this);
987
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
988
0
989
0
    + hb_enumerate (*this)
990
0
    | hb_filter (l->feature_index_map, hb_first)
991
0
    | hb_apply ([l, out, this] (const hb_pair_t<unsigned, const Record<Feature>&>& _)
992
0
                {
993
0
                  const Feature *f_sub = nullptr;
994
0
                  const Feature **f = nullptr;
995
0
                  if (l->feature_substitutes_map->has (_.first, &f))
996
0
                    f_sub = *f;
997
0
998
0
                  l->cur_feature_index = _.first;
999
0
                  subset_record_array (l, out, this, f_sub) (_.second);
1000
0
                  l->cur_feature_index = Index::NOT_FOUND_INDEX;
1001
0
                })
1002
0
    ;
1003
0
1004
0
    return_trace (true);
1005
0
  }
1006
};
1007
1008
typedef RecordListOf<Feature> FeatureList;
1009
1010
1011
struct LangSys
1012
{
1013
  unsigned int get_feature_count () const
1014
0
  { return featureIndex.len; }
1015
  hb_tag_t get_feature_index (unsigned int i) const
1016
0
  { return featureIndex[i]; }
1017
  unsigned int get_feature_indexes (unsigned int start_offset,
1018
            unsigned int *feature_count /* IN/OUT */,
1019
            unsigned int *feature_indexes /* OUT */) const
1020
3.57k
  { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
1021
  void add_feature_indexes_to (hb_set_t *feature_indexes) const
1022
0
  { featureIndex.add_indexes_to (feature_indexes); }
1023
1024
3.44k
  bool has_required_feature () const { return reqFeatureIndex != 0xFFFFu; }
1025
  unsigned int get_required_feature_index () const
1026
3.44k
  {
1027
3.44k
    if (reqFeatureIndex == 0xFFFFu)
1028
3.43k
      return Index::NOT_FOUND_INDEX;
1029
5
   return reqFeatureIndex;
1030
3.44k
  }
1031
1032
  LangSys* copy (hb_serialize_context_t *c) const
1033
0
  {
1034
0
    TRACE_SERIALIZE (this);
1035
0
    return_trace (c->embed (*this));
1036
0
  }
1037
1038
  bool compare (const LangSys& o, const hb_map_t *feature_index_map) const
1039
0
  {
1040
0
    if (reqFeatureIndex != o.reqFeatureIndex)
1041
0
      return false;
1042
0
1043
0
    auto iter =
1044
0
    + hb_iter (featureIndex)
1045
0
    | hb_filter (feature_index_map)
1046
0
    | hb_map (feature_index_map)
1047
0
    ;
1048
0
1049
0
    auto o_iter =
1050
0
    + hb_iter (o.featureIndex)
1051
0
    | hb_filter (feature_index_map)
1052
0
    | hb_map (feature_index_map)
1053
0
    ;
1054
0
1055
0
    for (; iter && o_iter; iter++, o_iter++)
1056
0
    {
1057
0
      unsigned a = *iter;
1058
0
      unsigned b = *o_iter;
1059
0
      if (a != b) return false;
1060
0
    }
1061
0
1062
0
    if (iter || o_iter) return false;
1063
0
1064
0
    return true;
1065
0
  }
1066
1067
  void collect_features (hb_prune_langsys_context_t *c) const
1068
0
  {
1069
0
    if (!has_required_feature () && !get_feature_count ()) return;
1070
0
    if (has_required_feature () &&
1071
0
        c->duplicate_feature_map->has (reqFeatureIndex))
1072
0
      c->new_feature_indexes->add (get_required_feature_index ());
1073
0
1074
0
    + hb_iter (featureIndex)
1075
0
    | hb_filter (c->duplicate_feature_map)
1076
0
    | hb_sink (c->new_feature_indexes)
1077
0
    ;
1078
0
  }
1079
1080
  bool subset (hb_subset_context_t        *c,
1081
         hb_subset_layout_context_t *l,
1082
         const Tag                  *tag = nullptr) const
1083
0
  {
1084
0
    TRACE_SUBSET (this);
1085
0
    auto *out = c->serializer->start_embed (*this);
1086
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
1087
0
1088
0
    const uint32_t *v;
1089
0
    out->reqFeatureIndex = l->feature_map_w_duplicates->has (reqFeatureIndex, &v) ? *v : 0xFFFFu;
1090
0
1091
0
    if (!l->visitFeatureIndex (featureIndex.len))
1092
0
      return_trace (false);
1093
0
1094
0
    auto it =
1095
0
    + hb_iter (featureIndex)
1096
0
    | hb_filter (l->feature_map_w_duplicates)
1097
0
    | hb_map (l->feature_map_w_duplicates)
1098
0
    ;
1099
0
1100
0
    bool ret = bool (it);
1101
0
    out->featureIndex.serialize (c->serializer, l, it);
1102
0
    return_trace (ret);
1103
0
  }
1104
1105
  bool sanitize (hb_sanitize_context_t *c,
1106
     const Record_sanitize_closure_t * = nullptr) const
1107
3.79k
  {
1108
3.79k
    TRACE_SANITIZE (this);
1109
3.79k
    return_trace (c->check_struct (this) && featureIndex.sanitize (c));
1110
3.79k
  }
1111
1112
  Offset16  lookupOrderZ; /* = Null (reserved for an offset to a
1113
         * reordering table) */
1114
  HBUINT16  reqFeatureIndex;/* Index of a feature required for this
1115
         * language system--if no required features
1116
         * = 0xFFFFu */
1117
  IndexArray  featureIndex; /* Array of indices into the FeatureList */
1118
  public:
1119
  DEFINE_SIZE_ARRAY_SIZED (6, featureIndex);
1120
};
1121
DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys);
1122
1123
struct Script
1124
{
1125
  unsigned int get_lang_sys_count () const
1126
0
  { return langSys.len; }
1127
  const Tag& get_lang_sys_tag (unsigned int i) const
1128
0
  { return langSys.get_tag (i); }
1129
  unsigned int get_lang_sys_tags (unsigned int start_offset,
1130
          unsigned int *lang_sys_count /* IN/OUT */,
1131
          hb_tag_t     *lang_sys_tags /* OUT */) const
1132
0
  { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
1133
  const LangSys& get_lang_sys (unsigned int i) const
1134
6.88k
  {
1135
6.88k
    if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
1136
0
    return this+langSys[i].offset;
1137
6.88k
  }
1138
  bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
1139
5.34k
  { return langSys.find_index (tag, index); }
1140
1141
0
  bool has_default_lang_sys () const           { return defaultLangSys != 0; }
1142
6.88k
  const LangSys& get_default_lang_sys () const { return this+defaultLangSys; }
1143
1144
  void prune_langsys (hb_prune_langsys_context_t *c,
1145
                      unsigned script_index) const
1146
0
  {
1147
0
    if (!has_default_lang_sys () && !get_lang_sys_count ()) return;
1148
0
    if (!c->visitScript ()) return;
1149
0
1150
0
    if (!c->script_langsys_map->has (script_index))
1151
0
    {
1152
0
      if (unlikely (!c->script_langsys_map->set (script_index, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
1153
0
  return;
1154
0
    }
1155
0
1156
0
    if (has_default_lang_sys ())
1157
0
    {
1158
0
      //only collect features from non-redundant langsys
1159
0
      const LangSys& d = get_default_lang_sys ();
1160
0
      if (c->visitLangsys (d.get_feature_count ())) {
1161
0
        d.collect_features (c);
1162
0
      }
1163
0
1164
0
      for (auto _ : + hb_enumerate (langSys))
1165
0
      {
1166
0
        const LangSys& l = this+_.second.offset;
1167
0
        if (!c->visitLangsys (l.get_feature_count ())) continue;
1168
0
        if (l.compare (d, c->duplicate_feature_map)) continue;
1169
0
1170
0
        l.collect_features (c);
1171
0
        c->script_langsys_map->get (script_index)->add (_.first);
1172
0
      }
1173
0
    }
1174
0
    else
1175
0
    {
1176
0
      for (auto _ : + hb_enumerate (langSys))
1177
0
      {
1178
0
        const LangSys& l = this+_.second.offset;
1179
0
        if (!c->visitLangsys (l.get_feature_count ())) continue;
1180
0
        l.collect_features (c);
1181
0
        c->script_langsys_map->get (script_index)->add (_.first);
1182
0
      }
1183
0
    }
1184
0
  }
1185
1186
  bool subset (hb_subset_context_t         *c,
1187
         hb_subset_layout_context_t  *l,
1188
         const Tag                   *tag) const
1189
0
  {
1190
0
    TRACE_SUBSET (this);
1191
0
    if (!l->visitScript ()) return_trace (false);
1192
0
    if (tag && !c->plan->layout_scripts.has (*tag))
1193
0
      return false;
1194
0
1195
0
    auto *out = c->serializer->start_embed (*this);
1196
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
1197
0
1198
0
    bool defaultLang = false;
1199
0
    if (has_default_lang_sys ())
1200
0
    {
1201
0
      c->serializer->push ();
1202
0
      const LangSys& ls = this+defaultLangSys;
1203
0
      bool ret = ls.subset (c, l);
1204
0
      if (!ret && tag && *tag != HB_TAG ('D', 'F', 'L', 'T'))
1205
0
      {
1206
0
  c->serializer->pop_discard ();
1207
0
  out->defaultLangSys = 0;
1208
0
      }
1209
0
      else
1210
0
      {
1211
0
  c->serializer->add_link (out->defaultLangSys, c->serializer->pop_pack ());
1212
0
  defaultLang = true;
1213
0
      }
1214
0
    }
1215
0
1216
0
    const hb_set_t *active_langsys = l->script_langsys_map->get (l->cur_script_index);
1217
0
    if (active_langsys)
1218
0
    {
1219
0
      + hb_enumerate (langSys)
1220
0
      | hb_filter (active_langsys, hb_first)
1221
0
      | hb_map (hb_second)
1222
0
      | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); })
1223
0
      | hb_apply (subset_record_array (l, &(out->langSys), this))
1224
0
      ;
1225
0
    }
1226
0
1227
0
    return_trace (bool (out->langSys.len) || defaultLang || l->table_tag == HB_OT_TAG_GSUB);
1228
0
  }
1229
1230
  bool sanitize (hb_sanitize_context_t *c,
1231
     const Record_sanitize_closure_t * = nullptr) const
1232
3.39k
  {
1233
3.39k
    TRACE_SANITIZE (this);
1234
3.39k
    return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
1235
3.39k
  }
1236
1237
  protected:
1238
  Offset16To<LangSys>
1239
    defaultLangSys; /* Offset to DefaultLangSys table--from
1240
         * beginning of Script table--may be Null */
1241
  RecordArrayOf<LangSys>
1242
    langSys;  /* Array of LangSysRecords--listed
1243
         * alphabetically by LangSysTag */
1244
  public:
1245
  DEFINE_SIZE_ARRAY_SIZED (4, langSys);
1246
};
1247
1248
struct RecordListOfScript : RecordListOf<Script>
1249
{
1250
  bool subset (hb_subset_context_t *c,
1251
               hb_subset_layout_context_t *l) const
1252
0
  {
1253
0
    TRACE_SUBSET (this);
1254
0
    auto *out = c->serializer->start_embed (*this);
1255
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
1256
0
1257
0
    for (auto _ : + hb_enumerate (*this))
1258
0
    {
1259
0
      auto snap = c->serializer->snapshot ();
1260
0
      l->cur_script_index = _.first;
1261
0
      bool ret = _.second.subset (l, this);
1262
0
      if (!ret) c->serializer->revert (snap);
1263
0
      else out->len++;
1264
0
    }
1265
0
1266
0
    return_trace (true);
1267
0
  }
1268
};
1269
1270
typedef RecordListOfScript ScriptList;
1271
1272
1273
1274
struct LookupFlag : HBUINT16
1275
{
1276
  enum Flags {
1277
    RightToLeft   = 0x0001u,
1278
    IgnoreBaseGlyphs  = 0x0002u,
1279
    IgnoreLigatures = 0x0004u,
1280
    IgnoreMarks   = 0x0008u,
1281
    IgnoreFlags   = 0x000Eu,
1282
    UseMarkFilteringSet = 0x0010u,
1283
    Reserved    = 0x00E0u,
1284
    MarkAttachmentType  = 0xFF00u
1285
  };
1286
  public:
1287
  DEFINE_SIZE_STATIC (2);
1288
};
1289
1290
} /* namespace OT */
1291
/* This has to be outside the namespace. */
1292
HB_MARK_AS_FLAG_T (OT::LookupFlag::Flags);
1293
namespace OT {
1294
1295
struct Lookup
1296
{
1297
5.20k
  unsigned int get_subtable_count () const { return subTable.len; }
1298
1299
  template <typename TSubTable>
1300
  const Array16OfOffset16To<TSubTable>& get_subtables () const
1301
5.28k
  { return reinterpret_cast<const Array16OfOffset16To<TSubTable> &> (subTable); }
OT::ArrayOf<OT::OffsetTo<OT::Layout::GPOS_impl::PosLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > const& OT::Lookup::get_subtables<OT::Layout::GPOS_impl::PosLookupSubTable>() const
Line
Count
Source
1301
297
  { return reinterpret_cast<const Array16OfOffset16To<TSubTable> &> (subTable); }
OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> > const& OT::Lookup::get_subtables<OT::Layout::GSUB_impl::SubstLookupSubTable>() const
Line
Count
Source
1301
4.98k
  { return reinterpret_cast<const Array16OfOffset16To<TSubTable> &> (subTable); }
1302
  template <typename TSubTable>
1303
  Array16OfOffset16To<TSubTable>& get_subtables ()
1304
0
  { return reinterpret_cast<Array16OfOffset16To<TSubTable> &> (subTable); }
Unexecuted instantiation: OT::ArrayOf<OT::OffsetTo<OT::Layout::GPOS_impl::PosLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >& OT::Lookup::get_subtables<OT::Layout::GPOS_impl::PosLookupSubTable>()
Unexecuted instantiation: OT::ArrayOf<OT::OffsetTo<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::NumType<true, unsigned short, 2u>, void, true>, OT::NumType<true, unsigned short, 2u> >& OT::Lookup::get_subtables<OT::Layout::GSUB_impl::SubstLookupSubTable>()
1305
1306
  template <typename TSubTable>
1307
  const TSubTable& get_subtable (unsigned int i) const
1308
231
  { return this+get_subtables<TSubTable> ()[i]; }
OT::Layout::GPOS_impl::PosLookupSubTable const& OT::Lookup::get_subtable<OT::Layout::GPOS_impl::PosLookupSubTable>(unsigned int) const
Line
Count
Source
1308
93
  { return this+get_subtables<TSubTable> ()[i]; }
OT::Layout::GSUB_impl::SubstLookupSubTable const& OT::Lookup::get_subtable<OT::Layout::GSUB_impl::SubstLookupSubTable>(unsigned int) const
Line
Count
Source
1308
138
  { return this+get_subtables<TSubTable> ()[i]; }
1309
  template <typename TSubTable>
1310
  TSubTable& get_subtable (unsigned int i)
1311
  { return this+get_subtables<TSubTable> ()[i]; }
1312
1313
  size_t get_size () const
1314
0
  {
1315
0
    const HBUINT16 &markFilteringSet = StructAfter<const HBUINT16> (subTable);
1316
0
    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
1317
0
      return (const char *) &StructAfter<const char> (markFilteringSet) - (const char *) this;
1318
0
    return (const char *) &markFilteringSet - (const char *) this;
1319
0
  }
1320
1321
10.1k
  unsigned int get_type () const { return lookupType; }
1322
1323
  /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
1324
   * higher 16-bit is mark-filtering-set if the lookup uses one.
1325
   * Not to be confused with glyph_props which is very similar. */
1326
  uint32_t get_props () const
1327
0
  {
1328
0
    unsigned int flag = lookupFlag;
1329
0
    if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
1330
0
    {
1331
0
      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
1332
0
      flag += (markFilteringSet << 16);
1333
0
    }
1334
0
    return flag;
1335
0
  }
1336
1337
  template <typename TSubTable, typename context_t, typename ...Ts>
1338
  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
1339
75
  {
1340
75
    unsigned int lookup_type = get_type ();
1341
75
    TRACE_DISPATCH (this, lookup_type);
1342
75
    unsigned int count = get_subtable_count ();
1343
306
    for (unsigned int i = 0; i < count; i++) {
1344
231
      typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, ds...);
1345
231
      if (c->stop_sublookup_iteration (r))
1346
0
  return_trace (r);
1347
231
    }
1348
75
    return_trace (c->default_return_value ());
1349
75
  }
Unexecuted instantiation: OT::hb_ot_apply_context_t::return_t OT::Lookup::dispatch<OT::Layout::GPOS_impl::PosLookupSubTable, OT::hb_ot_apply_context_t>(OT::hb_ot_apply_context_t*) const
Unexecuted instantiation: OT::hb_intersects_context_t::return_t OT::Lookup::dispatch<OT::Layout::GPOS_impl::PosLookupSubTable, OT::hb_intersects_context_t>(OT::hb_intersects_context_t*) const
Unexecuted instantiation: OT::hb_collect_glyphs_context_t::return_t OT::Lookup::dispatch<OT::Layout::GPOS_impl::PosLookupSubTable, OT::hb_collect_glyphs_context_t>(OT::hb_collect_glyphs_context_t*) const
Unexecuted instantiation: OT::hb_closure_lookups_context_t::return_t OT::Lookup::dispatch<OT::Layout::GPOS_impl::PosLookupSubTable, OT::hb_closure_lookups_context_t>(OT::hb_closure_lookups_context_t*) const
Unexecuted instantiation: OT::hb_collect_variation_indices_context_t::return_t OT::Lookup::dispatch<OT::Layout::GPOS_impl::PosLookupSubTable, OT::hb_collect_variation_indices_context_t>(OT::hb_collect_variation_indices_context_t*) const
OT::hb_accelerate_subtables_context_t::return_t OT::Lookup::dispatch<OT::Layout::GPOS_impl::PosLookupSubTable, OT::hb_accelerate_subtables_context_t>(OT::hb_accelerate_subtables_context_t*) const
Line
Count
Source
1339
36
  {
1340
36
    unsigned int lookup_type = get_type ();
1341
36
    TRACE_DISPATCH (this, lookup_type);
1342
36
    unsigned int count = get_subtable_count ();
1343
129
    for (unsigned int i = 0; i < count; i++) {
1344
93
      typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, ds...);
1345
93
      if (c->stop_sublookup_iteration (r))
1346
0
  return_trace (r);
1347
93
    }
1348
36
    return_trace (c->default_return_value ());
1349
36
  }
Unexecuted instantiation: OT::hb_have_non_1to1_context_t::return_t OT::Lookup::dispatch<OT::Layout::GSUB_impl::SubstLookupSubTable, 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::Lookup::dispatch<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::hb_ot_apply_context_t>(OT::hb_ot_apply_context_t*) const
Unexecuted instantiation: OT::hb_intersects_context_t::return_t OT::Lookup::dispatch<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::hb_intersects_context_t>(OT::hb_intersects_context_t*) const
Unexecuted instantiation: OT::hb_closure_context_t::return_t OT::Lookup::dispatch<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::hb_closure_context_t>(OT::hb_closure_context_t*) const
Unexecuted instantiation: OT::hb_depend_context_t::return_t OT::Lookup::dispatch<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::hb_depend_context_t>(OT::hb_depend_context_t*) const
Unexecuted instantiation: OT::hb_closure_lookups_context_t::return_t OT::Lookup::dispatch<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::hb_closure_lookups_context_t>(OT::hb_closure_lookups_context_t*) const
Unexecuted instantiation: OT::hb_collect_glyphs_context_t::return_t OT::Lookup::dispatch<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::hb_collect_glyphs_context_t>(OT::hb_collect_glyphs_context_t*) const
Unexecuted instantiation: OT::hb_would_apply_context_t::return_t OT::Lookup::dispatch<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::hb_would_apply_context_t>(OT::hb_would_apply_context_t*) const
OT::hb_accelerate_subtables_context_t::return_t OT::Lookup::dispatch<OT::Layout::GSUB_impl::SubstLookupSubTable, OT::hb_accelerate_subtables_context_t>(OT::hb_accelerate_subtables_context_t*) const
Line
Count
Source
1339
39
  {
1340
39
    unsigned int lookup_type = get_type ();
1341
39
    TRACE_DISPATCH (this, lookup_type);
1342
39
    unsigned int count = get_subtable_count ();
1343
177
    for (unsigned int i = 0; i < count; i++) {
1344
138
      typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, ds...);
1345
138
      if (c->stop_sublookup_iteration (r))
1346
0
  return_trace (r);
1347
138
    }
1348
39
    return_trace (c->default_return_value ());
1349
39
  }
Unexecuted instantiation: hb_get_glyph_alternates_dispatch_t::return_t OT::Lookup::dispatch<OT::Layout::GSUB_impl::SubstLookupSubTable, 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::Lookup::dispatch<OT::Layout::GSUB_impl::SubstLookupSubTable, 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::Lookup::dispatch<OT::Layout::GPOS_impl::PosLookupSubTable, 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
1350
1351
  bool serialize (hb_serialize_context_t *c,
1352
      unsigned int lookup_type,
1353
      uint32_t lookup_props,
1354
      unsigned int num_subtables)
1355
0
  {
1356
0
    TRACE_SERIALIZE (this);
1357
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
1358
0
    lookupType = lookup_type;
1359
0
    lookupFlag = lookup_props & 0xFFFFu;
1360
0
    if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false);
1361
0
    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
1362
0
    {
1363
0
      if (unlikely (!c->extend (this))) return_trace (false);
1364
0
      HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
1365
0
      markFilteringSet = lookup_props >> 16;
1366
0
    }
1367
0
    return_trace (true);
1368
0
  }
1369
1370
  template <typename TSubTable>
1371
  bool subset (hb_subset_context_t *c) const
1372
0
  {
1373
0
    TRACE_SUBSET (this);
1374
0
    auto *out = c->serializer->start_embed (*this);
1375
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
1376
0
    out->lookupType = lookupType;
1377
0
    out->lookupFlag = lookupFlag;
1378
0
1379
0
    const hb_set_t *glyphset = c->plan->glyphset_gsub ();
1380
0
    unsigned int lookup_type = get_type ();
1381
0
    + hb_iter (get_subtables <TSubTable> ())
1382
0
    | hb_filter ([this, glyphset, lookup_type] (const Offset16To<TSubTable> &_) { return (this+_).intersects (glyphset, lookup_type); })
1383
0
    | hb_apply (subset_offset_array (c, out->get_subtables<TSubTable> (), this, lookup_type))
1384
0
    ;
1385
0
1386
0
    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
1387
0
    {
1388
0
      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
1389
0
      hb_codepoint_t *idx;
1390
0
      if (!c->plan->used_mark_sets_map.has (markFilteringSet, &idx))
1391
0
      {
1392
0
        unsigned new_flag = lookupFlag;
1393
0
        new_flag &= ~LookupFlag::UseMarkFilteringSet;
1394
0
        // https://github.com/harfbuzz/harfbuzz/issues/5499
1395
0
        // If we remove UseMarkFilteringSet flag because the set is now empty,
1396
0
        // we need to add IgnoreMarks flag, otherwise the lookup will not
1397
0
        // ignore any marks, which changes the behavior.
1398
0
        new_flag |= LookupFlag::IgnoreMarks;
1399
0
        out->lookupFlag = new_flag;
1400
0
      }
1401
0
      else
1402
0
      {
1403
0
        if (unlikely (!c->serializer->extend (out))) return_trace (false);
1404
0
        HBUINT16 &outMarkFilteringSet = StructAfter<HBUINT16> (out->subTable);
1405
0
        outMarkFilteringSet = *idx;
1406
0
      }
1407
0
    }
1408
0
1409
0
    // Always keep the lookup even if it's empty. The rest of layout subsetting depends on lookup
1410
0
    // indices being consistent with those computed during planning. So if an empty lookup is
1411
0
    // discarded during the subset phase it will invalidate all subsequent lookup indices.
1412
0
    // Generally we shouldn't end up with an empty lookup as we pre-prune them during the planning
1413
0
    // phase, but it can happen in rare cases such as when during closure subtable is considered
1414
0
    // degenerate (see: https://github.com/harfbuzz/harfbuzz/issues/3853)
1415
0
    return_trace (true);
1416
0
  }
Unexecuted instantiation: bool OT::Lookup::subset<OT::Layout::GPOS_impl::PosLookupSubTable>(hb_subset_context_t*) const
Unexecuted instantiation: bool OT::Lookup::subset<OT::Layout::GSUB_impl::SubstLookupSubTable>(hb_subset_context_t*) const
1417
1418
  template <typename TSubTable>
1419
  bool sanitize (hb_sanitize_context_t *c) const
1420
5.05k
  {
1421
5.05k
    TRACE_SANITIZE (this);
1422
5.05k
    if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
1423
5.05k
    hb_barrier ();
1424
1425
5.05k
    unsigned subtables = get_subtable_count ();
1426
5.05k
    if (unlikely (!c->visit_subtables (subtables))) return_trace (false);
1427
1428
5.05k
    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
1429
0
    {
1430
0
      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
1431
0
      if (!markFilteringSet.sanitize (c)) return_trace (false);
1432
0
    }
1433
1434
5.05k
    if (unlikely (!get_subtables<TSubTable> ().sanitize (c, this, get_type ())))
1435
0
      return_trace (false);
1436
1437
5.05k
    if (unlikely (get_type () == TSubTable::Extension))
1438
0
    {
1439
0
      hb_barrier ();
1440
1441
      /* The spec says all subtables of an Extension lookup should
1442
       * have the same type, which shall not be the Extension type
1443
       * itself (but we already checked for that).
1444
       * This is specially important if one has a reverse type!
1445
       */
1446
0
      unsigned int type = get_subtable<TSubTable> (0).u.extension.get_type ();
1447
0
      for (unsigned int i = 1; i < subtables; i++)
1448
0
  if (get_subtable<TSubTable> (i).u.extension.get_type () != type)
1449
0
    return_trace (false);
1450
0
    }
1451
5.05k
    return_trace (true);
1452
5.05k
  }
bool OT::Lookup::sanitize<OT::Layout::GPOS_impl::PosLookupSubTable>(hb_sanitize_context_t*) const
Line
Count
Source
1420
204
  {
1421
204
    TRACE_SANITIZE (this);
1422
204
    if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
1423
204
    hb_barrier ();
1424
1425
204
    unsigned subtables = get_subtable_count ();
1426
204
    if (unlikely (!c->visit_subtables (subtables))) return_trace (false);
1427
1428
204
    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
1429
0
    {
1430
0
      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
1431
0
      if (!markFilteringSet.sanitize (c)) return_trace (false);
1432
0
    }
1433
1434
204
    if (unlikely (!get_subtables<TSubTable> ().sanitize (c, this, get_type ())))
1435
0
      return_trace (false);
1436
1437
204
    if (unlikely (get_type () == TSubTable::Extension))
1438
0
    {
1439
0
      hb_barrier ();
1440
1441
      /* The spec says all subtables of an Extension lookup should
1442
       * have the same type, which shall not be the Extension type
1443
       * itself (but we already checked for that).
1444
       * This is specially important if one has a reverse type!
1445
       */
1446
0
      unsigned int type = get_subtable<TSubTable> (0).u.extension.get_type ();
1447
0
      for (unsigned int i = 1; i < subtables; i++)
1448
0
  if (get_subtable<TSubTable> (i).u.extension.get_type () != type)
1449
0
    return_trace (false);
1450
0
    }
1451
204
    return_trace (true);
1452
204
  }
bool OT::Lookup::sanitize<OT::Layout::GSUB_impl::SubstLookupSubTable>(hb_sanitize_context_t*) const
Line
Count
Source
1420
4.84k
  {
1421
4.84k
    TRACE_SANITIZE (this);
1422
4.84k
    if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
1423
4.84k
    hb_barrier ();
1424
1425
4.84k
    unsigned subtables = get_subtable_count ();
1426
4.84k
    if (unlikely (!c->visit_subtables (subtables))) return_trace (false);
1427
1428
4.84k
    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
1429
0
    {
1430
0
      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
1431
0
      if (!markFilteringSet.sanitize (c)) return_trace (false);
1432
0
    }
1433
1434
4.84k
    if (unlikely (!get_subtables<TSubTable> ().sanitize (c, this, get_type ())))
1435
0
      return_trace (false);
1436
1437
4.84k
    if (unlikely (get_type () == TSubTable::Extension))
1438
0
    {
1439
0
      hb_barrier ();
1440
1441
      /* The spec says all subtables of an Extension lookup should
1442
       * have the same type, which shall not be the Extension type
1443
       * itself (but we already checked for that).
1444
       * This is specially important if one has a reverse type!
1445
       */
1446
0
      unsigned int type = get_subtable<TSubTable> (0).u.extension.get_type ();
1447
0
      for (unsigned int i = 1; i < subtables; i++)
1448
0
  if (get_subtable<TSubTable> (i).u.extension.get_type () != type)
1449
0
    return_trace (false);
1450
0
    }
1451
4.84k
    return_trace (true);
1452
4.84k
  }
1453
1454
  protected:
1455
  HBUINT16  lookupType;   /* Different enumerations for GSUB and GPOS */
1456
  HBUINT16  lookupFlag;   /* Lookup qualifiers */
1457
  Array16Of<Offset16>
1458
    subTable;   /* Array of SubTables */
1459
/*HBUINT16  markFilteringSetX[HB_VAR_ARRAY];*//* Index (base 0) into GDEF mark glyph sets
1460
           * structure. This field is only present if bit
1461
           * UseMarkFilteringSet of lookup flags is set. */
1462
  public:
1463
  DEFINE_SIZE_ARRAY (6, subTable);
1464
};
1465
1466
template <typename Types>
1467
using LookupList = List16OfOffsetTo<Lookup, typename Types::HBLUINT>;
1468
1469
template <typename TLookup, typename OffsetType>
1470
struct LookupOffsetList : List16OfOffsetTo<TLookup, OffsetType>
1471
{
1472
  bool subset (hb_subset_context_t        *c,
1473
         hb_subset_layout_context_t *l) const
1474
0
  {
1475
0
    TRACE_SUBSET (this);
1476
0
    auto *out = c->serializer->start_embed (this);
1477
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
1478
0
1479
0
    + hb_enumerate (*this)
1480
0
    | hb_filter (l->lookup_index_map, hb_first)
1481
0
    | hb_map (hb_second)
1482
0
    | hb_apply (subset_offset_array (c, *out, this))
1483
0
    ;
1484
0
    return_trace (true);
1485
0
  }
Unexecuted instantiation: OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned int, 4u> >::subset(hb_subset_context_t*, OT::hb_subset_layout_context_t*) const
Unexecuted instantiation: OT::LookupOffsetList<OT::Layout::GPOS_impl::PosLookup, OT::NumType<true, unsigned short, 2u> >::subset(hb_subset_context_t*, OT::hb_subset_layout_context_t*) const
Unexecuted instantiation: OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned int, 4u> >::subset(hb_subset_context_t*, OT::hb_subset_layout_context_t*) const
Unexecuted instantiation: OT::LookupOffsetList<OT::Layout::GSUB_impl::SubstLookup, OT::NumType<true, unsigned short, 2u> >::subset(hb_subset_context_t*, OT::hb_subset_layout_context_t*) const
1486
1487
  bool sanitize (hb_sanitize_context_t *c) const
1488
  {
1489
    TRACE_SANITIZE (this);
1490
    return_trace ((List16OfOffsetTo<TLookup, OffsetType>::sanitize (c, this)));
1491
  }
1492
};
1493
1494
1495
/*
1496
 * Coverage Table
1497
 */
1498
1499
1500
static bool ClassDef_remap_and_serialize (hb_serialize_context_t *c,
1501
            const hb_set_t &klasses,
1502
                                          bool use_class_zero,
1503
                                          hb_sorted_vector_t<hb_codepoint_pair_t> &glyph_and_klass, /* IN/OUT */
1504
            hb_map_t *klass_map /*IN/OUT*/)
1505
0
{
1506
0
  if (!klass_map)
1507
0
    return ClassDef_serialize (c, glyph_and_klass.iter ());
1508
0
1509
0
  /* any glyph not assigned a class value falls into Class zero (0),
1510
0
   * if any glyph assigned to class 0, remapping must start with 0->0*/
1511
0
  if (!use_class_zero)
1512
0
    klass_map->set (0, 0);
1513
0
1514
0
  unsigned idx = klass_map->has (0) ? 1 : 0;
1515
0
  for (const unsigned k: klasses)
1516
0
  {
1517
0
    if (klass_map->has (k)) continue;
1518
0
    klass_map->set (k, idx);
1519
0
    idx++;
1520
0
  }
1521
0
1522
0
1523
0
  if (unlikely (!c->propagate_error (glyph_and_klass, klasses, klass_map)))
1524
0
    return false;
1525
0
1526
0
  for (unsigned i = 0; i < glyph_and_klass.length; i++)
1527
0
  {
1528
0
    hb_codepoint_t klass = glyph_and_klass[i].second;
1529
0
    glyph_and_klass[i].second = klass_map->get (klass);
1530
0
  }
1531
0
1532
0
  return ClassDef_serialize (c, glyph_and_klass.iter ());
1533
0
}
Unexecuted instantiation: hb-face.cc:OT::ClassDef_remap_and_serialize(hb_serialize_context_t*, hb_set_t const&, bool, hb_vector_t<hb_pair_t<unsigned int, unsigned int>, true>&, hb_map_t*)
Unexecuted instantiation: hb-font.cc:OT::ClassDef_remap_and_serialize(hb_serialize_context_t*, hb_set_t const&, bool, hb_vector_t<hb_pair_t<unsigned int, unsigned int>, true>&, hb_map_t*)
Unexecuted instantiation: hb-ot-face.cc:OT::ClassDef_remap_and_serialize(hb_serialize_context_t*, hb_set_t const&, bool, hb_vector_t<hb_pair_t<unsigned int, unsigned int>, true>&, hb_map_t*)
Unexecuted instantiation: hb-ot-font.cc:OT::ClassDef_remap_and_serialize(hb_serialize_context_t*, hb_set_t const&, bool, hb_vector_t<hb_pair_t<unsigned int, unsigned int>, true>&, hb_map_t*)
Unexecuted instantiation: VARC.cc:OT::ClassDef_remap_and_serialize(hb_serialize_context_t*, hb_set_t const&, bool, hb_vector_t<hb_pair_t<unsigned int, unsigned int>, true>&, hb_map_t*)
Unexecuted instantiation: hb-ot-metrics.cc:OT::ClassDef_remap_and_serialize(hb_serialize_context_t*, hb_set_t const&, bool, hb_vector_t<hb_pair_t<unsigned int, unsigned int>, true>&, hb_map_t*)
Unexecuted instantiation: hb-ot-shape.cc:OT::ClassDef_remap_and_serialize(hb_serialize_context_t*, hb_set_t const&, bool, hb_vector_t<hb_pair_t<unsigned int, unsigned int>, true>&, hb_map_t*)
Unexecuted instantiation: hb-ot-var.cc:OT::ClassDef_remap_and_serialize(hb_serialize_context_t*, hb_set_t const&, bool, hb_vector_t<hb_pair_t<unsigned int, unsigned int>, true>&, hb_map_t*)
Unexecuted instantiation: hb-static.cc:OT::ClassDef_remap_and_serialize(hb_serialize_context_t*, hb_set_t const&, bool, hb_vector_t<hb_pair_t<unsigned int, unsigned int>, true>&, hb_map_t*)
Unexecuted instantiation: hb-ft.cc:OT::ClassDef_remap_and_serialize(hb_serialize_context_t*, hb_set_t const&, bool, hb_vector_t<hb_pair_t<unsigned int, unsigned int>, true>&, hb_map_t*)
Unexecuted instantiation: hb-aat-layout.cc:OT::ClassDef_remap_and_serialize(hb_serialize_context_t*, hb_set_t const&, bool, hb_vector_t<hb_pair_t<unsigned int, unsigned int>, true>&, hb_map_t*)
Unexecuted instantiation: hb-aat-map.cc:OT::ClassDef_remap_and_serialize(hb_serialize_context_t*, hb_set_t const&, bool, hb_vector_t<hb_pair_t<unsigned int, unsigned int>, true>&, hb_map_t*)
Unexecuted instantiation: hb-ot-cff1-table.cc:OT::ClassDef_remap_and_serialize(hb_serialize_context_t*, hb_set_t const&, bool, hb_vector_t<hb_pair_t<unsigned int, unsigned int>, true>&, hb_map_t*)
Unexecuted instantiation: hb-ot-cff2-table.cc:OT::ClassDef_remap_and_serialize(hb_serialize_context_t*, hb_set_t const&, bool, hb_vector_t<hb_pair_t<unsigned int, unsigned int>, true>&, hb_map_t*)
Unexecuted instantiation: hb-ot-layout.cc:OT::ClassDef_remap_and_serialize(hb_serialize_context_t*, hb_set_t const&, bool, hb_vector_t<hb_pair_t<unsigned int, unsigned int>, true>&, hb_map_t*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::ClassDef_remap_and_serialize(hb_serialize_context_t*, hb_set_t const&, bool, hb_vector_t<hb_pair_t<unsigned int, unsigned int>, true>&, hb_map_t*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::ClassDef_remap_and_serialize(hb_serialize_context_t*, hb_set_t const&, bool, hb_vector_t<hb_pair_t<unsigned int, unsigned int>, true>&, hb_map_t*)
1534
1535
/*
1536
 * Class Definition Table
1537
 */
1538
1539
template <typename Types>
1540
struct ClassDefFormat1_3
1541
{
1542
  friend struct ClassDef;
1543
1544
  private:
1545
  unsigned int get_class (hb_codepoint_t glyph_id) const
1546
0
  {
1547
0
    return classValue[(unsigned int) (glyph_id - startGlyph)];
1548
0
  }
Unexecuted instantiation: OT::ClassDefFormat1_3<OT::Layout::SmallTypes>::get_class(unsigned int) const
Unexecuted instantiation: OT::ClassDefFormat1_3<OT::Layout::MediumTypes>::get_class(unsigned int) const
1549
1550
  unsigned get_population () const
1551
0
  {
1552
0
    return classValue.len;
1553
0
  }
Unexecuted instantiation: OT::ClassDefFormat1_3<OT::Layout::SmallTypes>::get_population() const
Unexecuted instantiation: OT::ClassDefFormat1_3<OT::Layout::MediumTypes>::get_population() const
1554
1555
  template<typename Iterator,
1556
     hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
1557
  bool serialize (hb_serialize_context_t *c,
1558
      Iterator it)
1559
0
  {
1560
0
    TRACE_SERIALIZE (this);
1561
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
1562
0
1563
0
    if (unlikely (!it))
1564
0
    {
1565
0
      classFormat = Types::size == 2 ? 1 : 3;
1566
0
      startGlyph = 0;
1567
0
      classValue.len = 0;
1568
0
      return_trace (true);
1569
0
    }
1570
0
1571
0
    hb_codepoint_t glyph_min = (*it).first;
1572
0
    hb_codepoint_t glyph_max = + it
1573
0
             | hb_map (hb_first)
1574
0
             | hb_reduce (hb_max, 0u);
1575
0
    unsigned glyph_count = glyph_max - glyph_min + 1;
1576
0
1577
0
    startGlyph = glyph_min;
1578
0
    if (unlikely (!classValue.serialize (c, glyph_count))) return_trace (false);
1579
0
    for (const hb_pair_t<hb_codepoint_t, uint32_t> gid_klass_pair : + it)
1580
0
    {
1581
0
      unsigned idx = gid_klass_pair.first - glyph_min;
1582
0
      classValue[idx] = gid_klass_pair.second;
1583
0
    }
1584
0
    return_trace (true);
1585
0
  }
Unexecuted instantiation: hb-face.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-face.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-font.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-font.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-face.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-face.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-font.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-font.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: VARC.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_20LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: VARC.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_20LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-metrics.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-metrics.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-shape.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-shape.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-var.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-var.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-static.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-static.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ft.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ft.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-aat-layout.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-aat-layout.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-aat-map.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-aat-map.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-cff1-table.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-cff1-table.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-cff2-table.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-cff2-table.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-layout.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-layout.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-shaper-arabic.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-shaper-arabic.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-shape-fallback.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-shape-fallback.cc:_ZN2OT17ClassDefFormat1_3INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
1586
1587
  bool subset (hb_subset_context_t *c,
1588
         hb_map_t *klass_map = nullptr /*OUT*/,
1589
               bool keep_empty_table = true,
1590
               bool use_class_zero = true,
1591
               const Coverage* glyph_filter = nullptr) const
1592
0
  {
1593
0
    TRACE_SUBSET (this);
1594
0
1595
0
    hb_sorted_vector_t<hb_codepoint_pair_t> glyph_and_klass;
1596
0
    hb_set_t orig_klasses;
1597
0
1598
0
    hb_codepoint_t start = startGlyph;
1599
0
    hb_codepoint_t end   = start + classValue.len;
1600
0
1601
0
    for (const hb_codepoint_t gid : + hb_range (start, end))
1602
0
    {
1603
0
      hb_codepoint_t new_gid = c->plan->map_gsub_glyph (gid);
1604
0
      if (new_gid == HB_MAP_VALUE_INVALID) continue;
1605
0
      if (glyph_filter && !glyph_filter->has(gid)) continue;
1606
0
1607
0
      unsigned klass = classValue[gid - start];
1608
0
      if (!klass) continue;
1609
0
1610
0
      glyph_and_klass.push (hb_pair (new_gid, klass));
1611
0
      orig_klasses.add (klass);
1612
0
    }
1613
0
1614
0
    if (use_class_zero)
1615
0
    {
1616
0
      const hb_set_t& glyphset = *c->plan->glyphset_gsub ();
1617
0
      unsigned glyph_count = glyph_filter
1618
0
           ? hb_len (hb_iter (glyphset) | hb_filter (glyph_filter))
1619
0
           : glyphset.get_population ();
1620
0
      use_class_zero = glyph_count <= glyph_and_klass.length;
1621
0
    }
1622
0
    if (!ClassDef_remap_and_serialize (c->serializer,
1623
0
                                       orig_klasses,
1624
0
                                       use_class_zero,
1625
0
                                       glyph_and_klass,
1626
0
                                       klass_map))
1627
0
      return_trace (false);
1628
0
    return_trace (keep_empty_table || (bool) glyph_and_klass);
1629
0
  }
Unexecuted instantiation: OT::ClassDefFormat1_3<OT::Layout::SmallTypes>::subset(hb_subset_context_t*, hb_map_t*, bool, bool, OT::Layout::Common::Coverage const*) const
Unexecuted instantiation: OT::ClassDefFormat1_3<OT::Layout::MediumTypes>::subset(hb_subset_context_t*, hb_map_t*, bool, bool, OT::Layout::Common::Coverage const*) const
1630
1631
  bool sanitize (hb_sanitize_context_t *c) const
1632
209
  {
1633
209
    TRACE_SANITIZE (this);
1634
209
    return_trace (c->check_struct (this) && classValue.sanitize (c));
1635
209
  }
OT::ClassDefFormat1_3<OT::Layout::SmallTypes>::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
1632
209
  {
1633
209
    TRACE_SANITIZE (this);
1634
209
    return_trace (c->check_struct (this) && classValue.sanitize (c));
1635
209
  }
Unexecuted instantiation: OT::ClassDefFormat1_3<OT::Layout::MediumTypes>::sanitize(hb_sanitize_context_t*) const
1636
1637
121
  unsigned cost () const { return 1; }
OT::ClassDefFormat1_3<OT::Layout::SmallTypes>::cost() const
Line
Count
Source
1637
121
  unsigned cost () const { return 1; }
Unexecuted instantiation: OT::ClassDefFormat1_3<OT::Layout::MediumTypes>::cost() const
1638
1639
  template <typename set_t>
1640
  bool collect_coverage (set_t *glyphs) const
1641
0
  {
1642
0
    unsigned int start = 0;
1643
0
    unsigned int count = classValue.len;
1644
0
    for (unsigned int i = 0; i < count; i++)
1645
0
    {
1646
0
      if (classValue[i])
1647
0
  continue;
1648
1649
0
      if (start != i)
1650
0
  if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + i)))
1651
0
    return false;
1652
1653
0
      start = i + 1;
1654
0
    }
1655
0
    if (start != count)
1656
0
      if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + count)))
1657
0
  return false;
1658
1659
0
    return true;
1660
0
  }
Unexecuted instantiation: bool OT::ClassDefFormat1_3<OT::Layout::SmallTypes>::collect_coverage<hb_set_t>(hb_set_t*) const
Unexecuted instantiation: bool OT::ClassDefFormat1_3<OT::Layout::MediumTypes>::collect_coverage<hb_set_t>(hb_set_t*) const
1661
1662
  template <typename set_t>
1663
  bool collect_class (set_t *glyphs, unsigned klass) const
1664
66
  {
1665
66
    unsigned int count = classValue.len;
1666
396
    for (unsigned int i = 0; i < count; i++)
1667
330
      if (classValue[i] == klass) glyphs->add (startGlyph + i);
1668
66
    return true;
1669
66
  }
Unexecuted instantiation: bool OT::ClassDefFormat1_3<OT::Layout::SmallTypes>::collect_class<hb_set_t>(hb_set_t*, unsigned int) const
Unexecuted instantiation: bool OT::ClassDefFormat1_3<OT::Layout::MediumTypes>::collect_class<hb_set_t>(hb_set_t*, unsigned int) const
bool OT::ClassDefFormat1_3<OT::Layout::SmallTypes>::collect_class<hb_set_digest_t>(hb_set_digest_t*, unsigned int) const
Line
Count
Source
1664
66
  {
1665
66
    unsigned int count = classValue.len;
1666
396
    for (unsigned int i = 0; i < count; i++)
1667
330
      if (classValue[i] == klass) glyphs->add (startGlyph + i);
1668
66
    return true;
1669
66
  }
Unexecuted instantiation: bool OT::ClassDefFormat1_3<OT::Layout::MediumTypes>::collect_class<hb_set_digest_t>(hb_set_digest_t*, unsigned int) const
1670
1671
  bool intersects (const hb_set_t *glyphs) const
1672
0
  {
1673
0
    hb_codepoint_t start = startGlyph;
1674
0
    hb_codepoint_t end = startGlyph + classValue.len;
1675
0
    for (hb_codepoint_t iter = startGlyph - 1;
1676
0
   glyphs->next (&iter) && iter < end;)
1677
0
      if (classValue[iter - start]) return true;
1678
0
    return false;
1679
0
  }
Unexecuted instantiation: OT::ClassDefFormat1_3<OT::Layout::SmallTypes>::intersects(hb_set_t const*) const
Unexecuted instantiation: OT::ClassDefFormat1_3<OT::Layout::MediumTypes>::intersects(hb_set_t const*) const
1680
  bool intersects_class (const hb_set_t *glyphs, unsigned klass) const
1681
0
  {
1682
0
    unsigned int count = classValue.len;
1683
0
    if (klass == 0)
1684
0
    {
1685
      /* Match if there's any glyph that is not listed! */
1686
0
      hb_codepoint_t g = HB_SET_VALUE_INVALID;
1687
0
      if (!glyphs->next (&g)) return false;
1688
0
      if (g < startGlyph) return true;
1689
0
      g = startGlyph + count - 1;
1690
0
      if (glyphs->next (&g)) return true;
1691
      /* Fall through. */
1692
0
    }
1693
    /* TODO Speed up, using set overlap first? */
1694
    /* TODO(iter) Rewrite as dagger. */
1695
0
    const typename Types::HBUINT *arr = classValue.arrayZ;
1696
0
    for (unsigned int i = 0; i < count; i++)
1697
0
      if (arr[i] == klass && glyphs->has (startGlyph + i))
1698
0
  return true;
1699
0
    return false;
1700
0
  }
Unexecuted instantiation: OT::ClassDefFormat1_3<OT::Layout::SmallTypes>::intersects_class(hb_set_t const*, unsigned int) const
Unexecuted instantiation: OT::ClassDefFormat1_3<OT::Layout::MediumTypes>::intersects_class(hb_set_t const*, unsigned int) const
1701
1702
  void intersected_class_glyphs (const hb_set_t *glyphs, unsigned klass, hb_set_t *intersect_glyphs) const
1703
0
  {
1704
0
    unsigned count = classValue.len;
1705
0
    if (klass == 0)
1706
0
    {
1707
0
      unsigned start_glyph = startGlyph;
1708
0
      for (uint32_t g = HB_SET_VALUE_INVALID;
1709
0
     glyphs->next (&g) && g < start_glyph;)
1710
0
  intersect_glyphs->add (g);
1711
1712
0
      for (uint32_t g = startGlyph + count - 1;
1713
0
     glyphs-> next (&g);)
1714
0
  intersect_glyphs->add (g);
1715
1716
0
      return;
1717
0
    }
1718
1719
0
    for (unsigned i = 0; i < count; i++)
1720
0
      if (classValue[i] == klass && glyphs->has (startGlyph + i))
1721
0
  intersect_glyphs->add (startGlyph + i);
1722
1723
#if 0
1724
    /* The following implementation is faster asymptotically, but slower
1725
     * in practice. */
1726
    unsigned start_glyph = startGlyph;
1727
    unsigned end_glyph = start_glyph + count;
1728
    for (unsigned g = startGlyph - 1;
1729
   glyphs->next (&g) && g < end_glyph;)
1730
      if (classValue.arrayZ[g - start_glyph] == klass)
1731
        intersect_glyphs->add (g);
1732
#endif
1733
0
  }
Unexecuted instantiation: OT::ClassDefFormat1_3<OT::Layout::SmallTypes>::intersected_class_glyphs(hb_set_t const*, unsigned int, hb_set_t*) const
Unexecuted instantiation: OT::ClassDefFormat1_3<OT::Layout::MediumTypes>::intersected_class_glyphs(hb_set_t const*, unsigned int, hb_set_t*) const
1734
1735
  void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const
1736
0
  {
1737
0
    if (glyphs->is_empty ()) return;
1738
0
1739
0
    /* An empty ClassDef assigns class zero to every glyph, so every glyph in
1740
0
     * `glyphs` intersects class zero.  Handle it up front: `end_glyph` below
1741
0
     * underflows when startGlyph is zero, and neither comparison can then be
1742
0
     * true. */
1743
0
    if (!classValue.len)
1744
0
    {
1745
0
      intersect_classes->add (0);
1746
0
      return;
1747
0
    }
1748
0
1749
0
    hb_codepoint_t end_glyph = startGlyph + classValue.len - 1;
1750
0
    if (glyphs->get_min () < startGlyph ||
1751
0
        glyphs->get_max () > end_glyph)
1752
0
      intersect_classes->add (0);
1753
0
1754
0
    for (const auto& _ : + hb_enumerate (classValue))
1755
0
    {
1756
0
      hb_codepoint_t g = startGlyph + _.first;
1757
0
      if (glyphs->has (g))
1758
0
        intersect_classes->add (_.second);
1759
0
    }
1760
0
  }
Unexecuted instantiation: OT::ClassDefFormat1_3<OT::Layout::SmallTypes>::intersected_classes(hb_set_t const*, hb_set_t*) const
Unexecuted instantiation: OT::ClassDefFormat1_3<OT::Layout::MediumTypes>::intersected_classes(hb_set_t const*, hb_set_t*) const
1761
1762
  protected:
1763
  HBUINT16  classFormat;  /* Format identifier--format = 1 */
1764
  typename Types::HBGlyphID
1765
     startGlyph;  /* First GlyphID of the classValueArray */
1766
  typename Types::template ArrayOf<typename Types::HBUINT>
1767
    classValue; /* Array of Class Values--one per GlyphID */
1768
  public:
1769
  DEFINE_SIZE_ARRAY (2 + 2 * Types::size, classValue);
1770
};
1771
1772
template <typename Types>
1773
struct ClassDefFormat2_4
1774
{
1775
  friend struct ClassDef;
1776
1777
  private:
1778
  unsigned int get_class (hb_codepoint_t glyph_id) const
1779
20
  {
1780
20
    return rangeRecord.bsearch (glyph_id).value;
1781
20
  }
OT::ClassDefFormat2_4<OT::Layout::SmallTypes>::get_class(unsigned int) const
Line
Count
Source
1779
20
  {
1780
20
    return rangeRecord.bsearch (glyph_id).value;
1781
20
  }
Unexecuted instantiation: OT::ClassDefFormat2_4<OT::Layout::MediumTypes>::get_class(unsigned int) const
1782
1783
  unsigned get_population () const
1784
0
  {
1785
0
    typename Types::large_int ret = 0;
1786
0
    for (const auto &r : rangeRecord)
1787
0
      ret += r.get_population ();
1788
0
    return ret > UINT_MAX ? UINT_MAX : (unsigned) ret;
1789
0
  }
Unexecuted instantiation: OT::ClassDefFormat2_4<OT::Layout::SmallTypes>::get_population() const
Unexecuted instantiation: OT::ClassDefFormat2_4<OT::Layout::MediumTypes>::get_population() const
1790
1791
  template<typename Iterator,
1792
     hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
1793
  bool serialize (hb_serialize_context_t *c,
1794
      Iterator it)
1795
0
  {
1796
0
    TRACE_SERIALIZE (this);
1797
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
1798
0
1799
0
    if (unlikely (!it))
1800
0
    {
1801
0
      classFormat = Types::size == 2 ? 2 : 4;
1802
0
      rangeRecord.len = 0;
1803
0
      return_trace (true);
1804
0
    }
1805
0
1806
0
    unsigned unsorted = false;
1807
0
    unsigned num_ranges = 1;
1808
0
    hb_codepoint_t prev_gid = (*it).first;
1809
0
    unsigned prev_klass = (*it).second;
1810
0
1811
0
    RangeRecord<Types> range_rec;
1812
0
    range_rec.first = prev_gid;
1813
0
    range_rec.last = prev_gid;
1814
0
    range_rec.value = prev_klass;
1815
0
1816
0
    auto *record = c->copy (range_rec);
1817
0
    if (unlikely (!record)) return_trace (false);
1818
0
1819
0
    for (const auto gid_klass_pair : + (++it))
1820
0
    {
1821
0
      hb_codepoint_t cur_gid = gid_klass_pair.first;
1822
0
      unsigned cur_klass = gid_klass_pair.second;
1823
0
1824
0
      if (cur_gid != prev_gid + 1 ||
1825
0
    cur_klass != prev_klass)
1826
0
      {
1827
0
1828
0
  if (unlikely (cur_gid < prev_gid))
1829
0
    unsorted = true;
1830
0
1831
0
  if (unlikely (!record)) break;
1832
0
  record->last = prev_gid;
1833
0
  num_ranges++;
1834
0
1835
0
  range_rec.first = cur_gid;
1836
0
  range_rec.last = cur_gid;
1837
0
  range_rec.value = cur_klass;
1838
0
1839
0
  record = c->copy (range_rec);
1840
0
      }
1841
0
1842
0
      prev_klass = cur_klass;
1843
0
      prev_gid = cur_gid;
1844
0
    }
1845
0
1846
0
    if (unlikely (c->in_error ())) return_trace (false);
1847
0
1848
0
    if (likely (record)) record->last = prev_gid;
1849
0
    rangeRecord.len = num_ranges;
1850
0
1851
0
    if (unlikely (unsorted))
1852
0
      rangeRecord.as_array ().qsort (RangeRecord<Types>::cmp_range);
1853
0
1854
0
    return_trace (true);
1855
0
  }
Unexecuted instantiation: hb-face.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-face.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-font.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-font.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-face.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-face.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-font.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-font.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: VARC.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_20LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: VARC.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_20LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-metrics.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-metrics.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-shape.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-shape.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-var.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-var.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-static.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-static.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ft.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ft.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-aat-layout.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-aat-layout.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-aat-map.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-aat-map.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-cff1-table.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-cff1-table.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-cff2-table.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-cff2-table.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-layout.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-layout.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-shaper-arabic.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-shaper-arabic.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-shape-fallback.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout10SmallTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
Unexecuted instantiation: hb-ot-shape-fallback.cc:_ZN2OT17ClassDefFormat2_4INS_6Layout11MediumTypesEE9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEERK3$_6RK4$_17LPv0EETnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_jEE5valuesrSK_18is_sorted_iteratorEvE4typeELSH_0EEEbP22hb_serialize_context_tSK_
1856
1857
  bool subset (hb_subset_context_t *c,
1858
         hb_map_t *klass_map = nullptr /*OUT*/,
1859
               bool keep_empty_table = true,
1860
               bool use_class_zero = true,
1861
               const Coverage* glyph_filter = nullptr) const
1862
0
  {
1863
0
    TRACE_SUBSET (this);
1864
0
    const hb_set_t &glyph_set = *c->plan->glyphset_gsub ();
1865
0
1866
0
    hb_sorted_vector_t<hb_codepoint_pair_t> glyph_and_klass;
1867
0
    hb_set_t orig_klasses;
1868
0
1869
0
    if (glyph_set.get_population () * hb_bit_storage ((unsigned) rangeRecord.len)
1870
0
  < get_population ())
1871
0
    {
1872
0
      for (hb_codepoint_t g : glyph_set)
1873
0
      {
1874
0
  unsigned klass = get_class (g);
1875
0
  if (!klass) continue;
1876
0
  hb_codepoint_t new_gid = c->plan->map_gsub_glyph (g);
1877
0
  if (new_gid == HB_MAP_VALUE_INVALID) continue;
1878
0
  if (glyph_filter && !glyph_filter->has (g)) continue;
1879
0
  glyph_and_klass.push (hb_pair (new_gid, klass));
1880
0
  orig_klasses.add (klass);
1881
0
      }
1882
0
    }
1883
0
    else
1884
0
    {
1885
0
      unsigned num_source_glyphs = c->plan->source->get_num_glyphs ();
1886
0
      for (auto &range : rangeRecord)
1887
0
      {
1888
0
  unsigned klass = range.value;
1889
0
  if (!klass) continue;
1890
0
  hb_codepoint_t start = range.first;
1891
0
  hb_codepoint_t end   = hb_min (range.last + 1, num_source_glyphs);
1892
0
  for (hb_codepoint_t g = start; g < end; g++)
1893
0
  {
1894
0
    hb_codepoint_t new_gid = c->plan->map_gsub_glyph (g);
1895
0
    if (new_gid == HB_MAP_VALUE_INVALID) continue;
1896
0
    if (glyph_filter && !glyph_filter->has (g)) continue;
1897
0
1898
0
    glyph_and_klass.push (hb_pair (new_gid, klass));
1899
0
    orig_klasses.add (klass);
1900
0
  }
1901
0
      }
1902
0
    }
1903
0
1904
0
    const hb_set_t& glyphset = *c->plan->glyphset_gsub ();
1905
0
    unsigned glyph_count = glyph_filter
1906
0
                           ? hb_len (hb_iter (glyphset) | hb_filter (glyph_filter))
1907
0
                           : glyphset.get_population ();
1908
0
    use_class_zero = use_class_zero && glyph_count <= glyph_and_klass.length;
1909
0
    if (!ClassDef_remap_and_serialize (c->serializer,
1910
0
                                       orig_klasses,
1911
0
                                       use_class_zero,
1912
0
                                       glyph_and_klass,
1913
0
                                       klass_map))
1914
0
      return_trace (false);
1915
0
    return_trace (keep_empty_table || (bool) glyph_and_klass);
1916
0
  }
Unexecuted instantiation: OT::ClassDefFormat2_4<OT::Layout::SmallTypes>::subset(hb_subset_context_t*, hb_map_t*, bool, bool, OT::Layout::Common::Coverage const*) const
Unexecuted instantiation: OT::ClassDefFormat2_4<OT::Layout::MediumTypes>::subset(hb_subset_context_t*, hb_map_t*, bool, bool, OT::Layout::Common::Coverage const*) const
1917
1918
  bool sanitize (hb_sanitize_context_t *c) const
1919
328
  {
1920
328
    TRACE_SANITIZE (this);
1921
328
    return_trace (rangeRecord.sanitize (c));
1922
328
  }
OT::ClassDefFormat2_4<OT::Layout::SmallTypes>::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
1919
328
  {
1920
328
    TRACE_SANITIZE (this);
1921
328
    return_trace (rangeRecord.sanitize (c));
1922
328
  }
Unexecuted instantiation: OT::ClassDefFormat2_4<OT::Layout::MediumTypes>::sanitize(hb_sanitize_context_t*) const
1923
1924
133
  unsigned cost () const { return hb_bit_storage ((unsigned) rangeRecord.len); /* bsearch cost */ }
OT::ClassDefFormat2_4<OT::Layout::SmallTypes>::cost() const
Line
Count
Source
1924
133
  unsigned cost () const { return hb_bit_storage ((unsigned) rangeRecord.len); /* bsearch cost */ }
Unexecuted instantiation: OT::ClassDefFormat2_4<OT::Layout::MediumTypes>::cost() const
1925
1926
  template <typename set_t>
1927
  bool collect_coverage (set_t *glyphs) const
1928
0
  {
1929
0
    for (auto &range : rangeRecord)
1930
0
      if (range.value)
1931
0
  if (unlikely (!range.collect_coverage (glyphs)))
1932
0
    return false;
1933
0
    return true;
1934
0
  }
Unexecuted instantiation: bool OT::ClassDefFormat2_4<OT::Layout::SmallTypes>::collect_coverage<hb_set_t>(hb_set_t*) const
Unexecuted instantiation: bool OT::ClassDefFormat2_4<OT::Layout::MediumTypes>::collect_coverage<hb_set_t>(hb_set_t*) const
1935
1936
  template <typename set_t>
1937
  bool collect_class (set_t *glyphs, unsigned int klass) const
1938
90
  {
1939
90
    for (auto &range : rangeRecord)
1940
3.70k
    {
1941
3.70k
      if (range.value == klass)
1942
253
  if (unlikely (!range.collect_coverage (glyphs)))
1943
5
    return false;
1944
3.70k
    }
1945
85
    return true;
1946
90
  }
Unexecuted instantiation: bool OT::ClassDefFormat2_4<OT::Layout::SmallTypes>::collect_class<hb_set_t>(hb_set_t*, unsigned int) const
Unexecuted instantiation: bool OT::ClassDefFormat2_4<OT::Layout::MediumTypes>::collect_class<hb_set_t>(hb_set_t*, unsigned int) const
bool OT::ClassDefFormat2_4<OT::Layout::SmallTypes>::collect_class<hb_set_digest_t>(hb_set_digest_t*, unsigned int) const
Line
Count
Source
1938
90
  {
1939
90
    for (auto &range : rangeRecord)
1940
3.70k
    {
1941
3.70k
      if (range.value == klass)
1942
253
  if (unlikely (!range.collect_coverage (glyphs)))
1943
5
    return false;
1944
3.70k
    }
1945
85
    return true;
1946
90
  }
Unexecuted instantiation: bool OT::ClassDefFormat2_4<OT::Layout::MediumTypes>::collect_class<hb_set_digest_t>(hb_set_digest_t*, unsigned int) const
1947
1948
  bool intersects (const hb_set_t *glyphs) const
1949
0
  {
1950
0
    if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len))
1951
0
    {
1952
0
      for (auto g : *glyphs)
1953
0
        if (get_class (g))
1954
0
    return true;
1955
0
      return false;
1956
0
    }
1957
0
1958
0
    return hb_any (+ hb_iter (rangeRecord)
1959
0
                   | hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs) && range.value; }));
1960
0
  }
Unexecuted instantiation: OT::ClassDefFormat2_4<OT::Layout::SmallTypes>::intersects(hb_set_t const*) const
Unexecuted instantiation: OT::ClassDefFormat2_4<OT::Layout::MediumTypes>::intersects(hb_set_t const*) const
1961
  bool intersects_class (const hb_set_t *glyphs, unsigned klass) const
1962
0
  {
1963
0
    if (klass == 0)
1964
0
    {
1965
      /* An empty ClassDef assigns class zero to every glyph, so it intersects
1966
       * class zero as long as there is any glyph at all.  The loop below is a
1967
       * no-op when there are no ranges, and the `g != HB_SET_VALUE_INVALID`
1968
       * guard after it would then wrongly report no intersection. */
1969
0
      if (!rangeRecord.len)
1970
0
        return !glyphs->is_empty ();
1971
1972
      /* Match if there's any glyph that is not listed! */
1973
0
      hb_codepoint_t g = HB_SET_VALUE_INVALID;
1974
0
      hb_codepoint_t last = HB_SET_VALUE_INVALID;
1975
0
      for (auto &range : rangeRecord)
1976
0
      {
1977
  /* Only probe for a glyph in the gap before this range; a range
1978
   * starting right after the previous one (or at glyph 0) has none. */
1979
0
  if (range.first != last + 1)
1980
0
  {
1981
0
    if (!glyphs->next (&g))
1982
0
      break;
1983
0
    if (g < range.first)
1984
0
      return true;
1985
0
  }
1986
0
  g = last = range.last;
1987
0
      }
1988
0
      if (g != HB_SET_VALUE_INVALID && glyphs->next (&g))
1989
0
  return true;
1990
      /* Fall through. */
1991
0
    }
1992
0
    for (const auto &range : rangeRecord)
1993
0
      if (range.value == klass && range.intersects (*glyphs))
1994
0
  return true;
1995
0
    return false;
1996
0
  }
Unexecuted instantiation: OT::ClassDefFormat2_4<OT::Layout::SmallTypes>::intersects_class(hb_set_t const*, unsigned int) const
Unexecuted instantiation: OT::ClassDefFormat2_4<OT::Layout::MediumTypes>::intersects_class(hb_set_t const*, unsigned int) const
1997
1998
  void intersected_class_glyphs (const hb_set_t *glyphs, unsigned klass, hb_set_t *intersect_glyphs) const
1999
0
  {
2000
0
    if (klass == 0)
2001
0
    {
2002
0
      hb_codepoint_t g = HB_SET_VALUE_INVALID;
2003
0
      for (auto &range : rangeRecord)
2004
0
      {
2005
0
  if (!glyphs->next (&g))
2006
0
    goto done;
2007
0
  while (g < range.first)
2008
0
  {
2009
0
    intersect_glyphs->add (g);
2010
0
    if (!glyphs->next (&g))
2011
0
      goto done;
2012
0
        }
2013
0
        g = range.last;
2014
0
      }
2015
0
      while (glyphs->next (&g))
2016
0
  intersect_glyphs->add (g);
2017
0
      done:
2018
2019
0
      return;
2020
0
    }
2021
2022
0
    unsigned count = rangeRecord.len;
2023
0
    if (count > glyphs->get_population () * hb_bit_storage (count))
2024
0
    {
2025
0
      for (auto g : *glyphs)
2026
0
      {
2027
0
        unsigned i;
2028
0
        if (rangeRecord.as_array ().bfind (g, &i) &&
2029
0
      rangeRecord.arrayZ[i].value == klass)
2030
0
    intersect_glyphs->add (g);
2031
0
      }
2032
0
      return;
2033
0
    }
2034
2035
0
    for (auto &range : rangeRecord)
2036
0
    {
2037
0
      if (range.value != klass) continue;
2038
2039
0
      unsigned end = range.last + 1;
2040
0
      for (hb_codepoint_t g = range.first - 1;
2041
0
     glyphs->next (&g) && g < end;)
2042
0
  intersect_glyphs->add (g);
2043
0
    }
2044
0
  }
Unexecuted instantiation: OT::ClassDefFormat2_4<OT::Layout::SmallTypes>::intersected_class_glyphs(hb_set_t const*, unsigned int, hb_set_t*) const
Unexecuted instantiation: OT::ClassDefFormat2_4<OT::Layout::MediumTypes>::intersected_class_glyphs(hb_set_t const*, unsigned int, hb_set_t*) const
2045
2046
  void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const
2047
0
  {
2048
0
    if (glyphs->is_empty ()) return;
2049
0
2050
0
    /* An empty ClassDef assigns class zero to every glyph, so every glyph in
2051
0
     * `glyphs` intersects class zero.  Handle it up front: the loops below are
2052
0
     * no-ops when there are no ranges, and the `g != HB_SET_VALUE_INVALID`
2053
0
     * guard would then wrongly skip adding class zero. */
2054
0
    if (!rangeRecord.len)
2055
0
    {
2056
0
      intersect_classes->add (0);
2057
0
      return;
2058
0
    }
2059
0
2060
0
    hb_codepoint_t g = HB_SET_VALUE_INVALID;
2061
0
    for (auto &range : rangeRecord)
2062
0
    {
2063
0
      if (!glyphs->next (&g))
2064
0
        break;
2065
0
      if (g < range.first)
2066
0
      {
2067
0
        intersect_classes->add (0);
2068
0
        break;
2069
0
      }
2070
0
      g = range.last;
2071
0
    }
2072
0
    if (g != HB_SET_VALUE_INVALID && glyphs->next (&g))
2073
0
      intersect_classes->add (0);
2074
0
2075
0
    for (const auto& range : rangeRecord)
2076
0
      if (range.intersects (*glyphs))
2077
0
        intersect_classes->add (range.value);
2078
0
  }
Unexecuted instantiation: OT::ClassDefFormat2_4<OT::Layout::SmallTypes>::intersected_classes(hb_set_t const*, hb_set_t*) const
Unexecuted instantiation: OT::ClassDefFormat2_4<OT::Layout::MediumTypes>::intersected_classes(hb_set_t const*, hb_set_t*) const
2079
2080
  protected:
2081
  HBUINT16  classFormat;  /* Format identifier--format = 2 */
2082
  typename Types::template SortedArrayOf<RangeRecord<Types>>
2083
    rangeRecord;  /* Array of glyph ranges--ordered by
2084
         * Start GlyphID */
2085
  public:
2086
  DEFINE_SIZE_ARRAY (2 + Types::size, rangeRecord);
2087
};
2088
2089
struct ClassDef
2090
{
2091
  /* Has interface. */
2092
0
  unsigned operator [] (hb_codepoint_t k) const { return get (k); }
2093
0
  bool has (hb_codepoint_t k) const { return (*this)[k]; }
2094
  /* Projection. */
2095
0
  hb_codepoint_t operator () (hb_codepoint_t k) const { return get (k); }
2096
2097
0
  unsigned int get (hb_codepoint_t k) const { return get_class (k); }
2098
  unsigned int get_class (hb_codepoint_t glyph_id) const
2099
6.61k
  {
2100
6.61k
    switch (u.format.v) {
2101
0
    case 1: hb_barrier (); return u.format1.get_class (glyph_id);
2102
20
    case 2: hb_barrier (); return u.format2.get_class (glyph_id);
2103
0
#ifndef HB_NO_BEYOND_64K
2104
0
    case 3: hb_barrier (); return u.format3.get_class (glyph_id);
2105
0
    case 4: hb_barrier (); return u.format4.get_class (glyph_id);
2106
0
#endif
2107
6.59k
    default:return 0;
2108
6.61k
    }
2109
6.61k
  }
2110
  unsigned int get_class (hb_codepoint_t glyph_id,
2111
        hb_ot_layout_mapping_cache_t *cache) const
2112
0
  {
2113
0
    unsigned klass;
2114
0
    if (cache && cache->get (glyph_id, &klass)) return klass;
2115
0
    klass = get_class (glyph_id);
2116
0
    if (cache) cache->set (glyph_id, klass);
2117
0
    return klass;
2118
0
  }
2119
2120
  unsigned get_population () const
2121
0
  {
2122
0
    switch (u.format.v) {
2123
0
    case 1: hb_barrier (); return u.format1.get_population ();
2124
0
    case 2: hb_barrier (); return u.format2.get_population ();
2125
0
#ifndef HB_NO_BEYOND_64K
2126
0
    case 3: hb_barrier (); return u.format3.get_population ();
2127
0
    case 4: hb_barrier (); return u.format4.get_population ();
2128
0
#endif
2129
0
    default:return NOT_COVERED;
2130
0
    }
2131
0
  }
2132
2133
  template<typename Iterator,
2134
     hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
2135
  bool serialize (hb_serialize_context_t *c, Iterator it_with_class_zero)
2136
0
  {
2137
0
    TRACE_SERIALIZE (this);
2138
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
2139
0
2140
0
    auto glyphs = + it_with_class_zero | hb_filter (hb_second);
2141
0
2142
0
    unsigned format = 2;
2143
0
    hb_codepoint_t glyph_max = 0;
2144
0
    unsigned class_max = 0;
2145
0
    if (likely (glyphs))
2146
0
    {
2147
0
      hb_codepoint_t glyph_min = (*glyphs).first;
2148
0
      glyph_max = glyph_min;
2149
0
2150
0
      unsigned num_ranges = 1;
2151
0
      hb_codepoint_t prev_gid = glyph_min;
2152
0
      unsigned prev_klass = (*glyphs).second;
2153
0
2154
0
      for (const auto gid_klass_pair : + glyphs)
2155
0
      {
2156
0
  hb_codepoint_t cur_gid = gid_klass_pair.first;
2157
0
  unsigned cur_klass = gid_klass_pair.second;
2158
0
  if (cur_klass > class_max) class_max = cur_klass;
2159
0
  if (cur_gid == glyph_min) continue;
2160
0
        if (cur_gid > glyph_max) glyph_max = cur_gid;
2161
0
  if (cur_gid != prev_gid + 1 ||
2162
0
      cur_klass != prev_klass)
2163
0
    num_ranges++;
2164
0
2165
0
  prev_gid = cur_gid;
2166
0
  prev_klass = cur_klass;
2167
0
      }
2168
0
2169
0
      uint64_t best_size = UINT64_MAX;
2170
0
      unsigned glyph_span = glyph_max - glyph_min + 1;
2171
0
      auto consider = [&] (unsigned candidate, uint64_t size)
2172
0
      {
2173
0
  if (size >= best_size) return;
2174
0
  best_size = size;
2175
0
  format = candidate;
2176
0
      };
2177
0
2178
0
      if (glyph_max <= 0xFFFFu && glyph_span <= 0xFFFFu && class_max <= 0xFFFFu)
2179
0
  consider (1, 6 + (uint64_t) HBUINT16::static_size * glyph_span);
2180
0
      if (glyph_max <= 0xFFFFu && num_ranges <= 0xFFFFu && class_max <= 0xFFFFu)
2181
0
  consider (2, 4 + (uint64_t) num_ranges *
2182
0
         (2 * HBGlyphID16::static_size + HBUINT16::static_size));
2183
0
#ifndef HB_NO_BEYOND_64K
2184
0
      if (glyph_max <= 0xFFFFFFu && glyph_span <= 0xFFFFFFu && class_max <= 0xFFFFFFu)
2185
0
  consider (3, 8 + (uint64_t) HBUINT24::static_size * glyph_span);
2186
0
      if (glyph_max <= 0xFFFFFFu && num_ranges <= 0xFFFFFFu && class_max <= 0xFFFFu)
2187
0
  consider (4, 5 + (uint64_t) num_ranges *
2188
0
         (2 * HBGlyphID24::static_size + HBUINT16::static_size));
2189
0
#endif
2190
0
      if (unlikely (best_size == UINT64_MAX))
2191
0
      {
2192
0
  c->check_success (false, HB_SERIALIZE_ERROR_INT_OVERFLOW);
2193
0
  return_trace (false);
2194
0
      }
2195
0
    }
2196
0
2197
0
    u.format.v = format;
2198
0
2199
0
    switch (u.format.v)
2200
0
    {
2201
0
    case 1: hb_barrier (); return_trace (u.format1.serialize (c, + it_with_class_zero | hb_filter (hb_second)));
2202
0
    case 2: hb_barrier (); return_trace (u.format2.serialize (c, + it_with_class_zero | hb_filter (hb_second)));
2203
0
#ifndef HB_NO_BEYOND_64K
2204
0
    case 3: hb_barrier (); return_trace (u.format3.serialize (c, + it_with_class_zero | hb_filter (hb_second)));
2205
0
    case 4: hb_barrier (); return_trace (u.format4.serialize (c, + it_with_class_zero | hb_filter (hb_second)));
2206
0
#endif
2207
0
    default:return_trace (false);
2208
0
    }
2209
0
  }
2210
2211
  bool subset (hb_subset_context_t *c,
2212
         hb_map_t *klass_map = nullptr /*OUT*/,
2213
               bool keep_empty_table = true,
2214
               bool use_class_zero = true,
2215
               const Coverage* glyph_filter = nullptr) const
2216
0
  {
2217
0
    TRACE_SUBSET (this);
2218
0
    switch (u.format.v) {
2219
0
    case 1: hb_barrier (); return_trace (u.format1.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
2220
0
    case 2: hb_barrier (); return_trace (u.format2.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
2221
0
#ifndef HB_NO_BEYOND_64K
2222
0
    case 3: hb_barrier (); return_trace (u.format3.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
2223
0
    case 4: hb_barrier (); return_trace (u.format4.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
2224
0
#endif
2225
0
    default:return_trace (false);
2226
0
    }
2227
0
  }
2228
2229
  bool sanitize (hb_sanitize_context_t *c) const
2230
537
  {
2231
537
    TRACE_SANITIZE (this);
2232
537
    if (!u.format.v.sanitize (c)) return_trace (false);
2233
537
    hb_barrier ();
2234
537
    switch (u.format.v) {
2235
209
    case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
2236
328
    case 2: hb_barrier (); return_trace (u.format2.sanitize (c));
2237
0
#ifndef HB_NO_BEYOND_64K
2238
0
    case 3: hb_barrier (); return_trace (u.format3.sanitize (c));
2239
0
    case 4: hb_barrier (); return_trace (u.format4.sanitize (c));
2240
0
#endif
2241
0
    default:return_trace (true);
2242
537
    }
2243
537
  }
2244
2245
  unsigned cost () const
2246
254
  {
2247
254
    switch (u.format.v) {
2248
121
    case 1: hb_barrier (); return u.format1.cost ();
2249
133
    case 2: hb_barrier (); return u.format2.cost ();
2250
0
#ifndef HB_NO_BEYOND_64K
2251
0
    case 3: hb_barrier (); return u.format3.cost ();
2252
0
    case 4: hb_barrier (); return u.format4.cost ();
2253
0
#endif
2254
0
    default:return 0u;
2255
254
    }
2256
254
  }
2257
2258
  /* Might return false if array looks unsorted.
2259
   * Used for faster rejection of corrupt data. */
2260
  template <typename set_t>
2261
  bool collect_coverage (set_t *glyphs) const
2262
0
  {
2263
0
    switch (u.format.v) {
2264
0
    case 1: hb_barrier (); return u.format1.collect_coverage (glyphs);
2265
0
    case 2: hb_barrier (); return u.format2.collect_coverage (glyphs);
2266
0
#ifndef HB_NO_BEYOND_64K
2267
0
    case 3: hb_barrier (); return u.format3.collect_coverage (glyphs);
2268
0
    case 4: hb_barrier (); return u.format4.collect_coverage (glyphs);
2269
0
#endif
2270
0
    default:return false;
2271
0
    }
2272
0
  }
2273
2274
  /* Might return false if array looks unsorted.
2275
   * Used for faster rejection of corrupt data. */
2276
  template <typename set_t>
2277
  bool collect_class (set_t *glyphs, unsigned int klass) const
2278
156
  {
2279
156
    switch (u.format.v) {
2280
66
    case 1: hb_barrier (); return u.format1.collect_class (glyphs, klass);
2281
90
    case 2: hb_barrier (); return u.format2.collect_class (glyphs, klass);
2282
0
#ifndef HB_NO_BEYOND_64K
2283
0
    case 3: hb_barrier (); return u.format3.collect_class (glyphs, klass);
2284
0
    case 4: hb_barrier (); return u.format4.collect_class (glyphs, klass);
2285
0
#endif
2286
0
    default:return false;
2287
156
    }
2288
156
  }
Unexecuted instantiation: bool OT::ClassDef::collect_class<hb_set_t>(hb_set_t*, unsigned int) const
bool OT::ClassDef::collect_class<hb_set_digest_t>(hb_set_digest_t*, unsigned int) const
Line
Count
Source
2278
156
  {
2279
156
    switch (u.format.v) {
2280
66
    case 1: hb_barrier (); return u.format1.collect_class (glyphs, klass);
2281
90
    case 2: hb_barrier (); return u.format2.collect_class (glyphs, klass);
2282
0
#ifndef HB_NO_BEYOND_64K
2283
0
    case 3: hb_barrier (); return u.format3.collect_class (glyphs, klass);
2284
0
    case 4: hb_barrier (); return u.format4.collect_class (glyphs, klass);
2285
0
#endif
2286
0
    default:return false;
2287
156
    }
2288
156
  }
2289
2290
  bool intersects (const hb_set_t *glyphs) const
2291
0
  {
2292
0
    switch (u.format.v) {
2293
0
    case 1: hb_barrier (); return u.format1.intersects (glyphs);
2294
0
    case 2: hb_barrier (); return u.format2.intersects (glyphs);
2295
0
#ifndef HB_NO_BEYOND_64K
2296
0
    case 3: hb_barrier (); return u.format3.intersects (glyphs);
2297
0
    case 4: hb_barrier (); return u.format4.intersects (glyphs);
2298
0
#endif
2299
0
    default:return false;
2300
0
    }
2301
0
  }
2302
  bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
2303
0
  {
2304
0
    switch (u.format.v) {
2305
0
    case 1: hb_barrier (); return u.format1.intersects_class (glyphs, klass);
2306
0
    case 2: hb_barrier (); return u.format2.intersects_class (glyphs, klass);
2307
0
#ifndef HB_NO_BEYOND_64K
2308
0
    case 3: hb_barrier (); return u.format3.intersects_class (glyphs, klass);
2309
0
    case 4: hb_barrier (); return u.format4.intersects_class (glyphs, klass);
2310
0
#endif
2311
0
    default:return false;
2312
0
    }
2313
0
  }
2314
2315
  void intersected_class_glyphs (const hb_set_t *glyphs, unsigned klass, hb_set_t *intersect_glyphs) const
2316
0
  {
2317
0
    switch (u.format.v) {
2318
0
    case 1: hb_barrier (); return u.format1.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
2319
0
    case 2: hb_barrier (); return u.format2.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
2320
0
#ifndef HB_NO_BEYOND_64K
2321
0
    case 3: hb_barrier (); return u.format3.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
2322
0
    case 4: hb_barrier (); return u.format4.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
2323
0
#endif
2324
0
    default:return;
2325
0
    }
2326
0
  }
2327
2328
  void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const
2329
0
  {
2330
0
    switch (u.format.v) {
2331
0
    case 1: hb_barrier (); return u.format1.intersected_classes (glyphs, intersect_classes);
2332
0
    case 2: hb_barrier (); return u.format2.intersected_classes (glyphs, intersect_classes);
2333
0
#ifndef HB_NO_BEYOND_64K
2334
0
    case 3: hb_barrier (); return u.format3.intersected_classes (glyphs, intersect_classes);
2335
0
    case 4: hb_barrier (); return u.format4.intersected_classes (glyphs, intersect_classes);
2336
0
#endif
2337
0
    default:return;
2338
0
    }
2339
0
  }
2340
2341
2342
  protected:
2343
  union {
2344
  struct { HBUINT16 v; }  format;   /* Format identifier */
2345
  ClassDefFormat1_3<SmallTypes> format1;
2346
  ClassDefFormat2_4<SmallTypes> format2;
2347
#ifndef HB_NO_BEYOND_64K
2348
  ClassDefFormat1_3<MediumTypes>format3;
2349
  ClassDefFormat2_4<MediumTypes>format4;
2350
#endif
2351
  } u;
2352
  public:
2353
  DEFINE_SIZE_UNION (2, format.v);
2354
};
2355
2356
template<typename Iterator>
2357
static inline bool ClassDef_serialize (hb_serialize_context_t *c,
2358
               Iterator it)
2359
0
{ return (c->start_embed<ClassDef> ()->serialize (c, it)); }
Unexecuted instantiation: hb-face.cc:bool OT::ClassDef_serialize<hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const> >(hb_serialize_context_t*, hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const>)
Unexecuted instantiation: hb-font.cc:bool OT::ClassDef_serialize<hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const> >(hb_serialize_context_t*, hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const>)
Unexecuted instantiation: hb-ot-face.cc:bool OT::ClassDef_serialize<hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const> >(hb_serialize_context_t*, hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const>)
Unexecuted instantiation: hb-ot-font.cc:bool OT::ClassDef_serialize<hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const> >(hb_serialize_context_t*, hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const>)
Unexecuted instantiation: VARC.cc:bool OT::ClassDef_serialize<hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const> >(hb_serialize_context_t*, hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const>)
Unexecuted instantiation: hb-ot-metrics.cc:bool OT::ClassDef_serialize<hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const> >(hb_serialize_context_t*, hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const>)
Unexecuted instantiation: hb-ot-shape.cc:bool OT::ClassDef_serialize<hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const> >(hb_serialize_context_t*, hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const>)
Unexecuted instantiation: hb-ot-var.cc:bool OT::ClassDef_serialize<hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const> >(hb_serialize_context_t*, hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const>)
Unexecuted instantiation: hb-static.cc:bool OT::ClassDef_serialize<hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const> >(hb_serialize_context_t*, hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const>)
Unexecuted instantiation: hb-ft.cc:bool OT::ClassDef_serialize<hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const> >(hb_serialize_context_t*, hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const>)
Unexecuted instantiation: hb-aat-layout.cc:bool OT::ClassDef_serialize<hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const> >(hb_serialize_context_t*, hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const>)
Unexecuted instantiation: hb-aat-map.cc:bool OT::ClassDef_serialize<hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const> >(hb_serialize_context_t*, hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const>)
Unexecuted instantiation: hb-ot-cff1-table.cc:bool OT::ClassDef_serialize<hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const> >(hb_serialize_context_t*, hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const>)
Unexecuted instantiation: hb-ot-cff2-table.cc:bool OT::ClassDef_serialize<hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const> >(hb_serialize_context_t*, hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const>)
Unexecuted instantiation: hb-ot-layout.cc:bool OT::ClassDef_serialize<hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const> >(hb_serialize_context_t*, hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const>)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:bool OT::ClassDef_serialize<hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const> >(hb_serialize_context_t*, hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const>)
Unexecuted instantiation: hb-ot-shape-fallback.cc:bool OT::ClassDef_serialize<hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const> >(hb_serialize_context_t*, hb_sorted_array_t<hb_pair_t<unsigned int, unsigned int> const>)
2360
2361
2362
/*
2363
 * Item Variation Store
2364
 */
2365
2366
/* ported from fonttools (class _Encoding) */
2367
struct delta_row_encoding_t
2368
{
2369
  /* each byte represents a region, value is one of 0/1/2/4, which means bytes
2370
   * needed for this region */
2371
  struct chars_t : hb_vector_t<uint8_t>
2372
  {
2373
    int cmp (const chars_t& other) const
2374
0
    {
2375
0
      return as_array ().cmp (other.as_array ());
2376
0
    }
2377
2378
    hb_pair_t<unsigned, unsigned> get_width ()
2379
0
    {
2380
0
      unsigned width = 0;
2381
0
      unsigned columns = 0;
2382
0
      for (unsigned i = 0; i < length; i++)
2383
0
      {
2384
0
  unsigned v = arrayZ[i];
2385
0
  width += v;
2386
0
  columns += (v != 0);
2387
0
      }
2388
0
      return hb_pair (width, columns);
2389
0
    }
2390
2391
    HB_HOT
2392
    hb_pair_t<unsigned, unsigned> combine_width (const chars_t& other) const
2393
0
    {
2394
0
      unsigned combined_width = 0;
2395
0
      unsigned combined_columns = 0;
2396
0
      for (unsigned i = 0; i < length; i++)
2397
0
      {
2398
0
        unsigned v = hb_max (arrayZ[i], other.arrayZ[i]);
2399
0
  combined_width += v;
2400
0
  combined_columns += (v != 0);
2401
0
      }
2402
0
      return hb_pair (combined_width, combined_columns);
2403
0
    }
2404
  };
2405
2406
0
  hb_pair_t<unsigned, unsigned> combine_width (const delta_row_encoding_t& other_encoding) const { return chars.combine_width (other_encoding.chars); }
2407
2408
  // Actual data
2409
2410
  chars_t chars;
2411
  unsigned width = 0;
2412
  unsigned overhead = 0;
2413
  hb_vector_t<const hb_vector_t<int>*> items;
2414
2415
  delta_row_encoding_t () = default;
2416
  delta_row_encoding_t (hb_vector_t<const hb_vector_t<int>*> &&rows, unsigned num_cols)
2417
0
  {
2418
0
    assert (rows);
2419
0
2420
0
    items = std::move (rows);
2421
0
2422
0
    if (unlikely (!chars.resize (num_cols)))
2423
0
      return;
2424
0
2425
0
    calculate_chars ();
2426
0
  }
2427
2428
  void merge (const delta_row_encoding_t& other)
2429
0
  {
2430
0
    items.alloc (items.length + other.items.length);
2431
0
    for (auto &row : other.items)
2432
0
      add_row (row);
2433
0
2434
0
    // Merge chars
2435
0
    assert (chars.length == other.chars.length);
2436
0
    for (unsigned i = 0; i < chars.length; i++)
2437
0
      chars.arrayZ[i] = hb_max (chars.arrayZ[i], other.chars.arrayZ[i]);
2438
0
    chars_changed ();
2439
0
  }
2440
2441
  void chars_changed ()
2442
0
  {
2443
0
    auto _ = chars.get_width ();
2444
0
    width = _.first;
2445
0
    overhead = get_chars_overhead (_.second);
2446
0
  }
2447
2448
  void calculate_chars ()
2449
0
  {
2450
0
    assert (items);
2451
0
2452
0
    bool long_words = false;
2453
0
2454
0
    for (auto &row : items)
2455
0
    {
2456
0
      assert (row->length == chars.length);
2457
0
2458
0
      /* 0/1/2 byte encoding */
2459
0
      for (unsigned i = 0; i < row->length; i++)
2460
0
      {
2461
0
  int v =  row->arrayZ[i];
2462
0
  if (v == 0)
2463
0
    continue;
2464
0
  else if (v > 32767 || v < -32768)
2465
0
  {
2466
0
    long_words = true;
2467
0
    chars.arrayZ[i] = hb_max (chars.arrayZ[i], 4);
2468
0
  }
2469
0
  else if (v > 127 || v < -128)
2470
0
    chars.arrayZ[i] = hb_max (chars.arrayZ[i], 2);
2471
0
  else
2472
0
    chars.arrayZ[i] = hb_max (chars.arrayZ[i], 1);
2473
0
      }
2474
0
    }
2475
0
2476
0
    if (long_words)
2477
0
    {
2478
0
      // Convert 1s to 2s
2479
0
      for (auto &v : chars)
2480
0
  if (v == 1)
2481
0
    v = 2;
2482
0
    }
2483
0
2484
0
    chars_changed ();
2485
0
  }
2486
2487
  bool is_empty () const
2488
0
  { return !items; }
2489
2490
  bool in_error () const
2491
0
  { return chars.in_error () || items.in_error (); }
2492
2493
  static inline unsigned get_chars_overhead (unsigned num_columns)
2494
0
  {
2495
0
    unsigned c = 4 + 6; // 4 bytes for LOffset, 6 bytes for VarData header
2496
0
    return c + num_columns * 2;
2497
0
  }
2498
2499
  unsigned get_gain (unsigned additional_bytes_per_rows = 1) const
2500
0
  {
2501
0
    int count = items.length;
2502
0
    return hb_max (0, (int) overhead - count * (int) additional_bytes_per_rows);
2503
0
  }
2504
2505
  int gain_from_merging (const delta_row_encoding_t& other_encoding) const
2506
0
  {
2507
0
    // Back of the envelope calculations to reject early.
2508
0
    signed additional_bytes_per_rows = other_encoding.width - width;
2509
0
    if (additional_bytes_per_rows > 0)
2510
0
    {
2511
0
      if (get_gain (additional_bytes_per_rows) == 0)
2512
0
        return 0;
2513
0
    }
2514
0
    else
2515
0
    {
2516
0
      if (other_encoding.get_gain (-additional_bytes_per_rows) == 0)
2517
0
  return 0;
2518
0
    }
2519
0
2520
0
    auto pair = combine_width (other_encoding);
2521
0
    unsigned combined_width = pair.first;
2522
0
    unsigned combined_columns = pair.second;
2523
0
2524
0
    int combined_gain = (int) overhead + (int) other_encoding.overhead;
2525
0
    combined_gain -= (combined_width - (int) width) * items.length;
2526
0
    combined_gain -= (combined_width - (int) other_encoding.width) * other_encoding.items.length;
2527
0
    combined_gain -= get_chars_overhead (combined_columns);
2528
0
2529
0
    return combined_gain;
2530
0
  }
2531
2532
  bool add_row (const hb_vector_t<int>* row)
2533
0
  { return items.push (row); }
2534
2535
  static int cmp (const void *pa, const void *pb)
2536
0
  {
2537
0
    const delta_row_encoding_t *a = (const delta_row_encoding_t *)pa;
2538
0
    const delta_row_encoding_t *b = (const delta_row_encoding_t *)pb;
2539
0
2540
0
    if (a->width != b->width)
2541
0
      return (int) a->width - (int) b->width;
2542
0
2543
0
    return b->chars.cmp (a->chars);
2544
0
  }
2545
};
2546
2547
struct VarRegionAxis
2548
{
2549
  float evaluate (int coord) const
2550
0
  {
2551
0
    int peak = peakCoord.to_int ();
2552
0
    if (peak == 0 || coord == peak)
2553
0
      return 1.f;
2554
0
    else if (coord == 0) // Faster
2555
0
      return 0.f;
2556
2557
0
    int start = startCoord.to_int (), end = endCoord.to_int ();
2558
2559
    /* TODO Move these to sanitize(). */
2560
0
    if (unlikely (start > peak || peak > end))
2561
0
      return 1.f;
2562
0
    if (unlikely (start < 0 && end > 0))
2563
0
      return 1.f;
2564
2565
0
    if (coord <= start || end <= coord)
2566
0
      return 0.f;
2567
2568
    /* Interpolate */
2569
0
    if (coord < peak)
2570
0
      return float (coord - start) / (peak - start);
2571
0
    else
2572
0
      return float (end - coord) / (end - peak);
2573
0
  }
2574
2575
  bool sanitize (hb_sanitize_context_t *c) const
2576
0
  {
2577
0
    TRACE_SANITIZE (this);
2578
0
    return_trace (c->check_struct (this));
2579
0
  }
2580
2581
  bool serialize (hb_serialize_context_t *c) const
2582
0
  {
2583
0
    TRACE_SERIALIZE (this);
2584
0
    return_trace (c->embed (this));
2585
0
  }
2586
2587
  public:
2588
  F2DOT14 startCoord;
2589
  F2DOT14 peakCoord;
2590
  F2DOT14 endCoord;
2591
  public:
2592
  DEFINE_SIZE_STATIC (6);
2593
};
2594
struct SparseVarRegionAxis
2595
{
2596
  float evaluate (const int *coords, unsigned int coord_len) const
2597
0
  {
2598
0
    unsigned i = axisIndex;
2599
0
    int coord = i < coord_len ? coords[i] : 0;
2600
0
    return axis.evaluate (coord);
2601
0
  }
2602
2603
  bool sanitize (hb_sanitize_context_t *c) const
2604
0
  {
2605
0
    TRACE_SANITIZE (this);
2606
0
    return_trace (c->check_struct (this));
2607
0
  }
2608
2609
  bool serialize (hb_serialize_context_t *c,
2610
      const SparseVarRegionAxis *src,
2611
      const hb_map_t *axis_map)
2612
0
  {
2613
0
    TRACE_SERIALIZE (this);
2614
0
    auto *out = c->embed (src);
2615
0
    if (unlikely (!out)) return_trace (false);
2616
0
    if (axis_map)
2617
0
    {
2618
0
      if (unlikely (!axis_map->has (out->axisIndex)))
2619
0
      {
2620
0
  c->err (HB_SERIALIZE_ERROR_OTHER);
2621
0
  return_trace (false);
2622
0
      }
2623
0
      if (unlikely (!c->check_assign (out->axisIndex, axis_map->get (out->axisIndex),
2624
0
            HB_SERIALIZE_ERROR_INT_OVERFLOW)))
2625
0
  return_trace (false);
2626
0
    }
2627
0
    return_trace (true);
2628
0
  }
2629
2630
  public:
2631
  HBUINT16 axisIndex;
2632
  VarRegionAxis axis;
2633
  public:
2634
  DEFINE_SIZE_STATIC (8);
2635
};
2636
2637
struct hb_scalar_cache_t
2638
{
2639
  private:
2640
  static constexpr unsigned STATIC_LENGTH = 128;
2641
  static constexpr float INVALID = NAN;
2642
2643
  public:
2644
0
  hb_scalar_cache_t () {}
2645
2646
  hb_scalar_cache_t (const hb_scalar_cache_t&) = delete;
2647
  hb_scalar_cache_t (hb_scalar_cache_t&&) = delete;
2648
  hb_scalar_cache_t& operator= (const hb_scalar_cache_t&) = delete;
2649
  hb_scalar_cache_t& operator= (hb_scalar_cache_t&&) = delete;
2650
2651
  static hb_scalar_cache_t *create (unsigned int count,
2652
            hb_scalar_cache_t *scratch_cache = nullptr)
2653
110k
  {
2654
110k
    if (!count) return (hb_scalar_cache_t *) &Null(hb_scalar_cache_t);
2655
2656
0
    if (scratch_cache && count <= STATIC_LENGTH)
2657
0
    {
2658
0
      scratch_cache->length = count;
2659
0
      scratch_cache->clear ();
2660
0
      return scratch_cache;
2661
0
    }
2662
2663
0
    auto *cache = (hb_scalar_cache_t *) hb_malloc (sizeof (hb_scalar_cache_t) - sizeof (static_values) + sizeof (static_values[0]) * count);
2664
0
    if (unlikely (!cache)) return (hb_scalar_cache_t *) &Null(hb_scalar_cache_t);
2665
2666
0
    cache->length = count;
2667
0
    cache->clear ();
2668
2669
0
    return cache;
2670
0
  }
2671
2672
  static void destroy (hb_scalar_cache_t *cache,
2673
           hb_scalar_cache_t *scratch_cache = nullptr)
2674
110k
  {
2675
110k
    if (cache != &Null(hb_scalar_cache_t) && cache != scratch_cache)
2676
0
      hb_free (cache);
2677
110k
  }
2678
2679
  void clear ()
2680
0
  {
2681
0
    auto *values = &static_values[0];
2682
0
    unsigned i = 0;
2683
0
#ifndef HB_OPTIMIZE_SIZE
2684
0
    for (; i + 3 < length; i += 4)
2685
0
    {
2686
0
      values[i + 0] = INVALID;
2687
0
      values[i + 1] = INVALID;
2688
0
      values[i + 2] = INVALID;
2689
0
      values[i + 3] = INVALID;
2690
0
    }
2691
0
#endif
2692
0
    for (; i < length; i++)
2693
0
      values[i] = INVALID;
2694
0
  }
2695
2696
  HB_ALWAYS_INLINE
2697
  bool get (unsigned i, float *value) const
2698
0
  {
2699
0
    if (unlikely (i >= length))
2700
0
    {
2701
0
      *value = 0.f;
2702
0
      return true;
2703
0
    }
2704
0
    auto *values = &static_values[0];
2705
0
    auto *cached_value = &values[i];
2706
0
    float v = *cached_value;
2707
0
    if (std::isnan (v))
2708
0
      return false;
2709
0
    *value = v;
2710
0
    return true;
2711
0
  }
2712
2713
  HB_ALWAYS_INLINE
2714
  void set (unsigned i, float value)
2715
0
  {
2716
0
    if (unlikely (i >= length)) return;
2717
0
    auto *values = &static_values[0];
2718
0
    auto *cached_value = &values[i];
2719
0
    *cached_value = value;
2720
0
  }
2721
2722
  public:
2723
  unsigned length;
2724
  private:
2725
  mutable hb_atomic_t<float> static_values[STATIC_LENGTH];
2726
};
2727
2728
struct VarRegionList
2729
{
2730
  private:
2731
  float evaluate_impl (unsigned int region_index,
2732
           const int *coords, unsigned int coord_len) const
2733
0
  {
2734
0
    const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount);
2735
0
    float v = 1.f;
2736
2737
0
    unsigned int count = axisCount;
2738
0
    for (unsigned int i = 0; i < count; i++)
2739
0
    {
2740
0
      int coord = i < coord_len ? coords[i] : 0;
2741
0
      float factor = axes[i].evaluate (coord);
2742
0
      if (factor == 0.f)
2743
0
      {
2744
0
  v = 0.f;
2745
0
  break;
2746
0
      }
2747
0
      v *= factor;
2748
0
    }
2749
2750
0
    return v;
2751
0
  }
2752
2753
  public:
2754
  HB_ALWAYS_INLINE
2755
  float evaluate (unsigned int region_index,
2756
      const int *coords, unsigned int coord_len,
2757
      hb_scalar_cache_t *cache = nullptr) const
2758
0
  {
2759
0
    if (unlikely (region_index >= regionCount))
2760
0
      return 0.;
2761
2762
0
    float v;
2763
0
    if (cache && cache->get (region_index, &v))
2764
0
      return v;
2765
2766
0
    v = evaluate_impl (region_index, coords, coord_len);
2767
2768
0
    if (cache)
2769
0
      cache->set (region_index, v);
2770
0
    return v;
2771
0
  }
2772
2773
  bool sanitize (hb_sanitize_context_t *c) const
2774
0
  {
2775
0
    TRACE_SANITIZE (this);
2776
0
    return_trace (c->check_struct (this) &&
2777
0
      hb_barrier () &&
2778
0
      axesZ.sanitize (c, axisCount * regionCount));
2779
0
  }
2780
2781
  bool serialize (hb_serialize_context_t *c,
2782
                  const hb_vector_t<hb_tag_t>& axis_tags,
2783
                  const hb_vector_t<const hb_hashmap_t<hb_tag_t, Triple>*>& regions)
2784
0
  {
2785
0
    TRACE_SERIALIZE (this);
2786
0
    unsigned axis_count = axis_tags.length;
2787
0
    unsigned region_count = regions.length;
2788
0
    if (!axis_count || !region_count) return_trace (false);
2789
0
    if (unlikely (hb_unsigned_mul_overflows (axis_count * region_count,
2790
0
                                             VarRegionAxis::static_size))) return_trace (false);
2791
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
2792
0
    axisCount = axis_count;
2793
0
    regionCount = region_count;
2794
0
2795
0
    for (unsigned r = 0; r < region_count; r++)
2796
0
    {
2797
0
      const auto& region = regions[r];
2798
0
      for (unsigned i = 0; i < axis_count; i++)
2799
0
      {
2800
0
        hb_tag_t tag = axis_tags.arrayZ[i];
2801
0
        VarRegionAxis var_region_rec;
2802
0
        Triple *coords;
2803
0
        if (region->has (tag, &coords))
2804
0
        {
2805
0
          var_region_rec.startCoord.set_float (coords->minimum);
2806
0
          var_region_rec.peakCoord.set_float (coords->middle);
2807
0
          var_region_rec.endCoord.set_float (coords->maximum);
2808
0
        }
2809
0
        else
2810
0
        {
2811
0
          var_region_rec.startCoord.set_int (0);
2812
0
          var_region_rec.peakCoord.set_int (0);
2813
0
          var_region_rec.endCoord.set_int (0);
2814
0
        }
2815
0
        if (!var_region_rec.serialize (c))
2816
0
          return_trace (false);
2817
0
      }
2818
0
    }
2819
0
    return_trace (true);
2820
0
  }
2821
2822
  bool serialize (hb_serialize_context_t *c, const VarRegionList *src, const hb_inc_bimap_t &region_map)
2823
0
  {
2824
0
    TRACE_SERIALIZE (this);
2825
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
2826
0
    axisCount = src->axisCount;
2827
0
    regionCount = region_map.get_population ();
2828
0
    if (unlikely (hb_unsigned_mul_overflows (axisCount * regionCount,
2829
0
               VarRegionAxis::static_size))) return_trace (false);
2830
0
    if (unlikely (!c->extend (this))) return_trace (false);
2831
0
    unsigned int region_count = src->regionCount;
2832
0
    for (unsigned int r = 0; r < regionCount; r++)
2833
0
    {
2834
0
      unsigned int backward = region_map.backward (r);
2835
0
      if (backward >= region_count) return_trace (false);
2836
0
      hb_memcpy (&axesZ[axisCount * r], &src->axesZ[axisCount * backward], VarRegionAxis::static_size * axisCount);
2837
0
    }
2838
0
2839
0
    return_trace (true);
2840
0
  }
2841
2842
  bool get_var_region (unsigned region_index,
2843
                       const hb_map_t& axes_old_index_tag_map,
2844
                       hb_hashmap_t<hb_tag_t, Triple>& axis_tuples /* OUT */) const
2845
0
  {
2846
0
    if (region_index >= regionCount) return false;
2847
0
    const VarRegionAxis* axis_region = axesZ.arrayZ + (region_index * axisCount);
2848
0
    for (unsigned i = 0; i < axisCount; i++)
2849
0
    {
2850
0
      hb_tag_t *axis_tag;
2851
0
      if (!axes_old_index_tag_map.has (i, &axis_tag))
2852
0
        return false;
2853
0
2854
0
      float min_val = axis_region->startCoord.to_float ();
2855
0
      float def_val = axis_region->peakCoord.to_float ();
2856
0
      float max_val = axis_region->endCoord.to_float ();
2857
0
2858
0
      if (def_val != 0.f)
2859
0
        axis_tuples.set (*axis_tag, Triple ((double) min_val, (double) def_val, (double) max_val));
2860
0
      axis_region++;
2861
0
    }
2862
0
    return !axis_tuples.in_error ();
2863
0
  }
2864
2865
  bool get_var_regions (const hb_map_t& axes_old_index_tag_map,
2866
                        hb_vector_t<hb_hashmap_t<hb_tag_t, Triple>>& regions /* OUT */) const
2867
0
  {
2868
0
    if (!regions.alloc (regionCount))
2869
0
      return false;
2870
0
2871
0
    for (unsigned i = 0; i < regionCount; i++)
2872
0
    {
2873
0
      hb_hashmap_t<hb_tag_t, Triple> axis_tuples;
2874
0
      if (!get_var_region (i, axes_old_index_tag_map, axis_tuples))
2875
0
        return false;
2876
0
      regions.push (std::move (axis_tuples));
2877
0
    }
2878
0
    return !regions.in_error ();
2879
0
  }
2880
2881
  size_t get_size () const
2882
0
  { return hb_unsigned_add_saturate (min_size,
2883
0
             hb_unsigned_mul_saturate (VarRegionAxis::static_size,
2884
0
                     axisCount, regionCount)); }
2885
2886
  public:
2887
  HBUINT16  axisCount;
2888
  HBUINT15  regionCount;
2889
  protected:
2890
  UnsizedArrayOf<VarRegionAxis>
2891
    axesZ;
2892
  public:
2893
  DEFINE_SIZE_ARRAY (4, axesZ);
2894
};
2895
2896
/* Whether a variation region is unreachable given per-axis reachable
2897
 * final-coordinate ranges, in F2Dot14 units (avar2 partial-instancing
2898
 * culling; see hb_subset_plan_t::avar2_reachable_ranges). A region is dead
2899
 * if some axis's tent evaluates to zero over the axis's entire reachable
2900
 * range. Mirrors the runtime evaluation: invalid tents evaluate as
2901
 * constant 1 and never kill a region. */
2902
static inline bool
2903
_hb_avar2_region_is_dead (const hb_hashmap_t<hb_tag_t, Triple> &axis_tuples,
2904
        const hb_hashmap_t<hb_tag_t, Triple> &reachable_ranges)
2905
0
{
2906
0
  for (auto _ : axis_tuples)
2907
0
  {
2908
0
    Triple *range;
2909
0
    if (!reachable_ranges.has (_.first, &range)) continue;
2910
0
    const Triple &tent = _.second;
2911
0
    int start = (int) roundf ((float) tent.minimum * 16384.f);
2912
0
    int peak  = (int) roundf ((float) tent.middle * 16384.f);
2913
0
    int end   = (int) roundf ((float) tent.maximum * 16384.f);
2914
0
    if (!peak) continue;
2915
0
    if (start > peak || peak > end) continue;
2916
0
    if (start < 0 && end > 0) continue;
2917
0
    int lo = (int) roundf ((float) range->minimum * 16384.f);
2918
0
    int hi = (int) roundf ((float) range->maximum * 16384.f);
2919
0
    /* Strict comparisons: the scalar is 1 (not 0) at v == peak, so a tent
2920
0
     * whose peak sits exactly on the range boundary is still live there.
2921
0
     * (Reachable ranges are padded by one F2Dot14 unit at their producer,
2922
0
     * which already covers this; strictness keeps the predicate correct on
2923
0
     * its own terms.) */
2924
0
    if (hi < start || lo > end)
2925
0
      return true;
2926
0
  }
2927
0
  return false;
2928
0
}
Unexecuted instantiation: hb-face.cc:OT::_hb_avar2_region_is_dead(hb_hashmap_t<unsigned int, Triple, false> const&, hb_hashmap_t<unsigned int, Triple, false> const&)
Unexecuted instantiation: hb-font.cc:OT::_hb_avar2_region_is_dead(hb_hashmap_t<unsigned int, Triple, false> const&, hb_hashmap_t<unsigned int, Triple, false> const&)
Unexecuted instantiation: hb-ot-face.cc:OT::_hb_avar2_region_is_dead(hb_hashmap_t<unsigned int, Triple, false> const&, hb_hashmap_t<unsigned int, Triple, false> const&)
Unexecuted instantiation: hb-ot-font.cc:OT::_hb_avar2_region_is_dead(hb_hashmap_t<unsigned int, Triple, false> const&, hb_hashmap_t<unsigned int, Triple, false> const&)
Unexecuted instantiation: VARC.cc:OT::_hb_avar2_region_is_dead(hb_hashmap_t<unsigned int, Triple, false> const&, hb_hashmap_t<unsigned int, Triple, false> const&)
Unexecuted instantiation: hb-ot-metrics.cc:OT::_hb_avar2_region_is_dead(hb_hashmap_t<unsigned int, Triple, false> const&, hb_hashmap_t<unsigned int, Triple, false> const&)
Unexecuted instantiation: hb-ot-shape.cc:OT::_hb_avar2_region_is_dead(hb_hashmap_t<unsigned int, Triple, false> const&, hb_hashmap_t<unsigned int, Triple, false> const&)
Unexecuted instantiation: hb-ot-var.cc:OT::_hb_avar2_region_is_dead(hb_hashmap_t<unsigned int, Triple, false> const&, hb_hashmap_t<unsigned int, Triple, false> const&)
Unexecuted instantiation: hb-static.cc:OT::_hb_avar2_region_is_dead(hb_hashmap_t<unsigned int, Triple, false> const&, hb_hashmap_t<unsigned int, Triple, false> const&)
Unexecuted instantiation: hb-ft.cc:OT::_hb_avar2_region_is_dead(hb_hashmap_t<unsigned int, Triple, false> const&, hb_hashmap_t<unsigned int, Triple, false> const&)
Unexecuted instantiation: hb-aat-layout.cc:OT::_hb_avar2_region_is_dead(hb_hashmap_t<unsigned int, Triple, false> const&, hb_hashmap_t<unsigned int, Triple, false> const&)
Unexecuted instantiation: hb-aat-map.cc:OT::_hb_avar2_region_is_dead(hb_hashmap_t<unsigned int, Triple, false> const&, hb_hashmap_t<unsigned int, Triple, false> const&)
Unexecuted instantiation: hb-ot-cff1-table.cc:OT::_hb_avar2_region_is_dead(hb_hashmap_t<unsigned int, Triple, false> const&, hb_hashmap_t<unsigned int, Triple, false> const&)
Unexecuted instantiation: hb-ot-cff2-table.cc:OT::_hb_avar2_region_is_dead(hb_hashmap_t<unsigned int, Triple, false> const&, hb_hashmap_t<unsigned int, Triple, false> const&)
Unexecuted instantiation: hb-ot-layout.cc:OT::_hb_avar2_region_is_dead(hb_hashmap_t<unsigned int, Triple, false> const&, hb_hashmap_t<unsigned int, Triple, false> const&)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:OT::_hb_avar2_region_is_dead(hb_hashmap_t<unsigned int, Triple, false> const&, hb_hashmap_t<unsigned int, Triple, false> const&)
Unexecuted instantiation: hb-ot-shape-fallback.cc:OT::_hb_avar2_region_is_dead(hb_hashmap_t<unsigned int, Triple, false> const&, hb_hashmap_t<unsigned int, Triple, false> const&)
2929
2930
struct SparseVariationRegion
2931
{
2932
  float evaluate (const int *coords, unsigned int coord_len) const
2933
0
  {
2934
0
    float v = 1.f;
2935
0
    unsigned int count = axes.len;
2936
0
    for (unsigned int i = 0; i < count; i++)
2937
0
    {
2938
0
      float factor = (this+axes[i]).evaluate (coords, coord_len);
2939
0
      if (factor == 0.f)
2940
0
  return 0.;
2941
0
      v *= factor;
2942
0
    }
2943
0
    return v;
2944
0
  }
2945
2946
  bool serialize (hb_serialize_context_t *c,
2947
      const SparseVariationRegion *src,
2948
      const hb_map_t *axis_map)
2949
0
  {
2950
0
    TRACE_SERIALIZE (this);
2951
0
    if (unlikely (!axes.serialize (c, (unsigned) src->axes.len))) return_trace (false);
2952
0
    for (unsigned i = 0; i < axes.len; i++)
2953
0
      if (unlikely (src->axes[i].is_null () ||
2954
0
        !axes[i].serialize_serialize (c, &(src+src->axes[i]), axis_map)))
2955
0
  return_trace (false);
2956
0
    return_trace (true);
2957
0
  }
2958
2959
  bool sanitize (hb_sanitize_context_t *c) const
2960
0
  {
2961
0
    TRACE_SANITIZE (this);
2962
0
    return_trace (axes.sanitize (c, this));
2963
0
  }
2964
2965
  protected:
2966
  Array16Of<Offset32To<SparseVarRegionAxis>> axes;
2967
  public:
2968
  DEFINE_SIZE_ARRAY (2, axes);
2969
};
2970
2971
struct SparseVarRegionList
2972
{
2973
  HB_ALWAYS_INLINE
2974
  float evaluate (unsigned int region_index,
2975
      const int *coords, unsigned int coord_len,
2976
      hb_scalar_cache_t *cache = nullptr) const
2977
0
  {
2978
0
    if (unlikely (region_index >= regions.len))
2979
0
      return 0.;
2980
2981
0
    float v;
2982
0
    if (cache && cache->get (region_index, &v))
2983
0
      return v;
2984
2985
0
    const SparseVariationRegion &region = this+regions[region_index];
2986
2987
0
    v = region.evaluate (coords, coord_len);
2988
0
    if (cache)
2989
0
      cache->set (region_index, v);
2990
2991
0
    return v;
2992
0
  }
2993
2994
  bool sanitize (hb_sanitize_context_t *c) const
2995
0
  {
2996
0
    TRACE_SANITIZE (this);
2997
0
    return_trace (regions.sanitize (c, this));
2998
0
  }
2999
3000
  bool serialize (hb_serialize_context_t *c,
3001
      const SparseVarRegionList *src,
3002
      const hb_inc_bimap_t &region_map,
3003
      const hb_map_t *axis_map)
3004
0
  {
3005
0
    TRACE_SERIALIZE (this);
3006
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
3007
0
    regions.len = region_map.get_population ();
3008
0
    if (unlikely (!c->extend (regions))) return_trace (false);
3009
0
3010
0
    for (unsigned i = 0; i < regions.len; i++)
3011
0
    {
3012
0
      unsigned old_index = region_map.backward (i);
3013
0
      if (unlikely (old_index >= src->regions.len ||
3014
0
        !regions[i].serialize_serialize (c,
3015
0
               &(src+src->regions[old_index]),
3016
0
               axis_map)))
3017
0
  return_trace (false);
3018
0
    }
3019
0
    return_trace (true);
3020
0
  }
3021
3022
  public:
3023
  Array32Of<Offset32To<SparseVariationRegion>>
3024
    regions;
3025
  public:
3026
  DEFINE_SIZE_ARRAY (4, regions);
3027
};
3028
3029
3030
struct VarData
3031
{
3032
  unsigned int get_item_count () const
3033
0
  { return itemCount; }
3034
3035
  unsigned int get_region_index_count () const
3036
0
  { return regionIndices.len; }
3037
3038
  unsigned get_region_index (unsigned i) const
3039
0
  { return i >= regionIndices.len ? -1 : regionIndices[i]; }
3040
3041
  size_t get_row_size () const
3042
0
  { return (wordCount () + regionIndices.len) * (longWords () ? 2 : 1); }
3043
3044
  size_t get_size () const
3045
0
  { return hb_unsigned_add_saturate (min_size - regionIndices.min_size,
3046
0
             regionIndices.get_size (),
3047
0
             hb_unsigned_mul_saturate (itemCount, get_row_size ())); }
3048
3049
  template <typename Float = float>
3050
  Float _get_delta (unsigned int inner,
3051
        const int *coords, unsigned int coord_count,
3052
        const VarRegionList &regions,
3053
        hb_scalar_cache_t *cache = nullptr) const
3054
0
  {
3055
0
    if (unlikely (inner >= itemCount))
3056
0
      return 0.;
3057
0
    bool is_long = longWords ();
3058
0
    unsigned int count = regionIndices.len;
3059
0
    unsigned word_count = wordCount ();
3060
0
    unsigned int scount = is_long ? count : word_count;
3061
0
    unsigned int lcount = is_long ? word_count : 0;
3062
3063
0
    const HBUINT8 *bytes = get_delta_bytes ();
3064
0
    const HBUINT8 *row = bytes + inner * get_row_size ();
3065
3066
0
    Float delta = 0;
3067
0
    unsigned int i = 0;
3068
3069
0
    const HBINT32 *lcursor = reinterpret_cast<const HBINT32 *> (row);
3070
0
    for (; i < lcount; i++)
3071
0
    {
3072
0
      float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
3073
0
      if (scalar)
3074
0
        delta += (Float) scalar * (int) *lcursor;
3075
0
      lcursor++;
3076
0
    }
3077
0
    const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (lcursor);
3078
0
    for (; i < scount; i++)
3079
0
    {
3080
0
      float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
3081
0
      if (scalar)
3082
0
       delta += (Float) scalar * (int) *scursor;
3083
0
      scursor++;
3084
0
    }
3085
0
    const HBINT8 *bcursor = reinterpret_cast<const HBINT8 *> (scursor);
3086
0
    for (; i < count; i++)
3087
0
    {
3088
0
      float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
3089
0
      if (scalar)
3090
0
        delta += (Float) scalar * (int) *bcursor;
3091
0
      bcursor++;
3092
0
    }
3093
3094
0
    return delta;
3095
0
  }
Unexecuted instantiation: float OT::VarData::_get_delta<float>(unsigned int, int const*, unsigned int, OT::VarRegionList const&, OT::hb_scalar_cache_t*) const
Unexecuted instantiation: double OT::VarData::_get_delta<double>(unsigned int, int const*, unsigned int, OT::VarRegionList const&, OT::hb_scalar_cache_t*) const
3096
3097
  template <typename Float = float>
3098
  HB_ALWAYS_INLINE
3099
  Float get_delta (unsigned int inner,
3100
       const int *coords, unsigned int coord_count,
3101
       const VarRegionList &regions,
3102
       hb_scalar_cache_t *cache = nullptr) const
3103
0
  {
3104
0
    unsigned int count = regionIndices.len;
3105
0
    if (!count) return Float (0); // This is quite common, so optimize it.
3106
0
    return _get_delta<Float> (inner, coords, coord_count, regions, cache);
3107
0
  }
Unexecuted instantiation: float OT::VarData::get_delta<float>(unsigned int, int const*, unsigned int, OT::VarRegionList const&, OT::hb_scalar_cache_t*) const
Unexecuted instantiation: double OT::VarData::get_delta<double>(unsigned int, int const*, unsigned int, OT::VarRegionList const&, OT::hb_scalar_cache_t*) const
3108
3109
  void get_region_scalars (const int *coords, unsigned int coord_count,
3110
         const VarRegionList &regions,
3111
         float *scalars /*OUT */,
3112
         unsigned int num_scalars) const
3113
0
  {
3114
0
    unsigned count = hb_min (num_scalars, regionIndices.len);
3115
0
    for (unsigned int i = 0; i < count; i++)
3116
0
      scalars[i] = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
3117
0
    for (unsigned int i = count; i < num_scalars; i++)
3118
0
      scalars[i] = 0.f;
3119
0
  }
3120
3121
  bool sanitize (hb_sanitize_context_t *c) const
3122
0
  {
3123
0
    TRACE_SANITIZE (this);
3124
0
    return_trace (c->check_struct (this) &&
3125
0
      regionIndices.sanitize (c) &&
3126
0
      hb_barrier () &&
3127
0
      wordCount () <= regionIndices.len &&
3128
0
      c->check_range (get_delta_bytes (),
3129
0
          itemCount,
3130
0
          get_row_size ()));
3131
0
  }
3132
3133
  bool serialize (hb_serialize_context_t *c,
3134
                  bool has_long,
3135
                  const hb_vector_t<const hb_vector_t<int>*>& rows)
3136
0
  {
3137
0
    TRACE_SERIALIZE (this);
3138
0
    unsigned row_count = rows.length;
3139
0
    if (!row_count) {
3140
0
      // Nothing to serialize, will be empty.
3141
0
      return false;
3142
0
    }
3143
0
3144
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
3145
0
    if (unlikely (!c->check_assign (itemCount, row_count,
3146
0
                                    HB_SERIALIZE_ERROR_INT_OVERFLOW)))
3147
0
      return_trace (false);
3148
0
3149
0
    int min_threshold = has_long ? -32768 : -128;
3150
0
    int max_threshold = has_long ? +32767 : +127;
3151
0
    enum delta_size_t { kZero=0, kNonWord, kWord };
3152
0
    hb_vector_t<delta_size_t> delta_sz;
3153
0
    unsigned num_regions = rows[0]->length;
3154
0
    if (!delta_sz.resize (num_regions))
3155
0
      return_trace (false);
3156
0
3157
0
    unsigned word_count = 0;
3158
0
    for (unsigned r = 0; r < num_regions; r++)
3159
0
    {
3160
0
      for (unsigned i = 0; i < row_count; i++)
3161
0
      {
3162
0
        int delta = rows[i]->arrayZ[r];
3163
0
        if (delta < min_threshold || delta > max_threshold)
3164
0
        {
3165
0
          delta_sz[r] = kWord;
3166
0
          word_count++;
3167
0
          break;
3168
0
        }
3169
0
        else if (delta != 0)
3170
0
        {
3171
0
          delta_sz[r] = kNonWord;
3172
0
        }
3173
0
      }
3174
0
    }
3175
0
3176
0
    /* reorder regions: words and then non-words*/
3177
0
    unsigned word_index = 0;
3178
0
    unsigned non_word_index = word_count;
3179
0
    hb_map_t ri_map;
3180
0
    for (unsigned r = 0; r < num_regions; r++)
3181
0
    {
3182
0
      if (!delta_sz[r]) continue;
3183
0
      unsigned new_r = (delta_sz[r] == kWord)? word_index++ : non_word_index++;
3184
0
      if (!ri_map.set (new_r, r))
3185
0
        return_trace (false);
3186
0
    }
3187
0
3188
0
    wordSizeCount = word_count | (has_long ? 0x8000u /* LONG_WORDS */ : 0);
3189
0
3190
0
    unsigned ri_count = ri_map.get_population ();
3191
0
    regionIndices.len = ri_count;
3192
0
    if (unlikely (!c->extend (this))) return_trace (false);
3193
0
3194
0
    for (unsigned r = 0; r < ri_count; r++)
3195
0
    {
3196
0
      hb_codepoint_t *idx;
3197
0
      if (!ri_map.has (r, &idx))
3198
0
        return_trace (false);
3199
0
      regionIndices[r] = *idx;
3200
0
    }
3201
0
3202
0
    HBUINT8 *delta_bytes = get_delta_bytes ();
3203
0
    unsigned row_size = get_row_size ();
3204
0
    for (unsigned int i = 0; i < row_count; i++)
3205
0
    {
3206
0
      for (unsigned int r = 0; r < ri_count; r++)
3207
0
      {
3208
0
        int delta = rows[i]->arrayZ[ri_map[r]];
3209
0
        set_item_delta_fast (i, r, delta, delta_bytes, row_size);
3210
0
      }
3211
0
    }
3212
0
    return_trace (true);
3213
0
  }
3214
3215
  bool serialize (hb_serialize_context_t *c,
3216
      const VarData *src,
3217
      const hb_inc_bimap_t &inner_map,
3218
      const hb_inc_bimap_t &region_map,
3219
      const hb_set_t *culled_regions = nullptr)
3220
0
  {
3221
0
    TRACE_SERIALIZE (this);
3222
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
3223
0
    itemCount = inner_map.get_next_value ();
3224
0
3225
0
    /* Optimize word count */
3226
0
    unsigned ri_count = src->regionIndices.len;
3227
0
    enum delta_size_t { kZero=0, kNonWord, kWord };
3228
0
    hb_vector_t<delta_size_t> delta_sz;
3229
0
    hb_vector_t<unsigned int> ri_map; /* maps new index to old index */
3230
0
    delta_sz.resize (ri_count);
3231
0
    ri_map.resize (ri_count);
3232
0
    unsigned int new_word_count = 0;
3233
0
    unsigned int r;
3234
0
3235
0
    const HBUINT8 *src_delta_bytes = src->get_delta_bytes ();
3236
0
    unsigned src_row_size = src->get_row_size ();
3237
0
    unsigned src_word_count = src->wordCount ();
3238
0
    bool     src_long_words = src->longWords ();
3239
0
3240
0
    bool has_long = false;
3241
0
    if (src_long_words)
3242
0
    {
3243
0
      for (r = 0; r < src_word_count; r++)
3244
0
      {
3245
0
        for (unsigned old_gid : inner_map.keys())
3246
0
  {
3247
0
    int32_t delta = src->get_item_delta_fast (old_gid, r, src_delta_bytes, src_row_size);
3248
0
    if (delta < -32768 || 32767 < delta)
3249
0
    {
3250
0
      has_long = true;
3251
0
      break;
3252
0
    }
3253
0
        }
3254
0
      }
3255
0
    }
3256
0
3257
0
    signed min_threshold = has_long ? -32768 : -128;
3258
0
    signed max_threshold = has_long ? +32767 : +127;
3259
0
    for (r = 0; r < ri_count; r++)
3260
0
    {
3261
0
      bool short_circuit = src_long_words == has_long && src_word_count <= r;
3262
0
3263
0
      delta_sz[r] = kZero;
3264
0
      if (culled_regions && culled_regions->has (src->regionIndices[r]))
3265
0
  continue; /* unreachable region: drop its column */
3266
0
      for (unsigned old_gid : inner_map.keys())
3267
0
      {
3268
0
  int32_t delta = src->get_item_delta_fast (old_gid, r, src_delta_bytes, src_row_size);
3269
0
  if (delta < min_threshold || max_threshold < delta)
3270
0
  {
3271
0
    delta_sz[r] = kWord;
3272
0
    new_word_count++;
3273
0
    break;
3274
0
  }
3275
0
  else if (delta != 0)
3276
0
  {
3277
0
    delta_sz[r] = kNonWord;
3278
0
    if (short_circuit)
3279
0
      break;
3280
0
  }
3281
0
      }
3282
0
    }
3283
0
3284
0
    unsigned int word_index = 0;
3285
0
    unsigned int non_word_index = new_word_count;
3286
0
    unsigned int new_ri_count = 0;
3287
0
    for (r = 0; r < ri_count; r++)
3288
0
      if (delta_sz[r])
3289
0
      {
3290
0
  unsigned new_r = (delta_sz[r] == kWord)? word_index++ : non_word_index++;
3291
0
  ri_map[new_r] = r;
3292
0
  new_ri_count++;
3293
0
      }
3294
0
3295
0
    wordSizeCount = new_word_count | (has_long ? 0x8000u /* LONG_WORDS */ : 0);
3296
0
3297
0
    regionIndices.len = new_ri_count;
3298
0
3299
0
    if (unlikely (!c->extend (this))) return_trace (false);
3300
0
3301
0
    for (r = 0; r < new_ri_count; r++)
3302
0
      regionIndices[r] = region_map[src->regionIndices[ri_map[r]]];
3303
0
3304
0
    HBUINT8 *delta_bytes = get_delta_bytes ();
3305
0
    unsigned row_size = get_row_size ();
3306
0
    unsigned count = itemCount;
3307
0
    for (unsigned int i = 0; i < count; i++)
3308
0
    {
3309
0
      unsigned int old = inner_map.backward (i);
3310
0
      for (unsigned int r = 0; r < new_ri_count; r++)
3311
0
  set_item_delta_fast (i, r,
3312
0
           src->get_item_delta_fast (old, ri_map[r],
3313
0
                   src_delta_bytes, src_row_size),
3314
0
           delta_bytes, row_size);
3315
0
    }
3316
0
3317
0
    return_trace (true);
3318
0
  }
3319
3320
  void collect_region_refs (hb_set_t &region_indices, const hb_inc_bimap_t &inner_map) const
3321
0
  {
3322
0
    const HBUINT8 *delta_bytes = get_delta_bytes ();
3323
0
    unsigned row_size = get_row_size ();
3324
0
3325
0
    for (unsigned int r = 0; r < regionIndices.len; r++)
3326
0
    {
3327
0
      unsigned int region = regionIndices.arrayZ[r];
3328
0
      if (region_indices.has (region)) continue;
3329
0
      for (hb_codepoint_t old_gid : inner_map.keys())
3330
0
  if (get_item_delta_fast (old_gid, r, delta_bytes, row_size) != 0)
3331
0
  {
3332
0
    region_indices.add (region);
3333
0
    break;
3334
0
  }
3335
0
    }
3336
0
  }
3337
3338
  public:
3339
  const HBUINT8 *get_delta_bytes () const
3340
0
  { return &StructAfter<HBUINT8> (regionIndices); }
3341
3342
  protected:
3343
  HBUINT8 *get_delta_bytes ()
3344
0
  { return &StructAfter<HBUINT8> (regionIndices); }
3345
3346
  public:
3347
  int32_t get_item_delta_fast (unsigned int item, unsigned int region,
3348
             const HBUINT8 *delta_bytes, unsigned row_size) const
3349
0
  {
3350
0
    if (unlikely (item >= itemCount || region >= regionIndices.len)) return 0;
3351
0
3352
0
    const HBINT8 *p = (const HBINT8 *) delta_bytes + item * row_size;
3353
0
    unsigned word_count = wordCount ();
3354
0
    bool is_long = longWords ();
3355
0
    if (is_long)
3356
0
    {
3357
0
      if (region < word_count)
3358
0
  return ((const HBINT32 *) p)[region];
3359
0
      else
3360
0
  return ((const HBINT16 *)(p + HBINT32::static_size * word_count))[region - word_count];
3361
0
    }
3362
0
    else
3363
0
    {
3364
0
      if (region < word_count)
3365
0
  return ((const HBINT16 *) p)[region];
3366
0
      else
3367
0
  return (p + HBINT16::static_size * word_count)[region - word_count];
3368
0
    }
3369
0
  }
3370
  int32_t get_item_delta (unsigned int item, unsigned int region) const
3371
0
  {
3372
0
     return get_item_delta_fast (item, region,
3373
0
         get_delta_bytes (),
3374
0
         get_row_size ());
3375
0
  }
3376
3377
  protected:
3378
  void set_item_delta_fast (unsigned int item, unsigned int region, int32_t delta,
3379
          HBUINT8 *delta_bytes, unsigned row_size)
3380
0
  {
3381
0
    HBINT8 *p = (HBINT8 *) delta_bytes + item * row_size;
3382
0
    unsigned word_count = wordCount ();
3383
0
    bool is_long = longWords ();
3384
0
    if (is_long)
3385
0
    {
3386
0
      if (region < word_count)
3387
0
  ((HBINT32 *) p)[region] = delta;
3388
0
      else
3389
0
  ((HBINT16 *)(p + HBINT32::static_size * word_count))[region - word_count] = delta;
3390
0
    }
3391
0
    else
3392
0
    {
3393
0
      if (region < word_count)
3394
0
  ((HBINT16 *) p)[region] = delta;
3395
0
      else
3396
0
  (p + HBINT16::static_size * word_count)[region - word_count] = delta;
3397
0
    }
3398
0
  }
3399
  void set_item_delta (unsigned int item, unsigned int region, int32_t delta)
3400
0
  {
3401
0
    set_item_delta_fast (item, region, delta,
3402
0
       get_delta_bytes (),
3403
0
       get_row_size ());
3404
0
  }
3405
3406
0
  bool longWords () const { return wordSizeCount & 0x8000u /* LONG_WORDS */; }
3407
0
  unsigned wordCount () const { return wordSizeCount & 0x7FFFu /* WORD_DELTA_COUNT_MASK */; }
3408
3409
  protected:
3410
  HBUINT16    itemCount;
3411
  HBUINT16    wordSizeCount;
3412
  Array16Of<HBUINT16> regionIndices;
3413
/*UnsizedArrayOf<HBUINT8>bytesX;*/
3414
  public:
3415
  DEFINE_SIZE_ARRAY (6, regionIndices);
3416
};
3417
3418
struct MultiVarData
3419
{
3420
  size_t get_size () const
3421
0
  { return hb_unsigned_add_saturate (min_size - regionIndices.min_size,
3422
0
             regionIndices.get_size ()); }
3423
3424
  const TupleList &get_delta_sets () const
3425
0
  { return this+StructAfter<decltype (deltaSetsX)> (regionIndices); }
3426
3427
  void get_delta (unsigned int inner,
3428
      const int *coords, unsigned int coord_count,
3429
      const SparseVarRegionList &regions,
3430
      hb_array_t<double> out,
3431
      hb_scalar_cache_t *cache = nullptr) const
3432
0
  {
3433
0
    auto &deltaSets = get_delta_sets ();
3434
3435
0
    auto values_iter = deltaSets.fetcher (inner);
3436
0
    unsigned regionCount = regionIndices.len;
3437
0
    unsigned skip = 0;
3438
0
    for (unsigned regionIndex = 0; regionIndex < regionCount; regionIndex++)
3439
0
    {
3440
0
      float scalar = regions.evaluate (regionIndices.arrayZ[regionIndex],
3441
0
               coords, coord_count,
3442
0
               cache);
3443
      // We skip lazily. Helps with the tail end.
3444
0
      if (scalar == 0.0f)
3445
0
        skip += out.length;
3446
0
      else
3447
0
      {
3448
0
        if (skip)
3449
0
  {
3450
0
    values_iter.skip (skip);
3451
0
    skip = 0;
3452
0
  }
3453
0
  values_iter.add_to (out, scalar);
3454
0
      }
3455
0
    }
3456
0
  }
3457
3458
  bool sanitize (hb_sanitize_context_t *c) const
3459
0
  {
3460
0
    TRACE_SANITIZE (this);
3461
0
    return_trace (format.sanitize (c) &&
3462
0
      hb_barrier () &&
3463
0
      format == 1 &&
3464
0
      regionIndices.sanitize (c) &&
3465
0
      hb_barrier () &&
3466
0
      StructAfter<decltype (deltaSetsX)> (regionIndices).sanitize (c, this));
3467
0
  }
3468
3469
  unsigned get_item_count () const
3470
0
  { return get_delta_sets ().count; }
3471
3472
  void collect_region_refs (hb_set_t &region_indices) const
3473
0
  {
3474
0
    for (unsigned region : regionIndices)
3475
0
      region_indices.add (region);
3476
0
  }
3477
3478
  bool serialize (hb_serialize_context_t *c,
3479
      const MultiVarData *src,
3480
      const hb_inc_bimap_t &inner_map,
3481
      const hb_inc_bimap_t &region_map)
3482
0
  {
3483
0
    TRACE_SERIALIZE (this);
3484
0
    unsigned region_count = src->regionIndices.len;
3485
0
    unsigned header_size = HBUINT8::static_size +
3486
0
         Array16Of<HBUINT16>::min_size +
3487
0
         region_count * HBUINT16::static_size +
3488
0
         HBUINT32::static_size;
3489
0
    if (unlikely (!c->extend_size (this, header_size, false)))
3490
0
      return_trace (false);
3491
0
    format = 1;
3492
0
    regionIndices.len = region_count;
3493
0
    for (unsigned i = 0; i < regionIndices.len; i++)
3494
0
    {
3495
0
      unsigned old_region = src->regionIndices[i];
3496
0
      if (unlikely (!region_map.has (old_region)))
3497
0
  return_trace (false);
3498
0
      regionIndices[i] = region_map.get (old_region);
3499
0
    }
3500
0
3501
0
    const auto &src_delta_sets = src->get_delta_sets ();
3502
0
    hb_vector_t<hb_ubytes_t> delta_sets;
3503
0
    unsigned data_size = 0;
3504
0
    if (unlikely (!delta_sets.alloc_exact (inner_map.get_population ())))
3505
0
      return_trace (false);
3506
0
    for (unsigned i = 0; i < inner_map.get_population (); i++)
3507
0
    {
3508
0
      unsigned old_inner = inner_map.backward (i);
3509
0
      if (unlikely (old_inner >= src_delta_sets.count)) return_trace (false);
3510
0
      hb_ubytes_t bytes = static_cast<const CFF2Index &> (src_delta_sets)[old_inner];
3511
0
      data_size = hb_unsigned_add_saturate (data_size, bytes.length);
3512
0
      delta_sets.push (bytes);
3513
0
    }
3514
0
    if (unlikely (data_size == UINT_MAX || delta_sets.in_error ()))
3515
0
      return_trace (false);
3516
0
3517
0
    auto &out_delta_sets = StructAfter<decltype (deltaSetsX)> (regionIndices);
3518
0
    return_trace (out_delta_sets.serialize_serialize (c, delta_sets.iter (), &data_size));
3519
0
  }
3520
3521
  protected:
3522
  HBUINT8       format; // 1
3523
  Array16Of<HBUINT16> regionIndices;
3524
  Offset32To<TupleList> deltaSetsX;
3525
  public:
3526
  DEFINE_SIZE_MIN (7);
3527
};
3528
3529
struct ItemVariationStore
3530
{
3531
  friend struct item_variations_t;
3532
3533
  hb_scalar_cache_t *create_cache () const
3534
110k
  {
3535
#ifdef HB_NO_VAR
3536
    return hb_scalar_cache_t::create (0);
3537
#endif
3538
110k
    return hb_scalar_cache_t::create ((this+regions).regionCount);
3539
110k
  }
3540
3541
  static void destroy_cache (hb_scalar_cache_t *cache)
3542
110k
  {
3543
110k
    hb_scalar_cache_t::destroy (cache);
3544
110k
  }
3545
3546
  private:
3547
  template <typename Float = float>
3548
  Float get_delta (unsigned int outer, unsigned int inner,
3549
       const int *coords, unsigned int coord_count,
3550
       hb_scalar_cache_t *cache = nullptr) const
3551
0
  {
3552
#ifdef HB_NO_VAR
3553
    return Float (0);
3554
#endif
3555
3556
0
    if (unlikely (outer >= dataSets.len))
3557
0
      return Float (0);
3558
3559
0
    return (this+dataSets[outer]).get_delta<Float> (inner,
3560
0
               coords, coord_count,
3561
0
               this+regions,
3562
0
               cache);
3563
0
  }
Unexecuted instantiation: float OT::ItemVariationStore::get_delta<float>(unsigned int, unsigned int, int const*, unsigned int, OT::hb_scalar_cache_t*) const
Unexecuted instantiation: double OT::ItemVariationStore::get_delta<double>(unsigned int, unsigned int, int const*, unsigned int, OT::hb_scalar_cache_t*) const
3564
3565
  public:
3566
  bool has_delta_set (unsigned int index) const
3567
0
  {
3568
0
#ifdef HB_NO_VAR
3569
0
    return false;
3570
0
#endif
3571
0
3572
0
    unsigned int outer = index >> 16;
3573
0
    unsigned int inner = index & 0xFFFF;
3574
0
    return outer < dataSets.len &&
3575
0
     inner < (this+dataSets[outer]).get_item_count ();
3576
0
  }
3577
3578
  template <typename Float = float>
3579
  Float get_delta (unsigned int index,
3580
       const int *coords, unsigned int coord_count,
3581
       hb_scalar_cache_t *cache = nullptr) const
3582
0
  {
3583
0
    unsigned int outer = index >> 16;
3584
0
    unsigned int inner = index & 0xFFFF;
3585
0
    return get_delta<Float> (outer, inner, coords, coord_count, cache);
3586
0
  }
Unexecuted instantiation: float OT::ItemVariationStore::get_delta<float>(unsigned int, int const*, unsigned int, OT::hb_scalar_cache_t*) const
Unexecuted instantiation: double OT::ItemVariationStore::get_delta<double>(unsigned int, int const*, unsigned int, OT::hb_scalar_cache_t*) const
3587
  template <typename Float = float>
3588
  Float get_delta (unsigned int index,
3589
       hb_array_t<const int> coords,
3590
       hb_scalar_cache_t *cache = nullptr) const
3591
0
  {
3592
0
    return get_delta<Float> (index,
3593
0
          coords.arrayZ, coords.length,
3594
0
          cache);
3595
0
  }
Unexecuted instantiation: float OT::ItemVariationStore::get_delta<float>(unsigned int, hb_array_t<int const>, OT::hb_scalar_cache_t*) const
Unexecuted instantiation: double OT::ItemVariationStore::get_delta<double>(unsigned int, hb_array_t<int const>, OT::hb_scalar_cache_t*) const
3596
3597
  bool sanitize (hb_sanitize_context_t *c) const
3598
0
  {
3599
#ifdef HB_NO_VAR
3600
    return true;
3601
#endif
3602
3603
0
    TRACE_SANITIZE (this);
3604
0
    return_trace (c->check_struct (this) &&
3605
0
      hb_barrier () &&
3606
0
      format == 1 &&
3607
0
      regions.sanitize (c, this) &&
3608
0
      dataSets.sanitize (c, this));
3609
0
  }
3610
3611
  bool serialize (hb_serialize_context_t *c,
3612
                  bool has_long,
3613
                  const hb_vector_t<hb_tag_t>& axis_tags,
3614
                  const hb_vector_t<const hb_hashmap_t<hb_tag_t, Triple>*>& region_list,
3615
                  const hb_vector_t<delta_row_encoding_t>& vardata_encodings)
3616
0
  {
3617
0
    TRACE_SERIALIZE (this);
3618
0
#ifdef HB_NO_VAR
3619
0
    return_trace (false);
3620
0
#endif
3621
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
3622
0
3623
0
    format = 1;
3624
0
    if (!regions.serialize_serialize (c, axis_tags, region_list))
3625
0
      return_trace (false);
3626
0
3627
0
    unsigned num_var_data = vardata_encodings.length;
3628
0
    if (!num_var_data) return_trace (false);
3629
0
    if (unlikely (!c->check_assign (dataSets.len, num_var_data,
3630
0
                                    HB_SERIALIZE_ERROR_INT_OVERFLOW)))
3631
0
      return_trace (false);
3632
0
3633
0
    if (unlikely (!c->extend (dataSets))) return_trace (false);
3634
0
    for (unsigned i = 0; i < num_var_data; i++)
3635
0
      if (!dataSets[i].serialize_serialize (c, has_long, vardata_encodings[i].items))
3636
0
        return_trace (false);
3637
0
3638
0
    return_trace (true);
3639
0
  }
3640
3641
  bool serialize (hb_serialize_context_t *c,
3642
      const ItemVariationStore *src,
3643
      const hb_array_t <const hb_inc_bimap_t> &inner_maps,
3644
      const hb_set_t *culled_regions = nullptr)
3645
0
  {
3646
0
    TRACE_SERIALIZE (this);
3647
0
#ifdef HB_NO_VAR
3648
0
    return_trace (false);
3649
0
#endif
3650
0
3651
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
3652
0
3653
0
    unsigned int set_count = 0;
3654
0
    for (unsigned int i = 0; i < inner_maps.length; i++)
3655
0
      if (inner_maps[i].get_population ())
3656
0
  set_count++;
3657
0
3658
0
    format = 1;
3659
0
3660
0
    const auto &src_regions = src+src->regions;
3661
0
3662
0
    hb_set_t region_indices;
3663
0
    for (unsigned int i = 0; i < inner_maps.length; i++)
3664
0
      (src+src->dataSets[i]).collect_region_refs (region_indices, inner_maps[i]);
3665
0
3666
0
    if (region_indices.in_error ())
3667
0
      return_trace (false);
3668
0
3669
0
    region_indices.del_range ((src_regions).regionCount, hb_set_t::INVALID);
3670
0
3671
0
    if (culled_regions)
3672
0
      region_indices.subtract (*culled_regions);
3673
0
3674
0
    /* TODO use constructor when our data-structures support that. */
3675
0
    hb_inc_bimap_t region_map;
3676
0
    + hb_iter (region_indices)
3677
0
    | hb_apply ([&region_map] (unsigned _) { region_map.add(_); })
3678
0
    ;
3679
0
    if (region_map.in_error())
3680
0
      return_trace (false);
3681
0
3682
0
    if (unlikely (!regions.serialize_serialize (c, &src_regions, region_map)))
3683
0
      return_trace (false);
3684
0
3685
0
    dataSets.len = set_count;
3686
0
    if (unlikely (!c->extend (dataSets))) return_trace (false);
3687
0
3688
0
    /* TODO: The following code could be simplified when
3689
0
     * List16OfOffset16To::subset () can take a custom param to be passed to VarData::serialize () */
3690
0
    unsigned int set_index = 0;
3691
0
    for (unsigned int i = 0; i < inner_maps.length; i++)
3692
0
    {
3693
0
      if (!inner_maps[i].get_population ()) continue;
3694
0
      if (unlikely (!dataSets[set_index++]
3695
0
         .serialize_serialize (c, &(src+src->dataSets[i]), inner_maps[i], region_map,
3696
0
             culled_regions)))
3697
0
  return_trace (false);
3698
0
    }
3699
0
3700
0
    return_trace (true);
3701
0
  }
3702
3703
  ItemVariationStore *copy (hb_serialize_context_t *c) const
3704
0
  {
3705
0
    TRACE_SERIALIZE (this);
3706
0
    auto *out = c->start_embed (this);
3707
0
    if (unlikely (!out)) return_trace (nullptr);
3708
0
3709
0
    hb_vector_t <hb_inc_bimap_t> inner_maps;
3710
0
    unsigned count = dataSets.len;
3711
0
    for (unsigned i = 0; i < count; i++)
3712
0
    {
3713
0
      hb_inc_bimap_t *map = inner_maps.push ();
3714
0
      if (unlikely (!c->propagate_error(inner_maps)))
3715
0
        return_trace(nullptr);
3716
0
      auto &data = this+dataSets[i];
3717
0
3718
0
      unsigned itemCount = data.get_item_count ();
3719
0
      for (unsigned j = 0; j < itemCount; j++)
3720
0
  map->add (j);
3721
0
    }
3722
0
3723
0
    if (unlikely (!out->serialize (c, this, inner_maps))) return_trace (nullptr);
3724
0
3725
0
    return_trace (out);
3726
0
  }
3727
3728
  /* Collect regions that a partial avar2 instance can never reach, per the
3729
   * plan's reachable final-coordinate ranges. */
3730
  bool collect_dead_regions (const hb_map_t &axes_old_index_tag_map,
3731
           const hb_hashmap_t<hb_tag_t, Triple> &reachable_ranges,
3732
           hb_set_t &dead_regions /* OUT */) const
3733
0
  {
3734
0
#ifndef HB_NO_VAR
3735
0
    if (!reachable_ranges.get_population ()) return true;
3736
0
    const VarRegionList &region_list = this+regions;
3737
0
    unsigned count = region_list.regionCount;
3738
0
    for (unsigned i = 0; i < count; i++)
3739
0
    {
3740
0
      hb_hashmap_t<hb_tag_t, Triple> axis_tuples;
3741
0
      if (!region_list.get_var_region (i, axes_old_index_tag_map, axis_tuples))
3742
0
  return false;
3743
0
      if (_hb_avar2_region_is_dead (axis_tuples, reachable_ranges))
3744
0
  dead_regions.add (i);
3745
0
    }
3746
0
    return !dead_regions.in_error ();
3747
0
#else
3748
0
    return true;
3749
0
#endif
3750
0
  }
3751
3752
  bool subset (hb_subset_context_t *c, const hb_array_t<const hb_inc_bimap_t> &inner_maps) const
3753
0
  {
3754
0
    TRACE_SUBSET (this);
3755
0
#ifdef HB_NO_VAR
3756
0
    return_trace (false);
3757
0
#endif
3758
0
3759
0
    ItemVariationStore *varstore_prime = c->serializer->start_embed<ItemVariationStore> ();
3760
0
    if (unlikely (!varstore_prime)) return_trace (false);
3761
0
3762
0
    /* avar2 partial instancing: cull unreachable regions. */
3763
0
    hb_set_t dead_regions;
3764
0
    if (c->plan->has_avar2)
3765
0
      if (!collect_dead_regions (c->plan->axes_old_index_tag_map,
3766
0
         c->plan->avar2_reachable_ranges,
3767
0
         dead_regions))
3768
0
  return_trace (false);
3769
0
3770
0
    varstore_prime->serialize (c->serializer, this, inner_maps,
3771
0
             dead_regions.get_population () ? &dead_regions : nullptr);
3772
0
3773
0
    return_trace (
3774
0
        !c->serializer->in_error()
3775
0
        && varstore_prime->dataSets);
3776
0
  }
3777
3778
  unsigned int get_region_index_count (unsigned int major) const
3779
0
  {
3780
#ifdef HB_NO_VAR
3781
    return 0;
3782
#endif
3783
0
    return (this+dataSets[major]).get_region_index_count ();
3784
0
  }
3785
3786
  void get_region_scalars (unsigned int major,
3787
         const int *coords, unsigned int coord_count,
3788
         float *scalars /*OUT*/,
3789
         unsigned int num_scalars) const
3790
0
  {
3791
#ifdef HB_NO_VAR
3792
    for (unsigned i = 0; i < num_scalars; i++)
3793
      scalars[i] = 0.f;
3794
    return;
3795
#endif
3796
3797
0
    (this+dataSets[major]).get_region_scalars (coords, coord_count,
3798
0
                 this+regions,
3799
0
                 &scalars[0], num_scalars);
3800
0
  }
3801
3802
  unsigned int get_sub_table_count () const
3803
0
   {
3804
0
#ifdef HB_NO_VAR
3805
0
     return 0;
3806
0
#endif
3807
0
     return dataSets.len;
3808
0
   }
3809
3810
  const VarData& get_sub_table (unsigned i) const
3811
0
  {
3812
0
#ifdef HB_NO_VAR
3813
0
     return Null (VarData);
3814
0
#endif
3815
0
     return this+dataSets[i];
3816
0
  }
3817
3818
  const VarRegionList& get_region_list () const
3819
0
  {
3820
0
#ifdef HB_NO_VAR
3821
0
     return Null (VarRegionList);
3822
0
#endif
3823
0
     return this+regions;
3824
0
  }
3825
3826
  protected:
3827
  HBUINT16        format;
3828
  Offset32To<VarRegionList>   regions;
3829
  Array16OfOffset32To<VarData>    dataSets;
3830
  public:
3831
  DEFINE_SIZE_ARRAY_SIZED (8, dataSets);
3832
};
3833
3834
struct MultiItemVariationStore
3835
{
3836
  hb_scalar_cache_t *create_cache (hb_scalar_cache_t *static_cache = nullptr) const
3837
0
  {
3838
#ifdef HB_NO_VAR
3839
    return hb_scalar_cache_t::create (0);
3840
#endif
3841
0
    auto &r = this+regions;
3842
0
    unsigned count = r.regions.len;
3843
3844
0
    return hb_scalar_cache_t::create (count, static_cache);
3845
0
  }
3846
3847
  static void destroy_cache (hb_scalar_cache_t *cache,
3848
           hb_scalar_cache_t *static_cache = nullptr)
3849
0
  {
3850
0
    hb_scalar_cache_t::destroy (cache, static_cache);
3851
0
  }
3852
3853
  private:
3854
  void get_delta (unsigned int outer, unsigned int inner,
3855
      const int *coords, unsigned int coord_count,
3856
      hb_array_t<double> out,
3857
      hb_scalar_cache_t *cache = nullptr) const
3858
0
  {
3859
#ifdef HB_NO_VAR
3860
    return;
3861
#endif
3862
3863
0
    if (unlikely (outer >= dataSets.len))
3864
0
      return;
3865
3866
0
    return (this+dataSets[outer]).get_delta (inner,
3867
0
               coords, coord_count,
3868
0
               this+regions,
3869
0
               out,
3870
0
               cache);
3871
0
  }
3872
3873
  public:
3874
  void get_delta (unsigned int index,
3875
      const int *coords, unsigned int coord_count,
3876
      hb_array_t<double> out,
3877
      hb_scalar_cache_t *cache = nullptr) const
3878
0
  {
3879
0
    unsigned int outer = index >> 16;
3880
0
    unsigned int inner = index & 0xFFFF;
3881
0
    get_delta (outer, inner, coords, coord_count, out, cache);
3882
0
  }
3883
  void get_delta (unsigned int index,
3884
      hb_array_t<const int> coords,
3885
      hb_array_t<double> out,
3886
      hb_scalar_cache_t *cache = nullptr) const
3887
0
  {
3888
0
    return get_delta (index,
3889
0
          coords.arrayZ, coords.length,
3890
0
          out,
3891
0
          cache);
3892
0
  }
3893
3894
  bool sanitize (hb_sanitize_context_t *c) const
3895
0
  {
3896
#ifdef HB_NO_VAR
3897
    return true;
3898
#endif
3899
3900
0
    TRACE_SANITIZE (this);
3901
0
    return_trace (c->check_struct (this) &&
3902
0
      hb_barrier () &&
3903
0
      format == 1 &&
3904
0
      regions.sanitize (c, this) &&
3905
0
      dataSets.sanitize (c, this));
3906
0
  }
3907
3908
  bool create_subset_plan (const hb_set_t &var_indices,
3909
         hb_vector_t<hb_inc_bimap_t> *inner_maps,
3910
         hb_map_t *varidx_map) const
3911
0
  {
3912
0
    if (unlikely (!inner_maps->resize (dataSets.len))) return false;
3913
0
    for (hb_codepoint_t var_idx : var_indices)
3914
0
    {
3915
0
      unsigned outer = var_idx >> 16;
3916
0
      unsigned inner = var_idx & 0xFFFFu;
3917
0
      if (unlikely (outer >= dataSets.len ||
3918
0
        inner >= (this+dataSets[outer]).get_item_count ()))
3919
0
  return false;
3920
0
      (*inner_maps)[outer].add (inner);
3921
0
    }
3922
0
3923
0
    unsigned new_outer = 0;
3924
0
    for (unsigned outer = 0; outer < inner_maps->length; outer++)
3925
0
    {
3926
0
      const hb_inc_bimap_t &inner_map = (*inner_maps)[outer];
3927
0
      if (!inner_map.get_population ()) continue;
3928
0
      if (unlikely (inner_map.in_error ())) return false;
3929
0
      for (unsigned new_inner = 0;
3930
0
     new_inner < inner_map.get_population ();
3931
0
     new_inner++)
3932
0
      {
3933
0
  unsigned old_inner = inner_map.backward (new_inner);
3934
0
  varidx_map->set ((outer << 16) | old_inner,
3935
0
      (new_outer << 16) | new_inner);
3936
0
      }
3937
0
      new_outer++;
3938
0
    }
3939
0
    return !inner_maps->in_error () && !varidx_map->in_error ();
3940
0
  }
3941
3942
  bool serialize (hb_serialize_context_t *c,
3943
      const MultiItemVariationStore *src,
3944
      const hb_array_t<const hb_inc_bimap_t> &inner_maps,
3945
      const hb_map_t *axis_map)
3946
0
  {
3947
0
    TRACE_SERIALIZE (this);
3948
0
    if (unlikely (!c->extend_min (this) ||
3949
0
      inner_maps.length < src->dataSets.len))
3950
0
      return_trace (false);
3951
0
    format = 1;
3952
0
3953
0
    const auto &src_regions = src+src->regions;
3954
0
    hb_set_t region_indices;
3955
0
    unsigned set_count = 0;
3956
0
    for (unsigned i = 0; i < src->dataSets.len; i++)
3957
0
    {
3958
0
      if (!inner_maps[i].get_population ()) continue;
3959
0
      set_count++;
3960
0
      (src+src->dataSets[i]).collect_region_refs (region_indices);
3961
0
    }
3962
0
    region_indices.del_range (src_regions.regions.len, hb_set_t::INVALID);
3963
0
    hb_inc_bimap_t region_map;
3964
0
    region_map.add_set (&region_indices);
3965
0
    if (unlikely (region_indices.in_error () || region_map.in_error () ||
3966
0
      !regions.serialize_serialize (c, &src_regions, region_map, axis_map)))
3967
0
      return_trace (false);
3968
0
3969
0
    dataSets.len = set_count;
3970
0
    if (unlikely (!c->extend (dataSets))) return_trace (false);
3971
0
    unsigned set_index = 0;
3972
0
    for (unsigned i = 0; i < src->dataSets.len; i++)
3973
0
    {
3974
0
      if (!inner_maps[i].get_population ()) continue;
3975
0
      if (unlikely (!dataSets[set_index++].serialize_serialize (
3976
0
          c, &(src+src->dataSets[i]), inner_maps[i], region_map)))
3977
0
  return_trace (false);
3978
0
    }
3979
0
    return_trace (true);
3980
0
  }
3981
3982
  protected:
3983
  HBUINT16        format; // 1
3984
  Offset32To<SparseVarRegionList> regions;
3985
  Array16OfOffset32To<MultiVarData> dataSets;
3986
  public:
3987
  DEFINE_SIZE_ARRAY_SIZED (8, dataSets);
3988
};
3989
3990
template <typename MapCountT>
3991
struct DeltaSetIndexMapFormat01
3992
{
3993
  friend struct DeltaSetIndexMap;
3994
3995
  size_t get_size () const
3996
0
  { return hb_unsigned_mul_add_saturate (mapCount, get_width (), min_size); }
Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned short, 2u> >::get_size() const
Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned int, 4u> >::get_size() const
3997
3998
  private:
3999
  DeltaSetIndexMapFormat01* copy (hb_serialize_context_t *c) const
4000
0
  {
4001
0
    TRACE_SERIALIZE (this);
4002
0
    return_trace (c->embed (this));
4003
0
  }
Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned short, 2u> >::copy(hb_serialize_context_t*) const
Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned int, 4u> >::copy(hb_serialize_context_t*) const
4004
4005
  template <typename T>
4006
  bool serialize (hb_serialize_context_t *c, const T &plan)
4007
0
  {
4008
0
    unsigned int width = plan.get_width ();
4009
0
    unsigned int inner_bit_count = plan.get_inner_bit_count ();
4010
0
    const hb_array_t<const uint32_t> output_map = plan.get_output_map ();
4011
0
4012
0
    TRACE_SERIALIZE (this);
4013
0
    if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0))))
4014
0
      return_trace (false);
4015
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
4016
0
4017
0
    entryFormat = ((width-1)<<4)|(inner_bit_count-1);
4018
0
    mapCount = output_map.length;
4019
0
    HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length);
4020
0
    if (unlikely (!p)) return_trace (false);
4021
0
    for (unsigned int i = 0; i < output_map.length; i++)
4022
0
    {
4023
0
      unsigned int v = output_map.arrayZ[i];
4024
0
      if (v)
4025
0
      {
4026
0
  unsigned int outer = v >> 16;
4027
0
  unsigned int inner = v & 0xFFFF;
4028
0
  unsigned int u = (outer << inner_bit_count) | inner;
4029
0
  for (unsigned int w = width; w > 0;)
4030
0
  {
4031
0
    p[--w] = u;
4032
0
    u >>= 8;
4033
0
  }
4034
0
      }
4035
0
      p += width;
4036
0
    }
4037
0
    return_trace (true);
4038
0
  }
Unexecuted instantiation: bool OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned short, 2u> >::serialize<OT::avar::avar2_index_map_plan_t>(hb_serialize_context_t*, OT::avar::avar2_index_map_plan_t const&)
Unexecuted instantiation: bool OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned int, 4u> >::serialize<OT::avar::avar2_index_map_plan_t>(hb_serialize_context_t*, OT::avar::avar2_index_map_plan_t const&)
Unexecuted instantiation: bool OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned short, 2u> >::serialize<OT::index_map_subset_plan_t>(hb_serialize_context_t*, OT::index_map_subset_plan_t const&)
Unexecuted instantiation: bool OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned int, 4u> >::serialize<OT::index_map_subset_plan_t>(hb_serialize_context_t*, OT::index_map_subset_plan_t const&)
Unexecuted instantiation: bool OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned short, 2u> >::serialize<OT::delta_set_index_map_subset_plan_t>(hb_serialize_context_t*, OT::delta_set_index_map_subset_plan_t const&)
Unexecuted instantiation: bool OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned int, 4u> >::serialize<OT::delta_set_index_map_subset_plan_t>(hb_serialize_context_t*, OT::delta_set_index_map_subset_plan_t const&)
4039
4040
  HB_ALWAYS_INLINE
4041
  uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */
4042
0
  {
4043
    /* If count is zero, pass value unchanged.  This takes
4044
     * care of direct mapping for advance map. */
4045
0
    if (!mapCount)
4046
0
      return v;
4047
0
    return _map (v);
4048
0
  }
Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned short, 2u> >::map(unsigned int) const
Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned int, 4u> >::map(unsigned int) const
4049
4050
  HB_HOT
4051
  uint32_t _map (unsigned int v) const /* Returns 16.16 outer.inner. */
4052
0
  {
4053
0
    if (v >= mapCount)
4054
0
      v = mapCount - 1;
4055
4056
0
    unsigned int u = 0;
4057
0
    { /* Fetch it. */
4058
0
      unsigned int w = get_width ();
4059
0
      const HBUINT8 *p = mapDataZ.arrayZ + w * v;
4060
0
      for (; w; w--)
4061
0
        u = (u << 8) + *p++;
4062
0
    }
4063
4064
0
    { /* Repack it. */
4065
0
      unsigned int n = get_inner_bit_count ();
4066
0
      unsigned int outer = u >> n;
4067
0
      unsigned int inner = u & ((1 << n) - 1);
4068
0
      u = (outer<<16) | inner;
4069
0
    }
4070
4071
0
    return u;
4072
0
  }
Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned short, 2u> >::_map(unsigned int) const
Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned int, 4u> >::_map(unsigned int) const
4073
4074
0
  unsigned get_map_count () const       { return mapCount; }
Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned short, 2u> >::get_map_count() const
Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned int, 4u> >::get_map_count() const
4075
0
  unsigned get_width () const           { return ((entryFormat >> 4) & 3) + 1; }
Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned short, 2u> >::get_width() const
Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned int, 4u> >::get_width() const
4076
0
  unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; }
Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned short, 2u> >::get_inner_bit_count() const
Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned int, 4u> >::get_inner_bit_count() const
4077
4078
4079
  bool sanitize (hb_sanitize_context_t *c) const
4080
0
  {
4081
0
    TRACE_SANITIZE (this);
4082
0
    return_trace (c->check_struct (this) &&
4083
0
      hb_barrier () &&
4084
0
                  c->check_range (mapDataZ.arrayZ,
4085
0
                                  mapCount,
4086
0
                                  get_width ()));
4087
0
  }
Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned short, 2u> >::sanitize(hb_sanitize_context_t*) const
Unexecuted instantiation: OT::DeltaSetIndexMapFormat01<OT::NumType<true, unsigned int, 4u> >::sanitize(hb_sanitize_context_t*) const
4088
4089
  protected:
4090
  HBUINT8       format;         /* Format identifier--format = 0 */
4091
  HBUINT8       entryFormat;    /* A packed field that describes the compressed
4092
                                 * representation of delta-set indices. */
4093
  MapCountT     mapCount;       /* The number of mapping entries. */
4094
  UnsizedArrayOf<HBUINT8>
4095
                mapDataZ;       /* The delta-set index mapping data. */
4096
4097
  public:
4098
  DEFINE_SIZE_ARRAY (2+MapCountT::static_size, mapDataZ);
4099
};
4100
4101
struct DeltaSetIndexMap
4102
{
4103
  template <typename T>
4104
  bool serialize (hb_serialize_context_t *c, const T &plan)
4105
0
  {
4106
0
    TRACE_SERIALIZE (this);
4107
0
    unsigned length = plan.get_output_map ().length;
4108
0
    u.format.v = length <= 0xFFFF ? 0 : 1;
4109
0
    switch (u.format.v) {
4110
0
    case 0: hb_barrier (); return_trace (u.format0.serialize (c, plan));
4111
0
    case 1: hb_barrier (); return_trace (u.format1.serialize (c, plan));
4112
0
    default:return_trace (false);
4113
0
    }
4114
0
  }
Unexecuted instantiation: bool OT::DeltaSetIndexMap::serialize<OT::avar::avar2_index_map_plan_t>(hb_serialize_context_t*, OT::avar::avar2_index_map_plan_t const&)
Unexecuted instantiation: bool OT::DeltaSetIndexMap::serialize<OT::index_map_subset_plan_t>(hb_serialize_context_t*, OT::index_map_subset_plan_t const&)
Unexecuted instantiation: bool OT::DeltaSetIndexMap::serialize<OT::delta_set_index_map_subset_plan_t>(hb_serialize_context_t*, OT::delta_set_index_map_subset_plan_t const&)
4115
4116
  uint32_t map (unsigned v) const
4117
0
  {
4118
0
    switch (u.format.v) {
4119
0
    case 0: hb_barrier (); return (u.format0.map (v));
4120
0
    case 1: hb_barrier (); return (u.format1.map (v));
4121
0
    default:return v;
4122
0
    }
4123
0
  }
4124
4125
  unsigned get_map_count () const
4126
0
  {
4127
0
    switch (u.format.v) {
4128
0
    case 0: hb_barrier (); return u.format0.get_map_count ();
4129
0
    case 1: hb_barrier (); return u.format1.get_map_count ();
4130
0
    default:return 0;
4131
0
    }
4132
0
  }
4133
4134
  unsigned get_width () const
4135
0
  {
4136
0
    switch (u.format.v) {
4137
0
    case 0: hb_barrier (); return u.format0.get_width ();
4138
0
    case 1: hb_barrier (); return u.format1.get_width ();
4139
0
    default:return 0;
4140
0
    }
4141
0
  }
4142
4143
  unsigned get_inner_bit_count () const
4144
0
  {
4145
0
    switch (u.format.v) {
4146
0
    case 0: hb_barrier (); return u.format0.get_inner_bit_count ();
4147
0
    case 1: hb_barrier (); return u.format1.get_inner_bit_count ();
4148
0
    default:return 0;
4149
0
    }
4150
0
  }
4151
4152
  bool sanitize (hb_sanitize_context_t *c) const
4153
0
  {
4154
0
    TRACE_SANITIZE (this);
4155
0
    if (!u.format.v.sanitize (c)) return_trace (false);
4156
0
    hb_barrier ();
4157
0
    switch (u.format.v) {
4158
0
    case 0: hb_barrier (); return_trace (u.format0.sanitize (c));
4159
0
    case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
4160
0
    default:return_trace (true);
4161
0
    }
4162
0
  }
4163
4164
  DeltaSetIndexMap* copy (hb_serialize_context_t *c) const
4165
0
  {
4166
0
    TRACE_SERIALIZE (this);
4167
0
    switch (u.format.v) {
4168
0
    case 0: hb_barrier (); return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format0.copy (c)));
4169
0
    case 1: hb_barrier (); return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format1.copy (c)));
4170
0
    default:return_trace (nullptr);
4171
0
    }
4172
0
  }
4173
4174
  protected:
4175
  union {
4176
  struct { HBUINT8 v; }             format;         /* Format identifier */
4177
  DeltaSetIndexMapFormat01<HBUINT16> format0;
4178
  DeltaSetIndexMapFormat01<HBUINT32> format1;
4179
  } u;
4180
  public:
4181
  DEFINE_SIZE_UNION (1, format.v);
4182
};
4183
4184
4185
struct ItemVarStoreInstancer
4186
{
4187
  ItemVarStoreInstancer (const ItemVariationStore *varStore_,
4188
       const DeltaSetIndexMap *varIdxMap,
4189
       hb_array_t<const int> coords,
4190
       hb_scalar_cache_t *cache = nullptr) :
4191
224k
    varStore (varStore_), varIdxMap (varIdxMap), coords (coords), cache (cache)
4192
224k
  {
4193
224k
    if (!varStore)
4194
0
      varStore = &Null(ItemVariationStore);
4195
    /* Like hb_font_t::has_nonzero_coords, treat explicit all-zero coordinates
4196
     * as the default instance, which uses unadjusted values (OFF 7.1). */
4197
224k
    if (!hb_any (coords))
4198
224k
      this->coords = {};
4199
224k
  }
4200
4201
0
  operator bool () const { return varStore && bool (coords); }
4202
4203
  float operator[] (uint32_t varIdx) const
4204
0
  { return (*this) (varIdx); }
4205
4206
  float operator() (uint32_t varIdx, unsigned short offset = 0) const
4207
0
  { return get_delta (varIdx, offset); }
4208
4209
  double get_condition_delta (uint32_t varIdx) const
4210
0
  { return get_delta<double> (varIdx); }
4211
4212
  template <typename Float = float>
4213
  Float get_delta (uint32_t varIdx, unsigned short offset = 0) const
4214
0
  {
4215
   /* Ordinary stores do not apply deltas at the default instance. */
4216
0
   if (!coords || varIdx == VarIdx::NO_VARIATION)
4217
0
     return Float (0);
4218
4219
0
    varIdx += offset;
4220
0
    if (varIdxMap)
4221
0
      varIdx = varIdxMap->map (varIdx);
4222
0
    return varStore->get_delta<Float> (varIdx, coords, cache);
4223
0
  }
Unexecuted instantiation: float OT::ItemVarStoreInstancer::get_delta<float>(unsigned int, unsigned short) const
Unexecuted instantiation: double OT::ItemVarStoreInstancer::get_delta<double>(unsigned int, unsigned short) const
4224
4225
  const ItemVariationStore *varStore;
4226
  const DeltaSetIndexMap *varIdxMap;
4227
  hb_array_t<const int> coords;
4228
  hb_scalar_cache_t *cache;
4229
};
4230
4231
struct MultiItemVarStoreInstancer
4232
{
4233
  MultiItemVarStoreInstancer (const MultiItemVariationStore *varStore,
4234
            const DeltaSetIndexMap *varIdxMap,
4235
            hb_array_t<const int> coords,
4236
            hb_scalar_cache_t *cache = nullptr) :
4237
0
    varStore (varStore), varIdxMap (varIdxMap), coords (coords), cache (cache)
4238
0
  {
4239
0
    if (!varStore)
4240
0
      varStore = &Null(MultiItemVariationStore);
4241
0
  }
4242
4243
0
  operator bool () const { return varStore; }
4244
4245
  double get_condition_delta (uint32_t varIdx) const
4246
0
  { return (double) (*this)[varIdx]; }
4247
4248
  double operator[] (uint32_t varIdx) const
4249
0
  {
4250
0
    double v = 0;
4251
0
    (*this) (hb_array (&v, 1), varIdx);
4252
0
    return v;
4253
0
  }
4254
4255
  void operator() (hb_array_t<double> out, uint32_t varIdx, unsigned short offset = 0) const
4256
0
  {
4257
    /* Static VARC fonts can have constant deltas even with empty coordinates. */
4258
0
    if (varIdx != VarIdx::NO_VARIATION)
4259
0
    {
4260
0
      varIdx += offset;
4261
0
      if (varIdxMap)
4262
0
  varIdx = varIdxMap->map (varIdx);
4263
0
      varStore->get_delta (varIdx, coords, out, cache);
4264
0
    }
4265
0
    else
4266
0
      for (unsigned i = 0; i < out.length; i++)
4267
0
        out.arrayZ[i] = 0.;
4268
0
  }
4269
4270
  const MultiItemVariationStore *varStore;
4271
  const DeltaSetIndexMap *varIdxMap;
4272
  hb_array_t<const int> coords;
4273
  hb_scalar_cache_t *cache;
4274
};
4275
4276
4277
/*
4278
 * Feature Variations
4279
 */
4280
enum Cond_with_Var_flag_t
4281
{
4282
  KEEP_COND_WITH_VAR = 0,
4283
  KEEP_RECORD_WITH_VAR = 1,
4284
  DROP_COND_WITH_VAR = 2,
4285
  DROP_RECORD_WITH_VAR = 3,
4286
};
4287
4288
enum lookup_condition_subset_result_t
4289
{
4290
  LOOKUP_CONDITION_SUBSET_ERROR,
4291
  LOOKUP_CONDITION_SUBSET_FALSE,
4292
  LOOKUP_CONDITION_SUBSET_TRUE,
4293
  LOOKUP_CONDITION_SUBSET_KEEP,
4294
};
4295
4296
struct Condition;
4297
4298
template <typename Instancer>
4299
static bool
4300
_hb_recurse_condition_evaluate (const struct Condition &condition,
4301
        const int *coords,
4302
        unsigned int coord_len,
4303
        Instancer *instancer);
4304
4305
struct ConditionAxisRange
4306
{
4307
  friend struct Condition;
4308
4309
  bool subset (hb_subset_context_t *c) const
4310
0
  {
4311
0
    TRACE_SUBSET (this);
4312
0
    auto *out = c->serializer->embed (this);
4313
0
    if (unlikely (!out)) return_trace (false);
4314
0
4315
0
    const hb_map_t *index_map = &c->plan->axes_index_map;
4316
0
    if (index_map->is_empty ()) return_trace (true);
4317
0
4318
0
    const hb_map_t& axes_old_index_tag_map = c->plan->axes_old_index_tag_map;
4319
0
    hb_codepoint_t *axis_tag;
4320
0
    if (!axes_old_index_tag_map.has (axisIndex, &axis_tag) ||
4321
0
        !index_map->has (axisIndex))
4322
0
      return_trace (false);
4323
0
4324
0
    const hb_hashmap_t<hb_tag_t, Triple>& normalized_axes_location = c->plan->axes_location;
4325
0
    Triple axis_limit{-1.0, 0.0, 1.0};
4326
0
    Triple *normalized_limit;
4327
0
    if (normalized_axes_location.has (*axis_tag, &normalized_limit))
4328
0
      axis_limit = *normalized_limit;
4329
0
4330
0
    const hb_hashmap_t<hb_tag_t, TripleDistances>& axes_triple_distances = c->plan->axes_triple_distances;
4331
0
    TripleDistances axis_triple_distances{1.0, 1.0};
4332
0
    TripleDistances *triple_dists;
4333
0
    if (axes_triple_distances.has (*axis_tag, &triple_dists))
4334
0
      axis_triple_distances = *triple_dists;
4335
0
4336
0
    float normalized_min = renormalizeValue ((double) filterRangeMinValue.to_float (), axis_limit, axis_triple_distances, false);
4337
0
    float normalized_max = renormalizeValue ((double) filterRangeMaxValue.to_float (), axis_limit, axis_triple_distances, false);
4338
0
    out->filterRangeMinValue.set_float (normalized_min);
4339
0
    out->filterRangeMaxValue.set_float (normalized_max);
4340
0
4341
0
    return_trace (c->serializer->check_assign (out->axisIndex, index_map->get (axisIndex),
4342
0
                                               HB_SERIALIZE_ERROR_INT_OVERFLOW));
4343
0
  }
4344
4345
  private:
4346
  Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
4347
                                             hb_map_t *condition_map /* OUT */) const
4348
0
  {
4349
0
    //invalid axis index, drop the entire record
4350
0
    if (!c->axes_index_tag_map->has (axisIndex))
4351
0
      return DROP_RECORD_WITH_VAR;
4352
0
4353
0
    hb_tag_t axis_tag = c->axes_index_tag_map->get (axisIndex);
4354
0
4355
0
    Triple axis_range (-1.0, 0.0, 1.0);
4356
0
    Triple *axis_limit;
4357
0
    bool axis_set_by_user = false;
4358
0
    if (c->axes_location->has (axis_tag, &axis_limit))
4359
0
    {
4360
0
      axis_range = *axis_limit;
4361
0
      axis_set_by_user = true;
4362
0
    }
4363
0
4364
0
    float axis_min_val = axis_range.minimum;
4365
0
    float axis_default_val = axis_range.middle;
4366
0
    float axis_max_val = axis_range.maximum;
4367
0
4368
0
    float filter_min_val = filterRangeMinValue.to_float ();
4369
0
    float filter_max_val = filterRangeMaxValue.to_float ();
4370
0
4371
0
    if (axis_default_val < filter_min_val ||
4372
0
        axis_default_val > filter_max_val)
4373
0
      c->apply = false;
4374
0
4375
0
    //condition not met, drop the entire record
4376
0
    if (axis_min_val > filter_max_val || axis_max_val < filter_min_val ||
4377
0
        filter_min_val > filter_max_val)
4378
0
      return DROP_RECORD_WITH_VAR;
4379
0
4380
0
    //condition met and axis pinned, drop the condition
4381
0
    if (axis_set_by_user && axis_range.is_point ())
4382
0
      return DROP_COND_WITH_VAR;
4383
0
4384
0
    if (filter_max_val != axis_max_val || filter_min_val != axis_min_val)
4385
0
    {
4386
0
      // add axisIndex->value into the hashmap so we can check if the record is
4387
0
      // unique with variations
4388
0
      uint16_t int_filter_max_val = (uint16_t) filterRangeMaxValue.to_int ();
4389
0
      uint16_t int_filter_min_val = (uint16_t) filterRangeMinValue.to_int ();
4390
0
      hb_codepoint_t val = (int_filter_max_val << 16) + int_filter_min_val;
4391
0
4392
0
      condition_map->set (axisIndex, val);
4393
0
      return KEEP_COND_WITH_VAR;
4394
0
    }
4395
0
    return KEEP_RECORD_WITH_VAR;
4396
0
  }
4397
4398
  template <typename Instancer>
4399
  bool evaluate (const int *coords, unsigned int coord_len,
4400
     Instancer *instancer HB_UNUSED) const
4401
0
  {
4402
0
    int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
4403
0
    return filterRangeMinValue.to_int () <= coord && coord <= filterRangeMaxValue.to_int ();
4404
0
  }
Unexecuted instantiation: bool OT::ConditionAxisRange::evaluate<OT::ItemVarStoreInstancer>(int const*, unsigned int, OT::ItemVarStoreInstancer*) const
Unexecuted instantiation: bool OT::ConditionAxisRange::evaluate<OT::MultiItemVarStoreInstancer>(int const*, unsigned int, OT::MultiItemVarStoreInstancer*) const
4405
4406
  public:
4407
  bool sanitize (hb_sanitize_context_t *c) const
4408
0
  {
4409
0
    TRACE_SANITIZE (this);
4410
0
    return_trace (c->check_struct (this));
4411
0
  }
4412
4413
  protected:
4414
  HBUINT16  format;   /* Format identifier--format = 1 */
4415
  HBUINT16  axisIndex;
4416
  F2DOT14 filterRangeMinValue;
4417
  F2DOT14 filterRangeMaxValue;
4418
  public:
4419
  DEFINE_SIZE_STATIC (8);
4420
};
4421
4422
struct ConditionValue
4423
{
4424
  friend struct Condition;
4425
4426
  bool subset (hb_subset_context_t *c) const
4427
0
  {
4428
0
    TRACE_SUBSET (this);
4429
0
    auto *out = c->serializer->embed (this);
4430
0
    if (unlikely (!out)) return_trace (false);
4431
0
4432
0
    if (varIdx == VarIdx::NO_VARIATION)
4433
0
      return_trace (true);
4434
0
4435
0
    hb_pair_t<unsigned, int> *condition_value;
4436
0
    if (c->plan->layout_condition_idx_value_map.has ((uintptr_t) this, &condition_value))
4437
0
    {
4438
0
      out->defaultValue = condition_value->second;
4439
0
      out->varIdx = condition_value->first;
4440
0
      return_trace (true);
4441
0
    }
4442
0
4443
0
    hb_pair_t<unsigned, int> *new_varidx_delta;
4444
0
    if (!c->plan->layout_variation_idx_delta_map.has (varIdx, &new_varidx_delta))
4445
0
      return_trace (false);
4446
0
4447
0
    if (unlikely (!c->serializer->check_assign (
4448
0
    out->defaultValue,
4449
0
    defaultValue + hb_second (*new_varidx_delta),
4450
0
    HB_SERIALIZE_ERROR_INT_OVERFLOW)))
4451
0
      return_trace (false);
4452
0
    out->varIdx = hb_first (*new_varidx_delta);
4453
0
    return_trace (true);
4454
0
  }
4455
4456
  private:
4457
  template <typename Instancer>
4458
  bool evaluate (const int *coords, unsigned int coord_len,
4459
     Instancer *instancer) const
4460
0
  {
4461
0
    double value = defaultValue;
4462
0
    value += instancer->get_condition_delta (varIdx);
4463
0
    return value > 0;
4464
0
  }
Unexecuted instantiation: bool OT::ConditionValue::evaluate<OT::ItemVarStoreInstancer>(int const*, unsigned int, OT::ItemVarStoreInstancer*) const
Unexecuted instantiation: bool OT::ConditionValue::evaluate<OT::MultiItemVarStoreInstancer>(int const*, unsigned int, OT::MultiItemVarStoreInstancer*) const
4465
4466
  public:
4467
  bool sanitize (hb_sanitize_context_t *c) const
4468
0
  {
4469
0
    TRACE_SANITIZE (this);
4470
0
    return_trace (c->check_struct (this));
4471
0
  }
4472
4473
  protected:
4474
  HBUINT16  format;   /* Format identifier--format = 2 */
4475
  HBINT16 defaultValue;   /* Value at default instance. */
4476
  VarIdx  varIdx;   /* Variation index */
4477
  public:
4478
  DEFINE_SIZE_STATIC (8);
4479
};
4480
4481
struct ConditionAnd
4482
{
4483
  friend struct Condition;
4484
4485
  bool subset (hb_subset_context_t *c) const
4486
0
  {
4487
0
    TRACE_SUBSET (this);
4488
0
    auto *out = c->serializer->start_embed (this);
4489
0
    if (unlikely (!out || !c->serializer->extend_min (out)))
4490
0
      return_trace (false);
4491
0
    out->format = format;
4492
0
4493
0
    for (const auto &offset : conditions)
4494
0
    {
4495
0
      if (offset.is_null ())
4496
0
      {
4497
0
  auto *out_offset = out->conditions.serialize_append (c->serializer);
4498
0
  if (unlikely (!out_offset)) return_trace (false);
4499
0
  *out_offset = 0;
4500
0
      }
4501
0
      else if (unlikely (!subset_offset_array (c, out->conditions, this) (offset)))
4502
0
  return_trace (false);
4503
0
    }
4504
0
4505
0
    return_trace (true);
4506
0
  }
4507
4508
  private:
4509
  template <typename Instancer>
4510
  bool evaluate (const int *coords, unsigned int coord_len,
4511
     Instancer *instancer) const
4512
0
  {
4513
0
    unsigned int count = conditions.len;
4514
0
    for (unsigned int i = 0; i < count; i++)
4515
0
      if (!_hb_recurse_condition_evaluate (this+conditions.arrayZ[i],
4516
0
             coords, coord_len,
4517
0
             instancer))
4518
0
  return false;
4519
0
    return true;
4520
0
  }
Unexecuted instantiation: bool OT::ConditionAnd::evaluate<OT::ItemVarStoreInstancer>(int const*, unsigned int, OT::ItemVarStoreInstancer*) const
Unexecuted instantiation: bool OT::ConditionAnd::evaluate<OT::MultiItemVarStoreInstancer>(int const*, unsigned int, OT::MultiItemVarStoreInstancer*) const
4521
4522
  public:
4523
  bool sanitize (hb_sanitize_context_t *c) const
4524
0
  {
4525
0
    TRACE_SANITIZE (this);
4526
0
    return_trace (conditions.sanitize (c, this));
4527
0
  }
4528
4529
  protected:
4530
  HBUINT16  format;   /* Format identifier--format = 3 */
4531
  Array8OfOffset24To<struct Condition>  conditions;
4532
  public:
4533
  DEFINE_SIZE_ARRAY (3, conditions);
4534
};
4535
4536
struct ConditionOr
4537
{
4538
  friend struct Condition;
4539
4540
  bool subset (hb_subset_context_t *c) const
4541
0
  {
4542
0
    TRACE_SUBSET (this);
4543
0
    auto *out = c->serializer->start_embed (this);
4544
0
    if (unlikely (!out || !c->serializer->extend_min (out)))
4545
0
      return_trace (false);
4546
0
    out->format = format;
4547
0
4548
0
    for (const auto &offset : conditions)
4549
0
    {
4550
0
      if (offset.is_null ())
4551
0
      {
4552
0
  auto *out_offset = out->conditions.serialize_append (c->serializer);
4553
0
  if (unlikely (!out_offset)) return_trace (false);
4554
0
  *out_offset = 0;
4555
0
      }
4556
0
      else if (unlikely (!subset_offset_array (c, out->conditions, this) (offset)))
4557
0
  return_trace (false);
4558
0
    }
4559
0
4560
0
    return_trace (true);
4561
0
  }
4562
4563
  private:
4564
  template <typename Instancer>
4565
  bool evaluate (const int *coords, unsigned int coord_len,
4566
     Instancer *instancer) const
4567
0
  {
4568
0
    unsigned int count = conditions.len;
4569
0
    for (unsigned int i = 0; i < count; i++)
4570
0
      if (_hb_recurse_condition_evaluate (this+conditions.arrayZ[i],
4571
0
            coords, coord_len,
4572
0
            instancer))
4573
0
  return true;
4574
0
    return false;
4575
0
  }
Unexecuted instantiation: bool OT::ConditionOr::evaluate<OT::ItemVarStoreInstancer>(int const*, unsigned int, OT::ItemVarStoreInstancer*) const
Unexecuted instantiation: bool OT::ConditionOr::evaluate<OT::MultiItemVarStoreInstancer>(int const*, unsigned int, OT::MultiItemVarStoreInstancer*) const
4576
4577
  public:
4578
  bool sanitize (hb_sanitize_context_t *c) const
4579
0
  {
4580
0
    TRACE_SANITIZE (this);
4581
0
    return_trace (conditions.sanitize (c, this));
4582
0
  }
4583
4584
  protected:
4585
  HBUINT16  format;   /* Format identifier--format = 4 */
4586
  Array8OfOffset24To<struct Condition>  conditions;
4587
  public:
4588
  DEFINE_SIZE_ARRAY (3, conditions);
4589
};
4590
4591
struct ConditionNegate
4592
{
4593
  friend struct Condition;
4594
4595
  bool subset (hb_subset_context_t *c) const
4596
0
  {
4597
0
    TRACE_SUBSET (this);
4598
0
    auto *out = c->serializer->embed (this);
4599
0
    if (unlikely (!out)) return_trace (false);
4600
0
    if (condition.is_null ())
4601
0
    {
4602
0
      out->condition = 0;
4603
0
      return_trace (true);
4604
0
    }
4605
0
    return_trace (out->condition.serialize_subset (c, condition, this));
4606
0
  }
4607
4608
  private:
4609
  template <typename Instancer>
4610
  bool evaluate (const int *coords, unsigned int coord_len,
4611
     Instancer *instancer) const
4612
0
  {
4613
0
    return !_hb_recurse_condition_evaluate (this+condition,
4614
0
              coords, coord_len,
4615
0
              instancer);
4616
0
  }
Unexecuted instantiation: bool OT::ConditionNegate::evaluate<OT::ItemVarStoreInstancer>(int const*, unsigned int, OT::ItemVarStoreInstancer*) const
Unexecuted instantiation: bool OT::ConditionNegate::evaluate<OT::MultiItemVarStoreInstancer>(int const*, unsigned int, OT::MultiItemVarStoreInstancer*) const
4617
4618
  public:
4619
  bool sanitize (hb_sanitize_context_t *c) const
4620
0
  {
4621
0
    TRACE_SANITIZE (this);
4622
0
    return_trace (condition.sanitize (c, this));
4623
0
  }
4624
4625
  protected:
4626
  HBUINT16  format;   /* Format identifier--format = 5 */
4627
  Offset24To<struct Condition>  condition;
4628
  public:
4629
  DEFINE_SIZE_STATIC (5);
4630
};
4631
4632
struct Condition
4633
{
4634
  friend struct ConditionSet;
4635
4636
  static bool serialize_constant (hb_serialize_context_t *c, bool value)
4637
0
  {
4638
0
    auto *out = c->start_embed<ConditionValue> ();
4639
0
    if (unlikely (!out || !c->extend_min (out))) return false;
4640
0
    out->format = 2;
4641
0
    out->defaultValue = value ? 1 : 0;
4642
0
    out->varIdx = VarIdx::NO_VARIATION;
4643
0
    return true;
4644
0
  }
4645
4646
  lookup_condition_subset_result_t subset_lookup_condition (
4647
              hb_subset_context_t *c,
4648
              unsigned depth = HB_MAX_NESTING_LEVEL,
4649
              bool materialize_true = false) const;
4650
4651
  template <typename Instancer>
4652
  bool evaluate (const int *coords, unsigned int coord_len,
4653
     Instancer *instancer) const
4654
0
  {
4655
0
    switch (u.format.v) {
4656
    /* A null condition offset resolves to the nil Condition, whose reserved
4657
     * format 0 represents the True condition required by the specification. */
4658
0
    case 0: return true;
4659
0
    case 1: hb_barrier (); return u.format1.evaluate (coords, coord_len, instancer);
4660
0
    case 2: hb_barrier (); return u.format2.evaluate (coords, coord_len, instancer);
4661
0
    case 3: hb_barrier (); return u.format3.evaluate (coords, coord_len, instancer);
4662
0
    case 4: hb_barrier (); return u.format4.evaluate (coords, coord_len, instancer);
4663
0
    case 5: hb_barrier (); return u.format5.evaluate (coords, coord_len, instancer);
4664
0
    default:return false;
4665
0
    }
4666
0
  }
Unexecuted instantiation: bool OT::Condition::evaluate<OT::ItemVarStoreInstancer>(int const*, unsigned int, OT::ItemVarStoreInstancer*) const
Unexecuted instantiation: bool OT::Condition::evaluate<OT::MultiItemVarStoreInstancer>(int const*, unsigned int, OT::MultiItemVarStoreInstancer*) const
4667
4668
  Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
4669
                                             hb_map_t *condition_map /* OUT */,
4670
                                             unsigned depth = HB_MAX_NESTING_LEVEL) const
4671
0
  {
4672
0
    if (unlikely (!depth))
4673
0
    {
4674
0
      c->apply = false;
4675
0
      return DROP_RECORD_WITH_VAR;
4676
0
    }
4677
0
4678
0
    switch (u.format.v) {
4679
0
    case 0: return KEEP_RECORD_WITH_VAR;
4680
0
    case 1: hb_barrier (); return u.format1.keep_with_variations (c, condition_map);
4681
0
    case 2: case 3: case 4: case 5: break;
4682
0
    default: c->apply = false; return DROP_RECORD_WITH_VAR;
4683
0
    }
4684
0
4685
0
    hb_barrier ();
4686
0
    bool applies = evaluate (c->instancer->coords.arrayZ,
4687
0
           c->instancer->coords.length, c->instancer);
4688
0
    c->apply &= applies;
4689
0
    if (c->all_axes_pinned)
4690
0
      return applies ? DROP_COND_WITH_VAR : DROP_RECORD_WITH_VAR;
4691
0
4692
0
    if (u.format.v == 2)
4693
0
      return u.format2.varIdx == VarIdx::NO_VARIATION ||
4694
0
             !c->instancer->varStore->has_delta_set (u.format2.varIdx) ?
4695
0
             (applies ? KEEP_RECORD_WITH_VAR : DROP_RECORD_WITH_VAR) :
4696
0
             KEEP_COND_WITH_VAR;
4697
0
4698
0
    auto classify_child = [c, condition_map, depth] (const Condition &child)
4699
0
    {
4700
0
      auto child_context = *c;
4701
0
      child_context.apply = true;
4702
0
      return child.keep_with_variations (&child_context, condition_map, depth - 1);
4703
0
    };
4704
0
4705
0
    if (u.format.v == 5)
4706
0
    {
4707
0
      auto result = classify_child (&u.format5 + u.format5.condition);
4708
0
      return result == DROP_RECORD_WITH_VAR ? KEEP_RECORD_WITH_VAR :
4709
0
             result == KEEP_COND_WITH_VAR ? KEEP_COND_WITH_VAR :
4710
0
             DROP_RECORD_WITH_VAR;
4711
0
    }
4712
0
4713
0
    bool is_and = u.format.v == 3;
4714
0
    bool variable = false;
4715
0
    const auto &conditions = is_and ? u.format3.conditions : u.format4.conditions;
4716
0
    const void *base = is_and ? (const void *) &u.format3 : (const void *) &u.format4;
4717
0
    for (const auto &offset : conditions)
4718
0
    {
4719
0
      auto result = classify_child (base + offset);
4720
0
      if (is_and && result == DROP_RECORD_WITH_VAR)
4721
0
        return DROP_RECORD_WITH_VAR;
4722
0
      if (!is_and && (result == DROP_COND_WITH_VAR || result == KEEP_RECORD_WITH_VAR))
4723
0
        return KEEP_RECORD_WITH_VAR;
4724
0
      variable |= result == KEEP_COND_WITH_VAR;
4725
0
    }
4726
0
    return variable ? KEEP_COND_WITH_VAR :
4727
0
           is_and ? KEEP_RECORD_WITH_VAR : DROP_RECORD_WITH_VAR;
4728
0
  }
4729
4730
  template <typename context_t, typename ...Ts>
4731
  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
4732
0
  {
4733
0
    if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
4734
0
    TRACE_DISPATCH (this, u.format.v);
4735
0
    switch (u.format.v) {
4736
0
    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
4737
0
    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
4738
0
    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
4739
0
    case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
4740
0
    case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
4741
0
    default:return_trace (c->default_return_value ());
4742
0
    }
4743
0
  }
Unexecuted instantiation: hb_subset_context_t::return_t OT::Condition::dispatch<hb_subset_context_t>(hb_subset_context_t*) const
Unexecuted instantiation: hb_sanitize_context_t::return_t OT::Condition::dispatch<hb_sanitize_context_t>(hb_sanitize_context_t*) const
4744
4745
  bool sanitize (hb_sanitize_context_t *c) const
4746
0
  {
4747
0
    TRACE_SANITIZE (this);
4748
4749
0
    if (unlikely (!c->check_start_recursion (HB_MAX_NESTING_LEVEL)))
4750
0
      return_trace (c->no_dispatch_return_value ());
4751
4752
0
    return_trace (c->end_recursion (this->dispatch (c)));
4753
0
  }
4754
4755
  bool collect_var_indices (hb_set_t *var_indices,
4756
          unsigned depth = HB_MAX_NESTING_LEVEL,
4757
                            hb_hashmap_t<uintptr_t, hb_pair_t<unsigned, int>> *condition_values = nullptr) const;
4758
4759
  bool serialize (hb_serialize_context_t *c,
4760
      const Condition *src,
4761
      const hb_map_t &varidx_map,
4762
      const hb_map_t *axis_map = nullptr);
4763
4764
  private:
4765
  lookup_condition_subset_result_t subset_lookup_condition_impl (
4766
              hb_subset_context_t *c,
4767
              unsigned depth) const;
4768
4769
  protected:
4770
  union {
4771
  struct { HBUINT16 v; }  format;   /* Format identifier */
4772
  ConditionAxisRange  format1;
4773
  ConditionValue  format2;
4774
  ConditionAnd    format3;
4775
  ConditionOr   format4;
4776
  ConditionNegate format5;
4777
  } u;
4778
  public:
4779
  DEFINE_SIZE_UNION (2, format.v);
4780
};
4781
4782
template <typename Instancer>
4783
bool
4784
_hb_recurse_condition_evaluate (const struct Condition &condition,
4785
        const int *coords,
4786
        unsigned int coord_len,
4787
        Instancer *instancer)
4788
0
{
4789
0
  return condition.evaluate (coords, coord_len, instancer);
4790
0
}
Unexecuted instantiation: hb-face.cc:bool OT::_hb_recurse_condition_evaluate<OT::ItemVarStoreInstancer>(OT::Condition const&, int const*, unsigned int, OT::ItemVarStoreInstancer*)
Unexecuted instantiation: hb-font.cc:bool OT::_hb_recurse_condition_evaluate<OT::ItemVarStoreInstancer>(OT::Condition const&, int const*, unsigned int, OT::ItemVarStoreInstancer*)
Unexecuted instantiation: hb-ot-face.cc:bool OT::_hb_recurse_condition_evaluate<OT::ItemVarStoreInstancer>(OT::Condition const&, int const*, unsigned int, OT::ItemVarStoreInstancer*)
Unexecuted instantiation: hb-ot-font.cc:bool OT::_hb_recurse_condition_evaluate<OT::ItemVarStoreInstancer>(OT::Condition const&, int const*, unsigned int, OT::ItemVarStoreInstancer*)
Unexecuted instantiation: VARC.cc:bool OT::_hb_recurse_condition_evaluate<OT::MultiItemVarStoreInstancer>(OT::Condition const&, int const*, unsigned int, OT::MultiItemVarStoreInstancer*)
Unexecuted instantiation: VARC.cc:bool OT::_hb_recurse_condition_evaluate<OT::ItemVarStoreInstancer>(OT::Condition const&, int const*, unsigned int, OT::ItemVarStoreInstancer*)
Unexecuted instantiation: hb-ot-metrics.cc:bool OT::_hb_recurse_condition_evaluate<OT::ItemVarStoreInstancer>(OT::Condition const&, int const*, unsigned int, OT::ItemVarStoreInstancer*)
Unexecuted instantiation: hb-ot-shape.cc:bool OT::_hb_recurse_condition_evaluate<OT::ItemVarStoreInstancer>(OT::Condition const&, int const*, unsigned int, OT::ItemVarStoreInstancer*)
Unexecuted instantiation: hb-ot-var.cc:bool OT::_hb_recurse_condition_evaluate<OT::ItemVarStoreInstancer>(OT::Condition const&, int const*, unsigned int, OT::ItemVarStoreInstancer*)
Unexecuted instantiation: hb-static.cc:bool OT::_hb_recurse_condition_evaluate<OT::ItemVarStoreInstancer>(OT::Condition const&, int const*, unsigned int, OT::ItemVarStoreInstancer*)
Unexecuted instantiation: hb-ft.cc:bool OT::_hb_recurse_condition_evaluate<OT::ItemVarStoreInstancer>(OT::Condition const&, int const*, unsigned int, OT::ItemVarStoreInstancer*)
Unexecuted instantiation: hb-aat-layout.cc:bool OT::_hb_recurse_condition_evaluate<OT::ItemVarStoreInstancer>(OT::Condition const&, int const*, unsigned int, OT::ItemVarStoreInstancer*)
Unexecuted instantiation: hb-aat-map.cc:bool OT::_hb_recurse_condition_evaluate<OT::ItemVarStoreInstancer>(OT::Condition const&, int const*, unsigned int, OT::ItemVarStoreInstancer*)
Unexecuted instantiation: hb-ot-cff1-table.cc:bool OT::_hb_recurse_condition_evaluate<OT::ItemVarStoreInstancer>(OT::Condition const&, int const*, unsigned int, OT::ItemVarStoreInstancer*)
Unexecuted instantiation: hb-ot-cff2-table.cc:bool OT::_hb_recurse_condition_evaluate<OT::ItemVarStoreInstancer>(OT::Condition const&, int const*, unsigned int, OT::ItemVarStoreInstancer*)
Unexecuted instantiation: hb-ot-layout.cc:bool OT::_hb_recurse_condition_evaluate<OT::ItemVarStoreInstancer>(OT::Condition const&, int const*, unsigned int, OT::ItemVarStoreInstancer*)
Unexecuted instantiation: hb-ot-shaper-arabic.cc:bool OT::_hb_recurse_condition_evaluate<OT::ItemVarStoreInstancer>(OT::Condition const&, int const*, unsigned int, OT::ItemVarStoreInstancer*)
Unexecuted instantiation: hb-ot-shape-fallback.cc:bool OT::_hb_recurse_condition_evaluate<OT::ItemVarStoreInstancer>(OT::Condition const&, int const*, unsigned int, OT::ItemVarStoreInstancer*)
4791
4792
struct ConditionList
4793
{
4794
  const Condition& operator[] (unsigned i) const
4795
0
  { return this+conditions[i]; }
4796
4797
0
  unsigned get_count () const { return conditions.len; }
4798
4799
  bool serialize (hb_serialize_context_t *c,
4800
      const ConditionList *src,
4801
      const hb_inc_bimap_t &condition_map,
4802
      const hb_map_t &varidx_map,
4803
      const hb_map_t *axis_map)
4804
0
  {
4805
0
    TRACE_SERIALIZE (this);
4806
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
4807
0
    conditions.len = condition_map.get_population ();
4808
0
    if (unlikely (!c->extend (conditions))) return_trace (false);
4809
0
    for (unsigned i = 0; i < conditions.len; i++)
4810
0
    {
4811
0
      unsigned old_index = condition_map.backward (i);
4812
0
      if (unlikely (old_index >= src->conditions.len ||
4813
0
        !conditions[i].serialize_serialize (
4814
0
      c, &(src+src->conditions[old_index]), varidx_map, axis_map)))
4815
0
  return_trace (false);
4816
0
    }
4817
0
    return_trace (true);
4818
0
  }
4819
4820
  bool sanitize (hb_sanitize_context_t *c) const
4821
0
  {
4822
0
    TRACE_SANITIZE (this);
4823
0
    return_trace (conditions.sanitize (c, this));
4824
0
  }
4825
4826
  protected:
4827
  Array32OfOffset32To<Condition> conditions;
4828
  public:
4829
  DEFINE_SIZE_ARRAY (4, conditions);
4830
};
4831
4832
inline bool
4833
Condition::collect_var_indices (hb_set_t *var_indices, unsigned depth,
4834
                               hb_hashmap_t<uintptr_t, hb_pair_t<unsigned, int>> *condition_values) const
4835
0
{
4836
0
  if (unlikely (!depth)) return false;
4837
0
  switch (u.format.v)
4838
0
  {
4839
0
    case 0:
4840
0
    case 1:
4841
0
      return true;
4842
0
    case 2:
4843
0
      if (u.format2.varIdx != VarIdx::NO_VARIATION)
4844
0
      {
4845
0
        var_indices->add (u.format2.varIdx);
4846
0
        if (condition_values &&
4847
0
            !condition_values->set ((uintptr_t) &u.format2,
4848
0
                                    hb_pair (unsigned (u.format2.varIdx), int (u.format2.defaultValue))))
4849
0
          return false;
4850
0
      }
4851
0
      return !var_indices->in_error ();
4852
0
    case 3:
4853
0
      for (const auto &offset : u.format3.conditions)
4854
0
  if (unlikely (!(&u.format3+offset).collect_var_indices (var_indices,
4855
0
                   depth - 1, condition_values)))
4856
0
    return false;
4857
0
      return true;
4858
0
    case 4:
4859
0
      for (const auto &offset : u.format4.conditions)
4860
0
  if (unlikely (!(&u.format4+offset).collect_var_indices (var_indices,
4861
0
                   depth - 1, condition_values)))
4862
0
    return false;
4863
0
      return true;
4864
0
    case 5:
4865
0
      return (&u.format5+u.format5.condition).collect_var_indices (var_indices,
4866
0
                  depth - 1, condition_values);
4867
0
    default:
4868
0
      return false;
4869
0
  }
4870
0
}
4871
4872
inline bool
4873
Condition::serialize (hb_serialize_context_t *c,
4874
          const Condition *src,
4875
          const hb_map_t &varidx_map,
4876
          const hb_map_t *axis_map)
4877
0
{
4878
0
  TRACE_SERIALIZE (this);
4879
0
  switch (src->u.format.v)
4880
0
  {
4881
0
    case 0:
4882
0
    {
4883
0
      auto *out = c->start_embed<ConditionValue> ();
4884
0
      if (unlikely (!out || !c->extend_min (out))) return_trace (false);
4885
0
      out->format = 2;
4886
0
      out->defaultValue = 1;
4887
0
      out->varIdx = VarIdx::NO_VARIATION;
4888
0
      return_trace (true);
4889
0
    }
4890
0
    case 1:
4891
0
    {
4892
0
      auto *out = c->embed (&src->u.format1);
4893
0
      if (unlikely (!out)) return_trace (false);
4894
0
      if (axis_map)
4895
0
      {
4896
0
  if (unlikely (!axis_map->has (out->axisIndex)))
4897
0
  {
4898
0
    c->err (HB_SERIALIZE_ERROR_OTHER);
4899
0
    return_trace (false);
4900
0
  }
4901
0
  if (unlikely (!c->check_assign (out->axisIndex, axis_map->get (out->axisIndex),
4902
0
              HB_SERIALIZE_ERROR_INT_OVERFLOW)))
4903
0
    return_trace (false);
4904
0
      }
4905
0
      return_trace (true);
4906
0
    }
4907
0
    case 2:
4908
0
    {
4909
0
      auto *out = c->embed (&src->u.format2);
4910
0
      if (unlikely (!out ||
4911
0
        (src->u.format2.varIdx != VarIdx::NO_VARIATION &&
4912
0
         !varidx_map.has (src->u.format2.varIdx))))
4913
0
  return_trace (false);
4914
0
      out->varIdx = src->u.format2.varIdx == VarIdx::NO_VARIATION ?
4915
0
        src->u.format2.varIdx : varidx_map.get (src->u.format2.varIdx);
4916
0
      return_trace (true);
4917
0
    }
4918
0
    case 3:
4919
0
    {
4920
0
      auto *out = c->start_embed<ConditionAnd> ();
4921
0
      if (unlikely (!c->extend_min (out))) return_trace (false);
4922
0
      out->format = 3;
4923
0
      out->conditions.len = src->u.format3.conditions.len;
4924
0
      if (unlikely (!c->extend (out->conditions))) return_trace (false);
4925
0
      for (unsigned i = 0; i < out->conditions.len; i++)
4926
0
  if (unlikely (!out->conditions[i].serialize_serialize (
4927
0
      c, &(&src->u.format3+src->u.format3.conditions[i]),
4928
0
      varidx_map, axis_map)))
4929
0
    return_trace (false);
4930
0
      return_trace (true);
4931
0
    }
4932
0
    case 4:
4933
0
    {
4934
0
      auto *out = c->start_embed<ConditionOr> ();
4935
0
      if (unlikely (!c->extend_min (out))) return_trace (false);
4936
0
      out->format = 4;
4937
0
      out->conditions.len = src->u.format4.conditions.len;
4938
0
      if (unlikely (!c->extend (out->conditions))) return_trace (false);
4939
0
      for (unsigned i = 0; i < out->conditions.len; i++)
4940
0
  if (unlikely (!out->conditions[i].serialize_serialize (
4941
0
      c, &(&src->u.format4+src->u.format4.conditions[i]),
4942
0
      varidx_map, axis_map)))
4943
0
    return_trace (false);
4944
0
      return_trace (true);
4945
0
    }
4946
0
    case 5:
4947
0
    {
4948
0
      auto *out = c->embed (&src->u.format5);
4949
0
      if (unlikely (!out ||
4950
0
        !out->condition.serialize_serialize (
4951
0
      c, &(&src->u.format5+src->u.format5.condition),
4952
0
      varidx_map, axis_map)))
4953
0
  return_trace (false);
4954
0
      return_trace (true);
4955
0
    }
4956
0
    default:
4957
0
      return_trace (false);
4958
0
  }
4959
0
}
4960
4961
inline lookup_condition_subset_result_t
4962
Condition::subset_lookup_condition (hb_subset_context_t *c,
4963
            unsigned depth,
4964
            bool materialize_true) const
4965
0
{
4966
0
  auto snap = c->serializer->snapshot ();
4967
0
  lookup_condition_subset_result_t result =
4968
0
      subset_lookup_condition_impl (c, depth);
4969
0
  if (result == LOOKUP_CONDITION_SUBSET_KEEP)
4970
0
    return result;
4971
0
4972
0
  c->serializer->revert (snap);
4973
0
  if (result != LOOKUP_CONDITION_SUBSET_TRUE || !materialize_true)
4974
0
    return result;
4975
0
4976
0
  return serialize_constant (c->serializer, true) ?
4977
0
         LOOKUP_CONDITION_SUBSET_KEEP : LOOKUP_CONDITION_SUBSET_ERROR;
4978
0
}
4979
4980
inline lookup_condition_subset_result_t
4981
Condition::subset_lookup_condition_impl (hb_subset_context_t *c,
4982
           unsigned depth) const
4983
0
{
4984
0
  if (unlikely (!depth))
4985
0
    return LOOKUP_CONDITION_SUBSET_ERROR;
4986
0
4987
0
  auto subset_offset = [c, depth] (Array8OfOffset24To<Condition> &out,
4988
0
           const Condition &condition)
4989
0
      -> lookup_condition_subset_result_t
4990
0
  {
4991
0
    auto snap = c->serializer->snapshot ();
4992
0
    auto *offset = out.serialize_append (c->serializer);
4993
0
    if (unlikely (!offset))
4994
0
      return LOOKUP_CONDITION_SUBSET_ERROR;
4995
0
4996
0
    c->serializer->push ();
4997
0
    lookup_condition_subset_result_t result =
4998
0
        condition.subset_lookup_condition (c, depth - 1);
4999
0
    if (result == LOOKUP_CONDITION_SUBSET_KEEP)
5000
0
      c->serializer->add_link (*offset, c->serializer->pop_pack ());
5001
0
    else
5002
0
    {
5003
0
      c->serializer->pop_discard ();
5004
0
      out.pop ();
5005
0
      c->serializer->revert (snap);
5006
0
    }
5007
0
    return result;
5008
0
  };
5009
0
5010
0
  switch (u.format.v)
5011
0
  {
5012
0
    case 0:
5013
0
      return LOOKUP_CONDITION_SUBSET_TRUE;
5014
0
5015
0
    case 1:
5016
0
    {
5017
0
      const ConditionAxisRange &src = u.format1;
5018
0
      if (c->plan->user_axes_location.is_empty ())
5019
0
        return c->serializer->embed (&src) ?
5020
0
               LOOKUP_CONDITION_SUBSET_KEEP :
5021
0
               LOOKUP_CONDITION_SUBSET_ERROR;
5022
0
5023
0
      hb_codepoint_t *axis_tag;
5024
0
      if (!c->plan->axes_old_index_tag_map.has (src.axisIndex, &axis_tag))
5025
0
        return LOOKUP_CONDITION_SUBSET_ERROR;
5026
0
5027
0
      Triple axis_limit {-1.f, 0.f, 1.f};
5028
0
      Triple *normalized_limit;
5029
0
      if (c->plan->axes_location.has (*axis_tag, &normalized_limit))
5030
0
        axis_limit = *normalized_limit;
5031
0
5032
0
      float filter_min = src.filterRangeMinValue.to_float ();
5033
0
      float filter_max = src.filterRangeMaxValue.to_float ();
5034
0
      if (filter_min > filter_max)
5035
0
        return LOOKUP_CONDITION_SUBSET_FALSE;
5036
0
      if (axis_limit.is_point ())
5037
0
        return filter_min <= axis_limit.middle &&
5038
0
         axis_limit.middle <= filter_max ?
5039
0
         LOOKUP_CONDITION_SUBSET_TRUE :
5040
0
         LOOKUP_CONDITION_SUBSET_FALSE;
5041
0
      if (axis_limit.maximum < filter_min ||
5042
0
    filter_max < axis_limit.minimum)
5043
0
        return LOOKUP_CONDITION_SUBSET_FALSE;
5044
0
      if (filter_min <= axis_limit.minimum &&
5045
0
    axis_limit.maximum <= filter_max)
5046
0
        return LOOKUP_CONDITION_SUBSET_TRUE;
5047
0
      if (!c->plan->axes_index_map.has (src.axisIndex))
5048
0
        return LOOKUP_CONDITION_SUBSET_ERROR;
5049
0
5050
0
      auto *out = c->serializer->embed (&src);
5051
0
      if (unlikely (!out))
5052
0
        return LOOKUP_CONDITION_SUBSET_ERROR;
5053
0
5054
0
      TripleDistances axis_distances {1.f, 1.f};
5055
0
      TripleDistances *distances;
5056
0
      if (c->plan->axes_triple_distances.has (*axis_tag, &distances))
5057
0
        axis_distances = *distances;
5058
0
5059
0
      out->filterRangeMinValue.set_float (
5060
0
    renormalizeValue (filter_min, axis_limit, axis_distances, false));
5061
0
      out->filterRangeMaxValue.set_float (
5062
0
    renormalizeValue (filter_max, axis_limit, axis_distances, false));
5063
0
      if (unlikely (!c->serializer->check_assign (
5064
0
    out->axisIndex,
5065
0
    c->plan->axes_index_map.get (src.axisIndex),
5066
0
    HB_SERIALIZE_ERROR_INT_OVERFLOW)))
5067
0
        return LOOKUP_CONDITION_SUBSET_ERROR;
5068
0
      return LOOKUP_CONDITION_SUBSET_KEEP;
5069
0
    }
5070
0
5071
0
    case 2:
5072
0
    {
5073
0
      const ConditionValue &src = u.format2;
5074
0
      auto *out = c->serializer->embed (&src);
5075
0
      if (unlikely (!out))
5076
0
        return LOOKUP_CONDITION_SUBSET_ERROR;
5077
0
5078
0
      if (src.varIdx == VarIdx::NO_VARIATION)
5079
0
        return c->plan->user_axes_location.is_empty () ?
5080
0
               LOOKUP_CONDITION_SUBSET_KEEP :
5081
0
               ((int) src.defaultValue > 0 ?
5082
0
    LOOKUP_CONDITION_SUBSET_TRUE :
5083
0
    LOOKUP_CONDITION_SUBSET_FALSE);
5084
0
5085
0
      hb_pair_t<unsigned, int> *condition_value;
5086
0
      if (c->plan->layout_condition_idx_value_map.has ((uintptr_t) &src, &condition_value))
5087
0
      {
5088
0
        out->defaultValue = condition_value->second;
5089
0
        out->varIdx = condition_value->first;
5090
0
        if (out->varIdx == VarIdx::NO_VARIATION)
5091
0
          return out->defaultValue > 0 ? LOOKUP_CONDITION_SUBSET_TRUE :
5092
0
                                        LOOKUP_CONDITION_SUBSET_FALSE;
5093
0
        return LOOKUP_CONDITION_SUBSET_KEEP;
5094
0
      }
5095
0
5096
0
      hb_pair_t<unsigned, int> *new_varidx_delta;
5097
0
      if (!c->plan->layout_variation_idx_delta_map.has (src.varIdx,
5098
0
              &new_varidx_delta))
5099
0
        return c->plan->user_axes_location.is_empty () ?
5100
0
               LOOKUP_CONDITION_SUBSET_KEEP :
5101
0
               ((int) src.defaultValue > 0 ?
5102
0
    LOOKUP_CONDITION_SUBSET_TRUE :
5103
0
    LOOKUP_CONDITION_SUBSET_FALSE);
5104
0
5105
0
      if (!c->plan->user_axes_location.is_empty () &&
5106
0
          hb_first (*new_varidx_delta) == VarIdx::NO_VARIATION)
5107
0
      {
5108
0
        // Conditions becoming constant depend on the unrounded sign, not
5109
0
        // the integer delta used to instance positioning values.
5110
0
        double value = (int) src.defaultValue +
5111
0
                      c->plan->layout_variation_delta (src.varIdx);
5112
0
        return value > 0 ? LOOKUP_CONDITION_SUBSET_TRUE :
5113
0
                          LOOKUP_CONDITION_SUBSET_FALSE;
5114
0
      }
5115
0
5116
0
      int default_value = (int) src.defaultValue +
5117
0
        hb_second (*new_varidx_delta);
5118
0
      if (unlikely (!c->serializer->check_assign (
5119
0
    out->defaultValue,
5120
0
    default_value,
5121
0
    HB_SERIALIZE_ERROR_INT_OVERFLOW)))
5122
0
        return LOOKUP_CONDITION_SUBSET_ERROR;
5123
0
      out->varIdx = hb_first (*new_varidx_delta);
5124
0
5125
0
      return LOOKUP_CONDITION_SUBSET_KEEP;
5126
0
    }
5127
0
5128
0
    case 3:
5129
0
    {
5130
0
      const ConditionAnd &src = u.format3;
5131
0
      auto *out = c->serializer->start_embed (&src);
5132
0
      if (unlikely (!out || !c->serializer->extend_min (out)))
5133
0
        return LOOKUP_CONDITION_SUBSET_ERROR;
5134
0
      out->format = 3;
5135
0
5136
0
      for (const auto &offset : src.conditions)
5137
0
      {
5138
0
        lookup_condition_subset_result_t result =
5139
0
            subset_offset (out->conditions, &src + offset);
5140
0
        if (result == LOOKUP_CONDITION_SUBSET_ERROR ||
5141
0
      result == LOOKUP_CONDITION_SUBSET_FALSE)
5142
0
          return result;
5143
0
      }
5144
0
      return out->conditions ?
5145
0
       LOOKUP_CONDITION_SUBSET_KEEP :
5146
0
       LOOKUP_CONDITION_SUBSET_TRUE;
5147
0
    }
5148
0
5149
0
    case 4:
5150
0
    {
5151
0
      const ConditionOr &src = u.format4;
5152
0
      auto *out = c->serializer->start_embed (&src);
5153
0
      if (unlikely (!out || !c->serializer->extend_min (out)))
5154
0
        return LOOKUP_CONDITION_SUBSET_ERROR;
5155
0
      out->format = 4;
5156
0
5157
0
      for (const auto &offset : src.conditions)
5158
0
      {
5159
0
        lookup_condition_subset_result_t result =
5160
0
            subset_offset (out->conditions, &src + offset);
5161
0
        if (result == LOOKUP_CONDITION_SUBSET_ERROR ||
5162
0
      result == LOOKUP_CONDITION_SUBSET_TRUE)
5163
0
          return result;
5164
0
      }
5165
0
      return out->conditions ?
5166
0
       LOOKUP_CONDITION_SUBSET_KEEP :
5167
0
       LOOKUP_CONDITION_SUBSET_FALSE;
5168
0
    }
5169
0
5170
0
    case 5:
5171
0
    {
5172
0
      const ConditionNegate &src = u.format5;
5173
0
      auto *out = c->serializer->embed (&src);
5174
0
      if (unlikely (!out))
5175
0
        return LOOKUP_CONDITION_SUBSET_ERROR;
5176
0
      out->condition = 0;
5177
0
5178
0
      c->serializer->push ();
5179
0
      lookup_condition_subset_result_t result =
5180
0
          (&src + src.condition).subset_lookup_condition (c, depth - 1);
5181
0
      if (result == LOOKUP_CONDITION_SUBSET_KEEP)
5182
0
      {
5183
0
        c->serializer->add_link (out->condition,
5184
0
         c->serializer->pop_pack ());
5185
0
        return result;
5186
0
      }
5187
0
5188
0
      c->serializer->pop_discard ();
5189
0
      if (result == LOOKUP_CONDITION_SUBSET_TRUE)
5190
0
        return LOOKUP_CONDITION_SUBSET_FALSE;
5191
0
      if (result == LOOKUP_CONDITION_SUBSET_FALSE)
5192
0
        return LOOKUP_CONDITION_SUBSET_TRUE;
5193
0
      return result;
5194
0
    }
5195
0
5196
0
    default:
5197
0
      return LOOKUP_CONDITION_SUBSET_FALSE;
5198
0
  }
5199
0
}
5200
5201
struct ConditionSet
5202
{
5203
  bool evaluate (const int *coords, unsigned int coord_len,
5204
     ItemVarStoreInstancer *instancer) const
5205
0
  {
5206
0
    unsigned int count = conditions.len;
5207
0
    for (unsigned int i = 0; i < count; i++)
5208
0
      if (!(this+conditions.arrayZ[i]).evaluate (coords, coord_len, instancer))
5209
0
  return false;
5210
0
    return true;
5211
0
  }
5212
5213
  void keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
5214
0
  {
5215
0
    hb_map_t *condition_map = hb_map_create ();
5216
0
    if (unlikely (!condition_map)) return;
5217
0
    hb::shared_ptr<hb_map_t> p {condition_map};
5218
0
5219
0
    hb_set_t *cond_set = hb_set_create ();
5220
0
    if (unlikely (!cond_set)) return;
5221
0
    hb::shared_ptr<hb_set_t> s {cond_set};
5222
0
5223
0
    c->apply = true;
5224
0
    bool should_keep = false;
5225
0
    /* The range map cannot identify value or boolean expressions uniquely. */
5226
0
    bool can_deduplicate = true;
5227
0
    unsigned num_kept_cond = 0, cond_idx = 0;
5228
0
    for (const auto& offset : conditions)
5229
0
    {
5230
0
      const Condition &condition = this+offset;
5231
0
      can_deduplicate &= condition.u.format.v <= 1;
5232
0
      Cond_with_Var_flag_t ret = condition.keep_with_variations (c, condition_map);
5233
0
      // condition is not met or condition out of range, drop the entire record
5234
0
      if (ret == DROP_RECORD_WITH_VAR)
5235
0
      {
5236
0
        c->apply = false;
5237
0
        return;
5238
0
      }
5239
0
5240
0
      if (ret == KEEP_COND_WITH_VAR)
5241
0
      {
5242
0
        should_keep = true;
5243
0
        cond_set->add (cond_idx);
5244
0
        num_kept_cond++;
5245
0
      }
5246
0
5247
0
      if (ret == KEEP_RECORD_WITH_VAR)
5248
0
        should_keep = true;
5249
0
5250
0
      cond_idx++;
5251
0
    }
5252
0
5253
0
    /* Satisfied pinned conditions still terminate first-match processing.
5254
0
     * Keep their universal record when other axes remain variable. */
5255
0
    c->universal = num_kept_cond == 0;
5256
0
    if (!should_keep && c->all_axes_pinned) return;
5257
0
5258
0
    //check if condition_set is unique with variations
5259
0
    if (can_deduplicate && c->conditionset_map->has (p))
5260
0
      //duplicate found, drop the entire record
5261
0
      return;
5262
0
5263
0
    if (can_deduplicate)
5264
0
      c->conditionset_map->set (p, 1);
5265
0
    c->record_cond_idx_map->set (c->cur_record_idx, s);
5266
0
  }
5267
5268
  bool subset (hb_subset_context_t *c,
5269
               hb_subset_layout_context_t *l,
5270
               bool insert_catch_all) const
5271
0
  {
5272
0
    TRACE_SUBSET (this);
5273
0
    auto *out = c->serializer->start_embed (this);
5274
0
    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
5275
0
5276
0
    if (insert_catch_all) return_trace (true);
5277
0
5278
0
    hb_set_t *retained_cond_set = nullptr;
5279
0
    if (l->feature_record_cond_idx_map != nullptr)
5280
0
      retained_cond_set = l->feature_record_cond_idx_map->get (l->cur_feature_var_record_idx);
5281
0
5282
0
    unsigned int count = conditions.len;
5283
0
    for (unsigned int i = 0; i < count; i++)
5284
0
    {
5285
0
      if (retained_cond_set != nullptr && !retained_cond_set->has (i))
5286
0
        continue;
5287
0
      const Condition &condition = this+conditions[i];
5288
0
      if (condition.u.format.v == 1)
5289
0
      {
5290
0
        subset_offset_array (c, out->conditions, this) (conditions[i]);
5291
0
        continue;
5292
0
      }
5293
0
5294
0
      auto *offset = out->conditions.serialize_append (c->serializer);
5295
0
      if (unlikely (!offset)) return_trace (false);
5296
0
      c->serializer->push ();
5297
0
      auto result = condition.subset_lookup_condition (c, HB_MAX_NESTING_LEVEL, true);
5298
0
      if (result == LOOKUP_CONDITION_SUBSET_FALSE)
5299
0
        /* A false condition must not become a null (true) ConditionSet. */
5300
0
        result = Condition::serialize_constant (c->serializer, false) ?
5301
0
                 LOOKUP_CONDITION_SUBSET_KEEP : LOOKUP_CONDITION_SUBSET_ERROR;
5302
0
      if (unlikely (result == LOOKUP_CONDITION_SUBSET_ERROR))
5303
0
      {
5304
0
        c->serializer->pop_discard ();
5305
0
        c->serializer->check_success (false);
5306
0
        return_trace (false);
5307
0
      }
5308
0
      c->serializer->add_link (*offset, c->serializer->pop_pack ());
5309
0
    }
5310
0
5311
0
    return_trace (bool (out->conditions));
5312
0
  }
5313
5314
  bool sanitize (hb_sanitize_context_t *c) const
5315
0
  {
5316
0
    TRACE_SANITIZE (this);
5317
0
    return_trace (conditions.sanitize (c, this));
5318
0
  }
5319
5320
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
5321
0
  {
5322
0
    for (const auto &offset : conditions)
5323
0
      if (unlikely (!(this+offset).collect_var_indices (c->layout_variation_indices,
5324
0
                                                       HB_MAX_NESTING_LEVEL,
5325
0
                                                       c->condition_values)))
5326
0
  c->layout_variation_indices->err ();
5327
0
  }
5328
5329
  protected:
5330
  Array16OfOffset32To<Condition>  conditions;
5331
  public:
5332
  DEFINE_SIZE_ARRAY (2, conditions);
5333
};
5334
5335
struct FeatureTableSubstitutionRecord
5336
{
5337
  friend struct FeatureTableSubstitution;
5338
5339
  void collect_lookups (const void *base, hb_set_t *lookup_indexes /* OUT */) const
5340
0
  {
5341
0
    return (base+feature).add_lookup_indexes_to (lookup_indexes);
5342
0
  }
5343
5344
  void closure_features (const void *base,
5345
       const hb_map_t *lookup_indexes,
5346
       hb_set_t       *feature_indexes /* OUT */) const
5347
0
  {
5348
0
    if ((base+feature).intersects_lookup_indexes (lookup_indexes))
5349
0
      feature_indexes->add (featureIndex);
5350
0
  }
5351
5352
  void collect_feature_substitutes_with_variations (hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
5353
                                                    hb_set_t& catch_all_record_feature_idxes,
5354
                                                    const hb_set_t *feature_indices,
5355
                                                    const void *base) const
5356
0
  {
5357
0
    if (feature_indices->has (featureIndex))
5358
0
    {
5359
0
      feature_substitutes_map->set (featureIndex, &(base+feature));
5360
0
      catch_all_record_feature_idxes.add (featureIndex);
5361
0
    }
5362
0
  }
5363
5364
  bool serialize (hb_subset_layout_context_t *c,
5365
                  unsigned feature_index,
5366
                  const Feature *f, const Tag *tag)
5367
0
  {
5368
0
    TRACE_SERIALIZE (this);
5369
0
    hb_serialize_context_t *s = c->subset_context->serializer;
5370
0
    if (unlikely (!s->extend_min (this))) return_trace (false);
5371
0
5372
0
    uint32_t *new_feature_idx;
5373
0
    if (!c->feature_map_w_duplicates->has (feature_index, &new_feature_idx))
5374
0
      return_trace (false);
5375
0
5376
0
    if (!s->check_assign (featureIndex, *new_feature_idx, HB_SERIALIZE_ERROR_INT_OVERFLOW))
5377
0
      return_trace (false);
5378
0
5379
0
    s->push ();
5380
0
    bool ret = f->subset (c->subset_context, c, tag);
5381
0
    if (ret) s->add_link (feature, s->pop_pack ());
5382
0
    else s->pop_discard ();
5383
0
5384
0
    return_trace (ret);
5385
0
  }
5386
5387
  bool subset (hb_subset_layout_context_t *c, const void *base) const
5388
0
  {
5389
0
    TRACE_SUBSET (this);
5390
0
    uint32_t *new_feature_index;
5391
0
    if (!c->feature_map_w_duplicates->has (featureIndex, &new_feature_index))
5392
0
      return_trace (false);
5393
0
5394
0
    auto *out = c->subset_context->serializer->embed (this);
5395
0
    if (unlikely (!out)) return_trace (false);
5396
0
5397
0
    out->featureIndex = *new_feature_index;
5398
0
    hb_pair_t<const void*, const void*> *original;
5399
0
    if (!c->feature_idx_tag_map->has (featureIndex, &original))
5400
0
      return_trace (false);
5401
0
    const Tag *tag = reinterpret_cast<const Tag*> (original->second);
5402
0
    return_trace (out->feature.serialize_subset (c->subset_context, feature, base, c, tag));
5403
0
  }
5404
5405
  bool sanitize (hb_sanitize_context_t *c, const void *base,
5406
     const FeatureList *feature_list) const
5407
0
  {
5408
0
    TRACE_SANITIZE (this);
5409
0
    if (unlikely (!c->check_struct (this))) return_trace (false);
5410
0
    hb_barrier ();
5411
    /* The substitute is read with the tag of the feature it replaces. */
5412
0
    const Record_sanitize_closure_t closure = {feature_list->get_tag (featureIndex), base};
5413
0
    return_trace (feature.sanitize (c, base, &closure));
5414
0
  }
5415
5416
  protected:
5417
  HBUINT16    featureIndex;
5418
  Offset32To<Feature> feature;
5419
  public:
5420
  DEFINE_SIZE_STATIC (6);
5421
};
5422
5423
struct FeatureTableSubstitution
5424
{
5425
  void collect_feature_indices (hb_set_t *feature_indices) const
5426
0
  {
5427
0
    for (const FeatureTableSubstitutionRecord &record : substitutions)
5428
0
      feature_indices->add (record.featureIndex);
5429
0
  }
5430
5431
  const Feature *find_substitute (unsigned int feature_index) const
5432
0
  {
5433
0
    unsigned int count = substitutions.len;
5434
0
    for (unsigned int i = 0; i < count; i++)
5435
0
    {
5436
0
      const FeatureTableSubstitutionRecord &record = substitutions.arrayZ[i];
5437
0
      if (record.featureIndex == feature_index)
5438
0
  return &(this+record.feature);
5439
0
    }
5440
0
    return nullptr;
5441
0
  }
5442
5443
  void collect_lookups (const hb_set_t *feature_indexes,
5444
      hb_set_t       *lookup_indexes /* OUT */) const
5445
0
  {
5446
0
    + hb_iter (substitutions)
5447
0
    | hb_filter (feature_indexes, &FeatureTableSubstitutionRecord::featureIndex)
5448
0
    | hb_apply ([this, lookup_indexes] (const FeatureTableSubstitutionRecord& r)
5449
0
    { r.collect_lookups (this, lookup_indexes); })
5450
0
    ;
5451
0
  }
5452
5453
  template <typename TagGetter>
5454
  void collect_name_ids (const hb_map_t *feature_index_map,
5455
                         TagGetter get_tag,
5456
                         hb_set_t *nameids_to_retain) const
5457
0
  {
5458
0
    for (const FeatureTableSubstitutionRecord &record : substitutions)
5459
0
      if (feature_index_map->has (record.featureIndex))
5460
0
        (this+record.feature).collect_name_ids (get_tag (record.featureIndex), nameids_to_retain);
5461
0
  }
5462
5463
  void closure_features (const hb_map_t *lookup_indexes,
5464
       hb_set_t       *feature_indexes /* OUT */) const
5465
0
  {
5466
0
    for (const FeatureTableSubstitutionRecord& record : substitutions)
5467
0
      record.closure_features (this, lookup_indexes, feature_indexes);
5468
0
  }
5469
5470
  bool intersects_features (const hb_map_t *feature_index_map) const
5471
0
  {
5472
0
    for (const FeatureTableSubstitutionRecord& record : substitutions)
5473
0
    {
5474
0
      if (feature_index_map->has (record.featureIndex)) return true;
5475
0
    }
5476
0
    return false;
5477
0
  }
5478
5479
  void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
5480
0
  {
5481
0
    for (const FeatureTableSubstitutionRecord& record : substitutions)
5482
0
      record.collect_feature_substitutes_with_variations (c->feature_substitutes_map,
5483
0
                                                          c->catch_all_record_feature_idxes,
5484
0
                                                          c->feature_indices, this);
5485
0
  }
5486
5487
  bool subset (hb_subset_context_t        *c,
5488
         hb_subset_layout_context_t *l,
5489
               bool insert_catch_all) const
5490
0
  {
5491
0
    TRACE_SUBSET (this);
5492
0
    auto *out = c->serializer->start_embed (*this);
5493
0
    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
5494
0
5495
0
    out->version.major = version.major;
5496
0
    out->version.minor = version.minor;
5497
0
5498
0
    if (insert_catch_all)
5499
0
    {
5500
0
      for (unsigned feature_index : *(l->catch_all_record_feature_idxes))
5501
0
      {
5502
0
        hb_pair_t<const void*, const void*> *p;
5503
0
        if (!l->feature_idx_tag_map->has (feature_index, &p))
5504
0
          return_trace (false);
5505
0
        auto *o = out->substitutions.serialize_append (c->serializer);
5506
0
        if (!o->serialize (l, feature_index,
5507
0
                           reinterpret_cast<const Feature*> (p->first),
5508
0
                           reinterpret_cast<const Tag*> (p->second)))
5509
0
          return_trace (false);
5510
0
      }
5511
0
      return_trace (true);
5512
0
    }
5513
0
5514
0
    + substitutions.iter ()
5515
0
    | hb_apply (subset_record_array (l, &(out->substitutions), this))
5516
0
    ;
5517
0
5518
0
    return_trace (bool (out->substitutions));
5519
0
  }
5520
5521
  bool sanitize (hb_sanitize_context_t *c, const FeatureList *feature_list) const
5522
0
  {
5523
0
    TRACE_SANITIZE (this);
5524
0
    return_trace (version.sanitize (c) &&
5525
0
      hb_barrier () &&
5526
0
      likely (version.major == 1) &&
5527
0
      substitutions.sanitize (c, this, feature_list));
5528
0
  }
5529
5530
  protected:
5531
  FixedVersion<>  version;  /* Version--0x00010000u */
5532
  Array16Of<FeatureTableSubstitutionRecord>
5533
      substitutions;
5534
  public:
5535
  DEFINE_SIZE_ARRAY (6, substitutions);
5536
};
5537
5538
struct FeatureVariationRecord
5539
{
5540
  friend struct FeatureVariations;
5541
5542
  void collect_lookups (const void     *base,
5543
      const hb_set_t *feature_indexes,
5544
      hb_set_t       *lookup_indexes /* OUT */) const
5545
0
  {
5546
0
    return (base+substitutions).collect_lookups (feature_indexes, lookup_indexes);
5547
0
  }
5548
5549
  template <typename TagGetter>
5550
  void collect_name_ids (const void *base,
5551
                         const hb_map_t *feature_index_map,
5552
                         TagGetter get_tag,
5553
                         hb_set_t *nameids_to_retain) const
5554
0
  {
5555
0
    (base+substitutions).collect_name_ids (feature_index_map, get_tag, nameids_to_retain);
5556
0
  }
5557
5558
  void closure_features (const void     *base,
5559
       const hb_map_t *lookup_indexes,
5560
       hb_set_t       *feature_indexes /* OUT */) const
5561
0
  {
5562
0
    (base+substitutions).closure_features (lookup_indexes, feature_indexes);
5563
0
  }
5564
5565
  bool intersects_features (const void *base, const hb_map_t *feature_index_map) const
5566
0
  {
5567
0
    return (base+substitutions).intersects_features (feature_index_map);
5568
0
  }
5569
5570
  void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
5571
                                                    const void *base) const
5572
0
  {
5573
0
    (base+conditions).keep_with_variations (c);
5574
0
    if (c->apply && !c->variation_applied)
5575
0
    {
5576
0
      (base+substitutions).collect_feature_substitutes_with_variations (c);
5577
0
      c->variation_applied = true; // set variations only once
5578
0
    }
5579
0
  }
5580
5581
  bool subset (hb_subset_layout_context_t *c, const void *base,
5582
               bool insert_catch_all = false) const
5583
0
  {
5584
0
    TRACE_SUBSET (this);
5585
0
    auto *out = c->subset_context->serializer->embed (this);
5586
0
    if (unlikely (!out)) return_trace (false);
5587
0
5588
0
    hb_set_t *retained_conditions = c->feature_record_cond_idx_map ?
5589
0
        c->feature_record_cond_idx_map->get (c->cur_feature_var_record_idx).get () : nullptr;
5590
0
    if (!insert_catch_all && retained_conditions && retained_conditions->is_empty ())
5591
0
      /* A null ConditionSet is the unconditional first-match record. */
5592
0
      out->conditions = 0;
5593
0
    else
5594
0
      out->conditions.serialize_subset (c->subset_context, conditions, base, c, insert_catch_all);
5595
0
    out->substitutions.serialize_subset (c->subset_context, substitutions, base, c, insert_catch_all);
5596
0
5597
0
    return_trace (true);
5598
0
  }
5599
5600
  bool sanitize (hb_sanitize_context_t *c, const void *base,
5601
     const FeatureList *feature_list) const
5602
0
  {
5603
0
    TRACE_SANITIZE (this);
5604
0
    return_trace (conditions.sanitize (c, base) &&
5605
0
      substitutions.sanitize (c, base, feature_list));
5606
0
  }
5607
5608
  void collect_variation_indices (hb_collect_variation_indices_context_t *c,
5609
          const void *base) const
5610
0
  { (base+conditions).collect_variation_indices (c); }
5611
5612
  protected:
5613
  Offset32To<ConditionSet>
5614
      conditions;
5615
  Offset32To<FeatureTableSubstitution>
5616
      substitutions;
5617
  public:
5618
  DEFINE_SIZE_STATIC (8);
5619
};
5620
5621
struct LookupIndexList
5622
{
5623
  void add_lookup_indexes_to (hb_set_t *lookup_indexes) const
5624
0
  { lookupIndices.add_indexes_to (lookup_indexes); }
5625
5626
  bool intersects_lookup_indexes (const hb_map_t *lookup_indexes) const
5627
0
  { return lookupIndices.intersects (lookup_indexes); }
5628
5629
  bool subset (hb_subset_context_t *c,
5630
         hb_subset_layout_context_t *l) const
5631
0
  {
5632
0
    TRACE_SUBSET (this);
5633
0
    auto *out = c->serializer->start_embed (this);
5634
0
    if (unlikely (!out || !c->serializer->extend_min (out)))
5635
0
      return_trace (false);
5636
0
5637
0
    auto it =
5638
0
    + hb_iter (lookupIndices)
5639
0
    | hb_filter (l->lookup_index_map)
5640
0
    | hb_map (l->lookup_index_map)
5641
0
    ;
5642
0
    out->lookupIndices.serialize (c->serializer, l, it);
5643
0
    return_trace (bool (out->lookupIndices));
5644
0
  }
5645
5646
  bool sanitize (hb_sanitize_context_t *c) const
5647
0
  {
5648
0
    TRACE_SANITIZE (this);
5649
0
    return_trace (lookupIndices.sanitize (c));
5650
0
  }
5651
5652
  protected:
5653
  IndexArray  lookupIndices;
5654
  public:
5655
  DEFINE_SIZE_ARRAY_SIZED (2, lookupIndices);
5656
};
5657
5658
struct LookupConditionRecord
5659
{
5660
  unsigned get_condition_offset (const void *base, const void *variations) const
5661
0
  { return (const char *) &(base+condition) - (const char *) variations; }
5662
5663
  template <typename Instancer>
5664
  bool evaluate (const void *base,
5665
     const int *coords,
5666
     unsigned int coord_len,
5667
     Instancer *instancer) const
5668
0
  { return (base+condition).evaluate (coords, coord_len, instancer); }
5669
5670
  bool evaluate (const void *base,
5671
                 const void *variations,
5672
                 hb_sorted_array_t<const unsigned> conditions) const
5673
0
  {
5674
0
    return !condition || hb_bsearch (get_condition_offset (base, variations),
5675
0
                                     conditions.arrayZ, conditions.length,
5676
0
                                     sizeof (unsigned),
5677
0
                                     _hb_cmp_operator<unsigned, unsigned>);
5678
0
  }
5679
5680
  bool collect_condition (const void *base,
5681
                          const void *variations,
5682
                          const int *coords,
5683
                          unsigned int coord_len,
5684
                          ItemVarStoreInstancer *instancer,
5685
                          hb_set_t *visited,
5686
                          hb_vector_t<unsigned> *conditions) const
5687
0
  {
5688
    /* Null conditions always apply and need no key state. */
5689
0
    if (!condition) return true;
5690
5691
0
    unsigned offset = get_condition_offset (base, variations);
5692
0
    if (visited->has (offset)) return true;
5693
0
    visited->add (offset);
5694
0
    if (unlikely (visited->in_error ())) return false;
5695
5696
0
    if (evaluate (base, coords, coord_len, instancer))
5697
0
      conditions->push (offset);
5698
0
    return !conditions->in_error ();
5699
0
  }
5700
5701
  void add_lookup_indexes_to (const void *base,
5702
            hb_set_t *lookup_indexes) const
5703
0
  { (base+lookupIndices).add_lookup_indexes_to (lookup_indexes); }
5704
5705
  bool intersects_lookup_indexes (const void *base,
5706
           const hb_map_t *lookup_indexes) const
5707
0
  { return (base+lookupIndices).intersects_lookup_indexes (lookup_indexes); }
5708
5709
  void collect_variation_indices (hb_collect_variation_indices_context_t *c,
5710
          const void *base) const
5711
0
  {
5712
0
    if (unlikely (!(base+condition).collect_var_indices (c->layout_variation_indices,
5713
0
                                                        HB_MAX_NESTING_LEVEL,
5714
0
                                                        c->condition_values)))
5715
0
      c->layout_variation_indices->err ();
5716
0
  }
5717
5718
  bool subset (hb_subset_context_t *c,
5719
         hb_subset_layout_context_t *l,
5720
         const void *base) const
5721
0
  {
5722
0
    TRACE_SUBSET (this);
5723
0
    auto *out = c->serializer->embed (this);
5724
0
    if (unlikely (!out)) return_trace (false);
5725
0
5726
0
    out->condition = 0;
5727
0
    c->serializer->push ();
5728
0
    lookup_condition_subset_result_t result =
5729
0
        (base + condition).subset_lookup_condition (c,
5730
0
              HB_MAX_NESTING_LEVEL,
5731
0
              true);
5732
0
    if (result != LOOKUP_CONDITION_SUBSET_KEEP)
5733
0
    {
5734
0
      c->serializer->pop_discard ();
5735
0
      return_trace (false);
5736
0
    }
5737
0
    c->serializer->add_link (out->condition, c->serializer->pop_pack ());
5738
0
5739
0
    return_trace (out->lookupIndices.serialize_subset (c, lookupIndices, base, l));
5740
0
  }
5741
5742
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
5743
0
  {
5744
0
    TRACE_SANITIZE (this);
5745
0
    return_trace (condition.sanitize (c, base) &&
5746
0
      lookupIndices.sanitize (c, base));
5747
0
  }
5748
5749
  protected:
5750
  Offset32To<Condition>   condition;
5751
  Offset32To<LookupIndexList> lookupIndices;
5752
  public:
5753
  DEFINE_SIZE_STATIC (8);
5754
};
5755
5756
struct FeatureLookupsTable
5757
{
5758
0
  bool adds_default_lookups () const { return flags & 0x0001u; }
5759
5760
  bool collect_conditions (const void *variations,
5761
                           const int *coords,
5762
                           unsigned int coord_len,
5763
                           ItemVarStoreInstancer *instancer,
5764
                           hb_set_t *visited,
5765
                           hb_vector_t<unsigned> *conditions) const
5766
0
  {
5767
0
    for (const LookupConditionRecord &record : records)
5768
0
      if (unlikely (!record.collect_condition (this, variations, coords, coord_len,
5769
0
                                               instancer, visited, conditions)))
5770
0
  return false;
5771
0
    return true;
5772
0
  }
5773
5774
  void collect_lookups (const void *variations,
5775
                       hb_sorted_array_t<const unsigned> conditions,
5776
                       hb_set_t *lookup_indexes) const
5777
0
  {
5778
0
    for (const LookupConditionRecord &record : records)
5779
0
      if (record.evaluate (this, variations, conditions))
5780
0
  record.add_lookup_indexes_to (this, lookup_indexes);
5781
0
  }
5782
5783
  template <typename Instancer>
5784
  void collect_lookups (const int *coords,
5785
      unsigned int coord_len,
5786
      Instancer *instancer,
5787
      hb_set_t *lookup_indexes) const
5788
  {
5789
    for (const LookupConditionRecord &record : records)
5790
      if (record.evaluate (this, coords, coord_len, instancer))
5791
  record.add_lookup_indexes_to (this, lookup_indexes);
5792
  }
5793
5794
  void collect_lookups (hb_set_t *lookup_indexes) const
5795
0
  {
5796
0
    for (const LookupConditionRecord &record : records)
5797
0
      record.add_lookup_indexes_to (this, lookup_indexes);
5798
0
  }
5799
5800
  bool intersects_lookup_indexes (const hb_map_t *lookup_indexes) const
5801
0
  {
5802
0
    for (const LookupConditionRecord &record : records)
5803
0
      if (record.intersects_lookup_indexes (this, lookup_indexes))
5804
0
  return true;
5805
0
    return false;
5806
0
  }
5807
5808
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
5809
0
  {
5810
0
    for (const LookupConditionRecord &record : records)
5811
0
      record.collect_variation_indices (c, this);
5812
0
  }
5813
5814
  bool subset (hb_subset_context_t *c,
5815
         hb_subset_layout_context_t *l) const
5816
0
  {
5817
0
    TRACE_SUBSET (this);
5818
0
    auto *out = c->serializer->start_embed (this);
5819
0
    if (unlikely (!out || !c->serializer->extend_min (out)))
5820
0
      return_trace (false);
5821
0
5822
0
    out->version.major = version.major;
5823
0
    out->version.minor = version.minor;
5824
0
    out->flags = flags;
5825
0
5826
0
    for (const LookupConditionRecord &record : records)
5827
0
    {
5828
0
      auto snap = c->serializer->snapshot ();
5829
0
      if (record.subset (c, l, this))
5830
0
  out->records.len++;
5831
0
      else
5832
0
  c->serializer->revert (snap);
5833
0
    }
5834
0
5835
0
    return_trace (true);
5836
0
  }
5837
5838
  bool sanitize (hb_sanitize_context_t *c) const
5839
0
  {
5840
0
    TRACE_SANITIZE (this);
5841
0
    return_trace (version.sanitize (c) &&
5842
0
      hb_barrier () &&
5843
0
      likely (version.major == 1) &&
5844
0
      records.sanitize (c, this));
5845
0
  }
5846
5847
  protected:
5848
  FixedVersion<>  version;  /* Version--0x00010000u */
5849
  HBUINT16  flags;
5850
  Array32Of<LookupConditionRecord>
5851
    records;
5852
  public:
5853
  DEFINE_SIZE_ARRAY (10, records);
5854
};
5855
5856
struct LookupVariationRecord
5857
{
5858
  friend struct FeatureVariations;
5859
5860
0
  unsigned get_feature_index () const { return featureIndex; }
5861
5862
  void collect_lookups (const void *base,
5863
                       const Feature &feature,
5864
                       hb_sorted_array_t<const unsigned> conditions,
5865
                       hb_set_t *lookup_indexes) const
5866
0
  {
5867
0
    const FeatureLookupsTable &feature_lookups = base+featureLookups;
5868
0
    if (feature_lookups.adds_default_lookups ())
5869
0
      feature.add_lookup_indexes_to (lookup_indexes);
5870
0
    feature_lookups.collect_lookups (base, conditions, lookup_indexes);
5871
0
  }
5872
5873
  void collect_lookups (const void *base,
5874
      const hb_set_t *feature_indexes,
5875
      hb_set_t *lookup_indexes) const
5876
0
  {
5877
0
    if (feature_indexes->has (featureIndex))
5878
0
      (base+featureLookups).collect_lookups (lookup_indexes);
5879
0
  }
5880
5881
  void closure_features (const void *base,
5882
       const hb_map_t *lookup_indexes,
5883
       hb_set_t *feature_indexes) const
5884
0
  {
5885
0
    if ((base+featureLookups).intersects_lookup_indexes (lookup_indexes))
5886
0
      feature_indexes->add (featureIndex);
5887
0
  }
5888
5889
  void collect_variation_indices (hb_collect_variation_indices_context_t *c,
5890
          const void *base) const
5891
0
  { (base+featureLookups).collect_variation_indices (c); }
5892
5893
  bool subset (hb_subset_layout_context_t *l, const void *base) const
5894
0
  {
5895
0
    hb_subset_context_t *c = l->subset_context;
5896
0
    TRACE_SUBSET (this);
5897
0
    uint32_t *new_feature_index;
5898
0
    if (!l->feature_map_w_duplicates->has (featureIndex, &new_feature_index))
5899
0
      return_trace (false);
5900
0
5901
0
    auto *out = c->serializer->embed (this);
5902
0
    if (unlikely (!out ||
5903
0
      !c->serializer->check_assign (out->featureIndex,
5904
0
            *new_feature_index,
5905
0
            HB_SERIALIZE_ERROR_INT_OVERFLOW)))
5906
0
      return_trace (false);
5907
0
5908
0
    return_trace (out->featureLookups.serialize_subset (c, featureLookups, base, l));
5909
0
  }
5910
5911
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
5912
0
  {
5913
0
    TRACE_SANITIZE (this);
5914
0
    return_trace (c->check_struct (this) &&
5915
0
      featureLookups.sanitize (c, base));
5916
0
  }
5917
5918
  protected:
5919
  HBUINT16      featureIndex;
5920
  Offset32To<FeatureLookupsTable> featureLookups;
5921
  public:
5922
  DEFINE_SIZE_STATIC (6);
5923
};
5924
5925
struct FeatureVariations
5926
{
5927
  static constexpr unsigned NOT_FOUND_INDEX = 0xFFFFFFFFu;
5928
5929
  const Array32Of<LookupVariationRecord> &get_lookup_variation_records () const
5930
224k
  {
5931
224k
    if (version.to_int () < 0x00010001u)
5932
224k
      return Null (Array32Of<LookupVariationRecord>);
5933
0
    return StructAfter<Array32Of<LookupVariationRecord>> (varRecords);
5934
224k
  }
5935
5936
  unsigned record_count () const
5937
0
  {
5938
0
    return varRecords.len;
5939
0
  }
5940
5941
  bool find_index (const int *coords, unsigned int coord_len,
5942
       unsigned int *index,
5943
       ItemVarStoreInstancer *instancer) const
5944
224k
  {
5945
224k
    unsigned int count = varRecords.len;
5946
224k
    for (unsigned int i = 0; i < count; i++)
5947
0
    {
5948
0
      const FeatureVariationRecord &record = varRecords.arrayZ[i];
5949
0
      if ((this+record.conditions).evaluate (coords, coord_len, instancer))
5950
0
      {
5951
0
  *index = i;
5952
0
  return true;
5953
0
      }
5954
0
    }
5955
224k
    *index = NOT_FOUND_INDEX;
5956
224k
    return false;
5957
224k
  }
5958
5959
  const Feature *find_substitute (unsigned int variations_index,
5960
          unsigned int feature_index) const
5961
0
  {
5962
0
    const FeatureVariationRecord &record = varRecords[variations_index];
5963
0
    return (this+record.substitutions).find_substitute (feature_index);
5964
0
  }
5965
5966
  bool collect_lookup_conditions (const int *coords,
5967
                                  unsigned int coord_len,
5968
                                  ItemVarStoreInstancer *instancer,
5969
                                  hb_vector_t<unsigned> *state) const
5970
224k
  {
5971
224k
    hb_set_t visited_tables, visited_conditions;
5972
224k
    for (const LookupVariationRecord &record : get_lookup_variation_records ())
5973
0
    {
5974
0
      unsigned offset = record.featureLookups;
5975
0
      if (visited_tables.has (offset)) continue;
5976
0
      visited_tables.add (offset);
5977
0
      if (unlikely (visited_tables.in_error ())) return false;
5978
5979
0
      const FeatureLookupsTable &feature_lookups = this+record.featureLookups;
5980
0
      if (unlikely (!feature_lookups.collect_conditions (this, coords, coord_len,
5981
0
                                                         instancer, &visited_conditions,
5982
0
                                                         state)))
5983
0
  return false;
5984
0
    }
5985
5986
    /* Key size depends on distinct conditions, not expanded lookup sets.
5987
     * Sorting makes it independent of their first traversal order. */
5988
224k
    state->qsort (_hb_cmp_operator<unsigned, unsigned>);
5989
224k
    return true;
5990
224k
  }
5991
5992
  bool get_lookup_variations (unsigned feature_index,
5993
                              const Feature &feature,
5994
                              hb_sorted_array_t<const unsigned> conditions,
5995
                              hb_set_t *lookup_indexes) const
5996
109
  {
5997
109
    for (const LookupVariationRecord &record : get_lookup_variation_records ())
5998
0
    {
5999
0
      if (record.featureIndex != feature_index) continue;
6000
6001
0
      record.collect_lookups (this, feature, conditions, lookup_indexes);
6002
0
      return true;
6003
0
    }
6004
109
    return false;
6005
109
  }
6006
6007
  void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
6008
0
  {
6009
0
    unsigned int count = varRecords.len;
6010
0
    for (unsigned int i = 0; i < count; i++)
6011
0
    {
6012
0
      c->cur_record_idx = i;
6013
0
      varRecords[i].collect_feature_substitutes_with_variations (c, this);
6014
0
      if (c->universal)
6015
0
        break;
6016
0
    }
6017
0
    if (c->universal || c->record_cond_idx_map->is_empty ())
6018
0
      c->catch_all_record_feature_idxes.reset ();
6019
0
  }
6020
6021
  FeatureVariations* copy (hb_serialize_context_t *c) const
6022
0
  {
6023
0
    TRACE_SERIALIZE (this);
6024
0
    return_trace (c->embed (*this));
6025
0
  }
6026
6027
  void collect_lookups (const hb_set_t *feature_indexes,
6028
      const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
6029
      hb_set_t       *lookup_indexes /* OUT */) const
6030
0
  {
6031
0
    unsigned count = varRecords.len;
6032
0
    for (unsigned int i = 0; i < count; i++)
6033
0
    {
6034
0
      if (feature_record_cond_idx_map &&
6035
0
          !feature_record_cond_idx_map->has (i))
6036
0
        continue;
6037
0
      varRecords[i].collect_lookups (this, feature_indexes, lookup_indexes);
6038
0
    }
6039
6040
0
    collect_lookup_variation_lookups (feature_indexes, lookup_indexes);
6041
0
  }
6042
6043
  template <typename TagGetter>
6044
  void collect_name_ids (const hb_map_t *feature_index_map,
6045
                         const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
6046
                         TagGetter get_tag,
6047
                         hb_set_t *nameids_to_retain) const
6048
0
  {
6049
0
    for (unsigned i = 0; i < varRecords.len; i++)
6050
0
    {
6051
0
      if (feature_record_cond_idx_map && !feature_record_cond_idx_map->has (i))
6052
0
        continue;
6053
0
      varRecords[i].collect_name_ids (this, feature_index_map, get_tag, nameids_to_retain);
6054
0
    }
6055
0
  }
6056
6057
  void collect_lookup_variation_lookups (const hb_set_t *feature_indexes,
6058
           hb_set_t *lookup_indexes /* OUT */) const
6059
0
  {
6060
0
    for (const LookupVariationRecord &record : get_lookup_variation_records ())
6061
0
      record.collect_lookups (this, feature_indexes, lookup_indexes);
6062
0
  }
6063
6064
  void closure_features (const hb_map_t *lookup_indexes,
6065
       const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
6066
       hb_set_t       *feature_indexes /* OUT */) const
6067
0
  {
6068
0
    unsigned int count = varRecords.len;
6069
0
    for (unsigned int i = 0; i < count; i++)
6070
0
    {
6071
0
      if (feature_record_cond_idx_map != nullptr &&
6072
0
          !feature_record_cond_idx_map->has (i))
6073
0
        continue;
6074
0
      varRecords[i].closure_features (this, lookup_indexes, feature_indexes);
6075
0
    }
6076
0
6077
0
    for (const LookupVariationRecord &record : get_lookup_variation_records ())
6078
0
      record.closure_features (this, lookup_indexes, feature_indexes);
6079
0
  }
6080
6081
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
6082
0
  {
6083
0
    for (const FeatureVariationRecord &record : varRecords)
6084
0
      record.collect_variation_indices (c, this);
6085
0
    for (const LookupVariationRecord &record : get_lookup_variation_records ())
6086
0
      record.collect_variation_indices (c, this);
6087
0
  }
6088
6089
  void collect_feature_indices (hb_set_t *feature_indices) const
6090
0
  {
6091
0
    for (const FeatureVariationRecord &record : varRecords)
6092
0
      (this+record.substitutions).collect_feature_indices (feature_indices);
6093
0
  }
6094
6095
  bool has_lookup_variations (unsigned feature_index) const
6096
0
  {
6097
0
    for (const LookupVariationRecord &record : get_lookup_variation_records ())
6098
0
    {
6099
0
      if (record.featureIndex == feature_index)
6100
0
  return true;
6101
0
      if (record.featureIndex > feature_index)
6102
0
  break;
6103
0
    }
6104
0
    return false;
6105
0
  }
6106
6107
  bool subset (hb_subset_context_t *c,
6108
         hb_subset_layout_context_t *l) const
6109
0
  {
6110
0
    TRACE_SUBSET (this);
6111
0
    auto *out = c->serializer->start_embed (*this);
6112
0
    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
6113
0
6114
0
    out->version.major = version.major;
6115
0
    out->version.minor = version.minor;
6116
0
6117
0
    int keep_up_to = -1;
6118
0
    for (int i = varRecords.len - 1; i >= 0; i--) {
6119
0
      if (varRecords[i].intersects_features (this, l->feature_map_w_duplicates)) {
6120
0
        keep_up_to = i;
6121
0
        break;
6122
0
      }
6123
0
    }
6124
0
6125
0
    unsigned count = (unsigned) (keep_up_to + 1);
6126
0
    for (unsigned i = 0; i < count; i++)
6127
0
    {
6128
0
      if (l->feature_record_cond_idx_map != nullptr &&
6129
0
          !l->feature_record_cond_idx_map->has (i))
6130
0
        continue;
6131
0
6132
0
      l->cur_feature_var_record_idx = i;
6133
0
      subset_record_array (l, &(out->varRecords), this) (varRecords[i]);
6134
0
    }
6135
0
6136
0
    if (out->varRecords.len && !l->catch_all_record_feature_idxes->is_empty ())
6137
0
    {
6138
0
      bool insert_catch_all_record = true;
6139
0
      subset_record_array (l, &(out->varRecords), this, insert_catch_all_record) (varRecords[0]);
6140
0
    }
6141
0
6142
0
    Array32Of<LookupVariationRecord> *out_lookup_records = nullptr;
6143
0
    if (version.minor >= 1)
6144
0
    {
6145
0
      out_lookup_records = &StructAfter<Array32Of<LookupVariationRecord>> (out->varRecords);
6146
0
      if (unlikely (!c->serializer->extend_min (out_lookup_records)))
6147
0
  return_trace (false);
6148
0
6149
0
      + get_lookup_variation_records ().iter ()
6150
0
      | hb_apply (subset_record_array (l, out_lookup_records, this))
6151
0
      ;
6152
0
    }
6153
0
6154
0
    return_trace (bool (out->varRecords) ||
6155
0
      (out_lookup_records && bool (*out_lookup_records)));
6156
0
  }
6157
6158
  bool sanitize (hb_sanitize_context_t *c, const FeatureList *feature_list) const
6159
0
  {
6160
0
    TRACE_SANITIZE (this);
6161
0
    return_trace (version.sanitize (c) &&
6162
0
      hb_barrier () &&
6163
0
      likely (version.major == 1) &&
6164
0
      varRecords.sanitize (c, this, feature_list) &&
6165
0
      (version.minor < 1 ||
6166
0
       get_lookup_variation_records ().sanitize (c, this)));
6167
0
  }
6168
6169
  protected:
6170
  FixedVersion<>  version;  /* Version--0x00010000u */
6171
  Array32Of<FeatureVariationRecord>
6172
      varRecords;
6173
  public:
6174
  DEFINE_SIZE_ARRAY_SIZED (8, varRecords);
6175
};
6176
6177
6178
/*
6179
 * Device Tables
6180
 */
6181
6182
struct HintingDevice
6183
{
6184
  friend struct Device;
6185
6186
  private:
6187
6188
  hb_position_t get_x_delta (hb_font_t *font) const
6189
0
  { return get_delta (font->x_ppem, font->x_scale); }
6190
6191
  hb_position_t get_y_delta (hb_font_t *font) const
6192
0
  { return get_delta (font->y_ppem, font->y_scale); }
6193
6194
  public:
6195
6196
  size_t get_size () const
6197
0
  {
6198
0
    unsigned int f = deltaFormat;
6199
0
    if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * HBUINT16::static_size;
6200
0
    return HBUINT16::static_size * (4 + ((endSize - startSize) >> (4 - f)));
6201
0
  }
6202
6203
  bool sanitize (hb_sanitize_context_t *c) const
6204
0
  {
6205
0
    TRACE_SANITIZE (this);
6206
0
    return_trace (c->check_struct (this) && c->check_range (this, this->get_size ()));
6207
0
  }
6208
6209
  HintingDevice* copy (hb_serialize_context_t *c) const
6210
0
  {
6211
0
    TRACE_SERIALIZE (this);
6212
0
    return_trace (c->embed<HintingDevice> (this));
6213
0
  }
6214
6215
  private:
6216
6217
  int get_delta (unsigned int ppem, int scale) const
6218
0
  {
6219
0
    if (!ppem) return 0;
6220
6221
0
    int pixels = get_delta_pixels (ppem);
6222
6223
0
    if (!pixels) return 0;
6224
6225
0
    return (int) (pixels * (int64_t) scale / ppem);
6226
0
  }
6227
  int get_delta_pixels (unsigned int ppem_size) const
6228
0
  {
6229
0
    unsigned int f = deltaFormat;
6230
0
    if (unlikely (f < 1 || f > 3))
6231
0
      return 0;
6232
6233
0
    if (ppem_size < startSize || ppem_size > endSize)
6234
0
      return 0;
6235
6236
0
    unsigned int s = ppem_size - startSize;
6237
6238
0
    unsigned int byte = deltaValueZ[s >> (4 - f)];
6239
0
    unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
6240
0
    unsigned int mask = (0xFFFFu >> (16 - (1 << f)));
6241
6242
0
    int delta = bits & mask;
6243
6244
0
    if ((unsigned int) delta >= ((mask + 1) >> 1))
6245
0
      delta -= mask + 1;
6246
6247
0
    return delta;
6248
0
  }
6249
6250
  protected:
6251
  HBUINT16  startSize;    /* Smallest size to correct--in ppem */
6252
  HBUINT16  endSize;    /* Largest size to correct--in ppem */
6253
  HBUINT16  deltaFormat;    /* Format of DeltaValue array data: 1, 2, or 3
6254
           * 1  Signed 2-bit value, 8 values per uint16
6255
           * 2  Signed 4-bit value, 4 values per uint16
6256
           * 3  Signed 8-bit value, 2 values per uint16
6257
           */
6258
  UnsizedArrayOf<HBUINT16>
6259
    deltaValueZ;    /* Array of compressed data */
6260
  public:
6261
  DEFINE_SIZE_ARRAY (6, deltaValueZ);
6262
};
6263
6264
struct VariationDevice
6265
{
6266
  friend struct Device;
6267
6268
  private:
6269
6270
  hb_position_t get_x_delta (hb_font_t *font,
6271
           const ItemVariationStore &store,
6272
           hb_scalar_cache_t *store_cache = nullptr) const
6273
0
  { return !font->has_nonzero_coords ? 0 : font->em_scalef_x (get_delta (font, store, store_cache)); }
6274
6275
  hb_position_t get_y_delta (hb_font_t *font,
6276
           const ItemVariationStore &store,
6277
           hb_scalar_cache_t *store_cache = nullptr) const
6278
0
  { return !font->has_nonzero_coords ? 0 : font->em_scalef_y (get_delta (font, store, store_cache)); }
6279
6280
  float get_x_delta_f (hb_font_t *font,
6281
           const ItemVariationStore &store,
6282
           hb_scalar_cache_t *store_cache) const
6283
0
  { return !font->has_nonzero_coords ? 0.f : font->em_fscalef_x (get_delta (font, store, store_cache)); }
6284
6285
  float get_y_delta_f (hb_font_t *font,
6286
           const ItemVariationStore &store,
6287
           hb_scalar_cache_t *store_cache) const
6288
0
  { return !font->has_nonzero_coords ? 0.f : font->em_fscalef_y (get_delta (font, store, store_cache)); }
6289
6290
  VariationDevice* copy (hb_serialize_context_t *c,
6291
                         const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) const
6292
0
  {
6293
0
    TRACE_SERIALIZE (this);
6294
0
    if (!layout_variation_idx_delta_map) return_trace (nullptr);
6295
0
6296
0
    hb_pair_t<unsigned, int> *v;
6297
0
    if (!layout_variation_idx_delta_map->has (varIdx, &v))
6298
0
      return_trace (nullptr);
6299
0
    /* The varidx was mapped to "no variations" during instancing (e.g. the
6300
0
     * instantiated row is all zeros). Drop the device instead of emitting one
6301
0
     * with an out-of-range varidx. */
6302
0
    if (hb_first (*v) == HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
6303
0
      return_trace (nullptr);
6304
0
6305
0
    c->start_zerocopy (this->static_size);
6306
0
    auto *out = c->embed (this);
6307
0
    if (unlikely (!out)) return_trace (nullptr);
6308
0
6309
0
    if (!c->check_assign (out->varIdx, hb_first (*v), HB_SERIALIZE_ERROR_INT_OVERFLOW))
6310
0
      return_trace (nullptr);
6311
0
    return_trace (out);
6312
0
  }
6313
6314
  void collect_variation_index (hb_collect_variation_indices_context_t *c) const
6315
0
  { c->layout_variation_indices->add (varIdx); }
6316
6317
  bool sanitize (hb_sanitize_context_t *c) const
6318
0
  {
6319
0
    TRACE_SANITIZE (this);
6320
0
    return_trace (c->check_struct (this));
6321
0
  }
6322
6323
  private:
6324
6325
  float get_delta (hb_font_t *font,
6326
       const ItemVariationStore &store,
6327
       hb_scalar_cache_t *store_cache = nullptr) const
6328
0
  {
6329
0
    return store.get_delta (varIdx, font->coords, font->num_coords, store_cache);
6330
0
  }
6331
6332
  protected:
6333
  VarIdx  varIdx;   /* Variation index */
6334
  HBUINT16  deltaFormat;  /* Format identifier for this table: 0x0x8000 */
6335
  public:
6336
  DEFINE_SIZE_STATIC (6);
6337
};
6338
6339
struct DeviceHeader
6340
{
6341
  protected:
6342
  HBUINT16    reserved1;
6343
  HBUINT16    reserved2;
6344
  public:
6345
  HBUINT16    format;   /* Format identifier */
6346
  public:
6347
  DEFINE_SIZE_STATIC (6);
6348
};
6349
6350
struct Device
6351
{
6352
  // Anchors retain fractional coordinates until their difference is rounded.
6353
  // Hinting adjustments and value records keep their integer semantics.
6354
  float get_x_delta_f (hb_font_t *font,
6355
           const ItemVariationStore &store,
6356
           hb_scalar_cache_t *store_cache = nullptr) const
6357
0
  {
6358
0
#ifndef HB_NO_VAR
6359
0
    if (u.b.format == 0x8000)
6360
0
    {
6361
0
      hb_barrier ();
6362
0
      return u.variation.get_x_delta_f (font, store, store_cache);
6363
0
    }
6364
0
#endif
6365
0
    return get_x_delta (font, store, store_cache);
6366
0
  }
6367
6368
  float get_y_delta_f (hb_font_t *font,
6369
           const ItemVariationStore &store,
6370
           hb_scalar_cache_t *store_cache = nullptr) const
6371
0
  {
6372
0
#ifndef HB_NO_VAR
6373
0
    if (u.b.format == 0x8000)
6374
0
    {
6375
0
      hb_barrier ();
6376
0
      return u.variation.get_y_delta_f (font, store, store_cache);
6377
0
    }
6378
0
#endif
6379
0
    return get_y_delta (font, store, store_cache);
6380
0
  }
6381
6382
  hb_position_t get_x_delta (hb_font_t *font,
6383
           const ItemVariationStore &store=Null (ItemVariationStore),
6384
           hb_scalar_cache_t *store_cache = nullptr) const
6385
0
  {
6386
0
    switch (u.b.format)
6387
0
    {
6388
0
#ifndef HB_NO_HINTING
6389
0
    case 1: case 2: case 3:
6390
0
      hb_barrier ();
6391
0
      return u.hinting.get_x_delta (font);
6392
0
#endif
6393
0
#ifndef HB_NO_VAR
6394
0
    case 0x8000:
6395
0
      hb_barrier ();
6396
0
      return u.variation.get_x_delta (font, store, store_cache);
6397
0
#endif
6398
0
    default:
6399
0
      return 0;
6400
0
    }
6401
0
  }
6402
  hb_position_t get_y_delta (hb_font_t *font,
6403
           const ItemVariationStore &store=Null (ItemVariationStore),
6404
           hb_scalar_cache_t *store_cache = nullptr) const
6405
0
  {
6406
0
    switch (u.b.format)
6407
0
    {
6408
0
    case 1: case 2: case 3:
6409
0
#ifndef HB_NO_HINTING
6410
0
      hb_barrier ();
6411
0
      return u.hinting.get_y_delta (font);
6412
0
#endif
6413
0
#ifndef HB_NO_VAR
6414
0
    case 0x8000:
6415
0
      hb_barrier ();
6416
0
      return u.variation.get_y_delta (font, store, store_cache);
6417
0
#endif
6418
0
    default:
6419
0
      return 0;
6420
0
    }
6421
0
  }
6422
6423
  bool sanitize (hb_sanitize_context_t *c) const
6424
0
  {
6425
0
    TRACE_SANITIZE (this);
6426
0
    if (!u.b.format.sanitize (c)) return_trace (false);
6427
0
    switch (u.b.format) {
6428
0
#ifndef HB_NO_HINTING
6429
0
    case 1: case 2: case 3:
6430
0
      hb_barrier ();
6431
0
      return_trace (u.hinting.sanitize (c));
6432
0
#endif
6433
0
#ifndef HB_NO_VAR
6434
0
    case 0x8000:
6435
0
      hb_barrier ();
6436
0
      return_trace (u.variation.sanitize (c));
6437
0
#endif
6438
0
    default:
6439
0
      return_trace (true);
6440
0
    }
6441
0
  }
6442
6443
  Device* copy (hb_serialize_context_t *c,
6444
                const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map=nullptr) const
6445
0
  {
6446
0
    TRACE_SERIALIZE (this);
6447
0
    switch (u.b.format) {
6448
0
#ifndef HB_NO_HINTING
6449
0
    case 1:
6450
0
    case 2:
6451
0
    case 3:
6452
0
      hb_barrier ();
6453
0
      return_trace (reinterpret_cast<Device *> (u.hinting.copy (c)));
6454
0
#endif
6455
0
#ifndef HB_NO_VAR
6456
0
    case 0x8000:
6457
0
      hb_barrier ();
6458
0
      return_trace (reinterpret_cast<Device *> (u.variation.copy (c, layout_variation_idx_delta_map)));
6459
0
#endif
6460
0
    default:
6461
0
      return_trace (nullptr);
6462
0
    }
6463
0
  }
6464
6465
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
6466
0
  {
6467
0
    switch (u.b.format) {
6468
0
#ifndef HB_NO_HINTING
6469
0
    case 1:
6470
0
    case 2:
6471
0
    case 3:
6472
0
      return;
6473
0
#endif
6474
0
#ifndef HB_NO_VAR
6475
0
    case 0x8000:
6476
0
      hb_barrier ();
6477
0
      u.variation.collect_variation_index (c);
6478
0
      return;
6479
0
#endif
6480
0
    default:
6481
0
      return;
6482
0
    }
6483
0
  }
6484
6485
  unsigned get_variation_index () const
6486
0
  {
6487
0
    switch (u.b.format) {
6488
0
#ifndef HB_NO_VAR
6489
0
    case 0x8000:
6490
0
      hb_barrier ();
6491
0
      return u.variation.varIdx;
6492
0
#endif
6493
0
    default:
6494
0
      return HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
6495
0
    }
6496
0
  }
6497
6498
  bool is_variation_device () const
6499
0
  {
6500
0
    switch (u.b.format) {
6501
0
#ifndef HB_NO_VAR
6502
0
    case 0x8000:
6503
0
      return true;
6504
0
#endif
6505
0
    default:
6506
0
      return false;
6507
0
    }
6508
0
  }
6509
6510
  protected:
6511
  union {
6512
  DeviceHeader    b;
6513
  HintingDevice   hinting;
6514
#ifndef HB_NO_VAR
6515
  VariationDevice variation;
6516
#endif
6517
  } u;
6518
  public:
6519
  DEFINE_SIZE_UNION (6, b);
6520
};
6521
6522
6523
} /* namespace OT */
6524
6525
6526
#endif /* HB_OT_LAYOUT_COMMON_HH */