QtBase  v6.3.1
hb-ot-glyf-table.hh
Go to the documentation of this file.
1 /*
2  * Copyright © 2015 Google, Inc.
3  * Copyright © 2019 Adobe Inc.
4  * Copyright © 2019 Ebrahim Byagowi
5  *
6  * This is part of HarfBuzz, a text shaping library.
7  *
8  * Permission is hereby granted, without written agreement and without
9  * license or royalty fees, to use, copy, modify, and distribute this
10  * software and its documentation for any purpose, provided that the
11  * above copyright notice and the following two paragraphs appear in
12  * all copies of this software.
13  *
14  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
15  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
17  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18  * DAMAGE.
19  *
20  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
21  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
23  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
24  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
25  *
26  * Google Author(s): Behdad Esfahbod, Garret Rieger, Roderick Sheeter
27  * Adobe Author(s): Michiharu Ariza
28  */
29 
30 #ifndef HB_OT_GLYF_TABLE_HH
31 #define HB_OT_GLYF_TABLE_HH
32 
33 #include "hb-open-type.hh"
34 #include "hb-ot-head-table.hh"
35 #include "hb-ot-hmtx-table.hh"
36 #include "hb-ot-var-gvar-table.hh"
37 #include "hb-draw.hh"
38 
39 namespace OT {
40 
41 
42 /*
43  * loca -- Index to Location
44  * https://docs.microsoft.com/en-us/typography/opentype/spec/loca
45  */
46 #define HB_OT_TAG_loca HB_TAG('l','o','c','a')
47 
48 #ifndef HB_MAX_COMPOSITE_OPERATIONS
49 #define HB_MAX_COMPOSITE_OPERATIONS 100000
50 #endif
51 
52 
53 struct loca
54 {
55  friend struct glyf;
56 
57  static constexpr hb_tag_t tableTag = HB_OT_TAG_loca;
58 
60  {
61  TRACE_SANITIZE (this);
62  return_trace (true);
63  }
64 
65  protected:
67  dataZ; /* Location data. */
68  public:
69  DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
70  * check the size externally, allow Null() object of it by
71  * defining it _MIN instead. */
72 };
73 
74 
75 /*
76  * glyf -- TrueType Glyph Data
77  * https://docs.microsoft.com/en-us/typography/opentype/spec/glyf
78  */
79 #define HB_OT_TAG_glyf HB_TAG('g','l','y','f')
80 
81 
82 struct glyf
83 {
84  static constexpr hb_tag_t tableTag = HB_OT_TAG_glyf;
85 
87  {
88  TRACE_SANITIZE (this);
89  /* Runtime checks as eager sanitizing each glyph is costy */
90  return_trace (true);
91  }
92 
93  template<typename Iterator,
94  hb_requires (hb_is_source_of (Iterator, unsigned int))>
95  static bool
96  _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_short_loca)
97  {
98  unsigned num_offsets = padded_offsets.len () + 1;
99  unsigned entry_size = use_short_loca ? 2 : 4;
100  char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets);
101 
102  if (unlikely (!loca_prime_data)) return false;
103 
104  DEBUG_MSG (SUBSET, nullptr, "loca entry_size %d num_offsets %d size %d",
105  entry_size, num_offsets, entry_size * num_offsets);
106 
107  if (use_short_loca)
108  _write_loca (padded_offsets, 1, hb_array ((HBUINT16 *) loca_prime_data, num_offsets));
109  else
110  _write_loca (padded_offsets, 0, hb_array ((HBUINT32 *) loca_prime_data, num_offsets));
111 
112  hb_blob_t *loca_blob = hb_blob_create (loca_prime_data,
113  entry_size * num_offsets,
115  loca_prime_data,
116  hb_free);
117 
118  bool result = plan->add_table (HB_OT_TAG_loca, loca_blob)
119  && _add_head_and_set_loca_version (plan, use_short_loca);
120 
121  hb_blob_destroy (loca_blob);
122  return result;
123  }
124 
125  template<typename IteratorIn, typename IteratorOut,
126  hb_requires (hb_is_source_of (IteratorIn, unsigned int)),
127  hb_requires (hb_is_sink_of (IteratorOut, unsigned))>
128  static void
129  _write_loca (IteratorIn it, unsigned right_shift, IteratorOut dest)
130  {
131  unsigned int offset = 0;
132  dest << 0;
133  + it
134  | hb_map ([=, &offset] (unsigned int padded_size)
135  {
136  offset += padded_size;
137  DEBUG_MSG (SUBSET, nullptr, "loca entry offset %d", offset);
138  return offset >> right_shift;
139  })
140  | hb_sink (dest)
141  ;
142  }
143 
144  /* requires source of SubsetGlyph complains the identifier isn't declared */
145  template <typename Iterator>
147  Iterator it,
148  bool use_short_loca,
149  const hb_subset_plan_t *plan)
150  {
151  TRACE_SERIALIZE (this);
152  unsigned init_len = c->length ();
153  for (const auto &_ : it) _.serialize (c, use_short_loca, plan);
154 
155  /* As a special case when all glyph in the font are empty, add a zero byte
156  * to the table, so that OTS doesn’t reject it, and to make the table work
157  * on Windows as well.
158  * See https://github.com/khaledhosny/ots/issues/52 */
159  if (init_len == c->length ())
160  {
161  HBUINT8 empty_byte;
162  empty_byte = 0;
163  c->copy (empty_byte);
164  }
165  return_trace (true);
166  }
167 
168  /* Byte region(s) per glyph to output
169  unpadded, hints removed if so requested
170  If we fail to process a glyph we produce an empty (0-length) glyph */
172  {
173  TRACE_SUBSET (this);
174 
175  glyf *glyf_prime = c->serializer->start_embed <glyf> ();
176  if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
177 
179  _populate_subset_glyphs (c->plan, &glyphs);
180 
181  auto padded_offsets =
182  + hb_iter (glyphs)
184  ;
185 
186  unsigned max_offset = + padded_offsets | hb_reduce (hb_add, 0);
187  bool use_short_loca = max_offset < 0x1FFFF;
188 
189 
190  glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan);
191  if (!use_short_loca) {
192  padded_offsets =
193  + hb_iter (glyphs)
195  ;
196  }
197 
198 
199  if (unlikely (c->serializer->in_error ())) return_trace (false);
200  return_trace (c->serializer->check_success (_add_loca_and_head (c->plan,
201  padded_offsets,
202  use_short_loca)));
203  }
204 
205  template <typename SubsetGlyph>
206  void
208  hb_vector_t<SubsetGlyph> *glyphs /* OUT */) const
209  {
211 
212  + hb_range (plan->num_output_glyphs ())
213  | hb_map ([&] (hb_codepoint_t new_gid)
214  {
215  SubsetGlyph subset_glyph = {0};
216  subset_glyph.new_gid = new_gid;
217 
218  /* should never fail: all old gids should be mapped */
219  if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid))
220  return subset_glyph;
221 
222  if (new_gid == 0 &&
224  subset_glyph.source_glyph = Glyph ();
225  else
226  subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
228  subset_glyph.drop_hints_bytes ();
229  else
230  subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
231  return subset_glyph;
232  })
233  | hb_sink (glyphs)
234  ;
235  }
236 
237  static bool
239  {
240  hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<head> (plan->source);
241  hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
242  hb_blob_destroy (head_blob);
243 
244  if (unlikely (!head_prime_blob))
245  return false;
246 
247  head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
248  head_prime->indexToLocFormat = use_short_loca ? 0 : 1;
249  bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
250 
251  hb_blob_destroy (head_prime_blob);
252  return success;
253  }
254 
256  {
257  protected:
259  {
263  WE_HAVE_A_SCALE = 0x0008,
264  MORE_COMPONENTS = 0x0020,
268  USE_MY_METRICS = 0x0200,
272  };
273 
274  public:
275  unsigned int get_size () const
276  {
277  unsigned int size = min_size;
278  /* arg1 and 2 are int16 */
279  if (flags & ARG_1_AND_2_ARE_WORDS) size += 4;
280  /* arg1 and 2 are int8 */
281  else size += 2;
282 
283  /* One x 16 bit (scale) */
284  if (flags & WE_HAVE_A_SCALE) size += 2;
285  /* Two x 16 bit (xscale, yscale) */
286  else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) size += 4;
287  /* Four x 16 bit (xscale, scale01, scale10, yscale) */
288  else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8;
289 
290  return size;
291  }
292 
293  void set_glyph_index (hb_codepoint_t new_gid) { glyphIndex = new_gid; }
295 
298  {
299  flags = (uint16_t) flags | OVERLAP_COMPOUND;
300  }
301 
302  bool has_instructions () const { return flags & WE_HAVE_INSTRUCTIONS; }
303 
304  bool has_more () const { return flags & MORE_COMPONENTS; }
305  bool is_use_my_metrics () const { return flags & USE_MY_METRICS; }
306  bool is_anchored () const { return !(flags & ARGS_ARE_XY_VALUES); }
307  void get_anchor_points (unsigned int &point1, unsigned int &point2) const
308  {
309  const HBUINT8 *p = &StructAfter<const HBUINT8> (glyphIndex);
311  {
312  point1 = ((const HBUINT16 *) p)[0];
313  point2 = ((const HBUINT16 *) p)[1];
314  }
315  else
316  {
317  point1 = p[0];
318  point2 = p[1];
319  }
320  }
321 
323  {
324  float matrix[4];
325  contour_point_t trans;
326  if (get_transformation (matrix, trans))
327  {
328  if (scaled_offsets ())
329  {
330  points.translate (trans);
331  points.transform (matrix);
332  }
333  else
334  {
335  points.transform (matrix);
336  points.translate (trans);
337  }
338  }
339  }
340 
341  protected:
342  bool scaled_offsets () const
344 
345  bool get_transformation (float (&matrix)[4], contour_point_t &trans) const
346  {
347  matrix[0] = matrix[3] = 1.f;
348  matrix[1] = matrix[2] = 0.f;
349 
350  int tx, ty;
351  const HBINT8 *p = &StructAfter<const HBINT8> (glyphIndex);
353  {
354  tx = *(const HBINT16 *) p;
355  p += HBINT16::static_size;
356  ty = *(const HBINT16 *) p;
357  p += HBINT16::static_size;
358  }
359  else
360  {
361  tx = *p++;
362  ty = *p++;
363  }
364  if (is_anchored ()) tx = ty = 0;
365 
366  trans.init ((float) tx, (float) ty);
367 
368  {
369  const F2DOT14 *points = (const F2DOT14 *) p;
370  if (flags & WE_HAVE_A_SCALE)
371  {
372  matrix[0] = matrix[3] = points[0].to_float ();
373  return true;
374  }
375  else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
376  {
377  matrix[0] = points[0].to_float ();
378  matrix[3] = points[1].to_float ();
379  return true;
380  }
381  else if (flags & WE_HAVE_A_TWO_BY_TWO)
382  {
383  matrix[0] = points[0].to_float ();
384  matrix[1] = points[1].to_float ();
385  matrix[2] = points[2].to_float ();
386  matrix[3] = points[3].to_float ();
387  return true;
388  }
389  }
390  return tx || ty;
391  }
392 
393  protected:
396  public:
398  };
399 
400  struct composite_iter_t : hb_iter_with_fallback_t<composite_iter_t, const CompositeGlyphChain &>
401  {
404  glyph (glyph_), current (nullptr), current_size (0)
405  {
406  set_next (current_);
407  }
408 
409  composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
410 
411  const CompositeGlyphChain &__item__ () const { return *current; }
412  bool __more__ () const { return current; }
413  void __next__ ()
414  {
415  if (!current->has_more ()) { current = nullptr; return; }
416 
417  set_next (&StructAtOffset<CompositeGlyphChain> (current, current_size));
418  }
419  bool operator != (const composite_iter_t& o) const
420  { return glyph != o.glyph || current != o.current; }
421 
422 
423  void set_next (const CompositeGlyphChain *composite)
424  {
425  if (!glyph.check_range (composite, CompositeGlyphChain::min_size))
426  {
427  current = nullptr;
428  current_size = 0;
429  return;
430  }
431  unsigned size = composite->get_size ();
432  if (!glyph.check_range (composite, size))
433  {
434  current = nullptr;
435  current_size = 0;
436  return;
437  }
438 
439  current = composite;
440  current_size = size;
441  }
442 
443  private:
444  hb_bytes_t glyph;
445  __item_t__ current;
446  unsigned current_size;
447  };
448 
450  {
455  PHANTOM_COUNT = 4
456  };
457 
458  struct accelerator_t;
459 
460  struct Glyph
461  {
463  {
465  FLAG_X_SHORT = 0x02,
466  FLAG_Y_SHORT = 0x04,
467  FLAG_REPEAT = 0x08,
468  FLAG_X_SAME = 0x10,
469  FLAG_Y_SAME = 0x20,
471  FLAG_RESERVED2 = 0x80
472  };
473 
474  private:
475  struct GlyphHeader
476  {
477  bool has_data () const { return numberOfContours; }
478 
479  bool get_extents (hb_font_t *font, const accelerator_t &glyf_accelerator,
480  hb_codepoint_t gid, hb_glyph_extents_t *extents) const
481  {
482  /* Undocumented rasterizer behavior: shift glyph to the left by (lsb - xMin), i.e., xMin = lsb */
483  /* extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax); */
484  extents->x_bearing = font->em_scale_x (glyf_accelerator.hmtx->get_side_bearing (gid));
485  extents->y_bearing = font->em_scale_y (hb_max (yMin, yMax));
486  extents->width = font->em_scale_x (hb_max (xMin, xMax) - hb_min (xMin, xMax));
487  extents->height = font->em_scale_y (hb_min (yMin, yMax) - hb_max (yMin, yMax));
488 
489  return true;
490  }
491 
492  HBINT16 numberOfContours;
493  /* If the number of contours is
494  * greater than or equal to zero,
495  * this is a simple glyph; if negative,
496  * this is a composite glyph. */
497  FWORD xMin; /* Minimum x for coordinate data. */
498  FWORD yMin; /* Minimum y for coordinate data. */
499  FWORD xMax; /* Maximum x for coordinate data. */
500  FWORD yMax; /* Maximum y for coordinate data. */
501  public:
502  DEFINE_SIZE_STATIC (10);
503  };
504 
505  struct SimpleGlyph
506  {
507  const GlyphHeader &header;
509  SimpleGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
510  header (header_), bytes (bytes_) {}
511 
512  unsigned int instruction_len_offset () const
513  { return GlyphHeader::static_size + 2 * header.numberOfContours; }
514 
515  unsigned int length (unsigned int instruction_len) const
516  { return instruction_len_offset () + 2 + instruction_len; }
517 
518  unsigned int instructions_length () const
519  {
520  unsigned int instruction_length_offset = instruction_len_offset ();
521  if (unlikely (instruction_length_offset + 2 > bytes.length)) return 0;
522 
523  const HBUINT16 &instructionLength = StructAtOffset<HBUINT16> (&bytes, instruction_length_offset);
524  /* Out of bounds of the current glyph */
525  if (unlikely (length (instructionLength) > bytes.length)) return 0;
526  return instructionLength;
527  }
528 
529  const Glyph trim_padding () const
530  {
531  /* based on FontTools _g_l_y_f.py::trim */
532  const uint8_t *glyph = (uint8_t*) bytes.arrayZ;
533  const uint8_t *glyph_end = glyph + bytes.length;
534  /* simple glyph w/contours, possibly trimmable */
535  glyph += instruction_len_offset ();
536 
537  if (unlikely (glyph + 2 >= glyph_end)) return Glyph ();
538  unsigned int num_coordinates = StructAtOffset<HBUINT16> (glyph - 2, 0) + 1;
539  unsigned int num_instructions = StructAtOffset<HBUINT16> (glyph, 0);
540 
541  glyph += 2 + num_instructions;
542 
543  unsigned int coord_bytes = 0;
544  unsigned int coords_with_flags = 0;
545  while (glyph < glyph_end)
546  {
547  uint8_t flag = *glyph;
548  glyph++;
549 
550  unsigned int repeat = 1;
551  if (flag & FLAG_REPEAT)
552  {
553  if (unlikely (glyph >= glyph_end)) return Glyph ();
554  repeat = *glyph + 1;
555  glyph++;
556  }
557 
558  unsigned int xBytes, yBytes;
559  xBytes = yBytes = 0;
560  if (flag & FLAG_X_SHORT) xBytes = 1;
561  else if ((flag & FLAG_X_SAME) == 0) xBytes = 2;
562 
563  if (flag & FLAG_Y_SHORT) yBytes = 1;
564  else if ((flag & FLAG_Y_SAME) == 0) yBytes = 2;
565 
566  coord_bytes += (xBytes + yBytes) * repeat;
567  coords_with_flags += repeat;
568  if (coords_with_flags >= num_coordinates) break;
569  }
570 
571  if (unlikely (coords_with_flags != num_coordinates)) return Glyph ();
572  return Glyph (bytes.sub_array (0, bytes.length + coord_bytes - (glyph_end - glyph)));
573  }
574 
575  /* zero instruction length */
576  void drop_hints ()
577  {
578  GlyphHeader &glyph_header = const_cast<GlyphHeader &> (header);
579  (HBUINT16 &) StructAtOffset<HBUINT16> (&glyph_header, instruction_len_offset ()) = 0;
580  }
581 
582  void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
583  {
584  unsigned int instructions_len = instructions_length ();
585  unsigned int glyph_length = length (instructions_len);
586  dest_start = bytes.sub_array (0, glyph_length - instructions_len);
587  dest_end = bytes.sub_array (glyph_length, bytes.length - glyph_length);
588  }
589 
590  void set_overlaps_flag ()
591  {
592  if (unlikely (!header.numberOfContours)) return;
593 
594  unsigned flags_offset = length (instructions_length ());
595  if (unlikely (flags_offset + 1 > bytes.length)) return;
596 
597  HBUINT8 &first_flag = (HBUINT8 &) StructAtOffset<HBUINT16> (&bytes, flags_offset);
598  first_flag = (uint8_t) first_flag | FLAG_OVERLAP_SIMPLE;
599  }
600 
601  static bool read_points (const HBUINT8 *&p /* IN/OUT */,
602  contour_point_vector_t &points_ /* IN/OUT */,
603  const hb_bytes_t &bytes,
604  void (* setter) (contour_point_t &_, float v),
605  const simple_glyph_flag_t short_flag,
606  const simple_glyph_flag_t same_flag)
607  {
608  float v = 0;
609  for (unsigned i = 0; i < points_.length; i++)
610  {
611  uint8_t flag = points_[i].flag;
612  if (flag & short_flag)
613  {
614  if (unlikely (!bytes.check_range (p))) return false;
615  if (flag & same_flag)
616  v += *p++;
617  else
618  v -= *p++;
619  }
620  else
621  {
622  if (!(flag & same_flag))
623  {
624  if (unlikely (!bytes.check_range ((const HBUINT16 *) p))) return false;
625  v += *(const HBINT16 *) p;
626  p += HBINT16::static_size;
627  }
628  }
629  setter (points_[i], v);
630  }
631  return true;
632  }
633 
634  bool get_contour_points (contour_point_vector_t &points_ /* OUT */,
635  bool phantom_only = false) const
636  {
637  const HBUINT16 *endPtsOfContours = &StructAfter<HBUINT16> (header);
638  int num_contours = header.numberOfContours;
639  if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours + 1]))) return false;
640  unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
641 
642  points_.resize (num_points);
643  for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
644  if (phantom_only) return true;
645 
646  for (int i = 0; i < num_contours; i++)
647  points_[endPtsOfContours[i]].is_end_point = true;
648 
649  /* Skip instructions */
650  const HBUINT8 *p = &StructAtOffset<HBUINT8> (&endPtsOfContours[num_contours + 1],
651  endPtsOfContours[num_contours]);
652 
653  /* Read flags */
654  for (unsigned int i = 0; i < num_points; i++)
655  {
656  if (unlikely (!bytes.check_range (p))) return false;
657  uint8_t flag = *p++;
658  points_[i].flag = flag;
659  if (flag & FLAG_REPEAT)
660  {
661  if (unlikely (!bytes.check_range (p))) return false;
662  unsigned int repeat_count = *p++;
663  while ((repeat_count-- > 0) && (++i < num_points))
664  points_[i].flag = flag;
665  }
666  }
667 
668  /* Read x & y coordinates */
669  return read_points (p, points_, bytes, [] (contour_point_t &p, float v) { p.x = v; },
671  && read_points (p, points_, bytes, [] (contour_point_t &p, float v) { p.y = v; },
673  }
674  };
675 
676  struct CompositeGlyph
677  {
678  const GlyphHeader &header;
680  CompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
681  header (header_), bytes (bytes_) {}
682 
683  composite_iter_t get_iterator () const
684  { return composite_iter_t (bytes, &StructAfter<CompositeGlyphChain, GlyphHeader> (header)); }
685 
686  unsigned int instructions_length (hb_bytes_t bytes) const
687  {
688  unsigned int start = bytes.length;
689  unsigned int end = bytes.length;
690  const CompositeGlyphChain *last = nullptr;
691  for (auto &item : get_iterator ())
692  last = &item;
693  if (unlikely (!last)) return 0;
694 
695  if (last->has_instructions ())
696  start = (char *) last - &bytes + last->get_size ();
697  if (unlikely (start > end)) return 0;
698  return end - start;
699  }
700 
701  /* Trimming for composites not implemented.
702  * If removing hints it falls out of that. */
703  const Glyph trim_padding () const { return Glyph (bytes); }
704 
705  void drop_hints ()
706  {
707  for (const auto &_ : get_iterator ())
708  const_cast<CompositeGlyphChain &> (_).drop_instructions_flag ();
709  }
710 
711  /* Chop instructions off the end */
712  void drop_hints_bytes (hb_bytes_t &dest_start) const
713  { dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
714 
715  void set_overlaps_flag ()
716  {
717  const_cast<CompositeGlyphChain &> (StructAfter<CompositeGlyphChain, GlyphHeader> (header))
718  .set_overlaps_flag ();
719  }
720  };
721 
722  enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
723 
724  public:
726  {
727  if (type != COMPOSITE) return composite_iter_t ();
728  return CompositeGlyph (*header, bytes).get_iterator ();
729  }
730 
731  const Glyph trim_padding () const
732  {
733  switch (type) {
734  case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding ();
735  case SIMPLE: return SimpleGlyph (*header, bytes).trim_padding ();
736  default: return bytes;
737  }
738  }
739 
740  void drop_hints ()
741  {
742  switch (type) {
743  case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
744  case SIMPLE: SimpleGlyph (*header, bytes).drop_hints (); return;
745  default: return;
746  }
747  }
748 
750  {
751  switch (type) {
752  case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return;
753  case SIMPLE: SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
754  default: return;
755  }
756  }
757 
758  void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
759  {
760  switch (type) {
761  case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return;
762  case SIMPLE: SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return;
763  default: return;
764  }
765  }
766 
767  /* Note: Recursively calls itself.
768  * all_points includes phantom points
769  */
770  bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
771  contour_point_vector_t &all_points /* OUT */,
772  bool phantom_only = false,
773  unsigned int depth = 0) const
774  {
775  if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
777 
778  switch (type) {
779  case COMPOSITE:
780  {
781  /* pseudo component points for each component in composite glyph */
782  unsigned num_points = hb_len (CompositeGlyph (*header, bytes).get_iterator ());
783  if (unlikely (!points.resize (num_points))) return false;
784  for (unsigned i = 0; i < points.length; i++)
785  points[i].init ();
786  break;
787  }
788  case SIMPLE:
789  if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
790  return false;
791  break;
792  }
793 
794  /* Init phantom points */
795  if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
797  {
798  for (unsigned i = 0; i < PHANTOM_COUNT; ++i) phantoms[i].init ();
799  int h_delta = (int) header->xMin -
800  glyf_accelerator.hmtx->get_side_bearing (gid);
801  int v_orig = (int) header->yMax +
802 #ifndef HB_NO_VERTICAL
803  glyf_accelerator.vmtx->get_side_bearing (gid)
804 #else
805  0
806 #endif
807  ;
808  unsigned h_adv = glyf_accelerator.hmtx->get_advance (gid);
809  unsigned v_adv =
810 #ifndef HB_NO_VERTICAL
811  glyf_accelerator.vmtx->get_advance (gid)
812 #else
813  - font->face->get_upem ()
814 #endif
815  ;
816  phantoms[PHANTOM_LEFT].x = h_delta;
817  phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
818  phantoms[PHANTOM_TOP].y = v_orig;
819  phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
820  }
821 
822 #ifndef HB_NO_VAR
823  glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ());
824 #endif
825 
826  switch (type) {
827  case SIMPLE:
828  all_points.extend (points.as_array ());
829  break;
830  case COMPOSITE:
831  {
832  unsigned int comp_index = 0;
833  for (auto &item : get_composite_iterator ())
834  {
835  contour_point_vector_t comp_points;
836  if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_glyph_index ())
837  .get_points (font, glyf_accelerator, comp_points,
838  phantom_only, depth + 1)
839  || comp_points.length < PHANTOM_COUNT))
840  return false;
841 
842  /* Copy phantom points from component if USE_MY_METRICS flag set */
843  if (item.is_use_my_metrics ())
844  for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
845  phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
846 
847  /* Apply component transformation & translation */
848  item.transform_points (comp_points);
849 
850  /* Apply translation from gvar */
851  comp_points.translate (points[comp_index]);
852 
853  if (item.is_anchored ())
854  {
855  unsigned int p1, p2;
856  item.get_anchor_points (p1, p2);
857  if (likely (p1 < all_points.length && p2 < comp_points.length))
858  {
859  contour_point_t delta;
860  delta.init (all_points[p1].x - comp_points[p2].x,
861  all_points[p1].y - comp_points[p2].y);
862 
863  comp_points.translate (delta);
864  }
865  }
866 
867  all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT));
868 
869  comp_index++;
870  }
871 
872  all_points.extend (phantoms);
873  } break;
874  default:
875  all_points.extend (phantoms);
876  }
877 
878  if (depth == 0) /* Apply at top level */
879  {
880  /* Undocumented rasterizer behavior:
881  * Shift points horizontally by the updated left side bearing
882  */
883  contour_point_t delta;
884  delta.init (-phantoms[PHANTOM_LEFT].x, 0.f);
885  if (delta.x) all_points.translate (delta);
886  }
887 
888  return true;
889  }
890 
891  bool get_extents (hb_font_t *font, const accelerator_t &glyf_accelerator,
892  hb_glyph_extents_t *extents) const
893  {
894  if (type == EMPTY) return true; /* Empty glyph; zero extents. */
895  return header->get_extents (font, glyf_accelerator, gid, extents);
896  }
897 
898  hb_bytes_t get_bytes () const { return bytes; }
899 
901  hb_codepoint_t gid_ = (hb_codepoint_t) -1) : bytes (bytes_), gid (gid_),
902  header (bytes.as<GlyphHeader> ())
903  {
904  int num_contours = header->numberOfContours;
905  if (unlikely (num_contours == 0)) type = EMPTY;
906  else if (num_contours > 0) type = SIMPLE;
907  else type = COMPOSITE; /* negative numbers */
908  }
909 
910  protected:
913  const GlyphHeader *header;
914  unsigned type;
915  };
916 
918  {
920  {
921  short_offset = false;
922  num_glyphs = 0;
923  loca_table = nullptr;
924  glyf_table = nullptr;
925 #ifndef HB_NO_VAR
926  gvar = nullptr;
927 #endif
928  hmtx = nullptr;
929 #ifndef HB_NO_VERTICAL
930  vmtx = nullptr;
931 #endif
932  const OT::head &head = *face->table.head;
933  if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
934  /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
935  return;
936  short_offset = 0 == head.indexToLocFormat;
937 
938  loca_table = face->table.loca.get_blob (); // Needs no destruct!
939  glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
940 #ifndef HB_NO_VAR
941  gvar = face->table.gvar;
942 #endif
943  hmtx = face->table.hmtx;
944 #ifndef HB_NO_VERTICAL
945  vmtx = face->table.vmtx;
946 #endif
947 
948  num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
949  num_glyphs = hb_min (num_glyphs, face->get_num_glyphs ());
950  }
952  {
953  glyf_table.destroy ();
954  }
955 
956  protected:
957  template<typename T>
959  {
960  if (gid >= num_glyphs) return false;
961 
962  /* Making this allocfree is not that easy
963  https://github.com/harfbuzz/harfbuzz/issues/2095
964  mostly because of gvar handling in VF fonts,
965  perhaps a separate path for non-VF fonts can be considered */
966  contour_point_vector_t all_points;
967 
968  bool phantom_only = !consumer.is_consuming_contour_points ();
969  if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, phantom_only)))
970  return false;
971 
972  if (consumer.is_consuming_contour_points ())
973  {
974  for (unsigned point_index = 0; point_index + 4 < all_points.length; ++point_index)
975  consumer.consume_point (all_points[point_index]);
976  consumer.points_end ();
977  }
978 
979  /* Where to write phantoms, nullptr if not requested */
980  contour_point_t *phantoms = consumer.get_phantoms_sink ();
981  if (phantoms)
982  for (unsigned i = 0; i < PHANTOM_COUNT; ++i)
983  phantoms[i] = all_points[all_points.length - PHANTOM_COUNT + i];
984 
985  return true;
986  }
987 
988 #ifndef HB_NO_VAR
990  {
994 
996  {
997  contour_bounds_t () { min_x = min_y = FLT_MAX; max_x = max_y = -FLT_MAX; }
998 
999  void add (const contour_point_t &p)
1000  {
1001  min_x = hb_min (min_x, p.x);
1002  min_y = hb_min (min_y, p.y);
1003  max_x = hb_max (max_x, p.x);
1004  max_y = hb_max (max_y, p.y);
1005  }
1006 
1007  bool empty () const { return (min_x >= max_x) || (min_y >= max_y); }
1008 
1010  {
1011  if (unlikely (empty ()))
1012  {
1013  extents->width = 0;
1014  extents->x_bearing = 0;
1015  extents->height = 0;
1016  extents->y_bearing = 0;
1017  return;
1018  }
1023  }
1024 
1025  protected:
1028 
1030  {
1031  font = font_;
1032  extents = extents_;
1033  phantoms = phantoms_;
1034  if (extents) bounds = contour_bounds_t ();
1035  }
1036 
1037  void consume_point (const contour_point_t &point) { bounds.add (point); }
1039 
1042  };
1043 
1044  public:
1045  unsigned
1046  get_advance_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
1047  {
1048  if (unlikely (gid >= num_glyphs)) return 0;
1049 
1050  bool success = false;
1051 
1052  contour_point_t phantoms[PHANTOM_COUNT];
1053  if (likely (font->num_coords == gvar->get_axis_count ()))
1054  success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms));
1055 
1056  if (unlikely (!success))
1057  return
1058 #ifndef HB_NO_VERTICAL
1059  is_vertical ? vmtx->get_advance (gid) :
1060 #endif
1061  hmtx->get_advance (gid);
1062 
1063  float result = is_vertical
1064  ? phantoms[PHANTOM_TOP].y - phantoms[PHANTOM_BOTTOM].y
1065  : phantoms[PHANTOM_RIGHT].x - phantoms[PHANTOM_LEFT].x;
1066  return hb_clamp (roundf (result), 0.f, (float) UINT_MAX / 2);
1067  }
1068 
1069  int get_side_bearing_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
1070  {
1071  if (unlikely (gid >= num_glyphs)) return 0;
1072 
1073  hb_glyph_extents_t extents;
1074 
1075  contour_point_t phantoms[PHANTOM_COUNT];
1076  if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms))))
1077  return
1078 #ifndef HB_NO_VERTICAL
1079  is_vertical ? vmtx->get_side_bearing (gid) :
1080 #endif
1081  hmtx->get_side_bearing (gid);
1082 
1083  return is_vertical
1084  ? ceilf (phantoms[PHANTOM_TOP].y) - extents.y_bearing
1085  : floorf (phantoms[PHANTOM_LEFT].x);
1086  }
1087 #endif
1088 
1089  public:
1091  {
1092  if (unlikely (gid >= num_glyphs)) return false;
1093 
1094 #ifndef HB_NO_VAR
1095  if (font->num_coords && font->num_coords == gvar->get_axis_count ())
1096  return get_points (font, gid, points_aggregator_t (font, extents, nullptr));
1097 #endif
1098  return glyph_for_gid (gid).get_extents (font, *this, extents);
1099  }
1100 
1101  const Glyph
1102  glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const
1103  {
1104  if (unlikely (gid >= num_glyphs)) return Glyph ();
1105 
1106  unsigned int start_offset, end_offset;
1107 
1108  if (short_offset)
1109  {
1110  const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ;
1111  start_offset = 2 * offsets[gid];
1112  end_offset = 2 * offsets[gid + 1];
1113  }
1114  else
1115  {
1116  const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ;
1117  start_offset = offsets[gid];
1118  end_offset = offsets[gid + 1];
1119  }
1120 
1121  if (unlikely (start_offset > end_offset || end_offset > glyf_table.get_length ()))
1122  return Glyph ();
1123 
1124  Glyph glyph (hb_bytes_t ((const char *) this->glyf_table + start_offset,
1125  end_offset - start_offset), gid);
1126  return needs_padding_removal ? glyph.trim_padding () : glyph;
1127  }
1128 
1129  unsigned
1131  hb_set_t *gids_to_retain,
1132  unsigned depth = 0,
1133  unsigned operation_count = 0) const
1134  {
1135  if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count;
1136  if (unlikely (operation_count++ > HB_MAX_COMPOSITE_OPERATIONS)) return operation_count;
1137  /* Check if is already visited */
1138  if (gids_to_retain->has (gid)) return operation_count;
1139 
1140  gids_to_retain->add (gid);
1141 
1142  auto it = glyph_for_gid (gid).get_composite_iterator ();
1143  while (it)
1144  {
1145  auto item = *(it++);
1146  operation_count =
1147  add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth, operation_count);
1148  }
1149 
1150  return operation_count;
1151  }
1152 
1154  {
1157 
1159  {
1160  optional_point_t () { has_data = false; }
1161  optional_point_t (float x_, float y_) { x = x_; y = y_; has_data = true; }
1162 
1163  bool has_data;
1164  float x;
1165  float y;
1166 
1168  { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
1170 
1171  path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
1172  {
1173  font = font_;
1174  draw_session = &draw_session_;
1176  }
1177 
1178  /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
1179  See also:
1180  * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
1181  * https://stackoverflow.com/a/20772557 */
1182  void consume_point (const contour_point_t &point)
1183  {
1184  bool is_on_curve = point.flag & Glyph::FLAG_ON_CURVE;
1185  optional_point_t p (point.x, point.y);
1186  if (!first_oncurve.has_data)
1187  {
1188  if (is_on_curve)
1189  {
1190  first_oncurve = p;
1192  }
1193  else
1194  {
1196  {
1197  optional_point_t mid = first_offcurve.lerp (p, .5f);
1198  first_oncurve = mid;
1199  last_offcurve = p;
1201  }
1202  else
1203  first_offcurve = p;
1204  }
1205  }
1206  else
1207  {
1208  if (last_offcurve.has_data)
1209  {
1210  if (is_on_curve)
1211  {
1213  font->em_fscalef_x (p.x), font->em_fscalef_y (p.y));
1215  }
1216  else
1217  {
1218  optional_point_t mid = last_offcurve.lerp (p, .5f);
1220  font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
1221  last_offcurve = p;
1222  }
1223  }
1224  else
1225  {
1226  if (is_on_curve)
1228  else
1229  last_offcurve = p;
1230  }
1231  }
1232 
1233  if (point.is_end_point)
1234  {
1236  {
1239  font->em_fscalef_x (mid.x), font->em_fscalef_y (mid.y));
1241  /* now check the rest */
1242  }
1243 
1250  else if (first_oncurve.has_data)
1252  else if (first_offcurve.has_data)
1253  {
1255  draw_session->move_to (x, y);
1256  draw_session->quadratic_to (x, y, x, y);
1257  }
1258 
1259  /* Getting ready for the next contour */
1262  }
1263  }
1264  void points_end () {}
1265 
1266  bool is_consuming_contour_points () { return true; }
1267  contour_point_t *get_phantoms_sink () { return nullptr; }
1268  };
1269 
1270  bool
1272  { return get_points (font, gid, path_builder_t (font, draw_session)); }
1273 
1274 #ifndef HB_NO_VAR
1276 #endif
1278 #ifndef HB_NO_VERTICAL
1280 #endif
1281 
1282  private:
1283  bool short_offset;
1284  unsigned int num_glyphs;
1285  hb_blob_ptr_t<loca> loca_table;
1286  hb_blob_ptr_t<glyf> glyf_table;
1287  };
1288 
1290  {
1294  hb_bytes_t dest_start; /* region of source_glyph to copy first */
1295  hb_bytes_t dest_end; /* region of source_glyph to copy second */
1296 
1298  bool use_short_loca,
1299  const hb_subset_plan_t *plan) const
1300  {
1301  TRACE_SERIALIZE (this);
1302 
1303  hb_bytes_t dest_glyph = dest_start.copy (c);
1304  dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length);
1305  unsigned int pad_length = use_short_loca ? padding () : 0;
1306  DEBUG_MSG (SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
1307 
1308  HBUINT8 pad;
1309  pad = 0;
1310  while (pad_length > 0)
1311  {
1312  c->embed (pad);
1313  pad_length--;
1314  }
1315 
1316  if (unlikely (!dest_glyph.length)) return_trace (true);
1317 
1318  /* update components gids */
1319  for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
1320  {
1322  if (plan->new_gid_for_old_gid (_.get_glyph_index (), &new_gid))
1323  const_cast<CompositeGlyphChain &> (_).set_glyph_index (new_gid);
1324  }
1325 
1326  if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
1327  Glyph (dest_glyph).drop_hints ();
1328 
1330  Glyph (dest_glyph).set_overlaps_flag ();
1331 
1332  return_trace (true);
1333  }
1334 
1337 
1338  unsigned int length () const { return dest_start.length + dest_end.length; }
1339  /* pad to 2 to ensure 2-byte loca will be ok */
1340  unsigned int padding () const { return length () % 2; }
1341  unsigned int padded_size () const { return length () + padding (); }
1342  };
1343 
1344  protected:
1346  dataZ; /* Glyphs data. */
1347  public:
1348  DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
1349  * check the size externally, allow Null() object of it by
1350  * defining it _MIN instead. */
1351 };
1352 
1355 };
1356 
1357 
1358 } /* namespace OT */
1359 
1360 
1361 #endif /* HB_OT_GLYF_TABLE_HH */
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
QPixmap p2
QPixmap p1
[0]
#define roundf(x)
Definition: hb-algs.hh:165
hb_array_t< T > hb_array(T *array, unsigned int length)
Definition: hb-array.hh:295
hb_array_t< const char > hb_bytes_t
Definition: hb-array.hh:434
hb_blob_t * hb_blob_copy_writable_or_fail(hb_blob_t *blob)
Definition: hb-blob.cc:200
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
char * hb_blob_get_data_writable(hb_blob_t *blob, unsigned int *length)
Definition: hb-blob.cc:402
#define TRACE_SERIALIZE(this)
Definition: hb-debug.hh:426
#define TRACE_SANITIZE(this)
Definition: hb-debug.hh:414
#define DEBUG_MSG(WHAT, OBJ,...)
#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
auto it hb_map(hb_second)) template< typename Type > inline hb_array_t< Type > operator()(hb_array_t< Type > array
static auto hb_requires(hb_is_iterable(Iterable))> static inline auto end(Iterable &&iterable) HB_AUTO_RETURN(hb_iter(iterable).end()) namespace OT
Definition: hb-iter.hh:331
#define DEFINE_SIZE_STATIC(size)
HB_EXTERN unsigned int start_offset
#define HB_MAX_COMPOSITE_OPERATIONS
#define HB_OT_TAG_glyf
#define HB_OT_TAG_loca
#define HB_OT_TAG_head
#define HB_MAX_NESTING_LEVEL
#define _(S, M)
@ HB_SUBSET_FLAGS_NO_HINTING
Definition: hb-subset.h:80
@ HB_SUBSET_FLAGS_NOTDEF_OUTLINE
Definition: hb-subset.h:86
@ HB_SUBSET_FLAGS_SET_OVERLAPS_FLAG
Definition: hb-subset.h:84
#define hb_calloc
Definition: hb.hh:236
#define likely(expr)
Definition: hb.hh:250
#define unlikely(expr)
Definition: hb.hh:251
#define hb_free
Definition: hb.hh:238
GeneratorWrapper< T > repeat(size_t repeats, GeneratorWrapper< T > &&generator)
Definition: catch_p_p.h:4251
HeaderSize entry_size(const QByteArray &name, const QByteArray &value)
Definition: hpacktable.cpp:55
IntType< uint8_t > HBUINT8
HBINT16 FWORD
IntType< uint16_t > HBUINT16
IntType< int16_t > HBINT16
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]
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 init[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1 beq endif SRC MASK if dst_r_bpp DST_R else add endif PF add sub src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head pixblock_size cache_preload_simple process_pixblock_tail pixinterleave dst_w_basereg irp beq endif process_pixblock_tail_head tst beq irp if pixblock_size chunk_size tst beq pixld SRC pixld MASK if DST_R else pixld DST_R endif if src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head if pixblock_size cache_preload_simple endif process_pixblock_tail pixinterleave dst_w_basereg irp if pixblock_size chunk_size tst beq if DST_W else pixst DST_W else mov ORIG_W endif add lsl if lsl endif if lsl endif lsl endif lsl endif lsl endif subs mov DST_W if regs_shortage str endif bge start_of_loop_label endm macro generate_composite_function
GLenum GLuint GLenum GLsizei length
Definition: qopengl.h:270
GLenum type
Definition: qopengl.h:270
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLint GLenum GLsizei GLsizei GLsizei depth
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLuint end
GLenum face
GLbitfield flags
GLuint start
GLenum GLuint GLintptr offset
GLint y
GLfixed GLfixed GLint GLint GLfixed points
Definition: qopenglext.h:5206
const GLubyte * c
Definition: qopenglext.h:12701
GLuint GLsizei const GLuint const GLintptr * offsets
Definition: qopenglext.h:2587
GLuint GLenum matrix
Definition: qopenglext.h:11564
GLdouble GLdouble t
[9]
Definition: qopenglext.h:243
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
GLbyte ty
Definition: qopenglext.h:6700
@ 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
QObject::connect nullptr
QGraphicsItem * item
QStringList::Iterator it
float to_float() const
void translate(const contour_point_t &p)
void init(float x_=0.f, float y_=0.f, bool is_end_point_=false)
void extend(const hb_array_t< contour_point_t > &a)
void translate(const contour_point_t &delta)
void get_anchor_points(unsigned int &point1, unsigned int &point2) const
void transform_points(contour_point_vector_t &points) const
void set_glyph_index(hb_codepoint_t new_gid)
hb_codepoint_t get_glyph_index() const
bool get_transformation(float(&matrix)[4], contour_point_t &trans) const
bool get_points(hb_font_t *font, const accelerator_t &glyf_accelerator, contour_point_vector_t &all_points, bool phantom_only=false, unsigned int depth=0) const
hb_bytes_t get_bytes() const
bool get_extents(hb_font_t *font, const accelerator_t &glyf_accelerator, hb_glyph_extents_t *extents) const
Glyph(hb_bytes_t bytes_=hb_bytes_t(), hb_codepoint_t gid_=(hb_codepoint_t) -1)
composite_iter_t get_composite_iterator() const
const GlyphHeader * header
const Glyph trim_padding() const
hb_codepoint_t gid
void drop_hints_bytes(hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
unsigned int padding() const
unsigned int length() const
unsigned int padded_size() const
bool serialize(hb_serialize_context_t *c, bool use_short_loca, const hb_subset_plan_t *plan) const
optional_point_t lerp(optional_point_t p, float t)
void consume_point(const contour_point_t &point)
struct OT::glyf::accelerator_t::path_builder_t::optional_point_t first_offcurve
struct OT::glyf::accelerator_t::path_builder_t::optional_point_t last_offcurve
struct OT::glyf::accelerator_t::path_builder_t::optional_point_t first_oncurve
path_builder_t(hb_font_t *font_, hb_draw_session_t &draw_session_)
void get_extents(hb_font_t *font, hb_glyph_extents_t *extents)
void consume_point(const contour_point_t &point)
struct OT::glyf::accelerator_t::points_aggregator_t::contour_bounds_t bounds
points_aggregator_t(hb_font_t *font_, hb_glyph_extents_t *extents_, contour_point_t *phantoms_)
const hmtx_accelerator_t * hmtx
unsigned add_gid_and_children(hb_codepoint_t gid, hb_set_t *gids_to_retain, unsigned depth=0, unsigned operation_count=0) const
bool get_points(hb_font_t *font, hb_codepoint_t gid, T consumer) const
const gvar_accelerator_t * gvar
accelerator_t(hb_face_t *face)
const Glyph glyph_for_gid(hb_codepoint_t gid, bool needs_padding_removal=false) const
bool get_path(hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
bool get_extents(hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
int get_side_bearing_var(hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
const vmtx_accelerator_t * vmtx
unsigned get_advance_var(hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
const CompositeGlyphChain * __item_t__
composite_iter_t(hb_bytes_t glyph_, __item_t__ current_)
const CompositeGlyphChain & __item__() const
void set_next(const CompositeGlyphChain *composite)
bool operator!=(const composite_iter_t &o) const
glyf_accelerator_t(hb_face_t *face)
bool subset(hb_subset_context_t *c) const
static bool _add_loca_and_head(hb_subset_plan_t *plan, Iterator padded_offsets, bool use_short_loca)
static void _write_loca(IteratorIn it, unsigned right_shift, IteratorOut dest)
UnsizedArrayOf< HBUINT8 > dataZ
static constexpr hb_tag_t tableTag
bool serialize(hb_serialize_context_t *c, Iterator it, bool use_short_loca, const hb_subset_plan_t *plan)
bool sanitize(hb_sanitize_context_t *c HB_UNUSED) const
static bool _add_head_and_set_loca_version(hb_subset_plan_t *plan, bool use_short_loca)
void _populate_subset_glyphs(const hb_subset_plan_t *plan, hb_vector_t< SubsetGlyph > *glyphs) const
DEFINE_SIZE_MIN(0)
bool apply_deltas_to_points(hb_codepoint_t glyph, hb_font_t *font, const hb_array_t< contour_point_t > points) const
HBUINT16 glyphDataFormat
HBUINT16 indexToLocFormat
UnsizedArrayOf< HBUINT8 > dataZ
bool sanitize(hb_sanitize_context_t *c HB_UNUSED) const
DEFINE_SIZE_MIN(0)
static constexpr hb_tag_t tableTag
Definition: main.cpp:38
bool check_range(const T *p, unsigned int size=T::static_size) const
Definition: hb-array.hh:259
Type * arrayZ
Definition: hb-array.hh:290
hb_array_t copy(hb_serialize_context_t *c) const
Definition: hb-array.hh:271
unsigned int length
Definition: hb-array.hh:291
hb_array_t sub_array(unsigned int start_offset=0, unsigned int *seg_count=nullptr) const
Definition: hb-array.hh:231
unsigned int get_size() const
Definition: hb-array.hh:211
void close_path()
Definition: hb-draw.hh:218
void line_to(float to_x, float to_y)
Definition: hb-draw.hh:180
void move_to(float to_x, float to_y)
Definition: hb-draw.hh:171
void quadratic_to(float control_x, float control_y, float to_x, float to_y)
Definition: hb-draw.hh:190
hb_position_t em_scalef_y(float v)
Definition: hb-font.hh:141
hb_position_t em_scalef_x(float v)
Definition: hb-font.hh:140
float em_fscalef_y(float v)
Definition: hb-font.hh:145
float em_fscalef_x(float v)
Definition: hb-font.hh:144
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
bool has(hb_codepoint_t k) const
Definition: hb-set.hh:111
void add(hb_codepoint_t g)
Definition: hb-set.hh:85
bool old_gid_for_new_gid(hb_codepoint_t new_gid, hb_codepoint_t *old_gid) const
bool new_gid_for_old_gid(hb_codepoint_t old_gid, hb_codepoint_t *new_gid) const
unsigned int num_output_glyphs() const
bool add_table(hb_tag_t tag, hb_blob_t *contents)
hb_face_t * source
c_array_t sub_array(unsigned int start_offset, unsigned int count) const
Definition: hb-vector.hh:163
unsigned int length
Definition: hb-vector.hh:76
int consumer()
Definition: main.cpp:128