Coverage Report

Created: 2026-10-17 07:10

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::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::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::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::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::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::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::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&)
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 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 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::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::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::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::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&)
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 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 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::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::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 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 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 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 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 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::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::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 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 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 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::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::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 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::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::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 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 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::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::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-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::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::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-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::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::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-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::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::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::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::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
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.72k
  {
464
3.72k
    if (_count && _indexes)
465
270
    {
466
270
      + this->as_array ().sub_array (start_offset, _count)
467
270
      | hb_sink (hb_array (_indexes, *_count))
468
270
      ;
469
270
    }
470
3.72k
    return this->len;
471
3.72k
  }
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
    TRACE_SUBSET (this);
754
0
    if (!tag) return_trace (false);
755
0
    if (*tag == HB_TAG ('s','i','z','e') && hb_barrier ())
756
0
      return_trace (u.size.subset (c));
757
0
    if ((*tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
758
0
      return_trace (u.stylisticSet.subset (c));
759
0
    if ((*tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
760
0
      return_trace (u.characterVariants.subset (c));
761
0
    return_trace (false);
762
0
  }
763
764
#ifndef HB_NO_LAYOUT_FEATURE_PARAMS
765
  const FeatureParamsSize& get_size_params (hb_tag_t tag) const
766
0
  {
767
0
    if (tag == HB_TAG ('s','i','z','e') && hb_barrier ())
768
0
      return u.size;
769
0
    return Null (FeatureParamsSize);
770
0
  }
771
  const FeatureParamsStylisticSet& get_stylistic_set_params (hb_tag_t tag) const
772
0
  {
773
0
    if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
774
0
      return u.stylisticSet;
775
0
    return Null (FeatureParamsStylisticSet);
776
0
  }
777
  const FeatureParamsCharacterVariants& get_character_variants_params (hb_tag_t tag) const
778
0
  {
779
0
    if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
780
0
      return u.characterVariants;
781
0
    return Null (FeatureParamsCharacterVariants);
782
0
  }
783
#endif
784
785
  private:
786
  union {
787
  FeatureParamsSize     size;
788
  FeatureParamsStylisticSet   stylisticSet;
789
  FeatureParamsCharacterVariants  characterVariants;
790
  } u;
791
  public:
792
  DEFINE_SIZE_MIN (0);
793
};
794
795
struct Record_sanitize_closure_t {
796
  hb_tag_t tag;
797
  const void *list_base;
798
};
799
800
struct Feature
801
{
802
  unsigned int get_lookup_count () const
803
0
  { return lookupIndex.len; }
804
  hb_tag_t get_lookup_index (unsigned int i) const
805
0
  { return lookupIndex[i]; }
806
  unsigned int get_lookup_indexes (unsigned int start_index,
807
           unsigned int *lookup_count /* IN/OUT */,
808
           unsigned int *lookup_tags /* OUT */) const
809
124
  { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
810
  void add_lookup_indexes_to (hb_set_t *lookup_indexes) const
811
0
  { lookupIndex.add_indexes_to (lookup_indexes); }
812
813
  const FeatureParams &get_feature_params () const
814
0
  { return this+featureParams; }
815
816
  bool intersects_lookup_indexes (const hb_map_t *lookup_indexes) const
817
0
  { return lookupIndex.intersects (lookup_indexes); }
818
819
  void collect_name_ids (hb_tag_t tag, hb_set_t *nameids_to_retain /* OUT */) const
820
0
  {
821
0
    if (featureParams)
822
0
      get_feature_params ().collect_name_ids (tag, nameids_to_retain);
823
0
  }
824
825
  bool subset (hb_subset_context_t         *c,
826
         hb_subset_layout_context_t  *l,
827
         const Tag                   *tag = nullptr) const
828
0
  {
829
0
    TRACE_SUBSET (this);
830
0
    auto *out = c->serializer->start_embed (*this);
831
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
832
0
833
0
    out->featureParams.serialize_subset (c, featureParams, this, tag);
834
0
835
0
    hb::shared_ptr<hb_set_t> *lookup_variations;
836
0
    if (l->cur_feature_index != Index::NOT_FOUND_INDEX &&
837
0
  l->lookup_variations->has (l->cur_feature_index, &lookup_variations))
838
0
    {
839
0
      auto it =
840
0
      + hb_iter (**lookup_variations)
841
0
      | hb_filter (l->lookup_index_map)
842
0
      | hb_map (l->lookup_index_map)
843
0
      ;
844
0
      out->lookupIndex.serialize (c->serializer, l, it);
845
0
    }
846
0
    else
847
0
    {
848
0
      auto it =
849
0
      + hb_iter (lookupIndex)
850
0
      | hb_filter (l->lookup_index_map)
851
0
      | hb_map (l->lookup_index_map)
852
0
      ;
853
0
      out->lookupIndex.serialize (c->serializer, l, it);
854
0
    }
855
0
    // The decision to keep or drop this feature is already made before we get here
856
0
    // so always retain it.
857
0
    return_trace (true);
858
0
  }
859
860
  bool sanitize (hb_sanitize_context_t *c,
861
     const Record_sanitize_closure_t *closure = nullptr) const
862
4.90k
  {
863
4.90k
    TRACE_SANITIZE (this);
864
4.90k
    return_trace (c->check_struct (this) &&
865
4.90k
      featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE) &&
866
4.90k
      lookupIndex.sanitize (c));
867
4.90k
  }
868
869
  Offset16To<FeatureParams>
870
     featureParams; /* Offset to Feature Parameters table (if one
871
         * has been defined for the feature), relative
872
         * to the beginning of the Feature Table; = Null
873
         * if not required */
874
  IndexArray   lookupIndex; /* Array of LookupList indices */
875
  public:
876
  DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex);
877
};
878
879
template <typename Type>
880
struct Record
881
{
882
14.0k
  int cmp (hb_tag_t a) const { return tag.cmp (a); }
OT::Record<OT::LangSys>::cmp(unsigned int) const
Line
Count
Source
882
168
  int cmp (hb_tag_t a) const { return tag.cmp (a); }
OT::Record<OT::Script>::cmp(unsigned int) const
Line
Count
Source
882
13.8k
  int cmp (hb_tag_t a) const { return tag.cmp (a); }
Unexecuted instantiation: OT::Record<OT::Feature>::cmp(unsigned int) const
883
884
  bool subset (hb_subset_layout_context_t *c, const void *base, const void *f_sub = nullptr) const
885
0
  {
886
0
    TRACE_SUBSET (this);
887
0
    auto *out = c->subset_context->serializer->embed (this);
888
0
    if (unlikely (!out)) return_trace (false);
889
0
890
0
    if (!f_sub)
891
0
      return_trace (out->offset.serialize_subset (c->subset_context, offset, base, c, &tag));
892
0
893
0
    const Feature& f = *reinterpret_cast<const Feature *> (f_sub);
894
0
    auto *s = c->subset_context->serializer;
895
0
    s->push ();
896
0
897
0
    out->offset = 0;
898
0
    bool ret = f.subset (c->subset_context, c, &tag);
899
0
    if (ret)
900
0
      s->add_link (out->offset, s->pop_pack ());
901
0
    else
902
0
      s->pop_discard ();
903
0
904
0
    return_trace (ret);
905
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
906
907
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
908
8.82k
  {
909
8.82k
    TRACE_SANITIZE (this);
910
8.82k
    const Record_sanitize_closure_t closure = {tag, base};
911
8.82k
    return_trace (c->check_struct (this) &&
912
8.82k
      offset.sanitize (c, base, &closure));
913
8.82k
  }
OT::Record<OT::LangSys>::sanitize(hb_sanitize_context_t*, void const*) const
Line
Count
Source
908
443
  {
909
443
    TRACE_SANITIZE (this);
910
443
    const Record_sanitize_closure_t closure = {tag, base};
911
443
    return_trace (c->check_struct (this) &&
912
443
      offset.sanitize (c, base, &closure));
913
443
  }
OT::Record<OT::Script>::sanitize(hb_sanitize_context_t*, void const*) const
Line
Count
Source
908
3.47k
  {
909
3.47k
    TRACE_SANITIZE (this);
910
3.47k
    const Record_sanitize_closure_t closure = {tag, base};
911
3.47k
    return_trace (c->check_struct (this) &&
912
3.47k
      offset.sanitize (c, base, &closure));
913
3.47k
  }
OT::Record<OT::Feature>::sanitize(hb_sanitize_context_t*, void const*) const
Line
Count
Source
908
4.90k
  {
909
4.90k
    TRACE_SANITIZE (this);
910
4.90k
    const Record_sanitize_closure_t closure = {tag, base};
911
4.90k
    return_trace (c->check_struct (this) &&
912
4.90k
      offset.sanitize (c, base, &closure));
913
4.90k
  }
Unexecuted instantiation: OT::Record<OT::JstfLangSys>::sanitize(hb_sanitize_context_t*, void const*) const
914
915
  Tag           tag;            /* 4-byte Tag identifier */
916
  Offset16To<Type>
917
                offset;         /* Offset from beginning of object holding
918
                                 * the Record */
919
  public:
920
  DEFINE_SIZE_STATIC (6);
921
};
922
923
template <typename Type>
924
struct RecordArrayOf : SortedArray16Of<Record<Type>>
925
{
926
  const Offset16To<Type>& get_offset (unsigned int i) const
927
10.6k
  { return (*this)[i].offset; }
OT::RecordArrayOf<OT::Script>::get_offset(unsigned int) const
Line
Count
Source
927
10.3k
  { return (*this)[i].offset; }
OT::RecordArrayOf<OT::Feature>::get_offset(unsigned int) const
Line
Count
Source
927
248
  { return (*this)[i].offset; }
928
  Offset16To<Type>& get_offset (unsigned int i)
929
  { return (*this)[i].offset; }
930
  const Tag& get_tag (unsigned int i) const
931
150
  { return (*this)[i].tag; }
Unexecuted instantiation: OT::RecordArrayOf<OT::LangSys>::get_tag(unsigned int) const
Unexecuted instantiation: OT::RecordArrayOf<OT::Script>::get_tag(unsigned int) const
OT::RecordArrayOf<OT::Feature>::get_tag(unsigned int) const
Line
Count
Source
931
150
  { return (*this)[i].tag; }
932
  unsigned int get_tags (unsigned int start_offset,
933
                         unsigned int *record_count /* IN/OUT */,
934
                         hb_tag_t     *record_tags /* OUT */) const
935
0
  {
936
0
    if (record_count && record_tags)
937
0
    {
938
0
      + this->as_array ().sub_array (start_offset, record_count)
939
0
      | hb_map (&Record<Type>::tag)
940
0
      | hb_sink (hb_array (record_tags, *record_count))
941
0
      ;
942
0
    }
943
0
    return this->len;
944
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
945
  bool find_index (hb_tag_t tag, unsigned int *index) const
946
19.0k
  {
947
19.0k
    return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
948
19.0k
  }
OT::RecordArrayOf<OT::LangSys>::find_index(unsigned int, unsigned int*) const
Line
Count
Source
946
5.35k
  {
947
5.35k
    return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
948
5.35k
  }
OT::RecordArrayOf<OT::Script>::find_index(unsigned int, unsigned int*) const
Line
Count
Source
946
13.7k
  {
947
13.7k
    return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
948
13.7k
  }
Unexecuted instantiation: OT::RecordArrayOf<OT::Feature>::find_index(unsigned int, unsigned int*) const
949
};
950
951
template <typename Type>
952
struct RecordListOf : RecordArrayOf<Type>
953
{
954
  const Type& operator [] (unsigned int i) const
955
10.6k
  { return this+this->get_offset (i); }
OT::RecordListOf<OT::Script>::operator[](unsigned int) const
Line
Count
Source
955
10.3k
  { return this+this->get_offset (i); }
OT::RecordListOf<OT::Feature>::operator[](unsigned int) const
Line
Count
Source
955
248
  { return this+this->get_offset (i); }
956
957
  bool subset (hb_subset_context_t *c,
958
               hb_subset_layout_context_t *l) const
959
  {
960
    TRACE_SUBSET (this);
961
    auto *out = c->serializer->start_embed (*this);
962
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
963
964
    + this->iter ()
965
    | hb_apply (subset_record_array (l, out, this))
966
    ;
967
    return_trace (true);
968
  }
969
970
  bool sanitize (hb_sanitize_context_t *c) const
971
5.88k
  {
972
5.88k
    TRACE_SANITIZE (this);
973
5.88k
    return_trace (RecordArrayOf<Type>::sanitize (c, this));
974
5.88k
  }
OT::RecordListOf<OT::Script>::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
971
2.94k
  {
972
2.94k
    TRACE_SANITIZE (this);
973
2.94k
    return_trace (RecordArrayOf<Type>::sanitize (c, this));
974
2.94k
  }
OT::RecordListOf<OT::Feature>::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
971
2.94k
  {
972
2.94k
    TRACE_SANITIZE (this);
973
2.94k
    return_trace (RecordArrayOf<Type>::sanitize (c, this));
974
2.94k
  }
975
};
976
977
struct RecordListOfFeature : RecordListOf<Feature>
978
{
979
  bool subset (hb_subset_context_t *c,
980
         hb_subset_layout_context_t *l) const
981
0
  {
982
0
    TRACE_SUBSET (this);
983
0
    auto *out = c->serializer->start_embed (*this);
984
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
985
0
986
0
    + hb_enumerate (*this)
987
0
    | hb_filter (l->feature_index_map, hb_first)
988
0
    | hb_apply ([l, out, this] (const hb_pair_t<unsigned, const Record<Feature>&>& _)
989
0
                {
990
0
                  const Feature *f_sub = nullptr;
991
0
                  const Feature **f = nullptr;
992
0
                  if (l->feature_substitutes_map->has (_.first, &f))
993
0
                    f_sub = *f;
994
0
995
0
                  l->cur_feature_index = _.first;
996
0
                  subset_record_array (l, out, this, f_sub) (_.second);
997
0
                  l->cur_feature_index = Index::NOT_FOUND_INDEX;
998
0
                })
999
0
    ;
1000
0
1001
0
    return_trace (true);
1002
0
  }
1003
};
1004
1005
typedef RecordListOf<Feature> FeatureList;
1006
1007
1008
struct LangSys
1009
{
1010
  unsigned int get_feature_count () const
1011
0
  { return featureIndex.len; }
1012
  hb_tag_t get_feature_index (unsigned int i) const
1013
0
  { return featureIndex[i]; }
1014
  unsigned int get_feature_indexes (unsigned int start_offset,
1015
            unsigned int *feature_count /* IN/OUT */,
1016
            unsigned int *feature_indexes /* OUT */) const
1017
3.59k
  { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
1018
  void add_feature_indexes_to (hb_set_t *feature_indexes) const
1019
0
  { featureIndex.add_indexes_to (feature_indexes); }
1020
1021
3.45k
  bool has_required_feature () const { return reqFeatureIndex != 0xFFFFu; }
1022
  unsigned int get_required_feature_index () const
1023
3.45k
  {
1024
3.45k
    if (reqFeatureIndex == 0xFFFFu)
1025
3.44k
      return Index::NOT_FOUND_INDEX;
1026
4
   return reqFeatureIndex;
1027
3.45k
  }
1028
1029
  LangSys* copy (hb_serialize_context_t *c) const
1030
0
  {
1031
0
    TRACE_SERIALIZE (this);
1032
0
    return_trace (c->embed (*this));
1033
0
  }
1034
1035
  bool compare (const LangSys& o, const hb_map_t *feature_index_map) const
1036
0
  {
1037
0
    if (reqFeatureIndex != o.reqFeatureIndex)
1038
0
      return false;
1039
0
1040
0
    auto iter =
1041
0
    + hb_iter (featureIndex)
1042
0
    | hb_filter (feature_index_map)
1043
0
    | hb_map (feature_index_map)
1044
0
    ;
1045
0
1046
0
    auto o_iter =
1047
0
    + hb_iter (o.featureIndex)
1048
0
    | hb_filter (feature_index_map)
1049
0
    | hb_map (feature_index_map)
1050
0
    ;
1051
0
1052
0
    for (; iter && o_iter; iter++, o_iter++)
1053
0
    {
1054
0
      unsigned a = *iter;
1055
0
      unsigned b = *o_iter;
1056
0
      if (a != b) return false;
1057
0
    }
1058
0
1059
0
    if (iter || o_iter) return false;
1060
0
1061
0
    return true;
1062
0
  }
1063
1064
  void collect_features (hb_prune_langsys_context_t *c) const
1065
0
  {
1066
0
    if (!has_required_feature () && !get_feature_count ()) return;
1067
0
    if (has_required_feature () &&
1068
0
        c->duplicate_feature_map->has (reqFeatureIndex))
1069
0
      c->new_feature_indexes->add (get_required_feature_index ());
1070
0
1071
0
    + hb_iter (featureIndex)
1072
0
    | hb_filter (c->duplicate_feature_map)
1073
0
    | hb_sink (c->new_feature_indexes)
1074
0
    ;
1075
0
  }
1076
1077
  bool subset (hb_subset_context_t        *c,
1078
         hb_subset_layout_context_t *l,
1079
         const Tag                  *tag = nullptr) const
1080
0
  {
1081
0
    TRACE_SUBSET (this);
1082
0
    auto *out = c->serializer->start_embed (*this);
1083
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
1084
0
1085
0
    const uint32_t *v;
1086
0
    out->reqFeatureIndex = l->feature_map_w_duplicates->has (reqFeatureIndex, &v) ? *v : 0xFFFFu;
1087
0
1088
0
    if (!l->visitFeatureIndex (featureIndex.len))
1089
0
      return_trace (false);
1090
0
1091
0
    auto it =
1092
0
    + hb_iter (featureIndex)
1093
0
    | hb_filter (l->feature_map_w_duplicates)
1094
0
    | hb_map (l->feature_map_w_duplicates)
1095
0
    ;
1096
0
1097
0
    bool ret = bool (it);
1098
0
    out->featureIndex.serialize (c->serializer, l, it);
1099
0
    return_trace (ret);
1100
0
  }
1101
1102
  bool sanitize (hb_sanitize_context_t *c,
1103
     const Record_sanitize_closure_t * = nullptr) const
1104
3.91k
  {
1105
3.91k
    TRACE_SANITIZE (this);
1106
3.91k
    return_trace (c->check_struct (this) && featureIndex.sanitize (c));
1107
3.91k
  }
1108
1109
  Offset16  lookupOrderZ; /* = Null (reserved for an offset to a
1110
         * reordering table) */
1111
  HBUINT16  reqFeatureIndex;/* Index of a feature required for this
1112
         * language system--if no required features
1113
         * = 0xFFFFu */
1114
  IndexArray  featureIndex; /* Array of indices into the FeatureList */
1115
  public:
1116
  DEFINE_SIZE_ARRAY_SIZED (6, featureIndex);
1117
};
1118
DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys);
1119
1120
struct Script
1121
{
1122
  unsigned int get_lang_sys_count () const
1123
0
  { return langSys.len; }
1124
  const Tag& get_lang_sys_tag (unsigned int i) const
1125
0
  { return langSys.get_tag (i); }
1126
  unsigned int get_lang_sys_tags (unsigned int start_offset,
1127
          unsigned int *lang_sys_count /* IN/OUT */,
1128
          hb_tag_t     *lang_sys_tags /* OUT */) const
1129
0
  { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
1130
  const LangSys& get_lang_sys (unsigned int i) const
1131
6.90k
  {
1132
6.90k
    if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
1133
0
    return this+langSys[i].offset;
1134
6.90k
  }
1135
  bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
1136
5.35k
  { return langSys.find_index (tag, index); }
1137
1138
0
  bool has_default_lang_sys () const           { return defaultLangSys != 0; }
1139
6.90k
  const LangSys& get_default_lang_sys () const { return this+defaultLangSys; }
1140
1141
  void prune_langsys (hb_prune_langsys_context_t *c,
1142
                      unsigned script_index) const
1143
0
  {
1144
0
    if (!has_default_lang_sys () && !get_lang_sys_count ()) return;
1145
0
    if (!c->visitScript ()) return;
1146
0
1147
0
    if (!c->script_langsys_map->has (script_index))
1148
0
    {
1149
0
      if (unlikely (!c->script_langsys_map->set (script_index, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
1150
0
  return;
1151
0
    }
1152
0
1153
0
    if (has_default_lang_sys ())
1154
0
    {
1155
0
      //only collect features from non-redundant langsys
1156
0
      const LangSys& d = get_default_lang_sys ();
1157
0
      if (c->visitLangsys (d.get_feature_count ())) {
1158
0
        d.collect_features (c);
1159
0
      }
1160
0
1161
0
      for (auto _ : + hb_enumerate (langSys))
1162
0
      {
1163
0
        const LangSys& l = this+_.second.offset;
1164
0
        if (!c->visitLangsys (l.get_feature_count ())) continue;
1165
0
        if (l.compare (d, c->duplicate_feature_map)) continue;
1166
0
1167
0
        l.collect_features (c);
1168
0
        c->script_langsys_map->get (script_index)->add (_.first);
1169
0
      }
1170
0
    }
1171
0
    else
1172
0
    {
1173
0
      for (auto _ : + hb_enumerate (langSys))
1174
0
      {
1175
0
        const LangSys& l = this+_.second.offset;
1176
0
        if (!c->visitLangsys (l.get_feature_count ())) continue;
1177
0
        l.collect_features (c);
1178
0
        c->script_langsys_map->get (script_index)->add (_.first);
1179
0
      }
1180
0
    }
1181
0
  }
1182
1183
  bool subset (hb_subset_context_t         *c,
1184
         hb_subset_layout_context_t  *l,
1185
         const Tag                   *tag) const
1186
0
  {
1187
0
    TRACE_SUBSET (this);
1188
0
    if (!l->visitScript ()) return_trace (false);
1189
0
    if (tag && !c->plan->layout_scripts.has (*tag))
1190
0
      return false;
1191
0
1192
0
    auto *out = c->serializer->start_embed (*this);
1193
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
1194
0
1195
0
    bool defaultLang = false;
1196
0
    if (has_default_lang_sys ())
1197
0
    {
1198
0
      c->serializer->push ();
1199
0
      const LangSys& ls = this+defaultLangSys;
1200
0
      bool ret = ls.subset (c, l);
1201
0
      if (!ret && tag && *tag != HB_TAG ('D', 'F', 'L', 'T'))
1202
0
      {
1203
0
  c->serializer->pop_discard ();
1204
0
  out->defaultLangSys = 0;
1205
0
      }
1206
0
      else
1207
0
      {
1208
0
  c->serializer->add_link (out->defaultLangSys, c->serializer->pop_pack ());
1209
0
  defaultLang = true;
1210
0
      }
1211
0
    }
1212
0
1213
0
    const hb_set_t *active_langsys = l->script_langsys_map->get (l->cur_script_index);
1214
0
    if (active_langsys)
1215
0
    {
1216
0
      + hb_enumerate (langSys)
1217
0
      | hb_filter (active_langsys, hb_first)
1218
0
      | hb_map (hb_second)
1219
0
      | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); })
1220
0
      | hb_apply (subset_record_array (l, &(out->langSys), this))
1221
0
      ;
1222
0
    }
1223
0
1224
0
    return_trace (bool (out->langSys.len) || defaultLang || l->table_tag == HB_OT_TAG_GSUB);
1225
0
  }
1226
1227
  bool sanitize (hb_sanitize_context_t *c,
1228
     const Record_sanitize_closure_t * = nullptr) const
1229
3.47k
  {
1230
3.47k
    TRACE_SANITIZE (this);
1231
3.47k
    return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
1232
3.47k
  }
1233
1234
  protected:
1235
  Offset16To<LangSys>
1236
    defaultLangSys; /* Offset to DefaultLangSys table--from
1237
         * beginning of Script table--may be Null */
1238
  RecordArrayOf<LangSys>
1239
    langSys;  /* Array of LangSysRecords--listed
1240
         * alphabetically by LangSysTag */
1241
  public:
1242
  DEFINE_SIZE_ARRAY_SIZED (4, langSys);
1243
};
1244
1245
struct RecordListOfScript : RecordListOf<Script>
1246
{
1247
  bool subset (hb_subset_context_t *c,
1248
               hb_subset_layout_context_t *l) const
1249
0
  {
1250
0
    TRACE_SUBSET (this);
1251
0
    auto *out = c->serializer->start_embed (*this);
1252
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
1253
0
1254
0
    for (auto _ : + hb_enumerate (*this))
1255
0
    {
1256
0
      auto snap = c->serializer->snapshot ();
1257
0
      l->cur_script_index = _.first;
1258
0
      bool ret = _.second.subset (l, this);
1259
0
      if (!ret) c->serializer->revert (snap);
1260
0
      else out->len++;
1261
0
    }
1262
0
1263
0
    return_trace (true);
1264
0
  }
1265
};
1266
1267
typedef RecordListOfScript ScriptList;
1268
1269
1270
1271
struct LookupFlag : HBUINT16
1272
{
1273
  enum Flags {
1274
    RightToLeft   = 0x0001u,
1275
    IgnoreBaseGlyphs  = 0x0002u,
1276
    IgnoreLigatures = 0x0004u,
1277
    IgnoreMarks   = 0x0008u,
1278
    IgnoreFlags   = 0x000Eu,
1279
    UseMarkFilteringSet = 0x0010u,
1280
    Reserved    = 0x00E0u,
1281
    MarkAttachmentType  = 0xFF00u
1282
  };
1283
  public:
1284
  DEFINE_SIZE_STATIC (2);
1285
};
1286
1287
} /* namespace OT */
1288
/* This has to be outside the namespace. */
1289
HB_MARK_AS_FLAG_T (OT::LookupFlag::Flags);
1290
namespace OT {
1291
1292
struct Lookup
1293
{
1294
5.33k
  unsigned int get_subtable_count () const { return subTable.len; }
1295
1296
  template <typename TSubTable>
1297
  const Array16OfOffset16To<TSubTable>& get_subtables () const
1298
5.43k
  { 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
1298
346
  { 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
1298
5.08k
  { return reinterpret_cast<const Array16OfOffset16To<TSubTable> &> (subTable); }
1299
  template <typename TSubTable>
1300
  Array16OfOffset16To<TSubTable>& get_subtables ()
1301
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>()
1302
1303
  template <typename TSubTable>
1304
  const TSubTable& get_subtable (unsigned int i) const
1305
275
  { 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
1305
114
  { 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
1305
161
  { return this+get_subtables<TSubTable> ()[i]; }
1306
  template <typename TSubTable>
1307
  TSubTable& get_subtable (unsigned int i)
1308
  { return this+get_subtables<TSubTable> ()[i]; }
1309
1310
  size_t get_size () const
1311
0
  {
1312
0
    const HBUINT16 &markFilteringSet = StructAfter<const HBUINT16> (subTable);
1313
0
    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
1314
0
      return (const char *) &StructAfter<const char> (markFilteringSet) - (const char *) this;
1315
0
    return (const char *) &markFilteringSet - (const char *) this;
1316
0
  }
1317
1318
10.4k
  unsigned int get_type () const { return lookupType; }
1319
1320
  /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
1321
   * higher 16-bit is mark-filtering-set if the lookup uses one.
1322
   * Not to be confused with glyph_props which is very similar. */
1323
  uint32_t get_props () const
1324
50
  {
1325
50
    unsigned int flag = lookupFlag;
1326
50
    if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
1327
0
    {
1328
0
      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
1329
0
      flag += (markFilteringSet << 16);
1330
0
    }
1331
50
    return flag;
1332
50
  }
1333
1334
  template <typename TSubTable, typename context_t, typename ...Ts>
1335
  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
1336
86
  {
1337
86
    unsigned int lookup_type = get_type ();
1338
86
    TRACE_DISPATCH (this, lookup_type);
1339
86
    unsigned int count = get_subtable_count ();
1340
361
    for (unsigned int i = 0; i < count; i++) {
1341
275
      typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, ds...);
1342
275
      if (c->stop_sublookup_iteration (r))
1343
0
  return_trace (r);
1344
275
    }
1345
86
    return_trace (c->default_return_value ());
1346
86
  }
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
1336
42
  {
1337
42
    unsigned int lookup_type = get_type ();
1338
42
    TRACE_DISPATCH (this, lookup_type);
1339
42
    unsigned int count = get_subtable_count ();
1340
156
    for (unsigned int i = 0; i < count; i++) {
1341
114
      typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, ds...);
1342
114
      if (c->stop_sublookup_iteration (r))
1343
0
  return_trace (r);
1344
114
    }
1345
42
    return_trace (c->default_return_value ());
1346
42
  }
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
1336
44
  {
1337
44
    unsigned int lookup_type = get_type ();
1338
44
    TRACE_DISPATCH (this, lookup_type);
1339
44
    unsigned int count = get_subtable_count ();
1340
205
    for (unsigned int i = 0; i < count; i++) {
1341
161
      typename context_t::return_t r = get_subtable<TSubTable> (i).dispatch (c, lookup_type, ds...);
1342
161
      if (c->stop_sublookup_iteration (r))
1343
0
  return_trace (r);
1344
161
    }
1345
44
    return_trace (c->default_return_value ());
1346
44
  }
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
1347
1348
  bool serialize (hb_serialize_context_t *c,
1349
      unsigned int lookup_type,
1350
      uint32_t lookup_props,
1351
      unsigned int num_subtables)
1352
0
  {
1353
0
    TRACE_SERIALIZE (this);
1354
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
1355
0
    lookupType = lookup_type;
1356
0
    lookupFlag = lookup_props & 0xFFFFu;
1357
0
    if (unlikely (!subTable.serialize (c, num_subtables))) return_trace (false);
1358
0
    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
1359
0
    {
1360
0
      if (unlikely (!c->extend (this))) return_trace (false);
1361
0
      HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
1362
0
      markFilteringSet = lookup_props >> 16;
1363
0
    }
1364
0
    return_trace (true);
1365
0
  }
1366
1367
  template <typename TSubTable>
1368
  bool subset (hb_subset_context_t *c) const
1369
0
  {
1370
0
    TRACE_SUBSET (this);
1371
0
    auto *out = c->serializer->start_embed (*this);
1372
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
1373
0
    out->lookupType = lookupType;
1374
0
    out->lookupFlag = lookupFlag;
1375
0
1376
0
    const hb_set_t *glyphset = c->plan->glyphset_gsub ();
1377
0
    unsigned int lookup_type = get_type ();
1378
0
    + hb_iter (get_subtables <TSubTable> ())
1379
0
    | hb_filter ([this, glyphset, lookup_type] (const Offset16To<TSubTable> &_) { return (this+_).intersects (glyphset, lookup_type); })
1380
0
    | hb_apply (subset_offset_array (c, out->get_subtables<TSubTable> (), this, lookup_type))
1381
0
    ;
1382
0
1383
0
    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
1384
0
    {
1385
0
      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
1386
0
      hb_codepoint_t *idx;
1387
0
      if (!c->plan->used_mark_sets_map.has (markFilteringSet, &idx))
1388
0
      {
1389
0
        unsigned new_flag = lookupFlag;
1390
0
        new_flag &= ~LookupFlag::UseMarkFilteringSet;
1391
0
        // https://github.com/harfbuzz/harfbuzz/issues/5499
1392
0
        // If we remove UseMarkFilteringSet flag because the set is now empty,
1393
0
        // we need to add IgnoreMarks flag, otherwise the lookup will not
1394
0
        // ignore any marks, which changes the behavior.
1395
0
        new_flag |= LookupFlag::IgnoreMarks;
1396
0
        out->lookupFlag = new_flag;
1397
0
      }
1398
0
      else
1399
0
      {
1400
0
        if (unlikely (!c->serializer->extend (out))) return_trace (false);
1401
0
        HBUINT16 &outMarkFilteringSet = StructAfter<HBUINT16> (out->subTable);
1402
0
        outMarkFilteringSet = *idx;
1403
0
      }
1404
0
    }
1405
0
1406
0
    // Always keep the lookup even if it's empty. The rest of layout subsetting depends on lookup
1407
0
    // indices being consistent with those computed during planning. So if an empty lookup is
1408
0
    // discarded during the subset phase it will invalidate all subsequent lookup indices.
1409
0
    // Generally we shouldn't end up with an empty lookup as we pre-prune them during the planning
1410
0
    // phase, but it can happen in rare cases such as when during closure subtable is considered
1411
0
    // degenerate (see: https://github.com/harfbuzz/harfbuzz/issues/3853)
1412
0
    return_trace (true);
1413
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
1414
1415
  template <typename TSubTable>
1416
  bool sanitize (hb_sanitize_context_t *c) const
1417
5.15k
  {
1418
5.15k
    TRACE_SANITIZE (this);
1419
5.15k
    if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
1420
5.15k
    hb_barrier ();
1421
1422
5.15k
    unsigned subtables = get_subtable_count ();
1423
5.15k
    if (unlikely (!c->visit_subtables (subtables))) return_trace (false);
1424
1425
5.15k
    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
1426
0
    {
1427
0
      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
1428
0
      if (!markFilteringSet.sanitize (c)) return_trace (false);
1429
0
    }
1430
1431
5.15k
    if (unlikely (!get_subtables<TSubTable> ().sanitize (c, this, get_type ())))
1432
0
      return_trace (false);
1433
1434
5.15k
    if (unlikely (get_type () == TSubTable::Extension))
1435
0
    {
1436
0
      hb_barrier ();
1437
1438
      /* The spec says all subtables of an Extension lookup should
1439
       * have the same type, which shall not be the Extension type
1440
       * itself (but we already checked for that).
1441
       * This is specially important if one has a reverse type!
1442
       */
1443
0
      unsigned int type = get_subtable<TSubTable> (0).u.extension.get_type ();
1444
0
      for (unsigned int i = 1; i < subtables; i++)
1445
0
  if (get_subtable<TSubTable> (i).u.extension.get_type () != type)
1446
0
    return_trace (false);
1447
0
    }
1448
5.15k
    return_trace (true);
1449
5.15k
  }
bool OT::Lookup::sanitize<OT::Layout::GPOS_impl::PosLookupSubTable>(hb_sanitize_context_t*) const
Line
Count
Source
1417
232
  {
1418
232
    TRACE_SANITIZE (this);
1419
232
    if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
1420
232
    hb_barrier ();
1421
1422
232
    unsigned subtables = get_subtable_count ();
1423
232
    if (unlikely (!c->visit_subtables (subtables))) return_trace (false);
1424
1425
232
    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
1426
0
    {
1427
0
      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
1428
0
      if (!markFilteringSet.sanitize (c)) return_trace (false);
1429
0
    }
1430
1431
232
    if (unlikely (!get_subtables<TSubTable> ().sanitize (c, this, get_type ())))
1432
0
      return_trace (false);
1433
1434
232
    if (unlikely (get_type () == TSubTable::Extension))
1435
0
    {
1436
0
      hb_barrier ();
1437
1438
      /* The spec says all subtables of an Extension lookup should
1439
       * have the same type, which shall not be the Extension type
1440
       * itself (but we already checked for that).
1441
       * This is specially important if one has a reverse type!
1442
       */
1443
0
      unsigned int type = get_subtable<TSubTable> (0).u.extension.get_type ();
1444
0
      for (unsigned int i = 1; i < subtables; i++)
1445
0
  if (get_subtable<TSubTable> (i).u.extension.get_type () != type)
1446
0
    return_trace (false);
1447
0
    }
1448
232
    return_trace (true);
1449
232
  }
bool OT::Lookup::sanitize<OT::Layout::GSUB_impl::SubstLookupSubTable>(hb_sanitize_context_t*) const
Line
Count
Source
1417
4.92k
  {
1418
4.92k
    TRACE_SANITIZE (this);
1419
4.92k
    if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false);
1420
4.92k
    hb_barrier ();
1421
1422
4.92k
    unsigned subtables = get_subtable_count ();
1423
4.92k
    if (unlikely (!c->visit_subtables (subtables))) return_trace (false);
1424
1425
4.92k
    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
1426
0
    {
1427
0
      const HBUINT16 &markFilteringSet = StructAfter<HBUINT16> (subTable);
1428
0
      if (!markFilteringSet.sanitize (c)) return_trace (false);
1429
0
    }
1430
1431
4.92k
    if (unlikely (!get_subtables<TSubTable> ().sanitize (c, this, get_type ())))
1432
0
      return_trace (false);
1433
1434
4.92k
    if (unlikely (get_type () == TSubTable::Extension))
1435
0
    {
1436
0
      hb_barrier ();
1437
1438
      /* The spec says all subtables of an Extension lookup should
1439
       * have the same type, which shall not be the Extension type
1440
       * itself (but we already checked for that).
1441
       * This is specially important if one has a reverse type!
1442
       */
1443
0
      unsigned int type = get_subtable<TSubTable> (0).u.extension.get_type ();
1444
0
      for (unsigned int i = 1; i < subtables; i++)
1445
0
  if (get_subtable<TSubTable> (i).u.extension.get_type () != type)
1446
0
    return_trace (false);
1447
0
    }
1448
4.92k
    return_trace (true);
1449
4.92k
  }
1450
1451
  protected:
1452
  HBUINT16  lookupType;   /* Different enumerations for GSUB and GPOS */
1453
  HBUINT16  lookupFlag;   /* Lookup qualifiers */
1454
  Array16Of<Offset16>
1455
    subTable;   /* Array of SubTables */
1456
/*HBUINT16  markFilteringSetX[HB_VAR_ARRAY];*//* Index (base 0) into GDEF mark glyph sets
1457
           * structure. This field is only present if bit
1458
           * UseMarkFilteringSet of lookup flags is set. */
1459
  public:
1460
  DEFINE_SIZE_ARRAY (6, subTable);
1461
};
1462
1463
template <typename Types>
1464
using LookupList = List16OfOffsetTo<Lookup, typename Types::HBLUINT>;
1465
1466
template <typename TLookup, typename OffsetType>
1467
struct LookupOffsetList : List16OfOffsetTo<TLookup, OffsetType>
1468
{
1469
  bool subset (hb_subset_context_t        *c,
1470
         hb_subset_layout_context_t *l) const
1471
0
  {
1472
0
    TRACE_SUBSET (this);
1473
0
    auto *out = c->serializer->start_embed (this);
1474
0
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
1475
0
1476
0
    + hb_enumerate (*this)
1477
0
    | hb_filter (l->lookup_index_map, hb_first)
1478
0
    | hb_map (hb_second)
1479
0
    | hb_apply (subset_offset_array (c, *out, this))
1480
0
    ;
1481
0
    return_trace (true);
1482
0
  }
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 short, 2u> >::subset(hb_subset_context_t*, OT::hb_subset_layout_context_t*) const
1483
1484
  bool sanitize (hb_sanitize_context_t *c) const
1485
  {
1486
    TRACE_SANITIZE (this);
1487
    return_trace ((List16OfOffsetTo<TLookup, OffsetType>::sanitize (c, this)));
1488
  }
1489
};
1490
1491
1492
/*
1493
 * Coverage Table
1494
 */
1495
1496
1497
static bool ClassDef_remap_and_serialize (hb_serialize_context_t *c,
1498
            const hb_set_t &klasses,
1499
                                          bool use_class_zero,
1500
                                          hb_sorted_vector_t<hb_codepoint_pair_t> &glyph_and_klass, /* IN/OUT */
1501
            hb_map_t *klass_map /*IN/OUT*/)
1502
0
{
1503
0
  if (!klass_map)
1504
0
    return ClassDef_serialize (c, glyph_and_klass.iter ());
1505
0
1506
0
  /* any glyph not assigned a class value falls into Class zero (0),
1507
0
   * if any glyph assigned to class 0, remapping must start with 0->0*/
1508
0
  if (!use_class_zero)
1509
0
    klass_map->set (0, 0);
1510
0
1511
0
  unsigned idx = klass_map->has (0) ? 1 : 0;
1512
0
  for (const unsigned k: klasses)
1513
0
  {
1514
0
    if (klass_map->has (k)) continue;
1515
0
    klass_map->set (k, idx);
1516
0
    idx++;
1517
0
  }
1518
0
1519
0
1520
0
  if (unlikely (!c->propagate_error (glyph_and_klass, klasses, klass_map)))
1521
0
    return false;
1522
0
1523
0
  for (unsigned i = 0; i < glyph_and_klass.length; i++)
1524
0
  {
1525
0
    hb_codepoint_t klass = glyph_and_klass[i].second;
1526
0
    glyph_and_klass[i].second = klass_map->get (klass);
1527
0
  }
1528
0
1529
0
  return ClassDef_serialize (c, glyph_and_klass.iter ());
1530
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*)
1531
1532
/*
1533
 * Class Definition Table
1534
 */
1535
1536
template <typename Types>
1537
struct ClassDefFormat1_3
1538
{
1539
  friend struct ClassDef;
1540
1541
  private:
1542
  unsigned int get_class (hb_codepoint_t glyph_id) const
1543
0
  {
1544
0
    return classValue[(unsigned int) (glyph_id - startGlyph)];
1545
0
  }
1546
1547
  unsigned get_population () const
1548
0
  {
1549
0
    return classValue.len;
1550
0
  }
1551
1552
  template<typename Iterator,
1553
     hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
1554
  bool serialize (hb_serialize_context_t *c,
1555
      Iterator it)
1556
0
  {
1557
0
    TRACE_SERIALIZE (this);
1558
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
1559
0
1560
0
    if (unlikely (!it))
1561
0
    {
1562
0
      classFormat = Types::size == 2 ? 1 : 3;
1563
0
      startGlyph = 0;
1564
0
      classValue.len = 0;
1565
0
      return_trace (true);
1566
0
    }
1567
0
1568
0
    hb_codepoint_t glyph_min = (*it).first;
1569
0
    hb_codepoint_t glyph_max = + it
1570
0
             | hb_map (hb_first)
1571
0
             | hb_reduce (hb_max, 0u);
1572
0
    unsigned glyph_count = glyph_max - glyph_min + 1;
1573
0
1574
0
    startGlyph = glyph_min;
1575
0
    if (unlikely (!classValue.serialize (c, glyph_count))) return_trace (false);
1576
0
    for (const hb_pair_t<hb_codepoint_t, uint32_t> gid_klass_pair : + it)
1577
0
    {
1578
0
      unsigned idx = gid_klass_pair.first - glyph_min;
1579
0
      classValue[idx] = gid_klass_pair.second;
1580
0
    }
1581
0
    return_trace (true);
1582
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-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-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-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: 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: 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-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-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-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-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-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-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-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-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-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-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-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_
1583
1584
  bool subset (hb_subset_context_t *c,
1585
         hb_map_t *klass_map = nullptr /*OUT*/,
1586
               bool keep_empty_table = true,
1587
               bool use_class_zero = true,
1588
               const Coverage* glyph_filter = nullptr) const
1589
0
  {
1590
0
    TRACE_SUBSET (this);
1591
0
1592
0
    hb_sorted_vector_t<hb_codepoint_pair_t> glyph_and_klass;
1593
0
    hb_set_t orig_klasses;
1594
0
1595
0
    hb_codepoint_t start = startGlyph;
1596
0
    hb_codepoint_t end   = start + classValue.len;
1597
0
1598
0
    for (const hb_codepoint_t gid : + hb_range (start, end))
1599
0
    {
1600
0
      hb_codepoint_t new_gid = c->plan->map_gsub_glyph (gid);
1601
0
      if (new_gid == HB_MAP_VALUE_INVALID) continue;
1602
0
      if (glyph_filter && !glyph_filter->has(gid)) continue;
1603
0
1604
0
      unsigned klass = classValue[gid - start];
1605
0
      if (!klass) continue;
1606
0
1607
0
      glyph_and_klass.push (hb_pair (new_gid, klass));
1608
0
      orig_klasses.add (klass);
1609
0
    }
1610
0
1611
0
    if (use_class_zero)
1612
0
    {
1613
0
      const hb_set_t& glyphset = *c->plan->glyphset_gsub ();
1614
0
      unsigned glyph_count = glyph_filter
1615
0
           ? hb_len (hb_iter (glyphset) | hb_filter (glyph_filter))
1616
0
           : glyphset.get_population ();
1617
0
      use_class_zero = glyph_count <= glyph_and_klass.length;
1618
0
    }
1619
0
    if (!ClassDef_remap_and_serialize (c->serializer,
1620
0
                                       orig_klasses,
1621
0
                                       use_class_zero,
1622
0
                                       glyph_and_klass,
1623
0
                                       klass_map))
1624
0
      return_trace (false);
1625
0
    return_trace (keep_empty_table || (bool) glyph_and_klass);
1626
0
  }
1627
1628
  bool sanitize (hb_sanitize_context_t *c) const
1629
247
  {
1630
247
    TRACE_SANITIZE (this);
1631
247
    return_trace (c->check_struct (this) && classValue.sanitize (c));
1632
247
  }
1633
1634
143
  unsigned cost () const { return 1; }
1635
1636
  template <typename set_t>
1637
  bool collect_coverage (set_t *glyphs) const
1638
0
  {
1639
0
    unsigned int start = 0;
1640
0
    unsigned int count = classValue.len;
1641
0
    for (unsigned int i = 0; i < count; i++)
1642
0
    {
1643
0
      if (classValue[i])
1644
0
  continue;
1645
1646
0
      if (start != i)
1647
0
  if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + i)))
1648
0
    return false;
1649
1650
0
      start = i + 1;
1651
0
    }
1652
0
    if (start != count)
1653
0
      if (unlikely (!glyphs->add_range (startGlyph + start, startGlyph + count)))
1654
0
  return false;
1655
1656
0
    return true;
1657
0
  }
1658
1659
  template <typename set_t>
1660
  bool collect_class (set_t *glyphs, unsigned klass) const
1661
78
  {
1662
78
    unsigned int count = classValue.len;
1663
468
    for (unsigned int i = 0; i < count; i++)
1664
390
      if (classValue[i] == klass) glyphs->add (startGlyph + i);
1665
78
    return true;
1666
78
  }
Unexecuted instantiation: bool OT::ClassDefFormat1_3<OT::Layout::SmallTypes>::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
1661
78
  {
1662
78
    unsigned int count = classValue.len;
1663
468
    for (unsigned int i = 0; i < count; i++)
1664
390
      if (classValue[i] == klass) glyphs->add (startGlyph + i);
1665
78
    return true;
1666
78
  }
1667
1668
  bool intersects (const hb_set_t *glyphs) const
1669
0
  {
1670
0
    hb_codepoint_t start = startGlyph;
1671
0
    hb_codepoint_t end = startGlyph + classValue.len;
1672
0
    for (hb_codepoint_t iter = startGlyph - 1;
1673
0
   glyphs->next (&iter) && iter < end;)
1674
0
      if (classValue[iter - start]) return true;
1675
0
    return false;
1676
0
  }
1677
  bool intersects_class (const hb_set_t *glyphs, unsigned klass) const
1678
0
  {
1679
0
    unsigned int count = classValue.len;
1680
0
    if (klass == 0)
1681
0
    {
1682
      /* Match if there's any glyph that is not listed! */
1683
0
      hb_codepoint_t g = HB_SET_VALUE_INVALID;
1684
0
      if (!glyphs->next (&g)) return false;
1685
0
      if (g < startGlyph) return true;
1686
0
      g = startGlyph + count - 1;
1687
0
      if (glyphs->next (&g)) return true;
1688
      /* Fall through. */
1689
0
    }
1690
    /* TODO Speed up, using set overlap first? */
1691
    /* TODO(iter) Rewrite as dagger. */
1692
0
    const typename Types::HBUINT *arr = classValue.arrayZ;
1693
0
    for (unsigned int i = 0; i < count; i++)
1694
0
      if (arr[i] == klass && glyphs->has (startGlyph + i))
1695
0
  return true;
1696
0
    return false;
1697
0
  }
1698
1699
  void intersected_class_glyphs (const hb_set_t *glyphs, unsigned klass, hb_set_t *intersect_glyphs) const
1700
0
  {
1701
0
    unsigned count = classValue.len;
1702
0
    if (klass == 0)
1703
0
    {
1704
0
      unsigned start_glyph = startGlyph;
1705
0
      for (uint32_t g = HB_SET_VALUE_INVALID;
1706
0
     glyphs->next (&g) && g < start_glyph;)
1707
0
  intersect_glyphs->add (g);
1708
1709
0
      for (uint32_t g = startGlyph + count - 1;
1710
0
     glyphs-> next (&g);)
1711
0
  intersect_glyphs->add (g);
1712
1713
0
      return;
1714
0
    }
1715
1716
0
    for (unsigned i = 0; i < count; i++)
1717
0
      if (classValue[i] == klass && glyphs->has (startGlyph + i))
1718
0
  intersect_glyphs->add (startGlyph + i);
1719
1720
#if 0
1721
    /* The following implementation is faster asymptotically, but slower
1722
     * in practice. */
1723
    unsigned start_glyph = startGlyph;
1724
    unsigned end_glyph = start_glyph + count;
1725
    for (unsigned g = startGlyph - 1;
1726
   glyphs->next (&g) && g < end_glyph;)
1727
      if (classValue.arrayZ[g - start_glyph] == klass)
1728
        intersect_glyphs->add (g);
1729
#endif
1730
0
  }
1731
1732
  void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const
1733
0
  {
1734
0
    if (glyphs->is_empty ()) return;
1735
0
1736
0
    /* An empty ClassDef assigns class zero to every glyph, so every glyph in
1737
0
     * `glyphs` intersects class zero.  Handle it up front: `end_glyph` below
1738
0
     * underflows when startGlyph is zero, and neither comparison can then be
1739
0
     * true. */
1740
0
    if (!classValue.len)
1741
0
    {
1742
0
      intersect_classes->add (0);
1743
0
      return;
1744
0
    }
1745
0
1746
0
    hb_codepoint_t end_glyph = startGlyph + classValue.len - 1;
1747
0
    if (glyphs->get_min () < startGlyph ||
1748
0
        glyphs->get_max () > end_glyph)
1749
0
      intersect_classes->add (0);
1750
0
1751
0
    for (const auto& _ : + hb_enumerate (classValue))
1752
0
    {
1753
0
      hb_codepoint_t g = startGlyph + _.first;
1754
0
      if (glyphs->has (g))
1755
0
        intersect_classes->add (_.second);
1756
0
    }
1757
0
  }
1758
1759
  protected:
1760
  HBUINT16  classFormat;  /* Format identifier--format = 1 */
1761
  typename Types::HBGlyphID
1762
     startGlyph;  /* First GlyphID of the classValueArray */
1763
  typename Types::template ArrayOf<typename Types::HBUINT>
1764
    classValue; /* Array of Class Values--one per GlyphID */
1765
  public:
1766
  DEFINE_SIZE_ARRAY (2 + 2 * Types::size, classValue);
1767
};
1768
1769
template <typename Types>
1770
struct ClassDefFormat2_4
1771
{
1772
  friend struct ClassDef;
1773
1774
  private:
1775
  unsigned int get_class (hb_codepoint_t glyph_id) const
1776
69
  {
1777
69
    return rangeRecord.bsearch (glyph_id).value;
1778
69
  }
1779
1780
  unsigned get_population () const
1781
0
  {
1782
0
    typename Types::large_int ret = 0;
1783
0
    for (const auto &r : rangeRecord)
1784
0
      ret += r.get_population ();
1785
0
    return ret > UINT_MAX ? UINT_MAX : (unsigned) ret;
1786
0
  }
1787
1788
  template<typename Iterator,
1789
     hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
1790
  bool serialize (hb_serialize_context_t *c,
1791
      Iterator it)
1792
0
  {
1793
0
    TRACE_SERIALIZE (this);
1794
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
1795
0
1796
0
    if (unlikely (!it))
1797
0
    {
1798
0
      classFormat = Types::size == 2 ? 2 : 4;
1799
0
      rangeRecord.len = 0;
1800
0
      return_trace (true);
1801
0
    }
1802
0
1803
0
    unsigned unsorted = false;
1804
0
    unsigned num_ranges = 1;
1805
0
    hb_codepoint_t prev_gid = (*it).first;
1806
0
    unsigned prev_klass = (*it).second;
1807
0
1808
0
    RangeRecord<Types> range_rec;
1809
0
    range_rec.first = prev_gid;
1810
0
    range_rec.last = prev_gid;
1811
0
    range_rec.value = prev_klass;
1812
0
1813
0
    auto *record = c->copy (range_rec);
1814
0
    if (unlikely (!record)) return_trace (false);
1815
0
1816
0
    for (const auto gid_klass_pair : + (++it))
1817
0
    {
1818
0
      hb_codepoint_t cur_gid = gid_klass_pair.first;
1819
0
      unsigned cur_klass = gid_klass_pair.second;
1820
0
1821
0
      if (cur_gid != prev_gid + 1 ||
1822
0
    cur_klass != prev_klass)
1823
0
      {
1824
0
1825
0
  if (unlikely (cur_gid < prev_gid))
1826
0
    unsorted = true;
1827
0
1828
0
  if (unlikely (!record)) break;
1829
0
  record->last = prev_gid;
1830
0
  num_ranges++;
1831
0
1832
0
  range_rec.first = cur_gid;
1833
0
  range_rec.last = cur_gid;
1834
0
  range_rec.value = cur_klass;
1835
0
1836
0
  record = c->copy (range_rec);
1837
0
      }
1838
0
1839
0
      prev_klass = cur_klass;
1840
0
      prev_gid = cur_gid;
1841
0
    }
1842
0
1843
0
    if (unlikely (c->in_error ())) return_trace (false);
1844
0
1845
0
    if (likely (record)) record->last = prev_gid;
1846
0
    rangeRecord.len = num_ranges;
1847
0
1848
0
    if (unlikely (unsorted))
1849
0
      rangeRecord.as_array ().qsort (RangeRecord<Types>::cmp_range);
1850
0
1851
0
    return_trace (true);
1852
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-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-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-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: 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: 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-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-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-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-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-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-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-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-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-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-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-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_
1853
1854
  bool subset (hb_subset_context_t *c,
1855
         hb_map_t *klass_map = nullptr /*OUT*/,
1856
               bool keep_empty_table = true,
1857
               bool use_class_zero = true,
1858
               const Coverage* glyph_filter = nullptr) const
1859
0
  {
1860
0
    TRACE_SUBSET (this);
1861
0
    const hb_set_t &glyph_set = *c->plan->glyphset_gsub ();
1862
0
1863
0
    hb_sorted_vector_t<hb_codepoint_pair_t> glyph_and_klass;
1864
0
    hb_set_t orig_klasses;
1865
0
1866
0
    if (glyph_set.get_population () * hb_bit_storage ((unsigned) rangeRecord.len)
1867
0
  < get_population ())
1868
0
    {
1869
0
      for (hb_codepoint_t g : glyph_set)
1870
0
      {
1871
0
  unsigned klass = get_class (g);
1872
0
  if (!klass) continue;
1873
0
  hb_codepoint_t new_gid = c->plan->map_gsub_glyph (g);
1874
0
  if (new_gid == HB_MAP_VALUE_INVALID) continue;
1875
0
  if (glyph_filter && !glyph_filter->has (g)) continue;
1876
0
  glyph_and_klass.push (hb_pair (new_gid, klass));
1877
0
  orig_klasses.add (klass);
1878
0
      }
1879
0
    }
1880
0
    else
1881
0
    {
1882
0
      unsigned num_source_glyphs = c->plan->source->get_num_glyphs ();
1883
0
      for (auto &range : rangeRecord)
1884
0
      {
1885
0
  unsigned klass = range.value;
1886
0
  if (!klass) continue;
1887
0
  hb_codepoint_t start = range.first;
1888
0
  hb_codepoint_t end   = hb_min (range.last + 1, num_source_glyphs);
1889
0
  for (hb_codepoint_t g = start; g < end; g++)
1890
0
  {
1891
0
    hb_codepoint_t new_gid = c->plan->map_gsub_glyph (g);
1892
0
    if (new_gid == HB_MAP_VALUE_INVALID) continue;
1893
0
    if (glyph_filter && !glyph_filter->has (g)) continue;
1894
0
1895
0
    glyph_and_klass.push (hb_pair (new_gid, klass));
1896
0
    orig_klasses.add (klass);
1897
0
  }
1898
0
      }
1899
0
    }
1900
0
1901
0
    const hb_set_t& glyphset = *c->plan->glyphset_gsub ();
1902
0
    unsigned glyph_count = glyph_filter
1903
0
                           ? hb_len (hb_iter (glyphset) | hb_filter (glyph_filter))
1904
0
                           : glyphset.get_population ();
1905
0
    use_class_zero = use_class_zero && glyph_count <= glyph_and_klass.length;
1906
0
    if (!ClassDef_remap_and_serialize (c->serializer,
1907
0
                                       orig_klasses,
1908
0
                                       use_class_zero,
1909
0
                                       glyph_and_klass,
1910
0
                                       klass_map))
1911
0
      return_trace (false);
1912
0
    return_trace (keep_empty_table || (bool) glyph_and_klass);
1913
0
  }
1914
1915
  bool sanitize (hb_sanitize_context_t *c) const
1916
374
  {
1917
374
    TRACE_SANITIZE (this);
1918
374
    return_trace (rangeRecord.sanitize (c));
1919
374
  }
1920
1921
153
  unsigned cost () const { return hb_bit_storage ((unsigned) rangeRecord.len); /* bsearch cost */ }
1922
1923
  template <typename set_t>
1924
  bool collect_coverage (set_t *glyphs) const
1925
0
  {
1926
0
    for (auto &range : rangeRecord)
1927
0
      if (range.value)
1928
0
  if (unlikely (!range.collect_coverage (glyphs)))
1929
0
    return false;
1930
0
    return true;
1931
0
  }
1932
1933
  template <typename set_t>
1934
  bool collect_class (set_t *glyphs, unsigned int klass) const
1935
102
  {
1936
102
    for (auto &range : rangeRecord)
1937
4.39k
    {
1938
4.39k
      if (range.value == klass)
1939
316
  if (unlikely (!range.collect_coverage (glyphs)))
1940
4
    return false;
1941
4.39k
    }
1942
98
    return true;
1943
102
  }
Unexecuted instantiation: bool OT::ClassDefFormat2_4<OT::Layout::SmallTypes>::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
1935
102
  {
1936
102
    for (auto &range : rangeRecord)
1937
4.39k
    {
1938
4.39k
      if (range.value == klass)
1939
316
  if (unlikely (!range.collect_coverage (glyphs)))
1940
4
    return false;
1941
4.39k
    }
1942
98
    return true;
1943
102
  }
1944
1945
  bool intersects (const hb_set_t *glyphs) const
1946
0
  {
1947
0
    if (rangeRecord.len > glyphs->get_population () * hb_bit_storage ((unsigned) rangeRecord.len))
1948
0
    {
1949
0
      for (auto g : *glyphs)
1950
0
        if (get_class (g))
1951
0
    return true;
1952
0
      return false;
1953
0
    }
1954
0
1955
0
    return hb_any (+ hb_iter (rangeRecord)
1956
0
                   | hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs) && range.value; }));
1957
0
  }
1958
  bool intersects_class (const hb_set_t *glyphs, unsigned klass) const
1959
0
  {
1960
0
    if (klass == 0)
1961
0
    {
1962
      /* An empty ClassDef assigns class zero to every glyph, so it intersects
1963
       * class zero as long as there is any glyph at all.  The loop below is a
1964
       * no-op when there are no ranges, and the `g != HB_SET_VALUE_INVALID`
1965
       * guard after it would then wrongly report no intersection. */
1966
0
      if (!rangeRecord.len)
1967
0
        return !glyphs->is_empty ();
1968
1969
      /* Match if there's any glyph that is not listed! */
1970
0
      hb_codepoint_t g = HB_SET_VALUE_INVALID;
1971
0
      hb_codepoint_t last = HB_SET_VALUE_INVALID;
1972
0
      auto it = hb_iter (rangeRecord);
1973
0
      for (auto &range : it)
1974
0
      {
1975
0
        if (it->first == last + 1)
1976
0
  {
1977
0
    it++;
1978
0
    continue;
1979
0
  }
1980
1981
0
  if (!glyphs->next (&g))
1982
0
    break;
1983
0
  if (g < range.first)
1984
0
    return true;
1985
0
  g = range.last;
1986
0
  last = g;
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
  }
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
  }
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
  }
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.32k
  {
2100
6.32k
    switch (u.format.v) {
2101
0
    case 1: hb_barrier (); return u.format1.get_class (glyph_id);
2102
69
    case 2: hb_barrier (); return u.format2.get_class (glyph_id);
2103
#ifndef HB_NO_BEYOND_64K
2104
    case 3: hb_barrier (); return u.format3.get_class (glyph_id);
2105
    case 4: hb_barrier (); return u.format4.get_class (glyph_id);
2106
#endif
2107
6.25k
    default:return 0;
2108
6.32k
    }
2109
6.32k
  }
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
621
  {
2231
621
    TRACE_SANITIZE (this);
2232
621
    if (!u.format.v.sanitize (c)) return_trace (false);
2233
621
    hb_barrier ();
2234
621
    switch (u.format.v) {
2235
247
    case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
2236
374
    case 2: hb_barrier (); return_trace (u.format2.sanitize (c));
2237
#ifndef HB_NO_BEYOND_64K
2238
    case 3: hb_barrier (); return_trace (u.format3.sanitize (c));
2239
    case 4: hb_barrier (); return_trace (u.format4.sanitize (c));
2240
#endif
2241
0
    default:return_trace (true);
2242
621
    }
2243
621
  }
2244
2245
  unsigned cost () const
2246
296
  {
2247
296
    switch (u.format.v) {
2248
143
    case 1: hb_barrier (); return u.format1.cost ();
2249
153
    case 2: hb_barrier (); return u.format2.cost ();
2250
#ifndef HB_NO_BEYOND_64K
2251
    case 3: hb_barrier (); return u.format3.cost ();
2252
    case 4: hb_barrier (); return u.format4.cost ();
2253
#endif
2254
0
    default:return 0u;
2255
296
    }
2256
296
  }
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
#ifndef HB_NO_BEYOND_64K
2267
    case 3: hb_barrier (); return u.format3.collect_coverage (glyphs);
2268
    case 4: hb_barrier (); return u.format4.collect_coverage (glyphs);
2269
#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
180
  {
2279
180
    switch (u.format.v) {
2280
78
    case 1: hb_barrier (); return u.format1.collect_class (glyphs, klass);
2281
102
    case 2: hb_barrier (); return u.format2.collect_class (glyphs, klass);
2282
#ifndef HB_NO_BEYOND_64K
2283
    case 3: hb_barrier (); return u.format3.collect_class (glyphs, klass);
2284
    case 4: hb_barrier (); return u.format4.collect_class (glyphs, klass);
2285
#endif
2286
0
    default:return false;
2287
180
    }
2288
180
  }
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
180
  {
2279
180
    switch (u.format.v) {
2280
78
    case 1: hb_barrier (); return u.format1.collect_class (glyphs, klass);
2281
102
    case 2: hb_barrier (); return u.format2.collect_class (glyphs, klass);
2282
#ifndef HB_NO_BEYOND_64K
2283
    case 3: hb_barrier (); return u.format3.collect_class (glyphs, klass);
2284
    case 4: hb_barrier (); return u.format4.collect_class (glyphs, klass);
2285
#endif
2286
0
    default:return false;
2287
180
    }
2288
180
  }
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
#ifndef HB_NO_BEYOND_64K
2308
    case 3: hb_barrier (); return u.format3.intersects_class (glyphs, klass);
2309
    case 4: hb_barrier (); return u.format4.intersects_class (glyphs, klass);
2310
#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
#ifndef HB_NO_BEYOND_64K
2321
    case 3: hb_barrier (); return u.format3.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
2322
    case 4: hb_barrier (); return u.format4.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
2323
#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 int INVALID = INT_MIN;
2642
  static constexpr float MULTIPLIER = 1 << ((sizeof (int) * 8) - 2);
2643
  static constexpr float DIVISOR = 1.f / MULTIPLIER;
2644
2645
  public:
2646
0
  hb_scalar_cache_t () {}
2647
2648
  hb_scalar_cache_t (const hb_scalar_cache_t&) = delete;
2649
  hb_scalar_cache_t (hb_scalar_cache_t&&) = delete;
2650
  hb_scalar_cache_t& operator= (const hb_scalar_cache_t&) = delete;
2651
  hb_scalar_cache_t& operator= (hb_scalar_cache_t&&) = delete;
2652
2653
  static hb_scalar_cache_t *create (unsigned int count,
2654
            hb_scalar_cache_t *scratch_cache = nullptr)
2655
78.1k
  {
2656
78.1k
    if (!count) return (hb_scalar_cache_t *) &Null(hb_scalar_cache_t);
2657
2658
0
    if (scratch_cache && count <= STATIC_LENGTH)
2659
0
    {
2660
0
      scratch_cache->length = count;
2661
0
      scratch_cache->clear ();
2662
0
      return scratch_cache;
2663
0
    }
2664
2665
0
    auto *cache = (hb_scalar_cache_t *) hb_malloc (sizeof (hb_scalar_cache_t) - sizeof (static_values) + sizeof (static_values[0]) * count);
2666
0
    if (unlikely (!cache)) return (hb_scalar_cache_t *) &Null(hb_scalar_cache_t);
2667
2668
0
    cache->length = count;
2669
0
    cache->clear ();
2670
2671
0
    return cache;
2672
0
  }
2673
2674
  static void destroy (hb_scalar_cache_t *cache,
2675
           hb_scalar_cache_t *scratch_cache = nullptr)
2676
78.1k
  {
2677
78.1k
    if (cache != &Null(hb_scalar_cache_t) && cache != scratch_cache)
2678
0
      hb_free (cache);
2679
78.1k
  }
2680
2681
  void clear ()
2682
0
  {
2683
0
    auto *values = &static_values[0];
2684
0
    unsigned i = 0;
2685
0
#ifndef HB_OPTIMIZE_SIZE
2686
0
    for (; i + 3 < length; i += 4)
2687
0
    {
2688
0
      values[i + 0] = INVALID;
2689
0
      values[i + 1] = INVALID;
2690
0
      values[i + 2] = INVALID;
2691
0
      values[i + 3] = INVALID;
2692
0
    }
2693
0
#endif
2694
0
    for (; i < length; i++)
2695
0
      values[i] = INVALID;
2696
0
  }
2697
2698
  HB_ALWAYS_INLINE
2699
  bool get (unsigned i, float *value) const
2700
0
  {
2701
0
    if (unlikely (i >= length))
2702
0
    {
2703
0
      *value = 0.f;
2704
0
      return true;
2705
0
    }
2706
0
    auto *values = &static_values[0];
2707
0
    auto *cached_value = &values[i];
2708
    // Super hot. Most common path is that we have a cached value of 0.
2709
0
    int v = *cached_value;
2710
0
    if (likely (!v))
2711
0
    {
2712
0
      *value = 0.f;
2713
0
      return true;
2714
0
    }
2715
0
    if (v == INVALID)
2716
0
      return false;
2717
0
    *value = v * DIVISOR;
2718
0
    return true;
2719
0
  }
2720
2721
  HB_ALWAYS_INLINE
2722
  void set (unsigned i, float value)
2723
0
  {
2724
0
    if (unlikely (i >= length)) return;
2725
0
    auto *values = &static_values[0];
2726
0
    auto *cached_value = &values[i];
2727
0
    *cached_value = roundf(value * MULTIPLIER);
2728
0
  }
2729
2730
  public:
2731
  unsigned length;
2732
  private:
2733
  mutable hb_atomic_t<int> static_values[STATIC_LENGTH];
2734
};
2735
2736
struct VarRegionList
2737
{
2738
  private:
2739
  float evaluate_impl (unsigned int region_index,
2740
           const int *coords, unsigned int coord_len) const
2741
0
  {
2742
0
    const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount);
2743
0
    float v = 1.f;
2744
2745
0
    unsigned int count = axisCount;
2746
0
    for (unsigned int i = 0; i < count; i++)
2747
0
    {
2748
0
      int coord = i < coord_len ? coords[i] : 0;
2749
0
      float factor = axes[i].evaluate (coord);
2750
0
      if (factor == 0.f)
2751
0
      {
2752
0
  v = 0.f;
2753
0
  break;
2754
0
      }
2755
0
      v *= factor;
2756
0
    }
2757
2758
0
    return v;
2759
0
  }
2760
2761
  public:
2762
  HB_ALWAYS_INLINE
2763
  float evaluate (unsigned int region_index,
2764
      const int *coords, unsigned int coord_len,
2765
      hb_scalar_cache_t *cache = nullptr) const
2766
0
  {
2767
0
    if (unlikely (region_index >= regionCount))
2768
0
      return 0.;
2769
2770
0
    float v;
2771
0
    if (cache && cache->get (region_index, &v))
2772
0
      return v;
2773
2774
0
    v = evaluate_impl (region_index, coords, coord_len);
2775
2776
0
    if (cache)
2777
0
      cache->set (region_index, v);
2778
0
    return v;
2779
0
  }
2780
2781
  bool sanitize (hb_sanitize_context_t *c) const
2782
0
  {
2783
0
    TRACE_SANITIZE (this);
2784
0
    return_trace (c->check_struct (this) &&
2785
0
      hb_barrier () &&
2786
0
      axesZ.sanitize (c, axisCount * regionCount));
2787
0
  }
2788
2789
  bool serialize (hb_serialize_context_t *c,
2790
                  const hb_vector_t<hb_tag_t>& axis_tags,
2791
                  const hb_vector_t<const hb_hashmap_t<hb_tag_t, Triple>*>& regions)
2792
0
  {
2793
0
    TRACE_SERIALIZE (this);
2794
0
    unsigned axis_count = axis_tags.length;
2795
0
    unsigned region_count = regions.length;
2796
0
    if (!axis_count || !region_count) return_trace (false);
2797
0
    if (unlikely (hb_unsigned_mul_overflows (axis_count * region_count,
2798
0
                                             VarRegionAxis::static_size))) return_trace (false);
2799
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
2800
0
    axisCount = axis_count;
2801
0
    regionCount = region_count;
2802
0
2803
0
    for (unsigned r = 0; r < region_count; r++)
2804
0
    {
2805
0
      const auto& region = regions[r];
2806
0
      for (unsigned i = 0; i < axis_count; i++)
2807
0
      {
2808
0
        hb_tag_t tag = axis_tags.arrayZ[i];
2809
0
        VarRegionAxis var_region_rec;
2810
0
        Triple *coords;
2811
0
        if (region->has (tag, &coords))
2812
0
        {
2813
0
          var_region_rec.startCoord.set_float (coords->minimum);
2814
0
          var_region_rec.peakCoord.set_float (coords->middle);
2815
0
          var_region_rec.endCoord.set_float (coords->maximum);
2816
0
        }
2817
0
        else
2818
0
        {
2819
0
          var_region_rec.startCoord.set_int (0);
2820
0
          var_region_rec.peakCoord.set_int (0);
2821
0
          var_region_rec.endCoord.set_int (0);
2822
0
        }
2823
0
        if (!var_region_rec.serialize (c))
2824
0
          return_trace (false);
2825
0
      }
2826
0
    }
2827
0
    return_trace (true);
2828
0
  }
2829
2830
  bool serialize (hb_serialize_context_t *c, const VarRegionList *src, const hb_inc_bimap_t &region_map)
2831
0
  {
2832
0
    TRACE_SERIALIZE (this);
2833
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
2834
0
    axisCount = src->axisCount;
2835
0
    regionCount = region_map.get_population ();
2836
0
    if (unlikely (hb_unsigned_mul_overflows (axisCount * regionCount,
2837
0
               VarRegionAxis::static_size))) return_trace (false);
2838
0
    if (unlikely (!c->extend (this))) return_trace (false);
2839
0
    unsigned int region_count = src->regionCount;
2840
0
    for (unsigned int r = 0; r < regionCount; r++)
2841
0
    {
2842
0
      unsigned int backward = region_map.backward (r);
2843
0
      if (backward >= region_count) return_trace (false);
2844
0
      hb_memcpy (&axesZ[axisCount * r], &src->axesZ[axisCount * backward], VarRegionAxis::static_size * axisCount);
2845
0
    }
2846
0
2847
0
    return_trace (true);
2848
0
  }
2849
2850
  bool get_var_region (unsigned region_index,
2851
                       const hb_map_t& axes_old_index_tag_map,
2852
                       hb_hashmap_t<hb_tag_t, Triple>& axis_tuples /* OUT */) const
2853
0
  {
2854
0
    if (region_index >= regionCount) return false;
2855
0
    const VarRegionAxis* axis_region = axesZ.arrayZ + (region_index * axisCount);
2856
0
    for (unsigned i = 0; i < axisCount; i++)
2857
0
    {
2858
0
      hb_tag_t *axis_tag;
2859
0
      if (!axes_old_index_tag_map.has (i, &axis_tag))
2860
0
        return false;
2861
0
2862
0
      float min_val = axis_region->startCoord.to_float ();
2863
0
      float def_val = axis_region->peakCoord.to_float ();
2864
0
      float max_val = axis_region->endCoord.to_float ();
2865
0
2866
0
      if (def_val != 0.f)
2867
0
        axis_tuples.set (*axis_tag, Triple ((double) min_val, (double) def_val, (double) max_val));
2868
0
      axis_region++;
2869
0
    }
2870
0
    return !axis_tuples.in_error ();
2871
0
  }
2872
2873
  bool get_var_regions (const hb_map_t& axes_old_index_tag_map,
2874
                        hb_vector_t<hb_hashmap_t<hb_tag_t, Triple>>& regions /* OUT */) const
2875
0
  {
2876
0
    if (!regions.alloc (regionCount))
2877
0
      return false;
2878
0
2879
0
    for (unsigned i = 0; i < regionCount; i++)
2880
0
    {
2881
0
      hb_hashmap_t<hb_tag_t, Triple> axis_tuples;
2882
0
      if (!get_var_region (i, axes_old_index_tag_map, axis_tuples))
2883
0
        return false;
2884
0
      regions.push (std::move (axis_tuples));
2885
0
    }
2886
0
    return !regions.in_error ();
2887
0
  }
2888
2889
  size_t get_size () const
2890
0
  { return hb_unsigned_add_saturate (min_size,
2891
0
             hb_unsigned_mul_saturate (VarRegionAxis::static_size,
2892
0
                     axisCount, regionCount)); }
2893
2894
  public:
2895
  HBUINT16  axisCount;
2896
  HBUINT15  regionCount;
2897
  protected:
2898
  UnsizedArrayOf<VarRegionAxis>
2899
    axesZ;
2900
  public:
2901
  DEFINE_SIZE_ARRAY (4, axesZ);
2902
};
2903
2904
/* Whether a variation region is unreachable given per-axis reachable
2905
 * final-coordinate ranges, in F2Dot14 units (avar2 partial-instancing
2906
 * culling; see hb_subset_plan_t::avar2_reachable_ranges). A region is dead
2907
 * if some axis's tent evaluates to zero over the axis's entire reachable
2908
 * range. Mirrors the runtime evaluation: invalid tents evaluate as
2909
 * constant 1 and never kill a region. */
2910
static inline bool
2911
_hb_avar2_region_is_dead (const hb_hashmap_t<hb_tag_t, Triple> &axis_tuples,
2912
        const hb_hashmap_t<hb_tag_t, Triple> &reachable_ranges)
2913
0
{
2914
0
  for (auto _ : axis_tuples)
2915
0
  {
2916
0
    Triple *range;
2917
0
    if (!reachable_ranges.has (_.first, &range)) continue;
2918
0
    const Triple &tent = _.second;
2919
0
    int start = (int) roundf ((float) tent.minimum * 16384.f);
2920
0
    int peak  = (int) roundf ((float) tent.middle * 16384.f);
2921
0
    int end   = (int) roundf ((float) tent.maximum * 16384.f);
2922
0
    if (!peak) continue;
2923
0
    if (start > peak || peak > end) continue;
2924
0
    if (start < 0 && end > 0) continue;
2925
0
    int lo = (int) roundf ((float) range->minimum * 16384.f);
2926
0
    int hi = (int) roundf ((float) range->maximum * 16384.f);
2927
0
    /* Strict comparisons: the scalar is 1 (not 0) at v == peak, so a tent
2928
0
     * whose peak sits exactly on the range boundary is still live there.
2929
0
     * (Reachable ranges are padded by one F2Dot14 unit at their producer,
2930
0
     * which already covers this; strictness keeps the predicate correct on
2931
0
     * its own terms.) */
2932
0
    if (hi < start || lo > end)
2933
0
      return true;
2934
0
  }
2935
0
  return false;
2936
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&)
2937
2938
struct SparseVariationRegion
2939
{
2940
  float evaluate (const int *coords, unsigned int coord_len) const
2941
0
  {
2942
0
    float v = 1.f;
2943
0
    unsigned int count = axes.len;
2944
0
    for (unsigned int i = 0; i < count; i++)
2945
0
    {
2946
0
      float factor = (this+axes[i]).evaluate (coords, coord_len);
2947
0
      if (factor == 0.f)
2948
0
  return 0.;
2949
0
      v *= factor;
2950
0
    }
2951
0
    return v;
2952
0
  }
2953
2954
  bool serialize (hb_serialize_context_t *c,
2955
      const SparseVariationRegion *src,
2956
      const hb_map_t *axis_map)
2957
0
  {
2958
0
    TRACE_SERIALIZE (this);
2959
0
    if (unlikely (!axes.serialize (c, (unsigned) src->axes.len))) return_trace (false);
2960
0
    for (unsigned i = 0; i < axes.len; i++)
2961
0
      if (unlikely (src->axes[i].is_null () ||
2962
0
        !axes[i].serialize_serialize (c, &(src+src->axes[i]), axis_map)))
2963
0
  return_trace (false);
2964
0
    return_trace (true);
2965
0
  }
2966
2967
  bool sanitize (hb_sanitize_context_t *c) const
2968
0
  {
2969
0
    TRACE_SANITIZE (this);
2970
0
    return_trace (axes.sanitize (c, this));
2971
0
  }
2972
2973
  protected:
2974
  Array16Of<Offset32To<SparseVarRegionAxis>> axes;
2975
  public:
2976
  DEFINE_SIZE_ARRAY (2, axes);
2977
};
2978
2979
struct SparseVarRegionList
2980
{
2981
  HB_ALWAYS_INLINE
2982
  float evaluate (unsigned int region_index,
2983
      const int *coords, unsigned int coord_len,
2984
      hb_scalar_cache_t *cache = nullptr) const
2985
0
  {
2986
0
    if (unlikely (region_index >= regions.len))
2987
0
      return 0.;
2988
2989
0
    float v;
2990
0
    if (cache && cache->get (region_index, &v))
2991
0
      return v;
2992
2993
0
    const SparseVariationRegion &region = this+regions[region_index];
2994
2995
0
    v = region.evaluate (coords, coord_len);
2996
0
    if (cache)
2997
0
      cache->set (region_index, v);
2998
2999
0
    return v;
3000
0
  }
3001
3002
  bool sanitize (hb_sanitize_context_t *c) const
3003
0
  {
3004
0
    TRACE_SANITIZE (this);
3005
0
    return_trace (regions.sanitize (c, this));
3006
0
  }
3007
3008
  bool serialize (hb_serialize_context_t *c,
3009
      const SparseVarRegionList *src,
3010
      const hb_inc_bimap_t &region_map,
3011
      const hb_map_t *axis_map)
3012
0
  {
3013
0
    TRACE_SERIALIZE (this);
3014
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
3015
0
    regions.len = region_map.get_population ();
3016
0
    if (unlikely (!c->extend (regions))) return_trace (false);
3017
0
3018
0
    for (unsigned i = 0; i < regions.len; i++)
3019
0
    {
3020
0
      unsigned old_index = region_map.backward (i);
3021
0
      if (unlikely (old_index >= src->regions.len ||
3022
0
        !regions[i].serialize_serialize (c,
3023
0
               &(src+src->regions[old_index]),
3024
0
               axis_map)))
3025
0
  return_trace (false);
3026
0
    }
3027
0
    return_trace (true);
3028
0
  }
3029
3030
  public:
3031
  Array32Of<Offset32To<SparseVariationRegion>>
3032
    regions;
3033
  public:
3034
  DEFINE_SIZE_ARRAY (4, regions);
3035
};
3036
3037
3038
struct VarData
3039
{
3040
  unsigned int get_item_count () const
3041
0
  { return itemCount; }
3042
3043
  unsigned int get_region_index_count () const
3044
0
  { return regionIndices.len; }
3045
3046
  unsigned get_region_index (unsigned i) const
3047
0
  { return i >= regionIndices.len ? -1 : regionIndices[i]; }
3048
3049
  size_t get_row_size () const
3050
0
  { return (wordCount () + regionIndices.len) * (longWords () ? 2 : 1); }
3051
3052
  size_t get_size () const
3053
0
  { return hb_unsigned_add_saturate (min_size - regionIndices.min_size,
3054
0
             regionIndices.get_size (),
3055
0
             hb_unsigned_mul_saturate (itemCount, get_row_size ())); }
3056
3057
  template <typename Float = float>
3058
  Float _get_delta (unsigned int inner,
3059
        const int *coords, unsigned int coord_count,
3060
        const VarRegionList &regions,
3061
        hb_scalar_cache_t *cache = nullptr) const
3062
0
  {
3063
0
    if (unlikely (inner >= itemCount))
3064
0
      return 0.;
3065
0
    bool is_long = longWords ();
3066
0
    unsigned int count = regionIndices.len;
3067
0
    unsigned word_count = wordCount ();
3068
0
    unsigned int scount = is_long ? count : word_count;
3069
0
    unsigned int lcount = is_long ? word_count : 0;
3070
3071
0
    const HBUINT8 *bytes = get_delta_bytes ();
3072
0
    const HBUINT8 *row = bytes + inner * get_row_size ();
3073
3074
0
    Float delta = 0;
3075
0
    unsigned int i = 0;
3076
3077
0
    const HBINT32 *lcursor = reinterpret_cast<const HBINT32 *> (row);
3078
0
    for (; i < lcount; 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) *lcursor;
3083
0
      lcursor++;
3084
0
    }
3085
0
    const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (lcursor);
3086
0
    for (; i < scount; 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) *scursor;
3091
0
      scursor++;
3092
0
    }
3093
0
    const HBINT8 *bcursor = reinterpret_cast<const HBINT8 *> (scursor);
3094
0
    for (; i < count; i++)
3095
0
    {
3096
0
      float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
3097
0
      if (scalar)
3098
0
        delta += (Float) scalar * (int) *bcursor;
3099
0
      bcursor++;
3100
0
    }
3101
3102
0
    return delta;
3103
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
3104
3105
  template <typename Float = float>
3106
  HB_ALWAYS_INLINE
3107
  Float get_delta (unsigned int inner,
3108
       const int *coords, unsigned int coord_count,
3109
       const VarRegionList &regions,
3110
       hb_scalar_cache_t *cache = nullptr) const
3111
0
  {
3112
0
    unsigned int count = regionIndices.len;
3113
0
    if (!count) return Float (0); // This is quite common, so optimize it.
3114
0
    return _get_delta<Float> (inner, coords, coord_count, regions, cache);
3115
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
3116
3117
  void get_region_scalars (const int *coords, unsigned int coord_count,
3118
         const VarRegionList &regions,
3119
         float *scalars /*OUT */,
3120
         unsigned int num_scalars) const
3121
0
  {
3122
0
    unsigned count = hb_min (num_scalars, regionIndices.len);
3123
0
    for (unsigned int i = 0; i < count; i++)
3124
0
      scalars[i] = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
3125
0
    for (unsigned int i = count; i < num_scalars; i++)
3126
0
      scalars[i] = 0.f;
3127
0
  }
3128
3129
  bool sanitize (hb_sanitize_context_t *c) const
3130
0
  {
3131
0
    TRACE_SANITIZE (this);
3132
0
    return_trace (c->check_struct (this) &&
3133
0
      regionIndices.sanitize (c) &&
3134
0
      hb_barrier () &&
3135
0
      wordCount () <= regionIndices.len &&
3136
0
      c->check_range (get_delta_bytes (),
3137
0
          itemCount,
3138
0
          get_row_size ()));
3139
0
  }
3140
3141
  bool serialize (hb_serialize_context_t *c,
3142
                  bool has_long,
3143
                  const hb_vector_t<const hb_vector_t<int>*>& rows)
3144
0
  {
3145
0
    TRACE_SERIALIZE (this);
3146
0
    unsigned row_count = rows.length;
3147
0
    if (!row_count) {
3148
0
      // Nothing to serialize, will be empty.
3149
0
      return false;
3150
0
    }
3151
0
3152
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
3153
0
    if (unlikely (!c->check_assign (itemCount, row_count,
3154
0
                                    HB_SERIALIZE_ERROR_INT_OVERFLOW)))
3155
0
      return_trace (false);
3156
0
3157
0
    int min_threshold = has_long ? -32768 : -128;
3158
0
    int max_threshold = has_long ? +32767 : +127;
3159
0
    enum delta_size_t { kZero=0, kNonWord, kWord };
3160
0
    hb_vector_t<delta_size_t> delta_sz;
3161
0
    unsigned num_regions = rows[0]->length;
3162
0
    if (!delta_sz.resize (num_regions))
3163
0
      return_trace (false);
3164
0
3165
0
    unsigned word_count = 0;
3166
0
    for (unsigned r = 0; r < num_regions; r++)
3167
0
    {
3168
0
      for (unsigned i = 0; i < row_count; i++)
3169
0
      {
3170
0
        int delta = rows[i]->arrayZ[r];
3171
0
        if (delta < min_threshold || delta > max_threshold)
3172
0
        {
3173
0
          delta_sz[r] = kWord;
3174
0
          word_count++;
3175
0
          break;
3176
0
        }
3177
0
        else if (delta != 0)
3178
0
        {
3179
0
          delta_sz[r] = kNonWord;
3180
0
        }
3181
0
      }
3182
0
    }
3183
0
3184
0
    /* reorder regions: words and then non-words*/
3185
0
    unsigned word_index = 0;
3186
0
    unsigned non_word_index = word_count;
3187
0
    hb_map_t ri_map;
3188
0
    for (unsigned r = 0; r < num_regions; r++)
3189
0
    {
3190
0
      if (!delta_sz[r]) continue;
3191
0
      unsigned new_r = (delta_sz[r] == kWord)? word_index++ : non_word_index++;
3192
0
      if (!ri_map.set (new_r, r))
3193
0
        return_trace (false);
3194
0
    }
3195
0
3196
0
    wordSizeCount = word_count | (has_long ? 0x8000u /* LONG_WORDS */ : 0);
3197
0
3198
0
    unsigned ri_count = ri_map.get_population ();
3199
0
    regionIndices.len = ri_count;
3200
0
    if (unlikely (!c->extend (this))) return_trace (false);
3201
0
3202
0
    for (unsigned r = 0; r < ri_count; r++)
3203
0
    {
3204
0
      hb_codepoint_t *idx;
3205
0
      if (!ri_map.has (r, &idx))
3206
0
        return_trace (false);
3207
0
      regionIndices[r] = *idx;
3208
0
    }
3209
0
3210
0
    HBUINT8 *delta_bytes = get_delta_bytes ();
3211
0
    unsigned row_size = get_row_size ();
3212
0
    for (unsigned int i = 0; i < row_count; i++)
3213
0
    {
3214
0
      for (unsigned int r = 0; r < ri_count; r++)
3215
0
      {
3216
0
        int delta = rows[i]->arrayZ[ri_map[r]];
3217
0
        set_item_delta_fast (i, r, delta, delta_bytes, row_size);
3218
0
      }
3219
0
    }
3220
0
    return_trace (true);
3221
0
  }
3222
3223
  bool serialize (hb_serialize_context_t *c,
3224
      const VarData *src,
3225
      const hb_inc_bimap_t &inner_map,
3226
      const hb_inc_bimap_t &region_map,
3227
      const hb_set_t *culled_regions = nullptr)
3228
0
  {
3229
0
    TRACE_SERIALIZE (this);
3230
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
3231
0
    itemCount = inner_map.get_next_value ();
3232
0
3233
0
    /* Optimize word count */
3234
0
    unsigned ri_count = src->regionIndices.len;
3235
0
    enum delta_size_t { kZero=0, kNonWord, kWord };
3236
0
    hb_vector_t<delta_size_t> delta_sz;
3237
0
    hb_vector_t<unsigned int> ri_map; /* maps new index to old index */
3238
0
    delta_sz.resize (ri_count);
3239
0
    ri_map.resize (ri_count);
3240
0
    unsigned int new_word_count = 0;
3241
0
    unsigned int r;
3242
0
3243
0
    const HBUINT8 *src_delta_bytes = src->get_delta_bytes ();
3244
0
    unsigned src_row_size = src->get_row_size ();
3245
0
    unsigned src_word_count = src->wordCount ();
3246
0
    bool     src_long_words = src->longWords ();
3247
0
3248
0
    bool has_long = false;
3249
0
    if (src_long_words)
3250
0
    {
3251
0
      for (r = 0; r < src_word_count; r++)
3252
0
      {
3253
0
        for (unsigned old_gid : inner_map.keys())
3254
0
  {
3255
0
    int32_t delta = src->get_item_delta_fast (old_gid, r, src_delta_bytes, src_row_size);
3256
0
    if (delta < -32768 || 32767 < delta)
3257
0
    {
3258
0
      has_long = true;
3259
0
      break;
3260
0
    }
3261
0
        }
3262
0
      }
3263
0
    }
3264
0
3265
0
    signed min_threshold = has_long ? -32768 : -128;
3266
0
    signed max_threshold = has_long ? +32767 : +127;
3267
0
    for (r = 0; r < ri_count; r++)
3268
0
    {
3269
0
      bool short_circuit = src_long_words == has_long && src_word_count <= r;
3270
0
3271
0
      delta_sz[r] = kZero;
3272
0
      if (culled_regions && culled_regions->has (src->regionIndices[r]))
3273
0
  continue; /* unreachable region: drop its column */
3274
0
      for (unsigned old_gid : inner_map.keys())
3275
0
      {
3276
0
  int32_t delta = src->get_item_delta_fast (old_gid, r, src_delta_bytes, src_row_size);
3277
0
  if (delta < min_threshold || max_threshold < delta)
3278
0
  {
3279
0
    delta_sz[r] = kWord;
3280
0
    new_word_count++;
3281
0
    break;
3282
0
  }
3283
0
  else if (delta != 0)
3284
0
  {
3285
0
    delta_sz[r] = kNonWord;
3286
0
    if (short_circuit)
3287
0
      break;
3288
0
  }
3289
0
      }
3290
0
    }
3291
0
3292
0
    unsigned int word_index = 0;
3293
0
    unsigned int non_word_index = new_word_count;
3294
0
    unsigned int new_ri_count = 0;
3295
0
    for (r = 0; r < ri_count; r++)
3296
0
      if (delta_sz[r])
3297
0
      {
3298
0
  unsigned new_r = (delta_sz[r] == kWord)? word_index++ : non_word_index++;
3299
0
  ri_map[new_r] = r;
3300
0
  new_ri_count++;
3301
0
      }
3302
0
3303
0
    wordSizeCount = new_word_count | (has_long ? 0x8000u /* LONG_WORDS */ : 0);
3304
0
3305
0
    regionIndices.len = new_ri_count;
3306
0
3307
0
    if (unlikely (!c->extend (this))) return_trace (false);
3308
0
3309
0
    for (r = 0; r < new_ri_count; r++)
3310
0
      regionIndices[r] = region_map[src->regionIndices[ri_map[r]]];
3311
0
3312
0
    HBUINT8 *delta_bytes = get_delta_bytes ();
3313
0
    unsigned row_size = get_row_size ();
3314
0
    unsigned count = itemCount;
3315
0
    for (unsigned int i = 0; i < count; i++)
3316
0
    {
3317
0
      unsigned int old = inner_map.backward (i);
3318
0
      for (unsigned int r = 0; r < new_ri_count; r++)
3319
0
  set_item_delta_fast (i, r,
3320
0
           src->get_item_delta_fast (old, ri_map[r],
3321
0
                   src_delta_bytes, src_row_size),
3322
0
           delta_bytes, row_size);
3323
0
    }
3324
0
3325
0
    return_trace (true);
3326
0
  }
3327
3328
  void collect_region_refs (hb_set_t &region_indices, const hb_inc_bimap_t &inner_map) const
3329
0
  {
3330
0
    const HBUINT8 *delta_bytes = get_delta_bytes ();
3331
0
    unsigned row_size = get_row_size ();
3332
0
3333
0
    for (unsigned int r = 0; r < regionIndices.len; r++)
3334
0
    {
3335
0
      unsigned int region = regionIndices.arrayZ[r];
3336
0
      if (region_indices.has (region)) continue;
3337
0
      for (hb_codepoint_t old_gid : inner_map.keys())
3338
0
  if (get_item_delta_fast (old_gid, r, delta_bytes, row_size) != 0)
3339
0
  {
3340
0
    region_indices.add (region);
3341
0
    break;
3342
0
  }
3343
0
    }
3344
0
  }
3345
3346
  public:
3347
  const HBUINT8 *get_delta_bytes () const
3348
0
  { return &StructAfter<HBUINT8> (regionIndices); }
3349
3350
  protected:
3351
  HBUINT8 *get_delta_bytes ()
3352
0
  { return &StructAfter<HBUINT8> (regionIndices); }
3353
3354
  public:
3355
  int32_t get_item_delta_fast (unsigned int item, unsigned int region,
3356
             const HBUINT8 *delta_bytes, unsigned row_size) const
3357
0
  {
3358
0
    if (unlikely (item >= itemCount || region >= regionIndices.len)) return 0;
3359
0
3360
0
    const HBINT8 *p = (const HBINT8 *) delta_bytes + item * row_size;
3361
0
    unsigned word_count = wordCount ();
3362
0
    bool is_long = longWords ();
3363
0
    if (is_long)
3364
0
    {
3365
0
      if (region < word_count)
3366
0
  return ((const HBINT32 *) p)[region];
3367
0
      else
3368
0
  return ((const HBINT16 *)(p + HBINT32::static_size * word_count))[region - word_count];
3369
0
    }
3370
0
    else
3371
0
    {
3372
0
      if (region < word_count)
3373
0
  return ((const HBINT16 *) p)[region];
3374
0
      else
3375
0
  return (p + HBINT16::static_size * word_count)[region - word_count];
3376
0
    }
3377
0
  }
3378
  int32_t get_item_delta (unsigned int item, unsigned int region) const
3379
0
  {
3380
0
     return get_item_delta_fast (item, region,
3381
0
         get_delta_bytes (),
3382
0
         get_row_size ());
3383
0
  }
3384
3385
  protected:
3386
  void set_item_delta_fast (unsigned int item, unsigned int region, int32_t delta,
3387
          HBUINT8 *delta_bytes, unsigned row_size)
3388
0
  {
3389
0
    HBINT8 *p = (HBINT8 *) delta_bytes + item * row_size;
3390
0
    unsigned word_count = wordCount ();
3391
0
    bool is_long = longWords ();
3392
0
    if (is_long)
3393
0
    {
3394
0
      if (region < word_count)
3395
0
  ((HBINT32 *) p)[region] = delta;
3396
0
      else
3397
0
  ((HBINT16 *)(p + HBINT32::static_size * word_count))[region - word_count] = delta;
3398
0
    }
3399
0
    else
3400
0
    {
3401
0
      if (region < word_count)
3402
0
  ((HBINT16 *) p)[region] = delta;
3403
0
      else
3404
0
  (p + HBINT16::static_size * word_count)[region - word_count] = delta;
3405
0
    }
3406
0
  }
3407
  void set_item_delta (unsigned int item, unsigned int region, int32_t delta)
3408
0
  {
3409
0
    set_item_delta_fast (item, region, delta,
3410
0
       get_delta_bytes (),
3411
0
       get_row_size ());
3412
0
  }
3413
3414
0
  bool longWords () const { return wordSizeCount & 0x8000u /* LONG_WORDS */; }
3415
0
  unsigned wordCount () const { return wordSizeCount & 0x7FFFu /* WORD_DELTA_COUNT_MASK */; }
3416
3417
  protected:
3418
  HBUINT16    itemCount;
3419
  HBUINT16    wordSizeCount;
3420
  Array16Of<HBUINT16> regionIndices;
3421
/*UnsizedArrayOf<HBUINT8>bytesX;*/
3422
  public:
3423
  DEFINE_SIZE_ARRAY (6, regionIndices);
3424
};
3425
3426
struct MultiVarData
3427
{
3428
  size_t get_size () const
3429
0
  { return hb_unsigned_add_saturate (min_size - regionIndices.min_size,
3430
0
             regionIndices.get_size ()); }
3431
3432
  const TupleList &get_delta_sets () const
3433
0
  { return this+StructAfter<decltype (deltaSetsX)> (regionIndices); }
3434
3435
  void get_delta (unsigned int inner,
3436
      const int *coords, unsigned int coord_count,
3437
      const SparseVarRegionList &regions,
3438
      hb_array_t<double> out,
3439
      hb_scalar_cache_t *cache = nullptr) const
3440
0
  {
3441
0
    auto &deltaSets = get_delta_sets ();
3442
3443
0
    auto values_iter = deltaSets.fetcher (inner);
3444
0
    unsigned regionCount = regionIndices.len;
3445
0
    unsigned skip = 0;
3446
0
    for (unsigned regionIndex = 0; regionIndex < regionCount; regionIndex++)
3447
0
    {
3448
0
      float scalar = regions.evaluate (regionIndices.arrayZ[regionIndex],
3449
0
               coords, coord_count,
3450
0
               cache);
3451
      // We skip lazily. Helps with the tail end.
3452
0
      if (scalar == 0.0f)
3453
0
        skip += out.length;
3454
0
      else
3455
0
      {
3456
0
        if (skip)
3457
0
  {
3458
0
    values_iter.skip (skip);
3459
0
    skip = 0;
3460
0
  }
3461
0
  values_iter.add_to (out, scalar);
3462
0
      }
3463
0
    }
3464
0
  }
3465
3466
  bool sanitize (hb_sanitize_context_t *c) const
3467
0
  {
3468
0
    TRACE_SANITIZE (this);
3469
0
    return_trace (format.sanitize (c) &&
3470
0
      hb_barrier () &&
3471
0
      format == 1 &&
3472
0
      regionIndices.sanitize (c) &&
3473
0
      hb_barrier () &&
3474
0
      StructAfter<decltype (deltaSetsX)> (regionIndices).sanitize (c, this));
3475
0
  }
3476
3477
  unsigned get_item_count () const
3478
0
  { return get_delta_sets ().count; }
3479
3480
  void collect_region_refs (hb_set_t &region_indices) const
3481
0
  {
3482
0
    for (unsigned region : regionIndices)
3483
0
      region_indices.add (region);
3484
0
  }
3485
3486
  bool serialize (hb_serialize_context_t *c,
3487
      const MultiVarData *src,
3488
      const hb_inc_bimap_t &inner_map,
3489
      const hb_inc_bimap_t &region_map)
3490
0
  {
3491
0
    TRACE_SERIALIZE (this);
3492
0
    unsigned region_count = src->regionIndices.len;
3493
0
    unsigned header_size = HBUINT8::static_size +
3494
0
         Array16Of<HBUINT16>::min_size +
3495
0
         region_count * HBUINT16::static_size +
3496
0
         HBUINT32::static_size;
3497
0
    if (unlikely (!c->extend_size (this, header_size, false)))
3498
0
      return_trace (false);
3499
0
    format = 1;
3500
0
    regionIndices.len = region_count;
3501
0
    for (unsigned i = 0; i < regionIndices.len; i++)
3502
0
    {
3503
0
      unsigned old_region = src->regionIndices[i];
3504
0
      if (unlikely (!region_map.has (old_region)))
3505
0
  return_trace (false);
3506
0
      regionIndices[i] = region_map.get (old_region);
3507
0
    }
3508
0
3509
0
    const auto &src_delta_sets = src->get_delta_sets ();
3510
0
    hb_vector_t<hb_ubytes_t> delta_sets;
3511
0
    unsigned data_size = 0;
3512
0
    if (unlikely (!delta_sets.alloc_exact (inner_map.get_population ())))
3513
0
      return_trace (false);
3514
0
    for (unsigned i = 0; i < inner_map.get_population (); i++)
3515
0
    {
3516
0
      unsigned old_inner = inner_map.backward (i);
3517
0
      if (unlikely (old_inner >= src_delta_sets.count)) return_trace (false);
3518
0
      hb_ubytes_t bytes = static_cast<const CFF2Index &> (src_delta_sets)[old_inner];
3519
0
      data_size = hb_unsigned_add_saturate (data_size, bytes.length);
3520
0
      delta_sets.push (bytes);
3521
0
    }
3522
0
    if (unlikely (data_size == UINT_MAX || delta_sets.in_error ()))
3523
0
      return_trace (false);
3524
0
3525
0
    auto &out_delta_sets = StructAfter<decltype (deltaSetsX)> (regionIndices);
3526
0
    return_trace (out_delta_sets.serialize_serialize (c, delta_sets.iter (), &data_size));
3527
0
  }
3528
3529
  protected:
3530
  HBUINT8       format; // 1
3531
  Array16Of<HBUINT16> regionIndices;
3532
  Offset32To<TupleList> deltaSetsX;
3533
  public:
3534
  DEFINE_SIZE_MIN (7);
3535
};
3536
3537
struct ItemVariationStore
3538
{
3539
  friend struct item_variations_t;
3540
3541
  hb_scalar_cache_t *create_cache () const
3542
78.1k
  {
3543
#ifdef HB_NO_VAR
3544
    return hb_scalar_cache_t::create (0);
3545
#endif
3546
78.1k
    return hb_scalar_cache_t::create ((this+regions).regionCount);
3547
78.1k
  }
3548
3549
  static void destroy_cache (hb_scalar_cache_t *cache)
3550
78.1k
  {
3551
78.1k
    hb_scalar_cache_t::destroy (cache);
3552
78.1k
  }
3553
3554
  private:
3555
  template <typename Float = float>
3556
  Float get_delta (unsigned int outer, unsigned int inner,
3557
       const int *coords, unsigned int coord_count,
3558
       hb_scalar_cache_t *cache = nullptr) const
3559
0
  {
3560
#ifdef HB_NO_VAR
3561
    return Float (0);
3562
#endif
3563
3564
0
    if (unlikely (outer >= dataSets.len))
3565
0
      return Float (0);
3566
3567
0
    return (this+dataSets[outer]).get_delta<Float> (inner,
3568
0
               coords, coord_count,
3569
0
               this+regions,
3570
0
               cache);
3571
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
3572
3573
  public:
3574
  bool has_delta_set (unsigned int index) const
3575
0
  {
3576
0
#ifdef HB_NO_VAR
3577
0
    return false;
3578
0
#endif
3579
0
3580
0
    unsigned int outer = index >> 16;
3581
0
    unsigned int inner = index & 0xFFFF;
3582
0
    return outer < dataSets.len &&
3583
0
     inner < (this+dataSets[outer]).get_item_count ();
3584
0
  }
3585
3586
  template <typename Float = float>
3587
  Float get_delta (unsigned int index,
3588
       const int *coords, unsigned int coord_count,
3589
       hb_scalar_cache_t *cache = nullptr) const
3590
0
  {
3591
0
    unsigned int outer = index >> 16;
3592
0
    unsigned int inner = index & 0xFFFF;
3593
0
    return get_delta<Float> (outer, inner, coords, coord_count, cache);
3594
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
3595
  template <typename Float = float>
3596
  Float get_delta (unsigned int index,
3597
       hb_array_t<const int> coords,
3598
       hb_scalar_cache_t *cache = nullptr) const
3599
0
  {
3600
0
    return get_delta<Float> (index,
3601
0
          coords.arrayZ, coords.length,
3602
0
          cache);
3603
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
3604
3605
  bool sanitize (hb_sanitize_context_t *c) const
3606
0
  {
3607
#ifdef HB_NO_VAR
3608
    return true;
3609
#endif
3610
3611
0
    TRACE_SANITIZE (this);
3612
0
    return_trace (c->check_struct (this) &&
3613
0
      hb_barrier () &&
3614
0
      format == 1 &&
3615
0
      regions.sanitize (c, this) &&
3616
0
      dataSets.sanitize (c, this));
3617
0
  }
3618
3619
  bool serialize (hb_serialize_context_t *c,
3620
                  bool has_long,
3621
                  const hb_vector_t<hb_tag_t>& axis_tags,
3622
                  const hb_vector_t<const hb_hashmap_t<hb_tag_t, Triple>*>& region_list,
3623
                  const hb_vector_t<delta_row_encoding_t>& vardata_encodings)
3624
0
  {
3625
0
    TRACE_SERIALIZE (this);
3626
0
#ifdef HB_NO_VAR
3627
0
    return_trace (false);
3628
0
#endif
3629
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
3630
0
3631
0
    format = 1;
3632
0
    if (!regions.serialize_serialize (c, axis_tags, region_list))
3633
0
      return_trace (false);
3634
0
3635
0
    unsigned num_var_data = vardata_encodings.length;
3636
0
    if (!num_var_data) return_trace (false);
3637
0
    if (unlikely (!c->check_assign (dataSets.len, num_var_data,
3638
0
                                    HB_SERIALIZE_ERROR_INT_OVERFLOW)))
3639
0
      return_trace (false);
3640
0
3641
0
    if (unlikely (!c->extend (dataSets))) return_trace (false);
3642
0
    for (unsigned i = 0; i < num_var_data; i++)
3643
0
      if (!dataSets[i].serialize_serialize (c, has_long, vardata_encodings[i].items))
3644
0
        return_trace (false);
3645
0
3646
0
    return_trace (true);
3647
0
  }
3648
3649
  bool serialize (hb_serialize_context_t *c,
3650
      const ItemVariationStore *src,
3651
      const hb_array_t <const hb_inc_bimap_t> &inner_maps,
3652
      const hb_set_t *culled_regions = nullptr)
3653
0
  {
3654
0
    TRACE_SERIALIZE (this);
3655
0
#ifdef HB_NO_VAR
3656
0
    return_trace (false);
3657
0
#endif
3658
0
3659
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
3660
0
3661
0
    unsigned int set_count = 0;
3662
0
    for (unsigned int i = 0; i < inner_maps.length; i++)
3663
0
      if (inner_maps[i].get_population ())
3664
0
  set_count++;
3665
0
3666
0
    format = 1;
3667
0
3668
0
    const auto &src_regions = src+src->regions;
3669
0
3670
0
    hb_set_t region_indices;
3671
0
    for (unsigned int i = 0; i < inner_maps.length; i++)
3672
0
      (src+src->dataSets[i]).collect_region_refs (region_indices, inner_maps[i]);
3673
0
3674
0
    if (region_indices.in_error ())
3675
0
      return_trace (false);
3676
0
3677
0
    region_indices.del_range ((src_regions).regionCount, hb_set_t::INVALID);
3678
0
3679
0
    if (culled_regions)
3680
0
      region_indices.subtract (*culled_regions);
3681
0
3682
0
    /* TODO use constructor when our data-structures support that. */
3683
0
    hb_inc_bimap_t region_map;
3684
0
    + hb_iter (region_indices)
3685
0
    | hb_apply ([&region_map] (unsigned _) { region_map.add(_); })
3686
0
    ;
3687
0
    if (region_map.in_error())
3688
0
      return_trace (false);
3689
0
3690
0
    if (unlikely (!regions.serialize_serialize (c, &src_regions, region_map)))
3691
0
      return_trace (false);
3692
0
3693
0
    dataSets.len = set_count;
3694
0
    if (unlikely (!c->extend (dataSets))) return_trace (false);
3695
0
3696
0
    /* TODO: The following code could be simplified when
3697
0
     * List16OfOffset16To::subset () can take a custom param to be passed to VarData::serialize () */
3698
0
    unsigned int set_index = 0;
3699
0
    for (unsigned int i = 0; i < inner_maps.length; i++)
3700
0
    {
3701
0
      if (!inner_maps[i].get_population ()) continue;
3702
0
      if (unlikely (!dataSets[set_index++]
3703
0
         .serialize_serialize (c, &(src+src->dataSets[i]), inner_maps[i], region_map,
3704
0
             culled_regions)))
3705
0
  return_trace (false);
3706
0
    }
3707
0
3708
0
    return_trace (true);
3709
0
  }
3710
3711
  ItemVariationStore *copy (hb_serialize_context_t *c) const
3712
0
  {
3713
0
    TRACE_SERIALIZE (this);
3714
0
    auto *out = c->start_embed (this);
3715
0
    if (unlikely (!out)) return_trace (nullptr);
3716
0
3717
0
    hb_vector_t <hb_inc_bimap_t> inner_maps;
3718
0
    unsigned count = dataSets.len;
3719
0
    for (unsigned i = 0; i < count; i++)
3720
0
    {
3721
0
      hb_inc_bimap_t *map = inner_maps.push ();
3722
0
      if (unlikely (!c->propagate_error(inner_maps)))
3723
0
        return_trace(nullptr);
3724
0
      auto &data = this+dataSets[i];
3725
0
3726
0
      unsigned itemCount = data.get_item_count ();
3727
0
      for (unsigned j = 0; j < itemCount; j++)
3728
0
  map->add (j);
3729
0
    }
3730
0
3731
0
    if (unlikely (!out->serialize (c, this, inner_maps))) return_trace (nullptr);
3732
0
3733
0
    return_trace (out);
3734
0
  }
3735
3736
  /* Collect regions that a partial avar2 instance can never reach, per the
3737
   * plan's reachable final-coordinate ranges. */
3738
  bool collect_dead_regions (const hb_map_t &axes_old_index_tag_map,
3739
           const hb_hashmap_t<hb_tag_t, Triple> &reachable_ranges,
3740
           hb_set_t &dead_regions /* OUT */) const
3741
0
  {
3742
0
#ifndef HB_NO_VAR
3743
0
    if (!reachable_ranges.get_population ()) return true;
3744
0
    const VarRegionList &region_list = this+regions;
3745
0
    unsigned count = region_list.regionCount;
3746
0
    for (unsigned i = 0; i < count; i++)
3747
0
    {
3748
0
      hb_hashmap_t<hb_tag_t, Triple> axis_tuples;
3749
0
      if (!region_list.get_var_region (i, axes_old_index_tag_map, axis_tuples))
3750
0
  return false;
3751
0
      if (_hb_avar2_region_is_dead (axis_tuples, reachable_ranges))
3752
0
  dead_regions.add (i);
3753
0
    }
3754
0
    return !dead_regions.in_error ();
3755
0
#else
3756
0
    return true;
3757
0
#endif
3758
0
  }
3759
3760
  bool subset (hb_subset_context_t *c, const hb_array_t<const hb_inc_bimap_t> &inner_maps) const
3761
0
  {
3762
0
    TRACE_SUBSET (this);
3763
0
#ifdef HB_NO_VAR
3764
0
    return_trace (false);
3765
0
#endif
3766
0
3767
0
    ItemVariationStore *varstore_prime = c->serializer->start_embed<ItemVariationStore> ();
3768
0
    if (unlikely (!varstore_prime)) return_trace (false);
3769
0
3770
0
    /* avar2 partial instancing: cull unreachable regions. */
3771
0
    hb_set_t dead_regions;
3772
0
    if (c->plan->has_avar2)
3773
0
      if (!collect_dead_regions (c->plan->axes_old_index_tag_map,
3774
0
         c->plan->avar2_reachable_ranges,
3775
0
         dead_regions))
3776
0
  return_trace (false);
3777
0
3778
0
    varstore_prime->serialize (c->serializer, this, inner_maps,
3779
0
             dead_regions.get_population () ? &dead_regions : nullptr);
3780
0
3781
0
    return_trace (
3782
0
        !c->serializer->in_error()
3783
0
        && varstore_prime->dataSets);
3784
0
  }
3785
3786
  unsigned int get_region_index_count (unsigned int major) const
3787
0
  {
3788
#ifdef HB_NO_VAR
3789
    return 0;
3790
#endif
3791
0
    return (this+dataSets[major]).get_region_index_count ();
3792
0
  }
3793
3794
  void get_region_scalars (unsigned int major,
3795
         const int *coords, unsigned int coord_count,
3796
         float *scalars /*OUT*/,
3797
         unsigned int num_scalars) const
3798
0
  {
3799
#ifdef HB_NO_VAR
3800
    for (unsigned i = 0; i < num_scalars; i++)
3801
      scalars[i] = 0.f;
3802
    return;
3803
#endif
3804
3805
0
    (this+dataSets[major]).get_region_scalars (coords, coord_count,
3806
0
                 this+regions,
3807
0
                 &scalars[0], num_scalars);
3808
0
  }
3809
3810
  unsigned int get_sub_table_count () const
3811
0
   {
3812
0
#ifdef HB_NO_VAR
3813
0
     return 0;
3814
0
#endif
3815
0
     return dataSets.len;
3816
0
   }
3817
3818
  const VarData& get_sub_table (unsigned i) const
3819
0
  {
3820
0
#ifdef HB_NO_VAR
3821
0
     return Null (VarData);
3822
0
#endif
3823
0
     return this+dataSets[i];
3824
0
  }
3825
3826
  const VarRegionList& get_region_list () const
3827
0
  {
3828
0
#ifdef HB_NO_VAR
3829
0
     return Null (VarRegionList);
3830
0
#endif
3831
0
     return this+regions;
3832
0
  }
3833
3834
  protected:
3835
  HBUINT16        format;
3836
  Offset32To<VarRegionList>   regions;
3837
  Array16OfOffset32To<VarData>    dataSets;
3838
  public:
3839
  DEFINE_SIZE_ARRAY_SIZED (8, dataSets);
3840
};
3841
3842
struct MultiItemVariationStore
3843
{
3844
  hb_scalar_cache_t *create_cache (hb_scalar_cache_t *static_cache = nullptr) const
3845
0
  {
3846
#ifdef HB_NO_VAR
3847
    return hb_scalar_cache_t::create (0);
3848
#endif
3849
0
    auto &r = this+regions;
3850
0
    unsigned count = r.regions.len;
3851
3852
0
    return hb_scalar_cache_t::create (count, static_cache);
3853
0
  }
3854
3855
  static void destroy_cache (hb_scalar_cache_t *cache,
3856
           hb_scalar_cache_t *static_cache = nullptr)
3857
0
  {
3858
0
    hb_scalar_cache_t::destroy (cache, static_cache);
3859
0
  }
3860
3861
  private:
3862
  void get_delta (unsigned int outer, unsigned int inner,
3863
      const int *coords, unsigned int coord_count,
3864
      hb_array_t<double> out,
3865
      hb_scalar_cache_t *cache = nullptr) const
3866
0
  {
3867
#ifdef HB_NO_VAR
3868
    return;
3869
#endif
3870
3871
0
    if (unlikely (outer >= dataSets.len))
3872
0
      return;
3873
3874
0
    return (this+dataSets[outer]).get_delta (inner,
3875
0
               coords, coord_count,
3876
0
               this+regions,
3877
0
               out,
3878
0
               cache);
3879
0
  }
3880
3881
  public:
3882
  void get_delta (unsigned int index,
3883
      const int *coords, unsigned int coord_count,
3884
      hb_array_t<double> out,
3885
      hb_scalar_cache_t *cache = nullptr) const
3886
0
  {
3887
0
    unsigned int outer = index >> 16;
3888
0
    unsigned int inner = index & 0xFFFF;
3889
0
    get_delta (outer, inner, coords, coord_count, out, cache);
3890
0
  }
3891
  void get_delta (unsigned int index,
3892
      hb_array_t<const int> coords,
3893
      hb_array_t<double> out,
3894
      hb_scalar_cache_t *cache = nullptr) const
3895
0
  {
3896
0
    return get_delta (index,
3897
0
          coords.arrayZ, coords.length,
3898
0
          out,
3899
0
          cache);
3900
0
  }
3901
3902
  bool sanitize (hb_sanitize_context_t *c) const
3903
0
  {
3904
#ifdef HB_NO_VAR
3905
    return true;
3906
#endif
3907
3908
0
    TRACE_SANITIZE (this);
3909
0
    return_trace (c->check_struct (this) &&
3910
0
      hb_barrier () &&
3911
0
      format == 1 &&
3912
0
      regions.sanitize (c, this) &&
3913
0
      dataSets.sanitize (c, this));
3914
0
  }
3915
3916
  bool create_subset_plan (const hb_set_t &var_indices,
3917
         hb_vector_t<hb_inc_bimap_t> *inner_maps,
3918
         hb_map_t *varidx_map) const
3919
0
  {
3920
0
    if (unlikely (!inner_maps->resize (dataSets.len))) return false;
3921
0
    for (hb_codepoint_t var_idx : var_indices)
3922
0
    {
3923
0
      unsigned outer = var_idx >> 16;
3924
0
      unsigned inner = var_idx & 0xFFFFu;
3925
0
      if (unlikely (outer >= dataSets.len ||
3926
0
        inner >= (this+dataSets[outer]).get_item_count ()))
3927
0
  return false;
3928
0
      (*inner_maps)[outer].add (inner);
3929
0
    }
3930
0
3931
0
    unsigned new_outer = 0;
3932
0
    for (unsigned outer = 0; outer < inner_maps->length; outer++)
3933
0
    {
3934
0
      const hb_inc_bimap_t &inner_map = (*inner_maps)[outer];
3935
0
      if (!inner_map.get_population ()) continue;
3936
0
      if (unlikely (inner_map.in_error ())) return false;
3937
0
      for (unsigned new_inner = 0;
3938
0
     new_inner < inner_map.get_population ();
3939
0
     new_inner++)
3940
0
      {
3941
0
  unsigned old_inner = inner_map.backward (new_inner);
3942
0
  varidx_map->set ((outer << 16) | old_inner,
3943
0
      (new_outer << 16) | new_inner);
3944
0
      }
3945
0
      new_outer++;
3946
0
    }
3947
0
    return !inner_maps->in_error () && !varidx_map->in_error ();
3948
0
  }
3949
3950
  bool serialize (hb_serialize_context_t *c,
3951
      const MultiItemVariationStore *src,
3952
      const hb_array_t<const hb_inc_bimap_t> &inner_maps,
3953
      const hb_map_t *axis_map)
3954
0
  {
3955
0
    TRACE_SERIALIZE (this);
3956
0
    if (unlikely (!c->extend_min (this) ||
3957
0
      inner_maps.length < src->dataSets.len))
3958
0
      return_trace (false);
3959
0
    format = 1;
3960
0
3961
0
    const auto &src_regions = src+src->regions;
3962
0
    hb_set_t region_indices;
3963
0
    unsigned set_count = 0;
3964
0
    for (unsigned i = 0; i < src->dataSets.len; i++)
3965
0
    {
3966
0
      if (!inner_maps[i].get_population ()) continue;
3967
0
      set_count++;
3968
0
      (src+src->dataSets[i]).collect_region_refs (region_indices);
3969
0
    }
3970
0
    region_indices.del_range (src_regions.regions.len, hb_set_t::INVALID);
3971
0
    hb_inc_bimap_t region_map;
3972
0
    region_map.add_set (&region_indices);
3973
0
    if (unlikely (region_indices.in_error () || region_map.in_error () ||
3974
0
      !regions.serialize_serialize (c, &src_regions, region_map, axis_map)))
3975
0
      return_trace (false);
3976
0
3977
0
    dataSets.len = set_count;
3978
0
    if (unlikely (!c->extend (dataSets))) return_trace (false);
3979
0
    unsigned set_index = 0;
3980
0
    for (unsigned i = 0; i < src->dataSets.len; i++)
3981
0
    {
3982
0
      if (!inner_maps[i].get_population ()) continue;
3983
0
      if (unlikely (!dataSets[set_index++].serialize_serialize (
3984
0
          c, &(src+src->dataSets[i]), inner_maps[i], region_map)))
3985
0
  return_trace (false);
3986
0
    }
3987
0
    return_trace (true);
3988
0
  }
3989
3990
  protected:
3991
  HBUINT16        format; // 1
3992
  Offset32To<SparseVarRegionList> regions;
3993
  Array16OfOffset32To<MultiVarData> dataSets;
3994
  public:
3995
  DEFINE_SIZE_ARRAY_SIZED (8, dataSets);
3996
};
3997
3998
template <typename MapCountT>
3999
struct DeltaSetIndexMapFormat01
4000
{
4001
  friend struct DeltaSetIndexMap;
4002
4003
  size_t get_size () const
4004
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
4005
4006
  private:
4007
  DeltaSetIndexMapFormat01* copy (hb_serialize_context_t *c) const
4008
0
  {
4009
0
    TRACE_SERIALIZE (this);
4010
0
    return_trace (c->embed (this));
4011
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
4012
4013
  template <typename T>
4014
  bool serialize (hb_serialize_context_t *c, const T &plan)
4015
0
  {
4016
0
    unsigned int width = plan.get_width ();
4017
0
    unsigned int inner_bit_count = plan.get_inner_bit_count ();
4018
0
    const hb_array_t<const uint32_t> output_map = plan.get_output_map ();
4019
0
4020
0
    TRACE_SERIALIZE (this);
4021
0
    if (unlikely (output_map.length && ((((inner_bit_count-1)&~0xF)!=0) || (((width-1)&~0x3)!=0))))
4022
0
      return_trace (false);
4023
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
4024
0
4025
0
    entryFormat = ((width-1)<<4)|(inner_bit_count-1);
4026
0
    mapCount = output_map.length;
4027
0
    HBUINT8 *p = c->allocate_size<HBUINT8> (width * output_map.length);
4028
0
    if (unlikely (!p)) return_trace (false);
4029
0
    for (unsigned int i = 0; i < output_map.length; i++)
4030
0
    {
4031
0
      unsigned int v = output_map.arrayZ[i];
4032
0
      if (v)
4033
0
      {
4034
0
  unsigned int outer = v >> 16;
4035
0
  unsigned int inner = v & 0xFFFF;
4036
0
  unsigned int u = (outer << inner_bit_count) | inner;
4037
0
  for (unsigned int w = width; w > 0;)
4038
0
  {
4039
0
    p[--w] = u;
4040
0
    u >>= 8;
4041
0
  }
4042
0
      }
4043
0
      p += width;
4044
0
    }
4045
0
    return_trace (true);
4046
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&)
4047
4048
  HB_ALWAYS_INLINE
4049
  uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */
4050
0
  {
4051
    /* If count is zero, pass value unchanged.  This takes
4052
     * care of direct mapping for advance map. */
4053
0
    if (!mapCount)
4054
0
      return v;
4055
0
    return _map (v);
4056
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
4057
4058
  HB_HOT
4059
  uint32_t _map (unsigned int v) const /* Returns 16.16 outer.inner. */
4060
0
  {
4061
0
    if (v >= mapCount)
4062
0
      v = mapCount - 1;
4063
4064
0
    unsigned int u = 0;
4065
0
    { /* Fetch it. */
4066
0
      unsigned int w = get_width ();
4067
0
      const HBUINT8 *p = mapDataZ.arrayZ + w * v;
4068
0
      for (; w; w--)
4069
0
        u = (u << 8) + *p++;
4070
0
    }
4071
4072
0
    { /* Repack it. */
4073
0
      unsigned int n = get_inner_bit_count ();
4074
0
      unsigned int outer = u >> n;
4075
0
      unsigned int inner = u & ((1 << n) - 1);
4076
0
      u = (outer<<16) | inner;
4077
0
    }
4078
4079
0
    return u;
4080
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
4081
4082
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
4083
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
4084
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
4085
4086
4087
  bool sanitize (hb_sanitize_context_t *c) const
4088
0
  {
4089
0
    TRACE_SANITIZE (this);
4090
0
    return_trace (c->check_struct (this) &&
4091
0
      hb_barrier () &&
4092
0
                  c->check_range (mapDataZ.arrayZ,
4093
0
                                  mapCount,
4094
0
                                  get_width ()));
4095
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
4096
4097
  protected:
4098
  HBUINT8       format;         /* Format identifier--format = 0 */
4099
  HBUINT8       entryFormat;    /* A packed field that describes the compressed
4100
                                 * representation of delta-set indices. */
4101
  MapCountT     mapCount;       /* The number of mapping entries. */
4102
  UnsizedArrayOf<HBUINT8>
4103
                mapDataZ;       /* The delta-set index mapping data. */
4104
4105
  public:
4106
  DEFINE_SIZE_ARRAY (2+MapCountT::static_size, mapDataZ);
4107
};
4108
4109
struct DeltaSetIndexMap
4110
{
4111
  template <typename T>
4112
  bool serialize (hb_serialize_context_t *c, const T &plan)
4113
0
  {
4114
0
    TRACE_SERIALIZE (this);
4115
0
    unsigned length = plan.get_output_map ().length;
4116
0
    u.format.v = length <= 0xFFFF ? 0 : 1;
4117
0
    switch (u.format.v) {
4118
0
    case 0: hb_barrier (); return_trace (u.format0.serialize (c, plan));
4119
0
    case 1: hb_barrier (); return_trace (u.format1.serialize (c, plan));
4120
0
    default:return_trace (false);
4121
0
    }
4122
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&)
4123
4124
  uint32_t map (unsigned v) const
4125
0
  {
4126
0
    switch (u.format.v) {
4127
0
    case 0: hb_barrier (); return (u.format0.map (v));
4128
0
    case 1: hb_barrier (); return (u.format1.map (v));
4129
0
    default:return v;
4130
0
    }
4131
0
  }
4132
4133
  unsigned get_map_count () const
4134
0
  {
4135
0
    switch (u.format.v) {
4136
0
    case 0: hb_barrier (); return u.format0.get_map_count ();
4137
0
    case 1: hb_barrier (); return u.format1.get_map_count ();
4138
0
    default:return 0;
4139
0
    }
4140
0
  }
4141
4142
  unsigned get_width () const
4143
0
  {
4144
0
    switch (u.format.v) {
4145
0
    case 0: hb_barrier (); return u.format0.get_width ();
4146
0
    case 1: hb_barrier (); return u.format1.get_width ();
4147
0
    default:return 0;
4148
0
    }
4149
0
  }
4150
4151
  unsigned get_inner_bit_count () const
4152
0
  {
4153
0
    switch (u.format.v) {
4154
0
    case 0: hb_barrier (); return u.format0.get_inner_bit_count ();
4155
0
    case 1: hb_barrier (); return u.format1.get_inner_bit_count ();
4156
0
    default:return 0;
4157
0
    }
4158
0
  }
4159
4160
  bool sanitize (hb_sanitize_context_t *c) const
4161
0
  {
4162
0
    TRACE_SANITIZE (this);
4163
0
    if (!u.format.v.sanitize (c)) return_trace (false);
4164
0
    hb_barrier ();
4165
0
    switch (u.format.v) {
4166
0
    case 0: hb_barrier (); return_trace (u.format0.sanitize (c));
4167
0
    case 1: hb_barrier (); return_trace (u.format1.sanitize (c));
4168
0
    default:return_trace (true);
4169
0
    }
4170
0
  }
4171
4172
  DeltaSetIndexMap* copy (hb_serialize_context_t *c) const
4173
0
  {
4174
0
    TRACE_SERIALIZE (this);
4175
0
    switch (u.format.v) {
4176
0
    case 0: hb_barrier (); return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format0.copy (c)));
4177
0
    case 1: hb_barrier (); return_trace (reinterpret_cast<DeltaSetIndexMap *> (u.format1.copy (c)));
4178
0
    default:return_trace (nullptr);
4179
0
    }
4180
0
  }
4181
4182
  protected:
4183
  union {
4184
  struct { HBUINT8 v; }             format;         /* Format identifier */
4185
  DeltaSetIndexMapFormat01<HBUINT16> format0;
4186
  DeltaSetIndexMapFormat01<HBUINT32> format1;
4187
  } u;
4188
  public:
4189
  DEFINE_SIZE_UNION (1, format.v);
4190
};
4191
4192
4193
struct ItemVarStoreInstancer
4194
{
4195
  ItemVarStoreInstancer (const ItemVariationStore *varStore_,
4196
       const DeltaSetIndexMap *varIdxMap,
4197
       hb_array_t<const int> coords,
4198
       hb_scalar_cache_t *cache = nullptr) :
4199
159k
    varStore (varStore_), varIdxMap (varIdxMap), coords (coords), cache (cache)
4200
159k
  {
4201
159k
    if (!varStore)
4202
0
      varStore = &Null(ItemVariationStore);
4203
    /* Like hb_font_t::has_nonzero_coords, treat explicit all-zero coordinates
4204
     * as the default instance, which uses unadjusted values (OFF 7.1). */
4205
159k
    if (!hb_any (coords))
4206
159k
      this->coords = {};
4207
159k
  }
4208
4209
0
  operator bool () const { return varStore && bool (coords); }
4210
4211
  float operator[] (uint32_t varIdx) const
4212
0
  { return (*this) (varIdx); }
4213
4214
  float operator() (uint32_t varIdx, unsigned short offset = 0) const
4215
0
  { return get_delta (varIdx, offset); }
4216
4217
  double get_condition_delta (uint32_t varIdx) const
4218
0
  { return get_delta<double> (varIdx); }
4219
4220
  template <typename Float = float>
4221
  Float get_delta (uint32_t varIdx, unsigned short offset = 0) const
4222
0
  {
4223
   /* Ordinary stores do not apply deltas at the default instance. */
4224
0
   if (!coords || varIdx == VarIdx::NO_VARIATION)
4225
0
     return Float (0);
4226
4227
0
    varIdx += offset;
4228
0
    if (varIdxMap)
4229
0
      varIdx = varIdxMap->map (varIdx);
4230
0
    return varStore->get_delta<Float> (varIdx, coords, cache);
4231
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
4232
4233
  const ItemVariationStore *varStore;
4234
  const DeltaSetIndexMap *varIdxMap;
4235
  hb_array_t<const int> coords;
4236
  hb_scalar_cache_t *cache;
4237
};
4238
4239
struct MultiItemVarStoreInstancer
4240
{
4241
  MultiItemVarStoreInstancer (const MultiItemVariationStore *varStore,
4242
            const DeltaSetIndexMap *varIdxMap,
4243
            hb_array_t<const int> coords,
4244
            hb_scalar_cache_t *cache = nullptr) :
4245
0
    varStore (varStore), varIdxMap (varIdxMap), coords (coords), cache (cache)
4246
0
  {
4247
0
    if (!varStore)
4248
0
      varStore = &Null(MultiItemVariationStore);
4249
0
  }
4250
4251
0
  operator bool () const { return varStore; }
4252
4253
  double get_condition_delta (uint32_t varIdx) const
4254
0
  { return (double) (*this)[varIdx]; }
4255
4256
  double operator[] (uint32_t varIdx) const
4257
0
  {
4258
0
    double v = 0;
4259
0
    (*this) (hb_array (&v, 1), varIdx);
4260
0
    return v;
4261
0
  }
4262
4263
  void operator() (hb_array_t<double> out, uint32_t varIdx, unsigned short offset = 0) const
4264
0
  {
4265
    /* Static VARC fonts can have constant deltas even with empty coordinates. */
4266
0
    if (varIdx != VarIdx::NO_VARIATION)
4267
0
    {
4268
0
      varIdx += offset;
4269
0
      if (varIdxMap)
4270
0
  varIdx = varIdxMap->map (varIdx);
4271
0
      varStore->get_delta (varIdx, coords, out, cache);
4272
0
    }
4273
0
    else
4274
0
      for (unsigned i = 0; i < out.length; i++)
4275
0
        out.arrayZ[i] = 0.;
4276
0
  }
4277
4278
  const MultiItemVariationStore *varStore;
4279
  const DeltaSetIndexMap *varIdxMap;
4280
  hb_array_t<const int> coords;
4281
  hb_scalar_cache_t *cache;
4282
};
4283
4284
4285
/*
4286
 * Feature Variations
4287
 */
4288
enum Cond_with_Var_flag_t
4289
{
4290
  KEEP_COND_WITH_VAR = 0,
4291
  KEEP_RECORD_WITH_VAR = 1,
4292
  DROP_COND_WITH_VAR = 2,
4293
  DROP_RECORD_WITH_VAR = 3,
4294
};
4295
4296
enum lookup_condition_subset_result_t
4297
{
4298
  LOOKUP_CONDITION_SUBSET_ERROR,
4299
  LOOKUP_CONDITION_SUBSET_FALSE,
4300
  LOOKUP_CONDITION_SUBSET_TRUE,
4301
  LOOKUP_CONDITION_SUBSET_KEEP,
4302
};
4303
4304
struct Condition;
4305
4306
template <typename Instancer>
4307
static bool
4308
_hb_recurse_condition_evaluate (const struct Condition &condition,
4309
        const int *coords,
4310
        unsigned int coord_len,
4311
        Instancer *instancer);
4312
4313
struct ConditionAxisRange
4314
{
4315
  friend struct Condition;
4316
4317
  bool subset (hb_subset_context_t *c) const
4318
0
  {
4319
0
    TRACE_SUBSET (this);
4320
0
    auto *out = c->serializer->embed (this);
4321
0
    if (unlikely (!out)) return_trace (false);
4322
0
4323
0
    const hb_map_t *index_map = &c->plan->axes_index_map;
4324
0
    if (index_map->is_empty ()) return_trace (true);
4325
0
4326
0
    const hb_map_t& axes_old_index_tag_map = c->plan->axes_old_index_tag_map;
4327
0
    hb_codepoint_t *axis_tag;
4328
0
    if (!axes_old_index_tag_map.has (axisIndex, &axis_tag) ||
4329
0
        !index_map->has (axisIndex))
4330
0
      return_trace (false);
4331
0
4332
0
    const hb_hashmap_t<hb_tag_t, Triple>& normalized_axes_location = c->plan->axes_location;
4333
0
    Triple axis_limit{-1.0, 0.0, 1.0};
4334
0
    Triple *normalized_limit;
4335
0
    if (normalized_axes_location.has (*axis_tag, &normalized_limit))
4336
0
      axis_limit = *normalized_limit;
4337
0
4338
0
    const hb_hashmap_t<hb_tag_t, TripleDistances>& axes_triple_distances = c->plan->axes_triple_distances;
4339
0
    TripleDistances axis_triple_distances{1.0, 1.0};
4340
0
    TripleDistances *triple_dists;
4341
0
    if (axes_triple_distances.has (*axis_tag, &triple_dists))
4342
0
      axis_triple_distances = *triple_dists;
4343
0
4344
0
    float normalized_min = renormalizeValue ((double) filterRangeMinValue.to_float (), axis_limit, axis_triple_distances, false);
4345
0
    float normalized_max = renormalizeValue ((double) filterRangeMaxValue.to_float (), axis_limit, axis_triple_distances, false);
4346
0
    out->filterRangeMinValue.set_float (normalized_min);
4347
0
    out->filterRangeMaxValue.set_float (normalized_max);
4348
0
4349
0
    return_trace (c->serializer->check_assign (out->axisIndex, index_map->get (axisIndex),
4350
0
                                               HB_SERIALIZE_ERROR_INT_OVERFLOW));
4351
0
  }
4352
4353
  private:
4354
  Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
4355
                                             hb_map_t *condition_map /* OUT */) const
4356
0
  {
4357
0
    //invalid axis index, drop the entire record
4358
0
    if (!c->axes_index_tag_map->has (axisIndex))
4359
0
      return DROP_RECORD_WITH_VAR;
4360
0
4361
0
    hb_tag_t axis_tag = c->axes_index_tag_map->get (axisIndex);
4362
0
4363
0
    Triple axis_range (-1.0, 0.0, 1.0);
4364
0
    Triple *axis_limit;
4365
0
    bool axis_set_by_user = false;
4366
0
    if (c->axes_location->has (axis_tag, &axis_limit))
4367
0
    {
4368
0
      axis_range = *axis_limit;
4369
0
      axis_set_by_user = true;
4370
0
    }
4371
0
4372
0
    float axis_min_val = axis_range.minimum;
4373
0
    float axis_default_val = axis_range.middle;
4374
0
    float axis_max_val = axis_range.maximum;
4375
0
4376
0
    float filter_min_val = filterRangeMinValue.to_float ();
4377
0
    float filter_max_val = filterRangeMaxValue.to_float ();
4378
0
4379
0
    if (axis_default_val < filter_min_val ||
4380
0
        axis_default_val > filter_max_val)
4381
0
      c->apply = false;
4382
0
4383
0
    //condition not met, drop the entire record
4384
0
    if (axis_min_val > filter_max_val || axis_max_val < filter_min_val ||
4385
0
        filter_min_val > filter_max_val)
4386
0
      return DROP_RECORD_WITH_VAR;
4387
0
4388
0
    //condition met and axis pinned, drop the condition
4389
0
    if (axis_set_by_user && axis_range.is_point ())
4390
0
      return DROP_COND_WITH_VAR;
4391
0
4392
0
    if (filter_max_val != axis_max_val || filter_min_val != axis_min_val)
4393
0
    {
4394
0
      // add axisIndex->value into the hashmap so we can check if the record is
4395
0
      // unique with variations
4396
0
      uint16_t int_filter_max_val = (uint16_t) filterRangeMaxValue.to_int ();
4397
0
      uint16_t int_filter_min_val = (uint16_t) filterRangeMinValue.to_int ();
4398
0
      hb_codepoint_t val = (int_filter_max_val << 16) + int_filter_min_val;
4399
0
4400
0
      condition_map->set (axisIndex, val);
4401
0
      return KEEP_COND_WITH_VAR;
4402
0
    }
4403
0
    return KEEP_RECORD_WITH_VAR;
4404
0
  }
4405
4406
  template <typename Instancer>
4407
  bool evaluate (const int *coords, unsigned int coord_len,
4408
     Instancer *instancer HB_UNUSED) const
4409
0
  {
4410
0
    int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
4411
0
    return filterRangeMinValue.to_int () <= coord && coord <= filterRangeMaxValue.to_int ();
4412
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
4413
4414
  public:
4415
  bool sanitize (hb_sanitize_context_t *c) const
4416
0
  {
4417
0
    TRACE_SANITIZE (this);
4418
0
    return_trace (c->check_struct (this));
4419
0
  }
4420
4421
  protected:
4422
  HBUINT16  format;   /* Format identifier--format = 1 */
4423
  HBUINT16  axisIndex;
4424
  F2DOT14 filterRangeMinValue;
4425
  F2DOT14 filterRangeMaxValue;
4426
  public:
4427
  DEFINE_SIZE_STATIC (8);
4428
};
4429
4430
struct ConditionValue
4431
{
4432
  friend struct Condition;
4433
4434
  bool subset (hb_subset_context_t *c) const
4435
0
  {
4436
0
    TRACE_SUBSET (this);
4437
0
    auto *out = c->serializer->embed (this);
4438
0
    if (unlikely (!out)) return_trace (false);
4439
0
4440
0
    if (varIdx == VarIdx::NO_VARIATION)
4441
0
      return_trace (true);
4442
0
4443
0
    hb_pair_t<unsigned, int> *condition_value;
4444
0
    if (c->plan->layout_condition_idx_value_map.has ((uintptr_t) this, &condition_value))
4445
0
    {
4446
0
      out->defaultValue = condition_value->second;
4447
0
      out->varIdx = condition_value->first;
4448
0
      return_trace (true);
4449
0
    }
4450
0
4451
0
    hb_pair_t<unsigned, int> *new_varidx_delta;
4452
0
    if (!c->plan->layout_variation_idx_delta_map.has (varIdx, &new_varidx_delta))
4453
0
      return_trace (false);
4454
0
4455
0
    if (unlikely (!c->serializer->check_assign (
4456
0
    out->defaultValue,
4457
0
    defaultValue + hb_second (*new_varidx_delta),
4458
0
    HB_SERIALIZE_ERROR_INT_OVERFLOW)))
4459
0
      return_trace (false);
4460
0
    out->varIdx = hb_first (*new_varidx_delta);
4461
0
    return_trace (true);
4462
0
  }
4463
4464
  private:
4465
  template <typename Instancer>
4466
  bool evaluate (const int *coords, unsigned int coord_len,
4467
     Instancer *instancer) const
4468
0
  {
4469
0
    double value = defaultValue;
4470
0
    value += instancer->get_condition_delta (varIdx);
4471
0
    return value > 0;
4472
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
4473
4474
  public:
4475
  bool sanitize (hb_sanitize_context_t *c) const
4476
0
  {
4477
0
    TRACE_SANITIZE (this);
4478
0
    return_trace (c->check_struct (this));
4479
0
  }
4480
4481
  protected:
4482
  HBUINT16  format;   /* Format identifier--format = 2 */
4483
  HBINT16 defaultValue;   /* Value at default instance. */
4484
  VarIdx  varIdx;   /* Variation index */
4485
  public:
4486
  DEFINE_SIZE_STATIC (8);
4487
};
4488
4489
struct ConditionAnd
4490
{
4491
  friend struct Condition;
4492
4493
  bool subset (hb_subset_context_t *c) const
4494
0
  {
4495
0
    TRACE_SUBSET (this);
4496
0
    auto *out = c->serializer->start_embed (this);
4497
0
    if (unlikely (!out || !c->serializer->extend_min (out)))
4498
0
      return_trace (false);
4499
0
    out->format = format;
4500
0
4501
0
    for (const auto &offset : conditions)
4502
0
    {
4503
0
      if (offset.is_null ())
4504
0
      {
4505
0
  auto *out_offset = out->conditions.serialize_append (c->serializer);
4506
0
  if (unlikely (!out_offset)) return_trace (false);
4507
0
  *out_offset = 0;
4508
0
      }
4509
0
      else if (unlikely (!subset_offset_array (c, out->conditions, this) (offset)))
4510
0
  return_trace (false);
4511
0
    }
4512
0
4513
0
    return_trace (true);
4514
0
  }
4515
4516
  private:
4517
  template <typename Instancer>
4518
  bool evaluate (const int *coords, unsigned int coord_len,
4519
     Instancer *instancer) const
4520
0
  {
4521
0
    unsigned int count = conditions.len;
4522
0
    for (unsigned int i = 0; i < count; i++)
4523
0
      if (!_hb_recurse_condition_evaluate (this+conditions.arrayZ[i],
4524
0
             coords, coord_len,
4525
0
             instancer))
4526
0
  return false;
4527
0
    return true;
4528
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
4529
4530
  public:
4531
  bool sanitize (hb_sanitize_context_t *c) const
4532
0
  {
4533
0
    TRACE_SANITIZE (this);
4534
0
    return_trace (conditions.sanitize (c, this));
4535
0
  }
4536
4537
  protected:
4538
  HBUINT16  format;   /* Format identifier--format = 3 */
4539
  Array8OfOffset24To<struct Condition>  conditions;
4540
  public:
4541
  DEFINE_SIZE_ARRAY (3, conditions);
4542
};
4543
4544
struct ConditionOr
4545
{
4546
  friend struct Condition;
4547
4548
  bool subset (hb_subset_context_t *c) const
4549
0
  {
4550
0
    TRACE_SUBSET (this);
4551
0
    auto *out = c->serializer->start_embed (this);
4552
0
    if (unlikely (!out || !c->serializer->extend_min (out)))
4553
0
      return_trace (false);
4554
0
    out->format = format;
4555
0
4556
0
    for (const auto &offset : conditions)
4557
0
    {
4558
0
      if (offset.is_null ())
4559
0
      {
4560
0
  auto *out_offset = out->conditions.serialize_append (c->serializer);
4561
0
  if (unlikely (!out_offset)) return_trace (false);
4562
0
  *out_offset = 0;
4563
0
      }
4564
0
      else if (unlikely (!subset_offset_array (c, out->conditions, this) (offset)))
4565
0
  return_trace (false);
4566
0
    }
4567
0
4568
0
    return_trace (true);
4569
0
  }
4570
4571
  private:
4572
  template <typename Instancer>
4573
  bool evaluate (const int *coords, unsigned int coord_len,
4574
     Instancer *instancer) const
4575
0
  {
4576
0
    unsigned int count = conditions.len;
4577
0
    for (unsigned int i = 0; i < count; i++)
4578
0
      if (_hb_recurse_condition_evaluate (this+conditions.arrayZ[i],
4579
0
            coords, coord_len,
4580
0
            instancer))
4581
0
  return true;
4582
0
    return false;
4583
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
4584
4585
  public:
4586
  bool sanitize (hb_sanitize_context_t *c) const
4587
0
  {
4588
0
    TRACE_SANITIZE (this);
4589
0
    return_trace (conditions.sanitize (c, this));
4590
0
  }
4591
4592
  protected:
4593
  HBUINT16  format;   /* Format identifier--format = 4 */
4594
  Array8OfOffset24To<struct Condition>  conditions;
4595
  public:
4596
  DEFINE_SIZE_ARRAY (3, conditions);
4597
};
4598
4599
struct ConditionNegate
4600
{
4601
  friend struct Condition;
4602
4603
  bool subset (hb_subset_context_t *c) const
4604
0
  {
4605
0
    TRACE_SUBSET (this);
4606
0
    auto *out = c->serializer->embed (this);
4607
0
    if (unlikely (!out)) return_trace (false);
4608
0
    if (condition.is_null ())
4609
0
    {
4610
0
      out->condition = 0;
4611
0
      return_trace (true);
4612
0
    }
4613
0
    return_trace (out->condition.serialize_subset (c, condition, this));
4614
0
  }
4615
4616
  private:
4617
  template <typename Instancer>
4618
  bool evaluate (const int *coords, unsigned int coord_len,
4619
     Instancer *instancer) const
4620
0
  {
4621
0
    return !_hb_recurse_condition_evaluate (this+condition,
4622
0
              coords, coord_len,
4623
0
              instancer);
4624
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
4625
4626
  public:
4627
  bool sanitize (hb_sanitize_context_t *c) const
4628
0
  {
4629
0
    TRACE_SANITIZE (this);
4630
0
    return_trace (condition.sanitize (c, this));
4631
0
  }
4632
4633
  protected:
4634
  HBUINT16  format;   /* Format identifier--format = 5 */
4635
  Offset24To<struct Condition>  condition;
4636
  public:
4637
  DEFINE_SIZE_STATIC (5);
4638
};
4639
4640
struct Condition
4641
{
4642
  friend struct ConditionSet;
4643
4644
  static bool serialize_constant (hb_serialize_context_t *c, bool value)
4645
0
  {
4646
0
    auto *out = c->start_embed<ConditionValue> ();
4647
0
    if (unlikely (!out || !c->extend_min (out))) return false;
4648
0
    out->format = 2;
4649
0
    out->defaultValue = value ? 1 : 0;
4650
0
    out->varIdx = VarIdx::NO_VARIATION;
4651
0
    return true;
4652
0
  }
4653
4654
  lookup_condition_subset_result_t subset_lookup_condition (
4655
              hb_subset_context_t *c,
4656
              unsigned depth = HB_MAX_NESTING_LEVEL,
4657
              bool materialize_true = false) const;
4658
4659
  template <typename Instancer>
4660
  bool evaluate (const int *coords, unsigned int coord_len,
4661
     Instancer *instancer) const
4662
0
  {
4663
0
    switch (u.format.v) {
4664
    /* A null condition offset resolves to the nil Condition, whose reserved
4665
     * format 0 represents the True condition required by the specification. */
4666
0
    case 0: return true;
4667
0
    case 1: hb_barrier (); return u.format1.evaluate (coords, coord_len, instancer);
4668
0
    case 2: hb_barrier (); return u.format2.evaluate (coords, coord_len, instancer);
4669
0
    case 3: hb_barrier (); return u.format3.evaluate (coords, coord_len, instancer);
4670
0
    case 4: hb_barrier (); return u.format4.evaluate (coords, coord_len, instancer);
4671
0
    case 5: hb_barrier (); return u.format5.evaluate (coords, coord_len, instancer);
4672
0
    default:return false;
4673
0
    }
4674
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
4675
4676
  Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
4677
                                             hb_map_t *condition_map /* OUT */,
4678
                                             unsigned depth = HB_MAX_NESTING_LEVEL) const
4679
0
  {
4680
0
    if (unlikely (!depth))
4681
0
    {
4682
0
      c->apply = false;
4683
0
      return DROP_RECORD_WITH_VAR;
4684
0
    }
4685
0
4686
0
    switch (u.format.v) {
4687
0
    case 0: return KEEP_RECORD_WITH_VAR;
4688
0
    case 1: hb_barrier (); return u.format1.keep_with_variations (c, condition_map);
4689
0
    case 2: case 3: case 4: case 5: break;
4690
0
    default: c->apply = false; return DROP_RECORD_WITH_VAR;
4691
0
    }
4692
0
4693
0
    hb_barrier ();
4694
0
    bool applies = evaluate (c->instancer->coords.arrayZ,
4695
0
           c->instancer->coords.length, c->instancer);
4696
0
    c->apply &= applies;
4697
0
    if (c->all_axes_pinned)
4698
0
      return applies ? DROP_COND_WITH_VAR : DROP_RECORD_WITH_VAR;
4699
0
4700
0
    if (u.format.v == 2)
4701
0
      return u.format2.varIdx == VarIdx::NO_VARIATION ||
4702
0
             !c->instancer->varStore->has_delta_set (u.format2.varIdx) ?
4703
0
             (applies ? KEEP_RECORD_WITH_VAR : DROP_RECORD_WITH_VAR) :
4704
0
             KEEP_COND_WITH_VAR;
4705
0
4706
0
    auto classify_child = [c, condition_map, depth] (const Condition &child)
4707
0
    {
4708
0
      auto child_context = *c;
4709
0
      child_context.apply = true;
4710
0
      return child.keep_with_variations (&child_context, condition_map, depth - 1);
4711
0
    };
4712
0
4713
0
    if (u.format.v == 5)
4714
0
    {
4715
0
      auto result = classify_child (&u.format5 + u.format5.condition);
4716
0
      return result == DROP_RECORD_WITH_VAR ? KEEP_RECORD_WITH_VAR :
4717
0
             result == KEEP_COND_WITH_VAR ? KEEP_COND_WITH_VAR :
4718
0
             DROP_RECORD_WITH_VAR;
4719
0
    }
4720
0
4721
0
    bool is_and = u.format.v == 3;
4722
0
    bool variable = false;
4723
0
    const auto &conditions = is_and ? u.format3.conditions : u.format4.conditions;
4724
0
    const void *base = is_and ? (const void *) &u.format3 : (const void *) &u.format4;
4725
0
    for (const auto &offset : conditions)
4726
0
    {
4727
0
      auto result = classify_child (base + offset);
4728
0
      if (is_and && result == DROP_RECORD_WITH_VAR)
4729
0
        return DROP_RECORD_WITH_VAR;
4730
0
      if (!is_and && (result == DROP_COND_WITH_VAR || result == KEEP_RECORD_WITH_VAR))
4731
0
        return KEEP_RECORD_WITH_VAR;
4732
0
      variable |= result == KEEP_COND_WITH_VAR;
4733
0
    }
4734
0
    return variable ? KEEP_COND_WITH_VAR :
4735
0
           is_and ? KEEP_RECORD_WITH_VAR : DROP_RECORD_WITH_VAR;
4736
0
  }
4737
4738
  template <typename context_t, typename ...Ts>
4739
  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
4740
0
  {
4741
0
    if (unlikely (!c->may_dispatch (this, &u.format.v))) return c->no_dispatch_return_value ();
4742
0
    TRACE_DISPATCH (this, u.format.v);
4743
0
    switch (u.format.v) {
4744
0
    case 1: hb_barrier (); return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
4745
0
    case 2: hb_barrier (); return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
4746
0
    case 3: hb_barrier (); return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
4747
0
    case 4: hb_barrier (); return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
4748
0
    case 5: hb_barrier (); return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
4749
0
    default:return_trace (c->default_return_value ());
4750
0
    }
4751
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
4752
4753
  bool sanitize (hb_sanitize_context_t *c) const
4754
0
  {
4755
0
    TRACE_SANITIZE (this);
4756
4757
0
    if (unlikely (!c->check_start_recursion (HB_MAX_NESTING_LEVEL)))
4758
0
      return_trace (c->no_dispatch_return_value ());
4759
4760
0
    return_trace (c->end_recursion (this->dispatch (c)));
4761
0
  }
4762
4763
  bool collect_var_indices (hb_set_t *var_indices,
4764
          unsigned depth = HB_MAX_NESTING_LEVEL,
4765
                            hb_hashmap_t<uintptr_t, hb_pair_t<unsigned, int>> *condition_values = nullptr) const;
4766
4767
  bool serialize (hb_serialize_context_t *c,
4768
      const Condition *src,
4769
      const hb_map_t &varidx_map,
4770
      const hb_map_t *axis_map = nullptr);
4771
4772
  private:
4773
  lookup_condition_subset_result_t subset_lookup_condition_impl (
4774
              hb_subset_context_t *c,
4775
              unsigned depth) const;
4776
4777
  protected:
4778
  union {
4779
  struct { HBUINT16 v; }  format;   /* Format identifier */
4780
  ConditionAxisRange  format1;
4781
  ConditionValue  format2;
4782
  ConditionAnd    format3;
4783
  ConditionOr   format4;
4784
  ConditionNegate format5;
4785
  } u;
4786
  public:
4787
  DEFINE_SIZE_UNION (2, format.v);
4788
};
4789
4790
template <typename Instancer>
4791
bool
4792
_hb_recurse_condition_evaluate (const struct Condition &condition,
4793
        const int *coords,
4794
        unsigned int coord_len,
4795
        Instancer *instancer)
4796
0
{
4797
0
  return condition.evaluate (coords, coord_len, instancer);
4798
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*)
4799
4800
struct ConditionList
4801
{
4802
  const Condition& operator[] (unsigned i) const
4803
0
  { return this+conditions[i]; }
4804
4805
0
  unsigned get_count () const { return conditions.len; }
4806
4807
  bool serialize (hb_serialize_context_t *c,
4808
      const ConditionList *src,
4809
      const hb_inc_bimap_t &condition_map,
4810
      const hb_map_t &varidx_map,
4811
      const hb_map_t *axis_map)
4812
0
  {
4813
0
    TRACE_SERIALIZE (this);
4814
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
4815
0
    conditions.len = condition_map.get_population ();
4816
0
    if (unlikely (!c->extend (conditions))) return_trace (false);
4817
0
    for (unsigned i = 0; i < conditions.len; i++)
4818
0
    {
4819
0
      unsigned old_index = condition_map.backward (i);
4820
0
      if (unlikely (old_index >= src->conditions.len ||
4821
0
        !conditions[i].serialize_serialize (
4822
0
      c, &(src+src->conditions[old_index]), varidx_map, axis_map)))
4823
0
  return_trace (false);
4824
0
    }
4825
0
    return_trace (true);
4826
0
  }
4827
4828
  bool sanitize (hb_sanitize_context_t *c) const
4829
0
  {
4830
0
    TRACE_SANITIZE (this);
4831
0
    return_trace (conditions.sanitize (c, this));
4832
0
  }
4833
4834
  protected:
4835
  Array32OfOffset32To<Condition> conditions;
4836
  public:
4837
  DEFINE_SIZE_ARRAY (4, conditions);
4838
};
4839
4840
inline bool
4841
Condition::collect_var_indices (hb_set_t *var_indices, unsigned depth,
4842
                               hb_hashmap_t<uintptr_t, hb_pair_t<unsigned, int>> *condition_values) const
4843
0
{
4844
0
  if (unlikely (!depth)) return false;
4845
0
  switch (u.format.v)
4846
0
  {
4847
0
    case 0:
4848
0
    case 1:
4849
0
      return true;
4850
0
    case 2:
4851
0
      if (u.format2.varIdx != VarIdx::NO_VARIATION)
4852
0
      {
4853
0
        var_indices->add (u.format2.varIdx);
4854
0
        if (condition_values &&
4855
0
            !condition_values->set ((uintptr_t) &u.format2,
4856
0
                                    hb_pair (unsigned (u.format2.varIdx), int (u.format2.defaultValue))))
4857
0
          return false;
4858
0
      }
4859
0
      return !var_indices->in_error ();
4860
0
    case 3:
4861
0
      for (const auto &offset : u.format3.conditions)
4862
0
  if (unlikely (!(&u.format3+offset).collect_var_indices (var_indices,
4863
0
                   depth - 1, condition_values)))
4864
0
    return false;
4865
0
      return true;
4866
0
    case 4:
4867
0
      for (const auto &offset : u.format4.conditions)
4868
0
  if (unlikely (!(&u.format4+offset).collect_var_indices (var_indices,
4869
0
                   depth - 1, condition_values)))
4870
0
    return false;
4871
0
      return true;
4872
0
    case 5:
4873
0
      return (&u.format5+u.format5.condition).collect_var_indices (var_indices,
4874
0
                  depth - 1, condition_values);
4875
0
    default:
4876
0
      return false;
4877
0
  }
4878
0
}
4879
4880
inline bool
4881
Condition::serialize (hb_serialize_context_t *c,
4882
          const Condition *src,
4883
          const hb_map_t &varidx_map,
4884
          const hb_map_t *axis_map)
4885
0
{
4886
0
  TRACE_SERIALIZE (this);
4887
0
  switch (src->u.format.v)
4888
0
  {
4889
0
    case 0:
4890
0
    {
4891
0
      auto *out = c->start_embed<ConditionValue> ();
4892
0
      if (unlikely (!out || !c->extend_min (out))) return_trace (false);
4893
0
      out->format = 2;
4894
0
      out->defaultValue = 1;
4895
0
      out->varIdx = VarIdx::NO_VARIATION;
4896
0
      return_trace (true);
4897
0
    }
4898
0
    case 1:
4899
0
    {
4900
0
      auto *out = c->embed (&src->u.format1);
4901
0
      if (unlikely (!out)) return_trace (false);
4902
0
      if (axis_map)
4903
0
      {
4904
0
  if (unlikely (!axis_map->has (out->axisIndex)))
4905
0
  {
4906
0
    c->err (HB_SERIALIZE_ERROR_OTHER);
4907
0
    return_trace (false);
4908
0
  }
4909
0
  if (unlikely (!c->check_assign (out->axisIndex, axis_map->get (out->axisIndex),
4910
0
              HB_SERIALIZE_ERROR_INT_OVERFLOW)))
4911
0
    return_trace (false);
4912
0
      }
4913
0
      return_trace (true);
4914
0
    }
4915
0
    case 2:
4916
0
    {
4917
0
      auto *out = c->embed (&src->u.format2);
4918
0
      if (unlikely (!out ||
4919
0
        (src->u.format2.varIdx != VarIdx::NO_VARIATION &&
4920
0
         !varidx_map.has (src->u.format2.varIdx))))
4921
0
  return_trace (false);
4922
0
      out->varIdx = src->u.format2.varIdx == VarIdx::NO_VARIATION ?
4923
0
        src->u.format2.varIdx : varidx_map.get (src->u.format2.varIdx);
4924
0
      return_trace (true);
4925
0
    }
4926
0
    case 3:
4927
0
    {
4928
0
      auto *out = c->start_embed<ConditionAnd> ();
4929
0
      if (unlikely (!c->extend_min (out))) return_trace (false);
4930
0
      out->format = 3;
4931
0
      out->conditions.len = src->u.format3.conditions.len;
4932
0
      if (unlikely (!c->extend (out->conditions))) return_trace (false);
4933
0
      for (unsigned i = 0; i < out->conditions.len; i++)
4934
0
  if (unlikely (!out->conditions[i].serialize_serialize (
4935
0
      c, &(&src->u.format3+src->u.format3.conditions[i]),
4936
0
      varidx_map, axis_map)))
4937
0
    return_trace (false);
4938
0
      return_trace (true);
4939
0
    }
4940
0
    case 4:
4941
0
    {
4942
0
      auto *out = c->start_embed<ConditionOr> ();
4943
0
      if (unlikely (!c->extend_min (out))) return_trace (false);
4944
0
      out->format = 4;
4945
0
      out->conditions.len = src->u.format4.conditions.len;
4946
0
      if (unlikely (!c->extend (out->conditions))) return_trace (false);
4947
0
      for (unsigned i = 0; i < out->conditions.len; i++)
4948
0
  if (unlikely (!out->conditions[i].serialize_serialize (
4949
0
      c, &(&src->u.format4+src->u.format4.conditions[i]),
4950
0
      varidx_map, axis_map)))
4951
0
    return_trace (false);
4952
0
      return_trace (true);
4953
0
    }
4954
0
    case 5:
4955
0
    {
4956
0
      auto *out = c->embed (&src->u.format5);
4957
0
      if (unlikely (!out ||
4958
0
        !out->condition.serialize_serialize (
4959
0
      c, &(&src->u.format5+src->u.format5.condition),
4960
0
      varidx_map, axis_map)))
4961
0
  return_trace (false);
4962
0
      return_trace (true);
4963
0
    }
4964
0
    default:
4965
0
      return_trace (false);
4966
0
  }
4967
0
}
4968
4969
inline lookup_condition_subset_result_t
4970
Condition::subset_lookup_condition (hb_subset_context_t *c,
4971
            unsigned depth,
4972
            bool materialize_true) const
4973
0
{
4974
0
  auto snap = c->serializer->snapshot ();
4975
0
  lookup_condition_subset_result_t result =
4976
0
      subset_lookup_condition_impl (c, depth);
4977
0
  if (result == LOOKUP_CONDITION_SUBSET_KEEP)
4978
0
    return result;
4979
0
4980
0
  c->serializer->revert (snap);
4981
0
  if (result != LOOKUP_CONDITION_SUBSET_TRUE || !materialize_true)
4982
0
    return result;
4983
0
4984
0
  return serialize_constant (c->serializer, true) ?
4985
0
         LOOKUP_CONDITION_SUBSET_KEEP : LOOKUP_CONDITION_SUBSET_ERROR;
4986
0
}
4987
4988
inline lookup_condition_subset_result_t
4989
Condition::subset_lookup_condition_impl (hb_subset_context_t *c,
4990
           unsigned depth) const
4991
0
{
4992
0
  if (unlikely (!depth))
4993
0
    return LOOKUP_CONDITION_SUBSET_ERROR;
4994
0
4995
0
  auto subset_offset = [c, depth] (Array8OfOffset24To<Condition> &out,
4996
0
           const Condition &condition)
4997
0
      -> lookup_condition_subset_result_t
4998
0
  {
4999
0
    auto snap = c->serializer->snapshot ();
5000
0
    auto *offset = out.serialize_append (c->serializer);
5001
0
    if (unlikely (!offset))
5002
0
      return LOOKUP_CONDITION_SUBSET_ERROR;
5003
0
5004
0
    c->serializer->push ();
5005
0
    lookup_condition_subset_result_t result =
5006
0
        condition.subset_lookup_condition (c, depth - 1);
5007
0
    if (result == LOOKUP_CONDITION_SUBSET_KEEP)
5008
0
      c->serializer->add_link (*offset, c->serializer->pop_pack ());
5009
0
    else
5010
0
    {
5011
0
      c->serializer->pop_discard ();
5012
0
      out.pop ();
5013
0
      c->serializer->revert (snap);
5014
0
    }
5015
0
    return result;
5016
0
  };
5017
0
5018
0
  switch (u.format.v)
5019
0
  {
5020
0
    case 0:
5021
0
      return LOOKUP_CONDITION_SUBSET_TRUE;
5022
0
5023
0
    case 1:
5024
0
    {
5025
0
      const ConditionAxisRange &src = u.format1;
5026
0
      if (c->plan->user_axes_location.is_empty ())
5027
0
        return c->serializer->embed (&src) ?
5028
0
               LOOKUP_CONDITION_SUBSET_KEEP :
5029
0
               LOOKUP_CONDITION_SUBSET_ERROR;
5030
0
5031
0
      hb_codepoint_t *axis_tag;
5032
0
      if (!c->plan->axes_old_index_tag_map.has (src.axisIndex, &axis_tag))
5033
0
        return LOOKUP_CONDITION_SUBSET_ERROR;
5034
0
5035
0
      Triple axis_limit {-1.0, 0.0, 1.0};
5036
0
      Triple *normalized_limit;
5037
0
      if (c->plan->axes_location.has (*axis_tag, &normalized_limit))
5038
0
        axis_limit = *normalized_limit;
5039
0
5040
0
      double filter_min = (double) src.filterRangeMinValue.to_float ();
5041
0
      double filter_max = (double) src.filterRangeMaxValue.to_float ();
5042
0
      if (filter_min > filter_max)
5043
0
        return LOOKUP_CONDITION_SUBSET_FALSE;
5044
0
      if (axis_limit.is_point ())
5045
0
        return filter_min <= axis_limit.middle &&
5046
0
         axis_limit.middle <= filter_max ?
5047
0
         LOOKUP_CONDITION_SUBSET_TRUE :
5048
0
         LOOKUP_CONDITION_SUBSET_FALSE;
5049
0
      if (axis_limit.maximum < filter_min ||
5050
0
    filter_max < axis_limit.minimum)
5051
0
        return LOOKUP_CONDITION_SUBSET_FALSE;
5052
0
      if (filter_min <= axis_limit.minimum &&
5053
0
    axis_limit.maximum <= filter_max)
5054
0
        return LOOKUP_CONDITION_SUBSET_TRUE;
5055
0
      if (!c->plan->axes_index_map.has (src.axisIndex))
5056
0
        return LOOKUP_CONDITION_SUBSET_ERROR;
5057
0
5058
0
      auto *out = c->serializer->embed (&src);
5059
0
      if (unlikely (!out))
5060
0
        return LOOKUP_CONDITION_SUBSET_ERROR;
5061
0
5062
0
      TripleDistances axis_distances {1.0, 1.0};
5063
0
      TripleDistances *distances;
5064
0
      if (c->plan->axes_triple_distances.has (*axis_tag, &distances))
5065
0
        axis_distances = *distances;
5066
0
5067
0
      out->filterRangeMinValue.set_float (
5068
0
    renormalizeValue (filter_min, axis_limit, axis_distances, false));
5069
0
      out->filterRangeMaxValue.set_float (
5070
0
    renormalizeValue (filter_max, axis_limit, axis_distances, false));
5071
0
      if (unlikely (!c->serializer->check_assign (
5072
0
    out->axisIndex,
5073
0
    c->plan->axes_index_map.get (src.axisIndex),
5074
0
    HB_SERIALIZE_ERROR_INT_OVERFLOW)))
5075
0
        return LOOKUP_CONDITION_SUBSET_ERROR;
5076
0
      return LOOKUP_CONDITION_SUBSET_KEEP;
5077
0
    }
5078
0
5079
0
    case 2:
5080
0
    {
5081
0
      const ConditionValue &src = u.format2;
5082
0
      auto *out = c->serializer->embed (&src);
5083
0
      if (unlikely (!out))
5084
0
        return LOOKUP_CONDITION_SUBSET_ERROR;
5085
0
5086
0
      if (src.varIdx == VarIdx::NO_VARIATION)
5087
0
        return c->plan->user_axes_location.is_empty () ?
5088
0
               LOOKUP_CONDITION_SUBSET_KEEP :
5089
0
               ((int) src.defaultValue > 0 ?
5090
0
    LOOKUP_CONDITION_SUBSET_TRUE :
5091
0
    LOOKUP_CONDITION_SUBSET_FALSE);
5092
0
5093
0
      hb_pair_t<unsigned, int> *condition_value;
5094
0
      if (c->plan->layout_condition_idx_value_map.has ((uintptr_t) &src, &condition_value))
5095
0
      {
5096
0
        out->defaultValue = condition_value->second;
5097
0
        out->varIdx = condition_value->first;
5098
0
        if (out->varIdx == VarIdx::NO_VARIATION)
5099
0
          return out->defaultValue > 0 ? LOOKUP_CONDITION_SUBSET_TRUE :
5100
0
                                        LOOKUP_CONDITION_SUBSET_FALSE;
5101
0
        return LOOKUP_CONDITION_SUBSET_KEEP;
5102
0
      }
5103
0
5104
0
      hb_pair_t<unsigned, int> *new_varidx_delta;
5105
0
      if (!c->plan->layout_variation_idx_delta_map.has (src.varIdx,
5106
0
              &new_varidx_delta))
5107
0
        return c->plan->user_axes_location.is_empty () ?
5108
0
               LOOKUP_CONDITION_SUBSET_KEEP :
5109
0
               ((int) src.defaultValue > 0 ?
5110
0
    LOOKUP_CONDITION_SUBSET_TRUE :
5111
0
    LOOKUP_CONDITION_SUBSET_FALSE);
5112
0
5113
0
      if (!c->plan->user_axes_location.is_empty () &&
5114
0
          hb_first (*new_varidx_delta) == VarIdx::NO_VARIATION)
5115
0
      {
5116
0
        // Conditions becoming constant depend on the unrounded sign, not
5117
0
        // the integer delta used to instance positioning values.
5118
0
        double value = (int) src.defaultValue +
5119
0
                      c->plan->layout_variation_delta (src.varIdx);
5120
0
        return value > 0 ? LOOKUP_CONDITION_SUBSET_TRUE :
5121
0
                          LOOKUP_CONDITION_SUBSET_FALSE;
5122
0
      }
5123
0
5124
0
      int default_value = (int) src.defaultValue +
5125
0
        hb_second (*new_varidx_delta);
5126
0
      if (unlikely (!c->serializer->check_assign (
5127
0
    out->defaultValue,
5128
0
    default_value,
5129
0
    HB_SERIALIZE_ERROR_INT_OVERFLOW)))
5130
0
        return LOOKUP_CONDITION_SUBSET_ERROR;
5131
0
      out->varIdx = hb_first (*new_varidx_delta);
5132
0
5133
0
      return LOOKUP_CONDITION_SUBSET_KEEP;
5134
0
    }
5135
0
5136
0
    case 3:
5137
0
    {
5138
0
      const ConditionAnd &src = u.format3;
5139
0
      auto *out = c->serializer->start_embed (&src);
5140
0
      if (unlikely (!out || !c->serializer->extend_min (out)))
5141
0
        return LOOKUP_CONDITION_SUBSET_ERROR;
5142
0
      out->format = 3;
5143
0
5144
0
      for (const auto &offset : src.conditions)
5145
0
      {
5146
0
        lookup_condition_subset_result_t result =
5147
0
            subset_offset (out->conditions, &src + offset);
5148
0
        if (result == LOOKUP_CONDITION_SUBSET_ERROR ||
5149
0
      result == LOOKUP_CONDITION_SUBSET_FALSE)
5150
0
          return result;
5151
0
      }
5152
0
      return out->conditions ?
5153
0
       LOOKUP_CONDITION_SUBSET_KEEP :
5154
0
       LOOKUP_CONDITION_SUBSET_TRUE;
5155
0
    }
5156
0
5157
0
    case 4:
5158
0
    {
5159
0
      const ConditionOr &src = u.format4;
5160
0
      auto *out = c->serializer->start_embed (&src);
5161
0
      if (unlikely (!out || !c->serializer->extend_min (out)))
5162
0
        return LOOKUP_CONDITION_SUBSET_ERROR;
5163
0
      out->format = 4;
5164
0
5165
0
      for (const auto &offset : src.conditions)
5166
0
      {
5167
0
        lookup_condition_subset_result_t result =
5168
0
            subset_offset (out->conditions, &src + offset);
5169
0
        if (result == LOOKUP_CONDITION_SUBSET_ERROR ||
5170
0
      result == LOOKUP_CONDITION_SUBSET_TRUE)
5171
0
          return result;
5172
0
      }
5173
0
      return out->conditions ?
5174
0
       LOOKUP_CONDITION_SUBSET_KEEP :
5175
0
       LOOKUP_CONDITION_SUBSET_FALSE;
5176
0
    }
5177
0
5178
0
    case 5:
5179
0
    {
5180
0
      const ConditionNegate &src = u.format5;
5181
0
      auto *out = c->serializer->embed (&src);
5182
0
      if (unlikely (!out))
5183
0
        return LOOKUP_CONDITION_SUBSET_ERROR;
5184
0
      out->condition = 0;
5185
0
5186
0
      c->serializer->push ();
5187
0
      lookup_condition_subset_result_t result =
5188
0
          (&src + src.condition).subset_lookup_condition (c, depth - 1);
5189
0
      if (result == LOOKUP_CONDITION_SUBSET_KEEP)
5190
0
      {
5191
0
        c->serializer->add_link (out->condition,
5192
0
         c->serializer->pop_pack ());
5193
0
        return result;
5194
0
      }
5195
0
5196
0
      c->serializer->pop_discard ();
5197
0
      if (result == LOOKUP_CONDITION_SUBSET_TRUE)
5198
0
        return LOOKUP_CONDITION_SUBSET_FALSE;
5199
0
      if (result == LOOKUP_CONDITION_SUBSET_FALSE)
5200
0
        return LOOKUP_CONDITION_SUBSET_TRUE;
5201
0
      return result;
5202
0
    }
5203
0
5204
0
    default:
5205
0
      return LOOKUP_CONDITION_SUBSET_FALSE;
5206
0
  }
5207
0
}
5208
5209
struct ConditionSet
5210
{
5211
  bool evaluate (const int *coords, unsigned int coord_len,
5212
     ItemVarStoreInstancer *instancer) const
5213
0
  {
5214
0
    unsigned int count = conditions.len;
5215
0
    for (unsigned int i = 0; i < count; i++)
5216
0
      if (!(this+conditions.arrayZ[i]).evaluate (coords, coord_len, instancer))
5217
0
  return false;
5218
0
    return true;
5219
0
  }
5220
5221
  void keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
5222
0
  {
5223
0
    hb_map_t *condition_map = hb_map_create ();
5224
0
    if (unlikely (!condition_map)) return;
5225
0
    hb::shared_ptr<hb_map_t> p {condition_map};
5226
0
5227
0
    hb_set_t *cond_set = hb_set_create ();
5228
0
    if (unlikely (!cond_set)) return;
5229
0
    hb::shared_ptr<hb_set_t> s {cond_set};
5230
0
5231
0
    c->apply = true;
5232
0
    bool should_keep = false;
5233
0
    /* The range map cannot identify value or boolean expressions uniquely. */
5234
0
    bool can_deduplicate = true;
5235
0
    unsigned num_kept_cond = 0, cond_idx = 0;
5236
0
    for (const auto& offset : conditions)
5237
0
    {
5238
0
      const Condition &condition = this+offset;
5239
0
      can_deduplicate &= condition.u.format.v <= 1;
5240
0
      Cond_with_Var_flag_t ret = condition.keep_with_variations (c, condition_map);
5241
0
      // condition is not met or condition out of range, drop the entire record
5242
0
      if (ret == DROP_RECORD_WITH_VAR)
5243
0
      {
5244
0
        c->apply = false;
5245
0
        return;
5246
0
      }
5247
0
5248
0
      if (ret == KEEP_COND_WITH_VAR)
5249
0
      {
5250
0
        should_keep = true;
5251
0
        cond_set->add (cond_idx);
5252
0
        num_kept_cond++;
5253
0
      }
5254
0
5255
0
      if (ret == KEEP_RECORD_WITH_VAR)
5256
0
        should_keep = true;
5257
0
5258
0
      cond_idx++;
5259
0
    }
5260
0
5261
0
    /* Satisfied pinned conditions still terminate first-match processing.
5262
0
     * Keep their universal record when other axes remain variable. */
5263
0
    c->universal = num_kept_cond == 0;
5264
0
    if (!should_keep && c->all_axes_pinned) return;
5265
0
5266
0
    //check if condition_set is unique with variations
5267
0
    if (can_deduplicate && c->conditionset_map->has (p))
5268
0
      //duplicate found, drop the entire record
5269
0
      return;
5270
0
5271
0
    if (can_deduplicate)
5272
0
      c->conditionset_map->set (p, 1);
5273
0
    c->record_cond_idx_map->set (c->cur_record_idx, s);
5274
0
  }
5275
5276
  bool subset (hb_subset_context_t *c,
5277
               hb_subset_layout_context_t *l,
5278
               bool insert_catch_all) const
5279
0
  {
5280
0
    TRACE_SUBSET (this);
5281
0
    auto *out = c->serializer->start_embed (this);
5282
0
    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
5283
0
5284
0
    if (insert_catch_all) return_trace (true);
5285
0
5286
0
    hb_set_t *retained_cond_set = nullptr;
5287
0
    if (l->feature_record_cond_idx_map != nullptr)
5288
0
      retained_cond_set = l->feature_record_cond_idx_map->get (l->cur_feature_var_record_idx);
5289
0
5290
0
    unsigned int count = conditions.len;
5291
0
    for (unsigned int i = 0; i < count; i++)
5292
0
    {
5293
0
      if (retained_cond_set != nullptr && !retained_cond_set->has (i))
5294
0
        continue;
5295
0
      const Condition &condition = this+conditions[i];
5296
0
      if (condition.u.format.v == 1)
5297
0
      {
5298
0
        subset_offset_array (c, out->conditions, this) (conditions[i]);
5299
0
        continue;
5300
0
      }
5301
0
5302
0
      auto *offset = out->conditions.serialize_append (c->serializer);
5303
0
      if (unlikely (!offset)) return_trace (false);
5304
0
      c->serializer->push ();
5305
0
      auto result = condition.subset_lookup_condition (c, HB_MAX_NESTING_LEVEL, true);
5306
0
      if (result == LOOKUP_CONDITION_SUBSET_FALSE)
5307
0
        /* A false condition must not become a null (true) ConditionSet. */
5308
0
        result = Condition::serialize_constant (c->serializer, false) ?
5309
0
                 LOOKUP_CONDITION_SUBSET_KEEP : LOOKUP_CONDITION_SUBSET_ERROR;
5310
0
      if (unlikely (result == LOOKUP_CONDITION_SUBSET_ERROR))
5311
0
      {
5312
0
        c->serializer->pop_discard ();
5313
0
        c->serializer->check_success (false);
5314
0
        return_trace (false);
5315
0
      }
5316
0
      c->serializer->add_link (*offset, c->serializer->pop_pack ());
5317
0
    }
5318
0
5319
0
    return_trace (bool (out->conditions));
5320
0
  }
5321
5322
  bool sanitize (hb_sanitize_context_t *c) const
5323
0
  {
5324
0
    TRACE_SANITIZE (this);
5325
0
    return_trace (conditions.sanitize (c, this));
5326
0
  }
5327
5328
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
5329
0
  {
5330
0
    for (const auto &offset : conditions)
5331
0
      if (unlikely (!(this+offset).collect_var_indices (c->layout_variation_indices,
5332
0
                                                       HB_MAX_NESTING_LEVEL,
5333
0
                                                       c->condition_values)))
5334
0
  c->layout_variation_indices->err ();
5335
0
  }
5336
5337
  protected:
5338
  Array16OfOffset32To<Condition>  conditions;
5339
  public:
5340
  DEFINE_SIZE_ARRAY (2, conditions);
5341
};
5342
5343
struct FeatureTableSubstitutionRecord
5344
{
5345
  friend struct FeatureTableSubstitution;
5346
5347
  void collect_lookups (const void *base, hb_set_t *lookup_indexes /* OUT */) const
5348
0
  {
5349
0
    return (base+feature).add_lookup_indexes_to (lookup_indexes);
5350
0
  }
5351
5352
  void closure_features (const void *base,
5353
       const hb_map_t *lookup_indexes,
5354
       hb_set_t       *feature_indexes /* OUT */) const
5355
0
  {
5356
0
    if ((base+feature).intersects_lookup_indexes (lookup_indexes))
5357
0
      feature_indexes->add (featureIndex);
5358
0
  }
5359
5360
  void collect_feature_substitutes_with_variations (hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
5361
                                                    hb_set_t& catch_all_record_feature_idxes,
5362
                                                    const hb_set_t *feature_indices,
5363
                                                    const void *base) const
5364
0
  {
5365
0
    if (feature_indices->has (featureIndex))
5366
0
    {
5367
0
      feature_substitutes_map->set (featureIndex, &(base+feature));
5368
0
      catch_all_record_feature_idxes.add (featureIndex);
5369
0
    }
5370
0
  }
5371
5372
  bool serialize (hb_subset_layout_context_t *c,
5373
                  unsigned feature_index,
5374
                  const Feature *f, const Tag *tag)
5375
0
  {
5376
0
    TRACE_SERIALIZE (this);
5377
0
    hb_serialize_context_t *s = c->subset_context->serializer;
5378
0
    if (unlikely (!s->extend_min (this))) return_trace (false);
5379
0
5380
0
    uint32_t *new_feature_idx;
5381
0
    if (!c->feature_map_w_duplicates->has (feature_index, &new_feature_idx))
5382
0
      return_trace (false);
5383
0
5384
0
    if (!s->check_assign (featureIndex, *new_feature_idx, HB_SERIALIZE_ERROR_INT_OVERFLOW))
5385
0
      return_trace (false);
5386
0
5387
0
    s->push ();
5388
0
    bool ret = f->subset (c->subset_context, c, tag);
5389
0
    if (ret) s->add_link (feature, s->pop_pack ());
5390
0
    else s->pop_discard ();
5391
0
5392
0
    return_trace (ret);
5393
0
  }
5394
5395
  bool subset (hb_subset_layout_context_t *c, const void *base) const
5396
0
  {
5397
0
    TRACE_SUBSET (this);
5398
0
    uint32_t *new_feature_index;
5399
0
    if (!c->feature_map_w_duplicates->has (featureIndex, &new_feature_index))
5400
0
      return_trace (false);
5401
0
5402
0
    auto *out = c->subset_context->serializer->embed (this);
5403
0
    if (unlikely (!out)) return_trace (false);
5404
0
5405
0
    out->featureIndex = *new_feature_index;
5406
0
    hb_pair_t<const void*, const void*> *original;
5407
0
    if (!c->feature_idx_tag_map->has (featureIndex, &original))
5408
0
      return_trace (false);
5409
0
    const Tag *tag = reinterpret_cast<const Tag*> (original->second);
5410
0
    return_trace (out->feature.serialize_subset (c->subset_context, feature, base, c, tag));
5411
0
  }
5412
5413
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
5414
0
  {
5415
0
    TRACE_SANITIZE (this);
5416
0
    return_trace (c->check_struct (this) && feature.sanitize (c, base));
5417
0
  }
5418
5419
  protected:
5420
  HBUINT16    featureIndex;
5421
  Offset32To<Feature> feature;
5422
  public:
5423
  DEFINE_SIZE_STATIC (6);
5424
};
5425
5426
struct FeatureTableSubstitution
5427
{
5428
  void collect_feature_indices (hb_set_t *feature_indices) const
5429
0
  {
5430
0
    for (const FeatureTableSubstitutionRecord &record : substitutions)
5431
0
      feature_indices->add (record.featureIndex);
5432
0
  }
5433
5434
  const Feature *find_substitute (unsigned int feature_index) const
5435
0
  {
5436
0
    unsigned int count = substitutions.len;
5437
0
    for (unsigned int i = 0; i < count; i++)
5438
0
    {
5439
0
      const FeatureTableSubstitutionRecord &record = substitutions.arrayZ[i];
5440
0
      if (record.featureIndex == feature_index)
5441
0
  return &(this+record.feature);
5442
0
    }
5443
0
    return nullptr;
5444
0
  }
5445
5446
  void collect_lookups (const hb_set_t *feature_indexes,
5447
      hb_set_t       *lookup_indexes /* OUT */) const
5448
0
  {
5449
0
    + hb_iter (substitutions)
5450
0
    | hb_filter (feature_indexes, &FeatureTableSubstitutionRecord::featureIndex)
5451
0
    | hb_apply ([this, lookup_indexes] (const FeatureTableSubstitutionRecord& r)
5452
0
    { r.collect_lookups (this, lookup_indexes); })
5453
0
    ;
5454
0
  }
5455
5456
  template <typename TagGetter>
5457
  void collect_name_ids (const hb_map_t *feature_index_map,
5458
                         TagGetter get_tag,
5459
                         hb_set_t *nameids_to_retain) const
5460
0
  {
5461
0
    for (const FeatureTableSubstitutionRecord &record : substitutions)
5462
0
      if (feature_index_map->has (record.featureIndex))
5463
0
        (this+record.feature).collect_name_ids (get_tag (record.featureIndex), nameids_to_retain);
5464
0
  }
5465
5466
  void closure_features (const hb_map_t *lookup_indexes,
5467
       hb_set_t       *feature_indexes /* OUT */) const
5468
0
  {
5469
0
    for (const FeatureTableSubstitutionRecord& record : substitutions)
5470
0
      record.closure_features (this, lookup_indexes, feature_indexes);
5471
0
  }
5472
5473
  bool intersects_features (const hb_map_t *feature_index_map) const
5474
0
  {
5475
0
    for (const FeatureTableSubstitutionRecord& record : substitutions)
5476
0
    {
5477
0
      if (feature_index_map->has (record.featureIndex)) return true;
5478
0
    }
5479
0
    return false;
5480
0
  }
5481
5482
  void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
5483
0
  {
5484
0
    for (const FeatureTableSubstitutionRecord& record : substitutions)
5485
0
      record.collect_feature_substitutes_with_variations (c->feature_substitutes_map,
5486
0
                                                          c->catch_all_record_feature_idxes,
5487
0
                                                          c->feature_indices, this);
5488
0
  }
5489
5490
  bool subset (hb_subset_context_t        *c,
5491
         hb_subset_layout_context_t *l,
5492
               bool insert_catch_all) const
5493
0
  {
5494
0
    TRACE_SUBSET (this);
5495
0
    auto *out = c->serializer->start_embed (*this);
5496
0
    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
5497
0
5498
0
    out->version.major = version.major;
5499
0
    out->version.minor = version.minor;
5500
0
5501
0
    if (insert_catch_all)
5502
0
    {
5503
0
      for (unsigned feature_index : *(l->catch_all_record_feature_idxes))
5504
0
      {
5505
0
        hb_pair_t<const void*, const void*> *p;
5506
0
        if (!l->feature_idx_tag_map->has (feature_index, &p))
5507
0
          return_trace (false);
5508
0
        auto *o = out->substitutions.serialize_append (c->serializer);
5509
0
        if (!o->serialize (l, feature_index,
5510
0
                           reinterpret_cast<const Feature*> (p->first),
5511
0
                           reinterpret_cast<const Tag*> (p->second)))
5512
0
          return_trace (false);
5513
0
      }
5514
0
      return_trace (true);
5515
0
    }
5516
0
5517
0
    + substitutions.iter ()
5518
0
    | hb_apply (subset_record_array (l, &(out->substitutions), this))
5519
0
    ;
5520
0
5521
0
    return_trace (bool (out->substitutions));
5522
0
  }
5523
5524
  bool sanitize (hb_sanitize_context_t *c) const
5525
0
  {
5526
0
    TRACE_SANITIZE (this);
5527
0
    return_trace (version.sanitize (c) &&
5528
0
      hb_barrier () &&
5529
0
      likely (version.major == 1) &&
5530
0
      substitutions.sanitize (c, this));
5531
0
  }
5532
5533
  protected:
5534
  FixedVersion<>  version;  /* Version--0x00010000u */
5535
  Array16Of<FeatureTableSubstitutionRecord>
5536
      substitutions;
5537
  public:
5538
  DEFINE_SIZE_ARRAY (6, substitutions);
5539
};
5540
5541
struct FeatureVariationRecord
5542
{
5543
  friend struct FeatureVariations;
5544
5545
  void collect_lookups (const void     *base,
5546
      const hb_set_t *feature_indexes,
5547
      hb_set_t       *lookup_indexes /* OUT */) const
5548
0
  {
5549
0
    return (base+substitutions).collect_lookups (feature_indexes, lookup_indexes);
5550
0
  }
5551
5552
  template <typename TagGetter>
5553
  void collect_name_ids (const void *base,
5554
                         const hb_map_t *feature_index_map,
5555
                         TagGetter get_tag,
5556
                         hb_set_t *nameids_to_retain) const
5557
0
  {
5558
0
    (base+substitutions).collect_name_ids (feature_index_map, get_tag, nameids_to_retain);
5559
0
  }
5560
5561
  void closure_features (const void     *base,
5562
       const hb_map_t *lookup_indexes,
5563
       hb_set_t       *feature_indexes /* OUT */) const
5564
0
  {
5565
0
    (base+substitutions).closure_features (lookup_indexes, feature_indexes);
5566
0
  }
5567
5568
  bool intersects_features (const void *base, const hb_map_t *feature_index_map) const
5569
0
  {
5570
0
    return (base+substitutions).intersects_features (feature_index_map);
5571
0
  }
5572
5573
  void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
5574
                                                    const void *base) const
5575
0
  {
5576
0
    (base+conditions).keep_with_variations (c);
5577
0
    if (c->apply && !c->variation_applied)
5578
0
    {
5579
0
      (base+substitutions).collect_feature_substitutes_with_variations (c);
5580
0
      c->variation_applied = true; // set variations only once
5581
0
    }
5582
0
  }
5583
5584
  bool subset (hb_subset_layout_context_t *c, const void *base,
5585
               bool insert_catch_all = false) const
5586
0
  {
5587
0
    TRACE_SUBSET (this);
5588
0
    auto *out = c->subset_context->serializer->embed (this);
5589
0
    if (unlikely (!out)) return_trace (false);
5590
0
5591
0
    hb_set_t *retained_conditions = c->feature_record_cond_idx_map ?
5592
0
        c->feature_record_cond_idx_map->get (c->cur_feature_var_record_idx).get () : nullptr;
5593
0
    if (!insert_catch_all && retained_conditions && retained_conditions->is_empty ())
5594
0
      /* A null ConditionSet is the unconditional first-match record. */
5595
0
      out->conditions = 0;
5596
0
    else
5597
0
      out->conditions.serialize_subset (c->subset_context, conditions, base, c, insert_catch_all);
5598
0
    out->substitutions.serialize_subset (c->subset_context, substitutions, base, c, insert_catch_all);
5599
0
5600
0
    return_trace (true);
5601
0
  }
5602
5603
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
5604
0
  {
5605
0
    TRACE_SANITIZE (this);
5606
0
    return_trace (conditions.sanitize (c, base) &&
5607
0
      substitutions.sanitize (c, base));
5608
0
  }
5609
5610
  void collect_variation_indices (hb_collect_variation_indices_context_t *c,
5611
          const void *base) const
5612
0
  { (base+conditions).collect_variation_indices (c); }
5613
5614
  protected:
5615
  Offset32To<ConditionSet>
5616
      conditions;
5617
  Offset32To<FeatureTableSubstitution>
5618
      substitutions;
5619
  public:
5620
  DEFINE_SIZE_STATIC (8);
5621
};
5622
5623
struct LookupIndexList
5624
{
5625
  void add_lookup_indexes_to (hb_set_t *lookup_indexes) const
5626
0
  { lookupIndices.add_indexes_to (lookup_indexes); }
5627
5628
  bool intersects_lookup_indexes (const hb_map_t *lookup_indexes) const
5629
0
  { return lookupIndices.intersects (lookup_indexes); }
5630
5631
  bool subset (hb_subset_context_t *c,
5632
         hb_subset_layout_context_t *l) const
5633
0
  {
5634
0
    TRACE_SUBSET (this);
5635
0
    auto *out = c->serializer->start_embed (this);
5636
0
    if (unlikely (!out || !c->serializer->extend_min (out)))
5637
0
      return_trace (false);
5638
0
5639
0
    auto it =
5640
0
    + hb_iter (lookupIndices)
5641
0
    | hb_filter (l->lookup_index_map)
5642
0
    | hb_map (l->lookup_index_map)
5643
0
    ;
5644
0
    out->lookupIndices.serialize (c->serializer, l, it);
5645
0
    return_trace (bool (out->lookupIndices));
5646
0
  }
5647
5648
  bool sanitize (hb_sanitize_context_t *c) const
5649
0
  {
5650
0
    TRACE_SANITIZE (this);
5651
0
    return_trace (lookupIndices.sanitize (c));
5652
0
  }
5653
5654
  protected:
5655
  IndexArray  lookupIndices;
5656
  public:
5657
  DEFINE_SIZE_ARRAY_SIZED (2, lookupIndices);
5658
};
5659
5660
struct LookupConditionRecord
5661
{
5662
  unsigned get_condition_offset (const void *base, const void *variations) const
5663
0
  { return (const char *) &(base+condition) - (const char *) variations; }
5664
5665
  template <typename Instancer>
5666
  bool evaluate (const void *base,
5667
     const int *coords,
5668
     unsigned int coord_len,
5669
     Instancer *instancer) const
5670
0
  { return (base+condition).evaluate (coords, coord_len, instancer); }
5671
5672
  bool evaluate (const void *base,
5673
                 const void *variations,
5674
                 hb_sorted_array_t<const unsigned> conditions) const
5675
0
  {
5676
0
    return !condition || hb_bsearch (get_condition_offset (base, variations),
5677
0
                                     conditions.arrayZ, conditions.length,
5678
0
                                     sizeof (unsigned),
5679
0
                                     _hb_cmp_operator<unsigned, unsigned>);
5680
0
  }
5681
5682
  bool collect_condition (const void *base,
5683
                          const void *variations,
5684
                          const int *coords,
5685
                          unsigned int coord_len,
5686
                          ItemVarStoreInstancer *instancer,
5687
                          hb_set_t *visited,
5688
                          hb_vector_t<unsigned> *conditions) const
5689
0
  {
5690
    /* Null conditions always apply and need no key state. */
5691
0
    if (!condition) return true;
5692
5693
0
    unsigned offset = get_condition_offset (base, variations);
5694
0
    if (visited->has (offset)) return true;
5695
0
    visited->add (offset);
5696
0
    if (unlikely (visited->in_error ())) return false;
5697
5698
0
    if (evaluate (base, coords, coord_len, instancer))
5699
0
      conditions->push (offset);
5700
0
    return !conditions->in_error ();
5701
0
  }
5702
5703
  void add_lookup_indexes_to (const void *base,
5704
            hb_set_t *lookup_indexes) const
5705
0
  { (base+lookupIndices).add_lookup_indexes_to (lookup_indexes); }
5706
5707
  bool intersects_lookup_indexes (const void *base,
5708
           const hb_map_t *lookup_indexes) const
5709
0
  { return (base+lookupIndices).intersects_lookup_indexes (lookup_indexes); }
5710
5711
  void collect_variation_indices (hb_collect_variation_indices_context_t *c,
5712
          const void *base) const
5713
0
  {
5714
0
    if (unlikely (!(base+condition).collect_var_indices (c->layout_variation_indices,
5715
0
                                                        HB_MAX_NESTING_LEVEL,
5716
0
                                                        c->condition_values)))
5717
0
      c->layout_variation_indices->err ();
5718
0
  }
5719
5720
  bool subset (hb_subset_context_t *c,
5721
         hb_subset_layout_context_t *l,
5722
         const void *base) const
5723
0
  {
5724
0
    TRACE_SUBSET (this);
5725
0
    auto *out = c->serializer->embed (this);
5726
0
    if (unlikely (!out)) return_trace (false);
5727
0
5728
0
    out->condition = 0;
5729
0
    c->serializer->push ();
5730
0
    lookup_condition_subset_result_t result =
5731
0
        (base + condition).subset_lookup_condition (c,
5732
0
              HB_MAX_NESTING_LEVEL,
5733
0
              true);
5734
0
    if (result != LOOKUP_CONDITION_SUBSET_KEEP)
5735
0
    {
5736
0
      c->serializer->pop_discard ();
5737
0
      return_trace (false);
5738
0
    }
5739
0
    c->serializer->add_link (out->condition, c->serializer->pop_pack ());
5740
0
5741
0
    return_trace (out->lookupIndices.serialize_subset (c, lookupIndices, base, l));
5742
0
  }
5743
5744
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
5745
0
  {
5746
0
    TRACE_SANITIZE (this);
5747
0
    return_trace (condition.sanitize (c, base) &&
5748
0
      lookupIndices.sanitize (c, base));
5749
0
  }
5750
5751
  protected:
5752
  Offset32To<Condition>   condition;
5753
  Offset32To<LookupIndexList> lookupIndices;
5754
  public:
5755
  DEFINE_SIZE_STATIC (8);
5756
};
5757
5758
struct FeatureLookupsTable
5759
{
5760
0
  bool adds_default_lookups () const { return flags & 0x0001u; }
5761
5762
  bool collect_conditions (const void *variations,
5763
                           const int *coords,
5764
                           unsigned int coord_len,
5765
                           ItemVarStoreInstancer *instancer,
5766
                           hb_set_t *visited,
5767
                           hb_vector_t<unsigned> *conditions) const
5768
0
  {
5769
0
    for (const LookupConditionRecord &record : records)
5770
0
      if (unlikely (!record.collect_condition (this, variations, coords, coord_len,
5771
0
                                               instancer, visited, conditions)))
5772
0
  return false;
5773
0
    return true;
5774
0
  }
5775
5776
  void collect_lookups (const void *variations,
5777
                       hb_sorted_array_t<const unsigned> conditions,
5778
                       hb_set_t *lookup_indexes) const
5779
0
  {
5780
0
    for (const LookupConditionRecord &record : records)
5781
0
      if (record.evaluate (this, variations, conditions))
5782
0
  record.add_lookup_indexes_to (this, lookup_indexes);
5783
0
  }
5784
5785
  template <typename Instancer>
5786
  void collect_lookups (const int *coords,
5787
      unsigned int coord_len,
5788
      Instancer *instancer,
5789
      hb_set_t *lookup_indexes) const
5790
  {
5791
    for (const LookupConditionRecord &record : records)
5792
      if (record.evaluate (this, coords, coord_len, instancer))
5793
  record.add_lookup_indexes_to (this, lookup_indexes);
5794
  }
5795
5796
  void collect_lookups (hb_set_t *lookup_indexes) const
5797
0
  {
5798
0
    for (const LookupConditionRecord &record : records)
5799
0
      record.add_lookup_indexes_to (this, lookup_indexes);
5800
0
  }
5801
5802
  bool intersects_lookup_indexes (const hb_map_t *lookup_indexes) const
5803
0
  {
5804
0
    for (const LookupConditionRecord &record : records)
5805
0
      if (record.intersects_lookup_indexes (this, lookup_indexes))
5806
0
  return true;
5807
0
    return false;
5808
0
  }
5809
5810
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
5811
0
  {
5812
0
    for (const LookupConditionRecord &record : records)
5813
0
      record.collect_variation_indices (c, this);
5814
0
  }
5815
5816
  bool subset (hb_subset_context_t *c,
5817
         hb_subset_layout_context_t *l) const
5818
0
  {
5819
0
    TRACE_SUBSET (this);
5820
0
    auto *out = c->serializer->start_embed (this);
5821
0
    if (unlikely (!out || !c->serializer->extend_min (out)))
5822
0
      return_trace (false);
5823
0
5824
0
    out->version.major = version.major;
5825
0
    out->version.minor = version.minor;
5826
0
    out->flags = flags;
5827
0
5828
0
    for (const LookupConditionRecord &record : records)
5829
0
    {
5830
0
      auto snap = c->serializer->snapshot ();
5831
0
      if (record.subset (c, l, this))
5832
0
  out->records.len++;
5833
0
      else
5834
0
  c->serializer->revert (snap);
5835
0
    }
5836
0
5837
0
    return_trace (true);
5838
0
  }
5839
5840
  bool sanitize (hb_sanitize_context_t *c) const
5841
0
  {
5842
0
    TRACE_SANITIZE (this);
5843
0
    return_trace (version.sanitize (c) &&
5844
0
      hb_barrier () &&
5845
0
      likely (version.major == 1) &&
5846
0
      records.sanitize (c, this));
5847
0
  }
5848
5849
  protected:
5850
  FixedVersion<>  version;  /* Version--0x00010000u */
5851
  HBUINT16  flags;
5852
  Array32Of<LookupConditionRecord>
5853
    records;
5854
  public:
5855
  DEFINE_SIZE_ARRAY (10, records);
5856
};
5857
5858
struct LookupVariationRecord
5859
{
5860
  friend struct FeatureVariations;
5861
5862
0
  unsigned get_feature_index () const { return featureIndex; }
5863
5864
  void collect_lookups (const void *base,
5865
                       const Feature &feature,
5866
                       hb_sorted_array_t<const unsigned> conditions,
5867
                       hb_set_t *lookup_indexes) const
5868
0
  {
5869
0
    const FeatureLookupsTable &feature_lookups = base+featureLookups;
5870
0
    if (feature_lookups.adds_default_lookups ())
5871
0
      feature.add_lookup_indexes_to (lookup_indexes);
5872
0
    feature_lookups.collect_lookups (base, conditions, lookup_indexes);
5873
0
  }
5874
5875
  void collect_lookups (const void *base,
5876
      const hb_set_t *feature_indexes,
5877
      hb_set_t *lookup_indexes) const
5878
0
  {
5879
0
    if (feature_indexes->has (featureIndex))
5880
0
      (base+featureLookups).collect_lookups (lookup_indexes);
5881
0
  }
5882
5883
  void closure_features (const void *base,
5884
       const hb_map_t *lookup_indexes,
5885
       hb_set_t *feature_indexes) const
5886
0
  {
5887
0
    if ((base+featureLookups).intersects_lookup_indexes (lookup_indexes))
5888
0
      feature_indexes->add (featureIndex);
5889
0
  }
5890
5891
  void collect_variation_indices (hb_collect_variation_indices_context_t *c,
5892
          const void *base) const
5893
0
  { (base+featureLookups).collect_variation_indices (c); }
5894
5895
  bool subset (hb_subset_layout_context_t *l, const void *base) const
5896
0
  {
5897
0
    hb_subset_context_t *c = l->subset_context;
5898
0
    TRACE_SUBSET (this);
5899
0
    uint32_t *new_feature_index;
5900
0
    if (!l->feature_map_w_duplicates->has (featureIndex, &new_feature_index))
5901
0
      return_trace (false);
5902
0
5903
0
    auto *out = c->serializer->embed (this);
5904
0
    if (unlikely (!out ||
5905
0
      !c->serializer->check_assign (out->featureIndex,
5906
0
            *new_feature_index,
5907
0
            HB_SERIALIZE_ERROR_INT_OVERFLOW)))
5908
0
      return_trace (false);
5909
0
5910
0
    return_trace (out->featureLookups.serialize_subset (c, featureLookups, base, l));
5911
0
  }
5912
5913
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
5914
0
  {
5915
0
    TRACE_SANITIZE (this);
5916
0
    return_trace (c->check_struct (this) &&
5917
0
      featureLookups.sanitize (c, base));
5918
0
  }
5919
5920
  protected:
5921
  HBUINT16      featureIndex;
5922
  Offset32To<FeatureLookupsTable> featureLookups;
5923
  public:
5924
  DEFINE_SIZE_STATIC (6);
5925
};
5926
5927
struct FeatureVariations
5928
{
5929
  static constexpr unsigned NOT_FOUND_INDEX = 0xFFFFFFFFu;
5930
5931
  const Array32Of<LookupVariationRecord> &get_lookup_variation_records () const
5932
159k
  {
5933
159k
    if (version.to_int () < 0x00010001u)
5934
159k
      return Null (Array32Of<LookupVariationRecord>);
5935
0
    return StructAfter<Array32Of<LookupVariationRecord>> (varRecords);
5936
159k
  }
5937
5938
  unsigned record_count () const
5939
0
  {
5940
0
    return varRecords.len;
5941
0
  }
5942
5943
  bool find_index (const int *coords, unsigned int coord_len,
5944
       unsigned int *index,
5945
       ItemVarStoreInstancer *instancer) const
5946
159k
  {
5947
159k
    unsigned int count = varRecords.len;
5948
159k
    for (unsigned int i = 0; i < count; i++)
5949
0
    {
5950
0
      const FeatureVariationRecord &record = varRecords.arrayZ[i];
5951
0
      if ((this+record.conditions).evaluate (coords, coord_len, instancer))
5952
0
      {
5953
0
  *index = i;
5954
0
  return true;
5955
0
      }
5956
0
    }
5957
159k
    *index = NOT_FOUND_INDEX;
5958
159k
    return false;
5959
159k
  }
5960
5961
  const Feature *find_substitute (unsigned int variations_index,
5962
          unsigned int feature_index) const
5963
0
  {
5964
0
    const FeatureVariationRecord &record = varRecords[variations_index];
5965
0
    return (this+record.substitutions).find_substitute (feature_index);
5966
0
  }
5967
5968
  bool collect_lookup_conditions (const int *coords,
5969
                                  unsigned int coord_len,
5970
                                  ItemVarStoreInstancer *instancer,
5971
                                  hb_vector_t<unsigned> *state) const
5972
159k
  {
5973
159k
    hb_set_t visited_tables, visited_conditions;
5974
159k
    for (const LookupVariationRecord &record : get_lookup_variation_records ())
5975
0
    {
5976
0
      unsigned offset = record.featureLookups;
5977
0
      if (visited_tables.has (offset)) continue;
5978
0
      visited_tables.add (offset);
5979
0
      if (unlikely (visited_tables.in_error ())) return false;
5980
5981
0
      const FeatureLookupsTable &feature_lookups = this+record.featureLookups;
5982
0
      if (unlikely (!feature_lookups.collect_conditions (this, coords, coord_len,
5983
0
                                                         instancer, &visited_conditions,
5984
0
                                                         state)))
5985
0
  return false;
5986
0
    }
5987
5988
    /* Key size depends on distinct conditions, not expanded lookup sets.
5989
     * Sorting makes it independent of their first traversal order. */
5990
159k
    state->qsort (_hb_cmp_operator<unsigned, unsigned>);
5991
159k
    return true;
5992
159k
  }
5993
5994
  bool get_lookup_variations (unsigned feature_index,
5995
                              const Feature &feature,
5996
                              hb_sorted_array_t<const unsigned> conditions,
5997
                              hb_set_t *lookup_indexes) const
5998
124
  {
5999
124
    for (const LookupVariationRecord &record : get_lookup_variation_records ())
6000
0
    {
6001
0
      if (record.featureIndex != feature_index) continue;
6002
6003
0
      record.collect_lookups (this, feature, conditions, lookup_indexes);
6004
0
      return true;
6005
0
    }
6006
124
    return false;
6007
124
  }
6008
6009
  void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
6010
0
  {
6011
0
    unsigned int count = varRecords.len;
6012
0
    for (unsigned int i = 0; i < count; i++)
6013
0
    {
6014
0
      c->cur_record_idx = i;
6015
0
      varRecords[i].collect_feature_substitutes_with_variations (c, this);
6016
0
      if (c->universal)
6017
0
        break;
6018
0
    }
6019
0
    if (c->universal || c->record_cond_idx_map->is_empty ())
6020
0
      c->catch_all_record_feature_idxes.reset ();
6021
0
  }
6022
6023
  FeatureVariations* copy (hb_serialize_context_t *c) const
6024
0
  {
6025
0
    TRACE_SERIALIZE (this);
6026
0
    return_trace (c->embed (*this));
6027
0
  }
6028
6029
  void collect_lookups (const hb_set_t *feature_indexes,
6030
      const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
6031
      hb_set_t       *lookup_indexes /* OUT */) const
6032
0
  {
6033
0
    unsigned count = varRecords.len;
6034
0
    for (unsigned int i = 0; i < count; i++)
6035
0
    {
6036
0
      if (feature_record_cond_idx_map &&
6037
0
          !feature_record_cond_idx_map->has (i))
6038
0
        continue;
6039
0
      varRecords[i].collect_lookups (this, feature_indexes, lookup_indexes);
6040
0
    }
6041
6042
0
    collect_lookup_variation_lookups (feature_indexes, lookup_indexes);
6043
0
  }
6044
6045
  template <typename TagGetter>
6046
  void collect_name_ids (const hb_map_t *feature_index_map,
6047
                         const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
6048
                         TagGetter get_tag,
6049
                         hb_set_t *nameids_to_retain) const
6050
0
  {
6051
0
    for (unsigned i = 0; i < varRecords.len; i++)
6052
0
    {
6053
0
      if (feature_record_cond_idx_map && !feature_record_cond_idx_map->has (i))
6054
0
        continue;
6055
0
      varRecords[i].collect_name_ids (this, feature_index_map, get_tag, nameids_to_retain);
6056
0
    }
6057
0
  }
6058
6059
  void collect_lookup_variation_lookups (const hb_set_t *feature_indexes,
6060
           hb_set_t *lookup_indexes /* OUT */) const
6061
0
  {
6062
0
    for (const LookupVariationRecord &record : get_lookup_variation_records ())
6063
0
      record.collect_lookups (this, feature_indexes, lookup_indexes);
6064
0
  }
6065
6066
  void closure_features (const hb_map_t *lookup_indexes,
6067
       const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
6068
       hb_set_t       *feature_indexes /* OUT */) const
6069
0
  {
6070
0
    unsigned int count = varRecords.len;
6071
0
    for (unsigned int i = 0; i < count; i++)
6072
0
    {
6073
0
      if (feature_record_cond_idx_map != nullptr &&
6074
0
          !feature_record_cond_idx_map->has (i))
6075
0
        continue;
6076
0
      varRecords[i].closure_features (this, lookup_indexes, feature_indexes);
6077
0
    }
6078
0
6079
0
    for (const LookupVariationRecord &record : get_lookup_variation_records ())
6080
0
      record.closure_features (this, lookup_indexes, feature_indexes);
6081
0
  }
6082
6083
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
6084
0
  {
6085
0
    for (const FeatureVariationRecord &record : varRecords)
6086
0
      record.collect_variation_indices (c, this);
6087
0
    for (const LookupVariationRecord &record : get_lookup_variation_records ())
6088
0
      record.collect_variation_indices (c, this);
6089
0
  }
6090
6091
  void collect_feature_indices (hb_set_t *feature_indices) const
6092
0
  {
6093
0
    for (const FeatureVariationRecord &record : varRecords)
6094
0
      (this+record.substitutions).collect_feature_indices (feature_indices);
6095
0
  }
6096
6097
  bool has_lookup_variations (unsigned feature_index) const
6098
0
  {
6099
0
    for (const LookupVariationRecord &record : get_lookup_variation_records ())
6100
0
    {
6101
0
      if (record.featureIndex == feature_index)
6102
0
  return true;
6103
0
      if (record.featureIndex > feature_index)
6104
0
  break;
6105
0
    }
6106
0
    return false;
6107
0
  }
6108
6109
  bool subset (hb_subset_context_t *c,
6110
         hb_subset_layout_context_t *l) const
6111
0
  {
6112
0
    TRACE_SUBSET (this);
6113
0
    auto *out = c->serializer->start_embed (*this);
6114
0
    if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
6115
0
6116
0
    out->version.major = version.major;
6117
0
    out->version.minor = version.minor;
6118
0
6119
0
    int keep_up_to = -1;
6120
0
    for (int i = varRecords.len - 1; i >= 0; i--) {
6121
0
      if (varRecords[i].intersects_features (this, l->feature_map_w_duplicates)) {
6122
0
        keep_up_to = i;
6123
0
        break;
6124
0
      }
6125
0
    }
6126
0
6127
0
    unsigned count = (unsigned) (keep_up_to + 1);
6128
0
    for (unsigned i = 0; i < count; i++)
6129
0
    {
6130
0
      if (l->feature_record_cond_idx_map != nullptr &&
6131
0
          !l->feature_record_cond_idx_map->has (i))
6132
0
        continue;
6133
0
6134
0
      l->cur_feature_var_record_idx = i;
6135
0
      subset_record_array (l, &(out->varRecords), this) (varRecords[i]);
6136
0
    }
6137
0
6138
0
    if (out->varRecords.len && !l->catch_all_record_feature_idxes->is_empty ())
6139
0
    {
6140
0
      bool insert_catch_all_record = true;
6141
0
      subset_record_array (l, &(out->varRecords), this, insert_catch_all_record) (varRecords[0]);
6142
0
    }
6143
0
6144
0
    Array32Of<LookupVariationRecord> *out_lookup_records = nullptr;
6145
0
    if (version.minor >= 1)
6146
0
    {
6147
0
      out_lookup_records = &StructAfter<Array32Of<LookupVariationRecord>> (out->varRecords);
6148
0
      if (unlikely (!c->serializer->extend_min (out_lookup_records)))
6149
0
  return_trace (false);
6150
0
6151
0
      + get_lookup_variation_records ().iter ()
6152
0
      | hb_apply (subset_record_array (l, out_lookup_records, this))
6153
0
      ;
6154
0
    }
6155
0
6156
0
    return_trace (bool (out->varRecords) ||
6157
0
      (out_lookup_records && bool (*out_lookup_records)));
6158
0
  }
6159
6160
  bool sanitize (hb_sanitize_context_t *c) const
6161
0
  {
6162
0
    TRACE_SANITIZE (this);
6163
0
    return_trace (version.sanitize (c) &&
6164
0
      hb_barrier () &&
6165
0
      likely (version.major == 1) &&
6166
0
      varRecords.sanitize (c, this) &&
6167
0
      (version.minor < 1 ||
6168
0
       get_lookup_variation_records ().sanitize (c, this)));
6169
0
  }
6170
6171
  protected:
6172
  FixedVersion<>  version;  /* Version--0x00010000u */
6173
  Array32Of<FeatureVariationRecord>
6174
      varRecords;
6175
  public:
6176
  DEFINE_SIZE_ARRAY_SIZED (8, varRecords);
6177
};
6178
6179
6180
/*
6181
 * Device Tables
6182
 */
6183
6184
struct HintingDevice
6185
{
6186
  friend struct Device;
6187
6188
  private:
6189
6190
  hb_position_t get_x_delta (hb_font_t *font) const
6191
0
  { return get_delta (font->x_ppem, font->x_scale); }
6192
6193
  hb_position_t get_y_delta (hb_font_t *font) const
6194
0
  { return get_delta (font->y_ppem, font->y_scale); }
6195
6196
  public:
6197
6198
  size_t get_size () const
6199
0
  {
6200
0
    unsigned int f = deltaFormat;
6201
0
    if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * HBUINT16::static_size;
6202
0
    return HBUINT16::static_size * (4 + ((endSize - startSize) >> (4 - f)));
6203
0
  }
6204
6205
  bool sanitize (hb_sanitize_context_t *c) const
6206
0
  {
6207
0
    TRACE_SANITIZE (this);
6208
0
    return_trace (c->check_struct (this) && c->check_range (this, this->get_size ()));
6209
0
  }
6210
6211
  HintingDevice* copy (hb_serialize_context_t *c) const
6212
0
  {
6213
0
    TRACE_SERIALIZE (this);
6214
0
    return_trace (c->embed<HintingDevice> (this));
6215
0
  }
6216
6217
  private:
6218
6219
  int get_delta (unsigned int ppem, int scale) const
6220
0
  {
6221
0
    if (!ppem) return 0;
6222
6223
0
    int pixels = get_delta_pixels (ppem);
6224
6225
0
    if (!pixels) return 0;
6226
6227
0
    return (int) (pixels * (int64_t) scale / ppem);
6228
0
  }
6229
  int get_delta_pixels (unsigned int ppem_size) const
6230
0
  {
6231
0
    unsigned int f = deltaFormat;
6232
0
    if (unlikely (f < 1 || f > 3))
6233
0
      return 0;
6234
6235
0
    if (ppem_size < startSize || ppem_size > endSize)
6236
0
      return 0;
6237
6238
0
    unsigned int s = ppem_size - startSize;
6239
6240
0
    unsigned int byte = deltaValueZ[s >> (4 - f)];
6241
0
    unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
6242
0
    unsigned int mask = (0xFFFFu >> (16 - (1 << f)));
6243
6244
0
    int delta = bits & mask;
6245
6246
0
    if ((unsigned int) delta >= ((mask + 1) >> 1))
6247
0
      delta -= mask + 1;
6248
6249
0
    return delta;
6250
0
  }
6251
6252
  protected:
6253
  HBUINT16  startSize;    /* Smallest size to correct--in ppem */
6254
  HBUINT16  endSize;    /* Largest size to correct--in ppem */
6255
  HBUINT16  deltaFormat;    /* Format of DeltaValue array data: 1, 2, or 3
6256
           * 1  Signed 2-bit value, 8 values per uint16
6257
           * 2  Signed 4-bit value, 4 values per uint16
6258
           * 3  Signed 8-bit value, 2 values per uint16
6259
           */
6260
  UnsizedArrayOf<HBUINT16>
6261
    deltaValueZ;    /* Array of compressed data */
6262
  public:
6263
  DEFINE_SIZE_ARRAY (6, deltaValueZ);
6264
};
6265
6266
struct VariationDevice
6267
{
6268
  friend struct Device;
6269
6270
  private:
6271
6272
  hb_position_t get_x_delta (hb_font_t *font,
6273
           const ItemVariationStore &store,
6274
           hb_scalar_cache_t *store_cache = nullptr) const
6275
0
  { return !font->has_nonzero_coords ? 0 : font->em_scalef_x (get_delta (font, store, store_cache)); }
6276
6277
  hb_position_t get_y_delta (hb_font_t *font,
6278
           const ItemVariationStore &store,
6279
           hb_scalar_cache_t *store_cache = nullptr) const
6280
0
  { return !font->has_nonzero_coords ? 0 : font->em_scalef_y (get_delta (font, store, store_cache)); }
6281
6282
  VariationDevice* copy (hb_serialize_context_t *c,
6283
                         const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) const
6284
0
  {
6285
0
    TRACE_SERIALIZE (this);
6286
0
    if (!layout_variation_idx_delta_map) return_trace (nullptr);
6287
0
6288
0
    hb_pair_t<unsigned, int> *v;
6289
0
    if (!layout_variation_idx_delta_map->has (varIdx, &v))
6290
0
      return_trace (nullptr);
6291
0
    /* The varidx was mapped to "no variations" during instancing (e.g. the
6292
0
     * instantiated row is all zeros). Drop the device instead of emitting one
6293
0
     * with an out-of-range varidx. */
6294
0
    if (hb_first (*v) == HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
6295
0
      return_trace (nullptr);
6296
0
6297
0
    c->start_zerocopy (this->static_size);
6298
0
    auto *out = c->embed (this);
6299
0
    if (unlikely (!out)) return_trace (nullptr);
6300
0
6301
0
    if (!c->check_assign (out->varIdx, hb_first (*v), HB_SERIALIZE_ERROR_INT_OVERFLOW))
6302
0
      return_trace (nullptr);
6303
0
    return_trace (out);
6304
0
  }
6305
6306
  void collect_variation_index (hb_collect_variation_indices_context_t *c) const
6307
0
  { c->layout_variation_indices->add (varIdx); }
6308
6309
  bool sanitize (hb_sanitize_context_t *c) const
6310
0
  {
6311
0
    TRACE_SANITIZE (this);
6312
0
    return_trace (c->check_struct (this));
6313
0
  }
6314
6315
  private:
6316
6317
  float get_delta (hb_font_t *font,
6318
       const ItemVariationStore &store,
6319
       hb_scalar_cache_t *store_cache = nullptr) const
6320
0
  {
6321
0
    return store.get_delta (varIdx, font->coords, font->num_coords, store_cache);
6322
0
  }
6323
6324
  protected:
6325
  VarIdx  varIdx;   /* Variation index */
6326
  HBUINT16  deltaFormat;  /* Format identifier for this table: 0x0x8000 */
6327
  public:
6328
  DEFINE_SIZE_STATIC (6);
6329
};
6330
6331
struct DeviceHeader
6332
{
6333
  protected:
6334
  HBUINT16    reserved1;
6335
  HBUINT16    reserved2;
6336
  public:
6337
  HBUINT16    format;   /* Format identifier */
6338
  public:
6339
  DEFINE_SIZE_STATIC (6);
6340
};
6341
6342
struct Device
6343
{
6344
  hb_position_t get_x_delta (hb_font_t *font,
6345
           const ItemVariationStore &store=Null (ItemVariationStore),
6346
           hb_scalar_cache_t *store_cache = nullptr) const
6347
0
  {
6348
0
    switch (u.b.format)
6349
0
    {
6350
0
#ifndef HB_NO_HINTING
6351
0
    case 1: case 2: case 3:
6352
0
      hb_barrier ();
6353
0
      return u.hinting.get_x_delta (font);
6354
0
#endif
6355
0
#ifndef HB_NO_VAR
6356
0
    case 0x8000:
6357
0
      hb_barrier ();
6358
0
      return u.variation.get_x_delta (font, store, store_cache);
6359
0
#endif
6360
0
    default:
6361
0
      return 0;
6362
0
    }
6363
0
  }
6364
  hb_position_t get_y_delta (hb_font_t *font,
6365
           const ItemVariationStore &store=Null (ItemVariationStore),
6366
           hb_scalar_cache_t *store_cache = nullptr) const
6367
0
  {
6368
0
    switch (u.b.format)
6369
0
    {
6370
0
    case 1: case 2: case 3:
6371
0
#ifndef HB_NO_HINTING
6372
0
      hb_barrier ();
6373
0
      return u.hinting.get_y_delta (font);
6374
0
#endif
6375
0
#ifndef HB_NO_VAR
6376
0
    case 0x8000:
6377
0
      hb_barrier ();
6378
0
      return u.variation.get_y_delta (font, store, store_cache);
6379
0
#endif
6380
0
    default:
6381
0
      return 0;
6382
0
    }
6383
0
  }
6384
6385
  bool sanitize (hb_sanitize_context_t *c) const
6386
0
  {
6387
0
    TRACE_SANITIZE (this);
6388
0
    if (!u.b.format.sanitize (c)) return_trace (false);
6389
0
    switch (u.b.format) {
6390
0
#ifndef HB_NO_HINTING
6391
0
    case 1: case 2: case 3:
6392
0
      hb_barrier ();
6393
0
      return_trace (u.hinting.sanitize (c));
6394
0
#endif
6395
0
#ifndef HB_NO_VAR
6396
0
    case 0x8000:
6397
0
      hb_barrier ();
6398
0
      return_trace (u.variation.sanitize (c));
6399
0
#endif
6400
0
    default:
6401
0
      return_trace (true);
6402
0
    }
6403
0
  }
6404
6405
  Device* copy (hb_serialize_context_t *c,
6406
                const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map=nullptr) const
6407
0
  {
6408
0
    TRACE_SERIALIZE (this);
6409
0
    switch (u.b.format) {
6410
0
#ifndef HB_NO_HINTING
6411
0
    case 1:
6412
0
    case 2:
6413
0
    case 3:
6414
0
      hb_barrier ();
6415
0
      return_trace (reinterpret_cast<Device *> (u.hinting.copy (c)));
6416
0
#endif
6417
0
#ifndef HB_NO_VAR
6418
0
    case 0x8000:
6419
0
      hb_barrier ();
6420
0
      return_trace (reinterpret_cast<Device *> (u.variation.copy (c, layout_variation_idx_delta_map)));
6421
0
#endif
6422
0
    default:
6423
0
      return_trace (nullptr);
6424
0
    }
6425
0
  }
6426
6427
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
6428
0
  {
6429
0
    switch (u.b.format) {
6430
0
#ifndef HB_NO_HINTING
6431
0
    case 1:
6432
0
    case 2:
6433
0
    case 3:
6434
0
      return;
6435
0
#endif
6436
0
#ifndef HB_NO_VAR
6437
0
    case 0x8000:
6438
0
      hb_barrier ();
6439
0
      u.variation.collect_variation_index (c);
6440
0
      return;
6441
0
#endif
6442
0
    default:
6443
0
      return;
6444
0
    }
6445
0
  }
6446
6447
  unsigned get_variation_index () const
6448
0
  {
6449
0
    switch (u.b.format) {
6450
0
#ifndef HB_NO_VAR
6451
0
    case 0x8000:
6452
0
      hb_barrier ();
6453
0
      return u.variation.varIdx;
6454
0
#endif
6455
0
    default:
6456
0
      return HB_OT_LAYOUT_NO_VARIATIONS_INDEX;
6457
0
    }
6458
0
  }
6459
6460
  bool is_variation_device () const
6461
0
  {
6462
0
    switch (u.b.format) {
6463
0
#ifndef HB_NO_VAR
6464
0
    case 0x8000:
6465
0
      return true;
6466
0
#endif
6467
0
    default:
6468
0
      return false;
6469
0
    }
6470
0
  }
6471
6472
  protected:
6473
  union {
6474
  DeviceHeader    b;
6475
  HintingDevice   hinting;
6476
#ifndef HB_NO_VAR
6477
  VariationDevice variation;
6478
#endif
6479
  } u;
6480
  public:
6481
  DEFINE_SIZE_UNION (6, b);
6482
};
6483
6484
6485
} /* namespace OT */
6486
6487
6488
#endif /* HB_OT_LAYOUT_COMMON_HH */