27 #ifndef HB_OT_COLOR_CBDT_TABLE_HH |
27 #ifndef HB_OT_COLOR_CBDT_TABLE_HH |
28 #define HB_OT_COLOR_CBDT_TABLE_HH |
28 #define HB_OT_COLOR_CBDT_TABLE_HH |
29 |
29 |
30 #include "hb-open-type-private.hh" |
30 #include "hb-open-type-private.hh" |
31 |
31 |
|
32 /* |
|
33 * CBLC -- Color Bitmap Location |
|
34 * https://docs.microsoft.com/en-us/typography/opentype/spec/cblc |
|
35 * https://docs.microsoft.com/en-us/typography/opentype/spec/eblc |
|
36 * CBDT -- Color Bitmap Data |
|
37 * https://docs.microsoft.com/en-us/typography/opentype/spec/cbdt |
|
38 * https://docs.microsoft.com/en-us/typography/opentype/spec/ebdt |
|
39 */ |
|
40 #define HB_OT_TAG_CBLC HB_TAG('C','B','L','C') |
|
41 #define HB_OT_TAG_CBDT HB_TAG('C','B','D','T') |
|
42 |
|
43 |
32 namespace OT { |
44 namespace OT { |
33 |
45 |
34 struct SmallGlyphMetrics |
46 struct SmallGlyphMetrics |
35 { |
47 { |
36 inline bool sanitize (hb_sanitize_context_t *c) const |
48 inline bool sanitize (hb_sanitize_context_t *c) const |
45 extents->y_bearing = bearingY; |
57 extents->y_bearing = bearingY; |
46 extents->width = width; |
58 extents->width = width; |
47 extents->height = -height; |
59 extents->height = -height; |
48 } |
60 } |
49 |
61 |
50 HBUINT8 height; |
62 HBUINT8 height; |
51 HBUINT8 width; |
63 HBUINT8 width; |
52 HBINT8 bearingX; |
64 HBINT8 bearingX; |
53 HBINT8 bearingY; |
65 HBINT8 bearingY; |
54 HBUINT8 advance; |
66 HBUINT8 advance; |
55 |
67 public: |
56 DEFINE_SIZE_STATIC(5); |
68 DEFINE_SIZE_STATIC(5); |
57 }; |
69 }; |
58 |
70 |
59 struct BigGlyphMetrics : SmallGlyphMetrics |
71 struct BigGlyphMetrics : SmallGlyphMetrics |
60 { |
72 { |
61 HBINT8 vertBearingX; |
73 HBINT8 vertBearingX; |
62 HBINT8 vertBearingY; |
74 HBINT8 vertBearingY; |
63 HBUINT8 vertAdvance; |
75 HBUINT8 vertAdvance; |
64 |
76 public: |
65 DEFINE_SIZE_STATIC(8); |
77 DEFINE_SIZE_STATIC(8); |
66 }; |
78 }; |
67 |
79 |
68 struct SBitLineMetrics |
80 struct SBitLineMetrics |
69 { |
81 { |
71 { |
83 { |
72 TRACE_SANITIZE (this); |
84 TRACE_SANITIZE (this); |
73 return_trace (c->check_struct (this)); |
85 return_trace (c->check_struct (this)); |
74 } |
86 } |
75 |
87 |
76 HBINT8 ascender; |
88 HBINT8 ascender; |
77 HBINT8 decender; |
89 HBINT8 decender; |
78 HBUINT8 widthMax; |
90 HBUINT8 widthMax; |
79 HBINT8 caretSlopeNumerator; |
91 HBINT8 caretSlopeNumerator; |
80 HBINT8 caretSlopeDenominator; |
92 HBINT8 caretSlopeDenominator; |
81 HBINT8 caretOffset; |
93 HBINT8 caretOffset; |
82 HBINT8 minOriginSB; |
94 HBINT8 minOriginSB; |
83 HBINT8 minAdvanceSB; |
95 HBINT8 minAdvanceSB; |
84 HBINT8 maxBeforeBL; |
96 HBINT8 maxBeforeBL; |
85 HBINT8 minAfterBL; |
97 HBINT8 minAfterBL; |
86 HBINT8 padding1; |
98 HBINT8 padding1; |
87 HBINT8 padding2; |
99 HBINT8 padding2; |
88 |
100 public: |
89 DEFINE_SIZE_STATIC(12); |
101 DEFINE_SIZE_STATIC(12); |
90 }; |
102 }; |
91 |
103 |
92 |
104 |
93 /* |
105 /* |
100 { |
112 { |
101 TRACE_SANITIZE (this); |
113 TRACE_SANITIZE (this); |
102 return_trace (c->check_struct (this)); |
114 return_trace (c->check_struct (this)); |
103 } |
115 } |
104 |
116 |
105 HBUINT16 indexFormat; |
117 HBUINT16 indexFormat; |
106 HBUINT16 imageFormat; |
118 HBUINT16 imageFormat; |
107 HBUINT32 imageDataOffset; |
119 HBUINT32 imageDataOffset; |
108 |
120 public: |
109 DEFINE_SIZE_STATIC(8); |
121 DEFINE_SIZE_STATIC(8); |
110 }; |
122 }; |
111 |
123 |
112 template <typename OffsetType> |
124 template <typename OffsetType> |
113 struct IndexSubtableFormat1Or3 |
125 struct IndexSubtableFormat1Or3 |
129 *offset = header.imageDataOffset + offsetArrayZ[idx]; |
141 *offset = header.imageDataOffset + offsetArrayZ[idx]; |
130 *length = offsetArrayZ[idx + 1] - offsetArrayZ[idx]; |
142 *length = offsetArrayZ[idx + 1] - offsetArrayZ[idx]; |
131 return true; |
143 return true; |
132 } |
144 } |
133 |
145 |
134 IndexSubtableHeader header; |
146 IndexSubtableHeader header; |
135 Offset<OffsetType> offsetArrayZ[VAR]; |
147 Offset<OffsetType> offsetArrayZ[VAR]; |
136 |
148 public: |
137 DEFINE_SIZE_ARRAY(8, offsetArrayZ); |
149 DEFINE_SIZE_ARRAY(8, offsetArrayZ); |
138 }; |
150 }; |
139 |
151 |
140 struct IndexSubtableFormat1 : IndexSubtableFormat1Or3<HBUINT32> {}; |
152 struct IndexSubtableFormat1 : IndexSubtableFormat1Or3<HBUINT32> {}; |
141 struct IndexSubtableFormat3 : IndexSubtableFormat1Or3<HBUINT16> {}; |
153 struct IndexSubtableFormat3 : IndexSubtableFormat1Or3<HBUINT16> {}; |
212 } |
224 } |
213 return (this+offsetToSubtable).get_image_data (gid - firstGlyphIndex, |
225 return (this+offsetToSubtable).get_image_data (gid - firstGlyphIndex, |
214 offset, length, format); |
226 offset, length, format); |
215 } |
227 } |
216 |
228 |
217 HBUINT16 firstGlyphIndex; |
229 GlyphID firstGlyphIndex; |
218 HBUINT16 lastGlyphIndex; |
230 GlyphID lastGlyphIndex; |
219 LOffsetTo<IndexSubtable> offsetToSubtable; |
231 LOffsetTo<IndexSubtable> offsetToSubtable; |
220 |
232 public: |
221 DEFINE_SIZE_STATIC(8); |
233 DEFINE_SIZE_STATIC(8); |
222 }; |
234 }; |
223 |
235 |
224 struct IndexSubtableArray |
236 struct IndexSubtableArray |
225 { |
237 { |
|
238 friend struct CBDT; |
|
239 |
226 inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const |
240 inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const |
227 { |
241 { |
228 TRACE_SANITIZE (this); |
242 TRACE_SANITIZE (this); |
229 if (unlikely (!c->check_array (&indexSubtablesZ, indexSubtablesZ[0].static_size, count))) |
243 if (unlikely (!c->check_array (&indexSubtablesZ, indexSubtablesZ[0].static_size, count))) |
230 return_trace (false); |
244 return_trace (false); |
247 } |
261 } |
248 return nullptr; |
262 return nullptr; |
249 } |
263 } |
250 |
264 |
251 protected: |
265 protected: |
252 IndexSubtableRecord indexSubtablesZ[VAR]; |
266 IndexSubtableRecord indexSubtablesZ[VAR]; |
253 |
|
254 public: |
267 public: |
255 DEFINE_SIZE_ARRAY(0, indexSubtablesZ); |
268 DEFINE_SIZE_ARRAY(0, indexSubtablesZ); |
256 }; |
269 }; |
257 |
270 |
258 struct BitmapSizeTable |
271 struct BitmapSizeTable |
259 { |
272 { |
260 friend struct CBLC; |
273 friend struct CBLC; |
|
274 friend struct CBDT; |
261 |
275 |
262 inline bool sanitize (hb_sanitize_context_t *c, const void *base) const |
276 inline bool sanitize (hb_sanitize_context_t *c, const void *base) const |
263 { |
277 { |
264 TRACE_SANITIZE (this); |
278 TRACE_SANITIZE (this); |
265 return_trace (c->check_struct (this) && |
279 return_trace (c->check_struct (this) && |
273 { |
287 { |
274 return (base+indexSubtableArrayOffset).find_table (glyph, numberOfIndexSubtables); |
288 return (base+indexSubtableArrayOffset).find_table (glyph, numberOfIndexSubtables); |
275 } |
289 } |
276 |
290 |
277 protected: |
291 protected: |
278 LOffsetTo<IndexSubtableArray> indexSubtableArrayOffset; |
292 LOffsetTo<IndexSubtableArray> |
279 HBUINT32 indexTablesSize; |
293 indexSubtableArrayOffset; |
280 HBUINT32 numberOfIndexSubtables; |
294 HBUINT32 indexTablesSize; |
281 HBUINT32 colorRef; |
295 HBUINT32 numberOfIndexSubtables; |
282 SBitLineMetrics horizontal; |
296 HBUINT32 colorRef; |
283 SBitLineMetrics vertical; |
297 SBitLineMetrics horizontal; |
284 HBUINT16 startGlyphIndex; |
298 SBitLineMetrics vertical; |
285 HBUINT16 endGlyphIndex; |
299 GlyphID startGlyphIndex; |
286 HBUINT8 ppemX; |
300 GlyphID endGlyphIndex; |
287 HBUINT8 ppemY; |
301 HBUINT8 ppemX; |
288 HBUINT8 bitDepth; |
302 HBUINT8 ppemY; |
289 HBINT8 flags; |
303 HBUINT8 bitDepth; |
290 |
304 HBINT8 flags; |
291 public: |
305 public: |
292 DEFINE_SIZE_STATIC(48); |
306 DEFINE_SIZE_STATIC(48); |
293 }; |
307 }; |
294 |
308 |
295 |
309 |
297 * Glyph Bitmap Data Formats. |
311 * Glyph Bitmap Data Formats. |
298 */ |
312 */ |
299 |
313 |
300 struct GlyphBitmapDataFormat17 |
314 struct GlyphBitmapDataFormat17 |
301 { |
315 { |
302 SmallGlyphMetrics glyphMetrics; |
316 SmallGlyphMetrics glyphMetrics; |
303 HBUINT32 dataLen; |
317 LArrayOf<HBUINT8> data; |
304 HBUINT8 dataZ[VAR]; |
318 public: |
305 |
319 DEFINE_SIZE_ARRAY(9, data); |
306 DEFINE_SIZE_ARRAY(9, dataZ); |
320 }; |
307 }; |
321 |
308 |
322 struct GlyphBitmapDataFormat18 |
309 |
323 { |
310 /* |
324 BigGlyphMetrics glyphMetrics; |
311 * CBLC -- Color Bitmap Location Table |
325 LArrayOf<HBUINT8> data; |
312 */ |
326 public: |
313 |
327 DEFINE_SIZE_ARRAY(12, data); |
314 #define HB_OT_TAG_CBLC HB_TAG('C','B','L','C') |
328 }; |
|
329 |
|
330 struct GlyphBitmapDataFormat19 |
|
331 { |
|
332 LArrayOf<HBUINT8> data; |
|
333 public: |
|
334 DEFINE_SIZE_ARRAY(4, data); |
|
335 }; |
315 |
336 |
316 struct CBLC |
337 struct CBLC |
317 { |
338 { |
318 friend struct CBDT; |
339 friend struct CBDT; |
319 |
340 |
334 /* TODO: Make it possible to select strike. */ |
355 /* TODO: Make it possible to select strike. */ |
335 |
356 |
336 unsigned int count = sizeTables.len; |
357 unsigned int count = sizeTables.len; |
337 for (uint32_t i = 0; i < count; ++i) |
358 for (uint32_t i = 0; i < count; ++i) |
338 { |
359 { |
339 unsigned int startGlyphIndex = sizeTables.array[i].startGlyphIndex; |
360 unsigned int startGlyphIndex = sizeTables.arrayZ[i].startGlyphIndex; |
340 unsigned int endGlyphIndex = sizeTables.array[i].endGlyphIndex; |
361 unsigned int endGlyphIndex = sizeTables.arrayZ[i].endGlyphIndex; |
341 if (startGlyphIndex <= glyph && glyph <= endGlyphIndex) |
362 if (startGlyphIndex <= glyph && glyph <= endGlyphIndex) |
342 { |
363 { |
343 *x_ppem = sizeTables[i].ppemX; |
364 *x_ppem = sizeTables[i].ppemX; |
344 *y_ppem = sizeTables[i].ppemY; |
365 *y_ppem = sizeTables[i].ppemY; |
345 return sizeTables[i].find_table (glyph, this); |
366 return sizeTables[i].find_table (glyph, this); |
350 } |
371 } |
351 |
372 |
352 protected: |
373 protected: |
353 FixedVersion<> version; |
374 FixedVersion<> version; |
354 LArrayOf<BitmapSizeTable> sizeTables; |
375 LArrayOf<BitmapSizeTable> sizeTables; |
355 |
|
356 public: |
376 public: |
357 DEFINE_SIZE_ARRAY(8, sizeTables); |
377 DEFINE_SIZE_ARRAY(8, sizeTables); |
358 }; |
378 }; |
359 |
|
360 /* |
|
361 * CBDT -- Color Bitmap Data Table |
|
362 */ |
|
363 #define HB_OT_TAG_CBDT HB_TAG('C','B','D','T') |
|
364 |
379 |
365 struct CBDT |
380 struct CBDT |
366 { |
381 { |
367 static const hb_tag_t tableTag = HB_OT_TAG_CBDT; |
382 static const hb_tag_t tableTag = HB_OT_TAG_CBDT; |
368 |
383 |
386 if (hb_blob_get_length (cblc_blob) == 0) { |
401 if (hb_blob_get_length (cblc_blob) == 0) { |
387 cblc = nullptr; |
402 cblc = nullptr; |
388 cbdt = nullptr; |
403 cbdt = nullptr; |
389 return; /* Not a bitmap font. */ |
404 return; /* Not a bitmap font. */ |
390 } |
405 } |
391 cblc = Sanitizer<CBLC>::lock_instance (cblc_blob); |
406 cblc = cblc_blob->as<CBLC> (); |
392 cbdt = Sanitizer<CBDT>::lock_instance (cbdt_blob); |
407 cbdt = cbdt_blob->as<CBDT> (); |
393 |
408 |
394 } |
409 } |
395 |
410 |
396 inline void fini (void) |
411 inline void fini (void) |
397 { |
412 { |
445 extents->height *= upem / (float) y_ppem; |
460 extents->height *= upem / (float) y_ppem; |
446 |
461 |
447 return true; |
462 return true; |
448 } |
463 } |
449 |
464 |
|
465 inline void dump (void (*callback) (const uint8_t* data, unsigned int length, |
|
466 unsigned int group, unsigned int gid)) const |
|
467 { |
|
468 if (!cblc) |
|
469 return; // Not a color bitmap font. |
|
470 |
|
471 for (unsigned int i = 0; i < cblc->sizeTables.len; ++i) |
|
472 { |
|
473 const BitmapSizeTable &sizeTable = cblc->sizeTables[i]; |
|
474 const IndexSubtableArray &subtable_array = cblc+sizeTable.indexSubtableArrayOffset; |
|
475 for (unsigned int j = 0; j < sizeTable.numberOfIndexSubtables; ++j) |
|
476 { |
|
477 const IndexSubtableRecord &subtable_record = subtable_array.indexSubtablesZ[j]; |
|
478 for (unsigned int gid = subtable_record.firstGlyphIndex; |
|
479 gid <= subtable_record.lastGlyphIndex; ++gid) |
|
480 { |
|
481 unsigned int image_offset = 0, image_length = 0, image_format = 0; |
|
482 |
|
483 if (!subtable_record.get_image_data (gid, |
|
484 &image_offset, &image_length, &image_format)) |
|
485 continue; |
|
486 |
|
487 switch (image_format) |
|
488 { |
|
489 case 17: { |
|
490 const GlyphBitmapDataFormat17& glyphFormat17 = |
|
491 StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset); |
|
492 callback ((const uint8_t *) &glyphFormat17.data.arrayZ, |
|
493 glyphFormat17.data.len, i, gid); |
|
494 } |
|
495 break; |
|
496 case 18: { |
|
497 const GlyphBitmapDataFormat18& glyphFormat18 = |
|
498 StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset); |
|
499 callback ((const uint8_t *) &glyphFormat18.data.arrayZ, |
|
500 glyphFormat18.data.len, i, gid); |
|
501 } |
|
502 break; |
|
503 case 19: { |
|
504 const GlyphBitmapDataFormat19& glyphFormat19 = |
|
505 StructAtOffset<GlyphBitmapDataFormat19> (this->cbdt, image_offset); |
|
506 callback ((const uint8_t *) &glyphFormat19.data.arrayZ, |
|
507 glyphFormat19.data.len, i, gid); |
|
508 } |
|
509 break; |
|
510 default: |
|
511 continue; |
|
512 } |
|
513 } |
|
514 } |
|
515 } |
|
516 } |
|
517 |
450 private: |
518 private: |
451 hb_blob_t *cblc_blob; |
519 hb_blob_t *cblc_blob; |
452 hb_blob_t *cbdt_blob; |
520 hb_blob_t *cbdt_blob; |
453 const CBLC *cblc; |
521 const CBLC *cblc; |
454 const CBDT *cbdt; |
522 const CBDT *cbdt; |