w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

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 
46 struct cblc_bitmap_size_subset_context_t
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  */
59  hb_codepoint_t start_glyph; /* OUT */
60  hb_codepoint_t end_glyph; /* OUT */
61 };
62 
63 static inline bool
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 
75 struct SmallGlyphMetrics
76 {
78  {
79  TRACE_SANITIZE (this);
80  return_trace (c->check_struct (this));
81  }
82 
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 
92  HBUINT8 width;
96  public:
98 };
99 
101 {
105  public:
107 };
108 
109 struct SBitLineMetrics
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 
138 struct IndexSubtableHeader
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 
170  *offset = header.imageDataOffset + offsetArrayZ[idx];
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 
189  offsetArrayZ;
190  public:
192 };
193 
194 struct IndexSubtableFormat1 : IndexSubtableFormat1Or3<HBUINT32> {};
195 struct IndexSubtableFormat3 : IndexSubtableFormat1Or3<HBUINT16> {};
196 
197 struct IndexSubtable
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 
361 struct IndexSubtableRecord
362 {
363  bool sanitize (hb_sanitize_context_t *c, const void *base) const
364  {
365  TRACE_SANITIZE (this);
366  return_trace (c->check_struct (this) &&
369  }
370 
371  const IndexSubtable* get_subtable (const void *base) const
372  {
373  return &(base+offsetToSubtable);
374  }
375 
377  cblc_bitmap_size_subset_context_t *bitmap_size_context,
378  IndexSubtableRecord *record,
380  const void *base,
381  unsigned int *start /* INOUT */) const
382  {
383  TRACE_SERIALIZE (this);
384 
385  auto *subtable = c->serializer->start_embed<IndexSubtable> ();
386  if (unlikely (!subtable)) return_trace (false);
387  if (unlikely (!c->serializer->extend_min (subtable))) return_trace (false);
388 
389  auto *old_subtable = get_subtable (base);
390  auto *old_header = old_subtable->get_header ();
391 
392  subtable->populate_header (old_header->indexFormat,
393  old_header->imageFormat,
394  bitmap_size_context->cbdt_prime->length,
395  &bitmap_size_context->size);
396 
397  unsigned int num_glyphs = 0;
398  bool early_exit = false;
399  for (unsigned int i = *start; i < lookup->length; i++)
400  {
401  hb_codepoint_t new_gid = (*lookup)[i].first;
402  const IndexSubtableRecord *next_record = (*lookup)[i].second;
403  const IndexSubtable *next_subtable = next_record->get_subtable (base);
404  auto *next_header = next_subtable->get_header ();
405  if (next_header != old_header)
406  {
407  *start = i;
408  early_exit = true;
409  break;
410  }
411  unsigned int num_missing = record->add_glyph_for_subset (new_gid);
412  if (unlikely (!subtable->fill_missing_glyphs (c->serializer,
413  bitmap_size_context->cbdt_prime->length,
414  num_missing,
415  &bitmap_size_context->size,
416  &num_glyphs)))
417  return_trace (false);
418 
419  hb_codepoint_t old_gid = 0;
420  c->plan->old_gid_for_new_gid (new_gid, &old_gid);
421  if (old_gid < next_record->firstGlyphIndex)
422  return_trace (false);
423 
424  unsigned int old_idx = (unsigned int) old_gid - next_record->firstGlyphIndex;
425  if (unlikely (!next_subtable->copy_glyph_at_idx (c->serializer,
426  old_idx,
427  bitmap_size_context->cbdt,
428  bitmap_size_context->cbdt_length,
429  bitmap_size_context->cbdt_prime,
430  subtable,
431  &bitmap_size_context->size)))
432  return_trace (false);
433  num_glyphs += 1;
434  }
435  if (!early_exit)
436  *start = lookup->length;
437  if (unlikely (!subtable->finish_subtable (c->serializer,
438  bitmap_size_context->cbdt_prime->length,
439  num_glyphs,
440  &bitmap_size_context->size)))
441  return_trace (false);
442  return_trace (true);
443  }
444 
446  cblc_bitmap_size_subset_context_t *bitmap_size_context,
448  const void *base,
449  unsigned int *start, /* INOUT */
450  hb_vector_t<IndexSubtableRecord>* records /* INOUT */) const
451  {
452  TRACE_SERIALIZE (this);
453  auto snap = c->serializer->snapshot ();
454  unsigned int old_size = bitmap_size_context->size;
455  unsigned int old_cbdt_prime_length = bitmap_size_context->cbdt_prime->length;
456 
457  // Set to invalid state to indicate filling glyphs is not yet started.
458  if (unlikely (!records->resize (records->length + 1)))
459  return_trace (c->serializer->check_success (false));
460 
461  (*records)[records->length - 1].firstGlyphIndex = 1;
462  (*records)[records->length - 1].lastGlyphIndex = 0;
463  bitmap_size_context->size += IndexSubtableRecord::min_size;
464 
465  c->serializer->push ();
466 
467  if (unlikely (!add_new_subtable (c, bitmap_size_context, &((*records)[records->length - 1]), lookup, base, start)))
468  {
469  c->serializer->pop_discard ();
470  c->serializer->revert (snap);
471  bitmap_size_context->cbdt_prime->shrink (old_cbdt_prime_length);
472  bitmap_size_context->size = old_size;
473  records->resize (records->length - 1);
474  return_trace (false);
475  }
476 
477  bitmap_size_context->num_tables += 1;
478  return_trace (true);
479  }
480 
482  {
484  {
485  firstGlyphIndex = gid;
486  lastGlyphIndex = gid;
487  return 0;
488  }
489  // TODO maybe assert? this shouldn't occur.
490  if (lastGlyphIndex > gid)
491  return 0;
492  unsigned int num_missing = (unsigned int) (gid - lastGlyphIndex - 1);
493  lastGlyphIndex = gid;
494  return num_missing;
495  }
496 
497  bool get_extents (hb_glyph_extents_t *extents, const void *base) const
498  { return (base+offsetToSubtable).get_extents (extents); }
499 
500  bool get_image_data (unsigned int gid,
501  const void *base,
502  unsigned int *offset,
503  unsigned int *length,
504  unsigned int *format) const
505  {
506  if (gid < firstGlyphIndex || gid > lastGlyphIndex) return false;
507  return (base+offsetToSubtable).get_image_data (gid - firstGlyphIndex,
508  offset, length, format);
509  }
510 
514  public:
516 };
517 
518 struct IndexSubtableArray
519 {
520  friend struct CBDT;
521 
522  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
523  {
524  TRACE_SANITIZE (this);
525  return_trace (indexSubtablesZ.sanitize (c, count, this));
526  }
527 
528  void
531  const IndexSubtableRecord*>> *lookup /* OUT */) const
532  {
533  bool start_glyph_is_set = false;
534  for (hb_codepoint_t new_gid = 0; new_gid < c->plan->num_output_glyphs (); new_gid++)
535  {
536  hb_codepoint_t old_gid;
537  if (unlikely (!c->plan->old_gid_for_new_gid (new_gid, &old_gid))) continue;
538 
539  const IndexSubtableRecord* record = find_table (old_gid, bitmap_size_context->num_tables);
540  if (unlikely (!record)) continue;
541 
542  // Don't add gaps to the lookup. The best way to determine if a glyph is a
543  // gap is that it has no image data.
544  unsigned int offset, length, format;
545  if (unlikely (!record->get_image_data (old_gid, this, &offset, &length, &format))) continue;
546 
548 
549  if (!start_glyph_is_set)
550  {
551  bitmap_size_context->start_glyph = new_gid;
552  start_glyph_is_set = true;
553  }
554 
555  bitmap_size_context->end_glyph = new_gid;
556  }
557  }
558 
559  bool
561  cblc_bitmap_size_subset_context_t *bitmap_size_context) const
562  {
563  TRACE_SUBSET (this);
564 
565  auto *dst = c->serializer->start_embed<IndexSubtableArray> ();
566  if (unlikely (!dst)) return_trace (false);
567 
569  build_lookup (c, bitmap_size_context, &lookup);
570  if (unlikely (lookup.in_error ()))
571  return c->serializer->check_success (false);
572 
573  bitmap_size_context->size = 0;
574  bitmap_size_context->num_tables = 0;
576  for (unsigned int start = 0; start < lookup.length;)
577  {
578  if (unlikely (!lookup[start].second->add_new_record (c, bitmap_size_context, &lookup, this, &start, &records)))
579  {
580  // Discard any leftover pushes to the serializer from successful records.
581  for (unsigned int i = 0; i < records.length; i++)
582  c->serializer->pop_discard ();
583  return_trace (false);
584  }
585  }
586 
587  /* Workaround to ensure offset ordering is from least to greatest when
588  * resolving links. */
590  for (unsigned int i = 0; i < records.length; i++)
591  objidxs.push (c->serializer->pop_pack ());
592  for (unsigned int i = 0; i < records.length; i++)
593  {
594  IndexSubtableRecord* record = c->serializer->embed (records[i]);
595  if (unlikely (!record)) return_trace (false);
596  c->serializer->add_link (record->offsetToSubtable, objidxs[records.length - 1 - i]);
597  }
598  return_trace (true);
599  }
600 
601  public:
602  const IndexSubtableRecord* find_table (hb_codepoint_t glyph, unsigned int numTables) const
603  {
604  for (unsigned int i = 0; i < numTables; ++i)
605  {
606  unsigned int firstGlyphIndex = indexSubtablesZ[i].firstGlyphIndex;
607  unsigned int lastGlyphIndex = indexSubtablesZ[i].lastGlyphIndex;
608  if (firstGlyphIndex <= glyph && glyph <= lastGlyphIndex)
609  return &indexSubtablesZ[i];
610  }
611  return nullptr;
612  }
613 
614  protected:
616 };
617 
618 struct BitmapSizeTable
619 {
620  friend struct CBLC;
621  friend struct CBDT;
622 
623  bool sanitize (hb_sanitize_context_t *c, const void *base) const
624  {
625  TRACE_SANITIZE (this);
626  return_trace (c->check_struct (this) &&
628  horizontal.sanitize (c) &&
629  vertical.sanitize (c));
630  }
631 
632  const IndexSubtableRecord *
633  find_table (hb_codepoint_t glyph, const void *base, const void **out_base) const
634  {
635  *out_base = &(base+indexSubtableArrayOffset);
637  }
638 
639  bool
641  const char *cbdt, unsigned int cbdt_length,
642  hb_vector_t<char> *cbdt_prime /* INOUT */) const
643  {
644  TRACE_SUBSET (this);
645  auto *out_table = c->serializer->embed (this);
646  if (unlikely (!out_table)) return_trace (false);
647 
648  cblc_bitmap_size_subset_context_t bitmap_size_context;
649  bitmap_size_context.cbdt = cbdt;
650  bitmap_size_context.cbdt_length = cbdt_length;
651  bitmap_size_context.cbdt_prime = cbdt_prime;
652  bitmap_size_context.size = indexTablesSize;
653  bitmap_size_context.num_tables = numberOfIndexSubtables;
654  bitmap_size_context.start_glyph = 1;
655  bitmap_size_context.end_glyph = 0;
656 
657  if (!out_table->indexSubtableArrayOffset.serialize_subset (c,
659  base,
660  &bitmap_size_context))
661  return_trace (false);
662  if (!bitmap_size_context.size ||
663  !bitmap_size_context.num_tables ||
664  bitmap_size_context.start_glyph > bitmap_size_context.end_glyph)
665  return_trace (false);
666 
667  out_table->indexTablesSize = bitmap_size_context.size;
668  out_table->numberOfIndexSubtables = bitmap_size_context.num_tables;
669  out_table->startGlyphIndex = bitmap_size_context.start_glyph;
670  out_table->endGlyphIndex = bitmap_size_context.end_glyph;
671  return_trace (true);
672  }
673 
674  protected:
684  HBUINT8 ppemX;
685  HBUINT8 ppemY;
687  HBINT8 flags;
688  public:
690 };
691 
692 
693 /*
694  * Glyph Bitmap Data Formats.
695  */
696 
698 {
701  public:
703 };
704 
706 {
709  public:
711 };
712 
714 {
716  public:
718 };
719 
720 struct CBLC
721 {
722  friend struct CBDT;
723 
724  static constexpr hb_tag_t tableTag = HB_OT_TAG_CBLC;
725 
727  {
728  TRACE_SANITIZE (this);
729  return_trace (c->check_struct (this) &&
730  likely (version.major == 2 || version.major == 3) &&
731  sizeTables.sanitize (c, this));
732  }
733 
734  static bool
736  {
737  hb_blob_t *cbdt_prime_blob = hb_blob_create (cbdt_prime->arrayZ,
738  cbdt_prime->length,
740  cbdt_prime->arrayZ,
741  free);
742  cbdt_prime->init (); // Leak arrayZ to the blob.
743  bool ret = c->plan->add_table (HB_OT_TAG_CBDT, cbdt_prime_blob);
744  hb_blob_destroy (cbdt_prime_blob);
745  return ret;
746  }
747 
748  bool
750  const char *cbdt /* IN */, unsigned int cbdt_length,
751  CBLC *cblc_prime /* INOUT */, hb_vector_t<char> *cbdt_prime /* INOUT */) const
752  {
753  TRACE_SUBSET (this);
754  cblc_prime->sizeTables.len++;
755 
756  auto snap = c->serializer->snapshot ();
757  auto cbdt_prime_len = cbdt_prime->length;
758 
759  if (!table.subset (c, this, cbdt, cbdt_length, cbdt_prime))
760  {
761  cblc_prime->sizeTables.len--;
762  c->serializer->revert (snap);
763  cbdt_prime->shrink (cbdt_prime_len);
764  return_trace (false);
765  }
766  return_trace (true);
767  }
768 
769  // Implemented in cc file as it depends on definition of CBDT.
771 
772  protected:
774  {
775  unsigned count = sizeTables.len;
776  if (unlikely (!count))
777  return Null (BitmapSizeTable);
778 
779  unsigned int requested_ppem = hb_max (font->x_ppem, font->y_ppem);
780  if (!requested_ppem)
781  requested_ppem = 1<<30; /* Choose largest strike. */
782  unsigned int best_i = 0;
783  unsigned int best_ppem = hb_max (sizeTables[0].ppemX, sizeTables[0].ppemY);
784 
785  for (unsigned int i = 1; i < count; i++)
786  {
787  unsigned int ppem = hb_max (sizeTables[i].ppemX, sizeTables[i].ppemY);
788  if ((requested_ppem <= ppem && ppem < best_ppem) ||
789  (requested_ppem > best_ppem && ppem > best_ppem))
790  {
791  best_i = i;
792  best_ppem = ppem;
793  }
794  }
795 
796  return sizeTables[best_i];
797  }
798 
799  protected:
802  public:
804 };
805 
806 struct CBDT
807 {
808  static constexpr hb_tag_t tableTag = HB_OT_TAG_CBDT;
809 
810  struct accelerator_t
811  {
813  {
816 
818  }
819 
820  void fini ()
821  {
822  this->cblc.destroy ();
823  this->cbdt.destroy ();
824  }
825 
826  bool
828  {
829  const void *base;
830  const BitmapSizeTable &strike = this->cblc->choose_strike (font);
831  const IndexSubtableRecord *subtable_record = strike.find_table (glyph, cblc, &base);
832  if (!subtable_record || !strike.ppemX || !strike.ppemY)
833  return false;
834 
835  if (subtable_record->get_extents (extents, base))
836  return true;
837 
838  unsigned int image_offset = 0, image_length = 0, image_format = 0;
839  if (!subtable_record->get_image_data (glyph, base, &image_offset, &image_length, &image_format))
840  return false;
841 
842  unsigned int cbdt_len = cbdt.get_length ();
843  if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
844  return false;
845 
846  switch (image_format)
847  {
848  case 17: {
849  if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
850  return false;
851  auto &glyphFormat17 = StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
852  glyphFormat17.glyphMetrics.get_extents (font, extents);
853  break;
854  }
855  case 18: {
856  if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
857  return false;
858  auto &glyphFormat18 = StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
859  glyphFormat18.glyphMetrics.get_extents (font, extents);
860  break;
861  }
862  default: return false; /* TODO: Support other image formats. */
863  }
864 
865  /* Convert to font units. */
866  float x_scale = upem / (float) strike.ppemX;
867  float y_scale = upem / (float) strike.ppemY;
868  extents->x_bearing = roundf (extents->x_bearing * x_scale);
869  extents->y_bearing = roundf (extents->y_bearing * y_scale);
870  extents->width = roundf (extents->width * x_scale);
871  extents->height = roundf (extents->height * y_scale);
872 
873  return true;
874  }
875 
876  hb_blob_t*
878  {
879  const void *base;
880  const BitmapSizeTable &strike = this->cblc->choose_strike (font);
881  const IndexSubtableRecord *subtable_record = strike.find_table (glyph, cblc, &base);
882  if (!subtable_record || !strike.ppemX || !strike.ppemY)
883  return hb_blob_get_empty ();
884 
885  unsigned int image_offset = 0, image_length = 0, image_format = 0;
886  if (!subtable_record->get_image_data (glyph, base, &image_offset, &image_length, &image_format))
887  return hb_blob_get_empty ();
888 
889  unsigned int cbdt_len = cbdt.get_length ();
890  if (unlikely (image_offset > cbdt_len || cbdt_len - image_offset < image_length))
891  return hb_blob_get_empty ();
892 
893  switch (image_format)
894  {
895  case 17:
896  {
897  if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
898  return hb_blob_get_empty ();
899  auto &glyphFormat17 = StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
900  return hb_blob_create_sub_blob (cbdt.get_blob (),
901  image_offset + GlyphBitmapDataFormat17::min_size,
902  glyphFormat17.data.len);
903  }
904  case 18:
905  {
906  if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
907  return hb_blob_get_empty ();
908  auto &glyphFormat18 = StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
909  return hb_blob_create_sub_blob (cbdt.get_blob (),
910  image_offset + GlyphBitmapDataFormat18::min_size,
911  glyphFormat18.data.len);
912  }
913  case 19:
914  {
915  if (unlikely (image_length < GlyphBitmapDataFormat19::min_size))
916  return hb_blob_get_empty ();
917  auto &glyphFormat19 = StructAtOffset<GlyphBitmapDataFormat19> (this->cbdt, image_offset);
918  return hb_blob_create_sub_blob (cbdt.get_blob (),
919  image_offset + GlyphBitmapDataFormat19::min_size,
920  glyphFormat19.data.len);
921  }
922  default: return hb_blob_get_empty (); /* TODO: Support other image formats. */
923  }
924  }
925 
926  bool has_data () const { return cbdt.get_length (); }
927 
928  private:
931 
932  unsigned int upem;
933  };
934 
936  {
937  TRACE_SANITIZE (this);
938  return_trace (c->check_struct (this) &&
939  likely (version.major == 2 || version.major == 3));
940  }
941 
942  protected:
945  public:
947 };
948 
949 inline bool
951 {
952  TRACE_SUBSET (this);
953 
954  auto *cblc_prime = c->serializer->start_embed<CBLC> ();
955 
956  // Use a vector as a secondary buffer as the tables need to be built in parallel.
957  hb_vector_t<char> cbdt_prime;
958 
959  if (unlikely (!cblc_prime)) return_trace (false);
960  if (unlikely (!c->serializer->extend_min (cblc_prime))) return_trace (false);
961  cblc_prime->version = version;
962 
963  hb_blob_t* cbdt_blob = hb_sanitize_context_t ().reference_table<CBDT> (c->plan->source);
964  unsigned int cbdt_length;
965  CBDT* cbdt = (CBDT *) hb_blob_get_data (cbdt_blob, &cbdt_length);
966  if (unlikely (cbdt_length < CBDT::min_size))
967  {
968  hb_blob_destroy (cbdt_blob);
969  return_trace (false);
970  }
971  _copy_data_to_cbdt (&cbdt_prime, cbdt, CBDT::min_size);
972 
973  for (const BitmapSizeTable& table : + sizeTables.iter ())
974  subset_size_table (c, table, (const char *) cbdt, cbdt_length, cblc_prime, &cbdt_prime);
975 
976  hb_blob_destroy (cbdt_blob);
977 
978  return_trace (CBLC::sink_cbdt (c, &cbdt_prime));
979 }
980 
981 struct CBDT_accelerator_t : CBDT::accelerator_t {};
982 
983 } /* namespace OT */
984 
985 #endif /* HB_OT_COLOR_CBDT_TABLE_HH */
static double snap(double x)
int lookup(const char *)
#define count(a)
Definition: aptex-macros.h:781
#define free(a)
Definition: decNumber.cpp:310
struct rect data
Definition: dvipdfm.c:64
#define c(n)
Definition: gpos-common.c:150
int base
Definition: gsftopk.c:1502
#define memcpy(d, s, n)
Definition: gsftopk.c:64
double y_scale
Definition: hbf2gf.c:275
#define likely(x)
Definition: jbig2arith.cc:115
#define unlikely(x)
Definition: jbig2arith.cc:116
small capitals from c petite p scientific i
Definition: afcover.h:80
FT_UInt idx
Definition: cffcmap.c:135
FT_Face face
Definition: cffdrivr.c:659
static int ret
Definition: convert.c:72
#define length(c)
Definition: ctangleboot.c:65
Definition: hb-iter.hh:336
static bool _copy_data_to_cbdt(hb_vector_t< char > *cbdt_prime, const void *data, unsigned length)
static int format
Definition: pbmclean.c:15
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 pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand 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 fetch_mask_pixblock pixld mask_basereg pixblock_size MASK 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
static int size
Definition: ppmlabel.c:24
static int offset
Definition: ppmtogif.c:642
struct @1025 hb_max
hb_blob_t * hb_blob_get_empty()
Definition: hb-blob.cc:190
hb_blob_t * hb_blob_create_sub_blob(hb_blob_t *parent, unsigned int offset, unsigned int length)
Definition: hb-blob.cc:133
const char * hb_blob_get_data(hb_blob_t *blob, unsigned int *length)
Definition: hb-blob.cc:341
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:72
void hb_blob_destroy(hb_blob_t *blob)
Definition: hb-blob.cc:226
@ HB_MEMORY_MODE_WRITABLE
Definition: hb-blob.h:70
uint32_t hb_codepoint_t
Definition: hb-common.h:106
uint32_t hb_tag_t
Definition: hb-common.h:147
#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
unsigned int hb_face_get_upem(const hb_face_t *face)
Definition: hb-face.cc:484
#define DEFINE_SIZE_STATIC(size)
Definition: hb-machinery.hh:98
#define DEFINE_SIZE_UNION(size, _member)
#define DEFINE_SIZE_ARRAY(size, array)
#define Null(Type)
Definition: hb-null.hh:94
#define HB_UNUSED
Definition: hb.hh:260
#define roundf(x)
Definition: hb.hh:514
#define HB_INTERNAL
Definition: hb.hh:265
#define HB_OT_TAG_CBDT
#define HB_OT_TAG_CBLC
LNNOffsetTo< IndexSubtableArray > indexSubtableArrayOffset
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
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
static constexpr unsigned min_size
FixedVersion version
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
LArrayOf< BitmapSizeTable > sizeTables
bool subset(hb_subset_context_t *c) const
FixedVersion version
static constexpr hb_tag_t tableTag
bool sanitize(hb_sanitize_context_t *c) const
static bool sink_cbdt(hb_subset_context_t *c, hb_vector_t< char > *cbdt_prime)
const BitmapSizeTable & choose_strike(hb_font_t *font) const
static constexpr unsigned min_size
static constexpr unsigned min_size
static constexpr unsigned min_size
bool sanitize(hb_sanitize_context_t *c, unsigned int count) const
const IndexSubtableRecord * find_table(hb_codepoint_t glyph, unsigned int numTables) const
bool subset(hb_subset_context_t *c, cblc_bitmap_size_subset_context_t *bitmap_size_context) const
UnsizedArrayOf< IndexSubtableRecord > indexSubtablesZ
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
UnsizedArrayOf< Offset< OffsetType > > offsetArrayZ
bool add_offset(hb_serialize_context_t *c, unsigned int offset, unsigned int *size)
bool sanitize(hb_sanitize_context_t *c, unsigned int glyph_count) const
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, const void *base) const
bool sanitize(hb_sanitize_context_t *c, const void *base) const
static constexpr unsigned min_size
const IndexSubtable * get_subtable(const void *base) const
LOffsetTo< IndexSubtable > offsetToSubtable
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
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)
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
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
union OT::IndexSubtable::@1072 u
IndexSubtableHeader header
bool get_extents(hb_glyph_extents_t *extents) const
IndexSubtableFormat1 format1
IndexSubtableFormat3 format3
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
Definition: pbmfont.h:11
Definition: pbmfont.h:4
hb_blob_t * reference_table(const hb_face_t *face, hb_tag_t tableTag=Type::tableTag)
Definition: hb-sanitize.hh:382
bool resize(int size_)
Definition: hb-vector.hh:216
void shrink(int size_)
Definition: hb-vector.hh:245
Type * arrayZ
Definition: hb-vector.hh:62
unsigned int length
Definition: hb-vector.hh:60
void init()
Definition: hb-vector.hh:64
Type * push()
Definition: hb-vector.hh:165
bool alloc(unsigned int size)
Definition: hb-vector.hh:182
Definition: zic.c:306
Definition: table.h:30
second
Definition: tex4ht.c:4115
return() int(((double) *(font_tbl[cur_fnt].wtbl+(int)(*(font_tbl[cur_fnt].char_wi+(int)(ch - font_tbl[cur_fnt].char_f)% 256)))/(double)(1L<< 20)) *(double) font_tbl[cur_fnt].scale)
int ppem
Definition: ttflib.c:39
@ start
Definition: preamble.c:52