Imported Upstream version 2.3.1
[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>
125   typename context_t::return_t dispatch (context_t *c) 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     case 1:     return_trace (u.header.apple ? c->dispatch (u.format1) : c->default_return_value ());
132     case 2:     return_trace (c->dispatch (u.format2));
133     case 3:     return_trace (u.header.apple ? c->dispatch (u.format3) : c->default_return_value ());
134     default:    return_trace (c->default_return_value ());
135     }
136   }
137
138   bool sanitize (hb_sanitize_context_t *c) const
139   {
140     TRACE_SANITIZE (this);
141     if (unlikely (!u.header.sanitize (c) ||
142                   u.header.length < u.header.min_size ||
143                   !c->check_range (this, u.header.length))) return_trace (false);
144
145     return_trace (dispatch (c));
146   }
147
148   public:
149   union {
150   KernSubTableHeader                            header;
151   AAT::KerxSubTableFormat0<KernSubTableHeader>  format0;
152   AAT::KerxSubTableFormat1<KernSubTableHeader>  format1;
153   AAT::KerxSubTableFormat2<KernSubTableHeader>  format2;
154   KernSubTableFormat3<KernSubTableHeader>       format3;
155   } u;
156   public:
157   DEFINE_SIZE_MIN (KernSubTableHeader::static_size);
158 };
159
160
161 struct KernOTSubTableHeader
162 {
163   static constexpr bool apple = false;
164   typedef AAT::ObsoleteTypes Types;
165
166   unsigned int tuple_count () const { return 0; }
167   bool is_horizontal () const { return (coverage & Horizontal); }
168
169   enum Coverage
170   {
171     Horizontal  = 0x01u,
172     Minimum     = 0x02u,
173     CrossStream = 0x04u,
174     Override    = 0x08u,
175
176     /* Not supported: */
177     Backwards   = 0x00u,
178     Variation   = 0x00u,
179   };
180
181   bool sanitize (hb_sanitize_context_t *c) const
182   {
183     TRACE_SANITIZE (this);
184     return_trace (c->check_struct (this));
185   }
186
187   public:
188   HBUINT16      versionZ;       /* Unused. */
189   HBUINT16      length;         /* Length of the subtable (including this header). */
190   HBUINT8       format;         /* Subtable format. */
191   HBUINT8       coverage;       /* Coverage bits. */
192   public:
193   DEFINE_SIZE_STATIC (6);
194 };
195
196 struct KernOT : AAT::KerxTable<KernOT>
197 {
198   friend struct AAT::KerxTable<KernOT>;
199
200   static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
201   static constexpr unsigned minVersion = 0u;
202
203   typedef KernOTSubTableHeader SubTableHeader;
204   typedef SubTableHeader::Types Types;
205   typedef KernSubTable<SubTableHeader> SubTable;
206
207   protected:
208   HBUINT16      version;        /* Version--0x0000u */
209   HBUINT16      tableCount;     /* Number of subtables in the kerning table. */
210   SubTable      firstSubTable;  /* Subtables. */
211   public:
212   DEFINE_SIZE_MIN (4);
213 };
214
215
216 struct KernAATSubTableHeader
217 {
218   static constexpr bool apple = true;
219   typedef AAT::ObsoleteTypes Types;
220
221   unsigned int tuple_count () const { return 0; }
222   bool is_horizontal () const       { return !(coverage & Vertical); }
223
224   enum Coverage
225   {
226     Vertical    = 0x80u,
227     CrossStream = 0x40u,
228     Variation   = 0x20u,
229
230     /* Not supported: */
231     Backwards   = 0x00u,
232   };
233
234   bool sanitize (hb_sanitize_context_t *c) const
235   {
236     TRACE_SANITIZE (this);
237     return_trace (c->check_struct (this));
238   }
239
240   public:
241   HBUINT32      length;         /* Length of the subtable (including this header). */
242   HBUINT8       coverage;       /* Coverage bits. */
243   HBUINT8       format;         /* Subtable format. */
244   HBUINT16      tupleIndex;     /* The tuple index (used for variations fonts).
245                                * This value specifies which tuple this subtable covers.
246                                * Note: We don't implement. */
247   public:
248   DEFINE_SIZE_STATIC (8);
249 };
250
251 struct KernAAT : AAT::KerxTable<KernAAT>
252 {
253   friend struct AAT::KerxTable<KernAAT>;
254
255   static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
256   static constexpr unsigned minVersion = 0x00010000u;
257
258   typedef KernAATSubTableHeader SubTableHeader;
259   typedef SubTableHeader::Types Types;
260   typedef KernSubTable<SubTableHeader> SubTable;
261
262   protected:
263   HBUINT32      version;        /* Version--0x00010000u */
264   HBUINT32      tableCount;     /* Number of subtables in the kerning table. */
265   SubTable      firstSubTable;  /* Subtables. */
266   public:
267   DEFINE_SIZE_MIN (8);
268 };
269
270 struct kern
271 {
272   static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
273
274   bool has_data () const { return u.version32; }
275   unsigned int get_type () const { return u.major; }
276
277   bool has_state_machine () const
278   {
279     switch (get_type ()) {
280     case 0: return u.ot.has_state_machine ();
281     case 1: return u.aat.has_state_machine ();
282     default:return false;
283     }
284   }
285
286   bool has_cross_stream () const
287   {
288     switch (get_type ()) {
289     case 0: return u.ot.has_cross_stream ();
290     case 1: return u.aat.has_cross_stream ();
291     default:return false;
292     }
293   }
294
295   int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
296   {
297     switch (get_type ()) {
298     case 0: return u.ot.get_h_kerning (left, right);
299     case 1: return u.aat.get_h_kerning (left, right);
300     default:return 0;
301     }
302   }
303
304   bool apply (AAT::hb_aat_apply_context_t *c) const
305   { return dispatch (c); }
306
307   template <typename context_t>
308   typename context_t::return_t dispatch (context_t *c) const
309   {
310     unsigned int subtable_type = get_type ();
311     TRACE_DISPATCH (this, subtable_type);
312     switch (subtable_type) {
313     case 0:     return_trace (c->dispatch (u.ot));
314     case 1:     return_trace (c->dispatch (u.aat));
315     default:    return_trace (c->default_return_value ());
316     }
317   }
318
319   bool sanitize (hb_sanitize_context_t *c) const
320   {
321     TRACE_SANITIZE (this);
322     if (!u.version32.sanitize (c)) return_trace (false);
323     return_trace (dispatch (c));
324   }
325
326   protected:
327   union {
328   HBUINT32              version32;
329   HBUINT16              major;
330   KernOT                ot;
331   KernAAT               aat;
332   } u;
333   public:
334   DEFINE_SIZE_UNION (4, version32);
335 };
336
337 } /* namespace OT */
338
339
340 #endif /* HB_OT_KERN_TABLE_HH */