Coverage Report

Created: 2024-08-27 12:17

/src/harfbuzz/src/hb-ot-kern-table.hh
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright © 2017  Google, 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
 * Google Author(s): Behdad Esfahbod
25
 */
26
27
#ifndef HB_OT_KERN_TABLE_HH
28
#define HB_OT_KERN_TABLE_HH
29
30
#include "hb-aat-layout-kerx-table.hh"
31
32
33
/*
34
 * kern -- Kerning
35
 * https://docs.microsoft.com/en-us/typography/opentype/spec/kern
36
 * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html
37
 */
38
#define HB_OT_TAG_kern HB_TAG('k','e','r','n')
39
40
41
namespace OT {
42
43
44
template <typename KernSubTableHeader>
45
struct KernSubTableFormat3
46
{
47
  int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
48
2.58k
  {
49
2.58k
    hb_array_t<const FWORD> kernValue = kernValueZ.as_array (kernValueCount);
50
2.58k
    hb_array_t<const HBUINT8> leftClass = StructAfter<const UnsizedArrayOf<HBUINT8>> (kernValue).as_array (glyphCount);
51
2.58k
    hb_array_t<const HBUINT8> rightClass = StructAfter<const UnsizedArrayOf<HBUINT8>> (leftClass).as_array (glyphCount);
52
2.58k
    hb_array_t<const HBUINT8> kernIndex = StructAfter<const UnsizedArrayOf<HBUINT8>> (rightClass).as_array (leftClassCount * rightClassCount);
53
54
2.58k
    unsigned int leftC = leftClass[left];
55
2.58k
    unsigned int rightC = rightClass[right];
56
2.58k
    if (unlikely (leftC >= leftClassCount || rightC >= rightClassCount))
57
1.46k
      return 0;
58
1.12k
    unsigned int i = leftC * rightClassCount + rightC;
59
1.12k
    return kernValue[kernIndex[i]];
60
2.58k
  }
Unexecuted instantiation: OT::KernSubTableFormat3<OT::KernOTSubTableHeader>::get_kerning(unsigned int, unsigned int) const
OT::KernSubTableFormat3<OT::KernAATSubTableHeader>::get_kerning(unsigned int, unsigned int) const
Line
Count
Source
48
2.58k
  {
49
2.58k
    hb_array_t<const FWORD> kernValue = kernValueZ.as_array (kernValueCount);
50
2.58k
    hb_array_t<const HBUINT8> leftClass = StructAfter<const UnsizedArrayOf<HBUINT8>> (kernValue).as_array (glyphCount);
51
2.58k
    hb_array_t<const HBUINT8> rightClass = StructAfter<const UnsizedArrayOf<HBUINT8>> (leftClass).as_array (glyphCount);
52
2.58k
    hb_array_t<const HBUINT8> kernIndex = StructAfter<const UnsizedArrayOf<HBUINT8>> (rightClass).as_array (leftClassCount * rightClassCount);
53
54
2.58k
    unsigned int leftC = leftClass[left];
55
2.58k
    unsigned int rightC = rightClass[right];
56
2.58k
    if (unlikely (leftC >= leftClassCount || rightC >= rightClassCount))
57
1.46k
      return 0;
58
1.12k
    unsigned int i = leftC * rightClassCount + rightC;
59
1.12k
    return kernValue[kernIndex[i]];
60
2.58k
  }
61
62
  bool apply (AAT::hb_aat_apply_context_t *c) const
63
1.09k
  {
64
1.09k
    TRACE_APPLY (this);
65
66
1.09k
    if (!c->plan->requested_kerning)
67
275
      return false;
68
69
815
    if (header.coverage & header.Backwards)
70
0
      return false;
71
72
815
    hb_kern_machine_t<KernSubTableFormat3> machine (*this, header.coverage & header.CrossStream);
73
815
    machine.kern (c->font, c->buffer, c->plan->kern_mask);
74
75
815
    return_trace (true);
76
815
  }
Unexecuted instantiation: OT::KernSubTableFormat3<OT::KernOTSubTableHeader>::apply(AAT::hb_aat_apply_context_t*) const
OT::KernSubTableFormat3<OT::KernAATSubTableHeader>::apply(AAT::hb_aat_apply_context_t*) const
Line
Count
Source
63
1.09k
  {
64
1.09k
    TRACE_APPLY (this);
65
66
1.09k
    if (!c->plan->requested_kerning)
67
275
      return false;
68
69
815
    if (header.coverage & header.Backwards)
70
0
      return false;
71
72
815
    hb_kern_machine_t<KernSubTableFormat3> machine (*this, header.coverage & header.CrossStream);
73
815
    machine.kern (c->font, c->buffer, c->plan->kern_mask);
74
75
815
    return_trace (true);
76
815
  }
77
78
  bool sanitize (hb_sanitize_context_t *c) const
79
150
  {
80
150
    TRACE_SANITIZE (this);
81
150
    return_trace (c->check_struct (this) &&
82
150
      c->check_range (kernValueZ,
83
150
          kernValueCount * sizeof (FWORD) +
84
150
          glyphCount * 2 +
85
150
          leftClassCount * rightClassCount));
86
150
  }
Unexecuted instantiation: OT::KernSubTableFormat3<OT::KernOTSubTableHeader>::sanitize(hb_sanitize_context_t*) const
OT::KernSubTableFormat3<OT::KernAATSubTableHeader>::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
79
150
  {
80
150
    TRACE_SANITIZE (this);
81
150
    return_trace (c->check_struct (this) &&
82
150
      c->check_range (kernValueZ,
83
150
          kernValueCount * sizeof (FWORD) +
84
150
          glyphCount * 2 +
85
150
          leftClassCount * rightClassCount));
86
150
  }
87
88
  protected:
89
  KernSubTableHeader
90
    header;
91
  HBUINT16  glyphCount; /* The number of glyphs in this font. */
92
  HBUINT8 kernValueCount; /* The number of kerning values. */
93
  HBUINT8 leftClassCount; /* The number of left-hand classes. */
94
  HBUINT8 rightClassCount;/* The number of right-hand classes. */
95
  HBUINT8 flags;    /* Set to zero (reserved for future use). */
96
  UnsizedArrayOf<FWORD>
97
    kernValueZ; /* The kerning values.
98
         * Length kernValueCount. */
99
#if 0
100
  UnsizedArrayOf<HBUINT8>
101
    leftClass;  /* The left-hand classes.
102
         * Length glyphCount. */
103
  UnsizedArrayOf<HBUINT8>
104
    rightClass; /* The right-hand classes.
105
         * Length glyphCount. */
106
  UnsizedArrayOf<HBUINT8>kernIndex;
107
        /* The indices into the kernValue array.
108
         * Length leftClassCount * rightClassCount */
109
#endif
110
  public:
111
  DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 6, kernValueZ);
112
};
113
114
template <typename KernSubTableHeader>
115
struct KernSubTable
116
{
117
87.8k
  unsigned int get_size () const { return u.header.length; }
OT::KernSubTable<OT::KernOTSubTableHeader>::get_size() const
Line
Count
Source
117
66.8k
  unsigned int get_size () const { return u.header.length; }
OT::KernSubTable<OT::KernAATSubTableHeader>::get_size() const
Line
Count
Source
117
21.0k
  unsigned int get_size () const { return u.header.length; }
118
47.5k
  unsigned int get_type () const { return u.header.format; }
OT::KernSubTable<OT::KernOTSubTableHeader>::get_type() const
Line
Count
Source
118
33.0k
  unsigned int get_type () const { return u.header.format; }
OT::KernSubTable<OT::KernAATSubTableHeader>::get_type() const
Line
Count
Source
118
14.5k
  unsigned int get_type () const { return u.header.format; }
119
120
  int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
121
0
  {
122
0
    switch (get_type ()) {
123
0
    /* This method hooks up to hb_font_t's get_h_kerning.  Only support Format0. */
124
0
    case 0: return u.format0.get_kerning (left, right);
125
0
    default:return 0;
126
0
    }
127
0
  }
Unexecuted instantiation: OT::KernSubTable<OT::KernOTSubTableHeader>::get_kerning(unsigned int, unsigned int) const
Unexecuted instantiation: OT::KernSubTable<OT::KernAATSubTableHeader>::get_kerning(unsigned int, unsigned int) const
128
129
  template <typename context_t, typename ...Ts>
130
  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
131
41.4k
  {
132
41.4k
    unsigned int subtable_type = get_type ();
133
41.4k
    TRACE_DISPATCH (this, subtable_type);
134
41.4k
    switch (subtable_type) {
135
15.0k
    case 0: return_trace (c->dispatch (u.format0));
136
0
#ifndef HB_NO_AAT_SHAPE
137
2.28k
    case 1: return_trace (u.header.apple ? c->dispatch (u.format1, std::forward<Ts> (ds)...) : c->default_return_value ());
138
0
#endif
139
6.64k
    case 2: return_trace (c->dispatch (u.format2));
140
0
#ifndef HB_NO_AAT_SHAPE
141
1.71k
    case 3: return_trace (u.header.apple ? c->dispatch (u.format3, std::forward<Ts> (ds)...) : c->default_return_value ());
142
0
#endif
143
15.7k
    default:  return_trace (c->default_return_value ());
144
41.4k
    }
145
41.4k
  }
AAT::hb_aat_apply_context_t::return_t OT::KernSubTable<OT::KernOTSubTableHeader>::dispatch<AAT::hb_aat_apply_context_t>(AAT::hb_aat_apply_context_t*) const
Line
Count
Source
131
23.5k
  {
132
23.5k
    unsigned int subtable_type = get_type ();
133
23.5k
    TRACE_DISPATCH (this, subtable_type);
134
23.5k
    switch (subtable_type) {
135
9.55k
    case 0: return_trace (c->dispatch (u.format0));
136
0
#ifndef HB_NO_AAT_SHAPE
137
949
    case 1: return_trace (u.header.apple ? c->dispatch (u.format1, std::forward<Ts> (ds)...) : c->default_return_value ());
138
0
#endif
139
1.36k
    case 2: return_trace (c->dispatch (u.format2));
140
0
#ifndef HB_NO_AAT_SHAPE
141
401
    case 3: return_trace (u.header.apple ? c->dispatch (u.format3, std::forward<Ts> (ds)...) : c->default_return_value ());
142
0
#endif
143
11.3k
    default:  return_trace (c->default_return_value ());
144
23.5k
    }
145
23.5k
  }
AAT::hb_aat_apply_context_t::return_t OT::KernSubTable<OT::KernAATSubTableHeader>::dispatch<AAT::hb_aat_apply_context_t>(AAT::hb_aat_apply_context_t*) const
Line
Count
Source
131
11.0k
  {
132
11.0k
    unsigned int subtable_type = get_type ();
133
11.0k
    TRACE_DISPATCH (this, subtable_type);
134
11.0k
    switch (subtable_type) {
135
3.55k
    case 0: return_trace (c->dispatch (u.format0));
136
0
#ifndef HB_NO_AAT_SHAPE
137
671
    case 1: return_trace (u.header.apple ? c->dispatch (u.format1, std::forward<Ts> (ds)...) : c->default_return_value ());
138
0
#endif
139
4.51k
    case 2: return_trace (c->dispatch (u.format2));
140
0
#ifndef HB_NO_AAT_SHAPE
141
1.09k
    case 3: return_trace (u.header.apple ? c->dispatch (u.format3, std::forward<Ts> (ds)...) : c->default_return_value ());
142
0
#endif
143
1.24k
    default:  return_trace (c->default_return_value ());
144
11.0k
    }
145
11.0k
  }
hb_sanitize_context_t::return_t OT::KernSubTable<OT::KernOTSubTableHeader>::dispatch<hb_sanitize_context_t>(hb_sanitize_context_t*) const
Line
Count
Source
131
4.93k
  {
132
4.93k
    unsigned int subtable_type = get_type ();
133
4.93k
    TRACE_DISPATCH (this, subtable_type);
134
4.93k
    switch (subtable_type) {
135
1.41k
    case 0: return_trace (c->dispatch (u.format0));
136
0
#ifndef HB_NO_AAT_SHAPE
137
297
    case 1: return_trace (u.header.apple ? c->dispatch (u.format1, std::forward<Ts> (ds)...) : c->default_return_value ());
138
0
#endif
139
334
    case 2: return_trace (c->dispatch (u.format2));
140
0
#ifndef HB_NO_AAT_SHAPE
141
71
    case 3: return_trace (u.header.apple ? c->dispatch (u.format3, std::forward<Ts> (ds)...) : c->default_return_value ());
142
0
#endif
143
2.82k
    default:  return_trace (c->default_return_value ());
144
4.93k
    }
145
4.93k
  }
hb_sanitize_context_t::return_t OT::KernSubTable<OT::KernAATSubTableHeader>::dispatch<hb_sanitize_context_t>(hb_sanitize_context_t*) const
Line
Count
Source
131
1.87k
  {
132
1.87k
    unsigned int subtable_type = get_type ();
133
1.87k
    TRACE_DISPATCH (this, subtable_type);
134
1.87k
    switch (subtable_type) {
135
537
    case 0: return_trace (c->dispatch (u.format0));
136
0
#ifndef HB_NO_AAT_SHAPE
137
372
    case 1: return_trace (u.header.apple ? c->dispatch (u.format1, std::forward<Ts> (ds)...) : c->default_return_value ());
138
0
#endif
139
433
    case 2: return_trace (c->dispatch (u.format2));
140
0
#ifndef HB_NO_AAT_SHAPE
141
150
    case 3: return_trace (u.header.apple ? c->dispatch (u.format3, std::forward<Ts> (ds)...) : c->default_return_value ());
142
0
#endif
143
385
    default:  return_trace (c->default_return_value ());
144
1.87k
    }
145
1.87k
  }
146
147
  bool sanitize (hb_sanitize_context_t *c) const
148
7.22k
  {
149
7.22k
    TRACE_SANITIZE (this);
150
7.22k
    if (unlikely (!u.header.sanitize (c) ||
151
7.22k
      u.header.length < u.header.min_size ||
152
7.22k
      !c->check_range (this, u.header.length))) return_trace (false);
153
154
7.22k
    return_trace (dispatch (c));
155
7.22k
  }
OT::KernSubTable<OT::KernOTSubTableHeader>::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
148
5.14k
  {
149
5.14k
    TRACE_SANITIZE (this);
150
5.14k
    if (unlikely (!u.header.sanitize (c) ||
151
5.14k
      u.header.length < u.header.min_size ||
152
5.14k
      !c->check_range (this, u.header.length))) return_trace (false);
153
154
4.93k
    return_trace (dispatch (c));
155
5.14k
  }
OT::KernSubTable<OT::KernAATSubTableHeader>::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
148
2.08k
  {
149
2.08k
    TRACE_SANITIZE (this);
150
2.08k
    if (unlikely (!u.header.sanitize (c) ||
151
2.08k
      u.header.length < u.header.min_size ||
152
2.08k
      !c->check_range (this, u.header.length))) return_trace (false);
153
154
1.87k
    return_trace (dispatch (c));
155
2.08k
  }
156
157
  public:
158
  union {
159
  KernSubTableHeader        header;
160
  AAT::KerxSubTableFormat0<KernSubTableHeader>  format0;
161
  AAT::KerxSubTableFormat1<KernSubTableHeader>  format1;
162
  AAT::KerxSubTableFormat2<KernSubTableHeader>  format2;
163
  KernSubTableFormat3<KernSubTableHeader> format3;
164
  } u;
165
  public:
166
  DEFINE_SIZE_MIN (KernSubTableHeader::static_size);
167
};
168
169
170
struct KernOTSubTableHeader
171
{
172
  static constexpr bool apple = false;
173
  typedef AAT::ObsoleteTypes Types;
174
175
19.3k
  unsigned   tuple_count () const { return 0; }
176
40.4k
  bool     is_horizontal () const { return (coverage & Horizontal); }
177
178
  enum Coverage
179
  {
180
    Horizontal  = 0x01u,
181
    Minimum = 0x02u,
182
    CrossStream = 0x04u,
183
    Override  = 0x08u,
184
185
    /* Not supported: */
186
    Backwards = 0x00u,
187
    Variation = 0x00u,
188
  };
189
190
  bool sanitize (hb_sanitize_context_t *c) const
191
10.3k
  {
192
10.3k
    TRACE_SANITIZE (this);
193
10.3k
    return_trace (c->check_struct (this));
194
10.3k
  }
195
196
  public:
197
  HBUINT16  versionZ; /* Unused. */
198
  HBUINT16  length;   /* Length of the subtable (including this header). */
199
  HBUINT8 format;   /* Subtable format. */
200
  HBUINT8 coverage; /* Coverage bits. */
201
  public:
202
  DEFINE_SIZE_STATIC (6);
203
};
204
205
struct KernOT : AAT::KerxTable<KernOT>
206
{
207
  friend struct AAT::KerxTable<KernOT>;
208
209
  static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
210
  static constexpr unsigned minVersion = 0u;
211
212
  typedef KernOTSubTableHeader SubTableHeader;
213
  typedef SubTableHeader::Types Types;
214
  typedef KernSubTable<SubTableHeader> SubTable;
215
216
  protected:
217
  HBUINT16  version;  /* Version--0x0000u */
218
  HBUINT16  tableCount; /* Number of subtables in the kerning table. */
219
  SubTable  firstSubTable;  /* Subtables. */
220
  public:
221
  DEFINE_SIZE_MIN (4);
222
};
223
224
225
struct KernAATSubTableHeader
226
{
227
  static constexpr bool apple = true;
228
  typedef AAT::ObsoleteTypes Types;
229
230
437k
  unsigned   tuple_count () const { return 0; }
231
11.2k
  bool     is_horizontal () const { return !(coverage & Vertical); }
232
233
  enum Coverage
234
  {
235
    Vertical  = 0x80u,
236
    CrossStream = 0x40u,
237
    Variation = 0x20u,
238
239
    /* Not supported: */
240
    Backwards = 0x00u,
241
  };
242
243
  bool sanitize (hb_sanitize_context_t *c) const
244
4.21k
  {
245
4.21k
    TRACE_SANITIZE (this);
246
4.21k
    return_trace (c->check_struct (this));
247
4.21k
  }
248
249
  public:
250
  HBUINT32  length;   /* Length of the subtable (including this header). */
251
  HBUINT8 coverage; /* Coverage bits. */
252
  HBUINT8 format;   /* Subtable format. */
253
  HBUINT16  tupleIndex; /* The tuple index (used for variations fonts).
254
         * This value specifies which tuple this subtable covers.
255
         * Note: We don't implement. */
256
  public:
257
  DEFINE_SIZE_STATIC (8);
258
};
259
260
struct KernAAT : AAT::KerxTable<KernAAT>
261
{
262
  friend struct AAT::KerxTable<KernAAT>;
263
264
  static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
265
  static constexpr unsigned minVersion = 0x00010000u;
266
267
  typedef KernAATSubTableHeader SubTableHeader;
268
  typedef SubTableHeader::Types Types;
269
  typedef KernSubTable<SubTableHeader> SubTable;
270
271
  protected:
272
  HBUINT32  version;  /* Version--0x00010000u */
273
  HBUINT32  tableCount; /* Number of subtables in the kerning table. */
274
  SubTable  firstSubTable;  /* Subtables. */
275
  public:
276
  DEFINE_SIZE_MIN (8);
277
};
278
279
struct kern
280
{
281
  static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
282
283
298k
  bool     has_data () const { return u.version32; }
284
36.6k
  unsigned get_type () const { return u.major; }
285
286
  bool has_state_machine () const
287
3.45k
  {
288
3.45k
    switch (get_type ()) {
289
1.69k
    case 0: return u.ot.has_state_machine ();
290
0
#ifndef HB_NO_AAT_SHAPE
291
1.33k
    case 1: return u.aat.has_state_machine ();
292
0
#endif
293
419
    default:return false;
294
3.45k
    }
295
3.45k
  }
296
297
  bool has_cross_stream () const
298
2.85k
  {
299
2.85k
    switch (get_type ()) {
300
1.31k
    case 0: return u.ot.has_cross_stream ();
301
0
#ifndef HB_NO_AAT_SHAPE
302
1.17k
    case 1: return u.aat.has_cross_stream ();
303
0
#endif
304
370
    default:return false;
305
2.85k
    }
306
2.85k
  }
307
308
  int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
309
0
  {
310
0
    switch (get_type ()) {
311
0
    case 0: return u.ot.get_h_kerning (left, right);
312
0
#ifndef HB_NO_AAT_SHAPE
313
0
    case 1: return u.aat.get_h_kerning (left, right);
314
0
#endif
315
0
    default:return 0;
316
0
    }
317
0
  }
318
319
  bool apply (AAT::hb_aat_apply_context_t *c) const
320
27.0k
  { return dispatch (c); }
321
322
  template <typename context_t, typename ...Ts>
323
  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
324
30.3k
  {
325
30.3k
    unsigned int subtable_type = get_type ();
326
30.3k
    TRACE_DISPATCH (this, subtable_type);
327
30.3k
    switch (subtable_type) {
328
16.7k
    case 0: return_trace (c->dispatch (u.ot, std::forward<Ts> (ds)...));
329
0
#ifndef HB_NO_AAT_SHAPE
330
9.95k
    case 1: return_trace (c->dispatch (u.aat, std::forward<Ts> (ds)...));
331
0
#endif
332
3.59k
    default:  return_trace (c->default_return_value ());
333
30.3k
    }
334
30.3k
  }
AAT::hb_aat_apply_context_t::return_t OT::kern::dispatch<AAT::hb_aat_apply_context_t>(AAT::hb_aat_apply_context_t*) const
Line
Count
Source
324
27.0k
  {
325
27.0k
    unsigned int subtable_type = get_type ();
326
27.0k
    TRACE_DISPATCH (this, subtable_type);
327
27.0k
    switch (subtable_type) {
328
15.1k
    case 0: return_trace (c->dispatch (u.ot, std::forward<Ts> (ds)...));
329
0
#ifndef HB_NO_AAT_SHAPE
330
8.54k
    case 1: return_trace (c->dispatch (u.aat, std::forward<Ts> (ds)...));
331
0
#endif
332
3.35k
    default:  return_trace (c->default_return_value ());
333
27.0k
    }
334
27.0k
  }
hb_sanitize_context_t::return_t OT::kern::dispatch<hb_sanitize_context_t>(hb_sanitize_context_t*) const
Line
Count
Source
324
3.25k
  {
325
3.25k
    unsigned int subtable_type = get_type ();
326
3.25k
    TRACE_DISPATCH (this, subtable_type);
327
3.25k
    switch (subtable_type) {
328
1.59k
    case 0: return_trace (c->dispatch (u.ot, std::forward<Ts> (ds)...));
329
0
#ifndef HB_NO_AAT_SHAPE
330
1.41k
    case 1: return_trace (c->dispatch (u.aat, std::forward<Ts> (ds)...));
331
0
#endif
332
243
    default:  return_trace (c->default_return_value ());
333
3.25k
    }
334
3.25k
  }
335
336
  bool sanitize (hb_sanitize_context_t *c) const
337
3.27k
  {
338
3.27k
    TRACE_SANITIZE (this);
339
3.27k
    if (!u.version32.sanitize (c)) return_trace (false);
340
3.25k
    return_trace (dispatch (c));
341
3.27k
  }
342
343
  protected:
344
  union {
345
  HBUINT32    version32;
346
  HBUINT16    major;
347
  KernOT    ot;
348
#ifndef HB_NO_AAT_SHAPE
349
  KernAAT   aat;
350
#endif
351
  } u;
352
  public:
353
  DEFINE_SIZE_UNION (4, version32);
354
};
355
356
} /* namespace OT */
357
358
359
#endif /* HB_OT_KERN_TABLE_HH */