Imported Upstream version 1.4.6
[platform/upstream/harfbuzz.git] / src / hb-ot-cbdt-table.hh
1 /*
2  * Copyright © 2016  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): Seigo Nonaka
25  */
26
27 #ifndef HB_OT_CBDT_TABLE_HH
28 #define HB_OT_CBDT_TABLE_HH
29
30 #include "hb-open-type-private.hh"
31
32 namespace OT {
33
34 struct SmallGlyphMetrics
35 {
36   inline bool sanitize (hb_sanitize_context_t *c) const
37   {
38     TRACE_SANITIZE (this);
39     return_trace (c->check_struct (this));
40   }
41
42   inline void get_extents (hb_glyph_extents_t *extents) const
43   {
44     extents->x_bearing = bearingX;
45     extents->y_bearing = bearingY;
46     extents->width = width;
47     extents->height = -height;
48   }
49
50   BYTE height;
51   BYTE width;
52   CHAR bearingX;
53   CHAR bearingY;
54   BYTE advance;
55
56   DEFINE_SIZE_STATIC(5);
57 };
58
59 struct BigGlyphMetrics : SmallGlyphMetrics
60 {
61   CHAR vertBearingX;
62   CHAR vertBearingY;
63   BYTE vertAdvance;
64
65   DEFINE_SIZE_STATIC(8);
66 };
67
68 struct SBitLineMetrics
69 {
70   inline bool sanitize (hb_sanitize_context_t *c) const
71   {
72     TRACE_SANITIZE (this);
73     return_trace (c->check_struct (this));
74   }
75
76   CHAR ascender;
77   CHAR decender;
78   BYTE widthMax;
79   CHAR caretSlopeNumerator;
80   CHAR caretSlopeDenominator;
81   CHAR caretOffset;
82   CHAR minOriginSB;
83   CHAR minAdvanceSB;
84   CHAR maxBeforeBL;
85   CHAR minAfterBL;
86   CHAR padding1;
87   CHAR padding2;
88
89   DEFINE_SIZE_STATIC(12);
90 };
91
92
93 /*
94  * Index Subtables.
95  */
96
97 struct IndexSubtableHeader
98 {
99   inline bool sanitize (hb_sanitize_context_t *c) const
100   {
101     TRACE_SANITIZE (this);
102     return_trace (c->check_struct (this));
103   }
104
105   USHORT indexFormat;
106   USHORT imageFormat;
107   ULONG imageDataOffset;
108
109   DEFINE_SIZE_STATIC(8);
110 };
111
112 template <typename OffsetType>
113 struct IndexSubtableFormat1Or3
114 {
115   inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
116   {
117     TRACE_SANITIZE (this);
118     return_trace (c->check_struct (this) &&
119                   c->check_array (offsetArrayZ, offsetArrayZ[0].static_size, glyph_count + 1));
120   }
121
122   bool get_image_data (unsigned int idx,
123                        unsigned int *offset,
124                        unsigned int *length) const
125   {
126     if (unlikely (offsetArrayZ[idx + 1] <= offsetArrayZ[idx]))
127       return false;
128
129     *offset = header.imageDataOffset + offsetArrayZ[idx];
130     *length = offsetArrayZ[idx + 1] - offsetArrayZ[idx];
131     return true;
132   }
133
134   IndexSubtableHeader header;
135   Offset<OffsetType> offsetArrayZ[VAR];
136
137   DEFINE_SIZE_ARRAY(8, offsetArrayZ);
138 };
139
140 struct IndexSubtableFormat1 : IndexSubtableFormat1Or3<ULONG> {};
141 struct IndexSubtableFormat3 : IndexSubtableFormat1Or3<USHORT> {};
142
143 struct IndexSubtable
144 {
145   inline bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
146   {
147     TRACE_SANITIZE (this);
148     if (!u.header.sanitize (c)) return_trace (false);
149     switch (u.header.indexFormat) {
150     case 1: return_trace (u.format1.sanitize (c, glyph_count));
151     case 3: return_trace (u.format3.sanitize (c, glyph_count));
152     default:return_trace (true);
153     }
154   }
155
156   inline bool get_extents (hb_glyph_extents_t *extents) const
157   {
158     switch (u.header.indexFormat) {
159     case 2: case 5: /* TODO */
160     case 1: case 3: case 4: /* Variable-metrics formats do not have metrics here. */
161     default:return (false);
162     }
163   }
164
165   bool get_image_data (unsigned int idx,
166                        unsigned int *offset,
167                        unsigned int *length,
168                        unsigned int *format) const
169   {
170     *format = u.header.imageFormat;
171     switch (u.header.indexFormat) {
172     case 1: return u.format1.get_image_data (idx, offset, length);
173     case 3: return u.format3.get_image_data (idx, offset, length);
174     default: return false;
175     }
176   }
177
178   protected:
179   union {
180   IndexSubtableHeader   header;
181   IndexSubtableFormat1  format1;
182   IndexSubtableFormat3  format3;
183   /* TODO: Format 2, 4, 5. */
184   } u;
185   public:
186   DEFINE_SIZE_UNION (8, header);
187 };
188
189 struct IndexSubtableRecord
190 {
191   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
192   {
193     TRACE_SANITIZE (this);
194     return_trace (c->check_struct (this) &&
195                   firstGlyphIndex <= lastGlyphIndex &&
196                   offsetToSubtable.sanitize (c, this, lastGlyphIndex - firstGlyphIndex + 1));
197   }
198
199   inline bool get_extents (hb_glyph_extents_t *extents) const
200   {
201     return (this+offsetToSubtable).get_extents (extents);
202   }
203
204   bool get_image_data (unsigned int gid,
205                        unsigned int *offset,
206                        unsigned int *length,
207                        unsigned int *format) const
208   {
209     if (gid < firstGlyphIndex || gid > lastGlyphIndex)
210     {
211       return false;
212     }
213     return (this+offsetToSubtable).get_image_data (gid - firstGlyphIndex,
214                                                    offset, length, format);
215   }
216
217   USHORT firstGlyphIndex;
218   USHORT lastGlyphIndex;
219   LOffsetTo<IndexSubtable> offsetToSubtable;
220
221   DEFINE_SIZE_STATIC(8);
222 };
223
224 struct IndexSubtableArray
225 {
226   inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
227   {
228     TRACE_SANITIZE (this);
229     if (unlikely (!c->check_array (&indexSubtablesZ, indexSubtablesZ[0].static_size, count)))
230       return_trace (false);
231     for (unsigned int i = 0; i < count; i++)
232       if (unlikely (!indexSubtablesZ[i].sanitize (c, this)))
233         return_trace (false);
234     return_trace (true);
235   }
236
237   public:
238   const IndexSubtableRecord* find_table (hb_codepoint_t glyph, unsigned int numTables) const
239   {
240     for (unsigned int i = 0; i < numTables; ++i)
241     {
242       unsigned int firstGlyphIndex = indexSubtablesZ[i].firstGlyphIndex;
243       unsigned int lastGlyphIndex = indexSubtablesZ[i].lastGlyphIndex;
244       if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex) {
245         return &indexSubtablesZ[i];
246       }
247     }
248     return NULL;
249   }
250
251   protected:
252   IndexSubtableRecord indexSubtablesZ[VAR];
253
254   public:
255   DEFINE_SIZE_ARRAY(0, indexSubtablesZ);
256 };
257
258 struct BitmapSizeTable
259 {
260   friend struct CBLC;
261
262   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
263   {
264     TRACE_SANITIZE (this);
265     return_trace (c->check_struct (this) &&
266                   indexSubtableArrayOffset.sanitize (c, base, numberOfIndexSubtables) &&
267                   c->check_range (&(base+indexSubtableArrayOffset), indexTablesSize) &&
268                   horizontal.sanitize (c) &&
269                   vertical.sanitize (c));
270   }
271
272   const IndexSubtableRecord *find_table (hb_codepoint_t glyph, const void *base) const
273   {
274     return (base+indexSubtableArrayOffset).find_table (glyph, numberOfIndexSubtables);
275   }
276
277   protected:
278   LOffsetTo<IndexSubtableArray> indexSubtableArrayOffset;
279   ULONG indexTablesSize;
280   ULONG numberOfIndexSubtables;
281   ULONG colorRef;
282   SBitLineMetrics horizontal;
283   SBitLineMetrics vertical;
284   USHORT startGlyphIndex;
285   USHORT endGlyphIndex;
286   BYTE ppemX;
287   BYTE ppemY;
288   BYTE bitDepth;
289   CHAR flags;
290
291 public:
292   DEFINE_SIZE_STATIC(48);
293 };
294
295
296 /*
297  * Glyph Bitmap Data Formats.
298  */
299
300 struct GlyphBitmapDataFormat17
301 {
302   SmallGlyphMetrics glyphMetrics;
303   ULONG dataLen;
304   BYTE dataZ[VAR];
305
306   DEFINE_SIZE_ARRAY(9, dataZ);
307 };
308
309
310 /*
311  * CBLC -- Color Bitmap Location Table
312  */
313
314 #define HB_OT_TAG_CBLC HB_TAG('C','B','L','C')
315
316 struct CBLC
317 {
318   static const hb_tag_t tableTag = HB_OT_TAG_CBLC;
319
320   inline bool sanitize (hb_sanitize_context_t *c) const
321   {
322     TRACE_SANITIZE (this);
323     return_trace (c->check_struct (this) &&
324                   likely (version.major == 2 || version.major == 3) &&
325                   sizeTables.sanitize (c, this));
326   }
327
328   public:
329   const IndexSubtableRecord *find_table (hb_codepoint_t glyph,
330                                          unsigned int *x_ppem, unsigned int *y_ppem) const
331   {
332     /* TODO: Make it possible to select strike. */
333
334     unsigned int count = sizeTables.len;
335     for (uint32_t i = 0; i < count; ++i)
336     {
337       unsigned int startGlyphIndex = sizeTables.array[i].startGlyphIndex;
338       unsigned int endGlyphIndex = sizeTables.array[i].endGlyphIndex;
339       if (startGlyphIndex <= glyph && glyph <= endGlyphIndex)
340       {
341         *x_ppem = sizeTables[i].ppemX;
342         *y_ppem = sizeTables[i].ppemY;
343         return sizeTables[i].find_table (glyph, this);
344       }
345     }
346
347     return NULL;
348   }
349
350   protected:
351   FixedVersion<>                version;
352   LArrayOf<BitmapSizeTable>     sizeTables;
353
354   public:
355   DEFINE_SIZE_ARRAY(8, sizeTables);
356 };
357
358 /*
359  * CBDT -- Color Bitmap Data Table
360  */
361 #define HB_OT_TAG_CBDT HB_TAG('C','B','D','T')
362
363 struct CBDT
364 {
365   static const hb_tag_t tableTag = HB_OT_TAG_CBDT;
366
367   inline bool sanitize (hb_sanitize_context_t *c) const
368   {
369     TRACE_SANITIZE (this);
370     return_trace (c->check_struct (this) &&
371                   likely (version.major == 2 || version.major == 3));
372   }
373
374   protected:
375   FixedVersion<>version;
376   BYTE dataZ[VAR];
377
378   public:
379   DEFINE_SIZE_ARRAY(4, dataZ);
380 };
381
382 } /* namespace OT */
383
384 #endif /* HB_OT_CBDT_TABLE_HH */