Coverage Report

Created: 2023-06-07 06:14

/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
0
  {
49
0
    hb_array_t<const FWORD> kernValue = kernValueZ.as_array (kernValueCount);
50
0
    hb_array_t<const HBUINT8> leftClass = StructAfter<const UnsizedArrayOf<HBUINT8>> (kernValue).as_array (glyphCount);
51
0
    hb_array_t<const HBUINT8> rightClass = StructAfter<const UnsizedArrayOf<HBUINT8>> (leftClass).as_array (glyphCount);
52
0
    hb_array_t<const HBUINT8> kernIndex = StructAfter<const UnsizedArrayOf<HBUINT8>> (rightClass).as_array (leftClassCount * rightClassCount);
53
54
0
    unsigned int leftC = leftClass[left];
55
0
    unsigned int rightC = rightClass[right];
56
0
    if (unlikely (leftC >= leftClassCount || rightC >= rightClassCount))
57
0
      return 0;
58
0
    unsigned int i = leftC * rightClassCount + rightC;
59
0
    return kernValue[kernIndex[i]];
60
0
  }
Unexecuted instantiation: OT::KernSubTableFormat3<OT::KernOTSubTableHeader>::get_kerning(unsigned int, unsigned int) const
Unexecuted instantiation: OT::KernSubTableFormat3<OT::KernAATSubTableHeader>::get_kerning(unsigned int, unsigned int) const
61
62
  bool apply (AAT::hb_aat_apply_context_t *c) const
63
0
  {
64
0
    TRACE_APPLY (this);
65
66
0
    if (!c->plan->requested_kerning)
67
0
      return false;
68
69
0
    if (header.coverage & header.Backwards)
70
0
      return false;
71
72
0
    hb_kern_machine_t<KernSubTableFormat3> machine (*this, header.coverage & header.CrossStream);
73
0
    machine.kern (c->font, c->buffer, c->plan->kern_mask);
74
75
0
    return_trace (true);
76
0
  }
Unexecuted instantiation: OT::KernSubTableFormat3<OT::KernOTSubTableHeader>::apply(AAT::hb_aat_apply_context_t*) const
Unexecuted instantiation: OT::KernSubTableFormat3<OT::KernAATSubTableHeader>::apply(AAT::hb_aat_apply_context_t*) const
77
78
  bool sanitize (hb_sanitize_context_t *c) const
79
0
  {
80
0
    TRACE_SANITIZE (this);
81
0
    return_trace (c->check_struct (this) &&
82
0
      c->check_range (kernValueZ,
83
0
          kernValueCount * sizeof (FWORD) +
84
0
          glyphCount * 2 +
85
0
          leftClassCount * rightClassCount));
86
0
  }
Unexecuted instantiation: OT::KernSubTableFormat3<OT::KernOTSubTableHeader>::sanitize(hb_sanitize_context_t*) const
Unexecuted instantiation: OT::KernSubTableFormat3<OT::KernAATSubTableHeader>::sanitize(hb_sanitize_context_t*) const
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
74
  unsigned int get_size () const { return u.header.length; }
OT::KernSubTable<OT::KernOTSubTableHeader>::get_size() const
Line
Count
Source
117
74
  unsigned int get_size () const { return u.header.length; }
Unexecuted instantiation: OT::KernSubTable<OT::KernAATSubTableHeader>::get_size() const
118
44
  unsigned int get_type () const { return u.header.format; }
OT::KernSubTable<OT::KernOTSubTableHeader>::get_type() const
Line
Count
Source
118
44
  unsigned int get_type () const { return u.header.format; }
Unexecuted instantiation: OT::KernSubTable<OT::KernAATSubTableHeader>::get_type() const
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
40
  {
132
40
    unsigned int subtable_type = get_type ();
133
40
    TRACE_DISPATCH (this, subtable_type);
134
40
    switch (subtable_type) {
135
40
    case 0: return_trace (c->dispatch (u.format0));
136
0
#ifndef HB_NO_AAT_SHAPE
137
0
    case 1: return_trace (u.header.apple ? c->dispatch (u.format1, std::forward<Ts> (ds)...) : c->default_return_value ());
138
0
#endif
139
0
    case 2: return_trace (c->dispatch (u.format2));
140
0
#ifndef HB_NO_AAT_SHAPE
141
0
    case 3: return_trace (u.header.apple ? c->dispatch (u.format3, std::forward<Ts> (ds)...) : c->default_return_value ());
142
0
#endif
143
0
    default:  return_trace (c->default_return_value ());
144
40
    }
145
40
  }
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
36
  {
132
36
    unsigned int subtable_type = get_type ();
133
36
    TRACE_DISPATCH (this, subtable_type);
134
36
    switch (subtable_type) {
135
36
    case 0: return_trace (c->dispatch (u.format0));
136
0
#ifndef HB_NO_AAT_SHAPE
137
0
    case 1: return_trace (u.header.apple ? c->dispatch (u.format1, std::forward<Ts> (ds)...) : c->default_return_value ());
138
0
#endif
139
0
    case 2: return_trace (c->dispatch (u.format2));
140
0
#ifndef HB_NO_AAT_SHAPE
141
0
    case 3: return_trace (u.header.apple ? c->dispatch (u.format3, std::forward<Ts> (ds)...) : c->default_return_value ());
142
0
#endif
143
0
    default:  return_trace (c->default_return_value ());
144
36
    }
145
36
  }
Unexecuted instantiation: 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
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
  {
132
4
    unsigned int subtable_type = get_type ();
133
4
    TRACE_DISPATCH (this, subtable_type);
134
4
    switch (subtable_type) {
135
4
    case 0: return_trace (c->dispatch (u.format0));
136
0
#ifndef HB_NO_AAT_SHAPE
137
0
    case 1: return_trace (u.header.apple ? c->dispatch (u.format1, std::forward<Ts> (ds)...) : c->default_return_value ());
138
0
#endif
139
0
    case 2: return_trace (c->dispatch (u.format2));
140
0
#ifndef HB_NO_AAT_SHAPE
141
0
    case 3: return_trace (u.header.apple ? c->dispatch (u.format3, std::forward<Ts> (ds)...) : c->default_return_value ());
142
0
#endif
143
0
    default:  return_trace (c->default_return_value ());
144
4
    }
145
4
  }
Unexecuted instantiation: hb_sanitize_context_t::return_t OT::KernSubTable<OT::KernAATSubTableHeader>::dispatch<hb_sanitize_context_t>(hb_sanitize_context_t*) const
146
147
  bool sanitize (hb_sanitize_context_t *c) const
148
4
  {
149
4
    TRACE_SANITIZE (this);
150
4
    if (unlikely (!u.header.sanitize (c) ||
151
4
      u.header.length < u.header.min_size ||
152
4
      !c->check_range (this, u.header.length))) return_trace (false);
153
154
4
    return_trace (dispatch (c));
155
4
  }
OT::KernSubTable<OT::KernOTSubTableHeader>::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
148
4
  {
149
4
    TRACE_SANITIZE (this);
150
4
    if (unlikely (!u.header.sanitize (c) ||
151
4
      u.header.length < u.header.min_size ||
152
4
      !c->check_range (this, u.header.length))) return_trace (false);
153
154
4
    return_trace (dispatch (c));
155
4
  }
Unexecuted instantiation: OT::KernSubTable<OT::KernAATSubTableHeader>::sanitize(hb_sanitize_context_t*) const
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
0
  unsigned   tuple_count () const { return 0; }
176
36
  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
8
  {
192
8
    TRACE_SANITIZE (this);
193
8
    return_trace (c->check_struct (this));
194
8
  }
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
0
  unsigned   tuple_count () const { return 0; }
231
0
  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
0
  {
245
0
    TRACE_SANITIZE (this);
246
0
    return_trace (c->check_struct (this));
247
0
  }
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
20
  bool     has_data () const { return u.version32; }
284
11
  unsigned get_type () const { return u.major; }
285
286
  bool has_state_machine () const
287
1
  {
288
1
    switch (get_type ()) {
289
1
    case 0: return u.ot.has_state_machine ();
290
0
#ifndef HB_NO_AAT_SHAPE
291
0
    case 1: return u.aat.has_state_machine ();
292
0
#endif
293
0
    default:return false;
294
1
    }
295
1
  }
296
297
  bool has_cross_stream () const
298
0
  {
299
0
    switch (get_type ()) {
300
0
    case 0: return u.ot.has_cross_stream ();
301
0
#ifndef HB_NO_AAT_SHAPE
302
0
    case 1: return u.aat.has_cross_stream ();
303
0
#endif
304
0
    default:return false;
305
0
    }
306
0
  }
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
9
  { 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
10
  {
325
10
    unsigned int subtable_type = get_type ();
326
10
    TRACE_DISPATCH (this, subtable_type);
327
10
    switch (subtable_type) {
328
10
    case 0: return_trace (c->dispatch (u.ot, std::forward<Ts> (ds)...));
329
0
#ifndef HB_NO_AAT_SHAPE
330
0
    case 1: return_trace (c->dispatch (u.aat, std::forward<Ts> (ds)...));
331
0
#endif
332
0
    default:  return_trace (c->default_return_value ());
333
10
    }
334
10
  }
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
9
  {
325
9
    unsigned int subtable_type = get_type ();
326
9
    TRACE_DISPATCH (this, subtable_type);
327
9
    switch (subtable_type) {
328
9
    case 0: return_trace (c->dispatch (u.ot, std::forward<Ts> (ds)...));
329
0
#ifndef HB_NO_AAT_SHAPE
330
0
    case 1: return_trace (c->dispatch (u.aat, std::forward<Ts> (ds)...));
331
0
#endif
332
0
    default:  return_trace (c->default_return_value ());
333
9
    }
334
9
  }
hb_sanitize_context_t::return_t OT::kern::dispatch<hb_sanitize_context_t>(hb_sanitize_context_t*) const
Line
Count
Source
324
1
  {
325
1
    unsigned int subtable_type = get_type ();
326
1
    TRACE_DISPATCH (this, subtable_type);
327
1
    switch (subtable_type) {
328
1
    case 0: return_trace (c->dispatch (u.ot, std::forward<Ts> (ds)...));
329
0
#ifndef HB_NO_AAT_SHAPE
330
0
    case 1: return_trace (c->dispatch (u.aat, std::forward<Ts> (ds)...));
331
0
#endif
332
0
    default:  return_trace (c->default_return_value ());
333
1
    }
334
1
  }
335
336
  bool sanitize (hb_sanitize_context_t *c) const
337
1
  {
338
1
    TRACE_SANITIZE (this);
339
1
    if (!u.version32.sanitize (c)) return_trace (false);
340
1
    return_trace (dispatch (c));
341
1
  }
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 */