Coverage Report

Created: 2026-10-30 06:49

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