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-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 
49 struct loca
50 {
51  friend struct glyf;
52 
53  static constexpr hb_tag_t tableTag = HB_OT_TAG_loca;
54 
56  {
57  TRACE_SANITIZE (this);
58  return_trace (true);
59  }
60 
61  protected:
63  dataZ; /* Location data. */
64  public:
65  DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
66  * check the size externally, allow Null() object of it by
67  * defining it _MIN instead. */
68 };
69 
70 
71 /*
72  * glyf -- TrueType Glyph Data
73  * https://docs.microsoft.com/en-us/typography/opentype/spec/glyf
74  */
75 #define HB_OT_TAG_glyf HB_TAG('g','l','y','f')
76 
77 
78 struct glyf
79 {
80  static constexpr hb_tag_t tableTag = HB_OT_TAG_glyf;
81 
83  {
84  TRACE_SANITIZE (this);
85  /* Runtime checks as eager sanitizing each glyph is costy */
86  return_trace (true);
87  }
88 
89  template<typename Iterator,
90  hb_requires (hb_is_source_of (Iterator, unsigned int))>
91  static bool
92  _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets)
93  {
94  unsigned max_offset =
95  + padded_offsets
96  | hb_reduce (hb_add, 0)
97  ;
98  unsigned num_offsets = padded_offsets.len () + 1;
99  bool use_short_loca = max_offset < 0x1FFFF;
100  unsigned entry_size = use_short_loca ? 2 : 4;
101  char *loca_prime_data = (char *) calloc (entry_size, num_offsets);
102 
103  if (unlikely (!loca_prime_data)) return false;
104 
105  DEBUG_MSG (SUBSET, nullptr, "loca entry_size %d num_offsets %d "
106  "max_offset %d size %d",
107  entry_size, num_offsets, max_offset, entry_size * num_offsets);
108 
109  if (use_short_loca)
110  _write_loca (padded_offsets, 1, hb_array ((HBUINT16 *) loca_prime_data, num_offsets));
111  else
112  _write_loca (padded_offsets, 0, hb_array ((HBUINT32 *) loca_prime_data, num_offsets));
113 
114  hb_blob_t *loca_blob = hb_blob_create (loca_prime_data,
115  entry_size * num_offsets,
117  loca_prime_data,
118  free);
119 
120  bool result = plan->add_table (HB_OT_TAG_loca, loca_blob)
121  && _add_head_and_set_loca_version (plan, use_short_loca);
122 
123  hb_blob_destroy (loca_blob);
124  return result;
125  }
126 
127  template<typename IteratorIn, typename IteratorOut,
128  hb_requires (hb_is_source_of (IteratorIn, unsigned int)),
129  hb_requires (hb_is_sink_of (IteratorOut, unsigned))>
130  static void
131  _write_loca (IteratorIn it, unsigned right_shift, IteratorOut dest)
132  {
133  unsigned int offset = 0;
134  dest << 0;
135  + it
136  | hb_map ([=, &offset] (unsigned int padded_size)
137  {
138  offset += padded_size;
139  DEBUG_MSG (SUBSET, nullptr, "loca entry offset %d", offset);
140  return offset >> right_shift;
141  })
142  | hb_sink (dest)
143  ;
144  }
145 
146  /* requires source of SubsetGlyph complains the identifier isn't declared */
147  template <typename Iterator>
149  Iterator it,
150  const hb_subset_plan_t *plan)
151  {
152  TRACE_SERIALIZE (this);
153  unsigned init_len = c->length ();
154  for (const auto &_ : it) _.serialize (c, plan);
155 
156  /* As a special case when all glyph in the font are empty, add a zero byte
157  * to the table, so that OTS doesn’t reject it, and to make the table work
158  * on Windows as well.
159  * See https://github.com/khaledhosny/ots/issues/52 */
160  if (init_len == c->length ())
161  {
162  HBUINT8 empty_byte;
163  empty_byte = 0;
164  c->copy (empty_byte);
165  }
166  return_trace (true);
167  }
168 
169  /* Byte region(s) per glyph to output
170  unpadded, hints removed if so requested
171  If we fail to process a glyph we produce an empty (0-length) glyph */
173  {
174  TRACE_SUBSET (this);
175 
176  glyf *glyf_prime = c->serializer->start_embed <glyf> ();
177  if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
178 
180  _populate_subset_glyphs (c->plan, &glyphs);
181 
182  glyf_prime->serialize (c->serializer, hb_iter (glyphs), c->plan);
183 
184  auto padded_offsets =
185  + hb_iter (glyphs)
187  ;
188 
189  if (c->serializer->in_error ()) return_trace (false);
190  return_trace (c->serializer->check_success (_add_loca_and_head (c->plan,
191  padded_offsets)));
192  }
193 
194  template <typename SubsetGlyph>
195  void
197  hb_vector_t<SubsetGlyph> *glyphs /* OUT */) const
198  {
200  glyf.init (plan->source);
201 
202  + hb_range (plan->num_output_glyphs ())
203  | hb_map ([&] (hb_codepoint_t new_gid)
204  {
206  subset_glyph.new_gid = new_gid;
207 
208  /* should never fail: all old gids should be mapped */
209  if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid))
210  return subset_glyph;
211 
212  subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
213  if (plan->drop_hints) subset_glyph.drop_hints_bytes ();
214  else subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
215 
216  return subset_glyph;
217  })
218  | hb_sink (glyphs)
219  ;
220 
221  glyf.fini ();
222  }
223 
224  static bool
226  {
227  hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<head> (plan->source);
228  hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
229  hb_blob_destroy (head_blob);
230 
231  if (unlikely (!head_prime_blob))
232  return false;
233 
234  head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
235  head_prime->indexToLocFormat = use_short_loca ? 0 : 1;
236  bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
237 
238  hb_blob_destroy (head_prime_blob);
239  return success;
240  }
241 
242  struct CompositeGlyphChain
243  {
244  protected:
246  {
247  ARG_1_AND_2_ARE_WORDS = 0x0001,
248  ARGS_ARE_XY_VALUES = 0x0002,
249  ROUND_XY_TO_GRID = 0x0004,
250  WE_HAVE_A_SCALE = 0x0008,
251  MORE_COMPONENTS = 0x0020,
252  WE_HAVE_AN_X_AND_Y_SCALE = 0x0040,
253  WE_HAVE_A_TWO_BY_TWO = 0x0080,
254  WE_HAVE_INSTRUCTIONS = 0x0100,
255  USE_MY_METRICS = 0x0200,
256  OVERLAP_COMPOUND = 0x0400,
257  SCALED_COMPONENT_OFFSET = 0x0800,
259  };
260 
261  public:
262  unsigned int get_size () const
263  {
264  unsigned int size = min_size;
265  /* arg1 and 2 are int16 */
266  if (flags & ARG_1_AND_2_ARE_WORDS) size += 4;
267  /* arg1 and 2 are int8 */
268  else size += 2;
269 
270  /* One x 16 bit (scale) */
271  if (flags & WE_HAVE_A_SCALE) size += 2;
272  /* Two x 16 bit (xscale, yscale) */
273  else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) size += 4;
274  /* Four x 16 bit (xscale, scale01, scale10, yscale) */
275  else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8;
276 
277  return size;
278  }
279 
280  void set_glyph_index (hb_codepoint_t new_gid) { glyphIndex = new_gid; }
282 
284  bool has_instructions () const { return flags & WE_HAVE_INSTRUCTIONS; }
285 
286  bool has_more () const { return flags & MORE_COMPONENTS; }
287  bool is_use_my_metrics () const { return flags & USE_MY_METRICS; }
288  bool is_anchored () const { return !(flags & ARGS_ARE_XY_VALUES); }
289  void get_anchor_points (unsigned int &point1, unsigned int &point2) const
290  {
291  const HBUINT8 *p = &StructAfter<const HBUINT8> (glyphIndex);
293  {
294  point1 = ((const HBUINT16 *) p)[0];
295  point2 = ((const HBUINT16 *) p)[1];
296  }
297  else
298  {
299  point1 = p[0];
300  point2 = p[1];
301  }
302  }
303 
305  {
306  float matrix[4];
309  {
310  if (scaled_offsets ())
311  {
312  points.translate (trans);
313  points.transform (matrix);
314  }
315  else
316  {
317  points.transform (matrix);
318  points.translate (trans);
319  }
320  }
321  }
322 
323  protected:
324  bool scaled_offsets () const
326 
327  bool get_transformation (float (&matrix)[4], contour_point_t &trans) const
328  {
329  matrix[0] = matrix[3] = 1.f;
330  matrix[1] = matrix[2] = 0.f;
331 
332  int tx, ty;
333  const HBINT8 *p = &StructAfter<const HBINT8> (glyphIndex);
335  {
336  tx = *(const HBINT16 *) p;
338  ty = *(const HBINT16 *) p;
340  }
341  else
342  {
343  tx = *p++;
344  ty = *p++;
345  }
346  if (is_anchored ()) tx = ty = 0;
347 
348  trans.init ((float) tx, (float) ty);
349 
350  {
351  const F2DOT14 *points = (const F2DOT14 *) p;
352  if (flags & WE_HAVE_A_SCALE)
353  {
354  matrix[0] = matrix[3] = points[0].to_float ();
355  return true;
356  }
357  else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
358  {
359  matrix[0] = points[0].to_float ();
360  matrix[3] = points[1].to_float ();
361  return true;
362  }
363  else if (flags & WE_HAVE_A_TWO_BY_TWO)
364  {
365  matrix[0] = points[0].to_float ();
366  matrix[1] = points[1].to_float ();
367  matrix[2] = points[2].to_float ();
368  matrix[3] = points[3].to_float ();
369  return true;
370  }
371  }
372  return tx || ty;
373  }
374 
375  protected:
376  HBUINT16 flags;
378  public:
380  };
381 
382  struct composite_iter_t : hb_iter_with_fallback_t<composite_iter_t, const CompositeGlyphChain &>
383  {
386  glyph (glyph_), current (current_)
387  { if (!check_range (current)) current = nullptr; }
389 
390  const CompositeGlyphChain &__item__ () const { return *current; }
391  bool __more__ () const { return current; }
392  void __next__ ()
393  {
394  if (!current->has_more ()) { current = nullptr; return; }
395 
397  CompositeGlyphChain> (*current);
398  if (!check_range (possible)) { current = nullptr; return; }
399  current = possible;
400  }
401  bool operator != (const composite_iter_t& o) const
402  { return glyph != o.glyph || current != o.current; }
403 
405  {
406  return glyph.check_range (composite, CompositeGlyphChain::min_size)
407  && glyph.check_range (composite, composite->get_size ());
408  }
409 
410  private:
413  };
414 
416  {
417  PHANTOM_LEFT = 0,
418  PHANTOM_RIGHT = 1,
419  PHANTOM_TOP = 2,
420  PHANTOM_BOTTOM = 3,
421  PHANTOM_COUNT = 4
422  };
423 
424  struct accelerator_t;
425 
426  struct Glyph
427  {
429  {
430  FLAG_ON_CURVE = 0x01,
431  FLAG_X_SHORT = 0x02,
432  FLAG_Y_SHORT = 0x04,
433  FLAG_REPEAT = 0x08,
434  FLAG_X_SAME = 0x10,
435  FLAG_Y_SAME = 0x20,
436  FLAG_RESERVED1 = 0x40,
437  FLAG_RESERVED2 = 0x80
438  };
439 
440  private:
441  struct GlyphHeader
442  {
443  bool has_data () const { return numberOfContours; }
444 
445  bool get_extents (hb_font_t *font, const accelerator_t &glyf_accelerator,
447  {
448  /* Undocumented rasterizer behavior: shift glyph to the left by (lsb - xMin), i.e., xMin = lsb */
449  /* extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax); */
450  extents->x_bearing = font->em_scale_x (glyf_accelerator.hmtx->get_side_bearing (gid));
451  extents->y_bearing = font->em_scale_y (hb_max (yMin, yMax));
452  extents->width = font->em_scale_x (hb_max (xMin, xMax) - hb_min (xMin, xMax));
453  extents->height = font->em_scale_y (hb_min (yMin, yMax) - hb_max (yMin, yMax));
454 
455  return true;
456  }
457 
459  /* If the number of contours is
460  * greater than or equal to zero,
461  * this is a simple glyph; if negative,
462  * this is a composite glyph. */
463  FWORD xMin; /* Minimum x for coordinate data. */
464  FWORD yMin; /* Minimum y for coordinate data. */
465  FWORD xMax; /* Maximum x for coordinate data. */
466  FWORD yMax; /* Maximum y for coordinate data. */
467  public:
469  };
470 
471  struct SimpleGlyph
472  {
473  const GlyphHeader &header;
475  SimpleGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
476  header (header_), bytes (bytes_) {}
477 
478  unsigned int instruction_len_offset () const
479  { return GlyphHeader::static_size + 2 * header.numberOfContours; }
480 
481  unsigned int length (unsigned int instruction_len) const
482  { return instruction_len_offset () + 2 + instruction_len; }
483 
484  unsigned int instructions_length () const
485  {
486  unsigned int instruction_length_offset = instruction_len_offset ();
487  if (unlikely (instruction_length_offset + 2 > bytes.length)) return 0;
488 
489  const HBUINT16 &instructionLength = StructAtOffset<HBUINT16> (&bytes, instruction_length_offset);
490  /* Out of bounds of the current glyph */
491  if (unlikely (length (instructionLength) > bytes.length)) return 0;
492  return instructionLength;
493  }
494 
495  const Glyph trim_padding () const
496  {
497  /* based on FontTools _g_l_y_f.py::trim */
498  const char *glyph = bytes.arrayZ;
499  const char *glyph_end = glyph + bytes.length;
500  /* simple glyph w/contours, possibly trimmable */
502 
503  if (unlikely (glyph + 2 >= glyph_end)) return Glyph ();
504  unsigned int num_coordinates = StructAtOffset<HBUINT16> (glyph - 2, 0) + 1;
505  unsigned int num_instructions = StructAtOffset<HBUINT16> (glyph, 0);
506 
507  glyph += 2 + num_instructions;
508 
509  unsigned int coord_bytes = 0;
510  unsigned int coords_with_flags = 0;
511  while (glyph < glyph_end)
512  {
513  uint8_t flag = *glyph;
514  glyph++;
515 
516  unsigned int repeat = 1;
517  if (flag & FLAG_REPEAT)
518  {
519  if (unlikely (glyph >= glyph_end)) return Glyph ();
520  repeat = *glyph + 1;
521  glyph++;
522  }
523 
524  unsigned int xBytes, yBytes;
525  xBytes = yBytes = 0;
526  if (flag & FLAG_X_SHORT) xBytes = 1;
527  else if ((flag & FLAG_X_SAME) == 0) xBytes = 2;
528 
529  if (flag & FLAG_Y_SHORT) yBytes = 1;
530  else if ((flag & FLAG_Y_SAME) == 0) yBytes = 2;
531 
532  coord_bytes += (xBytes + yBytes) * repeat;
533  coords_with_flags += repeat;
534  if (coords_with_flags >= num_coordinates) break;
535  }
536 
537  if (unlikely (coords_with_flags != num_coordinates)) return Glyph ();
538  return Glyph (bytes.sub_array (0, bytes.length + coord_bytes - (glyph_end - glyph)));
539  }
540 
541  /* zero instruction length */
542  void drop_hints ()
543  {
544  GlyphHeader &glyph_header = const_cast<GlyphHeader &> (header);
545  (HBUINT16 &) StructAtOffset<HBUINT16> (&glyph_header, instruction_len_offset ()) = 0;
546  }
547 
548  void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
549  {
550  unsigned int instructions_len = instructions_length ();
551  unsigned int glyph_length = length (instructions_len);
552  dest_start = bytes.sub_array (0, glyph_length - instructions_len);
554  }
555 
556  static bool read_points (const HBUINT8 *&p /* IN/OUT */,
557  contour_point_vector_t &points_ /* IN/OUT */,
558  const hb_bytes_t &bytes,
559  void (* setter) (contour_point_t &_, float v),
560  const simple_glyph_flag_t short_flag,
561  const simple_glyph_flag_t same_flag)
562  {
563  float v = 0;
564  for (unsigned i = 0; i < points_.length; i++)
565  {
566  uint8_t flag = points_[i].flag;
567  if (flag & short_flag)
568  {
569  if (unlikely (!bytes.check_range (p))) return false;
570  if (flag & same_flag)
571  v += *p++;
572  else
573  v -= *p++;
574  }
575  else
576  {
577  if (!(flag & same_flag))
578  {
579  if (unlikely (!bytes.check_range ((const HBUINT16 *) p))) return false;
580  v += *(const HBINT16 *) p;
582  }
583  }
584  setter (points_[i], v);
585  }
586  return true;
587  }
588 
589  bool get_contour_points (contour_point_vector_t &points_ /* OUT */,
590  bool phantom_only = false) const
591  {
592  const HBUINT16 *endPtsOfContours = &StructAfter<HBUINT16> (header);
593  int num_contours = header.numberOfContours;
594  if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours + 1]))) return false;
595  unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
596 
597  points_.resize (num_points);
598  for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
599  if (phantom_only) return true;
600 
601  for (int i = 0; i < num_contours; i++)
602  points_[endPtsOfContours[i]].is_end_point = true;
603 
604  /* Skip instructions */
605  const HBUINT8 *p = &StructAtOffset<HBUINT8> (&endPtsOfContours[num_contours + 1],
606  endPtsOfContours[num_contours]);
607 
608  /* Read flags */
609  for (unsigned int i = 0; i < num_points; i++)
610  {
611  if (unlikely (!bytes.check_range (p))) return false;
612  uint8_t flag = *p++;
613  points_[i].flag = flag;
614  if (flag & FLAG_REPEAT)
615  {
616  if (unlikely (!bytes.check_range (p))) return false;
617  unsigned int repeat_count = *p++;
618  while ((repeat_count-- > 0) && (++i < num_points))
619  points_[i].flag = flag;
620  }
621  }
622 
623  /* Read x & y coordinates */
624  return read_points (p, points_, bytes, [] (contour_point_t &p, float v) { p.x = v; },
626  && read_points (p, points_, bytes, [] (contour_point_t &p, float v) { p.y = v; },
628  }
629  };
630 
631  struct CompositeGlyph
632  {
633  const GlyphHeader &header;
635  CompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
636  header (header_), bytes (bytes_) {}
637 
639  { return composite_iter_t (bytes, &StructAfter<CompositeGlyphChain, GlyphHeader> (header)); }
640 
641  unsigned int instructions_length (hb_bytes_t bytes) const
642  {
643  unsigned int start = bytes.length;
644  unsigned int end = bytes.length;
645  const CompositeGlyphChain *last = nullptr;
646  for (auto &item : get_iterator ())
647  last = &item;
648  if (unlikely (!last)) return 0;
649 
650  if (last->has_instructions ())
651  start = (char *) last - &bytes + last->get_size ();
652  if (unlikely (start > end)) return 0;
653  return end - start;
654  }
655 
656  /* Trimming for composites not implemented.
657  * If removing hints it falls out of that. */
658  const Glyph trim_padding () const { return Glyph (bytes); }
659 
660  void drop_hints ()
661  {
662  for (const auto &_ : get_iterator ())
663  const_cast<CompositeGlyphChain &> (_).drop_instructions_flag ();
664  }
665 
666  /* Chop instructions off the end */
667  void drop_hints_bytes (hb_bytes_t &dest_start) const
668  { dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
669  };
670 
672 
673  public:
675  {
676  if (type != COMPOSITE) return composite_iter_t ();
677  return CompositeGlyph (*header, bytes).get_iterator ();
678  }
679 
680  const Glyph trim_padding () const
681  {
682  switch (type) {
683  case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding ();
684  case SIMPLE: return SimpleGlyph (*header, bytes).trim_padding ();
685  default: return bytes;
686  }
687  }
688 
689  void drop_hints ()
690  {
691  switch (type) {
692  case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
693  case SIMPLE: SimpleGlyph (*header, bytes).drop_hints (); return;
694  default: return;
695  }
696  }
697 
698  void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
699  {
700  switch (type) {
701  case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return;
702  case SIMPLE: SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return;
703  default: return;
704  }
705  }
706 
707  /* Note: Recursively calls itself.
708  * all_points includes phantom points
709  */
710  bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
711  contour_point_vector_t &all_points /* OUT */,
712  bool phantom_only = false,
713  unsigned int depth = 0) const
714  {
715  if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
717 
718  switch (type) {
719  case COMPOSITE:
720  {
721  /* pseudo component points for each component in composite glyph */
722  unsigned num_points = hb_len (CompositeGlyph (*header, bytes).get_iterator ());
723  if (unlikely (!points.resize (num_points))) return false;
724  for (unsigned i = 0; i < points.length; i++)
725  points[i].init ();
726  break;
727  }
728  case SIMPLE:
729  if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
730  return false;
731  break;
732  }
733 
734  /* Init phantom points */
735  if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
736  hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
737  {
738  for (unsigned i = 0; i < PHANTOM_COUNT; ++i) phantoms[i].init ();
739  int h_delta = (int) header->xMin - glyf_accelerator.hmtx->get_side_bearing (gid);
740  int v_orig = (int) header->yMax + glyf_accelerator.vmtx->get_side_bearing (gid);
741  unsigned h_adv = glyf_accelerator.hmtx->get_advance (gid);
742  unsigned v_adv = glyf_accelerator.vmtx->get_advance (gid);
743  phantoms[PHANTOM_LEFT].x = h_delta;
744  phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
745  phantoms[PHANTOM_TOP].y = v_orig;
746  phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
747  }
748 
749 #ifndef HB_NO_VAR
750  if (unlikely (!glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ())))
751  return false;
752 #endif
753 
754  switch (type) {
755  case SIMPLE:
756  all_points.extend (points.as_array ());
757  break;
758  case COMPOSITE:
759  {
760  unsigned int comp_index = 0;
761  for (auto &item : get_composite_iterator ())
762  {
763  contour_point_vector_t comp_points;
764  if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_glyph_index ())
765  .get_points (font, glyf_accelerator, comp_points,
766  phantom_only, depth + 1)
767  || comp_points.length < PHANTOM_COUNT))
768  return false;
769 
770  /* Copy phantom points from component if USE_MY_METRICS flag set */
771  if (item.is_use_my_metrics ())
772  for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
773  phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
774 
775  /* Apply component transformation & translation */
776  item.transform_points (comp_points);
777 
778  /* Apply translation from gvar */
779  comp_points.translate (points[comp_index]);
780 
781  if (item.is_anchored ())
782  {
783  unsigned int p1, p2;
784  item.get_anchor_points (p1, p2);
785  if (likely (p1 < all_points.length && p2 < comp_points.length))
786  {
788  delta.init (all_points[p1].x - comp_points[p2].x,
789  all_points[p1].y - comp_points[p2].y);
790 
791  comp_points.translate (delta);
792  }
793  }
794 
795  all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT));
796 
797  comp_index++;
798  }
799 
800  all_points.extend (phantoms);
801  } break;
802  default:
803  all_points.extend (phantoms);
804  }
805 
806  if (depth == 0) /* Apply at top level */
807  {
808  /* Undocumented rasterizer behavior:
809  * Shift points horizontally by the updated left side bearing
810  */
812  delta.init (-phantoms[PHANTOM_LEFT].x, 0.f);
813  if (delta.x) all_points.translate (delta);
814  }
815 
816  return true;
817  }
818 
819  bool get_extents (hb_font_t *font, const accelerator_t &glyf_accelerator,
821  {
822  if (type == EMPTY) return true; /* Empty glyph; zero extents. */
823  return header->get_extents (font, glyf_accelerator, gid, extents);
824  }
825 
826  hb_bytes_t get_bytes () const { return bytes; }
827 
829  hb_codepoint_t gid_ = (hb_codepoint_t) -1) : bytes (bytes_), gid (gid_),
830  header (bytes.as<GlyphHeader> ())
831  {
832  int num_contours = header->numberOfContours;
833  if (unlikely (num_contours == 0)) type = EMPTY;
834  else if (num_contours > 0) type = SIMPLE;
835  else type = COMPOSITE; /* negative numbers */
836  }
837 
838  protected:
841  const GlyphHeader *header;
842  unsigned type;
843  };
844 
845  struct accelerator_t
846  {
847  void init (hb_face_t *face_)
848  {
849  short_offset = false;
850  num_glyphs = 0;
851  loca_table = nullptr;
852  glyf_table = nullptr;
853 #ifndef HB_NO_VAR
854  gvar = nullptr;
855 #endif
856  hmtx = nullptr;
857  vmtx = nullptr;
858  face = face_;
859  const OT::head &head = *face->table.head;
860  if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
861  /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
862  return;
864 
867 #ifndef HB_NO_VAR
868  gvar = face->table.gvar;
869 #endif
870  hmtx = face->table.hmtx;
871  vmtx = face->table.vmtx;
872 
873  num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
875  }
876 
877  void fini ()
878  {
879  loca_table.destroy ();
880  glyf_table.destroy ();
881  }
882 
883  protected:
884  template<typename T>
885  bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) const
886  {
887  if (gid >= num_glyphs) return false;
888 
889  /* Making this alloc free is not that easy
890  https://github.com/harfbuzz/harfbuzz/issues/2095
891  mostly because of gvar handling in VF fonts,
892  perhaps a separate path for non-VF fonts can be considered */
893  contour_point_vector_t all_points;
894 
895  bool phantom_only = !consumer.is_consuming_contour_points ();
896  if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, phantom_only)))
897  return false;
898 
899  if (consumer.is_consuming_contour_points ())
900  {
901  for (unsigned point_index = 0; point_index + 4 < all_points.length; ++point_index)
902  consumer.consume_point (all_points[point_index]);
903  consumer.points_end ();
904  }
905 
906  /* Where to write phantoms, nullptr if not requested */
907  contour_point_t *phantoms = consumer.get_phantoms_sink ();
908  if (phantoms)
909  for (unsigned i = 0; i < PHANTOM_COUNT; ++i)
910  phantoms[i] = all_points[all_points.length - PHANTOM_COUNT + i];
911 
912  return true;
913  }
914 
915 #ifndef HB_NO_VAR
916  struct points_aggregator_t
917  {
918  hb_font_t *font;
921 
922  struct contour_bounds_t
923  {
925 
926  void add (const contour_point_t &p)
927  {
928  min_x = hb_min (min_x, p.x);
929  min_y = hb_min (min_y, p.y);
930  max_x = hb_max (max_x, p.x);
931  max_y = hb_max (max_y, p.y);
932  }
933 
934  bool empty () const { return (min_x >= max_x) || (min_y >= max_y); }
935 
937  {
938  if (unlikely (empty ()))
939  {
940  extents->width = 0;
941  extents->x_bearing = 0;
942  extents->height = 0;
943  extents->y_bearing = 0;
944  return;
945  }
946  extents->x_bearing = font->em_scalef_x (min_x);
947  extents->width = font->em_scalef_x (max_x - min_x);
948  extents->y_bearing = font->em_scalef_y (max_y);
949  extents->height = font->em_scalef_y (min_y - max_y);
950  }
951 
952  protected:
953  float min_x, min_y, max_x, max_y;
954  } bounds;
955 
957  {
958  font = font_;
959  extents = extents_;
960  phantoms = phantoms_;
961  if (extents) bounds = contour_bounds_t ();
962  }
963 
966 
969  };
970 
971  public:
972  unsigned
974  {
975  if (unlikely (gid >= num_glyphs)) return 0;
976 
977  bool success = false;
978 
979  contour_point_t phantoms[PHANTOM_COUNT];
980  if (likely (font->num_coords == gvar->get_axis_count ()))
981  success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms));
982 
983  if (unlikely (!success))
984  return is_vertical ? vmtx->get_advance (gid) : hmtx->get_advance (gid);
985 
986  float result = is_vertical
987  ? phantoms[PHANTOM_TOP].y - phantoms[PHANTOM_BOTTOM].y
988  : phantoms[PHANTOM_RIGHT].x - phantoms[PHANTOM_LEFT].x;
989  return hb_clamp (roundf (result), 0.f, (float) UINT_MAX / 2);
990  }
991 
993  {
994  if (unlikely (gid >= num_glyphs)) return 0;
995 
997 
998  contour_point_t phantoms[PHANTOM_COUNT];
999  if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms))))
1000  return is_vertical ? vmtx->get_side_bearing (gid) : hmtx->get_side_bearing (gid);
1001 
1002  return is_vertical
1003  ? ceilf (phantoms[PHANTOM_TOP].y) - extents.y_bearing
1004  : floorf (phantoms[PHANTOM_LEFT].x);
1005  }
1006 #endif
1007 
1008  public:
1010  {
1011  if (unlikely (gid >= num_glyphs)) return false;
1012 
1013 #ifndef HB_NO_VAR
1014  if (font->num_coords && font->num_coords == gvar->get_axis_count ())
1015  return get_points (font, gid, points_aggregator_t (font, extents, nullptr));
1016 #endif
1017  return glyph_for_gid (gid).get_extents (font, *this, extents);
1018  }
1019 
1020  const Glyph
1021  glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const
1022  {
1023  if (unlikely (gid >= num_glyphs)) return Glyph ();
1024 
1025  unsigned int start_offset, end_offset;
1026 
1027  if (short_offset)
1028  {
1029  const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ;
1030  start_offset = 2 * offsets[gid];
1031  end_offset = 2 * offsets[gid + 1];
1032  }
1033  else
1034  {
1035  const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ;
1036  start_offset = offsets[gid];
1037  end_offset = offsets[gid + 1];
1038  }
1039 
1040  if (unlikely (start_offset > end_offset || end_offset > glyf_table.get_length ()))
1041  return Glyph ();
1042 
1043  Glyph glyph (hb_bytes_t ((const char *) this->glyf_table + start_offset,
1044  end_offset - start_offset), gid);
1045  return needs_padding_removal ? glyph.trim_padding () : glyph;
1046  }
1047 
1048  void
1050  unsigned int depth = 0) const
1051  {
1052  if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return;
1053  /* Check if is already visited */
1054  if (gids_to_retain->has (gid)) return;
1055 
1056  gids_to_retain->add (gid);
1057 
1058  for (auto &item : glyph_for_gid (gid).get_composite_iterator ())
1059  add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth);
1060  }
1061 
1062 #ifdef HB_EXPERIMENTAL_API
1063  struct path_builder_t
1064  {
1065  hb_font_t *font;
1066  draw_helper_t *draw_helper;
1067 
1068  struct optional_point_t
1069  {
1070  optional_point_t () { has_data = false; }
1071  optional_point_t (float x_, float y_) { x = x_; y = y_; has_data = true; }
1072 
1073  bool has_data;
1074  float x;
1075  float y;
1076 
1077  optional_point_t lerp (optional_point_t p, float t)
1078  { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
1079  } first_oncurve, first_offcurve, last_offcurve;
1080 
1081  path_builder_t (hb_font_t *font_, draw_helper_t &draw_helper_)
1082  {
1083  font = font_;
1084  draw_helper = &draw_helper_;
1085  first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
1086  }
1087 
1088  /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
1089  See also:
1090  * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
1091  * https://stackoverflow.com/a/20772557 */
1092  void consume_point (const contour_point_t &point)
1093  {
1094  /* Skip empty contours */
1095  if (unlikely (point.is_end_point && !first_oncurve.has_data && !first_offcurve.has_data))
1096  return;
1097 
1098  bool is_on_curve = point.flag & Glyph::FLAG_ON_CURVE;
1099  optional_point_t p (point.x, point.y);
1100  if (!first_oncurve.has_data)
1101  {
1102  if (is_on_curve)
1103  {
1104  first_oncurve = p;
1105  draw_helper->move_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y));
1106  }
1107  else
1108  {
1109  if (first_offcurve.has_data)
1110  {
1111  optional_point_t mid = first_offcurve.lerp (p, .5f);
1112  first_oncurve = mid;
1113  last_offcurve = p;
1114  draw_helper->move_to (font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
1115  }
1116  else
1117  first_offcurve = p;
1118  }
1119  }
1120  else
1121  {
1122  if (last_offcurve.has_data)
1123  {
1124  if (is_on_curve)
1125  {
1126  draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
1127  font->em_scalef_x (p.x), font->em_scalef_y (p.y));
1128  last_offcurve = optional_point_t ();
1129  }
1130  else
1131  {
1132  optional_point_t mid = last_offcurve.lerp (p, .5f);
1133  draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
1134  font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
1135  last_offcurve = p;
1136  }
1137  }
1138  else
1139  {
1140  if (is_on_curve)
1141  draw_helper->line_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y));
1142  else
1143  last_offcurve = p;
1144  }
1145  }
1146 
1147  if (point.is_end_point)
1148  {
1149  if (first_offcurve.has_data && last_offcurve.has_data)
1150  {
1151  optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
1152  draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
1153  font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
1154  last_offcurve = optional_point_t ();
1155  /* now check the rest */
1156  }
1157 
1158  if (first_offcurve.has_data && first_oncurve.has_data)
1159  draw_helper->quadratic_to (font->em_scalef_x (first_offcurve.x), font->em_scalef_y (first_offcurve.y),
1160  font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
1161  else if (last_offcurve.has_data && first_oncurve.has_data)
1162  draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
1163  font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
1164  else if (first_oncurve.has_data)
1165  draw_helper->line_to (font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
1166 
1167  /* Getting ready for the next contour */
1168  first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
1169  draw_helper->end_path ();
1170  }
1171  }
1172  void points_end () {}
1173 
1174  bool is_consuming_contour_points () { return true; }
1175  contour_point_t *get_phantoms_sink () { return nullptr; }
1176  };
1177 
1178  bool
1179  get_path (hb_font_t *font, hb_codepoint_t gid, draw_helper_t &draw_helper) const
1180  { return get_points (font, gid, path_builder_t (font, draw_helper)); }
1181 #endif
1182 
1183 #ifndef HB_NO_VAR
1184  const gvar_accelerator_t *gvar;
1185 #endif
1186  const hmtx_accelerator_t *hmtx;
1187  const vmtx_accelerator_t *vmtx;
1188 
1189  private:
1190  bool short_offset;
1191  unsigned int num_glyphs;
1194  hb_face_t *face;
1195  };
1196 
1197  struct SubsetGlyph
1198  {
1202  hb_bytes_t dest_start; /* region of source_glyph to copy first */
1203  hb_bytes_t dest_end; /* region of source_glyph to copy second */
1204 
1206  const hb_subset_plan_t *plan) const
1207  {
1208  TRACE_SERIALIZE (this);
1209 
1210  hb_bytes_t dest_glyph = dest_start.copy (c);
1211  dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length);
1212  unsigned int pad_length = padding ();
1213  DEBUG_MSG (SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
1214 
1215  HBUINT8 pad;
1216  pad = 0;
1217  while (pad_length > 0)
1218  {
1219  c->embed (pad);
1220  pad_length--;
1221  }
1222 
1223  if (unlikely (!dest_glyph.length)) return_trace (true);
1224 
1225  /* update components gids */
1226  for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
1227  {
1229  if (plan->new_gid_for_old_gid (_.get_glyph_index (), &new_gid))
1230  const_cast<CompositeGlyphChain &> (_).set_glyph_index (new_gid);
1231  }
1232 
1233  if (plan->drop_hints) Glyph (dest_glyph).drop_hints ();
1234 
1235  return_trace (true);
1236  }
1237 
1240 
1241  unsigned int length () const { return dest_start.length + dest_end.length; }
1242  /* pad to 2 to ensure 2-byte loca will be ok */
1243  unsigned int padding () const { return length () % 2; }
1244  unsigned int padded_size () const { return length () + padding (); }
1245  };
1246 
1247  protected:
1249  dataZ; /* Glyphs data. */
1250  public:
1251  DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
1252  * check the size externally, allow Null() object of it by
1253  * defining it _MIN instead. */
1254 };
1255 
1257 
1258 } /* namespace OT */
1259 
1260 
1261 #endif /* HB_OT_GLYF_TABLE_HH */
__inline float __cdecl ceilf(float _X)
Definition: CPAL.d:18923
__inline float __cdecl floorf(float _X)
Definition: CPAL.d:18965
#define font
Definition: aptex-macros.h:175
#define depth(a)
Definition: aptex-macros.h:199
char * p2
Definition: bmpfont.h:62
char * p1
Definition: bmpfont.h:62
static int item
Definition: brushtopbm.c:66
#define lerp(a, b)
unsigned long Glyph
#define Glyph
#define free(a)
Definition: decNumber.cpp:310
void glyphs(int opcode)
Definition: disdvi.c:775
int v
Definition: dviconv.c:10
static unsigned int glyph_length(char **glyphs)
Definition: ttf.c:471
long int flag
Definition: f2c.h:53
#define T
Definition: fmt.h:20
#define _(String)
Definition: ftxerr18.c:64
#define c(n)
Definition: gpos-common.c:150
pad
Definition: in_pcx.cpp:455
#define likely(x)
Definition: jbig2arith.cc:115
#define unlikely(x)
Definition: jbig2arith.cc:116
small capitals from c petite p
Definition: afcover.h:72
small capitals from c petite p scientific i
Definition: afcover.h:80
kerning y
Definition: ttdriver.c:212
int int double double double char double points
Definition: gdfx.h:18
unsigned char uint8_t
Definition: stdint.h:78
voidp calloc()
char is_vertical(int font_id)
Definition: tfm.c:781
#define FLT_MAX
Definition: c-minmax.h:81
#define UINT_MAX
Definition: c-minmax.h:56
#define dest
char * as
Definition: fixwrites.c:8
Definition: hb-iter.hh:336
static auto end(Iterable &&iterable) -> decltype((hb_iter(iterable).end()))
Definition: hb-iter.hh:344
float x
Definition: cordic.py:15
static int delta
Definition: pbmtolj.c:36
float ** matrix()
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 init[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 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 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
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
void composite()
static int repeat
Definition: pnmtops.c:230
static int32_t last
Definition: ppagelist.c:29
static int size
Definition: ppmlabel.c:24
static int offset
Definition: ppmtogif.c:642
struct @1026 hb_clamp
struct @1025 hb_max
struct @1028 hb_add
struct @1024 hb_min
hb_array_t< T > hb_array(T *array, unsigned int length)
Definition: hb-array.hh:263
hb_array_t< const char > hb_bytes_t
Definition: hb-array.hh:403
hb_blob_t * hb_blob_copy_writable_or_fail(hb_blob_t *blob)
Definition: hb-blob.cc:164
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
char * hb_blob_get_data_writable(hb_blob_t *blob, unsigned int *length)
Definition: hb-blob.cc:366
@ 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 DEBUG_MSG(WHAT, OBJ,...)
Definition: hb-debug.hh:232
#define return_trace(RET)
Definition: hb-debug.hh:349
#define TRACE_SUBSET(this)
Definition: hb-debug.hh:438
struct @1054 hb_sink
struct @1040 hb_len
struct @1045 hb_reduce
struct @1039 hb_iter
struct @1048 hb_range
struct @1041 hb_map
#define DEFINE_SIZE_MIN(size)
static const Type & StructAfter(const TObject &X)
Definition: hb-machinery.hh:72
#define DEFINE_SIZE_STATIC(size)
Definition: hb-machinery.hh:98
#define hb_requires(Cond)
Definition: hb-meta.hh:59
#define HB_OT_TAG_head
#define HB_MAX_NESTING_LEVEL
#define HB_UNUSED
Definition: hb.hh:260
#define roundf(x)
Definition: hb.hh:514
#define HB_OT_TAG_glyf
#define HB_OT_TAG_loca
#define flag
Definition: round_prec.c:45
#define uint16_t
Definition: stdint.in.h:161
static constexpr unsigned static_size
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)
static constexpr unsigned min_size
hb_codepoint_t get_glyph_index() const
bool get_transformation(float(&matrix)[4], contour_point_t &trans) const
void drop_hints_bytes(hb_bytes_t &dest_start) const
composite_iter_t get_iterator() const
unsigned int instructions_length(hb_bytes_t bytes) const
CompositeGlyph(const GlyphHeader &header_, hb_bytes_t bytes_)
bool get_extents(hb_font_t *font, const accelerator_t &glyf_accelerator, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
static constexpr unsigned static_size
SimpleGlyph(const GlyphHeader &header_, hb_bytes_t bytes_)
unsigned int instruction_len_offset() const
unsigned int instructions_length() const
bool get_contour_points(contour_point_vector_t &points_, bool phantom_only=false) const
const Glyph trim_padding() const
static bool read_points(const HBUINT8 *&p, contour_point_vector_t &points_, const hb_bytes_t &bytes, void(*setter)(contour_point_t &_, float v), const simple_glyph_flag_t short_flag, const simple_glyph_flag_t same_flag)
void drop_hints_bytes(hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
unsigned int length(unsigned int instruction_len) 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 Glyph trim_padding() const
hb_codepoint_t gid
void drop_hints_bytes(hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
const GlyphHeader * header
bool serialize(hb_serialize_context_t *c, const hb_subset_plan_t *plan) const
unsigned int padding() const
unsigned int length() const
unsigned int padded_size() const
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_)
hb_blob_ptr_t< glyf > glyf_table
bool get_points(hb_font_t *font, hb_codepoint_t gid, T consumer) const
const Glyph glyph_for_gid(hb_codepoint_t gid, bool needs_padding_removal=false) const
const vmtx_accelerator_t * vmtx
void add_gid_and_children(hb_codepoint_t gid, hb_set_t *gids_to_retain, unsigned int depth=0) const
const hmtx_accelerator_t * hmtx
bool get_extents(hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
void init(hb_face_t *face_)
const gvar_accelerator_t * gvar
int get_side_bearing_var(hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
hb_blob_ptr_t< loca > loca_table
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
bool check_range(const CompositeGlyphChain *composite) const
bool operator!=(const composite_iter_t &o) const
UnsizedArrayOf< HBUINT8 > dataZ
bool subset(hb_subset_context_t *c) const
bool sanitize(hb_sanitize_context_t *c) const
static void _write_loca(IteratorIn it, unsigned right_shift, IteratorOut dest)
static constexpr hb_tag_t tableTag
bool serialize(hb_serialize_context_t *c, Iterator it, const hb_subset_plan_t *plan)
static bool _add_loca_and_head(hb_subset_plan_t *plan, Iterator padded_offsets)
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
bool apply_deltas_to_points(hb_codepoint_t glyph, hb_font_t *font, const hb_array_t< contour_point_t > points) const
HBUINT16 indexToLocFormat
HBUINT16 glyphDataFormat
static constexpr hb_tag_t tableTag
friend struct glyf
bool sanitize(hb_sanitize_context_t *c) const
UnsizedArrayOf< HBUINT8 > dataZ
Definition: pbmfont.h:11
Definition: pbmfont.h:4
bool check_range(const T *p, unsigned int size=T::static_size) const
Definition: hb-array.hh:227
Type * arrayZ
Definition: hb-array.hh:258
hb_array_t copy(hb_serialize_context_t *c) const
Definition: hb-array.hh:239
unsigned int length
Definition: hb-array.hh:259
hb_array_t sub_array(unsigned int start_offset=0, unsigned int *seg_count=nullptr) const
Definition: hb-array.hh:199
hb_ot_face_t table
Definition: hb-face.hh:60
unsigned int get_num_glyphs() const
Definition: hb-face.hh:94
hb_blob_t * reference_table(const hb_face_t *face, hb_tag_t tableTag=Type::tableTag)
Definition: hb-sanitize.hh:382
void add(hb_codepoint_t g)
Definition: hb-set.hh:284
bool has(hb_codepoint_t k) const
Definition: hb-set.hh:448
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
bool resize(int size_)
Definition: hb-vector.hh:216
hb_array_t< const Type > sub_array(unsigned int start_offset, unsigned int count) const
Definition: hb-vector.hh:145
unsigned int length
Definition: hb-vector.hh:60
Definition: mpost.c:238
double y
Definition: mpost.c:239
double x
Definition: mpost.c:239
Definition: dvips.h:235
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)
TT_Glyph glyph
Definition: ttf2pfb.c:162
@ start
Definition: preamble.c:52
#define nullptr
Definition: xetex.h:75
static zic_t trans[50]
Definition: zic.c:412