xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-ot-kern-table.hh (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
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 {
get_kerningOT::KernSubTableFormat347   int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
48   {
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);
53 
54     unsigned int leftC = leftClass[left];
55     unsigned int rightC = rightClass[right];
56     if (unlikely (leftC >= leftClassCount || rightC >= rightClassCount))
57       return 0;
58     unsigned int i = leftC * rightClassCount + rightC;
59     return kernValue[kernIndex[i]];
60   }
61 
applyOT::KernSubTableFormat362   bool apply (AAT::hb_aat_apply_context_t *c) const
63   {
64     TRACE_APPLY (this);
65 
66     if (!c->plan->requested_kerning)
67       return false;
68 
69     if (header.coverage & header.Backwards)
70       return false;
71 
72     hb_kern_machine_t<KernSubTableFormat3> machine (*this, header.coverage & header.CrossStream);
73     machine.kern (c->font, c->buffer, c->plan->kern_mask);
74 
75     return_trace (true);
76   }
77 
sanitizeOT::KernSubTableFormat378   bool sanitize (hb_sanitize_context_t *c) const
79   {
80     TRACE_SANITIZE (this);
81     return_trace (c->check_struct (this) &&
82 		  hb_barrier () &&
83 		  c->check_range (kernValueZ,
84 				  kernValueCount * sizeof (FWORD) +
85 				  glyphCount * 2 +
86 				  leftClassCount * rightClassCount));
87   }
88 
89   template <typename set_t>
collect_glyphsOT::KernSubTableFormat390   void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
91   {
92     set_t set;
93     if (likely (glyphCount))
94       set.add_range (0, glyphCount - 1);
95     left_set.union_ (set);
96     right_set.union_ (set);
97   }
98 
99   protected:
100   KernSubTableHeader
101 		header;
102   HBUINT16	glyphCount;	/* The number of glyphs in this font. */
103   HBUINT8	kernValueCount;	/* The number of kerning values. */
104   HBUINT8	leftClassCount;	/* The number of left-hand classes. */
105   HBUINT8	rightClassCount;/* The number of right-hand classes. */
106   HBUINT8	flags;		/* Set to zero (reserved for future use). */
107   UnsizedArrayOf<FWORD>
108 		kernValueZ;	/* The kerning values.
109 				 * Length kernValueCount. */
110 #if 0
111   UnsizedArrayOf<HBUINT8>
112 		leftClass;	/* The left-hand classes.
113 				 * Length glyphCount. */
114   UnsizedArrayOf<HBUINT8>
115 		rightClass;	/* The right-hand classes.
116 				 * Length glyphCount. */
117   UnsizedArrayOf<HBUINT8>kernIndex;
118 				/* The indices into the kernValue array.
119 				 * Length leftClassCount * rightClassCount */
120 #endif
121   public:
122   DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 6, kernValueZ);
123 };
124 
125 template <typename KernSubTableHeader>
126 struct KernSubTable
127 {
get_sizeOT::KernSubTable128   unsigned int get_size () const { return u.header.length; }
get_typeOT::KernSubTable129   unsigned int get_type () const { return u.header.format; }
130 
get_kerningOT::KernSubTable131   int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
132   {
133     switch (get_type ()) {
134     /* This method hooks up to hb_font_t's get_h_kerning.  Only support Format0. */
135     case 0: hb_barrier (); return u.format0.get_kerning (left, right);
136     default:return 0;
137     }
138   }
139 
140   template <typename context_t, typename ...Ts>
dispatchOT::KernSubTable141   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
142   {
143     unsigned int subtable_type = get_type ();
144     TRACE_DISPATCH (this, subtable_type);
145     switch (subtable_type) {
146     case 0:	return_trace (c->dispatch (u.format0));
147 #ifndef HB_NO_AAT_SHAPE
148     case 1:	return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
149 #endif
150     case 2:	return_trace (c->dispatch (u.format2));
151 #ifndef HB_NO_AAT_SHAPE
152     case 3:	return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
153 #endif
154     default:	return_trace (c->default_return_value ());
155     }
156   }
157 
158   template <typename set_t>
collect_glyphsOT::KernSubTable159   void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
160   {
161     unsigned int subtable_type = get_type ();
162     switch (subtable_type) {
163     case 0:	u.format0.collect_glyphs (left_set, right_set, num_glyphs); return;
164     case 1:	u.format1.collect_glyphs (left_set, right_set, num_glyphs); return;
165     case 2:	u.format2.collect_glyphs (left_set, right_set, num_glyphs); return;
166     case 3:	u.format3.collect_glyphs (left_set, right_set, num_glyphs); return;
167     default:	return;
168     }
169   }
170 
sanitizeOT::KernSubTable171   bool sanitize (hb_sanitize_context_t *c) const
172   {
173     TRACE_SANITIZE (this);
174     if (unlikely (!(u.header.sanitize (c) &&
175 		    hb_barrier () &&
176 		    u.header.length >= u.header.min_size &&
177 		    c->check_range (this, u.header.length)))) return_trace (false);
178 
179     return_trace (dispatch (c));
180   }
181 
182   public:
183   union {
184   KernSubTableHeader				header;
185   AAT::KerxSubTableFormat0<KernSubTableHeader>	format0;
186   AAT::KerxSubTableFormat1<KernSubTableHeader>	format1;
187   AAT::KerxSubTableFormat2<KernSubTableHeader>	format2;
188   KernSubTableFormat3<KernSubTableHeader>	format3;
189   } u;
190   public:
191   DEFINE_SIZE_MIN (KernSubTableHeader::static_size);
192 };
193 
194 
195 struct KernOTSubTableHeader
196 {
197   static constexpr bool apple = false;
198   typedef AAT::ObsoleteTypes Types;
199 
tuple_countOT::KernOTSubTableHeader200   unsigned   tuple_count () const { return 0; }
is_horizontalOT::KernOTSubTableHeader201   bool     is_horizontal () const { return (coverage & Horizontal); }
202 
203   enum Coverage
204   {
205     Horizontal	= 0x01u,
206     Minimum	= 0x02u,
207     CrossStream	= 0x04u,
208     Override	= 0x08u,
209 
210     /* Not supported: */
211     Backwards	= 0x00u,
212     Variation	= 0x00u,
213   };
214 
sanitizeOT::KernOTSubTableHeader215   bool sanitize (hb_sanitize_context_t *c) const
216   {
217     TRACE_SANITIZE (this);
218     return_trace (c->check_struct (this));
219   }
220 
221   public:
222   HBUINT16	versionZ;	/* Unused. */
223   HBUINT16	length;		/* Length of the subtable (including this header). */
224   HBUINT8	format;		/* Subtable format. */
225   HBUINT8	coverage;	/* Coverage bits. */
226   public:
227   DEFINE_SIZE_STATIC (6);
228 };
229 
230 struct KernOT : AAT::KerxTable<KernOT>
231 {
232   friend struct AAT::KerxTable<KernOT>;
233 
234   static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
235   static constexpr unsigned minVersion = 0u;
236 
237   typedef KernOTSubTableHeader SubTableHeader;
238   typedef SubTableHeader::Types Types;
239   typedef KernSubTable<SubTableHeader> SubTable;
240 
241   protected:
242   HBUINT16	version;	/* Version--0x0000u */
243   HBUINT16	tableCount;	/* Number of subtables in the kerning table. */
244   SubTable	firstSubTable;	/* Subtables. */
245   public:
246   DEFINE_SIZE_MIN (4);
247 };
248 
249 
250 struct KernAATSubTableHeader
251 {
252   static constexpr bool apple = true;
253   typedef AAT::ObsoleteTypes Types;
254 
tuple_countOT::KernAATSubTableHeader255   unsigned   tuple_count () const { return 0; }
is_horizontalOT::KernAATSubTableHeader256   bool     is_horizontal () const { return !(coverage & Vertical); }
257 
258   enum Coverage
259   {
260     Vertical	= 0x80u,
261     CrossStream	= 0x40u,
262     Variation	= 0x20u,
263 
264     /* Not supported: */
265     Backwards	= 0x00u,
266   };
267 
sanitizeOT::KernAATSubTableHeader268   bool sanitize (hb_sanitize_context_t *c) const
269   {
270     TRACE_SANITIZE (this);
271     return_trace (c->check_struct (this));
272   }
273 
274   public:
275   HBUINT32	length;		/* Length of the subtable (including this header). */
276   HBUINT8	coverage;	/* Coverage bits. */
277   HBUINT8	format;		/* Subtable format. */
278   HBUINT16	tupleIndex;	/* The tuple index (used for variations fonts).
279 				 * This value specifies which tuple this subtable covers.
280 				 * Note: We don't implement. */
281   public:
282   DEFINE_SIZE_STATIC (8);
283 };
284 
285 struct KernAAT : AAT::KerxTable<KernAAT>
286 {
287   friend struct AAT::KerxTable<KernAAT>;
288 
289   static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
290   static constexpr unsigned minVersion = 0x00010000u;
291 
292   typedef KernAATSubTableHeader SubTableHeader;
293   typedef SubTableHeader::Types Types;
294   typedef KernSubTable<SubTableHeader> SubTable;
295 
296   protected:
297   HBUINT32	version;	/* Version--0x00010000u */
298   HBUINT32	tableCount;	/* Number of subtables in the kerning table. */
299   SubTable	firstSubTable;	/* Subtables. */
300   public:
301   DEFINE_SIZE_MIN (8);
302 };
303 
304 struct kern
305 {
306   static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
307 
has_dataOT::kern308   bool     has_data () const { return u.version32; }
get_typeOT::kern309   unsigned get_type () const { return u.major; }
310 
has_state_machineOT::kern311   bool has_state_machine () const
312   {
313     switch (get_type ()) {
314     case 0: hb_barrier (); return u.ot.has_state_machine ();
315 #ifndef HB_NO_AAT_SHAPE
316     case 1: hb_barrier (); return u.aat.has_state_machine ();
317 #endif
318     default:return false;
319     }
320   }
321 
has_cross_streamOT::kern322   bool has_cross_stream () const
323   {
324     switch (get_type ()) {
325     case 0: hb_barrier (); return u.ot.has_cross_stream ();
326 #ifndef HB_NO_AAT_SHAPE
327     case 1: hb_barrier (); return u.aat.has_cross_stream ();
328 #endif
329     default:return false;
330     }
331   }
332 
get_h_kerningOT::kern333   int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
334   {
335     switch (get_type ()) {
336     case 0: hb_barrier (); return u.ot.get_h_kerning (left, right);
337 #ifndef HB_NO_AAT_SHAPE
338     case 1: hb_barrier (); return u.aat.get_h_kerning (left, right);
339 #endif
340     default:return 0;
341     }
342   }
343 
applyOT::kern344   bool apply (AAT::hb_aat_apply_context_t *c,
345 	      const AAT::kern_accelerator_data_t *accel_data = nullptr) const
346   { return dispatch (c, accel_data); }
347 
348   template <typename context_t, typename ...Ts>
dispatchOT::kern349   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
350   {
351     unsigned int subtable_type = get_type ();
352     TRACE_DISPATCH (this, subtable_type);
353     switch (subtable_type) {
354     case 0:	return_trace (c->dispatch (u.ot, std::forward<Ts> (ds)...));
355 #ifndef HB_NO_AAT_SHAPE
356     case 1:	return_trace (c->dispatch (u.aat, std::forward<Ts> (ds)...));
357 #endif
358     default:	return_trace (c->default_return_value ());
359     }
360   }
361 
sanitizeOT::kern362   bool sanitize (hb_sanitize_context_t *c) const
363   {
364     TRACE_SANITIZE (this);
365     if (!u.version32.sanitize (c)) return_trace (false);
366     hb_barrier ();
367     return_trace (dispatch (c));
368   }
369 
create_accelerator_dataOT::kern370   AAT::kern_accelerator_data_t create_accelerator_data (unsigned num_glyphs) const
371   {
372     switch (get_type ()) {
373     case 0: hb_barrier (); return u.ot.create_accelerator_data (num_glyphs);
374 #ifndef HB_NO_AAT_SHAPE
375     case 1: hb_barrier (); return u.aat.create_accelerator_data (num_glyphs);
376 #endif
377     default:return AAT::kern_accelerator_data_t ();
378     }
379   }
380 
381   struct accelerator_t
382   {
accelerator_tOT::kern::accelerator_t383     accelerator_t (hb_face_t *face)
384     {
385       hb_sanitize_context_t sc;
386       this->table = sc.reference_table<kern> (face);
387       this->accel_data = this->table->create_accelerator_data (face->get_num_glyphs ());
388     }
~accelerator_tOT::kern::accelerator_t389     ~accelerator_t ()
390     {
391       this->table.destroy ();
392     }
393 
get_blobOT::kern::accelerator_t394     hb_blob_t *get_blob () const { return table.get_blob (); }
395 
applyOT::kern::accelerator_t396     bool apply (AAT::hb_aat_apply_context_t *c) const
397     {
398       return table->apply (c, &accel_data);
399     }
400 
401     hb_blob_ptr_t<kern> table;
402     AAT::kern_accelerator_data_t accel_data;
403   };
404 
405   protected:
406   union {
407   HBUINT32		version32;
408   HBUINT16		major;
409   KernOT		ot;
410 #ifndef HB_NO_AAT_SHAPE
411   KernAAT		aat;
412 #endif
413   } u;
414   public:
415   DEFINE_SIZE_UNION (4, version32);
416 };
417 
418 struct kern_accelerator_t : kern::accelerator_t {
kern_accelerator_tOT::kern_accelerator_t419   kern_accelerator_t (hb_face_t *face) : kern::accelerator_t (face) {}
420 };
421 
422 } /* namespace OT */
423 
424 
425 #endif /* HB_OT_KERN_TABLE_HH */
426