From b59eb54f70c20d0260026067177a958e11c3a044 Mon Sep 17 00:00:00 2001
From: Ebrahim Byagowi <ebrahim@gnu.org>
Date: Tue, 25 Feb 2020 10:30:59 +0330
Subject: [PATCH] [glyf] Refactor, move get_points inside Glyph

---
 src/hb-ot-glyf-table.hh | 269 +++++++++++++++++++---------------------
 1 file changed, 126 insertions(+), 143 deletions(-)

diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh
index facc2f5cc..efda05054 100644
--- a/src/hb-ot-glyf-table.hh
+++ b/src/hb-ot-glyf-table.hh
@@ -402,6 +402,15 @@ struct glyf
     __item_t__ current;
   };
 
+  enum phantom_point_index_t
+  {
+    PHANTOM_LEFT   = 0,
+    PHANTOM_RIGHT  = 1,
+    PHANTOM_TOP    = 2,
+    PHANTOM_BOTTOM = 3,
+    PHANTOM_COUNT  = 4
+  };
+
   struct Glyph
   {
     enum simple_glyph_flag_t
@@ -539,7 +548,7 @@ struct glyf
 			       const simple_glyph_flag_t same_flag)
       {
 	float v = 0;
-	for (unsigned int i = 0; i < points_.length - PHANTOM_COUNT; i++)
+	for (unsigned i = 0; i < points_.length; i++)
 	{
 	  uint8_t flag = points_[i].flag;
 	  if (flag & short_flag)
@@ -571,7 +580,7 @@ struct glyf
 	if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours + 1]))) return false;
 	unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
 
-	points_.resize (num_points + PHANTOM_COUNT);
+	points_.resize (num_points);
 	for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
 	if (phantom_only) return true;
 
@@ -644,28 +653,10 @@ struct glyf
       /* Chop instructions off the end */
       void drop_hints_bytes (hb_bytes_t &dest_start) const
       { dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
-
-      bool get_contour_points (contour_point_vector_t &points_ /* OUT */) const
-      {
-	/* add one pseudo point for each component in composite glyph */
-	unsigned int num_points = hb_len (get_iterator ());
-	points_.resize (num_points + PHANTOM_COUNT);
-	for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
-	return true;
-      }
     };
 
     enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
 
-    enum phantom_point_index_t
-    {
-      PHANTOM_LEFT   = 0,
-      PHANTOM_RIGHT  = 1,
-      PHANTOM_TOP    = 2,
-      PHANTOM_BOTTOM = 3,
-      PHANTOM_COUNT  = 4
-    };
-
     public:
     composite_iter_t get_composite_iterator () const
     {
@@ -700,132 +691,67 @@ struct glyf
       }
     }
 
-    /* for a simple glyph, return contour end points, flags, along with coordinate points
-     * for a composite glyph, return pseudo component points
-     * in both cases points trailed with four phantom points
-     */
-    bool get_contour_points (contour_point_vector_t &points_ /* OUT */, bool phantom_only = false) const
-    {
-      switch (type) {
-      case COMPOSITE: return CompositeGlyph (*header, bytes).get_contour_points (points_);
-      case SIMPLE:    return SimpleGlyph (*header, bytes).get_contour_points (points_, phantom_only);
-      default:
-	/* empty glyph */
-	points_.resize (PHANTOM_COUNT);
-	for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
-	return true;
-      }
-    }
-
-    bool is_simple_glyph ()    const { return type == SIMPLE; }
-    bool is_composite_glyph () const { return type == COMPOSITE; }
-
-    bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
-    {
-      if (type == EMPTY) return true; /* Empty glyph; zero extents. */
-      return header->get_extents (font, gid, extents);
-    }
-
-    hb_bytes_t get_bytes ()          const { return bytes; }
-    const GlyphHeader &get_header () const { return *header; }
-
-    Glyph (hb_bytes_t bytes_ = hb_bytes_t ()) :
-      bytes (bytes_), header (bytes.as<GlyphHeader> ())
-    {
-      int num_contours = header->numberOfContours;
-      if (unlikely (num_contours == 0)) type = EMPTY;
-      else if (num_contours > 0) type = SIMPLE;
-      else type = COMPOSITE; /* negative numbers */
-    }
-
-    protected:
-    hb_bytes_t bytes;
-    const GlyphHeader *header;
-    unsigned type;
-  };
-
-  struct accelerator_t
-  {
-    void init (hb_face_t *face_)
-    {
-      short_offset = false;
-      num_glyphs = 0;
-      loca_table = nullptr;
-      glyf_table = nullptr;
-      face = face_;
-      const OT::head &head = *face->table.head;
-      if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
-	/* Unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
-	return;
-      short_offset = 0 == head.indexToLocFormat;
-
-      loca_table = hb_sanitize_context_t ().reference_table<loca> (face);
-      glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
-
-      num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
-    }
-
-    void fini ()
-    {
-      loca_table.destroy ();
-      glyf_table.destroy ();
-    }
-
-    enum phantom_point_index_t
-    {
-      PHANTOM_LEFT   = 0,
-      PHANTOM_RIGHT  = 1,
-      PHANTOM_TOP    = 2,
-      PHANTOM_BOTTOM = 3,
-      PHANTOM_COUNT  = 4
-    };
-
-    protected:
-
-    void init_phantom_points (hb_codepoint_t gid, hb_array_t<contour_point_t> &phantoms /* IN/OUT */) const
-    {
-      const Glyph &glyph = glyph_for_gid (gid);
-      int h_delta = (int) glyph.get_header ().xMin - face->table.hmtx->get_side_bearing (gid);
-      int v_orig  = (int) glyph.get_header ().yMax + face->table.vmtx->get_side_bearing (gid);
-      unsigned int h_adv = face->table.hmtx->get_advance (gid);
-      unsigned int v_adv = face->table.vmtx->get_advance (gid);
-
-      phantoms[PHANTOM_LEFT].x = h_delta;
-      phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
-      phantoms[PHANTOM_TOP].y = v_orig;
-      phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
-    }
-
     /* Note: Recursively calls itself.
      * all_points includes phantom points
      */
-    bool _get_points (hb_codepoint_t gid,
-		      const int *coords, unsigned int coord_count,
-		      contour_point_vector_t &all_points /* OUT */,
-		      bool phantom_only = false,
-		      unsigned int depth = 0) const
+    template<typename T>
+    bool get_points (T glyph_for_gid, hb_font_t *font,
+		     contour_point_vector_t &all_points /* OUT */,
+		     bool phantom_only = false,
+		     unsigned int depth = 0) const
     {
-      if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return false;
+      if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
       contour_point_vector_t points;
-      const Glyph &glyph = glyph_for_gid (gid);
-      if (unlikely (!glyph.get_contour_points (points, phantom_only))) return false;
+
+      switch (type) {
+      case COMPOSITE:
+      {
+	/* pseudo component points for each component in composite glyph */
+	unsigned num_points = hb_len (CompositeGlyph (*header, bytes).get_iterator ());
+	if (unlikely (!points.resize (num_points))) return false;
+	for (unsigned i = 0; i < points.length; i++)
+	  points[i].init ();
+        break;
+      }
+      case SIMPLE:
+	if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
+	  return false;
+	break;
+      default: return false; /* empty glyph */
+      }
+
+      hb_face_t *face = font->face;
+
+      /* Init phantom points */
+      if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
       hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
-      init_phantom_points (gid, phantoms);
+      {
+	for (unsigned i = 0; i < PHANTOM_COUNT; ++i) phantoms[i].init ();
+	int h_delta = (int) header->xMin - face->table.hmtx->get_side_bearing (gid);
+	int v_orig  = (int) header->yMax + face->table.vmtx->get_side_bearing (gid);
+	unsigned h_adv = face->table.hmtx->get_advance (gid);
+	unsigned v_adv = face->table.vmtx->get_advance (gid);
+	phantoms[PHANTOM_LEFT].x = h_delta;
+	phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
+	phantoms[PHANTOM_TOP].y = v_orig;
+	phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
+      }
 
 #ifndef HB_NO_VAR
-      if (unlikely (!face->table.gvar->apply_deltas_to_points (gid, coords, coord_count, points.as_array ()))) return false;
+      if (unlikely (!face->table.gvar->apply_deltas_to_points (gid, font->coords, font->num_coords, points.as_array ()))) return false;
 #endif
 
-      if (glyph.is_simple_glyph ())
+      switch (type) {
+      case SIMPLE:
 	all_points.extend (points.as_array ());
-      else if (glyph.is_composite_glyph ())
+	break;
+      case COMPOSITE:
       {
 	unsigned int comp_index = 0;
-	for (auto &item : glyph.get_composite_iterator ())
+	for (auto &item : get_composite_iterator ())
 	{
 	  contour_point_vector_t comp_points;
-	  if (unlikely (!_get_points (item.glyphIndex, coords, coord_count,
-				      comp_points, phantom_only, depth))
+	  if (unlikely (!glyph_for_gid (item.glyphIndex).get_points (glyph_for_gid, font, comp_points, phantom_only, depth + 1))
 			|| comp_points.length < PHANTOM_COUNT)
 	    return false;
 
@@ -860,12 +786,76 @@ struct glyf
 	}
 
 	all_points.extend (phantoms);
+      } break;
+      default: return false;
+      }
+
+      if (depth == 0) /* Apply at top level */
+      {
+	/* Undocumented rasterizer behavior:
+	 * Shift points horizontally by the updated left side bearing
+	 */
+	contour_point_t delta;
+	delta.init (-phantoms[PHANTOM_LEFT].x, 0.f);
+	if (delta.x) all_points.translate (delta);
       }
-      else return false;
 
       return true;
     }
 
+    bool get_extents (hb_font_t *font, hb_glyph_extents_t *extents) const
+    {
+      if (type == EMPTY) return true; /* Empty glyph; zero extents. */
+      return header->get_extents (font, gid, extents);
+    }
+
+    hb_bytes_t get_bytes () const { return bytes; }
+
+    Glyph (hb_bytes_t bytes_ = hb_bytes_t (),
+	   hb_codepoint_t gid_ = (hb_codepoint_t) -1) : bytes (bytes_), gid (gid_),
+							header (bytes.as<GlyphHeader> ())
+    {
+      int num_contours = header->numberOfContours;
+      if (unlikely (num_contours == 0)) type = EMPTY;
+      else if (num_contours > 0) type = SIMPLE;
+      else type = COMPOSITE; /* negative numbers */
+    }
+
+    protected:
+    hb_bytes_t bytes;
+    hb_codepoint_t gid;
+    const GlyphHeader *header;
+    unsigned type;
+  };
+
+  struct accelerator_t
+  {
+    void init (hb_face_t *face_)
+    {
+      short_offset = false;
+      num_glyphs = 0;
+      loca_table = nullptr;
+      glyf_table = nullptr;
+      face = face_;
+      const OT::head &head = *face->table.head;
+      if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
+	/* Unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
+	return;
+      short_offset = 0 == head.indexToLocFormat;
+
+      loca_table = hb_sanitize_context_t ().reference_table<loca> (face);
+      glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
+
+      num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
+    }
+
+    void fini ()
+    {
+      loca_table.destroy ();
+      glyf_table.destroy ();
+    }
+
+    protected:
     template<typename T>
     bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) const
     {
@@ -876,17 +866,10 @@ struct glyf
       contour_point_vector_t all_points;
 
       bool phantom_only = !consumer.is_consuming_contour_points ();
-      if (unlikely (!_get_points (gid, font->coords, font->num_coords, all_points, phantom_only) ||
-		    all_points.length < PHANTOM_COUNT))
+      if (unlikely (!glyph_for_gid (gid).get_points ([this] (hb_codepoint_t gid) -> const Glyph { return this->glyph_for_gid (gid); },
+						     font, all_points, phantom_only)))
 	return false;
 
-      /* Undocumented rasterizer behavior:
-       * Shift points horizontally by the updated left side bearing
-       */
-      contour_point_t delta;
-      delta.init (-all_points[all_points.length - PHANTOM_COUNT + PHANTOM_LEFT].x, 0.f);
-      if (delta.x) all_points.translate (delta);
-
       if (consumer.is_consuming_contour_points ())
       {
 	for (unsigned point_index = 0; point_index + 4 < all_points.length; ++point_index)
@@ -1002,7 +985,7 @@ struct glyf
       if (font->num_coords && font->num_coords == face->table.gvar->get_axis_count ())
 	return get_points (font, gid, points_aggregator_t (font, extents, nullptr));
 #endif
-      return glyph_for_gid (gid).get_extents (font, gid, extents);
+      return glyph_for_gid (gid).get_extents (font, extents);
     }
 
     const Glyph
@@ -1028,7 +1011,7 @@ struct glyf
 	return Glyph ();
 
       Glyph glyph (hb_bytes_t ((const char *) this->glyf_table + start_offset,
-			       end_offset - start_offset));
+			       end_offset - start_offset), gid);
       return needs_padding_removal ? glyph.trim_padding () : glyph;
     }