Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/workdir/UnpackedTarball/harfbuzz/src/hb-ot-cmap-table.hh
Line
Count
Source
1
/*
2
 * Copyright © 2014  Google, Inc.
3
 *
4
 *  This is part of HarfBuzz, a text shaping library.
5
 *
6
 * Permission is hereby granted, without written agreement and without
7
 * license or royalty fees, to use, copy, modify, and distribute this
8
 * software and its documentation for any purpose, provided that the
9
 * above copyright notice and the following two paragraphs appear in
10
 * all copies of this software.
11
 *
12
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16
 * DAMAGE.
17
 *
18
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23
 *
24
 * Google Author(s): Behdad Esfahbod
25
 */
26
27
#ifndef HB_OT_CMAP_TABLE_HH
28
#define HB_OT_CMAP_TABLE_HH
29
30
#include "hb-ot-os2-table.hh"
31
#include "hb-ot-shaper-arabic-pua.hh"
32
#include "hb-open-type.hh"
33
#include "hb-set.hh"
34
#include "hb-cache.hh"
35
36
/*
37
 * cmap -- Character to Glyph Index Mapping
38
 * https://docs.microsoft.com/en-us/typography/opentype/spec/cmap
39
 */
40
#define HB_OT_TAG_cmap HB_TAG('c','m','a','p')
41
42
namespace OT {
43
44
static inline uint8_t unicode_to_macroman (hb_codepoint_t u)
45
0
{
46
0
  static const struct unicode_to_macroman_t
47
0
  {
48
0
    uint16_t unicode;
49
0
    uint8_t macroman;
50
0
  }
51
0
  mapping[] =
52
0
  {
53
0
    { 0x00A0, 0xCA },
54
0
    { 0x00A1, 0xC1 },
55
0
    { 0x00A2, 0xA2 },
56
0
    { 0x00A3, 0xA3 },
57
0
    { 0x00A5, 0xB4 },
58
0
    { 0x00A7, 0xA4 },
59
0
    { 0x00A8, 0xAC },
60
0
    { 0x00A9, 0xA9 },
61
0
    { 0x00AA, 0xBB },
62
0
    { 0x00AB, 0xC7 },
63
0
    { 0x00AC, 0xC2 },
64
0
    { 0x00AE, 0xA8 },
65
0
    { 0x00AF, 0xF8 },
66
0
    { 0x00B0, 0xA1 },
67
0
    { 0x00B1, 0xB1 },
68
0
    { 0x00B4, 0xAB },
69
0
    { 0x00B5, 0xB5 },
70
0
    { 0x00B6, 0xA6 },
71
0
    { 0x00B7, 0xE1 },
72
0
    { 0x00B8, 0xFC },
73
0
    { 0x00BA, 0xBC },
74
0
    { 0x00BB, 0xC8 },
75
0
    { 0x00BF, 0xC0 },
76
0
    { 0x00C0, 0xCB },
77
0
    { 0x00C1, 0xE7 },
78
0
    { 0x00C2, 0xE5 },
79
0
    { 0x00C3, 0xCC },
80
0
    { 0x00C4, 0x80 },
81
0
    { 0x00C5, 0x81 },
82
0
    { 0x00C6, 0xAE },
83
0
    { 0x00C7, 0x82 },
84
0
    { 0x00C8, 0xE9 },
85
0
    { 0x00C9, 0x83 },
86
0
    { 0x00CA, 0xE6 },
87
0
    { 0x00CB, 0xE8 },
88
0
    { 0x00CC, 0xED },
89
0
    { 0x00CD, 0xEA },
90
0
    { 0x00CE, 0xEB },
91
0
    { 0x00CF, 0xEC },
92
0
    { 0x00D1, 0x84 },
93
0
    { 0x00D2, 0xF1 },
94
0
    { 0x00D3, 0xEE },
95
0
    { 0x00D4, 0xEF },
96
0
    { 0x00D5, 0xCD },
97
0
    { 0x00D6, 0x85 },
98
0
    { 0x00D8, 0xAF },
99
0
    { 0x00D9, 0xF4 },
100
0
    { 0x00DA, 0xF2 },
101
0
    { 0x00DB, 0xF3 },
102
0
    { 0x00DC, 0x86 },
103
0
    { 0x00DF, 0xA7 },
104
0
    { 0x00E0, 0x88 },
105
0
    { 0x00E1, 0x87 },
106
0
    { 0x00E2, 0x89 },
107
0
    { 0x00E3, 0x8B },
108
0
    { 0x00E4, 0x8A },
109
0
    { 0x00E5, 0x8C },
110
0
    { 0x00E6, 0xBE },
111
0
    { 0x00E7, 0x8D },
112
0
    { 0x00E8, 0x8F },
113
0
    { 0x00E9, 0x8E },
114
0
    { 0x00EA, 0x90 },
115
0
    { 0x00EB, 0x91 },
116
0
    { 0x00EC, 0x93 },
117
0
    { 0x00ED, 0x92 },
118
0
    { 0x00EE, 0x94 },
119
0
    { 0x00EF, 0x95 },
120
0
    { 0x00F1, 0x96 },
121
0
    { 0x00F2, 0x98 },
122
0
    { 0x00F3, 0x97 },
123
0
    { 0x00F4, 0x99 },
124
0
    { 0x00F5, 0x9B },
125
0
    { 0x00F6, 0x9A },
126
0
    { 0x00F7, 0xD6 },
127
0
    { 0x00F8, 0xBF },
128
0
    { 0x00F9, 0x9D },
129
0
    { 0x00FA, 0x9C },
130
0
    { 0x00FB, 0x9E },
131
0
    { 0x00FC, 0x9F },
132
0
    { 0x00FF, 0xD8 },
133
0
    { 0x0131, 0xF5 },
134
0
    { 0x0152, 0xCE },
135
0
    { 0x0153, 0xCF },
136
0
    { 0x0178, 0xD9 },
137
0
    { 0x0192, 0xC4 },
138
0
    { 0x02C6, 0xF6 },
139
0
    { 0x02C7, 0xFF },
140
0
    { 0x02D8, 0xF9 },
141
0
    { 0x02D9, 0xFA },
142
0
    { 0x02DA, 0xFB },
143
0
    { 0x02DB, 0xFE },
144
0
    { 0x02DC, 0xF7 },
145
0
    { 0x02DD, 0xFD },
146
0
    { 0x03A9, 0xBD },
147
0
    { 0x03C0, 0xB9 },
148
0
    { 0x2013, 0xD0 },
149
0
    { 0x2014, 0xD1 },
150
0
    { 0x2018, 0xD4 },
151
0
    { 0x2019, 0xD5 },
152
0
    { 0x201A, 0xE2 },
153
0
    { 0x201C, 0xD2 },
154
0
    { 0x201D, 0xD3 },
155
0
    { 0x201E, 0xE3 },
156
0
    { 0x2020, 0xA0 },
157
0
    { 0x2021, 0xE0 },
158
0
    { 0x2022, 0xA5 },
159
0
    { 0x2026, 0xC9 },
160
0
    { 0x2030, 0xE4 },
161
0
    { 0x2039, 0xDC },
162
0
    { 0x203A, 0xDD },
163
0
    { 0x2044, 0xDA },
164
0
    { 0x20AC, 0xDB },
165
0
    { 0x2122, 0xAA },
166
0
    { 0x2202, 0xB6 },
167
0
    { 0x2206, 0xC6 },
168
0
    { 0x220F, 0xB8 },
169
0
    { 0x2211, 0xB7 },
170
0
    { 0x221A, 0xC3 },
171
0
    { 0x221E, 0xB0 },
172
0
    { 0x222B, 0xBA },
173
0
    { 0x2248, 0xC5 },
174
0
    { 0x2260, 0xAD },
175
0
    { 0x2264, 0xB2 },
176
0
    { 0x2265, 0xB3 },
177
0
    { 0x25CA, 0xD7 },
178
0
    { 0xF8FF, 0xF0 },
179
0
    { 0xFB01, 0xDE },
180
0
    { 0xFB02, 0xDF },
181
0
  };
182
0
  auto *c = hb_bsearch (u, mapping, ARRAY_LENGTH (mapping), sizeof (mapping[0]),
183
0
      _hb_cmp_operator<uint16_t, uint16_t>);
184
0
  return c ? c->macroman : 0;
185
0
}
Unexecuted instantiation: hb-face.cc:OT::unicode_to_macroman(unsigned int)
Unexecuted instantiation: hb-ot-face.cc:OT::unicode_to_macroman(unsigned int)
Unexecuted instantiation: hb-ot-font.cc:OT::unicode_to_macroman(unsigned int)
Unexecuted instantiation: hb-static.cc:OT::unicode_to_macroman(unsigned int)
Unexecuted instantiation: hb-subset.cc:OT::unicode_to_macroman(unsigned int)
Unexecuted instantiation: hb-subset-plan.cc:OT::unicode_to_macroman(unsigned int)
Unexecuted instantiation: hb-subset-table-other.cc:OT::unicode_to_macroman(unsigned int)
186
187
struct CmapSubtableFormat0
188
{
189
  bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
190
0
  {
191
0
    hb_codepoint_t gid = codepoint < 256 ? glyphIdArray[codepoint] : 0;
192
0
    if (unlikely (!gid))
193
0
      return false;
194
0
    *glyph = gid;
195
0
    return true;
196
0
  }
197
198
  unsigned get_language () const
199
0
  {
200
0
    return language;
201
0
  }
202
203
  void collect_unicodes (hb_set_t *out) const
204
0
  {
205
0
    for (unsigned int i = 0; i < 256; i++)
206
0
      if (glyphIdArray[i])
207
0
  out->add (i);
208
0
  }
209
210
  void collect_mapping (hb_set_t *unicodes, /* OUT */
211
      hb_map_t *mapping /* OUT */) const
212
0
  {
213
0
    for (unsigned i = 0; i < 256; i++)
214
0
      if (glyphIdArray[i])
215
0
      {
216
0
  hb_codepoint_t glyph = glyphIdArray[i];
217
0
  unicodes->add (i);
218
0
  mapping->set (i, glyph);
219
0
      }
220
0
  }
221
222
  bool sanitize (hb_sanitize_context_t *c) const
223
0
  {
224
0
    TRACE_SANITIZE (this);
225
0
    return_trace (c->check_struct (this));
226
0
  }
227
228
  protected:
229
  HBUINT16  format;   /* Format number is set to 0. */
230
  HBUINT16  length;   /* Byte length of this subtable. */
231
  HBUINT16  language; /* Ignore. */
232
  HBUINT8 glyphIdArray[256];/* An array that maps character
233
         * code to glyph index values. */
234
  public:
235
  DEFINE_SIZE_STATIC (6 + 256);
236
};
237
238
struct CmapSubtableFormat4
239
{
240
  template<typename Iterator,
241
      typename Writer,
242
     hb_requires (hb_is_iterator (Iterator))>
243
  void to_ranges (Iterator it, Writer& range_writer)
244
0
  {
245
0
    hb_codepoint_t start_cp = 0, prev_run_start_cp = 0, run_start_cp = 0, end_cp = 0, last_gid = 0;
246
0
    int run_length = 0 , delta = 0, prev_delta = 0;
247
248
0
    enum {
249
0
      FIRST_SUB_RANGE,
250
0
      FOLLOWING_SUB_RANGE,
251
0
    } mode;
252
253
0
    while (it) {
254
      // Start a new range
255
0
      {
256
0
        const auto& pair = *it;
257
0
        start_cp = pair.first;
258
0
        prev_run_start_cp = start_cp;
259
0
        run_start_cp = start_cp;
260
0
        end_cp = start_cp;
261
0
        last_gid = pair.second;
262
0
        run_length = 1;
263
0
        prev_delta = 0;
264
0
      }
265
266
0
      delta = last_gid - start_cp;
267
0
      mode = FIRST_SUB_RANGE;
268
0
      it++;
269
270
0
      while (it) {
271
        // Process range
272
0
        const auto& pair = *it;
273
0
        hb_codepoint_t next_cp = pair.first;
274
0
        hb_codepoint_t next_gid = pair.second;
275
0
        if (next_cp != end_cp + 1) {
276
          // Current range is over, stop processing.
277
0
          break;
278
0
        }
279
280
0
        if (next_gid == last_gid + 1) {
281
          // The current run continues.
282
0
          end_cp = next_cp;
283
0
          run_length++;
284
0
          last_gid = next_gid;
285
0
          it++;
286
0
          continue;
287
0
        }
288
289
        // A new run is starting, decide if we want to commit the current run.
290
0
        int split_cost = (mode == FIRST_SUB_RANGE) ? 8 : 16;
291
0
        int run_cost = run_length * 2;
292
0
        if (run_cost >= split_cost) {
293
0
          commit_current_range(start_cp,
294
0
                               prev_run_start_cp,
295
0
                               run_start_cp,
296
0
                               end_cp,
297
0
                               delta,
298
0
                               prev_delta,
299
0
                               split_cost,
300
0
                               range_writer);
301
0
          start_cp = next_cp;
302
0
        }
303
304
        // Start the new run
305
0
        mode = FOLLOWING_SUB_RANGE;
306
0
        prev_run_start_cp = run_start_cp;
307
0
        run_start_cp = next_cp;
308
0
        end_cp = next_cp;
309
0
        prev_delta = delta;
310
0
        delta = next_gid - run_start_cp;
311
0
        run_length = 1;
312
0
        last_gid = next_gid;
313
0
        it++;
314
0
      }
315
316
      // Finalize range
317
0
      commit_current_range (start_cp,
318
0
                            prev_run_start_cp,
319
0
                            run_start_cp,
320
0
                            end_cp,
321
0
                            delta,
322
0
                            prev_delta,
323
0
                            8,
324
0
                            range_writer);
325
0
    }
326
327
0
    if (likely (end_cp != 0xFFFF)) {
328
0
      range_writer (0xFFFF, 0xFFFF, 1);
329
0
    }
330
0
  }
Unexecuted instantiation: _ZN2OT19CmapSubtableFormat49to_rangesI10hb_array_tIK9hb_pair_tIjjEEZNS0_23serialize_find_segcountIS6_TnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NS9_6item_tEEE5valueEvE4typeELPv0EEEjS9_E7CounterTnSD_LSE_0EEEvS9_RT0_
Unexecuted instantiation: _ZN2OT19CmapSubtableFormat49to_rangesI10hb_array_tIK9hb_pair_tIjjEEZNS0_32serialize_start_end_delta_arraysIS6_TnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NS9_6item_tEEE5valueEvE4typeELPv0EEEbP22hb_serialize_context_tS9_iE6WriterTnSD_LSE_0EEEvS9_RT0_
331
332
  /*
333
   * Writes the current range as either one or two ranges depending on what is most efficient.
334
   */
335
  template<typename Writer>
336
  void commit_current_range (hb_codepoint_t start,
337
                             hb_codepoint_t prev_run_start,
338
                             hb_codepoint_t run_start,
339
                             hb_codepoint_t end,
340
                             int run_delta,
341
                             int previous_run_delta,
342
                             int split_cost,
343
0
                             Writer& range_writer) {
344
0
    bool should_split = false;
345
0
    if (start < run_start && run_start < end) {
346
0
      int run_cost = (end - run_start + 1) * 2;
347
0
      if (run_cost >= split_cost) {
348
0
        should_split = true;
349
0
      }
350
0
    }
351
352
    // TODO(grieger): handle case where delta is legitimately 0, mark range offset array instead?
353
0
    if (should_split) {
354
0
      if (start == prev_run_start)
355
0
        range_writer (start, run_start - 1, previous_run_delta);
356
0
      else
357
0
        range_writer (start, run_start - 1, 0);
358
0
      range_writer (run_start, end, run_delta);
359
0
      return;
360
0
    }
361
362
363
0
    if (start == run_start) {
364
      // Range is only a run
365
0
      range_writer (start, end, run_delta);
366
0
      return;
367
0
    }
368
369
    // Write only a single non-run range.
370
0
    range_writer (start, end, 0);
371
0
  }
Unexecuted instantiation: _ZN2OT19CmapSubtableFormat420commit_current_rangeIZNS0_23serialize_find_segcountI10hb_array_tIK9hb_pair_tIjjEETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NS9_6item_tEEE5valueEvE4typeELPv0EEEjS9_E7CounterEEvjjjjiiiRS9_
Unexecuted instantiation: _ZN2OT19CmapSubtableFormat420commit_current_rangeIZNS0_32serialize_start_end_delta_arraysI10hb_array_tIK9hb_pair_tIjjEETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NS9_6item_tEEE5valueEvE4typeELPv0EEEbP22hb_serialize_context_tS9_iE6WriterEEvjjjjiiiRS9_
372
373
  template<typename Iterator,
374
     hb_requires (hb_is_iterator (Iterator))>
375
0
  unsigned serialize_find_segcount (Iterator it) {
376
0
    struct Counter {
377
0
      unsigned segcount = 0;
378
379
0
      void operator() (hb_codepoint_t start,
380
0
                       hb_codepoint_t end,
381
0
                       int delta) {
382
0
        segcount++;
383
0
      }
384
0
    } counter;
385
386
0
    to_ranges (+it, counter);
387
0
    return counter.segcount;
388
0
  }
389
390
391
  template<typename Iterator,
392
     hb_requires (hb_is_iterator (Iterator))>
393
  bool serialize_start_end_delta_arrays (hb_serialize_context_t *c,
394
                                         Iterator it,
395
                                         int segcount)
396
0
  {
397
0
    struct Writer {
398
0
      hb_serialize_context_t *serializer_;
399
0
      HBUINT16* end_code_;
400
0
      HBUINT16* start_code_;
401
0
      HBINT16* id_delta_;
402
0
      int index_;
403
404
0
      Writer(hb_serialize_context_t *serializer)
405
0
          : serializer_(serializer),
406
0
            end_code_(nullptr),
407
0
            start_code_(nullptr),
408
0
            id_delta_(nullptr),
409
0
            index_ (0) {}
410
0
      void operator() (hb_codepoint_t start,
411
0
                       hb_codepoint_t end,
412
0
                       int delta) {
413
0
        start_code_[index_] = start;
414
0
        end_code_[index_] = end;
415
0
        id_delta_[index_] = delta;
416
0
        index_++;
417
0
      }
418
0
    } writer(c);
419
420
0
    writer.end_code_ = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount, false);
421
0
    (void) c->allocate_size<HBUINT16> (2); // padding
422
0
    writer.start_code_ = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount, false);
423
0
    writer.id_delta_ = c->allocate_size<HBINT16> (HBINT16::static_size * segcount, false);
424
425
0
    if (unlikely (!writer.end_code_ || !writer.start_code_ || !writer.id_delta_)) return false;
426
427
0
    to_ranges (+it, writer);
428
0
    return true;
429
0
  }
430
431
  template<typename Iterator,
432
          hb_requires (hb_is_iterator (Iterator))>
433
  HBUINT16* serialize_rangeoffset_glyid (hb_serialize_context_t *c,
434
                                         Iterator it,
435
           HBUINT16 *endCode,
436
           HBUINT16 *startCode,
437
           HBINT16 *idDelta,
438
           unsigned segcount)
439
0
  {
440
0
    hb_map_t cp_to_gid { it };
441
442
0
    HBUINT16 *idRangeOffset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
443
0
    if (unlikely (!c->check_success (idRangeOffset))) return nullptr;
444
0
    if (unlikely ((char *)idRangeOffset - (char *)idDelta != (int) segcount * (int) HBINT16::static_size)) return nullptr;
445
446
0
    for (unsigned i : + hb_range (segcount)
447
0
          | hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; }))
448
0
    {
449
0
      idRangeOffset[i] = 2 * (c->start_embed<HBUINT16> () - idRangeOffset - i);
450
0
      for (hb_codepoint_t cp = startCode[i]; cp <= endCode[i]; cp++)
451
0
      {
452
0
        HBUINT16 gid;
453
0
        gid = cp_to_gid[cp];
454
0
        c->copy<HBUINT16> (gid);
455
0
      }
456
0
    }
457
458
0
    return idRangeOffset;
459
0
  }
460
461
  template<typename Iterator,
462
     hb_requires (hb_is_iterator (Iterator))>
463
  void serialize (hb_serialize_context_t *c,
464
      Iterator it)
465
0
  {
466
0
    auto format4_iter =
467
0
    + it
468
0
    | hb_filter ([&] (const hb_codepoint_pair_t _)
469
0
     { return _.first <= 0xFFFF; })
Unexecuted instantiation: hb-subset-table-other.cc:_ZZN2OT19CmapSubtableFormat49serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_9LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_ENKUlS5_E_clES5_
Unexecuted instantiation: hb-subset-table-other.cc:_ZZN2OT19CmapSubtableFormat49serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_ENKUlS5_E_clES5_
470
0
    ;
471
472
0
    if (!format4_iter) return;
473
474
0
    unsigned table_initpos = c->length ();
475
0
    if (unlikely (!c->extend_min (this))) return;
476
0
    this->format = 4;
477
478
0
    hb_vector_t<hb_codepoint_pair_t> cp_to_gid {
479
0
      format4_iter
480
0
    };
481
482
    //serialize endCode[], startCode[], idDelta[]
483
0
    HBUINT16* endCode = c->start_embed<HBUINT16> ();
484
0
    unsigned segcount = serialize_find_segcount (cp_to_gid.iter());
485
0
    if (unlikely (!serialize_start_end_delta_arrays (c, cp_to_gid.iter(), segcount)))
486
0
      return;
487
488
0
    HBUINT16 *startCode = endCode + segcount + 1;
489
0
    HBINT16 *idDelta = ((HBINT16*)startCode) + segcount;
490
491
0
    HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c,
492
0
                                                           cp_to_gid.iter (),
493
0
                                                           endCode,
494
0
                                                           startCode,
495
0
                                                           idDelta,
496
0
                                                           segcount);
497
0
    if (unlikely (!c->check_success (idRangeOffset))) return;
498
499
0
    this->length = c->length () - table_initpos;
500
0
    if ((long long) this->length != (long long) c->length () - table_initpos)
501
0
    {
502
0
      c->err (HB_SERIALIZE_ERROR_INT_OVERFLOW);
503
0
      return;
504
0
    }
505
506
0
    this->segCountX2 = segcount * 2;
507
0
    this->entrySelector = hb_max (1u, hb_bit_storage (segcount)) - 1;
508
0
    this->searchRange = 2 * (1u << this->entrySelector);
509
0
    this->rangeShift = segcount * 2 > this->searchRange
510
0
           ? 2 * segcount - this->searchRange
511
0
           : 0;
512
0
  }
Unexecuted instantiation: hb-face.cc:_ZN2OT19CmapSubtableFormat49serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_
Unexecuted instantiation: hb-face.cc:_ZN2OT19CmapSubtableFormat49serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_
Unexecuted instantiation: hb-ot-face.cc:_ZN2OT19CmapSubtableFormat49serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_
Unexecuted instantiation: hb-ot-face.cc:_ZN2OT19CmapSubtableFormat49serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_
Unexecuted instantiation: hb-ot-font.cc:_ZN2OT19CmapSubtableFormat49serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_
Unexecuted instantiation: hb-ot-font.cc:_ZN2OT19CmapSubtableFormat49serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_
Unexecuted instantiation: hb-static.cc:_ZN2OT19CmapSubtableFormat49serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_
Unexecuted instantiation: hb-static.cc:_ZN2OT19CmapSubtableFormat49serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_
Unexecuted instantiation: hb-subset.cc:_ZN2OT19CmapSubtableFormat49serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_9LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_
Unexecuted instantiation: hb-subset.cc:_ZN2OT19CmapSubtableFormat49serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_
Unexecuted instantiation: hb-subset-plan.cc:_ZN2OT19CmapSubtableFormat49serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_5LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_
Unexecuted instantiation: hb-subset-plan.cc:_ZN2OT19CmapSubtableFormat49serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_5LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_
Unexecuted instantiation: hb-subset-table-other.cc:_ZN2OT19CmapSubtableFormat49serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_9LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_
Unexecuted instantiation: hb-subset-table-other.cc:_ZN2OT19CmapSubtableFormat49serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_
513
514
  unsigned get_language () const
515
0
  {
516
0
    return language;
517
0
  }
518
519
  struct accelerator_t
520
  {
521
19.7k
    accelerator_t () {}
522
    accelerator_t (const CmapSubtableFormat4 *subtable) = delete;
523
524
    void init (const CmapSubtableFormat4 *subtable,
525
         unsigned int              subtable_data_size)
526
19.7k
    {
527
19.7k
      segCount = subtable->segCountX2 / 2;
528
19.7k
      endCount = subtable->values.arrayZ;
529
19.7k
      startCount = endCount + segCount + 1;
530
19.7k
      idDelta = startCount + segCount;
531
19.7k
      idRangeOffset = idDelta + segCount;
532
19.7k
      glyphIdArray = idRangeOffset + segCount;
533
534
19.7k
      unsigned int values_offset = 16 + 8 * segCount;
535
19.7k
      glyphIdArrayLength = subtable_data_size > values_offset
536
19.7k
         ? (subtable_data_size - values_offset) / 2
537
19.7k
         : 0;
538
19.7k
    }
539
540
    bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
541
59.7M
    {
542
59.7M
      struct CustomRange
543
59.7M
      {
544
59.7M
  int cmp (hb_codepoint_t k,
545
59.7M
     unsigned distance) const
546
417M
  {
547
417M
    if (k > last) return +1;
548
162M
    if (k < (&last)[distance]/*first*/) return -1;
549
1.46M
    return 0;
550
162M
  }
551
59.7M
  HBUINT16 last;
552
59.7M
      };
553
554
59.7M
      const HBUINT16 *found = hb_bsearch (codepoint,
555
59.7M
            this->endCount,
556
59.7M
            this->segCount,
557
59.7M
            sizeof (CustomRange),
558
59.7M
            _hb_cmp_method<hb_codepoint_t, CustomRange, unsigned>,
559
59.7M
            this->segCount + 1);
560
59.7M
      if (unlikely (!found))
561
58.2M
  return false;
562
1.46M
      unsigned int i = found - endCount;
563
564
1.46M
      hb_codepoint_t gid;
565
1.46M
      unsigned int rangeOffset = this->idRangeOffset[i];
566
1.46M
      if (rangeOffset == 0)
567
1.46M
  gid = codepoint + this->idDelta[i];
568
0
      else
569
0
      {
570
  /* Somebody has been smoking... */
571
0
  unsigned int index = rangeOffset / 2 + (codepoint - this->startCount[i]) + i - this->segCount;
572
0
  if (unlikely (index >= this->glyphIdArrayLength))
573
0
    return false;
574
0
  gid = this->glyphIdArray[index];
575
0
  if (unlikely (!gid))
576
0
    return false;
577
0
  gid += this->idDelta[i];
578
0
      }
579
1.46M
      gid &= 0xFFFFu;
580
1.46M
      if (unlikely (!gid))
581
0
  return false;
582
1.46M
      *glyph = gid;
583
1.46M
      return true;
584
1.46M
    }
585
586
    HB_INTERNAL static bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
587
59.7M
    { return ((const accelerator_t *) obj)->get_glyph (codepoint, glyph); }
588
589
    void collect_unicodes (hb_set_t *out) const
590
5
    {
591
5
      unsigned int count = this->segCount;
592
5
      if (count && this->startCount[count - 1] == 0xFFFFu)
593
5
  count--; /* Skip sentinel segment. */
594
630
      for (unsigned int i = 0; i < count; i++)
595
625
      {
596
625
  hb_codepoint_t start = this->startCount[i];
597
625
  hb_codepoint_t end = this->endCount[i];
598
625
  unsigned int rangeOffset = this->idRangeOffset[i];
599
625
        out->add_range(start, end);
600
625
  if (rangeOffset == 0)
601
625
  {
602
12.2k
    for (hb_codepoint_t codepoint = start; codepoint <= end; codepoint++)
603
11.6k
    {
604
11.6k
      hb_codepoint_t gid = (codepoint + this->idDelta[i]) & 0xFFFFu;
605
11.6k
      if (unlikely (!gid))
606
0
              out->del(codepoint);
607
11.6k
    }
608
625
  }
609
0
  else
610
0
  {
611
0
    for (hb_codepoint_t codepoint = start; codepoint <= end; codepoint++)
612
0
    {
613
0
      unsigned int index = rangeOffset / 2 + (codepoint - this->startCount[i]) + i - this->segCount;
614
0
      if (unlikely (index >= this->glyphIdArrayLength))
615
0
            {
616
0
              out->del_range (codepoint, end);
617
0
        break;
618
0
            }
619
0
      hb_codepoint_t gid = this->glyphIdArray[index];
620
0
      if (unlikely (!gid))
621
0
              out->del(codepoint);
622
0
    }
623
0
  }
624
625
      }
625
5
    }
626
627
    void collect_mapping (hb_set_t *unicodes, /* OUT */
628
        hb_map_t *mapping /* OUT */) const
629
6.57k
    {
630
      // TODO(grieger): optimize similar to collect_unicodes
631
      // (ie. use add_range())
632
6.57k
      unsigned count = this->segCount;
633
6.57k
      if (count && this->startCount[count - 1] == 0xFFFFu)
634
6.57k
  count--; /* Skip sentinel segment. */
635
827k
      for (unsigned i = 0; i < count; i++)
636
821k
      {
637
821k
  hb_codepoint_t start = this->startCount[i];
638
821k
  hb_codepoint_t end = this->endCount[i];
639
821k
  unsigned rangeOffset = this->idRangeOffset[i];
640
821k
  if (rangeOffset == 0)
641
821k
  {
642
16.1M
    for (hb_codepoint_t codepoint = start; codepoint <= end; codepoint++)
643
15.2M
    {
644
15.2M
      hb_codepoint_t gid = (codepoint + this->idDelta[i]) & 0xFFFFu;
645
15.2M
      if (unlikely (!gid))
646
0
        continue;
647
15.2M
      unicodes->add (codepoint);
648
15.2M
      mapping->set (codepoint, gid);
649
15.2M
    }
650
821k
  }
651
0
  else
652
0
  {
653
0
    for (hb_codepoint_t codepoint = start; codepoint <= end; codepoint++)
654
0
    {
655
0
      unsigned index = rangeOffset / 2 + (codepoint - this->startCount[i]) + i - this->segCount;
656
0
      if (unlikely (index >= this->glyphIdArrayLength))
657
0
        break;
658
0
      hb_codepoint_t gid = this->glyphIdArray[index];
659
0
      if (unlikely (!gid))
660
0
        continue;
661
0
      unicodes->add (codepoint);
662
0
      mapping->set (codepoint, gid);
663
0
    }
664
0
  }
665
821k
      }
666
6.57k
    }
667
668
    const HBUINT16 *endCount;
669
    const HBUINT16 *startCount;
670
    const HBUINT16 *idDelta;
671
    const HBUINT16 *idRangeOffset;
672
    const HBUINT16 *glyphIdArray;
673
    unsigned int segCount;
674
    unsigned int glyphIdArrayLength;
675
  };
676
677
  bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph,
678
      unsigned int subtable_data_size) const
679
0
  {
680
0
    accelerator_t accel;
681
0
    accel.init (this, subtable_data_size);
682
0
    return accel.get_glyph_func (&accel, codepoint, glyph);
683
0
  }
684
  bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
685
0
  { return false; }
686
687
  void collect_unicodes (hb_set_t *out, unsigned int subtable_data_size) const
688
5
  {
689
5
    accelerator_t accel;
690
5
    accel.init (this, subtable_data_size);
691
5
    accel.collect_unicodes (out);
692
5
  }
693
  void collect_unicodes (hb_set_t *out) const
694
0
  { collect_unicodes (out, length); }
695
696
  void collect_mapping (hb_set_t *unicodes, /* OUT */
697
      hb_map_t *mapping, /* OUT */
698
      unsigned int subtable_data_size) const
699
6.57k
  {
700
6.57k
    accelerator_t accel;
701
6.57k
    accel.init (this, subtable_data_size);
702
6.57k
    accel.collect_mapping (unicodes, mapping);
703
6.57k
  }
704
  void collect_mapping (hb_set_t *unicodes, /* OUT */
705
      hb_map_t *mapping /* OUT */) const
706
0
  { collect_mapping (unicodes, mapping, length); }
707
708
  bool sanitize (hb_sanitize_context_t *c) const
709
26.4k
  {
710
26.4k
    TRACE_SANITIZE (this);
711
26.4k
    if (unlikely (!c->check_struct (this)))
712
0
      return_trace (false);
713
26.4k
    hb_barrier ();
714
715
26.4k
    return_trace (c->check_range (values, 2 + 4 * segCountX2));
716
26.4k
  }
717
718
  protected:
719
  HBUINT16  format;   /* Format number is set to 4. */
720
  HBUINT16  length;   /* This is the length in bytes of the
721
         * subtable. */
722
  HBUINT16  language; /* Ignore. */
723
  HBUINT16  segCountX2; /* 2 x segCount. */
724
  HBUINT16  searchRange;  /* 2 * (2**floor(log2(segCount))) */
725
  HBUINT16  entrySelector;  /* log2(searchRange/2) */
726
  HBUINT16  rangeShift; /* 2 x segCount - searchRange */
727
728
  UnsizedArrayOf<HBUINT16>
729
    values;
730
#if 0
731
  HBUINT16  endCount[segCount]; /* End characterCode for each segment,
732
           * last=0xFFFFu. */
733
  HBUINT16  reservedPad;    /* Set to 0. */
734
  HBUINT16  startCount[segCount]; /* Start character code for each segment. */
735
  HBINT16   idDelta[segCount];  /* Delta for all character codes in segment. */
736
  HBUINT16  idRangeOffset[segCount];/* Offsets into glyphIdArray or 0 */
737
  UnsizedArrayOf<HBUINT16>
738
    glyphIdArray; /* Glyph index array (arbitrary length) */
739
#endif
740
741
  public:
742
  DEFINE_SIZE_ARRAY (14, values);
743
};
744
745
struct CmapSubtableLongGroup
746
{
747
  friend struct CmapSubtableFormat12;
748
  friend struct CmapSubtableFormat13;
749
  template<typename U>
750
  friend struct CmapSubtableLongSegmented;
751
  friend struct cmap;
752
753
  int cmp (hb_codepoint_t codepoint) const
754
0
  {
755
0
    if (codepoint < startCharCode) return -1;
756
0
    if (codepoint > endCharCode)   return +1;
757
0
    return 0;
758
0
  }
759
760
  bool sanitize (hb_sanitize_context_t *c) const
761
0
  {
762
0
    TRACE_SANITIZE (this);
763
0
    return_trace (c->check_struct (this));
764
0
  }
765
766
  private:
767
  HBUINT32    startCharCode;  /* First character code in this group. */
768
  HBUINT32    endCharCode;  /* Last character code in this group. */
769
  HBUINT32    glyphID;  /* Glyph index; interpretation depends on
770
           * subtable format. */
771
  public:
772
  DEFINE_SIZE_STATIC (12);
773
};
774
DECLARE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup);
775
776
template <typename UINT>
777
struct CmapSubtableTrimmed
778
{
779
  bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
780
0
  {
781
    /* Rely on our implicit array bound-checking. */
782
0
    hb_codepoint_t gid = glyphIdArray[codepoint - startCharCode];
783
0
    if (unlikely (!gid))
784
0
      return false;
785
0
    *glyph = gid;
786
0
    return true;
787
0
  }
Unexecuted instantiation: OT::CmapSubtableTrimmed<OT::NumType<true, unsigned short, 2u> >::get_glyph(unsigned int, unsigned int*) const
Unexecuted instantiation: OT::CmapSubtableTrimmed<OT::NumType<true, unsigned int, 4u> >::get_glyph(unsigned int, unsigned int*) const
788
789
  unsigned get_language () const
790
0
  {
791
0
    return language;
792
0
  }
Unexecuted instantiation: OT::CmapSubtableTrimmed<OT::NumType<true, unsigned short, 2u> >::get_language() const
Unexecuted instantiation: OT::CmapSubtableTrimmed<OT::NumType<true, unsigned int, 4u> >::get_language() const
793
794
  void collect_unicodes (hb_set_t *out) const
795
0
  {
796
0
    hb_codepoint_t start = startCharCode;
797
0
    unsigned int count = glyphIdArray.len;
798
0
    for (unsigned int i = 0; i < count; i++)
799
0
      if (glyphIdArray[i])
800
0
  out->add (start + i);
801
0
  }
Unexecuted instantiation: OT::CmapSubtableTrimmed<OT::NumType<true, unsigned short, 2u> >::collect_unicodes(hb_set_t*) const
Unexecuted instantiation: OT::CmapSubtableTrimmed<OT::NumType<true, unsigned int, 4u> >::collect_unicodes(hb_set_t*) const
802
803
  void collect_mapping (hb_set_t *unicodes, /* OUT */
804
      hb_map_t *mapping /* OUT */) const
805
0
  {
806
0
    hb_codepoint_t start_cp = startCharCode;
807
0
    unsigned count = glyphIdArray.len;
808
0
    for (unsigned i = 0; i < count; i++)
809
0
      if (glyphIdArray[i])
810
0
      {
811
0
  hb_codepoint_t unicode = start_cp + i;
812
0
  hb_codepoint_t glyphid = glyphIdArray[i];
813
0
  unicodes->add (unicode);
814
0
  mapping->set (unicode, glyphid);
815
0
      }
816
0
  }
Unexecuted instantiation: OT::CmapSubtableTrimmed<OT::NumType<true, unsigned short, 2u> >::collect_mapping(hb_set_t*, hb_map_t*) const
Unexecuted instantiation: OT::CmapSubtableTrimmed<OT::NumType<true, unsigned int, 4u> >::collect_mapping(hb_set_t*, hb_map_t*) const
817
818
  bool sanitize (hb_sanitize_context_t *c) const
819
13.2k
  {
820
13.2k
    TRACE_SANITIZE (this);
821
13.2k
    return_trace (c->check_struct (this) && glyphIdArray.sanitize (c));
822
13.2k
  }
OT::CmapSubtableTrimmed<OT::NumType<true, unsigned short, 2u> >::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
819
13.2k
  {
820
13.2k
    TRACE_SANITIZE (this);
821
13.2k
    return_trace (c->check_struct (this) && glyphIdArray.sanitize (c));
822
13.2k
  }
Unexecuted instantiation: OT::CmapSubtableTrimmed<OT::NumType<true, unsigned int, 4u> >::sanitize(hb_sanitize_context_t*) const
823
824
  protected:
825
  UINT    formatReserved; /* Subtable format and (maybe) padding. */
826
  UINT    length;   /* Byte length of this subtable. */
827
  UINT    language; /* Ignore. */
828
  UINT    startCharCode;  /* First character code covered. */
829
  ArrayOf<HBGlyphID16, UINT>
830
    glyphIdArray; /* Array of glyph index values for character
831
         * codes in the range. */
832
  public:
833
  DEFINE_SIZE_ARRAY (5 * sizeof (UINT), glyphIdArray);
834
};
835
836
struct CmapSubtableFormat6  : CmapSubtableTrimmed<HBUINT16> {};
837
struct CmapSubtableFormat10 : CmapSubtableTrimmed<HBUINT32> {};
838
839
template <typename T>
840
struct CmapSubtableLongSegmented
841
{
842
  friend struct cmap;
843
844
  bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
845
0
  {
846
0
    hb_codepoint_t gid = T::group_get_glyph (groups.bsearch (codepoint), codepoint);
847
0
    if (unlikely (!gid))
848
0
      return false;
849
0
    *glyph = gid;
850
0
    return true;
851
0
  }
Unexecuted instantiation: OT::CmapSubtableLongSegmented<OT::CmapSubtableFormat12>::get_glyph(unsigned int, unsigned int*) const
Unexecuted instantiation: OT::CmapSubtableLongSegmented<OT::CmapSubtableFormat13>::get_glyph(unsigned int, unsigned int*) const
852
853
  unsigned get_language () const
854
0
  {
855
0
    return language;
856
0
  }
Unexecuted instantiation: OT::CmapSubtableLongSegmented<OT::CmapSubtableFormat12>::get_language() const
Unexecuted instantiation: OT::CmapSubtableLongSegmented<OT::CmapSubtableFormat13>::get_language() const
857
858
  void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const
859
0
  {
860
0
    for (unsigned int i = 0; i < this->groups.len; i++)
861
0
    {
862
0
      hb_codepoint_t start = this->groups[i].startCharCode;
863
0
      hb_codepoint_t end = hb_min ((hb_codepoint_t) this->groups[i].endCharCode,
864
0
           (hb_codepoint_t) HB_UNICODE_MAX);
865
0
      hb_codepoint_t gid = this->groups[i].glyphID;
866
0
      if (!gid)
867
0
      {
868
  /* Intention is: if (hb_is_same (T, CmapSubtableFormat13)) continue; */
869
0
  if (! T::group_get_glyph (this->groups[i], end)) continue;
870
0
  start++;
871
0
  gid++;
872
0
      }
873
0
      if (unlikely ((unsigned int) gid >= num_glyphs)) continue;
874
0
      if (unlikely ((unsigned int) (gid + end - start) >= num_glyphs))
875
0
  end = start + (hb_codepoint_t) num_glyphs - gid;
876
877
0
      out->add_range (start, hb_min (end, 0x10FFFFu));
878
0
    }
879
0
  }
Unexecuted instantiation: OT::CmapSubtableLongSegmented<OT::CmapSubtableFormat12>::collect_unicodes(hb_set_t*, unsigned int) const
Unexecuted instantiation: OT::CmapSubtableLongSegmented<OT::CmapSubtableFormat13>::collect_unicodes(hb_set_t*, unsigned int) const
880
881
  void collect_mapping (hb_set_t *unicodes, /* OUT */
882
      hb_map_t *mapping, /* OUT */
883
      unsigned num_glyphs) const
884
0
  {
885
0
    hb_codepoint_t last_end = 0;
886
0
    unsigned count = this->groups.len;
887
0
    for (unsigned i = 0; i < count; i++)
888
0
    {
889
0
      hb_codepoint_t start = this->groups.arrayZ[i].startCharCode;
890
0
      hb_codepoint_t end = hb_min ((hb_codepoint_t) this->groups.arrayZ[i].endCharCode,
891
0
           (hb_codepoint_t) HB_UNICODE_MAX);
892
0
      if (unlikely (start > end || start < last_end)) {
893
        // Range is not in order and is invalid, skip it.
894
0
        continue;
895
0
      }
896
0
      last_end = end;
897
898
899
0
      hb_codepoint_t gid = this->groups.arrayZ[i].glyphID;
900
0
      if (!gid)
901
0
      {
902
0
        if (T::formatNumber == 13) continue;
903
0
  start++;
904
0
  gid++;
905
0
      }
906
0
      if (unlikely ((unsigned int) gid >= num_glyphs)) continue;
907
0
      if (unlikely ((unsigned int) (gid + end - start) >= num_glyphs))
908
0
  end = start + (hb_codepoint_t) num_glyphs - gid;
909
910
0
      mapping->alloc (mapping->get_population () + end - start + 1);
911
912
0
      unicodes->add_range (start, end);
913
0
      for (unsigned cp = start; cp <= end; cp++)
914
0
      {
915
0
  mapping->set (cp, gid);
916
0
        gid += T::increment;
917
0
      }
918
0
    }
919
0
  }
Unexecuted instantiation: OT::CmapSubtableLongSegmented<OT::CmapSubtableFormat12>::collect_mapping(hb_set_t*, hb_map_t*, unsigned int) const
Unexecuted instantiation: OT::CmapSubtableLongSegmented<OT::CmapSubtableFormat13>::collect_mapping(hb_set_t*, hb_map_t*, unsigned int) const
920
921
  bool sanitize (hb_sanitize_context_t *c) const
922
0
  {
923
0
    TRACE_SANITIZE (this);
924
0
    return_trace (c->check_struct (this) && groups.sanitize (c));
925
0
  }
Unexecuted instantiation: OT::CmapSubtableLongSegmented<OT::CmapSubtableFormat12>::sanitize(hb_sanitize_context_t*) const
Unexecuted instantiation: OT::CmapSubtableLongSegmented<OT::CmapSubtableFormat13>::sanitize(hb_sanitize_context_t*) const
926
927
  protected:
928
  HBUINT16  format;   /* Subtable format; set to 12. */
929
  HBUINT16  reserved; /* Reserved; set to 0. */
930
  HBUINT32  length;   /* Byte length of this subtable. */
931
  HBUINT32  language; /* Ignore. */
932
  SortedArray32Of<CmapSubtableLongGroup>
933
    groups;   /* Groupings. */
934
  public:
935
  DEFINE_SIZE_ARRAY (16, groups);
936
};
937
938
struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
939
{
940
  static constexpr int increment = 1;
941
  static constexpr int formatNumber = 12;
942
943
  static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
944
           hb_codepoint_t u)
945
0
  { return likely (group.startCharCode <= group.endCharCode) ?
946
0
     group.glyphID + (u - group.startCharCode) : 0; }
947
948
949
  template<typename Iterator,
950
     hb_requires (hb_is_iterator (Iterator))>
951
  void serialize (hb_serialize_context_t *c,
952
      Iterator it)
953
0
  {
954
0
    if (!it) return;
955
0
    unsigned table_initpos = c->length ();
956
0
    if (unlikely (!c->extend_min (this))) return;
957
958
0
    hb_codepoint_t startCharCode = (hb_codepoint_t) -1, endCharCode = (hb_codepoint_t) -1;
959
0
    hb_codepoint_t glyphID = 0;
960
961
0
    for (const auto& _ : +it)
962
0
    {
963
0
      if (startCharCode == (hb_codepoint_t) -1)
964
0
      {
965
0
  startCharCode = _.first;
966
0
  endCharCode = _.first;
967
0
  glyphID = _.second;
968
0
      }
969
0
      else if (!_is_gid_consecutive (endCharCode, startCharCode, glyphID, _.first, _.second))
970
0
      {
971
0
  CmapSubtableLongGroup  grouprecord;
972
0
  grouprecord.startCharCode = startCharCode;
973
0
  grouprecord.endCharCode = endCharCode;
974
0
  grouprecord.glyphID = glyphID;
975
0
  c->copy<CmapSubtableLongGroup> (grouprecord);
976
977
0
  startCharCode = _.first;
978
0
  endCharCode = _.first;
979
0
  glyphID = _.second;
980
0
      }
981
0
      else
982
0
  endCharCode = _.first;
983
0
    }
984
985
0
    CmapSubtableLongGroup record;
986
0
    record.startCharCode = startCharCode;
987
0
    record.endCharCode = endCharCode;
988
0
    record.glyphID = glyphID;
989
0
    c->copy<CmapSubtableLongGroup> (record);
990
991
0
    this->format = 12;
992
0
    this->reserved = 0;
993
0
    this->length = c->length () - table_initpos;
994
0
    this->groups.len = (this->length - min_size) / CmapSubtableLongGroup::static_size;
995
0
  }
Unexecuted instantiation: hb-face.cc:_ZN2OT20CmapSubtableFormat129serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_
Unexecuted instantiation: hb-face.cc:_ZN2OT20CmapSubtableFormat129serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_
Unexecuted instantiation: hb-ot-face.cc:_ZN2OT20CmapSubtableFormat129serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_
Unexecuted instantiation: hb-ot-face.cc:_ZN2OT20CmapSubtableFormat129serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_
Unexecuted instantiation: hb-ot-font.cc:_ZN2OT20CmapSubtableFormat129serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_
Unexecuted instantiation: hb-ot-font.cc:_ZN2OT20CmapSubtableFormat129serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_
Unexecuted instantiation: hb-static.cc:_ZN2OT20CmapSubtableFormat129serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_
Unexecuted instantiation: hb-static.cc:_ZN2OT20CmapSubtableFormat129serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_
Unexecuted instantiation: hb-subset.cc:_ZN2OT20CmapSubtableFormat129serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_9LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_
Unexecuted instantiation: hb-subset.cc:_ZN2OT20CmapSubtableFormat129serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_
Unexecuted instantiation: hb-subset-plan.cc:_ZN2OT20CmapSubtableFormat129serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_5LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_
Unexecuted instantiation: hb-subset-plan.cc:_ZN2OT20CmapSubtableFormat129serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_5LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_
Unexecuted instantiation: hb-subset-table-other.cc:_ZN2OT20CmapSubtableFormat129serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_9LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_
Unexecuted instantiation: hb-subset-table-other.cc:_ZN2OT20CmapSubtableFormat129serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_
996
997
  static size_t get_sub_table_size (const hb_sorted_vector_t<CmapSubtableLongGroup> &groups_data)
998
0
  { return 16 + 12 * groups_data.length; }
999
1000
  private:
1001
  static bool _is_gid_consecutive (hb_codepoint_t endCharCode,
1002
           hb_codepoint_t startCharCode,
1003
           hb_codepoint_t glyphID,
1004
           hb_codepoint_t cp,
1005
           hb_codepoint_t new_gid)
1006
0
  {
1007
0
    return (cp - 1 == endCharCode) &&
1008
0
  new_gid == glyphID + (cp - startCharCode);
1009
0
  }
1010
1011
};
1012
1013
struct CmapSubtableFormat13 : CmapSubtableLongSegmented<CmapSubtableFormat13>
1014
{
1015
  static constexpr int increment = 0;
1016
  static constexpr int formatNumber = 13;
1017
1018
  static hb_codepoint_t group_get_glyph (const CmapSubtableLongGroup &group,
1019
           hb_codepoint_t u HB_UNUSED)
1020
0
  { return group.glyphID; }
1021
};
1022
1023
typedef enum
1024
{
1025
  GLYPH_VARIANT_NOT_FOUND = 0,
1026
  GLYPH_VARIANT_FOUND = 1,
1027
  GLYPH_VARIANT_USE_DEFAULT = 2
1028
} glyph_variant_t;
1029
1030
struct UnicodeValueRange
1031
{
1032
  int cmp (const hb_codepoint_t &codepoint) const
1033
0
  {
1034
0
    if (codepoint < startUnicodeValue) return -1;
1035
0
    if (codepoint > startUnicodeValue + additionalCount) return +1;
1036
0
    return 0;
1037
0
  }
1038
1039
  bool sanitize (hb_sanitize_context_t *c) const
1040
0
  {
1041
0
    TRACE_SANITIZE (this);
1042
0
    return_trace (c->check_struct (this));
1043
0
  }
1044
1045
  HBUINT24  startUnicodeValue;  /* First value in this range. */
1046
  HBUINT8 additionalCount;  /* Number of additional values in this
1047
           * range. */
1048
  public:
1049
  DEFINE_SIZE_STATIC (4);
1050
};
1051
1052
struct DefaultUVS : SortedArray32Of<UnicodeValueRange>
1053
{
1054
  void collect_unicodes (hb_set_t *out) const
1055
0
  {
1056
0
    unsigned int count = len;
1057
0
    for (unsigned int i = 0; i < count; i++)
1058
0
    {
1059
0
      hb_codepoint_t first = arrayZ[i].startUnicodeValue;
1060
0
      hb_codepoint_t last = hb_min ((hb_codepoint_t) (first + arrayZ[i].additionalCount),
1061
0
            (hb_codepoint_t) HB_UNICODE_MAX);
1062
0
      out->add_range (first, last);
1063
0
    }
1064
0
  }
1065
1066
  DefaultUVS* copy (hb_serialize_context_t *c,
1067
        const hb_set_t *unicodes) const
1068
0
  {
1069
0
    auto *out = c->start_embed<DefaultUVS> ();
1070
0
    auto snap = c->snapshot ();
1071
1072
0
    HBUINT32 len;
1073
0
    len = 0;
1074
0
    if (unlikely (!c->copy<HBUINT32> (len))) return nullptr;
1075
0
    unsigned init_len = c->length ();
1076
1077
0
    if (this->len > unicodes->get_population () * hb_bit_storage ((unsigned) this->len))
1078
0
    {
1079
0
      hb_codepoint_t start = HB_SET_VALUE_INVALID;
1080
0
      hb_codepoint_t end = HB_SET_VALUE_INVALID;
1081
1082
0
      for (auto u : *unicodes)
1083
0
      {
1084
0
        if (!as_array ().bsearch (u))
1085
0
    continue;
1086
0
  if (start == HB_SET_VALUE_INVALID)
1087
0
  {
1088
0
    start = u;
1089
0
    end = start - 1;
1090
0
  }
1091
0
  if (end + 1 != u || end - start == 255)
1092
0
        {
1093
0
    UnicodeValueRange rec;
1094
0
    rec.startUnicodeValue = start;
1095
0
    rec.additionalCount = end - start;
1096
0
    c->copy<UnicodeValueRange> (rec);
1097
0
    start = u;
1098
0
  }
1099
0
  end = u;
1100
0
      }
1101
0
      if (start != HB_SET_VALUE_INVALID)
1102
0
      {
1103
0
  UnicodeValueRange rec;
1104
0
  rec.startUnicodeValue = start;
1105
0
  rec.additionalCount = end - start;
1106
0
  c->copy<UnicodeValueRange> (rec);
1107
0
      }
1108
1109
0
    }
1110
0
    else
1111
0
    {
1112
0
      hb_codepoint_t lastCode = HB_SET_VALUE_INVALID;
1113
0
      int count = -1;
1114
1115
0
      for (const UnicodeValueRange& _ : *this)
1116
0
      {
1117
0
  hb_codepoint_t curEntry = (hb_codepoint_t) (_.startUnicodeValue - 1);
1118
0
  hb_codepoint_t end = curEntry + _.additionalCount + 2;
1119
1120
0
  for (; unicodes->next (&curEntry) && curEntry < end;)
1121
0
  {
1122
0
    count += 1;
1123
0
    if (lastCode == HB_SET_VALUE_INVALID)
1124
0
      lastCode = curEntry;
1125
0
    else if (lastCode + count != curEntry)
1126
0
    {
1127
0
      UnicodeValueRange rec;
1128
0
      rec.startUnicodeValue = lastCode;
1129
0
      rec.additionalCount = count - 1;
1130
0
      c->copy<UnicodeValueRange> (rec);
1131
1132
0
      lastCode = curEntry;
1133
0
      count = 0;
1134
0
    }
1135
0
  }
1136
0
      }
1137
1138
0
      if (lastCode != HB_MAP_VALUE_INVALID)
1139
0
      {
1140
0
  UnicodeValueRange rec;
1141
0
  rec.startUnicodeValue = lastCode;
1142
0
  rec.additionalCount = count;
1143
0
  c->copy<UnicodeValueRange> (rec);
1144
0
      }
1145
0
    }
1146
1147
0
    if (c->length () - init_len == 0)
1148
0
    {
1149
0
      c->revert (snap);
1150
0
      return nullptr;
1151
0
    }
1152
0
    else
1153
0
    {
1154
0
      if (unlikely (!c->check_assign (out->len,
1155
0
                                      (c->length () - init_len) / UnicodeValueRange::static_size,
1156
0
                                      HB_SERIALIZE_ERROR_INT_OVERFLOW))) return nullptr;
1157
0
      return out;
1158
0
    }
1159
0
  }
1160
1161
  public:
1162
  DEFINE_SIZE_ARRAY (4, *this);
1163
};
1164
1165
struct UVSMapping
1166
{
1167
  int cmp (const hb_codepoint_t &codepoint) const
1168
0
  { return unicodeValue.cmp (codepoint); }
1169
1170
  bool sanitize (hb_sanitize_context_t *c) const
1171
0
  {
1172
0
    TRACE_SANITIZE (this);
1173
0
    return_trace (c->check_struct (this));
1174
0
  }
1175
1176
  HBUINT24  unicodeValue; /* Base Unicode value of the UVS */
1177
  HBGlyphID16 glyphID;  /* Glyph ID of the UVS */
1178
  public:
1179
  DEFINE_SIZE_STATIC (5);
1180
};
1181
1182
struct NonDefaultUVS : SortedArray32Of<UVSMapping>
1183
{
1184
  void collect_unicodes (hb_set_t *out) const
1185
0
  {
1186
0
    for (const auto& a : as_array ())
1187
0
      out->add (a.unicodeValue);
1188
0
  }
1189
1190
  void collect_mapping (hb_set_t *unicodes, /* OUT */
1191
      hb_map_t *mapping /* OUT */) const
1192
0
  {
1193
0
    for (const auto& a : as_array ())
1194
0
    {
1195
0
      hb_codepoint_t unicode = a.unicodeValue;
1196
0
      hb_codepoint_t glyphid = a.glyphID;
1197
0
      unicodes->add (unicode);
1198
0
      mapping->set (unicode, glyphid);
1199
0
    }
1200
0
  }
1201
1202
  void closure_glyphs (const hb_set_t      *unicodes,
1203
           hb_set_t            *glyphset) const
1204
0
  {
1205
0
    + as_array ()
1206
0
    | hb_filter (unicodes, &UVSMapping::unicodeValue)
1207
0
    | hb_map (&UVSMapping::glyphID)
1208
0
    | hb_sink (glyphset)
1209
0
    ;
1210
0
  }
1211
1212
  NonDefaultUVS* copy (hb_serialize_context_t *c,
1213
           const hb_set_t *unicodes,
1214
           const hb_set_t *glyphs_requested,
1215
           const hb_map_t *glyph_map) const
1216
0
  {
1217
0
    auto *out = c->start_embed<NonDefaultUVS> ();
1218
0
    auto it =
1219
0
    + as_array ()
1220
0
    | hb_filter ([&] (const UVSMapping& _)
1221
0
     {
1222
0
       return unicodes->has (_.unicodeValue) || glyphs_requested->has (_.glyphID);
1223
0
     })
1224
0
    ;
1225
1226
0
    if (!it) return nullptr;
1227
1228
0
    HBUINT32 len;
1229
0
    len = it.len ();
1230
0
    if (unlikely (!c->copy<HBUINT32> (len))) return nullptr;
1231
1232
0
    for (const UVSMapping& _ : it)
1233
0
    {
1234
0
      UVSMapping mapping;
1235
0
      mapping.unicodeValue = _.unicodeValue;
1236
0
      mapping.glyphID = glyph_map->get (_.glyphID);
1237
0
      c->copy<UVSMapping> (mapping);
1238
0
    }
1239
1240
0
    return out;
1241
0
  }
1242
1243
  public:
1244
  DEFINE_SIZE_ARRAY (4, *this);
1245
};
1246
1247
struct VariationSelectorRecord
1248
{
1249
  glyph_variant_t get_glyph (hb_codepoint_t codepoint,
1250
           hb_codepoint_t *glyph,
1251
           const void *base) const
1252
25.0k
  {
1253
25.0k
    if ((base+defaultUVS).bfind (codepoint))
1254
0
      return GLYPH_VARIANT_USE_DEFAULT;
1255
25.0k
    const UVSMapping &nonDefault = (base+nonDefaultUVS).bsearch (codepoint);
1256
25.0k
    if (nonDefault.glyphID)
1257
0
    {
1258
0
      *glyph = nonDefault.glyphID;
1259
0
       return GLYPH_VARIANT_FOUND;
1260
0
    }
1261
25.0k
    return GLYPH_VARIANT_NOT_FOUND;
1262
25.0k
  }
1263
1264
  VariationSelectorRecord(const VariationSelectorRecord& other)
1265
0
  {
1266
0
    *this = other;
1267
0
  }
1268
1269
  void operator= (const VariationSelectorRecord& other)
1270
0
  {
1271
0
    varSelector = other.varSelector;
1272
0
    HBUINT32 offset = other.defaultUVS;
1273
0
    defaultUVS = offset;
1274
0
    offset = other.nonDefaultUVS;
1275
0
    nonDefaultUVS = offset;
1276
0
  }
1277
1278
  void collect_unicodes (hb_set_t *out, const void *base) const
1279
0
  {
1280
0
    (base+defaultUVS).collect_unicodes (out);
1281
0
    (base+nonDefaultUVS).collect_unicodes (out);
1282
0
  }
1283
1284
  void collect_mapping (const void *base,
1285
      hb_set_t *unicodes, /* OUT */
1286
      hb_map_t *mapping /* OUT */) const
1287
0
  {
1288
0
    (base+defaultUVS).collect_unicodes (unicodes);
1289
0
    (base+nonDefaultUVS).collect_mapping (unicodes, mapping);
1290
0
  }
1291
1292
  int cmp (const hb_codepoint_t &variation_selector) const
1293
0
  { return varSelector.cmp (variation_selector); }
1294
1295
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
1296
0
  {
1297
0
    TRACE_SANITIZE (this);
1298
0
    return_trace (c->check_struct (this) &&
1299
0
      defaultUVS.sanitize (c, base) &&
1300
0
      nonDefaultUVS.sanitize (c, base));
1301
0
  }
1302
1303
  hb_pair_t<unsigned, unsigned>
1304
  copy (hb_serialize_context_t *c,
1305
  const hb_set_t *unicodes,
1306
  const hb_set_t *glyphs_requested,
1307
  const hb_map_t *glyph_map,
1308
  const void *base) const
1309
0
  {
1310
0
    auto snap = c->snapshot ();
1311
0
    auto *out = c->embed<VariationSelectorRecord> (*this);
1312
0
    if (unlikely (!out)) return hb_pair (0, 0);
1313
1314
0
    out->defaultUVS = 0;
1315
0
    out->nonDefaultUVS = 0;
1316
1317
0
    unsigned non_default_uvs_objidx = 0;
1318
0
    if (nonDefaultUVS != 0)
1319
0
    {
1320
0
      c->push ();
1321
0
      if (c->copy (base+nonDefaultUVS, unicodes, glyphs_requested, glyph_map))
1322
0
  non_default_uvs_objidx = c->pop_pack ();
1323
0
      else c->pop_discard ();
1324
0
    }
1325
1326
0
    unsigned default_uvs_objidx = 0;
1327
0
    if (defaultUVS != 0)
1328
0
    {
1329
0
      c->push ();
1330
0
      if (c->copy (base+defaultUVS, unicodes))
1331
0
  default_uvs_objidx = c->pop_pack ();
1332
0
      else c->pop_discard ();
1333
0
    }
1334
1335
1336
0
    if (!default_uvs_objidx && !non_default_uvs_objidx)
1337
0
      c->revert (snap);
1338
1339
0
    return hb_pair (default_uvs_objidx, non_default_uvs_objidx);
1340
0
  }
1341
1342
  HBUINT24  varSelector;  /* Variation selector. */
1343
  Offset32To<DefaultUVS>
1344
    defaultUVS; /* Offset to Default UVS Table.  May be 0. */
1345
  Offset32To<NonDefaultUVS>
1346
    nonDefaultUVS;  /* Offset to Non-Default UVS Table.  May be 0. */
1347
  public:
1348
  DEFINE_SIZE_STATIC (11);
1349
};
1350
1351
struct CmapSubtableFormat14
1352
{
1353
  glyph_variant_t get_glyph_variant (hb_codepoint_t codepoint,
1354
             hb_codepoint_t variation_selector,
1355
             hb_codepoint_t *glyph) const
1356
25.0k
  { return record.bsearch (variation_selector).get_glyph (codepoint, glyph, this); }
1357
1358
  void collect_variation_selectors (hb_set_t *out) const
1359
6.57k
  {
1360
6.57k
    for (const auto& a : record.as_array ())
1361
0
      out->add (a.varSelector);
1362
6.57k
  }
1363
  void collect_variation_unicodes (hb_codepoint_t variation_selector,
1364
           hb_set_t *out) const
1365
0
  { record.bsearch (variation_selector).collect_unicodes (out, this); }
1366
1367
  void serialize (hb_serialize_context_t *c,
1368
      const hb_set_t *unicodes,
1369
      const hb_set_t *glyphs_requested,
1370
      const hb_map_t *glyph_map,
1371
      const void *base)
1372
0
  {
1373
0
    auto snap = c->snapshot ();
1374
0
    unsigned table_initpos = c->length ();
1375
0
    const char* init_tail = c->tail;
1376
1377
0
    if (unlikely (!c->extend_min (this))) return;
1378
0
    this->format = 14;
1379
1380
0
    auto src_tbl = reinterpret_cast<const CmapSubtableFormat14*> (base);
1381
1382
    /*
1383
     * Some versions of OTS require that offsets are in order. Due to the use
1384
     * of push()/pop_pack() serializing the variation records in order results
1385
     * in the offsets being in reverse order (first record has the largest
1386
     * offset). While this is perfectly valid, it will cause some versions of
1387
     * OTS to consider this table bad.
1388
     *
1389
     * So to prevent this issue we serialize the variation records in reverse
1390
     * order, so that the offsets are ordered from small to large. Since
1391
     * variation records are supposed to be in increasing order of varSelector
1392
     * we then have to reverse the order of the written variation selector
1393
     * records after everything is finalized.
1394
     */
1395
0
    hb_vector_t<hb_pair_t<unsigned, unsigned>> obj_indices;
1396
0
    for (int i = src_tbl->record.len - 1; i >= 0; i--)
1397
0
    {
1398
0
      if (!unicodes->has(src_tbl->record[i].varSelector))
1399
0
        continue;
1400
1401
0
      hb_pair_t<unsigned, unsigned> result = src_tbl->record[i].copy (c, unicodes, glyphs_requested, glyph_map, base);
1402
0
      if (result.first || result.second)
1403
0
  obj_indices.push (result);
1404
0
    }
1405
1406
0
    if (c->length () - table_initpos == CmapSubtableFormat14::min_size)
1407
0
    {
1408
0
      c->revert (snap);
1409
0
      return;
1410
0
    }
1411
1412
0
    if (unlikely (!c->check_success (!obj_indices.in_error ())))
1413
0
      return;
1414
1415
0
    int tail_len = init_tail - c->tail;
1416
0
    c->check_assign (this->length, c->length () - table_initpos + tail_len,
1417
0
                     HB_SERIALIZE_ERROR_INT_OVERFLOW);
1418
0
    c->check_assign (this->record.len,
1419
0
         (c->length () - table_initpos - CmapSubtableFormat14::min_size) /
1420
0
         VariationSelectorRecord::static_size,
1421
0
                     HB_SERIALIZE_ERROR_INT_OVERFLOW);
1422
1423
    /* Correct the incorrect write order by reversing the order of the variation
1424
       records array. */
1425
0
    _reverse_variation_records ();
1426
1427
    /* Now that records are in the right order, we can set up the offsets. */
1428
0
    _add_links_to_variation_records (c, obj_indices);
1429
0
  }
1430
1431
  void _reverse_variation_records ()
1432
0
  {
1433
0
    record.as_array ().reverse ();
1434
0
  }
1435
1436
  void _add_links_to_variation_records (hb_serialize_context_t *c,
1437
          const hb_vector_t<hb_pair_t<unsigned, unsigned>>& obj_indices)
1438
0
  {
1439
0
    for (unsigned i = 0; i < obj_indices.length; i++)
1440
0
    {
1441
      /*
1442
       * Since the record array has been reversed (see comments in copy())
1443
       * but obj_indices has not been, the indices at obj_indices[i]
1444
       * are for the variation record at record[j].
1445
       */
1446
0
      int j = obj_indices.length - 1 - i;
1447
0
      c->add_link (record[j].defaultUVS, obj_indices[i].first);
1448
0
      c->add_link (record[j].nonDefaultUVS, obj_indices[i].second);
1449
0
    }
1450
0
  }
1451
1452
  void closure_glyphs (const hb_set_t      *unicodes,
1453
           hb_set_t            *glyphset) const
1454
0
  {
1455
0
    + hb_iter (record)
1456
0
    | hb_filter (hb_bool, &VariationSelectorRecord::nonDefaultUVS)
1457
0
    | hb_filter (unicodes, &VariationSelectorRecord::varSelector)
1458
0
    | hb_map (&VariationSelectorRecord::nonDefaultUVS)
1459
0
    | hb_map (hb_add (this))
1460
0
    | hb_apply ([=] (const NonDefaultUVS& _) { _.closure_glyphs (unicodes, glyphset); })
1461
0
    ;
1462
0
  }
1463
1464
  void collect_unicodes (hb_set_t *out) const
1465
0
  {
1466
0
    for (const VariationSelectorRecord& _ : record)
1467
0
      _.collect_unicodes (out, this);
1468
0
  }
1469
1470
  void collect_mapping (hb_set_t *unicodes, /* OUT */
1471
      hb_map_t *mapping /* OUT */) const
1472
0
  {
1473
0
    for (const VariationSelectorRecord& _ : record)
1474
0
      _.collect_mapping (this, unicodes, mapping);
1475
0
  }
1476
1477
  bool sanitize (hb_sanitize_context_t *c) const
1478
0
  {
1479
0
    TRACE_SANITIZE (this);
1480
0
    return_trace (c->check_struct (this) &&
1481
0
      record.sanitize (c, this));
1482
0
  }
1483
1484
  protected:
1485
  HBUINT16  format;   /* Format number is set to 14. */
1486
  HBUINT32  length;   /* Byte length of this subtable. */
1487
  SortedArray32Of<VariationSelectorRecord>
1488
    record;   /* Variation selector records; sorted
1489
         * in increasing order of `varSelector'. */
1490
  public:
1491
  DEFINE_SIZE_ARRAY (10, record);
1492
};
1493
1494
struct CmapSubtable
1495
{
1496
  /* Note: We intentionally do NOT implement subtable formats 2 and 8. */
1497
1498
  bool get_glyph (hb_codepoint_t codepoint,
1499
      hb_codepoint_t *glyph,
1500
      unsigned int subtable_data_size = 0) const
1501
0
  {
1502
0
    switch (u.format.v) {
1503
0
    case  0: hb_barrier (); return u.format0 .get_glyph (codepoint, glyph);
1504
0
    case  4: hb_barrier (); return subtable_data_size
1505
0
              ? u.format4.get_glyph (codepoint, glyph, subtable_data_size)
1506
0
              : false;
1507
0
    case  6: hb_barrier (); return u.format6 .get_glyph (codepoint, glyph);
1508
0
    case 10: hb_barrier (); return u.format10.get_glyph (codepoint, glyph);
1509
0
    case 12: hb_barrier (); return u.format12.get_glyph (codepoint, glyph);
1510
0
    case 13: hb_barrier (); return u.format13.get_glyph (codepoint, glyph);
1511
0
    case 14:
1512
0
    default: return false;
1513
0
    }
1514
0
  }
1515
  void collect_unicodes (hb_set_t *out,
1516
       unsigned int num_glyphs = UINT_MAX,
1517
       unsigned int subtable_data_size = 0) const
1518
5
  {
1519
5
    switch (u.format.v) {
1520
0
    case  0: hb_barrier (); u.format0 .collect_unicodes (out); return;
1521
5
    case  4: hb_barrier (); if (subtable_data_size)
1522
5
            u.format4.collect_unicodes (out, subtable_data_size);
1523
0
          else
1524
0
            u.format4.collect_unicodes (out);
1525
5
          return;
1526
0
    case  6: hb_barrier (); u.format6 .collect_unicodes (out); return;
1527
0
    case 10: hb_barrier (); u.format10.collect_unicodes (out); return;
1528
0
    case 12: hb_barrier (); u.format12.collect_unicodes (out, num_glyphs); return;
1529
0
    case 13: hb_barrier (); u.format13.collect_unicodes (out, num_glyphs); return;
1530
0
    case 14:
1531
0
    default: return;
1532
5
    }
1533
5
  }
1534
1535
  void collect_mapping (hb_set_t *unicodes, /* OUT */
1536
      hb_map_t *mapping, /* OUT */
1537
      unsigned num_glyphs = UINT_MAX,
1538
      unsigned int subtable_data_size = 0) const
1539
6.57k
  {
1540
6.57k
    switch (u.format.v) {
1541
0
    case  0: hb_barrier (); u.format0 .collect_mapping (unicodes, mapping); return;
1542
6.57k
    case  4: hb_barrier (); if (subtable_data_size)
1543
6.57k
            u.format4.collect_mapping (unicodes, mapping, subtable_data_size);
1544
0
          else
1545
0
            u.format4.collect_mapping (unicodes, mapping);
1546
6.57k
          return;
1547
0
    case  6: hb_barrier (); u.format6 .collect_mapping (unicodes, mapping); return;
1548
0
    case 10: hb_barrier (); u.format10.collect_mapping (unicodes, mapping); return;
1549
0
    case 12: hb_barrier (); u.format12.collect_mapping (unicodes, mapping, num_glyphs); return;
1550
0
    case 13: hb_barrier (); u.format13.collect_mapping (unicodes, mapping, num_glyphs); return;
1551
0
    case 14:
1552
0
    default: return;
1553
6.57k
    }
1554
6.57k
  }
1555
1556
  unsigned get_language () const
1557
0
  {
1558
0
    switch (u.format.v) {
1559
0
    case  0: hb_barrier (); return u.format0 .get_language ();
1560
0
    case  4: hb_barrier (); return u.format4 .get_language ();
1561
0
    case  6: hb_barrier (); return u.format6 .get_language ();
1562
0
    case 10: hb_barrier (); return u.format10.get_language ();
1563
0
    case 12: hb_barrier (); return u.format12.get_language ();
1564
0
    case 13: hb_barrier (); return u.format13.get_language ();
1565
0
    case 14:
1566
0
    default: return 0;
1567
0
    }
1568
0
  }
1569
1570
  template<typename Iterator,
1571
     hb_requires (hb_is_iterator (Iterator))>
1572
  void serialize (hb_serialize_context_t *c,
1573
      Iterator it,
1574
      unsigned format,
1575
      const hb_subset_plan_t *plan,
1576
      const void *base)
1577
0
  {
1578
0
    switch (format) {
1579
0
    case  4: hb_barrier (); return u.format4.serialize (c, it);
1580
0
    case 12: hb_barrier (); return u.format12.serialize (c, it);
1581
0
    case 14: hb_barrier (); return u.format14.serialize (c, &plan->unicodes, &plan->glyphs_requested, plan->glyph_map, base);
1582
0
    default: return;
1583
0
    }
1584
0
  }
Unexecuted instantiation: hb-face.cc:_ZN2OT12CmapSubtable9serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_jPK16hb_subset_plan_tPKv
Unexecuted instantiation: hb-face.cc:_ZN2OT12CmapSubtable9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_jPK16hb_subset_plan_tPKv
Unexecuted instantiation: hb-ot-face.cc:_ZN2OT12CmapSubtable9serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_jPK16hb_subset_plan_tPKv
Unexecuted instantiation: hb-ot-face.cc:_ZN2OT12CmapSubtable9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_jPK16hb_subset_plan_tPKv
Unexecuted instantiation: hb-ot-font.cc:_ZN2OT12CmapSubtable9serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_jPK16hb_subset_plan_tPKv
Unexecuted instantiation: hb-ot-font.cc:_ZN2OT12CmapSubtable9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_jPK16hb_subset_plan_tPKv
Unexecuted instantiation: hb-static.cc:_ZN2OT12CmapSubtable9serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_jPK16hb_subset_plan_tPKv
Unexecuted instantiation: hb-static.cc:_ZN2OT12CmapSubtable9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_jPK16hb_subset_plan_tPKv
Unexecuted instantiation: hb-subset.cc:_ZN2OT12CmapSubtable9serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_9LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_jPK16hb_subset_plan_tPKv
Unexecuted instantiation: hb-subset.cc:_ZN2OT12CmapSubtable9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_jPK16hb_subset_plan_tPKv
Unexecuted instantiation: hb-subset-plan.cc:_ZN2OT12CmapSubtable9serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_5LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_jPK16hb_subset_plan_tPKv
Unexecuted instantiation: hb-subset-plan.cc:_ZN2OT12CmapSubtable9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_5LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_jPK16hb_subset_plan_tPKv
Unexecuted instantiation: hb-subset-table-other.cc:_ZN2OT12CmapSubtable9serializeI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_9LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSP_jPK16hb_subset_plan_tPKv
Unexecuted instantiation: hb-subset-table-other.cc:_ZN2OT12CmapSubtable9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEvP22hb_serialize_context_tSI_jPK16hb_subset_plan_tPKv
1585
1586
  bool sanitize (hb_sanitize_context_t *c) const
1587
39.6k
  {
1588
39.6k
    TRACE_SANITIZE (this);
1589
39.6k
    if (!u.format.v.sanitize (c)) return_trace (false);
1590
39.6k
    hb_barrier ();
1591
39.6k
    switch (u.format.v) {
1592
0
    case  0: hb_barrier (); return_trace (u.format0 .sanitize (c));
1593
26.4k
    case  4: hb_barrier (); return_trace (u.format4 .sanitize (c));
1594
13.2k
    case  6: hb_barrier (); return_trace (u.format6 .sanitize (c));
1595
0
    case 10: hb_barrier (); return_trace (u.format10.sanitize (c));
1596
0
    case 12: hb_barrier (); return_trace (u.format12.sanitize (c));
1597
0
    case 13: hb_barrier (); return_trace (u.format13.sanitize (c));
1598
0
    case 14: hb_barrier (); return_trace (u.format14.sanitize (c));
1599
0
    default:return_trace (true);
1600
39.6k
    }
1601
39.6k
  }
1602
1603
  public:
1604
  union {
1605
  struct { HBUINT16 v; }  format;   /* Format identifier */
1606
  CmapSubtableFormat0 format0;
1607
  CmapSubtableFormat4 format4;
1608
  CmapSubtableFormat6 format6;
1609
  CmapSubtableFormat10  format10;
1610
  CmapSubtableFormat12  format12;
1611
  CmapSubtableFormat13  format13;
1612
  CmapSubtableFormat14  format14;
1613
  } u;
1614
  public:
1615
  DEFINE_SIZE_UNION (2, format.v);
1616
};
1617
1618
1619
struct EncodingRecord
1620
{
1621
  int cmp (const EncodingRecord &other) const
1622
158k
  {
1623
158k
    int ret;
1624
158k
    ret = platformID.cmp (other.platformID);
1625
158k
    if (ret) return ret;
1626
79.2k
    if (other.encodingID != 0xFFFF)
1627
79.2k
    {
1628
79.2k
      ret = encodingID.cmp (other.encodingID);
1629
79.2k
      if (ret) return ret;
1630
79.2k
    }
1631
13.2k
    return 0;
1632
79.2k
  }
1633
1634
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
1635
39.6k
  {
1636
39.6k
    TRACE_SANITIZE (this);
1637
39.6k
    return_trace (c->check_struct (this) &&
1638
39.6k
      subtable.sanitize (c, base));
1639
39.6k
  }
1640
1641
  template<typename Iterator,
1642
     hb_requires (hb_is_iterator (Iterator))>
1643
  EncodingRecord* copy (hb_serialize_context_t *c,
1644
      Iterator it,
1645
      unsigned format,
1646
      const void *base,
1647
      const hb_subset_plan_t *plan,
1648
      /* INOUT */ unsigned *objidx) const
1649
0
  {
1650
0
    TRACE_SERIALIZE (this);
1651
0
    auto snap = c->snapshot ();
1652
0
    auto *out = c->embed (this);
1653
0
    if (unlikely (!out)) return_trace (nullptr);
1654
0
    out->subtable = 0;
1655
1656
0
    if (*objidx == 0)
1657
0
    {
1658
0
      CmapSubtable *cmapsubtable = c->push<CmapSubtable> ();
1659
0
      unsigned origin_length = c->length ();
1660
0
      cmapsubtable->serialize (c, it, format, plan, &(base+subtable));
1661
0
      if (c->length () > origin_length && !c->in_error()) *objidx = c->pop_pack ();
1662
0
      else c->pop_discard ();
1663
0
    }
1664
1665
0
    if (*objidx == 0)
1666
0
    {
1667
0
      c->revert (snap);
1668
0
      return_trace (nullptr);
1669
0
    }
1670
1671
0
    c->add_link (out->subtable, *objidx);
1672
0
    return_trace (out);
1673
0
  }
Unexecuted instantiation: hb-face.cc:_ZNK2OT14EncodingRecord4copyI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEPS0_P22hb_serialize_context_tSP_jPKvPK16hb_subset_plan_tPj
Unexecuted instantiation: hb-face.cc:_ZNK2OT14EncodingRecord4copyI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEPS0_P22hb_serialize_context_tSI_jPKvPK16hb_subset_plan_tPj
Unexecuted instantiation: hb-ot-face.cc:_ZNK2OT14EncodingRecord4copyI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEPS0_P22hb_serialize_context_tSP_jPKvPK16hb_subset_plan_tPj
Unexecuted instantiation: hb-ot-face.cc:_ZNK2OT14EncodingRecord4copyI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEPS0_P22hb_serialize_context_tSI_jPKvPK16hb_subset_plan_tPj
Unexecuted instantiation: hb-ot-font.cc:_ZNK2OT14EncodingRecord4copyI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEPS0_P22hb_serialize_context_tSP_jPKvPK16hb_subset_plan_tPj
Unexecuted instantiation: hb-ot-font.cc:_ZNK2OT14EncodingRecord4copyI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEPS0_P22hb_serialize_context_tSI_jPKvPK16hb_subset_plan_tPj
Unexecuted instantiation: hb-static.cc:_ZNK2OT14EncodingRecord4copyI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEPS0_P22hb_serialize_context_tSP_jPKvPK16hb_subset_plan_tPj
Unexecuted instantiation: hb-static.cc:_ZNK2OT14EncodingRecord4copyI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEPS0_P22hb_serialize_context_tSI_jPKvPK16hb_subset_plan_tPj
Unexecuted instantiation: hb-subset.cc:_ZNK2OT14EncodingRecord4copyI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_9LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEPS0_P22hb_serialize_context_tSP_jPKvPK16hb_subset_plan_tPj
Unexecuted instantiation: hb-subset.cc:_ZNK2OT14EncodingRecord4copyI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEPS0_P22hb_serialize_context_tSI_jPKvPK16hb_subset_plan_tPj
Unexecuted instantiation: hb-subset-plan.cc:_ZNK2OT14EncodingRecord4copyI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_5LPv0EERK8hb_set_tRK3$_8LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEPS0_P22hb_serialize_context_tSP_jPKvPK16hb_subset_plan_tPj
Unexecuted instantiation: hb-subset-plan.cc:_ZNK2OT14EncodingRecord4copyI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_5LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEPS0_P22hb_serialize_context_tSI_jPKvPK16hb_subset_plan_tPj
Unexecuted instantiation: hb-subset-table-other.cc:_ZNK2OT14EncodingRecord4copyI16hb_filter_iter_tIS2_I17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EERK8hb_set_tRK3$_9LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSP_6item_tEEE5valueEvE4typeELSF_0EEEPS0_P22hb_serialize_context_tSP_jPKvPK16hb_subset_plan_tPj
Unexecuted instantiation: hb-subset-table-other.cc:_ZNK2OT14EncodingRecord4copyI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS_4cmap6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NSI_6item_tEEE5valueEvE4typeELSF_0EEEPS0_P22hb_serialize_context_tSI_jPKvPK16hb_subset_plan_tPj
1674
1675
  HBUINT16  platformID; /* Platform ID. */
1676
  HBUINT16  encodingID; /* Platform-specific encoding ID. */
1677
  Offset32To<CmapSubtable>
1678
    subtable; /* Byte offset from beginning of table to the subtable for this encoding. */
1679
  public:
1680
  DEFINE_SIZE_STATIC (8);
1681
};
1682
1683
struct cmap;
1684
1685
struct SubtableUnicodesCache {
1686
1687
 private:
1688
  hb_blob_ptr_t<cmap> base_blob;
1689
  const char* base;
1690
  unsigned int table_length;
1691
  hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> cached_unicodes;
1692
1693
 public:
1694
1695
  static SubtableUnicodesCache* create (hb_blob_ptr_t<cmap> source_table)
1696
0
  {
1697
0
    SubtableUnicodesCache* cache =
1698
0
        (SubtableUnicodesCache*) hb_malloc (sizeof(SubtableUnicodesCache));
1699
1700
0
    if (unlikely (!cache))
1701
0
      return nullptr;
1702
1703
0
    new (cache) SubtableUnicodesCache (source_table);
1704
0
    return cache;
1705
0
  }
1706
1707
0
  static void destroy (void* value) {
1708
0
    if (!value) return;
1709
1710
0
    SubtableUnicodesCache* cache = (SubtableUnicodesCache*) value;
1711
0
    cache->~SubtableUnicodesCache ();
1712
0
    hb_free (cache);
1713
0
  }
1714
1715
  SubtableUnicodesCache(const void* cmap_base,
1716
      unsigned int table_length_ = 0)
1717
0
      : base_blob(),
1718
0
        base ((const char*) cmap_base),
1719
0
        table_length (table_length_),
1720
0
        cached_unicodes ()
1721
0
  {}
1722
1723
  SubtableUnicodesCache(hb_blob_ptr_t<cmap> base_blob_)
1724
0
      : base_blob(base_blob_),
1725
0
        base ((const char *) base_blob.get()),
1726
0
        table_length (base_blob.get_length ()),
1727
0
        cached_unicodes ()
1728
0
  {}
1729
1730
  ~SubtableUnicodesCache()
1731
0
  {
1732
0
    base_blob.destroy ();
1733
0
  }
1734
1735
  bool same_base(const void* other) const
1736
0
  {
1737
0
    return other == (const void*) base;
1738
0
  }
1739
1740
  const hb_set_t* set_for (const EncodingRecord* record,
1741
                           SubtableUnicodesCache& mutable_cache) const
1742
0
  {
1743
0
    if (cached_unicodes.has ((unsigned) ((const char *) record - base)))
1744
0
      return cached_unicodes.get ((unsigned) ((const char *) record - base));
1745
1746
0
    return mutable_cache.set_for (record);
1747
0
  }
1748
1749
  const hb_set_t* set_for (const EncodingRecord* record)
1750
0
  {
1751
0
    if (!cached_unicodes.has ((unsigned) ((const char *) record - base)))
1752
0
    {
1753
0
      hb_set_t *s = hb_set_create ();
1754
0
      if (unlikely (s->in_error ()))
1755
0
  return hb_set_get_empty ();
1756
1757
0
      unsigned int subtable_data_size = record->subtable < table_length
1758
0
          ? table_length - (unsigned int) record->subtable
1759
0
          : 0;
1760
0
      (base+record->subtable).collect_unicodes (s, UINT_MAX, subtable_data_size);
1761
1762
0
      if (unlikely (!cached_unicodes.set ((unsigned) ((const char *) record - base), hb::unique_ptr<hb_set_t> {s})))
1763
0
        return hb_set_get_empty ();
1764
1765
0
      return s;
1766
0
    }
1767
0
    return cached_unicodes.get ((unsigned) ((const char *) record - base));
1768
0
  }
1769
1770
};
1771
1772
static inline uint16_t
1773
_hb_symbol_pua_map (unsigned codepoint)
1774
0
{
1775
0
  if (codepoint <= 0x00FFu)
1776
0
  {
1777
    /* For symbol-encoded OpenType fonts, we duplicate the
1778
     * U+F000..F0FF range at U+0000..U+00FF.  That's what
1779
     * Windows seems to do, and that's hinted about at:
1780
     * https://docs.microsoft.com/en-us/typography/opentype/spec/recom
1781
     * under "Non-Standard (Symbol) Fonts". */
1782
0
    return 0xF000u + codepoint;
1783
0
  }
1784
0
  return 0;
1785
0
}
Unexecuted instantiation: hb-face.cc:OT::_hb_symbol_pua_map(unsigned int)
Unexecuted instantiation: hb-ot-face.cc:OT::_hb_symbol_pua_map(unsigned int)
Unexecuted instantiation: hb-ot-font.cc:OT::_hb_symbol_pua_map(unsigned int)
Unexecuted instantiation: hb-static.cc:OT::_hb_symbol_pua_map(unsigned int)
Unexecuted instantiation: hb-subset.cc:OT::_hb_symbol_pua_map(unsigned int)
Unexecuted instantiation: hb-subset-plan.cc:OT::_hb_symbol_pua_map(unsigned int)
Unexecuted instantiation: hb-subset-table-other.cc:OT::_hb_symbol_pua_map(unsigned int)
1786
1787
struct cmap
1788
{
1789
  static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap;
1790
1791
1792
0
  static SubtableUnicodesCache* create_filled_cache(hb_blob_ptr_t<cmap> source_table) {
1793
0
    const cmap* cmap = source_table.get();
1794
0
    auto it =
1795
0
    + hb_iter (cmap->encodingRecord)
1796
0
    | hb_filter ([&](const EncodingRecord& _) {
1797
0
      return cmap::filter_encoding_records_for_subset (cmap, _);
1798
0
    })
1799
0
    ;
1800
1801
0
    SubtableUnicodesCache* cache = SubtableUnicodesCache::create(source_table);
1802
1803
0
    if (unlikely (!cache))
1804
0
      return nullptr;
1805
1806
0
    for (const EncodingRecord& _ : it)
1807
0
      cache->set_for(&_); // populate the cache for this encoding record.
1808
1809
0
    return cache;
1810
0
  }
1811
1812
  template<typename Iterator, typename EncodingRecIter,
1813
     hb_requires (hb_is_iterator (EncodingRecIter))>
1814
  bool serialize (hb_serialize_context_t *c,
1815
      Iterator it,
1816
      EncodingRecIter encodingrec_iter,
1817
      const void *base,
1818
      hb_subset_plan_t *plan,
1819
                    bool drop_format_4 = false,
1820
        unsigned int source_table_length = 0)
1821
0
  {
1822
0
    if (unlikely (!c->extend_min ((*this))))  return false;
1823
0
    this->version = 0;
1824
1825
0
    unsigned format4objidx = 0, format12objidx = 0, format14objidx = 0;
1826
0
    auto snap = c->snapshot ();
1827
1828
0
    SubtableUnicodesCache local_unicodes_cache (base, source_table_length);
1829
0
    const SubtableUnicodesCache* unicodes_cache = &local_unicodes_cache;
1830
1831
0
    if (plan->accelerator &&
1832
0
        plan->accelerator->cmap_cache &&
1833
0
        plan->accelerator->cmap_cache->same_base (base))
1834
0
      unicodes_cache = plan->accelerator->cmap_cache;
1835
1836
0
    for (const EncodingRecord& _ : encodingrec_iter)
1837
0
    {
1838
0
      if (c->in_error ())
1839
0
        return false;
1840
1841
0
      unsigned format = (base+_.subtable).u.format.v;
1842
0
      if (format != 4 && format != 12 && format != 14) continue;
1843
1844
0
      const hb_set_t* unicodes_set = unicodes_cache->set_for (&_, local_unicodes_cache);
1845
1846
0
      if (!drop_format_4 && format == 4)
1847
0
      {
1848
0
        c->copy (_, + it | hb_filter (*unicodes_set, hb_first), 4u, base, plan, &format4objidx);
1849
0
        if (c->in_error () && c->only_overflow ())
1850
0
        {
1851
          // cmap4 overflowed, reset and retry serialization without format 4 subtables.
1852
0
          c->revert (snap);
1853
0
          return serialize (c, it,
1854
0
                            encodingrec_iter,
1855
0
                            base,
1856
0
                            plan,
1857
0
                            true,
1858
0
          source_table_length);
1859
0
        }
1860
0
      }
1861
1862
0
      else if (format == 12)
1863
0
      {
1864
0
        if (_can_drop (_,
1865
0
                       *unicodes_set,
1866
0
                       base,
1867
0
                       *unicodes_cache,
1868
0
                       local_unicodes_cache,
1869
0
                       + it | hb_map (hb_first), encodingrec_iter))
1870
0
          continue;
1871
0
        c->copy (_, + it | hb_filter (*unicodes_set, hb_first), 12u, base, plan, &format12objidx);
1872
0
      }
1873
0
      else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx);
1874
0
    }
1875
0
        unsigned length = c->length ();
1876
0
        unsigned available = length > cmap::min_size ? length - cmap::min_size : 0;
1877
0
        c->check_assign(this->encodingRecord.len,
1878
0
                        available / EncodingRecord::static_size,
1879
0
                        HB_SERIALIZE_ERROR_INT_OVERFLOW);
1880
1881
    // Fail if format 4 was dropped and there is no cmap12.
1882
0
    return !drop_format_4 || format12objidx;
1883
0
  }
Unexecuted instantiation: hb-face.cc:_ZN2OT4cmap9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS0_6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EES2_IS3_IKNS_14EncodingRecordEEZNKS0_6subsetES9_EUlRSH_E_SD_LSE_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT0_NSN_6item_tEEE5valueEvE4typeELSE_0EEEbP22hb_serialize_context_tT_SN_PKvP16hb_subset_plan_tbj
Unexecuted instantiation: hb-ot-face.cc:_ZN2OT4cmap9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS0_6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EES2_IS3_IKNS_14EncodingRecordEEZNKS0_6subsetES9_EUlRSH_E_SD_LSE_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT0_NSN_6item_tEEE5valueEvE4typeELSE_0EEEbP22hb_serialize_context_tT_SN_PKvP16hb_subset_plan_tbj
Unexecuted instantiation: hb-ot-font.cc:_ZN2OT4cmap9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS0_6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EES2_IS3_IKNS_14EncodingRecordEEZNKS0_6subsetES9_EUlRSH_E_SD_LSE_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT0_NSN_6item_tEEE5valueEvE4typeELSE_0EEEbP22hb_serialize_context_tT_SN_PKvP16hb_subset_plan_tbj
Unexecuted instantiation: hb-static.cc:_ZN2OT4cmap9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS0_6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EES2_IS3_IKNS_14EncodingRecordEEZNKS0_6subsetES9_EUlRSH_E_SD_LSE_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT0_NSN_6item_tEEE5valueEvE4typeELSE_0EEEbP22hb_serialize_context_tT_SN_PKvP16hb_subset_plan_tbj
Unexecuted instantiation: hb-subset.cc:_ZN2OT4cmap9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS0_6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EES2_IS3_IKNS_14EncodingRecordEEZNKS0_6subsetES9_EUlRSH_E_SD_LSE_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT0_NSN_6item_tEEE5valueEvE4typeELSE_0EEEbP22hb_serialize_context_tT_SN_PKvP16hb_subset_plan_tbj
Unexecuted instantiation: hb-subset-plan.cc:_ZN2OT4cmap9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS0_6subsetEP19hb_subset_context_tEUlS5_E_RK3$_5LPv0EES2_IS3_IKNS_14EncodingRecordEEZNKS0_6subsetES9_EUlRSH_E_SD_LSE_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT0_NSN_6item_tEEE5valueEvE4typeELSE_0EEEbP22hb_serialize_context_tT_SN_PKvP16hb_subset_plan_tbj
Unexecuted instantiation: hb-subset-table-other.cc:_ZN2OT4cmap9serializeI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS0_6subsetEP19hb_subset_context_tEUlS5_E_RK3$_6LPv0EES2_IS3_IKNS_14EncodingRecordEEZNKS0_6subsetES9_EUlRSH_E_SD_LSE_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT0_NSN_6item_tEEE5valueEvE4typeELSE_0EEEbP22hb_serialize_context_tT_SN_PKvP16hb_subset_plan_tbj
1884
1885
  template<typename Iterator, typename EncodingRecordIterator,
1886
      hb_requires (hb_is_iterator (Iterator)),
1887
      hb_requires (hb_is_iterator (EncodingRecordIterator))>
1888
  bool _can_drop (const EncodingRecord& cmap12,
1889
                  const hb_set_t& cmap12_unicodes,
1890
                  const void* base,
1891
                  const SubtableUnicodesCache& unicodes_cache,
1892
                  SubtableUnicodesCache& local_unicodes_cache,
1893
                  Iterator subset_unicodes,
1894
                  EncodingRecordIterator encoding_records)
1895
0
  {
1896
0
    for (auto cp : + subset_unicodes | hb_filter (cmap12_unicodes))
1897
0
    {
1898
0
      if (cp >= 0x10000) return false;
1899
0
    }
1900
1901
0
    unsigned target_platform;
1902
0
    unsigned target_encoding;
1903
0
    unsigned target_language = (base+cmap12.subtable).get_language ();
1904
1905
0
    if (cmap12.platformID == 0 && cmap12.encodingID == 4)
1906
0
    {
1907
0
      target_platform = 0;
1908
0
      target_encoding = 3;
1909
0
    } else if (cmap12.platformID == 3 && cmap12.encodingID == 10) {
1910
0
      target_platform = 3;
1911
0
      target_encoding = 1;
1912
0
    } else {
1913
0
      return false;
1914
0
    }
1915
1916
0
    for (const auto& _ : encoding_records)
1917
0
    {
1918
0
      if (_.platformID != target_platform
1919
0
          || _.encodingID != target_encoding
1920
0
          || (base+_.subtable).get_language() != target_language)
1921
0
        continue;
1922
1923
0
      const hb_set_t* sibling_unicodes = unicodes_cache.set_for (&_, local_unicodes_cache);
1924
1925
0
      auto cmap12 = + subset_unicodes | hb_filter (cmap12_unicodes);
1926
0
      auto sibling = + subset_unicodes | hb_filter (*sibling_unicodes);
1927
0
      for (; cmap12 && sibling; cmap12++, sibling++)
1928
0
      {
1929
0
        unsigned a = *cmap12;
1930
0
        unsigned b = *sibling;
1931
0
        if (a != b) return false;
1932
0
      }
1933
1934
0
      return !cmap12 && !sibling;
1935
0
    }
1936
1937
0
    return false;
1938
0
  }
Unexecuted instantiation: hb-face.cc:_ZN2OT4cmap9_can_dropI13hb_map_iter_tI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS0_6subsetEP19hb_subset_context_tEUlS6_E_RK3$_6LPv0EERK3$_8L24hb_function_sortedness_t0ELSF_0EES3_IS4_IKNS_14EncodingRecordEEZNKS0_6subsetESA_EUlRSN_E_SE_LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NST_6item_tEEE5valueEvE4typeELSF_0ETnPNSS_IXsr17hb_is_iterator_ofIT0_NSY_6item_tEEE5valueEvE4typeELSF_0EEEbSP_RK8hb_set_tPKvRKNS_21SubtableUnicodesCacheERS18_ST_SY_
Unexecuted instantiation: hb-ot-face.cc:_ZN2OT4cmap9_can_dropI13hb_map_iter_tI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS0_6subsetEP19hb_subset_context_tEUlS6_E_RK3$_6LPv0EERK3$_8L24hb_function_sortedness_t0ELSF_0EES3_IS4_IKNS_14EncodingRecordEEZNKS0_6subsetESA_EUlRSN_E_SE_LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NST_6item_tEEE5valueEvE4typeELSF_0ETnPNSS_IXsr17hb_is_iterator_ofIT0_NSY_6item_tEEE5valueEvE4typeELSF_0EEEbSP_RK8hb_set_tPKvRKNS_21SubtableUnicodesCacheERS18_ST_SY_
Unexecuted instantiation: hb-ot-font.cc:_ZN2OT4cmap9_can_dropI13hb_map_iter_tI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS0_6subsetEP19hb_subset_context_tEUlS6_E_RK3$_6LPv0EERK3$_8L24hb_function_sortedness_t0ELSF_0EES3_IS4_IKNS_14EncodingRecordEEZNKS0_6subsetESA_EUlRSN_E_SE_LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NST_6item_tEEE5valueEvE4typeELSF_0ETnPNSS_IXsr17hb_is_iterator_ofIT0_NSY_6item_tEEE5valueEvE4typeELSF_0EEEbSP_RK8hb_set_tPKvRKNS_21SubtableUnicodesCacheERS18_ST_SY_
Unexecuted instantiation: hb-static.cc:_ZN2OT4cmap9_can_dropI13hb_map_iter_tI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS0_6subsetEP19hb_subset_context_tEUlS6_E_RK3$_6LPv0EERK3$_8L24hb_function_sortedness_t0ELSF_0EES3_IS4_IKNS_14EncodingRecordEEZNKS0_6subsetESA_EUlRSN_E_SE_LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NST_6item_tEEE5valueEvE4typeELSF_0ETnPNSS_IXsr17hb_is_iterator_ofIT0_NSY_6item_tEEE5valueEvE4typeELSF_0EEEbSP_RK8hb_set_tPKvRKNS_21SubtableUnicodesCacheERS18_ST_SY_
Unexecuted instantiation: hb-subset.cc:_ZN2OT4cmap9_can_dropI13hb_map_iter_tI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS0_6subsetEP19hb_subset_context_tEUlS6_E_RK3$_6LPv0EERK3$_9L24hb_function_sortedness_t0ELSF_0EES3_IS4_IKNS_14EncodingRecordEEZNKS0_6subsetESA_EUlRSN_E_SE_LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NST_6item_tEEE5valueEvE4typeELSF_0ETnPNSS_IXsr17hb_is_iterator_ofIT0_NSY_6item_tEEE5valueEvE4typeELSF_0EEEbSP_RK8hb_set_tPKvRKNS_21SubtableUnicodesCacheERS18_ST_SY_
Unexecuted instantiation: hb-subset-plan.cc:_ZN2OT4cmap9_can_dropI13hb_map_iter_tI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS0_6subsetEP19hb_subset_context_tEUlS6_E_RK3$_5LPv0EERK3$_8L24hb_function_sortedness_t0ELSF_0EES3_IS4_IKNS_14EncodingRecordEEZNKS0_6subsetESA_EUlRSN_E_SE_LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NST_6item_tEEE5valueEvE4typeELSF_0ETnPNSS_IXsr17hb_is_iterator_ofIT0_NSY_6item_tEEE5valueEvE4typeELSF_0EEEbSP_RK8hb_set_tPKvRKNS_21SubtableUnicodesCacheERS18_ST_SY_
Unexecuted instantiation: hb-subset-table-other.cc:_ZN2OT4cmap9_can_dropI13hb_map_iter_tI16hb_filter_iter_tI17hb_sorted_array_tIK9hb_pair_tIjjEEZNKS0_6subsetEP19hb_subset_context_tEUlS6_E_RK3$_6LPv0EERK3$_9L24hb_function_sortedness_t0ELSF_0EES3_IS4_IKNS_14EncodingRecordEEZNKS0_6subsetESA_EUlRSN_E_SE_LSF_0EETnPN12hb_enable_ifIXsr17hb_is_iterator_ofIT_NST_6item_tEEE5valueEvE4typeELSF_0ETnPNSS_IXsr17hb_is_iterator_ofIT0_NSY_6item_tEEE5valueEvE4typeELSF_0EEEbSP_RK8hb_set_tPKvRKNS_21SubtableUnicodesCacheERS18_ST_SY_
1939
1940
  void closure_glyphs (const hb_set_t      *unicodes,
1941
           hb_set_t            *glyphset) const
1942
6.57k
  {
1943
6.57k
    + hb_iter (encodingRecord)
1944
6.57k
    | hb_map (&EncodingRecord::subtable)
1945
6.57k
    | hb_map (hb_add (this))
1946
19.7k
    | hb_filter ([&] (const CmapSubtable& _) { return _.u.format.v == 14; })
1947
6.57k
    | hb_apply ([=] (const CmapSubtable& _) { _.u.format14.closure_glyphs (unicodes, glyphset); })
1948
6.57k
    ;
1949
6.57k
  }
1950
1951
  bool subset (hb_subset_context_t *c) const
1952
0
  {
1953
0
    TRACE_SUBSET (this);
1954
1955
0
    cmap *cmap_prime = c->serializer->start_embed<cmap> ();
1956
1957
0
    auto encodingrec_iter =
1958
0
    + hb_iter (encodingRecord)
1959
0
    | hb_filter ([&](const EncodingRecord& _) {
1960
0
      return cmap::filter_encoding_records_for_subset (this, _);
1961
0
    })
1962
0
    ;
1963
1964
0
    if (unlikely (!encodingrec_iter.len ())) return_trace (false);
1965
1966
0
    const EncodingRecord *unicode_bmp= nullptr, *unicode_ucs4 = nullptr, *ms_bmp = nullptr, *ms_ucs4 = nullptr;
1967
0
    bool has_format12 = false;
1968
1969
0
    for (const EncodingRecord& _ : encodingrec_iter)
1970
0
    {
1971
0
      unsigned format = (this + _.subtable).u.format.v;
1972
0
      if (format == 12) has_format12 = true;
1973
1974
0
      const EncodingRecord *table = std::addressof (_);
1975
0
      if      (_.platformID == 0 && _.encodingID ==  3) unicode_bmp = table;
1976
0
      else if (_.platformID == 0 && _.encodingID ==  4) unicode_ucs4 = table;
1977
0
      else if (_.platformID == 3 && _.encodingID ==  1) ms_bmp = table;
1978
0
      else if (_.platformID == 3 && _.encodingID == 10) ms_ucs4 = table;
1979
0
    }
1980
1981
0
    if (unlikely (!has_format12 && !unicode_bmp && !ms_bmp)) return_trace (false);
1982
0
    if (unlikely (has_format12 && (!unicode_ucs4 && !ms_ucs4))) return_trace (false);
1983
1984
0
    auto it =
1985
0
    + c->plan->unicode_to_new_gid_list.iter ()
1986
0
    | hb_filter ([&] (const hb_codepoint_pair_t _)
1987
0
     { return (_.second != HB_MAP_VALUE_INVALID); })
1988
0
    ;
1989
1990
0
    return_trace (cmap_prime->serialize (c->serializer,
1991
0
                                         it,
1992
0
                                         encodingrec_iter,
1993
0
                                         this,
1994
0
                                         c->plan,
1995
0
           false,
1996
0
           c->source_blob->length));
1997
0
  }
1998
1999
  const CmapSubtable *find_best_subtable (bool *symbol = nullptr,
2000
            bool *mac = nullptr,
2001
            bool *macroman = nullptr) const
2002
13.2k
  {
2003
13.2k
    if (symbol) *symbol = false;
2004
13.2k
    if (mac) *mac = false;
2005
13.2k
    if (macroman) *macroman = false;
2006
2007
13.2k
    const CmapSubtable *subtable;
2008
2009
    /* Symbol subtable.
2010
     * Prefer symbol if available.
2011
     * https://github.com/harfbuzz/harfbuzz/issues/1918 */
2012
13.2k
    if ((subtable = this->find_subtable (3, 0)))
2013
0
    {
2014
0
      if (symbol) *symbol = true;
2015
0
      return subtable;
2016
0
    }
2017
2018
    /* 32-bit subtables. */
2019
13.2k
    if ((subtable = this->find_subtable (3, 10))) return subtable;
2020
13.2k
    if ((subtable = this->find_subtable (0, 6))) return subtable;
2021
13.2k
    if ((subtable = this->find_subtable (0, 4))) return subtable;
2022
2023
    /* 16-bit subtables. */
2024
13.2k
    if ((subtable = this->find_subtable (3, 1))) return subtable;
2025
0
    if ((subtable = this->find_subtable (0, 3))) return subtable;
2026
0
    if ((subtable = this->find_subtable (0, 2))) return subtable;
2027
0
    if ((subtable = this->find_subtable (0, 1))) return subtable;
2028
0
    if ((subtable = this->find_subtable (0, 0))) return subtable;
2029
2030
    /* MacRoman subtable. */
2031
0
    if ((subtable = this->find_subtable (1, 0)))
2032
0
    {
2033
0
      if (mac) *mac = true;
2034
0
      if (macroman) *macroman = true;
2035
0
      return subtable;
2036
0
    }
2037
    /* Any other Mac subtable; we just map ASCII for these. */
2038
0
    if ((subtable = this->find_subtable (1, 0xFFFF)))
2039
0
    {
2040
0
      if (mac) *mac = true;
2041
0
      return subtable;
2042
0
    }
2043
2044
    /* Meh. */
2045
0
    return &Null (CmapSubtable);
2046
0
  }
2047
2048
  struct accelerator_t
2049
  {
2050
    using cache_t = hb_cache_t<21, 19>;
2051
    static_assert (sizeof (cache_t) == 1024, "");
2052
2053
    accelerator_t (hb_face_t *face)
2054
13.2k
    {
2055
13.2k
      this->table = hb_sanitize_context_t ().reference_table<cmap> (face);
2056
13.2k
      bool symbol, mac, macroman;
2057
13.2k
      this->subtable = table->find_best_subtable (&symbol, &mac, &macroman);
2058
13.2k
      this->subtable_uvs = &Null (CmapSubtableFormat14);
2059
13.2k
      {
2060
13.2k
  const CmapSubtable *st = table->find_subtable (0, 5);
2061
13.2k
  if (st && st->u.format.v == 14)
2062
0
    subtable_uvs = &st->u.format14;
2063
13.2k
      }
2064
2065
13.2k
#ifndef HB_NO_OT_FONT_CMAP_CACHE
2066
13.2k
      cache = (cache_t *) hb_malloc (sizeof (cache_t));
2067
13.2k
      if (cache)
2068
13.2k
  new (cache) cache_t ();
2069
0
      else
2070
0
        return; // Such that get_glyph_funcZ remains null.
2071
13.2k
#endif
2072
2073
13.2k
      this->get_glyph_data = subtable;
2074
13.2k
#ifndef HB_NO_CMAP_LEGACY_SUBTABLES
2075
13.2k
      bool is_format4 = subtable->u.format.v == 4;
2076
13.2k
      auto set_format4_getter = [this] (bool (*func) (const void *,
2077
13.2k
                  hb_codepoint_t,
2078
13.2k
                  hb_codepoint_t *))
2079
13.2k
      {
2080
0
  this->format4_accel.init (&this->subtable->u.format4,
2081
0
          get_subtable_data_size (this->subtable));
2082
0
  this->get_glyph_data = &this->format4_accel;
2083
0
  this->get_glyph_funcZ = func;
2084
0
      };
2085
13.2k
      if (unlikely (symbol))
2086
0
      {
2087
0
  switch ((unsigned) face->table.OS2->get_font_page ()) {
2088
0
  case OS2::font_page_t::FONT_PAGE_NONE:
2089
0
    if (is_format4)
2090
0
      set_format4_getter (get_glyph_from_symbol<CmapSubtableFormat4::accelerator_t, _hb_symbol_pua_map>);
2091
0
    else
2092
0
      this->get_glyph_funcZ = get_glyph_from_symbol<CmapSubtable, _hb_symbol_pua_map>;
2093
0
    break;
2094
0
#ifndef HB_NO_OT_SHAPER_ARABIC_FALLBACK
2095
0
  case OS2::font_page_t::FONT_PAGE_SIMP_ARABIC:
2096
0
    if (is_format4)
2097
0
      set_format4_getter (get_glyph_from_symbol<CmapSubtableFormat4::accelerator_t, _hb_arabic_pua_simp_map>);
2098
0
    else
2099
0
      this->get_glyph_funcZ = get_glyph_from_symbol<CmapSubtable, _hb_arabic_pua_simp_map>;
2100
0
    break;
2101
0
  case OS2::font_page_t::FONT_PAGE_TRAD_ARABIC:
2102
0
    if (is_format4)
2103
0
      set_format4_getter (get_glyph_from_symbol<CmapSubtableFormat4::accelerator_t, _hb_arabic_pua_trad_map>);
2104
0
    else
2105
0
      this->get_glyph_funcZ = get_glyph_from_symbol<CmapSubtable, _hb_arabic_pua_trad_map>;
2106
0
    break;
2107
0
#endif
2108
0
  default:
2109
0
    if (is_format4)
2110
0
      set_format4_getter (get_glyph_from<CmapSubtableFormat4::accelerator_t>);
2111
0
    else
2112
0
      this->get_glyph_funcZ = get_glyph_from<CmapSubtable>;
2113
0
    break;
2114
0
  }
2115
0
      }
2116
13.2k
      else if (unlikely (macroman))
2117
0
      {
2118
0
  if (is_format4)
2119
0
    set_format4_getter (get_glyph_from_macroman<CmapSubtableFormat4::accelerator_t>);
2120
0
  else
2121
0
    this->get_glyph_funcZ = get_glyph_from_macroman<CmapSubtable>;
2122
0
      }
2123
13.2k
      else if (unlikely (mac))
2124
0
      {
2125
0
  if (is_format4)
2126
0
    set_format4_getter (get_glyph_from_ascii<CmapSubtableFormat4::accelerator_t>);
2127
0
  else
2128
0
    this->get_glyph_funcZ = get_glyph_from_ascii<CmapSubtable>;
2129
0
      }
2130
13.2k
      else
2131
13.2k
#endif
2132
13.2k
      {
2133
13.2k
  switch (subtable->u.format.v) {
2134
    /* Accelerate format 4 and format 12. */
2135
0
    default:
2136
0
      this->get_glyph_funcZ = get_glyph_from<CmapSubtable>;
2137
0
      break;
2138
0
    case 12:
2139
0
      this->get_glyph_funcZ = get_glyph_from<CmapSubtableFormat12>;
2140
0
      break;
2141
13.2k
    case  4:
2142
13.2k
    {
2143
13.2k
      this->format4_accel.init (&subtable->u.format4,
2144
13.2k
              get_subtable_data_size (subtable));
2145
13.2k
      this->get_glyph_data = &this->format4_accel;
2146
13.2k
      this->get_glyph_funcZ = this->format4_accel.get_glyph_func;
2147
13.2k
      break;
2148
0
    }
2149
13.2k
  }
2150
13.2k
      }
2151
13.2k
    }
2152
    ~accelerator_t ()
2153
13.1k
    {
2154
13.1k
#ifndef HB_NO_OT_FONT_CMAP_CACHE
2155
13.1k
      hb_free (cache);
2156
13.1k
#endif
2157
13.1k
      table.destroy ();
2158
13.1k
    }
2159
2160
    inline bool _cached_get (hb_codepoint_t unicode,
2161
           hb_codepoint_t *glyph) const
2162
392M
    {
2163
392M
#ifndef HB_NO_OT_FONT_CMAP_CACHE
2164
      // cache is always non-null if we have a get_glyph_funcZ
2165
392M
      unsigned v;
2166
392M
      if (cache->get (unicode, &v))
2167
333M
      {
2168
333M
        *glyph = v;
2169
333M
  return true;
2170
333M
      }
2171
59.7M
#endif
2172
59.7M
      bool ret  = this->get_glyph_funcZ (this->get_glyph_data, unicode, glyph);
2173
2174
59.7M
#ifndef HB_NO_OT_FONT_CMAP_CACHE
2175
59.7M
      if (ret)
2176
1.46M
        cache->set (unicode, *glyph);
2177
59.7M
#endif
2178
2179
59.7M
      return ret;
2180
392M
    }
2181
2182
    bool get_nominal_glyph (hb_codepoint_t  unicode,
2183
          hb_codepoint_t *glyph) const
2184
115M
    {
2185
115M
      if (unlikely (!this->get_glyph_funcZ)) return false;
2186
115M
      return _cached_get (unicode, glyph);
2187
115M
    }
2188
2189
    unsigned int get_nominal_glyphs (unsigned int count,
2190
             const hb_codepoint_t *first_unicode,
2191
             unsigned int unicode_stride,
2192
             hb_codepoint_t *first_glyph,
2193
             unsigned int glyph_stride) const
2194
31.1M
    {
2195
31.1M
      if (unlikely (!this->get_glyph_funcZ)) return 0;
2196
2197
31.1M
      unsigned int done;
2198
31.1M
      for (done = 0;
2199
295M
     done < count && _cached_get (*first_unicode, first_glyph);
2200
264M
     done++)
2201
264M
      {
2202
264M
  first_unicode = &StructAtOffsetUnaligned<hb_codepoint_t> (first_unicode, unicode_stride);
2203
264M
  first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
2204
264M
      }
2205
31.1M
      return done;
2206
31.1M
    }
2207
2208
    bool get_variation_glyph (hb_codepoint_t  unicode,
2209
            hb_codepoint_t  variation_selector,
2210
            hb_codepoint_t *glyph) const
2211
25.0k
    {
2212
25.0k
      switch (this->subtable_uvs->get_glyph_variant (unicode,
2213
25.0k
                 variation_selector,
2214
25.0k
                 glyph))
2215
25.0k
      {
2216
25.0k
  case GLYPH_VARIANT_NOT_FOUND: return false;
2217
0
  case GLYPH_VARIANT_FOUND: return true;
2218
0
  case GLYPH_VARIANT_USE_DEFAULT: break;
2219
25.0k
      }
2220
2221
0
      return get_nominal_glyph (unicode, glyph);
2222
25.0k
    }
2223
2224
    void collect_unicodes (hb_set_t *out, unsigned int num_glyphs) const
2225
5
    { subtable->collect_unicodes (out, num_glyphs, get_subtable_data_size (subtable)); }
2226
    void collect_mapping (hb_set_t *unicodes, hb_map_t *mapping,
2227
        unsigned num_glyphs = UINT_MAX) const
2228
6.57k
    { subtable->collect_mapping (unicodes, mapping, num_glyphs, get_subtable_data_size (subtable)); }
2229
    void collect_variation_selectors (hb_set_t *out) const
2230
6.57k
    { subtable_uvs->collect_variation_selectors (out); }
2231
    void collect_variation_unicodes (hb_codepoint_t variation_selector,
2232
             hb_set_t *out) const
2233
0
    { subtable_uvs->collect_variation_unicodes (variation_selector, out); }
2234
2235
    protected:
2236
    typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
2237
                hb_codepoint_t codepoint,
2238
                hb_codepoint_t *glyph);
2239
    typedef uint16_t (*hb_pua_remap_func_t) (unsigned);
2240
2241
    template <typename Type>
2242
    HB_INTERNAL static bool get_glyph_from (const void *obj,
2243
              hb_codepoint_t codepoint,
2244
              hb_codepoint_t *glyph)
2245
0
    {
2246
0
      const Type *typed_obj = (const Type *) obj;
2247
0
      return typed_obj->get_glyph (codepoint, glyph);
2248
0
    }
Unexecuted instantiation: bool OT::cmap::accelerator_t::get_glyph_from<OT::CmapSubtableFormat4::accelerator_t>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: bool OT::cmap::accelerator_t::get_glyph_from<OT::CmapSubtable>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: bool OT::cmap::accelerator_t::get_glyph_from<OT::CmapSubtableFormat12>(void const*, unsigned int, unsigned int*)
2249
2250
    template <typename Type, hb_pua_remap_func_t remap>
2251
    HB_INTERNAL static bool get_glyph_from_symbol (const void *obj,
2252
               hb_codepoint_t codepoint,
2253
               hb_codepoint_t *glyph)
2254
0
    {
2255
0
      const Type *typed_obj = (const Type *) obj;
2256
0
      if (likely (typed_obj->get_glyph (codepoint, glyph)))
2257
0
  return true;
2258
2259
0
      if (hb_codepoint_t c = remap (codepoint))
2260
0
  return typed_obj->get_glyph (c, glyph);
2261
2262
0
      return false;
2263
0
    }
Unexecuted instantiation: hb-face.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &OT::_hb_symbol_pua_map>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-face.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &OT::_hb_symbol_pua_map>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-face.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &(_hb_arabic_pua_simp_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-face.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &(_hb_arabic_pua_simp_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-face.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &(_hb_arabic_pua_trad_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-face.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &(_hb_arabic_pua_trad_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-ot-face.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &OT::_hb_symbol_pua_map>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-ot-face.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &OT::_hb_symbol_pua_map>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-ot-face.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &(_hb_arabic_pua_simp_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-ot-face.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &(_hb_arabic_pua_simp_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-ot-face.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &(_hb_arabic_pua_trad_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-ot-face.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &(_hb_arabic_pua_trad_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-ot-font.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &OT::_hb_symbol_pua_map>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-ot-font.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &OT::_hb_symbol_pua_map>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-ot-font.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &(_hb_arabic_pua_simp_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-ot-font.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &(_hb_arabic_pua_simp_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-ot-font.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &(_hb_arabic_pua_trad_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-ot-font.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &(_hb_arabic_pua_trad_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-static.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &OT::_hb_symbol_pua_map>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-static.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &OT::_hb_symbol_pua_map>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-static.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &(_hb_arabic_pua_simp_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-static.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &(_hb_arabic_pua_simp_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-static.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &(_hb_arabic_pua_trad_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-static.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &(_hb_arabic_pua_trad_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-subset.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &OT::_hb_symbol_pua_map>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-subset.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &OT::_hb_symbol_pua_map>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-subset.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &(_hb_arabic_pua_simp_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-subset.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &(_hb_arabic_pua_simp_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-subset.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &(_hb_arabic_pua_trad_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-subset.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &(_hb_arabic_pua_trad_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-subset-plan.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &OT::_hb_symbol_pua_map>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-subset-plan.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &OT::_hb_symbol_pua_map>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-subset-plan.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &(_hb_arabic_pua_simp_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-subset-plan.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &(_hb_arabic_pua_simp_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-subset-plan.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &(_hb_arabic_pua_trad_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-subset-plan.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &(_hb_arabic_pua_trad_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-subset-table-other.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &OT::_hb_symbol_pua_map>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-subset-table-other.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &OT::_hb_symbol_pua_map>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-subset-table-other.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &(_hb_arabic_pua_simp_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-subset-table-other.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &(_hb_arabic_pua_simp_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-subset-table-other.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtableFormat4::accelerator_t, &(_hb_arabic_pua_trad_map(unsigned int))>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: hb-subset-table-other.cc:bool OT::cmap::accelerator_t::get_glyph_from_symbol<OT::CmapSubtable, &(_hb_arabic_pua_trad_map(unsigned int))>(void const*, unsigned int, unsigned int*)
2264
2265
    template <typename Type>
2266
    HB_INTERNAL static bool get_glyph_from_ascii (const void *obj,
2267
              hb_codepoint_t codepoint,
2268
              hb_codepoint_t *glyph)
2269
0
    {
2270
0
      const Type *typed_obj = (const Type *) obj;
2271
0
      return codepoint < 0x80 && typed_obj->get_glyph (codepoint, glyph);
2272
0
    }
Unexecuted instantiation: bool OT::cmap::accelerator_t::get_glyph_from_ascii<OT::CmapSubtableFormat4::accelerator_t>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: bool OT::cmap::accelerator_t::get_glyph_from_ascii<OT::CmapSubtable>(void const*, unsigned int, unsigned int*)
2273
2274
    template <typename Type>
2275
    HB_INTERNAL static bool get_glyph_from_macroman (const void *obj,
2276
                 hb_codepoint_t codepoint,
2277
                 hb_codepoint_t *glyph)
2278
0
    {
2279
0
      if (get_glyph_from_ascii<Type> (obj, codepoint, glyph))
2280
0
  return true;
2281
2282
0
      const Type *typed_obj = (const Type *) obj;
2283
0
      unsigned c = unicode_to_macroman (codepoint);
2284
0
      return c && typed_obj->get_glyph (c, glyph);
2285
0
    }
Unexecuted instantiation: bool OT::cmap::accelerator_t::get_glyph_from_macroman<OT::CmapSubtableFormat4::accelerator_t>(void const*, unsigned int, unsigned int*)
Unexecuted instantiation: bool OT::cmap::accelerator_t::get_glyph_from_macroman<OT::CmapSubtable>(void const*, unsigned int, unsigned int*)
2286
2287
    unsigned int get_subtable_data_size (const CmapSubtable *subtable) const
2288
19.7k
    {
2289
19.7k
      unsigned int table_length = this->table.get_length ();
2290
19.7k
      uintptr_t table_start = (uintptr_t) (const void *) this->table.get ();
2291
19.7k
      uintptr_t subtable_addr = (uintptr_t) (const void *) subtable;
2292
19.7k
      if (unlikely (subtable_addr < table_start))
2293
0
  return 0;
2294
2295
19.7k
      uintptr_t subtable_offset = subtable_addr - table_start;
2296
19.7k
      if (unlikely (subtable_offset >= table_length))
2297
0
  return 0;
2298
2299
19.7k
      return table_length - (unsigned int) subtable_offset;
2300
19.7k
    }
2301
2302
    private:
2303
    hb_nonnull_ptr_t<const CmapSubtable> subtable;
2304
    hb_nonnull_ptr_t<const CmapSubtableFormat14> subtable_uvs;
2305
2306
    hb_cmap_get_glyph_func_t get_glyph_funcZ = nullptr;
2307
    const void *get_glyph_data = nullptr;
2308
2309
    CmapSubtableFormat4::accelerator_t format4_accel;
2310
2311
#ifndef HB_NO_OT_FONT_CMAP_CACHE
2312
    cache_t *cache = nullptr;
2313
#endif
2314
2315
    public:
2316
    hb_blob_ptr_t<cmap> table;
2317
  };
2318
2319
  protected:
2320
2321
  const CmapSubtable *find_subtable (unsigned int platform_id,
2322
             unsigned int encoding_id) const
2323
79.2k
  {
2324
79.2k
    EncodingRecord key;
2325
79.2k
    key.platformID = platform_id;
2326
79.2k
    key.encodingID = encoding_id;
2327
2328
79.2k
    const EncodingRecord &result = encodingRecord.bsearch (key);
2329
79.2k
    if (!result.subtable)
2330
66.0k
      return nullptr;
2331
2332
13.2k
    return &(this+result.subtable);
2333
79.2k
  }
2334
2335
  public:
2336
2337
  bool sanitize (hb_sanitize_context_t *c) const
2338
13.2k
  {
2339
13.2k
    TRACE_SANITIZE (this);
2340
13.2k
    return_trace (c->check_struct (this) &&
2341
13.2k
      hb_barrier () &&
2342
13.2k
      likely (version == 0) &&
2343
13.2k
      encodingRecord.sanitize (c, this));
2344
13.2k
  }
2345
2346
 private:
2347
2348
  static bool filter_encoding_records_for_subset(const cmap* cmap,
2349
                                                 const EncodingRecord& _)
2350
0
  {
2351
0
    return
2352
0
        (_.platformID == 0 && _.encodingID == 3) ||
2353
0
        (_.platformID == 0 && _.encodingID == 4) ||
2354
0
        (_.platformID == 3 && _.encodingID == 1) ||
2355
0
        (_.platformID == 3 && _.encodingID == 10) ||
2356
0
        (cmap + _.subtable).u.format.v == 14;
2357
0
  }
2358
2359
  protected:
2360
  HBUINT16  version;  /* Table version number (0). */
2361
  SortedArray16Of<EncodingRecord>
2362
    encodingRecord; /* Encoding tables. */
2363
  public:
2364
  DEFINE_SIZE_ARRAY (4, encodingRecord);
2365
};
2366
2367
struct cmap_accelerator_t : cmap::accelerator_t {
2368
63
  cmap_accelerator_t (hb_face_t *face) : cmap::accelerator_t (face) {}
2369
};
2370
2371
} /* namespace OT */
2372
2373
2374
#endif /* HB_OT_CMAP_TABLE_HH */