Coverage Report

Created: 2026-09-28 10:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/workdir/UnpackedTarball/harfbuzz/src/hb-ot-cff2-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_CFF2_TABLE_HH
28
#define HB_OT_CFF2_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
namespace CFF {
36
37
/*
38
 * CFF2 -- Compact Font Format (CFF) Version 2
39
 * https://docs.microsoft.com/en-us/typography/opentype/spec/cff2
40
 */
41
#define HB_OT_TAG_CFF2 HB_TAG('C','F','F','2')
42
43
typedef CFF2Index         CFF2CharStrings;
44
typedef Subrs<HBUINT32>   CFF2Subrs;
45
46
typedef FDSelect3_4<HBUINT32, HBUINT16> FDSelect4;
47
typedef FDSelect3_4_Range<HBUINT32, HBUINT16> FDSelect4_Range;
48
49
struct CFF2FDSelect
50
{
51
  bool serialize (hb_serialize_context_t *c, const CFF2FDSelect &src, unsigned int num_glyphs)
52
0
  {
53
0
    TRACE_SERIALIZE (this);
54
0
    unsigned int size = src.get_size (num_glyphs);
55
0
    CFF2FDSelect *dest = c->allocate_size<CFF2FDSelect> (size);
56
0
    if (unlikely (!dest)) return_trace (false);
57
0
    hb_memcpy (dest, &src, size);
58
0
    return_trace (true);
59
0
  }
60
61
  size_t get_size (unsigned int num_glyphs) const
62
0
  {
63
0
    switch (format)
64
0
    {
65
0
    case 0: hb_barrier (); return format.static_size + u.format0.get_size (num_glyphs);
66
0
    case 3: hb_barrier (); return format.static_size + u.format3.get_size ();
67
0
    case 4: hb_barrier (); return format.static_size + u.format4.get_size ();
68
0
    default:return 0;
69
0
    }
70
0
  }
71
72
  hb_codepoint_t get_fd (hb_codepoint_t glyph) const
73
0
  {
74
0
    if (this == &Null (CFF2FDSelect))
75
0
      return 0;
76
77
0
    switch (format)
78
0
    {
79
0
    case 0: hb_barrier (); return u.format0.get_fd (glyph);
80
0
    case 3: hb_barrier (); return u.format3.get_fd (glyph);
81
0
    case 4: hb_barrier (); return u.format4.get_fd (glyph);
82
0
    default:return 0;
83
0
    }
84
0
  }
85
86
  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
87
0
  {
88
0
    TRACE_SANITIZE (this);
89
0
    if (unlikely (!c->check_struct (this)))
90
0
      return_trace (false);
91
0
    hb_barrier ();
92
93
0
    switch (format)
94
0
    {
95
0
    case 0: hb_barrier (); return_trace (u.format0.sanitize (c, fdcount));
96
0
    case 3: hb_barrier (); return_trace (u.format3.sanitize (c, fdcount));
97
0
    case 4: hb_barrier (); return_trace (u.format4.sanitize (c, fdcount));
98
0
    default:return_trace (false);
99
0
    }
100
0
  }
101
102
  HBUINT8 format;
103
  union {
104
  FDSelect0 format0;
105
  FDSelect3 format3;
106
  FDSelect4 format4;
107
  } u;
108
  public:
109
  DEFINE_SIZE_MIN (2);
110
};
111
112
struct CFF2ItemVariationStore
113
{
114
  bool sanitize (hb_sanitize_context_t *c) const
115
0
  {
116
0
    TRACE_SANITIZE (this);
117
0
    return_trace (c->check_struct (this) &&
118
0
      hb_barrier () &&
119
0
      c->check_range (&varStore, size) &&
120
0
      varStore.sanitize (c));
121
0
  }
122
123
  bool serialize (hb_serialize_context_t *c, const CFF2ItemVariationStore *varStore)
124
0
  {
125
0
    TRACE_SERIALIZE (this);
126
0
    unsigned int size_ = varStore->get_size ();
127
0
    CFF2ItemVariationStore *dest = c->allocate_size<CFF2ItemVariationStore> (size_);
128
0
    if (unlikely (!dest)) return_trace (false);
129
0
    hb_memcpy (dest, varStore, size_);
130
0
    return_trace (true);
131
0
  }
132
133
0
  size_t get_size () const { return HBUINT16::static_size + size; }
134
135
  HBUINT16  size;
136
  ItemVariationStore  varStore;
137
138
  DEFINE_SIZE_MIN (2 + ItemVariationStore::min_size);
139
};
140
141
struct cff2_top_dict_values_t : top_dict_values_t<>
142
{
143
  void init ()
144
1
  {
145
1
    top_dict_values_t<>::init ();
146
1
    vstoreOffset = 0;
147
1
    FDSelectOffset = 0;
148
1
  }
149
1
  void fini () { top_dict_values_t<>::fini (); }
150
151
  int  vstoreOffset;
152
  int  FDSelectOffset;
153
};
154
155
struct cff2_top_dict_opset_t : top_dict_opset_t<>
156
{
157
  static void process_op (op_code_t op, num_interp_env_t& env, cff2_top_dict_values_t& dictval)
158
0
  {
159
0
    switch (op) {
160
0
      case OpCode_FontMatrix:
161
0
  {
162
0
    dict_val_t val;
163
0
    val.init ();
164
0
    dictval.add_op (op, env.str_ref);
165
0
    env.clear_args ();
166
0
  }
167
0
  break;
168
169
0
      case OpCode_vstore:
170
0
  dictval.vstoreOffset = env.argStack.pop_int ();
171
0
  env.clear_args ();
172
0
  break;
173
0
      case OpCode_FDSelect:
174
0
  dictval.FDSelectOffset = env.argStack.pop_int ();
175
0
  env.clear_args ();
176
0
  break;
177
178
0
      default:
179
0
  SUPER::process_op (op, env, dictval);
180
  /* Record this operand below if stack is empty, otherwise done */
181
0
  if (!env.argStack.is_empty ()) return;
182
0
    }
183
184
0
    if (unlikely (env.in_error ())) return;
185
186
0
    dictval.add_op (op, env.str_ref);
187
0
  }
188
189
  typedef top_dict_opset_t<> SUPER;
190
};
191
192
struct cff2_font_dict_values_t : dict_values_t<op_str_t>
193
{
194
  void init ()
195
0
  {
196
0
    dict_values_t<op_str_t>::init ();
197
0
    privateDictInfo.init ();
198
0
  }
199
0
  void fini () { dict_values_t<op_str_t>::fini (); }
200
201
  table_info_t    privateDictInfo;
202
};
203
204
struct cff2_font_dict_opset_t : dict_opset_t
205
{
206
  static void process_op (op_code_t op, num_interp_env_t& env, cff2_font_dict_values_t& dictval)
207
0
  {
208
0
    switch (op) {
209
0
      case OpCode_Private:
210
0
  dictval.privateDictInfo.offset = env.argStack.pop_uint ();
211
0
  dictval.privateDictInfo.size = env.argStack.pop_uint ();
212
0
  env.clear_args ();
213
0
  break;
214
215
0
      default:
216
0
  SUPER::process_op (op, env);
217
0
  if (!env.argStack.is_empty ())
218
0
    return;
219
0
    }
220
221
0
    if (unlikely (env.in_error ())) return;
222
223
0
    dictval.add_op (op, env.str_ref);
224
0
  }
225
226
  private:
227
  typedef dict_opset_t SUPER;
228
};
229
230
template <typename VAL>
231
struct cff2_private_dict_values_base_t : dict_values_t<VAL>
232
{
233
  void init ()
234
0
  {
235
0
    dict_values_t<VAL>::init ();
236
0
    subrsOffset = 0;
237
0
    localSubrs = &Null (CFF2Subrs);
238
0
    ivs = 0;
239
0
  }
Unexecuted instantiation: CFF::cff2_private_dict_values_base_t<CFF::dict_val_t>::init()
Unexecuted instantiation: CFF::cff2_private_dict_values_base_t<CFF::op_str_t>::init()
240
  void fini () { dict_values_t<VAL>::fini (); }
241
242
  int                subrsOffset;
243
  const CFF2Subrs   *localSubrs;
244
  unsigned int      ivs;
245
};
246
247
typedef cff2_private_dict_values_base_t<op_str_t> cff2_private_dict_values_subset_t;
248
typedef cff2_private_dict_values_base_t<num_dict_val_t> cff2_private_dict_values_t;
249
250
struct cff2_priv_dict_interp_env_t : num_interp_env_t
251
{
252
  cff2_priv_dict_interp_env_t (const hb_ubytes_t &str) :
253
0
    num_interp_env_t (str) {}
254
255
  void process_vsindex ()
256
0
  {
257
0
    if (likely (!seen_vsindex))
258
0
    {
259
0
      set_ivs (argStack.pop_uint ());
260
0
    }
261
0
    seen_vsindex = true;
262
0
  }
263
264
0
  unsigned int get_ivs () const { return ivs; }
265
0
  void   set_ivs (unsigned int ivs_) { ivs = ivs_; }
266
267
  protected:
268
  unsigned int  ivs = 0;
269
  bool    seen_vsindex = false;
270
};
271
272
struct cff2_private_dict_opset_t : dict_opset_t
273
{
274
  static void process_op (op_code_t op, cff2_priv_dict_interp_env_t& env, cff2_private_dict_values_t& dictval)
275
0
  {
276
0
    num_dict_val_t val;
277
0
    val.init ();
278
279
0
    switch (op) {
280
0
      case OpCode_StdHW:
281
0
      case OpCode_StdVW:
282
0
      case OpCode_BlueScale:
283
0
      case OpCode_BlueShift:
284
0
      case OpCode_BlueFuzz:
285
0
      case OpCode_ExpansionFactor:
286
0
      case OpCode_LanguageGroup:
287
0
      case OpCode_BlueValues:
288
0
      case OpCode_OtherBlues:
289
0
      case OpCode_FamilyBlues:
290
0
      case OpCode_FamilyOtherBlues:
291
0
      case OpCode_StemSnapH:
292
0
      case OpCode_StemSnapV:
293
0
  env.clear_args ();
294
0
  break;
295
0
      case OpCode_Subrs:
296
0
  dictval.subrsOffset = env.argStack.pop_int ();
297
0
  env.clear_args ();
298
0
  break;
299
0
      case OpCode_vsindexdict:
300
0
  env.process_vsindex ();
301
0
  dictval.ivs = env.get_ivs ();
302
0
  env.clear_args ();
303
0
  break;
304
0
      case OpCode_blenddict:
305
0
  break;
306
307
0
      default:
308
0
  dict_opset_t::process_op (op, env);
309
0
  if (!env.argStack.is_empty ()) return;
310
0
  break;
311
0
    }
312
313
0
    if (unlikely (env.in_error ())) return;
314
315
0
    dictval.add_op (op, env.str_ref, val);
316
0
  }
317
};
318
319
struct cff2_private_dict_opset_subset_t : dict_opset_t
320
{
321
  static void process_op (op_code_t op, cff2_priv_dict_interp_env_t& env, cff2_private_dict_values_subset_t& dictval)
322
0
  {
323
0
    switch (op) {
324
0
      case OpCode_BlueValues:
325
0
      case OpCode_OtherBlues:
326
0
      case OpCode_FamilyBlues:
327
0
      case OpCode_FamilyOtherBlues:
328
0
      case OpCode_StdHW:
329
0
      case OpCode_StdVW:
330
0
      case OpCode_BlueScale:
331
0
      case OpCode_BlueShift:
332
0
      case OpCode_BlueFuzz:
333
0
      case OpCode_StemSnapH:
334
0
      case OpCode_StemSnapV:
335
0
      case OpCode_LanguageGroup:
336
0
      case OpCode_ExpansionFactor:
337
0
  env.clear_args ();
338
0
  break;
339
340
0
      case OpCode_blenddict:
341
0
  env.clear_args ();
342
0
  return;
343
344
0
      case OpCode_Subrs:
345
0
  dictval.subrsOffset = env.argStack.pop_int ();
346
0
  env.clear_args ();
347
0
  break;
348
349
0
      case OpCode_vsindexdict:
350
0
  env.process_vsindex ();
351
0
  dictval.ivs = env.get_ivs ();
352
0
  env.clear_args ();
353
0
  break;
354
355
0
      default:
356
0
  SUPER::process_op (op, env);
357
0
  if (!env.argStack.is_empty ()) return;
358
0
  break;
359
0
    }
360
361
0
    if (unlikely (env.in_error ())) return;
362
363
0
    dictval.add_op (op, env.str_ref);
364
0
  }
365
366
  private:
367
  typedef dict_opset_t SUPER;
368
};
369
370
typedef dict_interpreter_t<cff2_top_dict_opset_t, cff2_top_dict_values_t> cff2_top_dict_interpreter_t;
371
typedef dict_interpreter_t<cff2_font_dict_opset_t, cff2_font_dict_values_t> cff2_font_dict_interpreter_t;
372
373
struct CFF2FDArray : FDArray<HBUINT32>
374
{
375
  /* FDArray::serialize does not compile without this partial specialization */
376
  template <typename ITER, typename OP_SERIALIZER>
377
  bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr)
378
0
  { return FDArray<HBUINT32>::serialize<cff2_font_dict_values_t, table_info_t> (c, it, opszr); }
379
};
380
381
} /* namespace CFF */
382
383
namespace OT {
384
385
using namespace CFF;
386
387
struct cff2
388
{
389
  static constexpr hb_tag_t tableTag = HB_OT_TAG_CFF2;
390
391
  bool sanitize (hb_sanitize_context_t *c) const
392
0
  {
393
0
    TRACE_SANITIZE (this);
394
0
    return_trace (c->check_struct (this) &&
395
0
      hb_barrier () &&
396
0
      likely (version.major == 2));
397
0
  }
398
399
  template <typename PRIVOPSET, typename PRIVDICTVAL>
400
  struct accelerator_templ_t
401
  {
402
    static constexpr hb_tag_t tableTag = cff2::tableTag;
403
404
    accelerator_templ_t (hb_face_t *face)
405
1
    {
406
1
      if (!face) return;
407
408
1
      topDict.init ();
409
1
      fontDicts.init ();
410
1
      privateDicts.init ();
411
412
1
      this->blob = sc.reference_table<cff2> (face);
413
414
      /* setup for run-time sanitization */
415
1
      sc.init (this->blob);
416
1
      sc.start_processing ();
417
418
1
      const OT::cff2 *cff2 = this->blob->template as<OT::cff2> ();
419
420
1
      if (cff2 == &Null (OT::cff2))
421
1
        goto fail;
422
423
0
      { /* parse top dict */
424
0
  hb_ubytes_t topDictStr = (cff2 + cff2->topDict).as_ubytes (cff2->topDictSize);
425
0
  if (unlikely (!topDictStr.sanitize (&sc))) goto fail;
426
0
  hb_barrier ();
427
0
  num_interp_env_t env (topDictStr);
428
0
  cff2_top_dict_interpreter_t top_interp (env);
429
0
  topDict.init ();
430
0
  if (unlikely (!top_interp.interpret (topDict))) goto fail;
431
0
      }
432
433
0
      globalSubrs = &StructAtOffsetOrNull<CFF2Subrs> (cff2, cff2->topDict + cff2->topDictSize, sc);
434
0
      varStore = &StructAtOffsetOrNull<CFF2ItemVariationStore> (cff2, topDict.vstoreOffset, sc);
435
0
      charStrings = &StructAtOffsetOrNull<CFF2CharStrings> (cff2, topDict.charStringsOffset, sc);
436
0
      fdArray = &StructAtOffsetOrNull<CFF2FDArray> (cff2, topDict.FDArrayOffset, sc);
437
0
      fdSelect = &StructAtOffsetOrNull<CFF2FDSelect> (cff2, topDict.FDSelectOffset, sc, fdArray->count);
438
439
0
      if (charStrings == &Null (CFF2CharStrings) ||
440
0
    globalSubrs == &Null (CFF2Subrs) ||
441
0
    fdArray == &Null (CFF2FDArray))
442
0
        goto fail;
443
444
0
      num_glyphs = charStrings->count;
445
0
      if (num_glyphs != sc.get_num_glyphs ())
446
0
        goto fail;
447
448
0
      fdCount = fdArray->count;
449
0
      if (!privateDicts.resize (fdCount))
450
0
        goto fail;
451
452
      /* parse font dicts and gather private dicts */
453
0
      for (unsigned int i = 0; i < fdCount; i++)
454
0
      {
455
0
  const hb_ubytes_t fontDictStr = (*fdArray)[i];
456
0
  if (unlikely (!fontDictStr.sanitize (&sc))) goto fail;
457
0
  hb_barrier ();
458
0
  cff2_font_dict_values_t  *font;
459
0
  num_interp_env_t env (fontDictStr);
460
0
  cff2_font_dict_interpreter_t font_interp (env);
461
0
  font = fontDicts.push ();
462
0
  if (unlikely (font == &Crap (cff2_font_dict_values_t))) goto fail;
463
0
  font->init ();
464
0
  if (unlikely (!font_interp.interpret (*font))) goto fail;
465
466
0
  const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
467
0
  if (unlikely (font->privateDictInfo.size &&
468
0
          privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
469
0
  cff2_priv_dict_interp_env_t env2 (privDictStr);
470
0
  dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t> priv_interp (env2);
471
0
  privateDicts[i].init ();
472
0
  if (unlikely (!priv_interp.interpret (privateDicts[i]))) goto fail;
473
474
0
  privateDicts[i].localSubrs = &StructAtOffsetOrNull<CFF2Subrs> (&privDictStr[0], privateDicts[i].subrsOffset, sc);
475
0
      }
476
477
0
      return;
478
479
1
      fail:
480
1
        _fini ();
481
1
    }
OT::cff2::accelerator_templ_t<CFF::cff2_private_dict_opset_t, CFF::cff2_private_dict_values_base_t<CFF::dict_val_t> >::accelerator_templ_t(hb_face_t*)
Line
Count
Source
405
1
    {
406
1
      if (!face) return;
407
408
1
      topDict.init ();
409
1
      fontDicts.init ();
410
1
      privateDicts.init ();
411
412
1
      this->blob = sc.reference_table<cff2> (face);
413
414
      /* setup for run-time sanitization */
415
1
      sc.init (this->blob);
416
1
      sc.start_processing ();
417
418
1
      const OT::cff2 *cff2 = this->blob->template as<OT::cff2> ();
419
420
1
      if (cff2 == &Null (OT::cff2))
421
1
        goto fail;
422
423
0
      { /* parse top dict */
424
0
  hb_ubytes_t topDictStr = (cff2 + cff2->topDict).as_ubytes (cff2->topDictSize);
425
0
  if (unlikely (!topDictStr.sanitize (&sc))) goto fail;
426
0
  hb_barrier ();
427
0
  num_interp_env_t env (topDictStr);
428
0
  cff2_top_dict_interpreter_t top_interp (env);
429
0
  topDict.init ();
430
0
  if (unlikely (!top_interp.interpret (topDict))) goto fail;
431
0
      }
432
433
0
      globalSubrs = &StructAtOffsetOrNull<CFF2Subrs> (cff2, cff2->topDict + cff2->topDictSize, sc);
434
0
      varStore = &StructAtOffsetOrNull<CFF2ItemVariationStore> (cff2, topDict.vstoreOffset, sc);
435
0
      charStrings = &StructAtOffsetOrNull<CFF2CharStrings> (cff2, topDict.charStringsOffset, sc);
436
0
      fdArray = &StructAtOffsetOrNull<CFF2FDArray> (cff2, topDict.FDArrayOffset, sc);
437
0
      fdSelect = &StructAtOffsetOrNull<CFF2FDSelect> (cff2, topDict.FDSelectOffset, sc, fdArray->count);
438
439
0
      if (charStrings == &Null (CFF2CharStrings) ||
440
0
    globalSubrs == &Null (CFF2Subrs) ||
441
0
    fdArray == &Null (CFF2FDArray))
442
0
        goto fail;
443
444
0
      num_glyphs = charStrings->count;
445
0
      if (num_glyphs != sc.get_num_glyphs ())
446
0
        goto fail;
447
448
0
      fdCount = fdArray->count;
449
0
      if (!privateDicts.resize (fdCount))
450
0
        goto fail;
451
452
      /* parse font dicts and gather private dicts */
453
0
      for (unsigned int i = 0; i < fdCount; i++)
454
0
      {
455
0
  const hb_ubytes_t fontDictStr = (*fdArray)[i];
456
0
  if (unlikely (!fontDictStr.sanitize (&sc))) goto fail;
457
0
  hb_barrier ();
458
0
  cff2_font_dict_values_t  *font;
459
0
  num_interp_env_t env (fontDictStr);
460
0
  cff2_font_dict_interpreter_t font_interp (env);
461
0
  font = fontDicts.push ();
462
0
  if (unlikely (font == &Crap (cff2_font_dict_values_t))) goto fail;
463
0
  font->init ();
464
0
  if (unlikely (!font_interp.interpret (*font))) goto fail;
465
466
0
  const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset, sc, font->privateDictInfo.size).as_ubytes (font->privateDictInfo.size);
467
0
  if (unlikely (font->privateDictInfo.size &&
468
0
          privDictStr == (const unsigned char *) &Null (UnsizedByteStr))) goto fail;
469
0
  cff2_priv_dict_interp_env_t env2 (privDictStr);
470
0
  dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t> priv_interp (env2);
471
0
  privateDicts[i].init ();
472
0
  if (unlikely (!priv_interp.interpret (privateDicts[i]))) goto fail;
473
474
0
  privateDicts[i].localSubrs = &StructAtOffsetOrNull<CFF2Subrs> (&privDictStr[0], privateDicts[i].subrsOffset, sc);
475
0
      }
476
477
0
      return;
478
479
1
      fail:
480
1
        _fini ();
481
1
    }
Unexecuted instantiation: OT::cff2::accelerator_templ_t<CFF::cff2_private_dict_opset_subset_t, CFF::cff2_private_dict_values_base_t<CFF::op_str_t> >::accelerator_templ_t(hb_face_t*)
482
0
    ~accelerator_templ_t () { _fini (); }
Unexecuted instantiation: OT::cff2::accelerator_templ_t<CFF::cff2_private_dict_opset_t, CFF::cff2_private_dict_values_base_t<CFF::dict_val_t> >::~accelerator_templ_t()
Unexecuted instantiation: OT::cff2::accelerator_templ_t<CFF::cff2_private_dict_opset_subset_t, CFF::cff2_private_dict_values_base_t<CFF::op_str_t> >::~accelerator_templ_t()
483
    void _fini ()
484
1
    {
485
1
      sc.end_processing ();
486
1
      topDict.fini ();
487
1
      fontDicts.fini ();
488
1
      privateDicts.fini ();
489
1
      hb_blob_destroy (blob);
490
1
      blob = nullptr;
491
492
1
      auto *scalars = cached_scalars_vector.get_acquire ();
493
1
      if (scalars && cached_scalars_vector.cmpexch (scalars, nullptr))
494
0
      {
495
0
  scalars->fini ();
496
0
  hb_free (scalars);
497
0
      }
498
1
    }
OT::cff2::accelerator_templ_t<CFF::cff2_private_dict_opset_t, CFF::cff2_private_dict_values_base_t<CFF::dict_val_t> >::_fini()
Line
Count
Source
484
1
    {
485
1
      sc.end_processing ();
486
1
      topDict.fini ();
487
1
      fontDicts.fini ();
488
1
      privateDicts.fini ();
489
1
      hb_blob_destroy (blob);
490
1
      blob = nullptr;
491
492
1
      auto *scalars = cached_scalars_vector.get_acquire ();
493
1
      if (scalars && cached_scalars_vector.cmpexch (scalars, nullptr))
494
0
      {
495
0
  scalars->fini ();
496
0
  hb_free (scalars);
497
0
      }
498
1
    }
Unexecuted instantiation: OT::cff2::accelerator_templ_t<CFF::cff2_private_dict_opset_subset_t, CFF::cff2_private_dict_values_base_t<CFF::op_str_t> >::_fini()
499
500
    hb_vector_t<uint16_t> *create_glyph_to_sid_map () const
501
    {
502
      return nullptr;
503
    }
504
505
0
    hb_blob_t *get_blob () const { return blob; }
506
507
1
    bool is_valid () const { return blob; }
508
509
    protected:
510
    hb_sanitize_context_t sc;
511
512
    public:
513
    hb_blob_t     *blob = nullptr;
514
    cff2_top_dict_values_t  topDict;
515
    const CFF2Subrs   *globalSubrs = nullptr;
516
    const CFF2ItemVariationStore  *varStore = nullptr;
517
    const CFF2CharStrings *charStrings = nullptr;
518
    const CFF2FDArray   *fdArray = nullptr;
519
    const CFF2FDSelect    *fdSelect = nullptr;
520
    unsigned int    fdCount = 0;
521
522
    hb_vector_t<cff2_font_dict_values_t>     fontDicts;
523
    hb_vector_t<PRIVDICTVAL>  privateDicts;
524
525
    mutable hb_atomic_t<hb_vector_t<float> *> cached_scalars_vector;
526
527
    unsigned int        num_glyphs = 0;
528
  };
529
530
  struct accelerator_t : accelerator_templ_t<cff2_private_dict_opset_t, cff2_private_dict_values_t>
531
  {
532
1
    accelerator_t (hb_face_t *face) : accelerator_templ_t (face) {}
533
534
    HB_INTERNAL bool get_extents (hb_font_t *font,
535
          hb_codepoint_t glyph,
536
          hb_glyph_extents_t *extents) const;
537
    HB_INTERNAL bool get_extents_at (hb_font_t *font,
538
             hb_codepoint_t glyph,
539
             hb_glyph_extents_t *extents,
540
             hb_array_t<const int> coords,
541
             int64_t *budget = nullptr) const;
542
    HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session, int64_t *budget = nullptr) const;
543
    HB_INTERNAL bool get_path_at (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session, hb_array_t<const int> coords, int64_t *budget = nullptr) const;
544
  };
545
546
  struct accelerator_subset_t : accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t>
547
  {
548
0
    accelerator_subset_t (hb_face_t *face) : SUPER (face) {}
549
    ~accelerator_subset_t ()
550
0
    {
551
0
      if (cff_accelerator)
552
0
  cff_subset_accelerator_t::destroy (cff_accelerator);
553
0
    }
554
555
    HB_INTERNAL bool subset (hb_subset_context_t *c) const;
556
    HB_INTERNAL bool serialize (hb_serialize_context_t *c,
557
        struct cff2_subset_plan &plan,
558
        hb_array_t<int> normalized_coords) const;
559
560
    mutable CFF::cff_subset_accelerator_t* cff_accelerator = nullptr;
561
562
    typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> SUPER;
563
  };
564
565
  public:
566
  FixedVersion<HBUINT8>   version;  /* Version of CFF2 table. set to 0x0200u */
567
  NNOffsetTo<TopDict, HBUINT8>  topDict;  /* headerSize = Offset to Top DICT. */
568
  HBUINT16      topDictSize;  /* Top DICT size */
569
570
  public:
571
  DEFINE_SIZE_STATIC (5);
572
};
573
574
struct cff2_accelerator_t : cff2::accelerator_t {
575
1
  cff2_accelerator_t (hb_face_t *face) : cff2::accelerator_t (face) {}
576
};
577
578
struct cff2_subset_accelerator_t : cff2::accelerator_subset_t {
579
0
  cff2_subset_accelerator_t (hb_face_t *face) : cff2::accelerator_subset_t (face) {}
580
};
581
582
} /* namespace OT */
583
584
#endif /* HB_OT_CFF2_TABLE_HH */