|
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 OffsetTo<IndexSubtable, ULONG> 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 OffsetTo<IndexSubtableArray, ULONG> 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 ArrayOf<BitmapSizeTable, ULONG> 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 */ |