Coverage Report

Created: 2026-08-31 07:00

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