Coverage Report

Created: 2024-05-20 07:14

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