Coverage Report

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