Imported Upstream version 1.7.6
[platform/upstream/harfbuzz.git] / src / hb-aat-layout-kerx-table.hh
1 /*
2  * Copyright © 2018  Ebrahim Byagowi
3  * Copyright © 2018  Google, Inc.
4  *
5  *  This is part of HarfBuzz, a text shaping library.
6  *
7  * Permission is hereby granted, without written agreement and without
8  * license or royalty fees, to use, copy, modify, and distribute this
9  * software and its documentation for any purpose, provided that the
10  * above copyright notice and the following two paragraphs appear in
11  * all copies of this software.
12  *
13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17  * DAMAGE.
18  *
19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
22  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24  *
25  * Google Author(s): Behdad Esfahbod
26  */
27
28 #ifndef HB_AAT_LAYOUT_KERX_TABLE_HH
29 #define HB_AAT_LAYOUT_KERX_TABLE_HH
30
31 #include "hb-open-type-private.hh"
32 #include "hb-aat-layout-common-private.hh"
33
34 #define HB_AAT_TAG_KERX HB_TAG('k','e','r','x')
35
36
37 namespace AAT {
38
39 using namespace OT;
40
41
42 struct KerxFormat0Records
43 {
44   inline bool sanitize (hb_sanitize_context_t *c) const
45   {
46     TRACE_SANITIZE (this);
47     return_trace (c->check_struct (this));
48   }
49
50   protected:
51   GlyphID       left;
52   GlyphID       right;
53   FWORD         value;
54   public:
55   DEFINE_SIZE_STATIC (6);
56 };
57
58 struct KerxSubTableFormat0
59 {
60   // TODO(ebraminio) Enable when we got suitable BinSearchArrayOf
61   // inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
62   // {
63   //   hb_glyph_pair_t pair = {left, right};
64   //   int i = pairs.bsearch (pair);
65   //   if (i == -1)
66   //     return 0;
67   //   return pairs[i].get_kerning ();
68   // }
69
70   inline bool sanitize (hb_sanitize_context_t *c) const
71   {
72     TRACE_SANITIZE (this);
73     return_trace (c->check_struct (this) &&
74       c->check_array (records, records[0].static_size, nPairs));
75   }
76
77   protected:
78   // TODO(ebraminio): A custom version of "BinSearchArrayOf<KerxPair> pairs;" is
79   // needed here to use HBUINT32 instead
80   HBUINT32 nPairs;      /* The number of kerning pairs in this subtable */
81   HBUINT32 searchRange; /* The largest power of two less than or equal to the value of nPairs,
82                          * multiplied by the size in bytes of an entry in the subtable. */
83   HBUINT32 entrySelector; /* This is calculated as log2 of the largest power of two less
84                            * than or equal to the value of nPairs. */
85   HBUINT32 rangeShift;  /* The value of nPairs minus the largest power of two less than or equal to nPairs. */
86   KerxFormat0Records records[VAR]; /* VAR=nPairs */
87   public:
88   DEFINE_SIZE_ARRAY (16, records);
89 };
90
91 struct KerxSubTableFormat1
92 {
93   inline bool sanitize (hb_sanitize_context_t *c) const
94   {
95     TRACE_SANITIZE (this);
96     return_trace (c->check_struct (this) &&
97       stateHeader.sanitize (c));
98   }
99
100   protected:
101   StateTable<HBUINT16>          stateHeader;
102   LOffsetTo<ArrayOf<HBUINT16> > valueTable;
103   public:
104   DEFINE_SIZE_STATIC (20);
105 };
106
107 // TODO(ebraminio): Maybe this can be replaced with Lookup<HBUINT16>?
108 struct KerxClassTable
109 {
110   inline unsigned int get_class (hb_codepoint_t g) const { return classes[g - firstGlyph]; }
111
112   inline bool sanitize (hb_sanitize_context_t *c) const
113   {
114     TRACE_SANITIZE (this);
115     return_trace (firstGlyph.sanitize (c) && classes.sanitize (c));
116   }
117
118   protected:
119   HBUINT16              firstGlyph;     /* First glyph in class range. */
120   ArrayOf<HBUINT16>     classes;        /* Glyph classes. */
121   public:
122   DEFINE_SIZE_ARRAY (4, classes);
123 };
124
125 struct KerxSubTableFormat2
126 {
127   inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
128   {
129     unsigned int l = (this+leftClassTable).get_class (left);
130     unsigned int r = (this+leftClassTable).get_class (left);
131     unsigned int offset = l * rowWidth + r * sizeof (FWORD);
132     const FWORD *arr = &(this+array);
133     if (unlikely ((const void *) arr < (const void *) this || (const void *) arr >= (const void *) end))
134       return 0;
135     const FWORD *v = &StructAtOffset<FWORD> (arr, offset);
136     if (unlikely ((const void *) v < (const void *) arr || (const void *) (v + 1) > (const void *) end))
137       return 0;
138     return *v;
139   }
140
141   inline bool sanitize (hb_sanitize_context_t *c) const
142   {
143     TRACE_SANITIZE (this);
144     return_trace (c->check_struct (this) &&
145       rowWidth.sanitize (c) &&
146                   leftClassTable.sanitize (c, this) &&
147                   rightClassTable.sanitize (c, this) &&
148                   array.sanitize (c, this));
149   }
150
151   protected:
152   HBUINT32      rowWidth;       /* The width, in bytes, of a row in the table. */
153   LOffsetTo<KerxClassTable>
154                 leftClassTable; /* Offset from beginning of this subtable to
155                                  * left-hand class table. */
156   LOffsetTo<KerxClassTable>
157                 rightClassTable;/* Offset from beginning of this subtable to
158                                  * right-hand class table. */
159   LOffsetTo<FWORD>
160                 array;          /* Offset from beginning of this subtable to
161                                  * the start of the kerning array. */
162   public:
163   DEFINE_SIZE_STATIC (16);
164 };
165
166 struct KerxSubTableFormat4
167 {
168   inline bool sanitize (hb_sanitize_context_t *c) const
169   {
170     TRACE_SANITIZE (this);
171     return_trace (c->check_struct (this) &&
172       rowWidth.sanitize (c) &&
173                   leftClassTable.sanitize (c, this) &&
174                   rightClassTable.sanitize (c, this) &&
175                   array.sanitize (c, this));
176   }
177
178   protected:
179   HBUINT32      rowWidth;       /* The width, in bytes, of a row in the table. */
180   LOffsetTo<KerxClassTable>
181                 leftClassTable; /* Offset from beginning of this subtable to
182                                  * left-hand class table. */
183   LOffsetTo<KerxClassTable>
184                 rightClassTable;/* Offset from beginning of this subtable to
185                                  * right-hand class table. */
186   LOffsetTo<FWORD>
187                 array;          /* Offset from beginning of this subtable to
188                                  * the start of the kerning array. */
189   public:
190   DEFINE_SIZE_STATIC (16);
191 };
192
193 struct KerxSubTableFormat6
194 {
195   inline bool sanitize (hb_sanitize_context_t *c) const
196   {
197     TRACE_SANITIZE (this);
198     return_trace (c->check_struct (this) &&
199       rowIndexTable.sanitize (c, this) &&
200       columnIndexTable.sanitize (c, this) &&
201       kerningArray.sanitize (c, this) &&
202       kerningVector.sanitize (c, this));
203   }
204
205   protected:
206   HBUINT32      flags;
207   HBUINT16      rowCount;
208   HBUINT16      columnCount;
209   LOffsetTo<Lookup<HBUINT16> >  rowIndexTable;
210   LOffsetTo<Lookup<HBUINT16> >  columnIndexTable;
211   LOffsetTo<Lookup<HBUINT16> >  kerningArray;
212   LOffsetTo<Lookup<HBUINT16> >  kerningVector;
213   public:
214   DEFINE_SIZE_STATIC (24);
215 };
216
217 enum coverage_flags_t
218 {
219   COVERAGE_VERTICAL_FLAG        = 0x80u,
220   COVERAGE_CROSSSTREAM_FLAG     = 0x40u,
221   COVERAGE_VARIATION_FLAG       = 0x20u,
222   COVERAGE_PROCESS_DIRECTION    = 0x10u,
223 };
224
225 struct KerxTable
226 {
227   inline bool apply (hb_aat_apply_context_t *c, const AAT::ankr *ankr) const
228   {
229     TRACE_APPLY (this);
230     /* TODO */
231     return_trace (false);
232   }
233
234   inline unsigned int get_size (void) const { return length; }
235
236   inline bool sanitize (hb_sanitize_context_t *c) const
237   {
238     TRACE_SANITIZE (this);
239     if (!c->check_struct (this))
240       return_trace (false);
241
242     switch (format) {
243     case 0: return u.format0.sanitize (c);
244     case 1: return u.format1.sanitize (c);
245     case 2: return u.format2.sanitize (c);
246     case 4: return u.format4.sanitize (c);
247     case 6: return u.format6.sanitize (c);
248     default:return_trace (false);
249     }
250   }
251
252 protected:
253   HBUINT32      length;
254   HBUINT8       coverage;
255   HBUINT16      unused;
256   HBUINT8       format;
257   HBUINT32      tupleIndex;
258   union {
259   KerxSubTableFormat0   format0;
260   KerxSubTableFormat1   format1;
261   KerxSubTableFormat2   format2;
262   KerxSubTableFormat4   format4;
263   KerxSubTableFormat6   format6;
264   } u;
265 public:
266   DEFINE_SIZE_MIN (12);
267 };
268
269 struct SubtableGlyphCoverageArray
270 {
271   inline bool sanitize (hb_sanitize_context_t *c) const
272   {
273     TRACE_SANITIZE (this);
274     return_trace (c->check_struct (this));
275   }
276
277   protected:
278   HBUINT32      length;
279   HBUINT32      coverage;
280   HBUINT32      tupleCount;
281   public:
282   DEFINE_SIZE_STATIC (12);
283 };
284
285 struct kerx
286 {
287   static const hb_tag_t tableTag = HB_AAT_TAG_KERX;
288
289   inline bool apply (hb_aat_apply_context_t *c, const AAT::ankr *ankr) const
290   {
291     TRACE_APPLY (this);
292     const KerxTable &table = StructAfter<KerxTable> (*this);
293     return_trace (table.apply (c, ankr));
294   }
295
296   inline bool sanitize (hb_sanitize_context_t *c) const
297   {
298     TRACE_SANITIZE (this);
299     if (!(c->check_struct (this)))
300      return_trace (false);
301
302     /* TODO: Something like `morx`s ChainSubtable should be done here instead */
303     const KerxTable *table = &StructAfter<KerxTable> (*this);
304     if (!(table->sanitize (c)))
305       return_trace (false);
306
307     for (unsigned int i = 0; i < nTables - 1; ++i)
308     {
309       table = &StructAfter<KerxTable> (*table);
310       if (!(table->sanitize (c)))
311         return_trace (false);
312     }
313
314     // If version is less than 3, we are done here; otherwise better to check footer also
315     if (version < 3)
316       return_trace (true);
317
318     // TODO: Investigate why this just work on some fonts no matter of version
319     // const SubtableGlyphCoverageArray &footer =
320     //   StructAfter<SubtableGlyphCoverageArray> (*table);
321     // return_trace (footer.sanitize (c));
322
323     return_trace (true);
324   }
325
326   protected:
327   HBUINT16              version;
328   HBUINT16              padding;
329   HBUINT32              nTables;
330 /*KerxTable tables[VAR];*/
331 /*SubtableGlyphCoverageArray coverage_array;*/
332   public:
333   DEFINE_SIZE_STATIC (8);
334 };
335
336 } /* namespace AAT */
337
338
339 #endif /* HB_AAT_LAYOUT_KERX_TABLE_HH */