QtBase  v6.3.1
hb-ot-color-cbdt-table.hh
Go to the documentation of this file.
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, Calder Kitagawa
25  */
26 
27 #ifndef HB_OT_COLOR_CBDT_TABLE_HH
28 #define HB_OT_COLOR_CBDT_TABLE_HH
29 
30 #include "hb-open-type.hh"
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 
44 namespace OT {
45 
47 {
48  const char *cbdt;
49  unsigned int cbdt_length;
51  unsigned int size; /* INOUT
52  * Input: old size of IndexSubtable
53  * Output: new size of IndexSubtable
54  */
55  unsigned int num_tables; /* INOUT
56  * Input: old number of subtables.
57  * Output: new number of subtables.
58  */
61 };
62 
63 static inline bool
64 _copy_data_to_cbdt (hb_vector_t<char> *cbdt_prime,
65  const void *data,
66  unsigned length)
67 {
68  unsigned int new_len = cbdt_prime->length + length;
69  if (unlikely (!cbdt_prime->alloc (new_len))) return false;
70  memcpy (cbdt_prime->arrayZ + cbdt_prime->length, data, length);
71  cbdt_prime->length = new_len;
72  return true;
73 }
74 
76 {
78  {
79  TRACE_SANITIZE (this);
80  return_trace (c->check_struct (this));
81  }
82 
83  void get_extents (hb_font_t *font, hb_glyph_extents_t *extents) const
84  {
85  extents->x_bearing = font->em_scale_x (bearingX);
86  extents->y_bearing = font->em_scale_y (bearingY);
87  extents->width = font->em_scale_x (width);
88  extents->height = font->em_scale_y (-static_cast<int>(height));
89  }
90 
96  public:
98 };
99 
101 {
105  public:
107 };
108 
110 {
112  {
113  TRACE_SANITIZE (this);
114  return_trace (c->check_struct (this));
115  }
116 
129  public:
131 };
132 
133 
134 /*
135  * Index Subtables.
136  */
137 
139 {
141  {
142  TRACE_SANITIZE (this);
143  return_trace (c->check_struct (this));
144  }
145 
149  public:
151 };
152 
153 template <typename OffsetType>
155 {
156  bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
157  {
158  TRACE_SANITIZE (this);
159  return_trace (c->check_struct (this) &&
160  offsetArrayZ.sanitize (c, glyph_count + 1));
161  }
162 
163  bool get_image_data (unsigned int idx,
164  unsigned int *offset,
165  unsigned int *length) const
166  {
167  if (unlikely (offsetArrayZ[idx + 1] <= offsetArrayZ[idx]))
168  return false;
169 
172  return true;
173  }
174 
176  unsigned int offset,
177  unsigned int *size /* OUT (accumulated) */)
178  {
179  TRACE_SERIALIZE (this);
180  Offset<OffsetType> embedded_offset;
181  embedded_offset = offset;
182  *size += sizeof (OffsetType);
183  auto *o = c->embed (embedded_offset);
184  return_trace ((bool) o);
185  }
186 
190  public:
192 };
193 
196 
198 {
199  bool sanitize (hb_sanitize_context_t *c, unsigned int glyph_count) const
200  {
201  TRACE_SANITIZE (this);
202  if (!u.header.sanitize (c)) return_trace (false);
203  switch (u.header.indexFormat)
204  {
205  case 1: return_trace (u.format1.sanitize (c, glyph_count));
206  case 3: return_trace (u.format3.sanitize (c, glyph_count));
207  default:return_trace (true);
208  }
209  }
210 
211  bool
213  unsigned int cbdt_prime_len,
214  unsigned int num_glyphs,
215  unsigned int *size /* OUT (accumulated) */)
216  {
217  TRACE_SERIALIZE (this);
218 
219  unsigned int local_offset = cbdt_prime_len - u.header.imageDataOffset;
220  switch (u.header.indexFormat)
221  {
222  case 1: return_trace (u.format1.add_offset (c, local_offset, size));
223  case 3: {
224  if (!u.format3.add_offset (c, local_offset, size))
225  return_trace (false);
226  if (!(num_glyphs & 0x01)) // Pad to 32-bit alignment if needed.
227  return_trace (u.format3.add_offset (c, 0, size));
228  return_trace (true);
229  }
230  // TODO: implement 2, 4, 5.
231  case 2: case 4: // No-op.
232  case 5: // Pad to 32-bit aligned.
233  default: return_trace (false);
234  }
235  }
236 
237  bool
239  unsigned int cbdt_prime_len,
240  unsigned int num_missing,
241  unsigned int *size /* OUT (accumulated) */,
242  unsigned int *num_glyphs /* OUT (accumulated) */)
243  {
244  TRACE_SERIALIZE (this);
245 
246  unsigned int local_offset = cbdt_prime_len - u.header.imageDataOffset;
247  switch (u.header.indexFormat)
248  {
249  case 1: {
250  for (unsigned int i = 0; i < num_missing; i++)
251  {
252  if (unlikely (!u.format1.add_offset (c, local_offset, size)))
253  return_trace (false);
254  *num_glyphs += 1;
255  }
256  return_trace (true);
257  }
258  case 3: {
259  for (unsigned int i = 0; i < num_missing; i++)
260  {
261  if (unlikely (!u.format3.add_offset (c, local_offset, size)))
262  return_trace (false);
263  *num_glyphs += 1;
264  }
265  return_trace (true);
266  }
267  // TODO: implement 2, 4, 5.
268  case 2: // Add empty space in cbdt_prime?.
269  case 4: case 5: // No-op as sparse is supported.
270  default: return_trace (false);
271  }
272  }
273 
274  bool
276  const char *cbdt, unsigned int cbdt_length,
277  hb_vector_t<char> *cbdt_prime /* INOUT */,
278  IndexSubtable *subtable_prime /* INOUT */,
279  unsigned int *size /* OUT (accumulated) */) const
280  {
281  TRACE_SERIALIZE (this);
282 
283  unsigned int offset, length, format;
284  if (unlikely (!get_image_data (idx, &offset, &length, &format))) return_trace (false);
285  if (unlikely (offset > cbdt_length || cbdt_length - offset < length)) return_trace (false);
286 
287  auto *header_prime = subtable_prime->get_header ();
288  unsigned int new_local_offset = cbdt_prime->length - (unsigned int) header_prime->imageDataOffset;
289  if (unlikely (!_copy_data_to_cbdt (cbdt_prime, cbdt + offset, length))) return_trace (false);
290 
291  return_trace (subtable_prime->add_offset (c, new_local_offset, size));
292  }
293 
294  bool
295  add_offset (hb_serialize_context_t *c, unsigned int local_offset,
296  unsigned int *size /* OUT (accumulated) */)
297  {
298  TRACE_SERIALIZE (this);
299  switch (u.header.indexFormat)
300  {
301  case 1: return_trace (u.format1.add_offset (c, local_offset, size));
302  case 3: return_trace (u.format3.add_offset (c, local_offset, size));
303  // TODO: Implement tables 2, 4, 5
304  case 2: // Should be a no-op.
305  case 4: case 5: // Handle sparse cases.
306  default: return_trace (false);
307  }
308  }
309 
311  {
312  switch (u.header.indexFormat)
313  {
314  case 2: case 5: /* TODO */
315  case 1: case 3: case 4: /* Variable-metrics formats do not have metrics here. */
316  default:return (false);
317  }
318  }
319 
320  bool
321  get_image_data (unsigned int idx, unsigned int *offset,
322  unsigned int *length, unsigned int *format) const
323  {
324  *format = u.header.imageFormat;
325  switch (u.header.indexFormat)
326  {
327  case 1: return u.format1.get_image_data (idx, offset, length);
328  case 3: return u.format3.get_image_data (idx, offset, length);
329  default: return false;
330  }
331  }
332 
333  const IndexSubtableHeader* get_header () const { return &u.header; }
334 
335  void populate_header (unsigned index_format,
336  unsigned image_format,
337  unsigned int image_data_offset,
338  unsigned int *size)
339  {
340  u.header.indexFormat = index_format;
341  u.header.imageFormat = image_format;
342  u.header.imageDataOffset = image_data_offset;
343  switch (u.header.indexFormat)
344  {
345  case 1: *size += IndexSubtableFormat1::min_size; break;
346  case 3: *size += IndexSubtableFormat3::min_size; break;
347  }
348  }
349 
350  protected:
351  union {
355  /* TODO: Format 2, 4, 5. */
356  } u;
357  public:
359 };
360 
362 {
363  /* XXX Remove this and fix by not inserting it into vector. */
365  {
366  firstGlyphIndex = o.firstGlyphIndex;
367  lastGlyphIndex = o.lastGlyphIndex;
368  offsetToSubtable = (unsigned) o.offsetToSubtable;
369  assert (offsetToSubtable.is_null ());
370  return *this;
371  }
372 
373  bool sanitize (hb_sanitize_context_t *c, const void *base) const
374  {
375  TRACE_SANITIZE (this);
376  return_trace (c->check_struct (this) &&
379  }
380 
381  const IndexSubtable* get_subtable (const void *base) const
382  {
383  return &(base+offsetToSubtable);
384  }
385 
387  cblc_bitmap_size_subset_context_t *bitmap_size_context,
390  const void *base,
391  unsigned int *start /* INOUT */) const
392  {
393  TRACE_SERIALIZE (this);
394 
395  auto *subtable = c->serializer->start_embed<IndexSubtable> ();
396  if (unlikely (!subtable)) return_trace (false);
397  if (unlikely (!c->serializer->extend_min (subtable))) return_trace (false);
398 
399  auto *old_subtable = get_subtable (base);
400  auto *old_header = old_subtable->get_header ();
401 
402  subtable->populate_header (old_header->indexFormat,
403  old_header->imageFormat,
404  bitmap_size_context->cbdt_prime->length,
405  &bitmap_size_context->size);
406 
407  unsigned int num_glyphs = 0;
408  bool early_exit = false;
409  for (unsigned int i = *start; i < lookup->length; i++)
410  {
411  hb_codepoint_t new_gid = (*lookup)[i].first;
412  const IndexSubtableRecord *next_record = (*lookup)[i].second;
413  const IndexSubtable *next_subtable = next_record->get_subtable (base);
414  auto *next_header = next_subtable->get_header ();
415  if (next_header != old_header)
416  {
417  *start = i;
418  early_exit = true;
419  break;
420  }
421  unsigned int num_missing = record->add_glyph_for_subset (new_gid);
422  if (unlikely (!subtable->fill_missing_glyphs (c->serializer,
423  bitmap_size_context->cbdt_prime->length,
424  num_missing,
425  &bitmap_size_context->size,
426  &num_glyphs)))
427  return_trace (false);
428 
429  hb_codepoint_t old_gid = 0;
430  c->plan->old_gid_for_new_gid (new_gid, &old_gid);
431  if (old_gid < next_record->firstGlyphIndex)
432  return_trace (false);
433 
434  unsigned int old_idx = (unsigned int) old_gid - next_record->firstGlyphIndex;
435  if (unlikely (!next_subtable->copy_glyph_at_idx (c->serializer,
436  old_idx,
437  bitmap_size_context->cbdt,
438  bitmap_size_context->cbdt_length,
439  bitmap_size_context->cbdt_prime,
440  subtable,
441  &bitmap_size_context->size)))
442  return_trace (false);
443  num_glyphs += 1;
444  }
445  if (!early_exit)
446  *start = lookup->length;
447  if (unlikely (!subtable->finish_subtable (c->serializer,
448  bitmap_size_context->cbdt_prime->length,
449  num_glyphs,
450  &bitmap_size_context->size)))
451  return_trace (false);
452  return_trace (true);
453  }
454 
456  cblc_bitmap_size_subset_context_t *bitmap_size_context,
458  const void *base,
459  unsigned int *start, /* INOUT */
460  hb_vector_t<IndexSubtableRecord>* records /* INOUT */) const
461  {
462  TRACE_SERIALIZE (this);
463  auto snap = c->serializer->snapshot ();
464  unsigned int old_size = bitmap_size_context->size;
465  unsigned int old_cbdt_prime_length = bitmap_size_context->cbdt_prime->length;
466 
467  // Set to invalid state to indicate filling glyphs is not yet started.
468  if (unlikely (!c->serializer->check_success (records->resize (records->length + 1))))
469  return_trace (false);
470 
471  (*records)[records->length - 1].firstGlyphIndex = 1;
472  (*records)[records->length - 1].lastGlyphIndex = 0;
473  bitmap_size_context->size += IndexSubtableRecord::min_size;
474 
475  c->serializer->push ();
476 
477  if (unlikely (!add_new_subtable (c, bitmap_size_context, &((*records)[records->length - 1]), lookup, base, start)))
478  {
479  c->serializer->pop_discard ();
480  c->serializer->revert (snap);
481  bitmap_size_context->cbdt_prime->shrink (old_cbdt_prime_length);
482  bitmap_size_context->size = old_size;
483  records->resize (records->length - 1);
484  return_trace (false);
485  }
486 
487  bitmap_size_context->num_tables += 1;
488  return_trace (true);
489  }
490 
492  {
494  {
495  firstGlyphIndex = gid;
496  lastGlyphIndex = gid;
497  return 0;
498  }
499  // TODO maybe assert? this shouldn't occur.
500  if (lastGlyphIndex > gid)
501  return 0;
502  unsigned int num_missing = (unsigned int) (gid - lastGlyphIndex - 1);
503  lastGlyphIndex = gid;
504  return num_missing;
505  }
506 
507  bool get_extents (hb_glyph_extents_t *extents, const void *base) const
508  { return (base+offsetToSubtable).get_extents (extents); }
509 
510  bool get_image_data (unsigned int gid,
511  const void *base,
512  unsigned int *offset,
513  unsigned int *length,
514  unsigned int *format) const
515  {
516  if (gid < firstGlyphIndex || gid > lastGlyphIndex) return false;
517  return (base+offsetToSubtable).get_image_data (gid - firstGlyphIndex,
518  offset, length, format);
519  }
520 
524  public:
526 };
527 
529 {
530  friend struct CBDT;
531 
532  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
533  {
534  TRACE_SANITIZE (this);
535  return_trace (indexSubtablesZ.sanitize (c, count, this));
536  }
537 
538  void
541  const IndexSubtableRecord*>> *lookup /* OUT */) const
542  {
543  bool start_glyph_is_set = false;
544  for (hb_codepoint_t new_gid = 0; new_gid < c->plan->num_output_glyphs (); new_gid++)
545  {
546  hb_codepoint_t old_gid;
547  if (unlikely (!c->plan->old_gid_for_new_gid (new_gid, &old_gid))) continue;
548 
549  const IndexSubtableRecord* record = find_table (old_gid, bitmap_size_context->num_tables);
550  if (unlikely (!record)) continue;
551 
552  // Don't add gaps to the lookup. The best way to determine if a glyph is a
553  // gap is that it has no image data.
554  unsigned int offset, length, format;
555  if (unlikely (!record->get_image_data (old_gid, this, &offset, &length, &format))) continue;
556 
558 
559  if (!start_glyph_is_set)
560  {
561  bitmap_size_context->start_glyph = new_gid;
562  start_glyph_is_set = true;
563  }
564 
565  bitmap_size_context->end_glyph = new_gid;
566  }
567  }
568 
569  bool
571  cblc_bitmap_size_subset_context_t *bitmap_size_context) const
572  {
573  TRACE_SUBSET (this);
574 
575  auto *dst = c->serializer->start_embed<IndexSubtableArray> ();
576  if (unlikely (!dst)) return_trace (false);
577 
579  build_lookup (c, bitmap_size_context, &lookup);
580  if (unlikely (!c->serializer->propagate_error (lookup)))
581  return false;
582 
583  bitmap_size_context->size = 0;
584  bitmap_size_context->num_tables = 0;
586  for (unsigned int start = 0; start < lookup.length;)
587  {
588  if (unlikely (!lookup[start].second->add_new_record (c, bitmap_size_context, &lookup, this, &start, &records)))
589  {
590  // Discard any leftover pushes to the serializer from successful records.
591  for (unsigned int i = 0; i < records.length; i++)
592  c->serializer->pop_discard ();
593  return_trace (false);
594  }
595  }
596 
597  /* Workaround to ensure offset ordering is from least to greatest when
598  * resolving links. */
600  for (unsigned int i = 0; i < records.length; i++)
601  objidxs.push (c->serializer->pop_pack ());
602  for (unsigned int i = 0; i < records.length; i++)
603  {
604  IndexSubtableRecord* record = c->serializer->embed (records[i]);
605  if (unlikely (!record)) return_trace (false);
606  c->serializer->add_link (record->offsetToSubtable, objidxs[records.length - 1 - i]);
607  }
608  return_trace (true);
609  }
610 
611  public:
612  const IndexSubtableRecord* find_table (hb_codepoint_t glyph, unsigned int numTables) const
613  {
614  for (unsigned int i = 0; i < numTables; ++i)
615  {
616  unsigned int firstGlyphIndex = indexSubtablesZ[i].firstGlyphIndex;
617  unsigned int lastGlyphIndex = indexSubtablesZ[i].lastGlyphIndex;
618  if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex)
619  return &indexSubtablesZ[i];
620  }
621  return nullptr;
622  }
623 
624  protected:
626 };
627 
629 {
630  friend struct CBLC;
631  friend struct CBDT;
632 
633  bool sanitize (hb_sanitize_context_t *c, const void *base) const
634  {
635  TRACE_SANITIZE (this);
636  return_trace (c->check_struct (this) &&
638  horizontal.sanitize (c) &&
639  vertical.sanitize (c));
640  }
641 
642  const IndexSubtableRecord *
643  find_table (hb_codepoint_t glyph, const void *base, const void **out_base) const
644  {
645  *out_base = &(base+indexSubtableArrayOffset);
646  return (base+indexSubtableArrayOffset).find_table (glyph, numberOfIndexSubtables);
647  }
648 
649  bool
651  const char *cbdt, unsigned int cbdt_length,
652  hb_vector_t<char> *cbdt_prime /* INOUT */) const
653  {
654  TRACE_SUBSET (this);
655  auto *out_table = c->serializer->embed (this);
656  if (unlikely (!out_table)) return_trace (false);
657 
658  cblc_bitmap_size_subset_context_t bitmap_size_context;
659  bitmap_size_context.cbdt = cbdt;
660  bitmap_size_context.cbdt_length = cbdt_length;
661  bitmap_size_context.cbdt_prime = cbdt_prime;
662  bitmap_size_context.size = indexTablesSize;
663  bitmap_size_context.num_tables = numberOfIndexSubtables;
664  bitmap_size_context.start_glyph = 1;
665  bitmap_size_context.end_glyph = 0;
666 
667  if (!out_table->indexSubtableArrayOffset.serialize_subset (c,
669  base,
670  &bitmap_size_context))
671  return_trace (false);
672  if (!bitmap_size_context.size ||
673  !bitmap_size_context.num_tables ||
674  bitmap_size_context.start_glyph > bitmap_size_context.end_glyph)
675  return_trace (false);
676 
677  out_table->indexTablesSize = bitmap_size_context.size;
678  out_table->numberOfIndexSubtables = bitmap_size_context.num_tables;
679  out_table->startGlyphIndex = bitmap_size_context.start_glyph;
680  out_table->endGlyphIndex = bitmap_size_context.end_glyph;
681  return_trace (true);
682  }
683 
684  protected:
698  public:
700 };
701 
702 
703 /*
704  * Glyph Bitmap Data Formats.
705  */
706 
708 {
711  public:
713 };
714 
716 {
719  public:
721 };
722 
724 {
726  public:
728 };
729 
730 struct CBLC
731 {
732  friend struct CBDT;
733 
734  static constexpr hb_tag_t tableTag = HB_OT_TAG_CBLC;
735 
737  {
738  TRACE_SANITIZE (this);
739  return_trace (c->check_struct (this) &&
740  likely (version.major == 2 || version.major == 3) &&
741  sizeTables.sanitize (c, this));
742  }
743 
744  static bool
746  {
747  hb_blob_t *cbdt_prime_blob = hb_blob_create (cbdt_prime->arrayZ,
748  cbdt_prime->length,
750  cbdt_prime->arrayZ,
751  hb_free);
752  cbdt_prime->init (); // Leak arrayZ to the blob.
753  bool ret = c->plan->add_table (HB_OT_TAG_CBDT, cbdt_prime_blob);
754  hb_blob_destroy (cbdt_prime_blob);
755  return ret;
756  }
757 
758  bool
760  const char *cbdt /* IN */, unsigned int cbdt_length,
761  CBLC *cblc_prime /* INOUT */, hb_vector_t<char> *cbdt_prime /* INOUT */) const
762  {
763  TRACE_SUBSET (this);
764  cblc_prime->sizeTables.len++;
765 
766  auto snap = c->serializer->snapshot ();
767  auto cbdt_prime_len = cbdt_prime->length;
768 
769  if (!table.subset (c, this, cbdt, cbdt_length, cbdt_prime))
770  {
771  cblc_prime->sizeTables.len--;
772  c->serializer->revert (snap);
773  cbdt_prime->shrink (cbdt_prime_len);
774  return_trace (false);
775  }
776  return_trace (true);
777  }
778 
779  // Implemented in cc file as it depends on definition of CBDT.
780  HB_INTERNAL bool subset (hb_subset_context_t *c) const;
781 
782  protected:
784  {
785  unsigned count = sizeTables.len;
786  if (unlikely (!count))
787  return Null (BitmapSizeTable);
788 
789  unsigned int requested_ppem = hb_max (font->x_ppem, font->y_ppem);
790  if (!requested_ppem)
791  requested_ppem = 1<<30; /* Choose largest strike. */
792  unsigned int best_i = 0;
793  unsigned int best_ppem = hb_max (sizeTables[0].ppemX, sizeTables[0].ppemY);
794 
795  for (unsigned int i = 1; i < count; i++)
796  {
797  unsigned int ppem = hb_max (sizeTables[i].ppemX, sizeTables[i].ppemY);
798  if ((requested_ppem <= ppem && ppem < best_ppem) ||
799  (requested_ppem > best_ppem && ppem > best_ppem))
800  {
801  best_i = i;
802  best_ppem = ppem;
803  }
804  }
805 
806  return sizeTables[best_i];
807  }
808 
809  protected:
812  public:
814 };
815 
816 struct CBDT
817 {
818  static constexpr hb_tag_t tableTag = HB_OT_TAG_CBDT;
819 
821  {
823  {
824  this->cblc = hb_sanitize_context_t ().reference_table<CBLC> (face);
825  this->cbdt = hb_sanitize_context_t ().reference_table<CBDT> (face);
826 
827  upem = hb_face_get_upem (face);
828  }
830  {
831  this->cblc.destroy ();
832  this->cbdt.destroy ();
833  }
834 
835  bool
837  {
838  const void *base;
839  const BitmapSizeTable &strike = this->cblc->choose_strike (font);
840  const IndexSubtableRecord *subtable_record = strike.find_table (glyph, cblc, &base);
841  if (!subtable_record || !strike.ppemX || !strike.ppemY)
842  return false;
843 
844  if (subtable_record->get_extents (extents, base))
845  return true;
846 
847  unsigned int image_offset = 0, image_length = 0, image_format = 0;
848  if (!subtable_record->get_image_data (glyph, base, &image_offset, &image_length, &image_format))
849  return false;
850 
851  unsigned int cbdt_len = cbdt.get_length ();
852  if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
853  return false;
854 
855  switch (image_format)
856  {
857  case 17: {
858  if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
859  return false;
860  auto &glyphFormat17 = StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
861  glyphFormat17.glyphMetrics.get_extents (font, extents);
862  break;
863  }
864  case 18: {
865  if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
866  return false;
867  auto &glyphFormat18 = StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
868  glyphFormat18.glyphMetrics.get_extents (font, extents);
869  break;
870  }
871  default: return false; /* TODO: Support other image formats. */
872  }
873 
874  /* Convert to font units. */
875  float x_scale = upem / (float) strike.ppemX;
876  float y_scale = upem / (float) strike.ppemY;
877  extents->x_bearing = roundf (extents->x_bearing * x_scale);
878  extents->y_bearing = roundf (extents->y_bearing * y_scale);
879  extents->width = roundf (extents->width * x_scale);
880  extents->height = roundf (extents->height * y_scale);
881 
882  return true;
883  }
884 
885  hb_blob_t*
887  {
888  const void *base;
889  const BitmapSizeTable &strike = this->cblc->choose_strike (font);
890  const IndexSubtableRecord *subtable_record = strike.find_table (glyph, cblc, &base);
891  if (!subtable_record || !strike.ppemX || !strike.ppemY)
892  return hb_blob_get_empty ();
893 
894  unsigned int image_offset = 0, image_length = 0, image_format = 0;
895  if (!subtable_record->get_image_data (glyph, base, &image_offset, &image_length, &image_format))
896  return hb_blob_get_empty ();
897 
898  unsigned int cbdt_len = cbdt.get_length ();
899  if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
900  return hb_blob_get_empty ();
901 
902  switch (image_format)
903  {
904  case 17:
905  {
906  if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
907  return hb_blob_get_empty ();
908  auto &glyphFormat17 = StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
909  return hb_blob_create_sub_blob (cbdt.get_blob (),
910  image_offset + GlyphBitmapDataFormat17::min_size,
911  glyphFormat17.data.len);
912  }
913  case 18:
914  {
915  if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
916  return hb_blob_get_empty ();
917  auto &glyphFormat18 = StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
918  return hb_blob_create_sub_blob (cbdt.get_blob (),
919  image_offset + GlyphBitmapDataFormat18::min_size,
920  glyphFormat18.data.len);
921  }
922  case 19:
923  {
924  if (unlikely (image_length < GlyphBitmapDataFormat19::min_size))
925  return hb_blob_get_empty ();
926  auto &glyphFormat19 = StructAtOffset<GlyphBitmapDataFormat19> (this->cbdt, image_offset);
927  return hb_blob_create_sub_blob (cbdt.get_blob (),
928  image_offset + GlyphBitmapDataFormat19::min_size,
929  glyphFormat19.data.len);
930  }
931  default: return hb_blob_get_empty (); /* TODO: Support other image formats. */
932  }
933  }
934 
935  bool has_data () const { return cbdt.get_length (); }
936 
937  private:
938  hb_blob_ptr_t<CBLC> cblc;
939  hb_blob_ptr_t<CBDT> cbdt;
940 
941  unsigned int upem;
942  };
943 
945  {
946  TRACE_SANITIZE (this);
947  return_trace (c->check_struct (this) &&
948  likely (version.major == 2 || version.major == 3));
949  }
950 
951  protected:
954  public:
956 };
957 
958 inline bool
960 {
961  TRACE_SUBSET (this);
962 
963  auto *cblc_prime = c->serializer->start_embed<CBLC> ();
964 
965  // Use a vector as a secondary buffer as the tables need to be built in parallel.
966  hb_vector_t<char> cbdt_prime;
967 
968  if (unlikely (!cblc_prime)) return_trace (false);
969  if (unlikely (!c->serializer->extend_min (cblc_prime))) return_trace (false);
970  cblc_prime->version = version;
971 
972  hb_blob_t* cbdt_blob = hb_sanitize_context_t ().reference_table<CBDT> (c->plan->source);
973  unsigned int cbdt_length;
974  CBDT* cbdt = (CBDT *) hb_blob_get_data (cbdt_blob, &cbdt_length);
975  if (unlikely (cbdt_length < CBDT::min_size))
976  {
977  hb_blob_destroy (cbdt_blob);
978  return_trace (false);
979  }
980  _copy_data_to_cbdt (&cbdt_prime, cbdt, CBDT::min_size);
981 
982  for (const BitmapSizeTable& table : + sizeTables.iter ())
983  subset_size_table (c, table, (const char *) cbdt, cbdt_length, cblc_prime, &cbdt_prime);
984 
985  hb_blob_destroy (cbdt_blob);
986 
987  return_trace (CBLC::sink_cbdt (c, &cbdt_prime));
988 }
989 
992 };
993 
994 
995 } /* namespace OT */
996 
997 #endif /* HB_OT_COLOR_CBDT_TABLE_HH */
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
FT_UInt idx
Definition: cffcmap.c:135
Definition: base.h:37
#define roundf(x)
Definition: hb-algs.hh:165
hb_blob_t * hb_blob_get_empty()
Definition: hb-blob.cc:226
hb_blob_t * hb_blob_create_sub_blob(hb_blob_t *parent, unsigned int offset, unsigned int length)
Definition: hb-blob.cc:169
const char * hb_blob_get_data(hb_blob_t *blob, unsigned int *length)
Definition: hb-blob.cc:377
hb_blob_t * hb_blob_create(const char *data, unsigned int length, hb_memory_mode_t mode, void *user_data, hb_destroy_func_t destroy)
Definition: hb-blob.cc:69
void hb_blob_destroy(hb_blob_t *blob)
Definition: hb-blob.cc:262
#define TRACE_SERIALIZE(this)
Definition: hb-debug.hh:426
#define TRACE_SANITIZE(this)
Definition: hb-debug.hh:414
#define return_trace(RET)
Definition: hb-debug.hh:349
#define TRACE_SUBSET(this)
Definition: hb-debug.hh:438
void const void *obj HB_UNUSED
Definition: hb-debug.hh:180
unsigned int hb_face_get_upem(const hb_face_t *face)
Definition: hb-face.cc:496
#define HB_OT_TAG_CBDT
#define HB_OT_TAG_CBLC
#define likely(expr)
Definition: hb.hh:250
#define unlikely(expr)
Definition: hb.hh:251
#define HB_INTERNAL
Definition: hb.hh:274
#define hb_free
Definition: hb.hh:238
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
[3]
#define assert
Definition: qcborcommon_p.h:63
GLenum GLuint GLenum GLsizei length
Definition: qopengl.h:270
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei count
GLenum face
GLint GLsizei width
GLenum GLenum dst
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint start
GLenum GLuint GLintptr offset
GLint GLsizei GLsizei GLenum format
GLenum const void GLbitfield GLuint firstGlyphIndex
const GLubyte * c
Definition: qopenglext.h:12701
GLenum GLenum GLsizei void * table
Definition: qopenglext.h:2745
@ HB_MEMORY_MODE_WRITABLE
Definition: hb-blob.h:72
uint32_t hb_codepoint_t
Definition: hb-common.h:106
uint32_t hb_tag_t
Definition: hb-common.h:157
QString base
MyRecord record(int row) const
[0]
bool sanitize(hb_sanitize_context_t *c, const void *base) const
const IndexSubtableRecord * find_table(hb_codepoint_t glyph, const void *base, const void **out_base) const
bool subset(hb_subset_context_t *c, const void *base, const char *cbdt, unsigned int cbdt_length, hb_vector_t< char > *cbdt_prime) const
NNOffset32To< IndexSubtableArray > indexSubtableArrayOffset
bool get_extents(hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
hb_blob_t * reference_png(hb_font_t *font, hb_codepoint_t glyph) const
UnsizedArrayOf< HBUINT8 > dataZ
bool sanitize(hb_sanitize_context_t *c) const
static constexpr hb_tag_t tableTag
FixedVersion version
DEFINE_SIZE_ARRAY(4, dataZ)
bool subset_size_table(hb_subset_context_t *c, const BitmapSizeTable &table, const char *cbdt, unsigned int cbdt_length, CBLC *cblc_prime, hb_vector_t< char > *cbdt_prime) const
static constexpr hb_tag_t tableTag
HB_INTERNAL bool subset(hb_subset_context_t *c) const
FixedVersion version
DEFINE_SIZE_ARRAY(8, sizeTables)
bool sanitize(hb_sanitize_context_t *c) const
Array32Of< BitmapSizeTable > sizeTables
static bool sink_cbdt(hb_subset_context_t *c, hb_vector_t< char > *cbdt_prime)
const BitmapSizeTable & choose_strike(hb_font_t *font) const
bool sanitize(hb_sanitize_context_t *c, unsigned int count) const
const IndexSubtableRecord * find_table(hb_codepoint_t glyph, unsigned int numTables) const
UnsizedArrayOf< IndexSubtableRecord > indexSubtablesZ
bool subset(hb_subset_context_t *c, cblc_bitmap_size_subset_context_t *bitmap_size_context) const
void build_lookup(hb_subset_context_t *c, cblc_bitmap_size_subset_context_t *bitmap_size_context, hb_vector_t< hb_pair_t< hb_codepoint_t, const IndexSubtableRecord * >> *lookup) const
bool add_offset(hb_serialize_context_t *c, unsigned int offset, unsigned int *size)
DEFINE_SIZE_ARRAY(8, offsetArrayZ)
bool sanitize(hb_sanitize_context_t *c, unsigned int glyph_count) const
UnsizedArrayOf< Offset< OffsetType > > offsetArrayZ
bool get_image_data(unsigned int idx, unsigned int *offset, unsigned int *length) const
bool sanitize(hb_sanitize_context_t *c) const
bool get_extents(hb_glyph_extents_t *extents HB_UNUSED) const
void populate_header(unsigned index_format, unsigned image_format, unsigned int image_data_offset, unsigned int *size)
bool add_offset(hb_serialize_context_t *c, unsigned int local_offset, unsigned int *size)
DEFINE_SIZE_UNION(8, header)
bool get_image_data(unsigned int idx, unsigned int *offset, unsigned int *length, unsigned int *format) const
bool sanitize(hb_sanitize_context_t *c, unsigned int glyph_count) const
bool copy_glyph_at_idx(hb_serialize_context_t *c, unsigned int idx, const char *cbdt, unsigned int cbdt_length, hb_vector_t< char > *cbdt_prime, IndexSubtable *subtable_prime, unsigned int *size) const
union OT::IndexSubtable::@150 u
bool fill_missing_glyphs(hb_serialize_context_t *c, unsigned int cbdt_prime_len, unsigned int num_missing, unsigned int *size, unsigned int *num_glyphs)
bool finish_subtable(hb_serialize_context_t *c, unsigned int cbdt_prime_len, unsigned int num_glyphs, unsigned int *size)
const IndexSubtableHeader * get_header() const
IndexSubtableHeader header
IndexSubtableFormat1 format1
IndexSubtableFormat3 format3
Offset32To< IndexSubtable > offsetToSubtable
bool get_extents(hb_glyph_extents_t *extents, const void *base) const
bool sanitize(hb_sanitize_context_t *c, const void *base) const
const IndexSubtable * get_subtable(const void *base) const
IndexSubtableRecord & operator=(const IndexSubtableRecord &o)
bool add_new_subtable(hb_subset_context_t *c, cblc_bitmap_size_subset_context_t *bitmap_size_context, IndexSubtableRecord *record, const hb_vector_t< hb_pair_t< hb_codepoint_t, const IndexSubtableRecord * >> *lookup, const void *base, unsigned int *start) const
unsigned int add_glyph_for_subset(hb_codepoint_t gid)
bool add_new_record(hb_subset_context_t *c, cblc_bitmap_size_subset_context_t *bitmap_size_context, const hb_vector_t< hb_pair_t< hb_codepoint_t, const IndexSubtableRecord * >> *lookup, const void *base, unsigned int *start, hb_vector_t< IndexSubtableRecord > *records) const
bool get_image_data(unsigned int gid, const void *base, unsigned int *offset, unsigned int *length, unsigned int *format) const
bool sanitize(hb_sanitize_context_t *c) const
bool sanitize(hb_sanitize_context_t *c) const
void get_extents(hb_font_t *font, hb_glyph_extents_t *extents) const
hb_position_t x_bearing
Definition: hb-font.h:141
hb_position_t y_bearing
Definition: hb-font.h:142
hb_position_t height
Definition: hb-font.h:144
hb_position_t width
Definition: hb-font.h:143
Type * push()
Definition: hb-vector.hh:183
void init()
Definition: hb-vector.hh:80
Type * arrayZ
Definition: hb-vector.hh:78
unsigned int length
Definition: hb-vector.hh:76
bool alloc(unsigned int size)
Definition: hb-vector.hh:292
bool resize(int size_)
Definition: hb-vector.hh:326
void shrink(int size_)
Definition: hb-vector.hh:359