2 * Copyright © 2017 Google, Inc.
4 * This is part of HarfBuzz, a text shaping library.
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.
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
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.
24 * Google Author(s): Behdad Esfahbod
27 #ifndef HB_OT_KERN_TABLE_HH
28 #define HB_OT_KERN_TABLE_HH
30 #include "hb-aat-layout-kerx-table.hh"
35 * https://docs.microsoft.com/en-us/typography/opentype/spec/kern
36 * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html
38 #define HB_OT_TAG_kern HB_TAG('k','e','r','n')
44 template <typename KernSubTableHeader>
45 struct KernSubTableFormat3
47 int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
49 hb_array_t<const FWORD> kernValue = kernValueZ.as_array (kernValueCount);
50 hb_array_t<const HBUINT8> leftClass = StructAfter<const UnsizedArrayOf<HBUINT8>> (kernValue).as_array (glyphCount);
51 hb_array_t<const HBUINT8> rightClass = StructAfter<const UnsizedArrayOf<HBUINT8>> (leftClass).as_array (glyphCount);
52 hb_array_t<const HBUINT8> kernIndex = StructAfter<const UnsizedArrayOf<HBUINT8>> (rightClass).as_array (leftClassCount * rightClassCount);
54 unsigned int leftC = leftClass[left];
55 unsigned int rightC = rightClass[right];
56 if (unlikely (leftC >= leftClassCount || rightC >= rightClassCount))
58 unsigned int i = leftC * rightClassCount + rightC;
59 return kernValue[kernIndex[i]];
62 bool apply (AAT::hb_aat_apply_context_t *c) const
66 if (!c->plan->requested_kerning)
69 if (header.coverage & header.Backwards)
72 hb_kern_machine_t<KernSubTableFormat3> machine (*this, header.coverage & header.CrossStream);
73 machine.kern (c->font, c->buffer, c->plan->kern_mask);
78 bool sanitize (hb_sanitize_context_t *c) const
80 TRACE_SANITIZE (this);
81 return_trace (c->check_struct (this) &&
82 c->check_range (kernValueZ,
83 kernValueCount * sizeof (FWORD) +
85 leftClassCount * rightClassCount));
89 KernSubTableHeader header;
90 HBUINT16 glyphCount; /* The number of glyphs in this font. */
91 HBUINT8 kernValueCount; /* The number of kerning values. */
92 HBUINT8 leftClassCount; /* The number of left-hand classes. */
93 HBUINT8 rightClassCount;/* The number of right-hand classes. */
94 HBUINT8 flags; /* Set to zero (reserved for future use). */
95 UnsizedArrayOf<FWORD> kernValueZ; /* The kerning values.
96 * Length kernValueCount. */
98 UnsizedArrayOf<HBUINT8>leftClass; /* The left-hand classes.
99 * Length glyphCount. */
100 UnsizedArrayOf<HBUINT8>rightClass; /* The right-hand classes.
101 * Length glyphCount. */
102 UnsizedArrayOf<HBUINT8>kernIndex; /* The indices into the kernValue array.
103 * Length leftClassCount * rightClassCount */
106 DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 6, kernValueZ);
109 template <typename KernSubTableHeader>
112 unsigned int get_size () const { return u.header.length; }
113 unsigned int get_type () const { return u.header.format; }
115 int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
117 switch (get_type ()) {
118 /* This method hooks up to hb_font_t's get_h_kerning. Only support Format0. */
119 case 0: return u.format0.get_kerning (left, right);
124 template <typename context_t, typename ...Ts>
125 typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
127 unsigned int subtable_type = get_type ();
128 TRACE_DISPATCH (this, subtable_type);
129 switch (subtable_type) {
130 case 0: return_trace (c->dispatch (u.format0));
131 #ifndef HB_NO_AAT_SHAPE
132 case 1: return_trace (u.header.apple ? c->dispatch (u.format1, hb_forward<Ts> (ds)...) : c->default_return_value ());
134 case 2: return_trace (c->dispatch (u.format2));
135 #ifndef HB_NO_AAT_SHAPE
136 case 3: return_trace (u.header.apple ? c->dispatch (u.format3, hb_forward<Ts> (ds)...) : c->default_return_value ());
138 default: return_trace (c->default_return_value ());
142 bool sanitize (hb_sanitize_context_t *c) const
144 TRACE_SANITIZE (this);
145 if (unlikely (!u.header.sanitize (c) ||
146 u.header.length < u.header.min_size ||
147 !c->check_range (this, u.header.length))) return_trace (false);
149 return_trace (dispatch (c));
154 KernSubTableHeader header;
155 AAT::KerxSubTableFormat0<KernSubTableHeader> format0;
156 AAT::KerxSubTableFormat1<KernSubTableHeader> format1;
157 AAT::KerxSubTableFormat2<KernSubTableHeader> format2;
158 KernSubTableFormat3<KernSubTableHeader> format3;
161 DEFINE_SIZE_MIN (KernSubTableHeader::static_size);
165 struct KernOTSubTableHeader
167 static constexpr bool apple = false;
168 typedef AAT::ObsoleteTypes Types;
170 unsigned tuple_count () const { return 0; }
171 bool is_horizontal () const { return (coverage & Horizontal); }
185 bool sanitize (hb_sanitize_context_t *c) const
187 TRACE_SANITIZE (this);
188 return_trace (c->check_struct (this));
192 HBUINT16 versionZ; /* Unused. */
193 HBUINT16 length; /* Length of the subtable (including this header). */
194 HBUINT8 format; /* Subtable format. */
195 HBUINT8 coverage; /* Coverage bits. */
197 DEFINE_SIZE_STATIC (6);
200 struct KernOT : AAT::KerxTable<KernOT>
202 friend struct AAT::KerxTable<KernOT>;
204 static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
205 static constexpr unsigned minVersion = 0u;
207 typedef KernOTSubTableHeader SubTableHeader;
208 typedef SubTableHeader::Types Types;
209 typedef KernSubTable<SubTableHeader> SubTable;
212 HBUINT16 version; /* Version--0x0000u */
213 HBUINT16 tableCount; /* Number of subtables in the kerning table. */
214 SubTable firstSubTable; /* Subtables. */
220 struct KernAATSubTableHeader
222 static constexpr bool apple = true;
223 typedef AAT::ObsoleteTypes Types;
225 unsigned tuple_count () const { return 0; }
226 bool is_horizontal () const { return !(coverage & Vertical); }
238 bool sanitize (hb_sanitize_context_t *c) const
240 TRACE_SANITIZE (this);
241 return_trace (c->check_struct (this));
245 HBUINT32 length; /* Length of the subtable (including this header). */
246 HBUINT8 coverage; /* Coverage bits. */
247 HBUINT8 format; /* Subtable format. */
248 HBUINT16 tupleIndex; /* The tuple index (used for variations fonts).
249 * This value specifies which tuple this subtable covers.
250 * Note: We don't implement. */
252 DEFINE_SIZE_STATIC (8);
255 struct KernAAT : AAT::KerxTable<KernAAT>
257 friend struct AAT::KerxTable<KernAAT>;
259 static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
260 static constexpr unsigned minVersion = 0x00010000u;
262 typedef KernAATSubTableHeader SubTableHeader;
263 typedef SubTableHeader::Types Types;
264 typedef KernSubTable<SubTableHeader> SubTable;
267 HBUINT32 version; /* Version--0x00010000u */
268 HBUINT32 tableCount; /* Number of subtables in the kerning table. */
269 SubTable firstSubTable; /* Subtables. */
276 static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
278 bool has_data () const { return u.version32; }
279 unsigned get_type () const { return u.major; }
281 bool has_state_machine () const
283 switch (get_type ()) {
284 case 0: return u.ot.has_state_machine ();
285 #ifndef HB_NO_AAT_SHAPE
286 case 1: return u.aat.has_state_machine ();
288 default:return false;
292 bool has_cross_stream () const
294 switch (get_type ()) {
295 case 0: return u.ot.has_cross_stream ();
296 #ifndef HB_NO_AAT_SHAPE
297 case 1: return u.aat.has_cross_stream ();
299 default:return false;
303 int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
305 switch (get_type ()) {
306 case 0: return u.ot.get_h_kerning (left, right);
307 #ifndef HB_NO_AAT_SHAPE
308 case 1: return u.aat.get_h_kerning (left, right);
314 bool apply (AAT::hb_aat_apply_context_t *c) const
315 { return dispatch (c); }
317 template <typename context_t, typename ...Ts>
318 typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
320 unsigned int subtable_type = get_type ();
321 TRACE_DISPATCH (this, subtable_type);
322 switch (subtable_type) {
323 case 0: return_trace (c->dispatch (u.ot, hb_forward<Ts> (ds)...));
324 #ifndef HB_NO_AAT_SHAPE
325 case 1: return_trace (c->dispatch (u.aat, hb_forward<Ts> (ds)...));
327 default: return_trace (c->default_return_value ());
331 bool sanitize (hb_sanitize_context_t *c) const
333 TRACE_SANITIZE (this);
334 if (!u.version32.sanitize (c)) return_trace (false);
335 return_trace (dispatch (c));
343 #ifndef HB_NO_AAT_SHAPE
348 DEFINE_SIZE_UNION (4, version32);
354 #endif /* HB_OT_KERN_TABLE_HH */