Coverage Report

Created: 2024-01-23 06:24

/src/harfbuzz/src/hb-ot-cff1-table.hh
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright © 2018 Adobe 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
 * Adobe Author(s): Michiharu Ariza
25
 */
26
27
#ifndef HB_OT_CFF1_TABLE_HH
28
#define HB_OT_CFF1_TABLE_HH
29
30
#include "hb-ot-cff-common.hh"
31
#include "hb-subset-cff1.hh"
32
#include "hb-draw.hh"
33
#include "hb-paint.hh"
34
35
#define HB_STRING_ARRAY_NAME cff1_std_strings
36
#define HB_STRING_ARRAY_LIST "hb-ot-cff1-std-str.hh"
37
#include "hb-string-array.hh"
38
#undef HB_STRING_ARRAY_LIST
39
#undef HB_STRING_ARRAY_NAME
40
41
namespace CFF {
42
43
/*
44
 * CFF -- Compact Font Format (CFF)
45
 * https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf
46
 */
47
#define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ')
48
49
28.6M
#define CFF_UNDEF_SID   CFF_UNDEF_CODE
50
51
enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
52
enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };
53
54
typedef CFFIndex<HBUINT16>  CFF1Index;
55
template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type> {};
56
57
typedef CFFIndex<HBUINT16> CFF1Index;
58
typedef CFF1Index          CFF1CharStrings;
59
typedef Subrs<HBUINT16>    CFF1Subrs;
60
61
struct CFF1FDSelect : FDSelect {};
62
63
/* Encoding */
64
struct Encoding0 {
65
  bool sanitize (hb_sanitize_context_t *c) const
66
1.14k
  {
67
1.14k
    TRACE_SANITIZE (this);
68
1.14k
    return_trace (codes.sanitize (c));
69
1.14k
  }
70
71
  hb_codepoint_t get_code (hb_codepoint_t glyph) const
72
0
  {
73
0
    assert (glyph > 0);
74
0
    glyph--;
75
0
    if (glyph < nCodes ())
76
0
    {
77
0
      return (hb_codepoint_t)codes[glyph];
78
0
    }
79
0
    else
80
0
      return CFF_UNDEF_CODE;
81
0
  }
82
83
0
  HBUINT8 &nCodes () { return codes.len; }
84
678
  HBUINT8 nCodes () const { return codes.len; }
85
86
  ArrayOf<HBUINT8, HBUINT8> codes;
87
88
  DEFINE_SIZE_ARRAY_SIZED (1, codes);
89
};
90
91
struct Encoding1_Range {
92
  bool sanitize (hb_sanitize_context_t *c) const
93
0
  {
94
0
    TRACE_SANITIZE (this);
95
0
    return_trace (c->check_struct (this));
96
0
  }
97
98
  HBUINT8   first;
99
  HBUINT8   nLeft;
100
101
  DEFINE_SIZE_STATIC (2);
102
};
103
104
struct Encoding1 {
105
  bool sanitize (hb_sanitize_context_t *c) const
106
597
  {
107
597
    TRACE_SANITIZE (this);
108
597
    return_trace (ranges.sanitize (c));
109
597
  }
110
111
  hb_codepoint_t get_code (hb_codepoint_t glyph) const
112
0
  {
113
0
    assert (glyph > 0);
114
0
    glyph--;
115
0
    for (unsigned int i = 0; i < nRanges (); i++)
116
0
    {
117
0
      if (glyph <= ranges[i].nLeft)
118
0
      {
119
0
  hb_codepoint_t code = (hb_codepoint_t) ranges[i].first + glyph;
120
0
  return (likely (code < 0x100) ? code: CFF_UNDEF_CODE);
121
0
      }
122
0
      glyph -= (ranges[i].nLeft + 1);
123
0
    }
124
0
    return CFF_UNDEF_CODE;
125
0
  }
126
127
0
  HBUINT8 &nRanges () { return ranges.len; }
128
57
  HBUINT8 nRanges () const { return ranges.len; }
129
130
  ArrayOf<Encoding1_Range, HBUINT8> ranges;
131
132
  DEFINE_SIZE_ARRAY_SIZED (1, ranges);
133
};
134
135
struct SuppEncoding {
136
  bool sanitize (hb_sanitize_context_t *c) const
137
0
  {
138
0
    TRACE_SANITIZE (this);
139
0
    return_trace (c->check_struct (this));
140
0
  }
141
142
  HBUINT8   code;
143
  HBUINT16  glyph;
144
145
  DEFINE_SIZE_STATIC (3);
146
};
147
148
struct CFF1SuppEncData {
149
  bool sanitize (hb_sanitize_context_t *c) const
150
735
  {
151
735
    TRACE_SANITIZE (this);
152
735
    return_trace (supps.sanitize (c));
153
735
  }
154
155
  void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
156
0
  {
157
0
    for (unsigned int i = 0; i < nSups (); i++)
158
0
      if (sid == supps[i].glyph)
159
0
  codes.push (supps[i].code);
160
0
  }
161
162
0
  HBUINT8 &nSups () { return supps.len; }
163
0
  HBUINT8 nSups () const { return supps.len; }
164
165
  ArrayOf<SuppEncoding, HBUINT8> supps;
166
167
  DEFINE_SIZE_ARRAY_SIZED (1, supps);
168
};
169
170
struct Encoding
171
{
172
  /* serialize a fullset Encoding */
173
  bool serialize (hb_serialize_context_t *c, const Encoding &src)
174
0
  {
175
0
    TRACE_SERIALIZE (this);
176
0
    unsigned int size = src.get_size ();
177
0
    Encoding *dest = c->allocate_size<Encoding> (size);
178
0
    if (unlikely (!dest)) return_trace (false);
179
0
    hb_memcpy (dest, &src, size);
180
0
    return_trace (true);
181
0
  }
182
183
  /* serialize a subset Encoding */
184
  bool serialize (hb_serialize_context_t *c,
185
      uint8_t format,
186
      unsigned int enc_count,
187
      const hb_vector_t<code_pair_t>& code_ranges,
188
      const hb_vector_t<code_pair_t>& supp_codes)
189
0
  {
190
0
    TRACE_SERIALIZE (this);
191
0
    Encoding *dest = c->extend_min (this);
192
0
    if (unlikely (!dest)) return_trace (false);
193
0
    dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
194
0
    switch (format) {
195
0
    case 0:
196
0
    {
197
0
      Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
198
0
      if (unlikely (!fmt0)) return_trace (false);
199
0
      fmt0->nCodes () = enc_count;
200
0
      unsigned int glyph = 0;
201
0
      for (unsigned int i = 0; i < code_ranges.length; i++)
202
0
      {
203
0
  hb_codepoint_t code = code_ranges[i].code;
204
0
  for (int left = (int)code_ranges[i].glyph; left >= 0; left--)
205
0
    fmt0->codes[glyph++] = code++;
206
0
  if (unlikely (!((glyph <= 0x100) && (code <= 0x100))))
207
0
    return_trace (false);
208
0
      }
209
0
    }
210
0
    break;
211
0
212
0
    case 1:
213
0
    {
214
0
      Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
215
0
      if (unlikely (!fmt1)) return_trace (false);
216
0
      fmt1->nRanges () = code_ranges.length;
217
0
      for (unsigned int i = 0; i < code_ranges.length; i++)
218
0
      {
219
0
  if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF))))
220
0
    return_trace (false);
221
0
  fmt1->ranges[i].first = code_ranges[i].code;
222
0
  fmt1->ranges[i].nLeft = code_ranges[i].glyph;
223
0
      }
224
0
    }
225
0
    break;
226
0
227
0
    }
228
0
229
0
    if (supp_codes.length)
230
0
    {
231
0
      CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
232
0
      if (unlikely (!suppData)) return_trace (false);
233
0
      suppData->nSups () = supp_codes.length;
234
0
      for (unsigned int i = 0; i < supp_codes.length; i++)
235
0
      {
236
0
  suppData->supps[i].code = supp_codes[i].code;
237
0
  suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */
238
0
      }
239
0
    }
240
0
241
0
    return_trace (true);
242
0
  }
243
244
  unsigned int get_size () const
245
0
  {
246
0
    unsigned int size = min_size;
247
0
    switch (table_format ())
248
0
    {
249
0
    case 0: size += u.format0.get_size (); break;
250
0
    case 1: size += u.format1.get_size (); break;
251
0
    }
252
0
    if (has_supplement ())
253
0
      size += suppEncData ().get_size ();
254
0
    return size;
255
0
  }
256
257
  hb_codepoint_t get_code (hb_codepoint_t glyph) const
258
0
  {
259
0
    switch (table_format ())
260
0
    {
261
0
    case 0: return u.format0.get_code (glyph);
262
0
    case 1: return u.format1.get_code (glyph);
263
0
    default:return 0;
264
0
    }
265
0
  }
266
267
2.73k
  uint8_t table_format () const { return format & 0x7F; }
268
1.63k
  bool  has_supplement () const { return format & 0x80; }
269
270
  void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
271
0
  {
272
0
    codes.resize (0);
273
0
    if (has_supplement ())
274
0
      suppEncData().get_codes (sid, codes);
275
0
  }
276
277
  bool sanitize (hb_sanitize_context_t *c) const
278
2.07k
  {
279
2.07k
    TRACE_SANITIZE (this);
280
2.07k
    if (unlikely (!c->check_struct (this)))
281
77
      return_trace (false);
282
283
1.99k
    switch (table_format ())
284
1.99k
    {
285
1.14k
    case 0: if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break;
286
1.08k
    case 1: if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break;
287
549
    default:return_trace (false);
288
1.99k
    }
289
1.99k
    return_trace (likely (!has_supplement () || suppEncData ().sanitize (c)));
290
1.99k
  }
291
292
  protected:
293
  const CFF1SuppEncData &suppEncData () const
294
735
  {
295
735
    switch (table_format ())
296
735
    {
297
678
    case 0: return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]);
298
57
    case 1: return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]);
299
0
    default:return Null (CFF1SuppEncData);
300
735
    }
301
735
  }
302
303
  public:
304
  HBUINT8 format;
305
  union {
306
  Encoding0 format0;
307
  Encoding1 format1;
308
  } u;
309
  /* CFF1SuppEncData  suppEncData; */
310
311
  DEFINE_SIZE_MIN (1);
312
};
313
314
/* Charset */
315
struct Charset0 {
316
  bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
317
37.4k
  {
318
37.4k
    TRACE_SANITIZE (this);
319
37.4k
    return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c));
320
37.4k
  }
321
322
  hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const
323
5.90M
  {
324
5.90M
    if (unlikely (glyph >= num_glyphs)) return 0;
325
5.90M
    if (glyph == 0)
326
29.2k
      return 0;
327
5.87M
    else
328
5.87M
      return sids[glyph - 1];
329
5.90M
  }
330
331
  void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
332
0
  {
333
0
    for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++)
334
0
      mapping->set (gid, sids[gid - 1]);
335
0
  }
336
337
  hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
338
4.23k
  {
339
4.23k
    if (sid == 0)
340
1.20k
      return 0;
341
342
92.5k
    for (unsigned int glyph = 1; glyph < num_glyphs; glyph++)
343
90.8k
    {
344
90.8k
      if (sids[glyph-1] == sid)
345
1.30k
  return glyph;
346
90.8k
    }
347
1.72k
    return 0;
348
3.03k
  }
349
350
  unsigned int get_size (unsigned int num_glyphs) const
351
0
  {
352
0
    assert (num_glyphs > 0);
353
0
    return HBUINT16::static_size * (num_glyphs - 1);
354
0
  }
355
356
  HBUINT16  sids[HB_VAR_ARRAY];
357
358
  DEFINE_SIZE_ARRAY(0, sids);
359
};
360
361
template <typename TYPE>
362
struct Charset_Range {
363
  bool sanitize (hb_sanitize_context_t *c) const
364
11.4M
  {
365
11.4M
    TRACE_SANITIZE (this);
366
11.4M
    return_trace (c->check_struct (this));
367
11.4M
  }
CFF::Charset_Range<OT::IntType<unsigned char, 1u> >::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
364
10.6M
  {
365
10.6M
    TRACE_SANITIZE (this);
366
10.6M
    return_trace (c->check_struct (this));
367
10.6M
  }
CFF::Charset_Range<OT::IntType<unsigned short, 2u> >::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
364
799k
  {
365
799k
    TRACE_SANITIZE (this);
366
799k
    return_trace (c->check_struct (this));
367
799k
  }
368
369
  HBUINT16  first;
370
  TYPE      nLeft;
371
372
  DEFINE_SIZE_STATIC (HBUINT16::static_size + TYPE::static_size);
373
};
374
375
template <typename TYPE>
376
struct Charset1_2 {
377
  bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
378
74.1k
  {
379
74.1k
    TRACE_SANITIZE (this);
380
74.1k
    if (unlikely (!c->check_struct (this)))
381
0
      return_trace (false);
382
74.1k
    num_glyphs--;
383
11.5M
    for (unsigned int i = 0; num_glyphs > 0; i++)
384
11.4M
    {
385
11.4M
      if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1)))
386
13.9k
  return_trace (false);
387
11.4M
      num_glyphs -= (ranges[i].nLeft + 1);
388
11.4M
    }
389
74.1k
    return_trace (true);
390
74.1k
  }
CFF::Charset1_2<OT::IntType<unsigned char, 1u> >::sanitize(hb_sanitize_context_t*, unsigned int) const
Line
Count
Source
378
70.9k
  {
379
70.9k
    TRACE_SANITIZE (this);
380
70.9k
    if (unlikely (!c->check_struct (this)))
381
0
      return_trace (false);
382
70.9k
    num_glyphs--;
383
10.7M
    for (unsigned int i = 0; num_glyphs > 0; i++)
384
10.6M
    {
385
10.6M
      if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1)))
386
12.1k
  return_trace (false);
387
10.6M
      num_glyphs -= (ranges[i].nLeft + 1);
388
10.6M
    }
389
58.7k
    return_trace (true);
390
70.9k
  }
CFF::Charset1_2<OT::IntType<unsigned short, 2u> >::sanitize(hb_sanitize_context_t*, unsigned int) const
Line
Count
Source
378
3.24k
  {
379
3.24k
    TRACE_SANITIZE (this);
380
3.24k
    if (unlikely (!c->check_struct (this)))
381
0
      return_trace (false);
382
3.24k
    num_glyphs--;
383
800k
    for (unsigned int i = 0; num_glyphs > 0; i++)
384
799k
    {
385
799k
      if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1)))
386
1.81k
  return_trace (false);
387
797k
      num_glyphs -= (ranges[i].nLeft + 1);
388
797k
    }
389
1.43k
    return_trace (true);
390
3.24k
  }
391
392
  hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const
393
5.78M
  {
394
5.78M
    if (unlikely (glyph >= num_glyphs)) return 0;
395
5.78M
    if (glyph == 0) return 0;
396
5.73M
    glyph--;
397
477M
    for (unsigned int i = 0;; i++)
398
483M
    {
399
483M
      if (glyph <= ranges[i].nLeft)
400
5.73M
  return (hb_codepoint_t) ranges[i].first + glyph;
401
477M
      glyph -= (ranges[i].nLeft + 1);
402
477M
    }
403
404
0
    return 0;
405
5.73M
  }
CFF::Charset1_2<OT::IntType<unsigned char, 1u> >::get_sid(unsigned int, unsigned int) const
Line
Count
Source
393
5.18M
  {
394
5.18M
    if (unlikely (glyph >= num_glyphs)) return 0;
395
5.18M
    if (glyph == 0) return 0;
396
5.13M
    glyph--;
397
412M
    for (unsigned int i = 0;; i++)
398
417M
    {
399
417M
      if (glyph <= ranges[i].nLeft)
400
5.13M
  return (hb_codepoint_t) ranges[i].first + glyph;
401
412M
      glyph -= (ranges[i].nLeft + 1);
402
412M
    }
403
404
0
    return 0;
405
5.13M
  }
CFF::Charset1_2<OT::IntType<unsigned short, 2u> >::get_sid(unsigned int, unsigned int) const
Line
Count
Source
393
596k
  {
394
596k
    if (unlikely (glyph >= num_glyphs)) return 0;
395
596k
    if (glyph == 0) return 0;
396
596k
    glyph--;
397
65.7M
    for (unsigned int i = 0;; i++)
398
66.3M
    {
399
66.3M
      if (glyph <= ranges[i].nLeft)
400
596k
  return (hb_codepoint_t) ranges[i].first + glyph;
401
65.7M
      glyph -= (ranges[i].nLeft + 1);
402
65.7M
    }
403
404
0
    return 0;
405
596k
  }
406
407
  void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
408
0
  {
409
0
    hb_codepoint_t gid = 1;
410
0
    if (gid >= num_glyphs)
411
0
      return;
412
0
    for (unsigned i = 0;; i++)
413
0
    {
414
0
      hb_codepoint_t sid = ranges[i].first;
415
0
      unsigned count = ranges[i].nLeft + 1;
416
0
      for (unsigned j = 0; j < count; j++)
417
0
  mapping->set (gid++, sid++);
418
0
419
0
      if (gid >= num_glyphs)
420
0
        break;
421
0
    }
422
0
  }
Unexecuted instantiation: CFF::Charset1_2<OT::IntType<unsigned char, 1u> >::collect_glyph_to_sid_map(hb_map_t*, unsigned int) const
Unexecuted instantiation: CFF::Charset1_2<OT::IntType<unsigned short, 2u> >::collect_glyph_to_sid_map(hb_map_t*, unsigned int) const
423
424
  hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
425
8.09k
  {
426
8.09k
    if (sid == 0) return 0;
427
7.17k
    hb_codepoint_t  glyph = 1;
428
8.39k
    for (unsigned int i = 0;; i++)
429
15.5k
    {
430
15.5k
      if (glyph >= num_glyphs)
431
1.36k
  return 0;
432
14.1k
      if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
433
5.80k
  return glyph + (sid - ranges[i].first);
434
8.39k
      glyph += (ranges[i].nLeft + 1);
435
8.39k
    }
436
437
0
    return 0;
438
7.17k
  }
CFF::Charset1_2<OT::IntType<unsigned char, 1u> >::get_glyph(unsigned int, unsigned int) const
Line
Count
Source
425
7.86k
  {
426
7.86k
    if (sid == 0) return 0;
427
6.95k
    hb_codepoint_t  glyph = 1;
428
6.95k
    for (unsigned int i = 0;; i++)
429
11.2k
    {
430
11.2k
      if (glyph >= num_glyphs)
431
1.35k
  return 0;
432
9.93k
      if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
433
5.60k
  return glyph + (sid - ranges[i].first);
434
4.33k
      glyph += (ranges[i].nLeft + 1);
435
4.33k
    }
436
437
0
    return 0;
438
6.95k
  }
CFF::Charset1_2<OT::IntType<unsigned short, 2u> >::get_glyph(unsigned int, unsigned int) const
Line
Count
Source
425
223
  {
426
223
    if (sid == 0) return 0;
427
212
    hb_codepoint_t  glyph = 1;
428
4.06k
    for (unsigned int i = 0;; i++)
429
4.27k
    {
430
4.27k
      if (glyph >= num_glyphs)
431
11
  return 0;
432
4.26k
      if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
433
201
  return glyph + (sid - ranges[i].first);
434
4.06k
      glyph += (ranges[i].nLeft + 1);
435
4.06k
    }
436
437
0
    return 0;
438
212
  }
439
440
  unsigned int get_size (unsigned int num_glyphs) const
441
0
  {
442
0
    unsigned int size = HBUINT8::static_size;
443
0
    int glyph = (int)num_glyphs;
444
0
445
0
    assert (glyph > 0);
446
0
    glyph--;
447
0
    for (unsigned int i = 0; glyph > 0; i++)
448
0
    {
449
0
      glyph -= (ranges[i].nLeft + 1);
450
0
      size += Charset_Range<TYPE>::static_size;
451
0
    }
452
0
453
0
    return size;
454
0
  }
Unexecuted instantiation: CFF::Charset1_2<OT::IntType<unsigned char, 1u> >::get_size(unsigned int) const
Unexecuted instantiation: CFF::Charset1_2<OT::IntType<unsigned short, 2u> >::get_size(unsigned int) const
455
456
  Charset_Range<TYPE>   ranges[HB_VAR_ARRAY];
457
458
  DEFINE_SIZE_ARRAY (0, ranges);
459
};
460
461
typedef Charset1_2<HBUINT8>     Charset1;
462
typedef Charset1_2<HBUINT16>    Charset2;
463
typedef Charset_Range<HBUINT8>  Charset1_Range;
464
typedef Charset_Range<HBUINT16> Charset2_Range;
465
466
struct Charset
467
{
468
  /* serialize a fullset Charset */
469
  bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
470
0
  {
471
0
    TRACE_SERIALIZE (this);
472
0
    unsigned int size = src.get_size (num_glyphs);
473
0
    Charset *dest = c->allocate_size<Charset> (size);
474
0
    if (unlikely (!dest)) return_trace (false);
475
0
    hb_memcpy (dest, &src, size);
476
0
    return_trace (true);
477
0
  }
478
479
  /* serialize a subset Charset */
480
  bool serialize (hb_serialize_context_t *c,
481
      uint8_t format,
482
      unsigned int num_glyphs,
483
      const hb_vector_t<code_pair_t>& sid_ranges)
484
0
  {
485
0
    TRACE_SERIALIZE (this);
486
0
    Charset *dest = c->extend_min (this);
487
0
    if (unlikely (!dest)) return_trace (false);
488
0
    dest->format = format;
489
0
    switch (format)
490
0
    {
491
0
    case 0:
492
0
    {
493
0
      Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
494
0
      if (unlikely (!fmt0)) return_trace (false);
495
0
      unsigned int glyph = 0;
496
0
      for (unsigned int i = 0; i < sid_ranges.length; i++)
497
0
      {
498
0
  hb_codepoint_t sid = sid_ranges[i].code;
499
0
  for (int left = (int)sid_ranges[i].glyph; left >= 0; left--)
500
0
    fmt0->sids[glyph++] = sid++;
501
0
      }
502
0
    }
503
0
    break;
504
0
505
0
    case 1:
506
0
    {
507
0
      Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length);
508
0
      if (unlikely (!fmt1)) return_trace (false);
509
0
      for (unsigned int i = 0; i < sid_ranges.length; i++)
510
0
      {
511
0
  if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
512
0
    return_trace (false);
513
0
  fmt1->ranges[i].first = sid_ranges[i].code;
514
0
  fmt1->ranges[i].nLeft = sid_ranges[i].glyph;
515
0
      }
516
0
    }
517
0
    break;
518
0
519
0
    case 2:
520
0
    {
521
0
      Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length);
522
0
      if (unlikely (!fmt2)) return_trace (false);
523
0
      for (unsigned int i = 0; i < sid_ranges.length; i++)
524
0
      {
525
0
  if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
526
0
    return_trace (false);
527
0
  fmt2->ranges[i].first = sid_ranges[i].code;
528
0
  fmt2->ranges[i].nLeft = sid_ranges[i].glyph;
529
0
      }
530
0
    }
531
0
    break;
532
0
533
0
    }
534
0
    return_trace (true);
535
0
  }
536
537
  unsigned int get_size (unsigned int num_glyphs) const
538
0
  {
539
0
    switch (format)
540
0
    {
541
0
    case 0: return min_size + u.format0.get_size (num_glyphs);
542
0
    case 1: return min_size + u.format1.get_size (num_glyphs);
543
0
    case 2: return min_size + u.format2.get_size (num_glyphs);
544
0
    default:return 0;
545
0
    }
546
0
  }
547
548
  hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs) const
549
11.6M
  {
550
11.6M
    switch (format)
551
11.6M
    {
552
5.90M
    case 0: return u.format0.get_sid (glyph, num_glyphs);
553
5.18M
    case 1: return u.format1.get_sid (glyph, num_glyphs);
554
596k
    case 2: return u.format2.get_sid (glyph, num_glyphs);
555
0
    default:return 0;
556
11.6M
    }
557
11.6M
  }
558
559
  void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
560
0
  {
561
0
    switch (format)
562
0
    {
563
0
    case 0: u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return;
564
0
    case 1: u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return;
565
0
    case 2: u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return;
566
0
    default:return;
567
0
    }
568
0
  }
569
570
  hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
571
12.3k
  {
572
12.3k
    switch (format)
573
12.3k
    {
574
4.23k
    case 0: return u.format0.get_glyph (sid, num_glyphs);
575
7.86k
    case 1: return u.format1.get_glyph (sid, num_glyphs);
576
223
    case 2: return u.format2.get_glyph (sid, num_glyphs);
577
0
    default:return 0;
578
12.3k
    }
579
12.3k
  }
580
581
  bool sanitize (hb_sanitize_context_t *c) const
582
124k
  {
583
124k
    TRACE_SANITIZE (this);
584
124k
    if (unlikely (!c->check_struct (this)))
585
1.04k
      return_trace (false);
586
587
123k
    switch (format)
588
123k
    {
589
37.4k
    case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
590
70.9k
    case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
591
3.24k
    case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
592
11.5k
    default:return_trace (false);
593
123k
    }
594
123k
  }
595
596
  HBUINT8       format;
597
  union {
598
    Charset0    format0;
599
    Charset1    format1;
600
    Charset2    format2;
601
  } u;
602
603
  DEFINE_SIZE_MIN (1);
604
};
605
606
struct CFF1StringIndex : CFF1Index
607
{
608
  bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
609
      const hb_inc_bimap_t &sidmap)
610
0
  {
611
0
    TRACE_SERIALIZE (this);
612
0
    if (unlikely ((strings.count == 0) || (sidmap.get_population () == 0)))
613
0
    {
614
0
      if (unlikely (!c->extend_min (this->count)))
615
0
  return_trace (false);
616
0
      count = 0;
617
0
      return_trace (true);
618
0
    }
619
0
620
0
    byte_str_array_t bytesArray;
621
0
    if (!bytesArray.resize (sidmap.get_population ()))
622
0
      return_trace (false);
623
0
    for (unsigned int i = 0; i < strings.count; i++)
624
0
    {
625
0
      hb_codepoint_t  j = sidmap[i];
626
0
      if (j != HB_MAP_VALUE_INVALID)
627
0
  bytesArray[j] = strings[i];
628
0
    }
629
0
630
0
    bool result = CFF1Index::serialize (c, bytesArray);
631
0
    return_trace (result);
632
0
  }
633
};
634
635
struct cff1_top_dict_interp_env_t : num_interp_env_t
636
{
637
  cff1_top_dict_interp_env_t ()
638
0
    : num_interp_env_t(), prev_offset(0), last_offset(0) {}
639
  cff1_top_dict_interp_env_t (const hb_ubytes_t &bytes)
640
260k
    : num_interp_env_t(bytes), prev_offset(0), last_offset(0) {}
641
642
  unsigned int prev_offset;
643
  unsigned int last_offset;
644
};
645
646
struct name_dict_values_t
647
{
648
  enum name_dict_val_index_t
649
  {
650
      version,
651
      notice,
652
      copyright,
653
      fullName,
654
      familyName,
655
      weight,
656
      postscript,
657
      fontName,
658
      baseFontName,
659
      registry,
660
      ordering,
661
662
      ValCount
663
  };
664
665
  void init ()
666
2.54M
  {
667
30.5M
    for (unsigned int i = 0; i < ValCount; i++)
668
27.9M
      values[i] = CFF_UNDEF_SID;
669
2.54M
  }
670
671
  unsigned int& operator[] (unsigned int i)
672
623k
  { assert (i < ValCount); return values[i]; }
673
674
  unsigned int operator[] (unsigned int i) const
675
451k
  { assert (i < ValCount); return values[i]; }
676
677
  static enum name_dict_val_index_t name_op_to_index (op_code_t op)
678
581k
  {
679
581k
    switch (op) {
680
0
      default: // can't happen - just make some compiler happy
681
116k
      case OpCode_version:
682
116k
  return version;
683
116k
      case OpCode_Notice:
684
116k
  return notice;
685
36.8k
      case OpCode_Copyright:
686
36.8k
  return copyright;
687
95.2k
      case OpCode_FullName:
688
95.2k
  return fullName;
689
115k
      case OpCode_FamilyName:
690
115k
  return familyName;
691
99.4k
      case OpCode_Weight:
692
99.4k
  return weight;
693
142
      case OpCode_PostScript:
694
142
  return postscript;
695
594
      case OpCode_FontName:
696
594
  return fontName;
697
152
      case OpCode_BaseFontName:
698
152
  return baseFontName;
699
581k
    }
700
581k
  }
701
702
  unsigned int  values[ValCount];
703
};
704
705
struct cff1_top_dict_val_t : op_str_t
706
{
707
  unsigned int  last_arg_offset;
708
};
709
710
struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t>
711
{
712
  void init ()
713
2.54M
  {
714
2.54M
    top_dict_values_t<cff1_top_dict_val_t>::init ();
715
716
2.54M
    nameSIDs.init ();
717
2.54M
    ros_supplement = 0;
718
2.54M
    cidCount = 8720;
719
2.54M
    EncodingOffset = 0;
720
2.54M
    CharsetOffset = 0;
721
2.54M
    FDSelectOffset = 0;
722
2.54M
    privateDictInfo.init ();
723
2.54M
  }
724
4.72M
  void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); }
725
726
  bool is_CID () const
727
451k
  { return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; }
728
729
  name_dict_values_t  nameSIDs;
730
  unsigned int    ros_supplement_offset;
731
  unsigned int    ros_supplement;
732
  unsigned int    cidCount;
733
734
  unsigned int    EncodingOffset;
735
  unsigned int    CharsetOffset;
736
  unsigned int    FDSelectOffset;
737
  table_info_t    privateDictInfo;
738
};
739
740
struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
741
{
742
  static void process_op (op_code_t op, cff1_top_dict_interp_env_t& env, cff1_top_dict_values_t& dictval)
743
3.78M
  {
744
3.78M
    cff1_top_dict_val_t  val;
745
3.78M
    val.last_arg_offset = (env.last_offset-1) - dictval.opStart;  /* offset to the last argument */
746
747
3.78M
    switch (op) {
748
116k
      case OpCode_version:
749
232k
      case OpCode_Notice:
750
269k
      case OpCode_Copyright:
751
364k
      case OpCode_FullName:
752
365k
      case OpCode_FontName:
753
481k
      case OpCode_FamilyName:
754
581k
      case OpCode_Weight:
755
581k
      case OpCode_PostScript:
756
581k
      case OpCode_BaseFontName:
757
581k
  dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint ();
758
581k
  env.clear_args ();
759
581k
  break;
760
12.3k
      case OpCode_isFixedPitch:
761
21.1k
      case OpCode_ItalicAngle:
762
115k
      case OpCode_UnderlinePosition:
763
119k
      case OpCode_UnderlineThickness:
764
120k
      case OpCode_PaintType:
765
120k
      case OpCode_CharstringType:
766
156k
      case OpCode_UniqueID:
767
156k
      case OpCode_StrokeWidth:
768
157k
      case OpCode_SyntheticBase:
769
177k
      case OpCode_CIDFontVersion:
770
177k
      case OpCode_CIDFontRevision:
771
178k
      case OpCode_CIDFontType:
772
178k
      case OpCode_UIDBase:
773
308k
      case OpCode_FontBBox:
774
321k
      case OpCode_XUID:
775
321k
      case OpCode_BaseFontBlend:
776
321k
  env.clear_args ();
777
321k
  break;
778
779
17.8k
      case OpCode_CIDCount:
780
17.8k
  dictval.cidCount = env.argStack.pop_uint ();
781
17.8k
  env.clear_args ();
782
17.8k
  break;
783
784
20.8k
      case OpCode_ROS:
785
20.8k
  dictval.ros_supplement = env.argStack.pop_uint ();
786
20.8k
  dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint ();
787
20.8k
  dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint ();
788
20.8k
  env.clear_args ();
789
20.8k
  break;
790
791
8.70k
      case OpCode_Encoding:
792
8.70k
  dictval.EncodingOffset = env.argStack.pop_uint ();
793
8.70k
  env.clear_args ();
794
8.70k
  if (unlikely (dictval.EncodingOffset == 0)) return;
795
3.85k
  break;
796
797
130k
      case OpCode_charset:
798
130k
  dictval.CharsetOffset = env.argStack.pop_uint ();
799
130k
  env.clear_args ();
800
130k
  if (unlikely (dictval.CharsetOffset == 0)) return;
801
129k
  break;
802
803
129k
      case OpCode_FDSelect:
804
19.7k
  dictval.FDSelectOffset = env.argStack.pop_uint ();
805
19.7k
  env.clear_args ();
806
19.7k
  break;
807
808
105k
      case OpCode_Private:
809
105k
  dictval.privateDictInfo.offset = env.argStack.pop_uint ();
810
105k
  dictval.privateDictInfo.size = env.argStack.pop_uint ();
811
105k
  env.clear_args ();
812
105k
  break;
813
814
2.58M
      default:
815
2.58M
  env.last_offset = env.str_ref.get_offset ();
816
2.58M
  top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval);
817
  /* Record this operand below if stack is empty, otherwise done */
818
2.58M
  if (!env.argStack.is_empty ()) return;
819
205k
  break;
820
3.78M
    }
821
822
1.40M
    if (unlikely (env.in_error ())) return;
823
824
1.39M
    dictval.add_op (op, env.str_ref, val);
825
1.39M
  }
826
};
827
828
struct cff1_font_dict_values_t : dict_values_t<op_str_t>
829
{
830
  void init ()
831
228k
  {
832
228k
    dict_values_t<op_str_t>::init ();
833
228k
    privateDictInfo.init ();
834
228k
    fontName = CFF_UNDEF_SID;
835
228k
  }
836
0
  void fini () { dict_values_t<op_str_t>::fini (); }
837
838
  table_info_t       privateDictInfo;
839
  unsigned int    fontName;
840
};
841
842
struct cff1_font_dict_opset_t : dict_opset_t
843
{
844
  static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval)
845
395k
  {
846
395k
    switch (op) {
847
70.2k
      case OpCode_FontName:
848
70.2k
  dictval.fontName = env.argStack.pop_uint ();
849
70.2k
  env.clear_args ();
850
70.2k
  break;
851
41
      case OpCode_FontMatrix:
852
74
      case OpCode_PaintType:
853
74
  env.clear_args ();
854
74
  break;
855
70.0k
      case OpCode_Private:
856
70.0k
  dictval.privateDictInfo.offset = env.argStack.pop_uint ();
857
70.0k
  dictval.privateDictInfo.size = env.argStack.pop_uint ();
858
70.0k
  env.clear_args ();
859
70.0k
  break;
860
861
255k
      default:
862
255k
  dict_opset_t::process_op (op, env);
863
255k
  if (!env.argStack.is_empty ()) return;
864
555
  break;
865
395k
    }
866
867
140k
    if (unlikely (env.in_error ())) return;
868
869
140k
    dictval.add_op (op, env.str_ref);
870
140k
  }
871
};
872
873
template <typename VAL>
874
struct cff1_private_dict_values_base_t : dict_values_t<VAL>
875
{
876
  void init ()
877
786k
  {
878
786k
    dict_values_t<VAL>::init ();
879
786k
    subrsOffset = 0;
880
786k
    localSubrs = &Null (CFF1Subrs);
881
786k
  }
882
  void fini () { dict_values_t<VAL>::fini (); }
883
884
  unsigned int      subrsOffset;
885
  const CFF1Subrs    *localSubrs;
886
};
887
888
typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t;
889
typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t;
890
891
struct cff1_private_dict_opset_t : dict_opset_t
892
{
893
  static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval)
894
2.86M
  {
895
2.86M
    num_dict_val_t val;
896
2.86M
    val.init ();
897
898
2.86M
    switch (op) {
899
86.8k
      case OpCode_BlueValues:
900
125k
      case OpCode_OtherBlues:
901
151k
      case OpCode_FamilyBlues:
902
182k
      case OpCode_FamilyOtherBlues:
903
265k
      case OpCode_StemSnapH:
904
347k
      case OpCode_StemSnapV:
905
347k
  env.clear_args ();
906
347k
  break;
907
86.3k
      case OpCode_StdHW:
908
169k
      case OpCode_StdVW:
909
177k
      case OpCode_BlueScale:
910
184k
      case OpCode_BlueShift:
911
192k
      case OpCode_BlueFuzz:
912
192k
      case OpCode_ForceBold:
913
198k
      case OpCode_LanguageGroup:
914
198k
      case OpCode_ExpansionFactor:
915
198k
      case OpCode_initialRandomSeed:
916
297k
      case OpCode_defaultWidthX:
917
347k
      case OpCode_nominalWidthX:
918
347k
  val.single_val = env.argStack.pop_num ();
919
347k
  env.clear_args ();
920
347k
  break;
921
72.6k
      case OpCode_Subrs:
922
72.6k
  dictval.subrsOffset = env.argStack.pop_uint ();
923
72.6k
  env.clear_args ();
924
72.6k
  break;
925
926
2.09M
      default:
927
2.09M
  dict_opset_t::process_op (op, env);
928
2.09M
  if (!env.argStack.is_empty ()) return;
929
4.30k
  break;
930
2.86M
    }
931
932
772k
    if (unlikely (env.in_error ())) return;
933
934
766k
    dictval.add_op (op, env.str_ref, val);
935
766k
  }
936
};
937
938
struct cff1_private_dict_opset_subset : dict_opset_t
939
{
940
  static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval)
941
0
  {
942
0
    switch (op) {
943
0
      case OpCode_BlueValues:
944
0
      case OpCode_OtherBlues:
945
0
      case OpCode_FamilyBlues:
946
0
      case OpCode_FamilyOtherBlues:
947
0
      case OpCode_StemSnapH:
948
0
      case OpCode_StemSnapV:
949
0
      case OpCode_StdHW:
950
0
      case OpCode_StdVW:
951
0
      case OpCode_BlueScale:
952
0
      case OpCode_BlueShift:
953
0
      case OpCode_BlueFuzz:
954
0
      case OpCode_ForceBold:
955
0
      case OpCode_LanguageGroup:
956
0
      case OpCode_ExpansionFactor:
957
0
      case OpCode_initialRandomSeed:
958
0
      case OpCode_defaultWidthX:
959
0
      case OpCode_nominalWidthX:
960
0
  env.clear_args ();
961
0
  break;
962
0
963
0
      case OpCode_Subrs:
964
0
  dictval.subrsOffset = env.argStack.pop_uint ();
965
0
  env.clear_args ();
966
0
  break;
967
0
968
0
      default:
969
0
  dict_opset_t::process_op (op, env);
970
0
  if (!env.argStack.is_empty ()) return;
971
0
  break;
972
0
    }
973
0
974
0
    if (unlikely (env.in_error ())) return;
975
0
976
0
    dictval.add_op (op, env.str_ref);
977
0
  }
978
};
979
980
typedef dict_interpreter_t<cff1_top_dict_opset_t, cff1_top_dict_values_t, cff1_top_dict_interp_env_t> cff1_top_dict_interpreter_t;
981
typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t;
982
983
typedef CFF1Index CFF1NameIndex;
984
typedef CFF1IndexOf<TopDict> CFF1TopDictIndex;
985
986
struct cff1_font_dict_values_mod_t
987
{
988
0
  cff1_font_dict_values_mod_t() { init (); }
989
990
0
  void init () { init ( &Null (cff1_font_dict_values_t), CFF_UNDEF_SID ); }
991
992
  void init (const cff1_font_dict_values_t *base_,
993
       unsigned int fontName_)
994
0
  {
995
0
    base = base_;
996
0
    fontName = fontName_;
997
0
    privateDictInfo.init ();
998
0
  }
999
1000
0
  unsigned get_count () const { return base->get_count (); }
1001
1002
0
  const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; }
1003
1004
  const cff1_font_dict_values_t    *base;
1005
  table_info_t       privateDictInfo;
1006
  unsigned int    fontName;
1007
};
1008
1009
struct CFF1FDArray : FDArray<HBUINT16>
1010
{
1011
  /* FDArray::serialize() requires this partial specialization to compile */
1012
  template <typename ITER, typename OP_SERIALIZER>
1013
  bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr)
1014
  { return FDArray<HBUINT16>::serialize<cff1_font_dict_values_mod_t, cff1_font_dict_values_mod_t> (c, it, opszr); }
1015
};
1016
1017
} /* namespace CFF */
1018
1019
namespace OT {
1020
1021
using namespace CFF;
1022
1023
struct cff1
1024
{
1025
  static constexpr hb_tag_t tableTag = HB_OT_TAG_cff1;
1026
1027
  bool sanitize (hb_sanitize_context_t *c) const
1028
203k
  {
1029
203k
    TRACE_SANITIZE (this);
1030
203k
    return_trace (c->check_struct (this) &&
1031
203k
      likely (version.major == 1));
1032
203k
  }
1033
1034
  template <typename PRIVOPSET, typename PRIVDICTVAL>
1035
  struct accelerator_templ_t
1036
  {
1037
    void init (hb_face_t *face)
1038
2.39M
    {
1039
2.39M
      topDict.init ();
1040
2.39M
      fontDicts.init ();
1041
2.39M
      privateDicts.init ();
1042
1043
2.39M
      this->blob = sc.reference_table<cff1> (face);
1044
1045
      /* setup for run-time santization */
1046
2.39M
      sc.init (this->blob);
1047
2.39M
      sc.start_processing ();
1048
1049
2.39M
      const OT::cff1 *cff = this->blob->template as<OT::cff1> ();
1050
1051
2.39M
      if (cff == &Null (OT::cff1))
1052
2.24M
      { fini (); return; }
1053
1054
155k
      nameIndex = &cff->nameIndex (cff);
1055
155k
      if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc))
1056
5.80k
      { fini (); return; }
1057
1058
149k
      topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ());
1059
149k
      if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0))
1060
3.87k
      { fini (); return; }
1061
1062
145k
      { /* parse top dict */
1063
145k
  const hb_ubytes_t topDictStr = (*topDictIndex)[0];
1064
145k
  if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
1065
145k
  cff1_top_dict_interp_env_t env (topDictStr);
1066
145k
  cff1_top_dict_interpreter_t top_interp (env);
1067
145k
  if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
1068
145k
      }
1069
1070
130k
      if (is_predef_charset ())
1071
6.12k
  charset = &Null (Charset);
1072
124k
      else
1073
124k
      {
1074
124k
  charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
1075
124k
  if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; }
1076
124k
      }
1077
1078
97.5k
      fdCount = 1;
1079
97.5k
      if (is_CID ())
1080
15.2k
      {
1081
15.2k
  fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset);
1082
15.2k
  fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
1083
15.2k
  if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) ||
1084
15.2k
      (fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
1085
5.89k
  { fini (); return; }
1086
1087
9.33k
  fdCount = fdArray->count;
1088
9.33k
      }
1089
82.2k
      else
1090
82.2k
      {
1091
82.2k
  fdArray = &Null (CFF1FDArray);
1092
82.2k
  fdSelect = &Null (CFF1FDSelect);
1093
82.2k
      }
1094
1095
91.6k
      encoding = &Null (Encoding);
1096
91.6k
      if (is_CID ())
1097
9.33k
      {
1098
9.33k
  if (unlikely (charset == &Null (Charset))) { fini (); return; }
1099
9.33k
      }
1100
82.2k
      else
1101
82.2k
      {
1102
82.2k
  if (!is_predef_encoding ())
1103
2.07k
  {
1104
2.07k
    encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
1105
2.07k
    if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; }
1106
2.07k
  }
1107
82.2k
      }
1108
1109
90.8k
      stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ());
1110
90.8k
      if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc))
1111
2.69k
      { fini (); return; }
1112
1113
88.1k
      globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ());
1114
88.1k
      if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc))
1115
5.91k
      { fini (); return; }
1116
1117
82.2k
      charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);
1118
1119
82.2k
      if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
1120
3.45k
      { fini (); return; }
1121
1122
78.8k
      num_glyphs = charStrings->count;
1123
78.8k
      if (num_glyphs != sc.get_num_glyphs ())
1124
861
      { fini (); return; }
1125
1126
77.9k
      if (unlikely (!privateDicts.resize (fdCount)))
1127
81
      { fini (); return; }
1128
498k
      for (unsigned int i = 0; i < fdCount; i++)
1129
420k
  privateDicts[i].init ();
1130
1131
      // parse CID font dicts and gather private dicts
1132
77.8k
      if (is_CID ())
1133
8.22k
      {
1134
120k
  for (unsigned int i = 0; i < fdCount; i++)
1135
114k
  {
1136
114k
    hb_ubytes_t fontDictStr = (*fdArray)[i];
1137
114k
    if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
1138
114k
    cff1_font_dict_values_t *font;
1139
114k
    cff1_top_dict_interp_env_t env (fontDictStr);
1140
114k
    cff1_font_dict_interpreter_t font_interp (env);
1141
114k
    font = fontDicts.push ();
1142
114k
    if (unlikely (fontDicts.in_error ())) { fini (); return; }
1143
1144
114k
    font->init ();
1145
114k
    if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
1146
113k
    PRIVDICTVAL *priv = &privateDicts[i];
1147
113k
    const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
1148
113k
    if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
1149
113k
    num_interp_env_t env2 (privDictStr);
1150
113k
    dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2);
1151
113k
    priv->init ();
1152
113k
    if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
1153
1154
112k
    priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
1155
112k
    if (priv->localSubrs != &Null (CFF1Subrs) &&
1156
112k
        unlikely (!priv->localSubrs->sanitize (&sc)))
1157
216
    { fini (); return; }
1158
112k
  }
1159
8.22k
      }
1160
69.6k
      else  /* non-CID */
1161
69.6k
      {
1162
69.6k
  cff1_top_dict_values_t *font = &topDict;
1163
69.6k
  PRIVDICTVAL *priv = &privateDicts[0];
1164
1165
69.6k
  const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
1166
69.6k
  if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
1167
69.5k
  num_interp_env_t env (privDictStr);
1168
69.5k
  dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env);
1169
69.5k
  priv->init ();
1170
69.5k
  if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
1171
1172
64.4k
  priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
1173
64.4k
  if (priv->localSubrs != &Null (CFF1Subrs) &&
1174
64.4k
      unlikely (!priv->localSubrs->sanitize (&sc)))
1175
3.01k
  { fini (); return; }
1176
64.4k
      }
1177
77.8k
    }
1178
1179
    void fini ()
1180
4.72M
    {
1181
4.72M
      sc.end_processing ();
1182
4.72M
      topDict.fini ();
1183
4.72M
      fontDicts.fini ();
1184
4.72M
      privateDicts.fini ();
1185
4.72M
      hb_blob_destroy (blob);
1186
4.72M
      blob = nullptr;
1187
4.72M
    }
1188
1189
10.9M
    bool is_valid () const { return blob; }
1190
451k
    bool   is_CID () const { return topDict.is_CID (); }
1191
1192
130k
    bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
1193
1194
    unsigned int std_code_to_glyph (hb_codepoint_t code) const
1195
16.4k
    {
1196
16.4k
      hb_codepoint_t sid = lookup_standard_encoding_for_sid (code);
1197
16.4k
      if (unlikely (sid == CFF_UNDEF_SID))
1198
2.70k
  return 0;
1199
1200
13.7k
      if (charset != &Null (Charset))
1201
10.4k
  return charset->get_glyph (sid, num_glyphs);
1202
3.27k
      else if ((topDict.CharsetOffset == ISOAdobeCharset)
1203
3.27k
        && (code <= 228 /*zcaron*/)) return sid;
1204
74
      return 0;
1205
13.7k
    }
1206
1207
82.2k
    bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
1208
1209
    hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const
1210
    {
1211
      if (encoding != &Null (Encoding))
1212
  return encoding->get_code (glyph);
1213
      else
1214
      {
1215
  hb_codepoint_t sid = glyph_to_sid (glyph);
1216
  if (sid == 0) return 0;
1217
  hb_codepoint_t code = 0;
1218
  switch (topDict.EncodingOffset)
1219
  {
1220
  case StandardEncoding:
1221
    code = lookup_standard_encoding_for_code (sid);
1222
    break;
1223
  case ExpertEncoding:
1224
    code = lookup_expert_encoding_for_code (sid);
1225
    break;
1226
  default:
1227
    break;
1228
  }
1229
  return code;
1230
      }
1231
    }
1232
1233
    hb_map_t *create_glyph_to_sid_map () const
1234
    {
1235
      if (charset != &Null (Charset))
1236
      {
1237
  hb_map_t *mapping = hb_map_create ();
1238
  mapping->set (0, 0);
1239
  charset->collect_glyph_to_sid_map (mapping, num_glyphs);
1240
  return mapping;
1241
      }
1242
      else
1243
  return nullptr;
1244
    }
1245
1246
    hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
1247
11.8M
    {
1248
11.8M
      if (charset != &Null (Charset))
1249
11.6M
  return charset->get_sid (glyph, num_glyphs);
1250
181k
      else
1251
181k
      {
1252
181k
  hb_codepoint_t sid = 0;
1253
181k
  switch (topDict.CharsetOffset)
1254
181k
  {
1255
164k
    case ISOAdobeCharset:
1256
164k
      if (glyph <= 228 /*zcaron*/) sid = glyph;
1257
164k
      break;
1258
3.24k
    case ExpertCharset:
1259
3.24k
      sid = lookup_expert_charset_for_sid (glyph);
1260
3.24k
      break;
1261
13.4k
    case ExpertSubsetCharset:
1262
13.4k
        sid = lookup_expert_subset_charset_for_sid (glyph);
1263
13.4k
      break;
1264
0
    default:
1265
0
      break;
1266
181k
  }
1267
181k
  return sid;
1268
181k
      }
1269
11.8M
    }
1270
1271
    hb_codepoint_t sid_to_glyph (hb_codepoint_t sid) const
1272
2.00k
    {
1273
2.00k
      if (charset != &Null (Charset))
1274
1.87k
  return charset->get_glyph (sid, num_glyphs);
1275
128
      else
1276
128
      {
1277
128
  hb_codepoint_t glyph = 0;
1278
128
  switch (topDict.CharsetOffset)
1279
128
  {
1280
114
    case ISOAdobeCharset:
1281
114
      if (sid <= 228 /*zcaron*/) glyph = sid;
1282
114
      break;
1283
2
    case ExpertCharset:
1284
2
      glyph = lookup_expert_charset_for_glyph (sid);
1285
2
      break;
1286
12
    case ExpertSubsetCharset:
1287
12
      glyph = lookup_expert_subset_charset_for_glyph (sid);
1288
12
      break;
1289
0
    default:
1290
0
      break;
1291
128
  }
1292
128
  return glyph;
1293
128
      }
1294
2.00k
    }
1295
1296
    protected:
1297
    hb_sanitize_context_t   sc;
1298
1299
    public:
1300
    hb_blob_t               *blob = nullptr;
1301
    const Encoding      *encoding = nullptr;
1302
    const Charset     *charset = nullptr;
1303
    const CFF1NameIndex     *nameIndex = nullptr;
1304
    const CFF1TopDictIndex  *topDictIndex = nullptr;
1305
    const CFF1StringIndex   *stringIndex = nullptr;
1306
    const CFF1Subrs     *globalSubrs = nullptr;
1307
    const CFF1CharStrings   *charStrings = nullptr;
1308
    const CFF1FDArray       *fdArray = nullptr;
1309
    const CFF1FDSelect      *fdSelect = nullptr;
1310
    unsigned int       fdCount = 0;
1311
1312
    cff1_top_dict_values_t   topDict;
1313
    hb_vector_t<cff1_font_dict_values_t>
1314
           fontDicts;
1315
    hb_vector_t<PRIVDICTVAL> privateDicts;
1316
1317
    unsigned int       num_glyphs = 0;
1318
  };
1319
1320
  struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
1321
  {
1322
    accelerator_t (hb_face_t *face)
1323
2.39M
    {
1324
2.39M
      SUPER::init (face);
1325
1326
2.39M
      glyph_names.set_relaxed (nullptr);
1327
1328
2.39M
      if (!is_valid ()) return;
1329
67.6k
      if (is_CID ()) return;
1330
1331
67.6k
    }
1332
    ~accelerator_t ()
1333
2.39M
    {
1334
2.39M
      hb_sorted_vector_t<gname_t> *names = glyph_names.get_relaxed ();
1335
2.39M
      if (names)
1336
46.6k
      {
1337
46.6k
  names->fini ();
1338
46.6k
  hb_free (names);
1339
46.6k
      }
1340
1341
2.39M
      SUPER::fini ();
1342
2.39M
    }
1343
1344
    bool get_glyph_name (hb_codepoint_t glyph,
1345
       char *buf, unsigned int buf_len) const
1346
2.43M
    {
1347
2.43M
      if (unlikely (glyph >= num_glyphs)) return false;
1348
54.8k
      if (unlikely (!is_valid ())) return false;
1349
48.8k
      if (is_CID()) return false;
1350
47.1k
      if (unlikely (!buf_len)) return true;
1351
47.1k
      hb_codepoint_t sid = glyph_to_sid (glyph);
1352
47.1k
      const char *str;
1353
47.1k
      size_t str_len;
1354
47.1k
      if (sid < cff1_std_strings_length)
1355
38.4k
      {
1356
38.4k
  hb_bytes_t byte_str = cff1_std_strings (sid);
1357
38.4k
  str = byte_str.arrayZ;
1358
38.4k
  str_len = byte_str.length;
1359
38.4k
      }
1360
8.69k
      else
1361
8.69k
      {
1362
8.69k
  hb_ubytes_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length];
1363
8.69k
  str = (const char *)ubyte_str.arrayZ;
1364
8.69k
  str_len = ubyte_str.length;
1365
8.69k
      }
1366
47.1k
      if (!str_len) return false;
1367
46.3k
      unsigned int len = hb_min (buf_len - 1, str_len);
1368
46.3k
      strncpy (buf, (const char*)str, len);
1369
46.3k
      buf[len] = '\0';
1370
46.3k
      return true;
1371
47.1k
    }
1372
1373
    bool get_glyph_from_name (const char *name, int len,
1374
            hb_codepoint_t *glyph) const
1375
2.44M
    {
1376
2.44M
      if (unlikely (!is_valid ())) return false;
1377
67.6k
      if (is_CID()) return false;
1378
61.4k
      if (len < 0) len = strlen (name);
1379
61.4k
      if (unlikely (!len)) return false;
1380
1381
46.6k
    retry:
1382
46.6k
      hb_sorted_vector_t<gname_t> *names = glyph_names.get_acquire ();
1383
46.6k
      if (unlikely (!names))
1384
46.6k
      {
1385
46.6k
  names = (hb_sorted_vector_t<gname_t> *) hb_calloc (sizeof (hb_sorted_vector_t<gname_t>), 1);
1386
46.6k
  if (likely (names))
1387
46.6k
  {
1388
46.6k
    names->init ();
1389
    /* TODO */
1390
1391
    /* fill glyph names */
1392
11.8M
    for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
1393
11.8M
    {
1394
11.8M
      hb_codepoint_t  sid = glyph_to_sid (gid);
1395
11.8M
      gname_t gname;
1396
11.8M
      gname.sid = sid;
1397
11.8M
      if (sid < cff1_std_strings_length)
1398
3.02M
        gname.name = cff1_std_strings (sid);
1399
8.80M
      else
1400
8.80M
      {
1401
8.80M
        hb_ubytes_t ustr = (*stringIndex)[sid - cff1_std_strings_length];
1402
8.80M
        gname.name = hb_bytes_t ((const char*) ustr.arrayZ, ustr.length);
1403
8.80M
      }
1404
11.8M
      if (unlikely (!gname.name.arrayZ))
1405
2.80M
        gname.name = hb_bytes_t ("", 0); /* To avoid nullptr. */
1406
11.8M
      names->push (gname);
1407
11.8M
    }
1408
46.6k
    names->qsort ();
1409
46.6k
  }
1410
46.6k
  if (unlikely (!glyph_names.cmpexch (nullptr, names)))
1411
0
  {
1412
0
    if (names)
1413
0
    {
1414
0
      names->fini ();
1415
0
      hb_free (names);
1416
0
    }
1417
0
    goto retry;
1418
0
  }
1419
46.6k
      }
1420
1421
46.6k
      gname_t key = { hb_bytes_t (name, len), 0 };
1422
46.6k
      const gname_t *gname = names ? names->bsearch (key) : nullptr;
1423
46.6k
      if (!gname) return false;
1424
2.00k
      hb_codepoint_t gid = sid_to_glyph (gname->sid);
1425
2.00k
      if (!gid && gname->sid) return false;
1426
2.00k
      *glyph = gid;
1427
2.00k
      return true;
1428
2.00k
    }
1429
1430
    HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
1431
    HB_INTERNAL bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const;
1432
    HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
1433
    HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
1434
1435
    private:
1436
    struct gname_t
1437
    {
1438
      hb_bytes_t  name;
1439
      uint16_t    sid;
1440
1441
      static int cmp (const void *a_, const void *b_)
1442
84.3M
      {
1443
84.3M
  const gname_t *a = (const gname_t *)a_;
1444
84.3M
  const gname_t *b = (const gname_t *)b_;
1445
84.3M
  unsigned minlen = hb_min (a->name.length, b->name.length);
1446
84.3M
  int ret = strncmp (a->name.arrayZ, b->name.arrayZ, minlen);
1447
84.3M
  if (ret) return ret;
1448
10.7M
  return a->name.length - b->name.length;
1449
84.3M
      }
1450
1451
224k
      int cmp (const gname_t &a) const { return cmp (&a, this); }
1452
    };
1453
1454
    mutable hb_atomic_ptr_t<hb_sorted_vector_t<gname_t>> glyph_names;
1455
1456
    typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
1457
  };
1458
1459
  struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> {};
1460
1461
0
  bool subset (hb_subset_context_t *c) const { return hb_subset_cff1 (c); }
1462
1463
  protected:
1464
  HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
1465
  HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
1466
  HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph);
1467
  HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph);
1468
  HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_glyph (hb_codepoint_t sid);
1469
  HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid);
1470
  HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code);
1471
1472
  public:
1473
  FixedVersion<HBUINT8> version;    /* Version of CFF table. set to 0x0100u */
1474
  NNOffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
1475
  HBUINT8        offSize;   /* offset size (unused?) */
1476
1477
  public:
1478
  DEFINE_SIZE_STATIC (4);
1479
};
1480
1481
struct cff1_accelerator_t : cff1::accelerator_t {
1482
2.39M
  cff1_accelerator_t (hb_face_t *face) : cff1::accelerator_t (face) {}
1483
};
1484
1485
} /* namespace OT */
1486
1487
#endif /* HB_OT_CFF1_TABLE_HH */