Imported Upstream version 2.6.4
[platform/upstream/harfbuzz.git] / src / hb-ot-kern-table.hh
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   {
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
62   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
78   bool sanitize (hb_sanitize_context_t *c) const
79   {
80     TRACE_SANITIZE (this);
81     return_trace (c->check_struct (this) &&
82                   c->check_range (kernValueZ,
83                                   kernValueCount * sizeof (FWORD) +
84                                   glyphCount * 2 +
85                                   leftClassCount * rightClassCount));
86   }
87
88   protected:
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. */
97 #if 0
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 */
104 #endif
105   public:
106   DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 6, kernValueZ);
107 };
108
109 template <typename KernSubTableHeader>
110 struct KernSubTable
111 {
112   unsigned int get_size () const { return u.header.length; }
113   unsigned int get_type () const { return u.header.format; }
114
115   int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
116   {
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);
120     default:return 0;
121     }
122   }
123
124   template <typename context_t, typename ...Ts>
125   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
126   {
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 ());
133 #endif
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 ());
137 #endif
138     default:    return_trace (c->default_return_value ());
139     }
140   }
141
142   bool sanitize (hb_sanitize_context_t *c) const
143   {
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);
148
149     return_trace (dispatch (c));
150   }
151
152   public:
153   union {
154   KernSubTableHeader                            header;
155   AAT::KerxSubTableFormat0<KernSubTableHeader>  format0;
156   AAT::KerxSubTableFormat1<KernSubTableHeader>  format1;
157   AAT::KerxSubTableFormat2<KernSubTableHeader>  format2;
158   KernSubTableFormat3<KernSubTableHeader>       format3;
159   } u;
160   public:
161   DEFINE_SIZE_MIN (KernSubTableHeader::static_size);
162 };
163
164
165 struct KernOTSubTableHeader
166 {
167   static constexpr bool apple = false;
168   typedef AAT::ObsoleteTypes Types;
169
170   unsigned   tuple_count () const { return 0; }
171   bool     is_horizontal () const { return (coverage & Horizontal); }
172
173   enum Coverage
174   {
175     Horizontal  = 0x01u,
176     Minimum     = 0x02u,
177     CrossStream = 0x04u,
178     Override    = 0x08u,
179
180     /* Not supported: */
181     Backwards   = 0x00u,
182     Variation   = 0x00u,
183   };
184
185   bool sanitize (hb_sanitize_context_t *c) const
186   {
187     TRACE_SANITIZE (this);
188     return_trace (c->check_struct (this));
189   }
190
191   public:
192   HBUINT16      versionZ;       /* Unused. */
193   HBUINT16      length;         /* Length of the subtable (including this header). */
194   HBUINT8       format;         /* Subtable format. */
195   HBUINT8       coverage;       /* Coverage bits. */
196   public:
197   DEFINE_SIZE_STATIC (6);
198 };
199
200 struct KernOT : AAT::KerxTable<KernOT>
201 {
202   friend struct AAT::KerxTable<KernOT>;
203
204   static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
205   static constexpr unsigned minVersion = 0u;
206
207   typedef KernOTSubTableHeader SubTableHeader;
208   typedef SubTableHeader::Types Types;
209   typedef KernSubTable<SubTableHeader> SubTable;
210
211   protected:
212   HBUINT16      version;        /* Version--0x0000u */
213   HBUINT16      tableCount;     /* Number of subtables in the kerning table. */
214   SubTable      firstSubTable;  /* Subtables. */
215   public:
216   DEFINE_SIZE_MIN (4);
217 };
218
219
220 struct KernAATSubTableHeader
221 {
222   static constexpr bool apple = true;
223   typedef AAT::ObsoleteTypes Types;
224
225   unsigned   tuple_count () const { return 0; }
226   bool     is_horizontal () const { return !(coverage & Vertical); }
227
228   enum Coverage
229   {
230     Vertical    = 0x80u,
231     CrossStream = 0x40u,
232     Variation   = 0x20u,
233
234     /* Not supported: */
235     Backwards   = 0x00u,
236   };
237
238   bool sanitize (hb_sanitize_context_t *c) const
239   {
240     TRACE_SANITIZE (this);
241     return_trace (c->check_struct (this));
242   }
243
244   public:
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. */
251   public:
252   DEFINE_SIZE_STATIC (8);
253 };
254
255 struct KernAAT : AAT::KerxTable<KernAAT>
256 {
257   friend struct AAT::KerxTable<KernAAT>;
258
259   static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
260   static constexpr unsigned minVersion = 0x00010000u;
261
262   typedef KernAATSubTableHeader SubTableHeader;
263   typedef SubTableHeader::Types Types;
264   typedef KernSubTable<SubTableHeader> SubTable;
265
266   protected:
267   HBUINT32      version;        /* Version--0x00010000u */
268   HBUINT32      tableCount;     /* Number of subtables in the kerning table. */
269   SubTable      firstSubTable;  /* Subtables. */
270   public:
271   DEFINE_SIZE_MIN (8);
272 };
273
274 struct kern
275 {
276   static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
277
278   bool     has_data () const { return u.version32; }
279   unsigned get_type () const { return u.major; }
280
281   bool has_state_machine () const
282   {
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 ();
287 #endif
288     default:return false;
289     }
290   }
291
292   bool has_cross_stream () const
293   {
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 ();
298 #endif
299     default:return false;
300     }
301   }
302
303   int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
304   {
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);
309 #endif
310     default:return 0;
311     }
312   }
313
314   bool apply (AAT::hb_aat_apply_context_t *c) const
315   { return dispatch (c); }
316
317   template <typename context_t, typename ...Ts>
318   typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
319   {
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)...));
326 #endif
327     default:    return_trace (c->default_return_value ());
328     }
329   }
330
331   bool sanitize (hb_sanitize_context_t *c) const
332   {
333     TRACE_SANITIZE (this);
334     if (!u.version32.sanitize (c)) return_trace (false);
335     return_trace (dispatch (c));
336   }
337
338   protected:
339   union {
340   HBUINT32              version32;
341   HBUINT16              major;
342   KernOT                ot;
343 #ifndef HB_NO_AAT_SHAPE
344   KernAAT               aat;
345 #endif
346   } u;
347   public:
348   DEFINE_SIZE_UNION (4, version32);
349 };
350
351 } /* namespace OT */
352
353
354 #endif /* HB_OT_KERN_TABLE_HH */