Coverage Report

Created: 2025-08-25 07:11

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