xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-ot-kern-table.hh (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker /*
2*2d1272b8SAndroid Build Coastguard Worker  * Copyright © 2017  Google, Inc.
3*2d1272b8SAndroid Build Coastguard Worker  *
4*2d1272b8SAndroid Build Coastguard Worker  *  This is part of HarfBuzz, a text shaping library.
5*2d1272b8SAndroid Build Coastguard Worker  *
6*2d1272b8SAndroid Build Coastguard Worker  * Permission is hereby granted, without written agreement and without
7*2d1272b8SAndroid Build Coastguard Worker  * license or royalty fees, to use, copy, modify, and distribute this
8*2d1272b8SAndroid Build Coastguard Worker  * software and its documentation for any purpose, provided that the
9*2d1272b8SAndroid Build Coastguard Worker  * above copyright notice and the following two paragraphs appear in
10*2d1272b8SAndroid Build Coastguard Worker  * all copies of this software.
11*2d1272b8SAndroid Build Coastguard Worker  *
12*2d1272b8SAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13*2d1272b8SAndroid Build Coastguard Worker  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14*2d1272b8SAndroid Build Coastguard Worker  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15*2d1272b8SAndroid Build Coastguard Worker  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16*2d1272b8SAndroid Build Coastguard Worker  * DAMAGE.
17*2d1272b8SAndroid Build Coastguard Worker  *
18*2d1272b8SAndroid Build Coastguard Worker  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19*2d1272b8SAndroid Build Coastguard Worker  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20*2d1272b8SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21*2d1272b8SAndroid Build Coastguard Worker  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22*2d1272b8SAndroid Build Coastguard Worker  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23*2d1272b8SAndroid Build Coastguard Worker  *
24*2d1272b8SAndroid Build Coastguard Worker  * Google Author(s): Behdad Esfahbod
25*2d1272b8SAndroid Build Coastguard Worker  */
26*2d1272b8SAndroid Build Coastguard Worker 
27*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_OT_KERN_TABLE_HH
28*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_KERN_TABLE_HH
29*2d1272b8SAndroid Build Coastguard Worker 
30*2d1272b8SAndroid Build Coastguard Worker #include "hb-aat-layout-kerx-table.hh"
31*2d1272b8SAndroid Build Coastguard Worker 
32*2d1272b8SAndroid Build Coastguard Worker 
33*2d1272b8SAndroid Build Coastguard Worker /*
34*2d1272b8SAndroid Build Coastguard Worker  * kern -- Kerning
35*2d1272b8SAndroid Build Coastguard Worker  * https://docs.microsoft.com/en-us/typography/opentype/spec/kern
36*2d1272b8SAndroid Build Coastguard Worker  * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html
37*2d1272b8SAndroid Build Coastguard Worker  */
38*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_TAG_kern HB_TAG('k','e','r','n')
39*2d1272b8SAndroid Build Coastguard Worker 
40*2d1272b8SAndroid Build Coastguard Worker 
41*2d1272b8SAndroid Build Coastguard Worker namespace OT {
42*2d1272b8SAndroid Build Coastguard Worker 
43*2d1272b8SAndroid Build Coastguard Worker 
44*2d1272b8SAndroid Build Coastguard Worker template <typename KernSubTableHeader>
45*2d1272b8SAndroid Build Coastguard Worker struct KernSubTableFormat3
46*2d1272b8SAndroid Build Coastguard Worker {
get_kerningOT::KernSubTableFormat347*2d1272b8SAndroid Build Coastguard Worker   int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
48*2d1272b8SAndroid Build Coastguard Worker   {
49*2d1272b8SAndroid Build Coastguard Worker     hb_array_t<const FWORD> kernValue = kernValueZ.as_array (kernValueCount);
50*2d1272b8SAndroid Build Coastguard Worker     hb_array_t<const HBUINT8> leftClass = StructAfter<const UnsizedArrayOf<HBUINT8>> (kernValue).as_array (glyphCount);
51*2d1272b8SAndroid Build Coastguard Worker     hb_array_t<const HBUINT8> rightClass = StructAfter<const UnsizedArrayOf<HBUINT8>> (leftClass).as_array (glyphCount);
52*2d1272b8SAndroid Build Coastguard Worker     hb_array_t<const HBUINT8> kernIndex = StructAfter<const UnsizedArrayOf<HBUINT8>> (rightClass).as_array (leftClassCount * rightClassCount);
53*2d1272b8SAndroid Build Coastguard Worker 
54*2d1272b8SAndroid Build Coastguard Worker     unsigned int leftC = leftClass[left];
55*2d1272b8SAndroid Build Coastguard Worker     unsigned int rightC = rightClass[right];
56*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (leftC >= leftClassCount || rightC >= rightClassCount))
57*2d1272b8SAndroid Build Coastguard Worker       return 0;
58*2d1272b8SAndroid Build Coastguard Worker     unsigned int i = leftC * rightClassCount + rightC;
59*2d1272b8SAndroid Build Coastguard Worker     return kernValue[kernIndex[i]];
60*2d1272b8SAndroid Build Coastguard Worker   }
61*2d1272b8SAndroid Build Coastguard Worker 
applyOT::KernSubTableFormat362*2d1272b8SAndroid Build Coastguard Worker   bool apply (AAT::hb_aat_apply_context_t *c) const
63*2d1272b8SAndroid Build Coastguard Worker   {
64*2d1272b8SAndroid Build Coastguard Worker     TRACE_APPLY (this);
65*2d1272b8SAndroid Build Coastguard Worker 
66*2d1272b8SAndroid Build Coastguard Worker     if (!c->plan->requested_kerning)
67*2d1272b8SAndroid Build Coastguard Worker       return false;
68*2d1272b8SAndroid Build Coastguard Worker 
69*2d1272b8SAndroid Build Coastguard Worker     if (header.coverage & header.Backwards)
70*2d1272b8SAndroid Build Coastguard Worker       return false;
71*2d1272b8SAndroid Build Coastguard Worker 
72*2d1272b8SAndroid Build Coastguard Worker     hb_kern_machine_t<KernSubTableFormat3> machine (*this, header.coverage & header.CrossStream);
73*2d1272b8SAndroid Build Coastguard Worker     machine.kern (c->font, c->buffer, c->plan->kern_mask);
74*2d1272b8SAndroid Build Coastguard Worker 
75*2d1272b8SAndroid Build Coastguard Worker     return_trace (true);
76*2d1272b8SAndroid Build Coastguard Worker   }
77*2d1272b8SAndroid Build Coastguard Worker 
sanitizeOT::KernSubTableFormat378*2d1272b8SAndroid Build Coastguard Worker   bool sanitize (hb_sanitize_context_t *c) const
79*2d1272b8SAndroid Build Coastguard Worker   {
80*2d1272b8SAndroid Build Coastguard Worker     TRACE_SANITIZE (this);
81*2d1272b8SAndroid Build Coastguard Worker     return_trace (c->check_struct (this) &&
82*2d1272b8SAndroid Build Coastguard Worker 		  hb_barrier () &&
83*2d1272b8SAndroid Build Coastguard Worker 		  c->check_range (kernValueZ,
84*2d1272b8SAndroid Build Coastguard Worker 				  kernValueCount * sizeof (FWORD) +
85*2d1272b8SAndroid Build Coastguard Worker 				  glyphCount * 2 +
86*2d1272b8SAndroid Build Coastguard Worker 				  leftClassCount * rightClassCount));
87*2d1272b8SAndroid Build Coastguard Worker   }
88*2d1272b8SAndroid Build Coastguard Worker 
89*2d1272b8SAndroid Build Coastguard Worker   template <typename set_t>
collect_glyphsOT::KernSubTableFormat390*2d1272b8SAndroid Build Coastguard Worker   void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
91*2d1272b8SAndroid Build Coastguard Worker   {
92*2d1272b8SAndroid Build Coastguard Worker     set_t set;
93*2d1272b8SAndroid Build Coastguard Worker     if (likely (glyphCount))
94*2d1272b8SAndroid Build Coastguard Worker       set.add_range (0, glyphCount - 1);
95*2d1272b8SAndroid Build Coastguard Worker     left_set.union_ (set);
96*2d1272b8SAndroid Build Coastguard Worker     right_set.union_ (set);
97*2d1272b8SAndroid Build Coastguard Worker   }
98*2d1272b8SAndroid Build Coastguard Worker 
99*2d1272b8SAndroid Build Coastguard Worker   protected:
100*2d1272b8SAndroid Build Coastguard Worker   KernSubTableHeader
101*2d1272b8SAndroid Build Coastguard Worker 		header;
102*2d1272b8SAndroid Build Coastguard Worker   HBUINT16	glyphCount;	/* The number of glyphs in this font. */
103*2d1272b8SAndroid Build Coastguard Worker   HBUINT8	kernValueCount;	/* The number of kerning values. */
104*2d1272b8SAndroid Build Coastguard Worker   HBUINT8	leftClassCount;	/* The number of left-hand classes. */
105*2d1272b8SAndroid Build Coastguard Worker   HBUINT8	rightClassCount;/* The number of right-hand classes. */
106*2d1272b8SAndroid Build Coastguard Worker   HBUINT8	flags;		/* Set to zero (reserved for future use). */
107*2d1272b8SAndroid Build Coastguard Worker   UnsizedArrayOf<FWORD>
108*2d1272b8SAndroid Build Coastguard Worker 		kernValueZ;	/* The kerning values.
109*2d1272b8SAndroid Build Coastguard Worker 				 * Length kernValueCount. */
110*2d1272b8SAndroid Build Coastguard Worker #if 0
111*2d1272b8SAndroid Build Coastguard Worker   UnsizedArrayOf<HBUINT8>
112*2d1272b8SAndroid Build Coastguard Worker 		leftClass;	/* The left-hand classes.
113*2d1272b8SAndroid Build Coastguard Worker 				 * Length glyphCount. */
114*2d1272b8SAndroid Build Coastguard Worker   UnsizedArrayOf<HBUINT8>
115*2d1272b8SAndroid Build Coastguard Worker 		rightClass;	/* The right-hand classes.
116*2d1272b8SAndroid Build Coastguard Worker 				 * Length glyphCount. */
117*2d1272b8SAndroid Build Coastguard Worker   UnsizedArrayOf<HBUINT8>kernIndex;
118*2d1272b8SAndroid Build Coastguard Worker 				/* The indices into the kernValue array.
119*2d1272b8SAndroid Build Coastguard Worker 				 * Length leftClassCount * rightClassCount */
120*2d1272b8SAndroid Build Coastguard Worker #endif
121*2d1272b8SAndroid Build Coastguard Worker   public:
122*2d1272b8SAndroid Build Coastguard Worker   DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 6, kernValueZ);
123*2d1272b8SAndroid Build Coastguard Worker };
124*2d1272b8SAndroid Build Coastguard Worker 
125*2d1272b8SAndroid Build Coastguard Worker template <typename KernSubTableHeader>
126*2d1272b8SAndroid Build Coastguard Worker struct KernSubTable
127*2d1272b8SAndroid Build Coastguard Worker {
get_sizeOT::KernSubTable128*2d1272b8SAndroid Build Coastguard Worker   unsigned int get_size () const { return u.header.length; }
get_typeOT::KernSubTable129*2d1272b8SAndroid Build Coastguard Worker   unsigned int get_type () const { return u.header.format; }
130*2d1272b8SAndroid Build Coastguard Worker 
get_kerningOT::KernSubTable131*2d1272b8SAndroid Build Coastguard Worker   int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
132*2d1272b8SAndroid Build Coastguard Worker   {
133*2d1272b8SAndroid Build Coastguard Worker     switch (get_type ()) {
134*2d1272b8SAndroid Build Coastguard Worker     /* This method hooks up to hb_font_t's get_h_kerning.  Only support Format0. */
135*2d1272b8SAndroid Build Coastguard Worker     case 0: hb_barrier (); return u.format0.get_kerning (left, right);
136*2d1272b8SAndroid Build Coastguard Worker     default:return 0;
137*2d1272b8SAndroid Build Coastguard Worker     }
138*2d1272b8SAndroid Build Coastguard Worker   }
139*2d1272b8SAndroid Build Coastguard Worker 
140*2d1272b8SAndroid Build Coastguard Worker   template <typename context_t, typename ...Ts>
dispatchOT::KernSubTable141*2d1272b8SAndroid Build Coastguard Worker   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
142*2d1272b8SAndroid Build Coastguard Worker   {
143*2d1272b8SAndroid Build Coastguard Worker     unsigned int subtable_type = get_type ();
144*2d1272b8SAndroid Build Coastguard Worker     TRACE_DISPATCH (this, subtable_type);
145*2d1272b8SAndroid Build Coastguard Worker     switch (subtable_type) {
146*2d1272b8SAndroid Build Coastguard Worker     case 0:	return_trace (c->dispatch (u.format0));
147*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
148*2d1272b8SAndroid Build Coastguard Worker     case 1:	return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
149*2d1272b8SAndroid Build Coastguard Worker #endif
150*2d1272b8SAndroid Build Coastguard Worker     case 2:	return_trace (c->dispatch (u.format2));
151*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
152*2d1272b8SAndroid Build Coastguard Worker     case 3:	return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
153*2d1272b8SAndroid Build Coastguard Worker #endif
154*2d1272b8SAndroid Build Coastguard Worker     default:	return_trace (c->default_return_value ());
155*2d1272b8SAndroid Build Coastguard Worker     }
156*2d1272b8SAndroid Build Coastguard Worker   }
157*2d1272b8SAndroid Build Coastguard Worker 
158*2d1272b8SAndroid Build Coastguard Worker   template <typename set_t>
collect_glyphsOT::KernSubTable159*2d1272b8SAndroid Build Coastguard Worker   void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
160*2d1272b8SAndroid Build Coastguard Worker   {
161*2d1272b8SAndroid Build Coastguard Worker     unsigned int subtable_type = get_type ();
162*2d1272b8SAndroid Build Coastguard Worker     switch (subtable_type) {
163*2d1272b8SAndroid Build Coastguard Worker     case 0:	u.format0.collect_glyphs (left_set, right_set, num_glyphs); return;
164*2d1272b8SAndroid Build Coastguard Worker     case 1:	u.format1.collect_glyphs (left_set, right_set, num_glyphs); return;
165*2d1272b8SAndroid Build Coastguard Worker     case 2:	u.format2.collect_glyphs (left_set, right_set, num_glyphs); return;
166*2d1272b8SAndroid Build Coastguard Worker     case 3:	u.format3.collect_glyphs (left_set, right_set, num_glyphs); return;
167*2d1272b8SAndroid Build Coastguard Worker     default:	return;
168*2d1272b8SAndroid Build Coastguard Worker     }
169*2d1272b8SAndroid Build Coastguard Worker   }
170*2d1272b8SAndroid Build Coastguard Worker 
sanitizeOT::KernSubTable171*2d1272b8SAndroid Build Coastguard Worker   bool sanitize (hb_sanitize_context_t *c) const
172*2d1272b8SAndroid Build Coastguard Worker   {
173*2d1272b8SAndroid Build Coastguard Worker     TRACE_SANITIZE (this);
174*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (!(u.header.sanitize (c) &&
175*2d1272b8SAndroid Build Coastguard Worker 		    hb_barrier () &&
176*2d1272b8SAndroid Build Coastguard Worker 		    u.header.length >= u.header.min_size &&
177*2d1272b8SAndroid Build Coastguard Worker 		    c->check_range (this, u.header.length)))) return_trace (false);
178*2d1272b8SAndroid Build Coastguard Worker 
179*2d1272b8SAndroid Build Coastguard Worker     return_trace (dispatch (c));
180*2d1272b8SAndroid Build Coastguard Worker   }
181*2d1272b8SAndroid Build Coastguard Worker 
182*2d1272b8SAndroid Build Coastguard Worker   public:
183*2d1272b8SAndroid Build Coastguard Worker   union {
184*2d1272b8SAndroid Build Coastguard Worker   KernSubTableHeader				header;
185*2d1272b8SAndroid Build Coastguard Worker   AAT::KerxSubTableFormat0<KernSubTableHeader>	format0;
186*2d1272b8SAndroid Build Coastguard Worker   AAT::KerxSubTableFormat1<KernSubTableHeader>	format1;
187*2d1272b8SAndroid Build Coastguard Worker   AAT::KerxSubTableFormat2<KernSubTableHeader>	format2;
188*2d1272b8SAndroid Build Coastguard Worker   KernSubTableFormat3<KernSubTableHeader>	format3;
189*2d1272b8SAndroid Build Coastguard Worker   } u;
190*2d1272b8SAndroid Build Coastguard Worker   public:
191*2d1272b8SAndroid Build Coastguard Worker   DEFINE_SIZE_MIN (KernSubTableHeader::static_size);
192*2d1272b8SAndroid Build Coastguard Worker };
193*2d1272b8SAndroid Build Coastguard Worker 
194*2d1272b8SAndroid Build Coastguard Worker 
195*2d1272b8SAndroid Build Coastguard Worker struct KernOTSubTableHeader
196*2d1272b8SAndroid Build Coastguard Worker {
197*2d1272b8SAndroid Build Coastguard Worker   static constexpr bool apple = false;
198*2d1272b8SAndroid Build Coastguard Worker   typedef AAT::ObsoleteTypes Types;
199*2d1272b8SAndroid Build Coastguard Worker 
tuple_countOT::KernOTSubTableHeader200*2d1272b8SAndroid Build Coastguard Worker   unsigned   tuple_count () const { return 0; }
is_horizontalOT::KernOTSubTableHeader201*2d1272b8SAndroid Build Coastguard Worker   bool     is_horizontal () const { return (coverage & Horizontal); }
202*2d1272b8SAndroid Build Coastguard Worker 
203*2d1272b8SAndroid Build Coastguard Worker   enum Coverage
204*2d1272b8SAndroid Build Coastguard Worker   {
205*2d1272b8SAndroid Build Coastguard Worker     Horizontal	= 0x01u,
206*2d1272b8SAndroid Build Coastguard Worker     Minimum	= 0x02u,
207*2d1272b8SAndroid Build Coastguard Worker     CrossStream	= 0x04u,
208*2d1272b8SAndroid Build Coastguard Worker     Override	= 0x08u,
209*2d1272b8SAndroid Build Coastguard Worker 
210*2d1272b8SAndroid Build Coastguard Worker     /* Not supported: */
211*2d1272b8SAndroid Build Coastguard Worker     Backwards	= 0x00u,
212*2d1272b8SAndroid Build Coastguard Worker     Variation	= 0x00u,
213*2d1272b8SAndroid Build Coastguard Worker   };
214*2d1272b8SAndroid Build Coastguard Worker 
sanitizeOT::KernOTSubTableHeader215*2d1272b8SAndroid Build Coastguard Worker   bool sanitize (hb_sanitize_context_t *c) const
216*2d1272b8SAndroid Build Coastguard Worker   {
217*2d1272b8SAndroid Build Coastguard Worker     TRACE_SANITIZE (this);
218*2d1272b8SAndroid Build Coastguard Worker     return_trace (c->check_struct (this));
219*2d1272b8SAndroid Build Coastguard Worker   }
220*2d1272b8SAndroid Build Coastguard Worker 
221*2d1272b8SAndroid Build Coastguard Worker   public:
222*2d1272b8SAndroid Build Coastguard Worker   HBUINT16	versionZ;	/* Unused. */
223*2d1272b8SAndroid Build Coastguard Worker   HBUINT16	length;		/* Length of the subtable (including this header). */
224*2d1272b8SAndroid Build Coastguard Worker   HBUINT8	format;		/* Subtable format. */
225*2d1272b8SAndroid Build Coastguard Worker   HBUINT8	coverage;	/* Coverage bits. */
226*2d1272b8SAndroid Build Coastguard Worker   public:
227*2d1272b8SAndroid Build Coastguard Worker   DEFINE_SIZE_STATIC (6);
228*2d1272b8SAndroid Build Coastguard Worker };
229*2d1272b8SAndroid Build Coastguard Worker 
230*2d1272b8SAndroid Build Coastguard Worker struct KernOT : AAT::KerxTable<KernOT>
231*2d1272b8SAndroid Build Coastguard Worker {
232*2d1272b8SAndroid Build Coastguard Worker   friend struct AAT::KerxTable<KernOT>;
233*2d1272b8SAndroid Build Coastguard Worker 
234*2d1272b8SAndroid Build Coastguard Worker   static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
235*2d1272b8SAndroid Build Coastguard Worker   static constexpr unsigned minVersion = 0u;
236*2d1272b8SAndroid Build Coastguard Worker 
237*2d1272b8SAndroid Build Coastguard Worker   typedef KernOTSubTableHeader SubTableHeader;
238*2d1272b8SAndroid Build Coastguard Worker   typedef SubTableHeader::Types Types;
239*2d1272b8SAndroid Build Coastguard Worker   typedef KernSubTable<SubTableHeader> SubTable;
240*2d1272b8SAndroid Build Coastguard Worker 
241*2d1272b8SAndroid Build Coastguard Worker   protected:
242*2d1272b8SAndroid Build Coastguard Worker   HBUINT16	version;	/* Version--0x0000u */
243*2d1272b8SAndroid Build Coastguard Worker   HBUINT16	tableCount;	/* Number of subtables in the kerning table. */
244*2d1272b8SAndroid Build Coastguard Worker   SubTable	firstSubTable;	/* Subtables. */
245*2d1272b8SAndroid Build Coastguard Worker   public:
246*2d1272b8SAndroid Build Coastguard Worker   DEFINE_SIZE_MIN (4);
247*2d1272b8SAndroid Build Coastguard Worker };
248*2d1272b8SAndroid Build Coastguard Worker 
249*2d1272b8SAndroid Build Coastguard Worker 
250*2d1272b8SAndroid Build Coastguard Worker struct KernAATSubTableHeader
251*2d1272b8SAndroid Build Coastguard Worker {
252*2d1272b8SAndroid Build Coastguard Worker   static constexpr bool apple = true;
253*2d1272b8SAndroid Build Coastguard Worker   typedef AAT::ObsoleteTypes Types;
254*2d1272b8SAndroid Build Coastguard Worker 
tuple_countOT::KernAATSubTableHeader255*2d1272b8SAndroid Build Coastguard Worker   unsigned   tuple_count () const { return 0; }
is_horizontalOT::KernAATSubTableHeader256*2d1272b8SAndroid Build Coastguard Worker   bool     is_horizontal () const { return !(coverage & Vertical); }
257*2d1272b8SAndroid Build Coastguard Worker 
258*2d1272b8SAndroid Build Coastguard Worker   enum Coverage
259*2d1272b8SAndroid Build Coastguard Worker   {
260*2d1272b8SAndroid Build Coastguard Worker     Vertical	= 0x80u,
261*2d1272b8SAndroid Build Coastguard Worker     CrossStream	= 0x40u,
262*2d1272b8SAndroid Build Coastguard Worker     Variation	= 0x20u,
263*2d1272b8SAndroid Build Coastguard Worker 
264*2d1272b8SAndroid Build Coastguard Worker     /* Not supported: */
265*2d1272b8SAndroid Build Coastguard Worker     Backwards	= 0x00u,
266*2d1272b8SAndroid Build Coastguard Worker   };
267*2d1272b8SAndroid Build Coastguard Worker 
sanitizeOT::KernAATSubTableHeader268*2d1272b8SAndroid Build Coastguard Worker   bool sanitize (hb_sanitize_context_t *c) const
269*2d1272b8SAndroid Build Coastguard Worker   {
270*2d1272b8SAndroid Build Coastguard Worker     TRACE_SANITIZE (this);
271*2d1272b8SAndroid Build Coastguard Worker     return_trace (c->check_struct (this));
272*2d1272b8SAndroid Build Coastguard Worker   }
273*2d1272b8SAndroid Build Coastguard Worker 
274*2d1272b8SAndroid Build Coastguard Worker   public:
275*2d1272b8SAndroid Build Coastguard Worker   HBUINT32	length;		/* Length of the subtable (including this header). */
276*2d1272b8SAndroid Build Coastguard Worker   HBUINT8	coverage;	/* Coverage bits. */
277*2d1272b8SAndroid Build Coastguard Worker   HBUINT8	format;		/* Subtable format. */
278*2d1272b8SAndroid Build Coastguard Worker   HBUINT16	tupleIndex;	/* The tuple index (used for variations fonts).
279*2d1272b8SAndroid Build Coastguard Worker 				 * This value specifies which tuple this subtable covers.
280*2d1272b8SAndroid Build Coastguard Worker 				 * Note: We don't implement. */
281*2d1272b8SAndroid Build Coastguard Worker   public:
282*2d1272b8SAndroid Build Coastguard Worker   DEFINE_SIZE_STATIC (8);
283*2d1272b8SAndroid Build Coastguard Worker };
284*2d1272b8SAndroid Build Coastguard Worker 
285*2d1272b8SAndroid Build Coastguard Worker struct KernAAT : AAT::KerxTable<KernAAT>
286*2d1272b8SAndroid Build Coastguard Worker {
287*2d1272b8SAndroid Build Coastguard Worker   friend struct AAT::KerxTable<KernAAT>;
288*2d1272b8SAndroid Build Coastguard Worker 
289*2d1272b8SAndroid Build Coastguard Worker   static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
290*2d1272b8SAndroid Build Coastguard Worker   static constexpr unsigned minVersion = 0x00010000u;
291*2d1272b8SAndroid Build Coastguard Worker 
292*2d1272b8SAndroid Build Coastguard Worker   typedef KernAATSubTableHeader SubTableHeader;
293*2d1272b8SAndroid Build Coastguard Worker   typedef SubTableHeader::Types Types;
294*2d1272b8SAndroid Build Coastguard Worker   typedef KernSubTable<SubTableHeader> SubTable;
295*2d1272b8SAndroid Build Coastguard Worker 
296*2d1272b8SAndroid Build Coastguard Worker   protected:
297*2d1272b8SAndroid Build Coastguard Worker   HBUINT32	version;	/* Version--0x00010000u */
298*2d1272b8SAndroid Build Coastguard Worker   HBUINT32	tableCount;	/* Number of subtables in the kerning table. */
299*2d1272b8SAndroid Build Coastguard Worker   SubTable	firstSubTable;	/* Subtables. */
300*2d1272b8SAndroid Build Coastguard Worker   public:
301*2d1272b8SAndroid Build Coastguard Worker   DEFINE_SIZE_MIN (8);
302*2d1272b8SAndroid Build Coastguard Worker };
303*2d1272b8SAndroid Build Coastguard Worker 
304*2d1272b8SAndroid Build Coastguard Worker struct kern
305*2d1272b8SAndroid Build Coastguard Worker {
306*2d1272b8SAndroid Build Coastguard Worker   static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
307*2d1272b8SAndroid Build Coastguard Worker 
has_dataOT::kern308*2d1272b8SAndroid Build Coastguard Worker   bool     has_data () const { return u.version32; }
get_typeOT::kern309*2d1272b8SAndroid Build Coastguard Worker   unsigned get_type () const { return u.major; }
310*2d1272b8SAndroid Build Coastguard Worker 
has_state_machineOT::kern311*2d1272b8SAndroid Build Coastguard Worker   bool has_state_machine () const
312*2d1272b8SAndroid Build Coastguard Worker   {
313*2d1272b8SAndroid Build Coastguard Worker     switch (get_type ()) {
314*2d1272b8SAndroid Build Coastguard Worker     case 0: hb_barrier (); return u.ot.has_state_machine ();
315*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
316*2d1272b8SAndroid Build Coastguard Worker     case 1: hb_barrier (); return u.aat.has_state_machine ();
317*2d1272b8SAndroid Build Coastguard Worker #endif
318*2d1272b8SAndroid Build Coastguard Worker     default:return false;
319*2d1272b8SAndroid Build Coastguard Worker     }
320*2d1272b8SAndroid Build Coastguard Worker   }
321*2d1272b8SAndroid Build Coastguard Worker 
has_cross_streamOT::kern322*2d1272b8SAndroid Build Coastguard Worker   bool has_cross_stream () const
323*2d1272b8SAndroid Build Coastguard Worker   {
324*2d1272b8SAndroid Build Coastguard Worker     switch (get_type ()) {
325*2d1272b8SAndroid Build Coastguard Worker     case 0: hb_barrier (); return u.ot.has_cross_stream ();
326*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
327*2d1272b8SAndroid Build Coastguard Worker     case 1: hb_barrier (); return u.aat.has_cross_stream ();
328*2d1272b8SAndroid Build Coastguard Worker #endif
329*2d1272b8SAndroid Build Coastguard Worker     default:return false;
330*2d1272b8SAndroid Build Coastguard Worker     }
331*2d1272b8SAndroid Build Coastguard Worker   }
332*2d1272b8SAndroid Build Coastguard Worker 
get_h_kerningOT::kern333*2d1272b8SAndroid Build Coastguard Worker   int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
334*2d1272b8SAndroid Build Coastguard Worker   {
335*2d1272b8SAndroid Build Coastguard Worker     switch (get_type ()) {
336*2d1272b8SAndroid Build Coastguard Worker     case 0: hb_barrier (); return u.ot.get_h_kerning (left, right);
337*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
338*2d1272b8SAndroid Build Coastguard Worker     case 1: hb_barrier (); return u.aat.get_h_kerning (left, right);
339*2d1272b8SAndroid Build Coastguard Worker #endif
340*2d1272b8SAndroid Build Coastguard Worker     default:return 0;
341*2d1272b8SAndroid Build Coastguard Worker     }
342*2d1272b8SAndroid Build Coastguard Worker   }
343*2d1272b8SAndroid Build Coastguard Worker 
applyOT::kern344*2d1272b8SAndroid Build Coastguard Worker   bool apply (AAT::hb_aat_apply_context_t *c,
345*2d1272b8SAndroid Build Coastguard Worker 	      const AAT::kern_accelerator_data_t *accel_data = nullptr) const
346*2d1272b8SAndroid Build Coastguard Worker   { return dispatch (c, accel_data); }
347*2d1272b8SAndroid Build Coastguard Worker 
348*2d1272b8SAndroid Build Coastguard Worker   template <typename context_t, typename ...Ts>
dispatchOT::kern349*2d1272b8SAndroid Build Coastguard Worker   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
350*2d1272b8SAndroid Build Coastguard Worker   {
351*2d1272b8SAndroid Build Coastguard Worker     unsigned int subtable_type = get_type ();
352*2d1272b8SAndroid Build Coastguard Worker     TRACE_DISPATCH (this, subtable_type);
353*2d1272b8SAndroid Build Coastguard Worker     switch (subtable_type) {
354*2d1272b8SAndroid Build Coastguard Worker     case 0:	return_trace (c->dispatch (u.ot, std::forward<Ts> (ds)...));
355*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
356*2d1272b8SAndroid Build Coastguard Worker     case 1:	return_trace (c->dispatch (u.aat, std::forward<Ts> (ds)...));
357*2d1272b8SAndroid Build Coastguard Worker #endif
358*2d1272b8SAndroid Build Coastguard Worker     default:	return_trace (c->default_return_value ());
359*2d1272b8SAndroid Build Coastguard Worker     }
360*2d1272b8SAndroid Build Coastguard Worker   }
361*2d1272b8SAndroid Build Coastguard Worker 
sanitizeOT::kern362*2d1272b8SAndroid Build Coastguard Worker   bool sanitize (hb_sanitize_context_t *c) const
363*2d1272b8SAndroid Build Coastguard Worker   {
364*2d1272b8SAndroid Build Coastguard Worker     TRACE_SANITIZE (this);
365*2d1272b8SAndroid Build Coastguard Worker     if (!u.version32.sanitize (c)) return_trace (false);
366*2d1272b8SAndroid Build Coastguard Worker     hb_barrier ();
367*2d1272b8SAndroid Build Coastguard Worker     return_trace (dispatch (c));
368*2d1272b8SAndroid Build Coastguard Worker   }
369*2d1272b8SAndroid Build Coastguard Worker 
create_accelerator_dataOT::kern370*2d1272b8SAndroid Build Coastguard Worker   AAT::kern_accelerator_data_t create_accelerator_data (unsigned num_glyphs) const
371*2d1272b8SAndroid Build Coastguard Worker   {
372*2d1272b8SAndroid Build Coastguard Worker     switch (get_type ()) {
373*2d1272b8SAndroid Build Coastguard Worker     case 0: hb_barrier (); return u.ot.create_accelerator_data (num_glyphs);
374*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
375*2d1272b8SAndroid Build Coastguard Worker     case 1: hb_barrier (); return u.aat.create_accelerator_data (num_glyphs);
376*2d1272b8SAndroid Build Coastguard Worker #endif
377*2d1272b8SAndroid Build Coastguard Worker     default:return AAT::kern_accelerator_data_t ();
378*2d1272b8SAndroid Build Coastguard Worker     }
379*2d1272b8SAndroid Build Coastguard Worker   }
380*2d1272b8SAndroid Build Coastguard Worker 
381*2d1272b8SAndroid Build Coastguard Worker   struct accelerator_t
382*2d1272b8SAndroid Build Coastguard Worker   {
accelerator_tOT::kern::accelerator_t383*2d1272b8SAndroid Build Coastguard Worker     accelerator_t (hb_face_t *face)
384*2d1272b8SAndroid Build Coastguard Worker     {
385*2d1272b8SAndroid Build Coastguard Worker       hb_sanitize_context_t sc;
386*2d1272b8SAndroid Build Coastguard Worker       this->table = sc.reference_table<kern> (face);
387*2d1272b8SAndroid Build Coastguard Worker       this->accel_data = this->table->create_accelerator_data (face->get_num_glyphs ());
388*2d1272b8SAndroid Build Coastguard Worker     }
~accelerator_tOT::kern::accelerator_t389*2d1272b8SAndroid Build Coastguard Worker     ~accelerator_t ()
390*2d1272b8SAndroid Build Coastguard Worker     {
391*2d1272b8SAndroid Build Coastguard Worker       this->table.destroy ();
392*2d1272b8SAndroid Build Coastguard Worker     }
393*2d1272b8SAndroid Build Coastguard Worker 
get_blobOT::kern::accelerator_t394*2d1272b8SAndroid Build Coastguard Worker     hb_blob_t *get_blob () const { return table.get_blob (); }
395*2d1272b8SAndroid Build Coastguard Worker 
applyOT::kern::accelerator_t396*2d1272b8SAndroid Build Coastguard Worker     bool apply (AAT::hb_aat_apply_context_t *c) const
397*2d1272b8SAndroid Build Coastguard Worker     {
398*2d1272b8SAndroid Build Coastguard Worker       return table->apply (c, &accel_data);
399*2d1272b8SAndroid Build Coastguard Worker     }
400*2d1272b8SAndroid Build Coastguard Worker 
401*2d1272b8SAndroid Build Coastguard Worker     hb_blob_ptr_t<kern> table;
402*2d1272b8SAndroid Build Coastguard Worker     AAT::kern_accelerator_data_t accel_data;
403*2d1272b8SAndroid Build Coastguard Worker   };
404*2d1272b8SAndroid Build Coastguard Worker 
405*2d1272b8SAndroid Build Coastguard Worker   protected:
406*2d1272b8SAndroid Build Coastguard Worker   union {
407*2d1272b8SAndroid Build Coastguard Worker   HBUINT32		version32;
408*2d1272b8SAndroid Build Coastguard Worker   HBUINT16		major;
409*2d1272b8SAndroid Build Coastguard Worker   KernOT		ot;
410*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_AAT_SHAPE
411*2d1272b8SAndroid Build Coastguard Worker   KernAAT		aat;
412*2d1272b8SAndroid Build Coastguard Worker #endif
413*2d1272b8SAndroid Build Coastguard Worker   } u;
414*2d1272b8SAndroid Build Coastguard Worker   public:
415*2d1272b8SAndroid Build Coastguard Worker   DEFINE_SIZE_UNION (4, version32);
416*2d1272b8SAndroid Build Coastguard Worker };
417*2d1272b8SAndroid Build Coastguard Worker 
418*2d1272b8SAndroid Build Coastguard Worker struct kern_accelerator_t : kern::accelerator_t {
kern_accelerator_tOT::kern_accelerator_t419*2d1272b8SAndroid Build Coastguard Worker   kern_accelerator_t (hb_face_t *face) : kern::accelerator_t (face) {}
420*2d1272b8SAndroid Build Coastguard Worker };
421*2d1272b8SAndroid Build Coastguard Worker 
422*2d1272b8SAndroid Build Coastguard Worker } /* namespace OT */
423*2d1272b8SAndroid Build Coastguard Worker 
424*2d1272b8SAndroid Build Coastguard Worker 
425*2d1272b8SAndroid Build Coastguard Worker #endif /* HB_OT_KERN_TABLE_HH */
426