Coverage Report

Created: 2025-07-07 10:01

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