Imported Upstream version 1.8.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-open-type-private.hh"
31
32 /*
33  * kern -- Kerning
34  * https://docs.microsoft.com/en-us/typography/opentype/spec/kern
35  * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html
36  */
37 #define HB_OT_TAG_kern HB_TAG('k','e','r','n')
38
39
40 namespace OT {
41
42
43 struct hb_glyph_pair_t
44 {
45   hb_codepoint_t left;
46   hb_codepoint_t right;
47 };
48
49 struct KernPair
50 {
51   inline int get_kerning (void) const
52   { return value; }
53
54   inline int cmp (const hb_glyph_pair_t &o) const
55   {
56     int ret = left.cmp (o.left);
57     if (ret) return ret;
58     return right.cmp (o.right);
59   }
60
61   inline bool sanitize (hb_sanitize_context_t *c) const
62   {
63     TRACE_SANITIZE (this);
64     return_trace (c->check_struct (this));
65   }
66
67   protected:
68   GlyphID       left;
69   GlyphID       right;
70   FWORD         value;
71   public:
72   DEFINE_SIZE_STATIC (6);
73 };
74
75 struct KernSubTableFormat0
76 {
77   inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
78   {
79     hb_glyph_pair_t pair = {left, right};
80     int i = pairs.bsearch (pair);
81     if (i == -1)
82       return 0;
83     return pairs[i].get_kerning ();
84   }
85
86   inline bool sanitize (hb_sanitize_context_t *c) const
87   {
88     TRACE_SANITIZE (this);
89     return_trace (pairs.sanitize (c));
90   }
91
92   protected:
93   BinSearchArrayOf<KernPair> pairs;     /* Array of kerning pairs. */
94   public:
95   DEFINE_SIZE_ARRAY (8, pairs);
96 };
97
98 struct KernClassTable
99 {
100   inline unsigned int get_class (hb_codepoint_t g) const { return classes[g - firstGlyph]; }
101
102   inline bool sanitize (hb_sanitize_context_t *c) const
103   {
104     TRACE_SANITIZE (this);
105     return_trace (firstGlyph.sanitize (c) && classes.sanitize (c));
106   }
107
108   protected:
109   HBUINT16              firstGlyph;     /* First glyph in class range. */
110   ArrayOf<HBUINT16>     classes;        /* Glyph classes. */
111   public:
112   DEFINE_SIZE_ARRAY (4, classes);
113 };
114
115 struct KernSubTableFormat2
116 {
117   inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
118   {
119     unsigned int l = (this+leftClassTable).get_class (left);
120     unsigned int r = (this+rightClassTable).get_class (right);
121     unsigned int offset = l * rowWidth + r * sizeof (FWORD);
122     const FWORD *arr = &(this+array);
123     if (unlikely ((const void *) arr < (const void *) this || (const void *) arr >= (const void *) end))
124       return 0;
125     const FWORD *v = &StructAtOffset<FWORD> (arr, offset);
126     if (unlikely ((const void *) v < (const void *) arr || (const void *) (v + 1) > (const void *) end))
127       return 0;
128     return *v;
129   }
130
131   inline bool sanitize (hb_sanitize_context_t *c) const
132   {
133     TRACE_SANITIZE (this);
134     return_trace (rowWidth.sanitize (c) &&
135                   leftClassTable.sanitize (c, this) &&
136                   rightClassTable.sanitize (c, this) &&
137                   array.sanitize (c, this));
138   }
139
140   protected:
141   HBUINT16      rowWidth;       /* The width, in bytes, of a row in the table. */
142   OffsetTo<KernClassTable>
143                 leftClassTable; /* Offset from beginning of this subtable to
144                                  * left-hand class table. */
145   OffsetTo<KernClassTable>
146                 rightClassTable;/* Offset from beginning of this subtable to
147                                  * right-hand class table. */
148   OffsetTo<FWORD>
149                 array;          /* Offset from beginning of this subtable to
150                                  * the start of the kerning array. */
151   public:
152   DEFINE_SIZE_MIN (8);
153 };
154
155 struct KernSubTable
156 {
157   inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end, unsigned int format) const
158   {
159     switch (format) {
160     case 0: return u.format0.get_kerning (left, right);
161     case 2: return u.format2.get_kerning (left, right, end);
162     default:return 0;
163     }
164   }
165
166   inline bool sanitize (hb_sanitize_context_t *c, unsigned int format) const
167   {
168     TRACE_SANITIZE (this);
169     switch (format) {
170     case 0: return_trace (u.format0.sanitize (c));
171     case 2: return_trace (u.format2.sanitize (c));
172     default:return_trace (true);
173     }
174   }
175
176   protected:
177   union {
178   KernSubTableFormat0   format0;
179   KernSubTableFormat2   format2;
180   } u;
181   public:
182   DEFINE_SIZE_MIN (0);
183 };
184
185
186 template <typename T>
187 struct KernSubTableWrapper
188 {
189   /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
190   inline const T* thiz (void) const { return static_cast<const T *> (this); }
191
192   inline bool is_horizontal (void) const
193   { return (thiz()->coverage & T::COVERAGE_CHECK_FLAGS) == T::COVERAGE_CHECK_HORIZONTAL; }
194
195   inline bool is_override (void) const
196   { return bool (thiz()->coverage & T::COVERAGE_OVERRIDE_FLAG); }
197
198   inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
199   { return thiz()->subtable.get_kerning (left, right, end, thiz()->format); }
200
201   inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
202   { return is_horizontal () ? get_kerning (left, right, end) : 0; }
203
204   inline unsigned int get_size (void) const { return thiz()->length; }
205
206   inline bool sanitize (hb_sanitize_context_t *c) const
207   {
208     TRACE_SANITIZE (this);
209     return_trace (c->check_struct (thiz()) &&
210                   thiz()->length >= T::min_size &&
211                   c->check_array (thiz(), 1, thiz()->length) &&
212                   thiz()->subtable.sanitize (c, thiz()->format));
213   }
214 };
215
216 template <typename T>
217 struct KernTable
218 {
219   /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
220   inline const T* thiz (void) const { return static_cast<const T *> (this); }
221
222   inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const
223   {
224     int v = 0;
225     const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data);
226     unsigned int count = thiz()->nTables;
227     for (unsigned int i = 0; i < count; i++)
228     {
229       if (st->is_override ())
230         v = 0;
231       v += st->get_h_kerning (left, right, table_length + (const char *) this);
232       st = &StructAfter<typename T::SubTableWrapper> (*st);
233     }
234     return v;
235   }
236
237   inline bool sanitize (hb_sanitize_context_t *c) const
238   {
239     TRACE_SANITIZE (this);
240     if (unlikely (!c->check_struct (thiz()) ||
241                   thiz()->version != T::VERSION))
242       return_trace (false);
243
244     const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data);
245     unsigned int count = thiz()->nTables;
246     for (unsigned int i = 0; i < count; i++)
247     {
248       if (unlikely (!st->sanitize (c)))
249         return_trace (false);
250       st = &StructAfter<typename T::SubTableWrapper> (*st);
251     }
252
253     return_trace (true);
254   }
255 };
256
257 struct KernOT : KernTable<KernOT>
258 {
259   friend struct KernTable<KernOT>;
260
261   static const uint16_t VERSION = 0x0000u;
262
263   struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper>
264   {
265     friend struct KernSubTableWrapper<SubTableWrapper>;
266
267     enum coverage_flags_t {
268       COVERAGE_DIRECTION_FLAG   = 0x01u,
269       COVERAGE_MINIMUM_FLAG     = 0x02u,
270       COVERAGE_CROSSSTREAM_FLAG = 0x04u,
271       COVERAGE_OVERRIDE_FLAG    = 0x08u,
272
273       COVERAGE_VARIATION_FLAG   = 0x00u, /* Not supported. */
274
275       COVERAGE_CHECK_FLAGS      = 0x07u,
276       COVERAGE_CHECK_HORIZONTAL = 0x01u
277     };
278
279     protected:
280     HBUINT16    versionZ;       /* Unused. */
281     HBUINT16    length;         /* Length of the subtable (including this header). */
282     HBUINT8     format;         /* Subtable format. */
283     HBUINT8     coverage;       /* Coverage bits. */
284     KernSubTable subtable;      /* Subtable data. */
285     public:
286     DEFINE_SIZE_MIN (6);
287   };
288
289   protected:
290   HBUINT16      version;        /* Version--0x0000u */
291   HBUINT16      nTables;        /* Number of subtables in the kerning table. */
292   HBUINT8               data[VAR];
293   public:
294   DEFINE_SIZE_ARRAY (4, data);
295 };
296
297 struct KernAAT : KernTable<KernAAT>
298 {
299   friend struct KernTable<KernAAT>;
300
301   static const uint32_t VERSION = 0x00010000u;
302
303   struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper>
304   {
305     friend struct KernSubTableWrapper<SubTableWrapper>;
306
307     enum coverage_flags_t {
308       COVERAGE_DIRECTION_FLAG   = 0x80u,
309       COVERAGE_CROSSSTREAM_FLAG = 0x40u,
310       COVERAGE_VARIATION_FLAG   = 0x20u,
311
312       COVERAGE_OVERRIDE_FLAG    = 0x00u, /* Not supported. */
313
314       COVERAGE_CHECK_FLAGS      = 0xE0u,
315       COVERAGE_CHECK_HORIZONTAL = 0x00u
316     };
317
318     protected:
319     HBUINT32    length;         /* Length of the subtable (including this header). */
320     HBUINT8     coverage;       /* Coverage bits. */
321     HBUINT8     format;         /* Subtable format. */
322     HBUINT16    tupleIndex;     /* The tuple index (used for variations fonts).
323                                  * This value specifies which tuple this subtable covers. */
324     KernSubTable subtable;      /* Subtable data. */
325     public:
326     DEFINE_SIZE_MIN (8);
327   };
328
329   protected:
330   HBUINT32              version;        /* Version--0x00010000u */
331   HBUINT32              nTables;        /* Number of subtables in the kerning table. */
332   HBUINT8               data[VAR];
333   public:
334   DEFINE_SIZE_ARRAY (8, data);
335 };
336
337 struct kern
338 {
339   static const hb_tag_t tableTag = HB_OT_TAG_kern;
340
341   inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const
342   {
343     switch (u.major) {
344     case 0: return u.ot.get_h_kerning (left, right, table_length);
345     case 1: return u.aat.get_h_kerning (left, right, table_length);
346     default:return 0;
347     }
348   }
349
350   inline bool sanitize (hb_sanitize_context_t *c) const
351   {
352     TRACE_SANITIZE (this);
353     if (!u.major.sanitize (c)) return_trace (false);
354     switch (u.major) {
355     case 0: return_trace (u.ot.sanitize (c));
356     case 1: return_trace (u.aat.sanitize (c));
357     default:return_trace (true);
358     }
359   }
360
361   struct accelerator_t
362   {
363     inline void init (hb_face_t *face)
364     {
365       blob = Sanitizer<kern>().sanitize (face->reference_table (HB_OT_TAG_kern));
366       table = blob->as<kern> ();
367       table_length = blob->length;
368     }
369     inline void fini (void)
370     {
371       hb_blob_destroy (blob);
372     }
373
374     inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
375     { return table->get_h_kerning (left, right, table_length); }
376
377     private:
378     hb_blob_t *blob;
379     const kern *table;
380     unsigned int table_length;
381   };
382
383   protected:
384   union {
385   HBUINT16              major;
386   KernOT                ot;
387   KernAAT               aat;
388   } u;
389   public:
390   DEFINE_SIZE_UNION (2, major);
391 };
392
393 } /* namespace OT */
394
395
396 #endif /* HB_OT_KERN_TABLE_HH */