[HarfBuzz] harfbuzz: Branch 'master' - 9 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Wed Nov 4 21:53:44 PST 2015


 src/hb-font-private.hh |   97 ++++++++++++---------
 src/hb-font.cc         |  220 +++++++++++++++++++++++++++++++++----------------
 src/hb-ft.cc           |   70 ++++++++-------
 src/hb-ot-font.cc      |  120 +++++++-------------------
 src/hb-ot-shape.cc     |   38 ++++----
 test/api/test-font.c   |    2 
 6 files changed, 302 insertions(+), 245 deletions(-)

New commits:
commit 5bc28b5f688ee90d103d052e98bc15d6e0e7e0b1
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Nov 4 21:53:16 2015 -0800

    Optimize positioning for when h_origin is nil

diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 455ebab..e0331cd 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -654,22 +654,22 @@ hb_ot_position_default (hb_ot_shape_context_t *c)
   if (HB_DIRECTION_IS_HORIZONTAL (direction))
   {
     for (unsigned int i = 0; i < count; i++)
-    {
       pos[i].x_advance = c->font->get_glyph_h_advance (info[i].codepoint);
-      c->font->subtract_glyph_h_origin (info[i].codepoint,
-					&pos[i].x_offset,
-					&pos[i].y_offset);
-    }
+    if (c->font->has_glyph_h_origin_func ())
+      for (unsigned int i = 0; i < count; i++)
+	c->font->subtract_glyph_h_origin (info[i].codepoint,
+					  &pos[i].x_offset,
+					  &pos[i].y_offset);
   }
   else
   {
     for (unsigned int i = 0; i < count; i++)
-    {
       pos[i].y_advance = c->font->get_glyph_v_advance (info[i].codepoint);
-      c->font->subtract_glyph_v_origin (info[i].codepoint,
-					&pos[i].x_offset,
-					&pos[i].y_offset);
-    }
+    if (c->font->has_glyph_v_origin_func ())
+      for (unsigned int i = 0; i < count; i++)
+	c->font->subtract_glyph_v_origin (info[i].codepoint,
+					  &pos[i].x_offset,
+					  &pos[i].y_offset);
   }
   if (c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK)
     _hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer);
@@ -719,17 +719,19 @@ hb_ot_position_complex (hb_ot_shape_context_t *c)
 
     /* Change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
 
-    for (unsigned int i = 0; i < count; i++)
-      c->font->add_glyph_h_origin (info[i].codepoint,
-				   &pos[i].x_offset,
-				   &pos[i].y_offset);
+    if (c->font->has_glyph_h_origin_func ())
+      for (unsigned int i = 0; i < count; i++)
+	c->font->add_glyph_h_origin (info[i].codepoint,
+				     &pos[i].x_offset,
+				     &pos[i].y_offset);
 
     c->plan->position (c->font, c->buffer);
 
-    for (unsigned int i = 0; i < count; i++)
-      c->font->subtract_glyph_h_origin (info[i].codepoint,
-					&pos[i].x_offset,
-					&pos[i].y_offset);
+    if (c->font->has_glyph_h_origin_func ())
+      for (unsigned int i = 0; i < count; i++)
+	c->font->subtract_glyph_h_origin (info[i].codepoint,
+					  &pos[i].x_offset,
+					  &pos[i].y_offset);
 
     ret = true;
   }
commit 762770c964f9f0591bf4c44427f73ea3e1c51733
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Nov 4 21:42:55 2015 -0800

    Add font->has_...() to check for individual nil font funcs
    
    Hopefully this wouldn't break any compiler.  There was some magic
    moments to getting this to compile...

diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index 421bd02..efc12a8 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -63,12 +63,13 @@ struct hb_font_funcs_t {
 
   /* Don't access these directly.  Call font->get_*() instead. */
 
-  union {
-    struct {
+  union get_t {
+    struct get_funcs_t {
 #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
       HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 #undef HB_FONT_FUNC_IMPLEMENT
     } f;
+    void (*array[]) (void);
   } get;
 
   struct {
@@ -146,6 +147,20 @@ struct hb_font_t {
 
   /* Public getters */
 
+  HB_INTERNAL bool has_func (unsigned int i);
+
+  /* has_* ... */
+#define HB_FONT_FUNC_IMPLEMENT(name) \
+  bool \
+  has_##name##_func (void) \
+  { \
+    hb_font_funcs_t *funcs = this->klass; \
+    unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \
+    return has_func (i); \
+  }
+  HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+
   inline hb_bool_t has_glyph (hb_codepoint_t unicode)
   {
     hb_codepoint_t glyph;
diff --git a/src/hb-font.cc b/src/hb-font.cc
index 9df71c0..33c644b 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -487,6 +487,13 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t             *ffuncs,    \
 HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 #undef HB_FONT_FUNC_IMPLEMENT
 
+bool
+hb_font_t::has_func (unsigned int i)
+{
+  if (parent && parent != hb_font_get_empty () && parent->has_func (i))
+    return true;
+  return this->klass->get.array[i] != _hb_font_funcs_parent.get.array[i];
+}
 
 /* Public getters */
 
commit 88e9a9bcae61421d9dd65715d25e5f20b2847c03
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Nov 4 21:16:26 2015 -0800

    Minor reshaping of hb_font_funcs_t implementation
    
    In anticipation of further changes.  No functional changes.

diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index b969143..421bd02 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -63,10 +63,12 @@ struct hb_font_funcs_t {
 
   /* Don't access these directly.  Call font->get_*() instead. */
 
-  struct {
+  union {
+    struct {
 #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
-    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
 #undef HB_FONT_FUNC_IMPLEMENT
+    } f;
   } get;
 
   struct {
@@ -154,85 +156,85 @@ struct hb_font_t {
 			      hb_codepoint_t *glyph)
   {
     *glyph = 0;
-    return klass->get.glyph (this, user_data,
-			     unicode, variation_selector, glyph,
-			     klass->user_data.glyph);
+    return klass->get.f.glyph (this, user_data,
+			       unicode, variation_selector, glyph,
+			       klass->user_data.glyph);
   }
 
   inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
   {
-    return klass->get.glyph_h_advance (this, user_data,
-				       glyph,
-				       klass->user_data.glyph_h_advance);
+    return klass->get.f.glyph_h_advance (this, user_data,
+					 glyph,
+					 klass->user_data.glyph_h_advance);
   }
 
   inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
   {
-    return klass->get.glyph_v_advance (this, user_data,
-				       glyph,
-				       klass->user_data.glyph_v_advance);
+    return klass->get.f.glyph_v_advance (this, user_data,
+					 glyph,
+					 klass->user_data.glyph_v_advance);
   }
 
   inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
 				       hb_position_t *x, hb_position_t *y)
   {
     *x = *y = 0;
-    return klass->get.glyph_h_origin (this, user_data,
-				      glyph, x, y,
-				      klass->user_data.glyph_h_origin);
+    return klass->get.f.glyph_h_origin (this, user_data,
+					glyph, x, y,
+					klass->user_data.glyph_h_origin);
   }
 
   inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
 				       hb_position_t *x, hb_position_t *y)
   {
     *x = *y = 0;
-    return klass->get.glyph_v_origin (this, user_data,
-				      glyph, x, y,
-				      klass->user_data.glyph_v_origin);
+    return klass->get.f.glyph_v_origin (this, user_data,
+					glyph, x, y,
+					klass->user_data.glyph_v_origin);
   }
 
   inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph)
   {
-    return klass->get.glyph_h_kerning (this, user_data,
-				       left_glyph, right_glyph,
-				       klass->user_data.glyph_h_kerning);
+    return klass->get.f.glyph_h_kerning (this, user_data,
+					 left_glyph, right_glyph,
+					 klass->user_data.glyph_h_kerning);
   }
 
   inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph)
   {
-    return klass->get.glyph_v_kerning (this, user_data,
-				       top_glyph, bottom_glyph,
-				       klass->user_data.glyph_v_kerning);
+    return klass->get.f.glyph_v_kerning (this, user_data,
+					 top_glyph, bottom_glyph,
+					 klass->user_data.glyph_v_kerning);
   }
 
   inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph,
 				      hb_glyph_extents_t *extents)
   {
     memset (extents, 0, sizeof (*extents));
-    return klass->get.glyph_extents (this, user_data,
-				     glyph,
-				     extents,
-				     klass->user_data.glyph_extents);
+    return klass->get.f.glyph_extents (this, user_data,
+				       glyph,
+				       extents,
+				       klass->user_data.glyph_extents);
   }
 
   inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
 					    hb_position_t *x, hb_position_t *y)
   {
     *x = *y = 0;
-    return klass->get.glyph_contour_point (this, user_data,
-					   glyph, point_index,
-					   x, y,
-					   klass->user_data.glyph_contour_point);
+    return klass->get.f.glyph_contour_point (this, user_data,
+					     glyph, point_index,
+					     x, y,
+					     klass->user_data.glyph_contour_point);
   }
 
   inline hb_bool_t get_glyph_name (hb_codepoint_t glyph,
 				   char *name, unsigned int size)
   {
     if (size) *name = '\0';
-    return klass->get.glyph_name (this, user_data,
-				  glyph,
-				  name, size,
-				  klass->user_data.glyph_name);
+    return klass->get.f.glyph_name (this, user_data,
+				    glyph,
+				    name, size,
+				    klass->user_data.glyph_name);
   }
 
   inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
@@ -240,10 +242,10 @@ struct hb_font_t {
   {
     *glyph = 0;
     if (len == -1) len = strlen (name);
-    return klass->get.glyph_from_name (this, user_data,
-				       name, len,
-				       glyph,
-				       klass->user_data.glyph_from_name);
+    return klass->get.f.glyph_from_name (this, user_data,
+					 name, len,
+					 glyph,
+					 klass->user_data.glyph_from_name);
   }
 
 
diff --git a/src/hb-font.cc b/src/hb-font.cc
index a1f227c..9df71c0 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -474,11 +474,11 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t             *ffuncs,    \
     ffuncs->destroy.name (ffuncs->user_data.name);                       \
                                                                          \
   if (func) {                                                            \
-    ffuncs->get.name = func;                                             \
+    ffuncs->get.f.name = func;                                           \
     ffuncs->user_data.name = user_data;                                  \
     ffuncs->destroy.name = destroy;                                      \
   } else {                                                               \
-    ffuncs->get.name = hb_font_get_##name##_parent;                      \
+    ffuncs->get.f.name = hb_font_get_##name##_parent;                    \
     ffuncs->user_data.name = NULL;                                       \
     ffuncs->destroy.name = NULL;                                         \
   }                                                                      \
commit a6a7715bac8b0c8f5473b84bc649c315ad4d2d51
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Nov 4 20:51:21 2015 -0800

    Comments

diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index 952682d..b969143 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -61,7 +61,7 @@ struct hb_font_funcs_t {
 
   hb_bool_t immutable;
 
-  /* Don't access these directly.  Call hb_font_get_*() instead. */
+  /* Don't access these directly.  Call font->get_*() instead. */
 
   struct {
 #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name;
commit 6c48ec830ffac00a920d047ed77acd1b05549074
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Nov 4 20:47:42 2015 -0800

    [ot] Remove font funcs that do nothing

diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index e68217d..8d33300 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -305,52 +305,6 @@ hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
 }
 
 static hb_bool_t
-hb_ot_get_glyph_h_origin (hb_font_t *font HB_UNUSED,
-			  void *font_data HB_UNUSED,
-			  hb_codepoint_t glyph HB_UNUSED,
-			  hb_position_t *x HB_UNUSED,
-			  hb_position_t *y HB_UNUSED,
-			  void *user_data HB_UNUSED)
-{
-  /* We always work in the horizontal coordinates. */
-  return true;
-}
-
-static hb_bool_t
-hb_ot_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
-			  void *font_data,
-			  hb_codepoint_t glyph,
-			  hb_position_t *x,
-			  hb_position_t *y,
-			  void *user_data HB_UNUSED)
-{
-  /* TODO */
-  return false;
-}
-
-static hb_position_t
-hb_ot_get_glyph_h_kerning (hb_font_t *font,
-			   void *font_data,
-			   hb_codepoint_t left_glyph,
-			   hb_codepoint_t right_glyph,
-			   void *user_data HB_UNUSED)
-{
-  /* TODO */
-  return 0;
-}
-
-static hb_position_t
-hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED,
-			   void *font_data HB_UNUSED,
-			   hb_codepoint_t top_glyph HB_UNUSED,
-			   hb_codepoint_t bottom_glyph HB_UNUSED,
-			   void *user_data HB_UNUSED)
-{
-  /* OpenType doesn't have vertical-kerning other than GPOS. */
-  return 0;
-}
-
-static hb_bool_t
 hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
 			 void *font_data,
 			 hb_codepoint_t glyph,
@@ -366,41 +320,6 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED,
   return ret;
 }
 
-static hb_bool_t
-hb_ot_get_glyph_contour_point (hb_font_t *font HB_UNUSED,
-			       void *font_data,
-			       hb_codepoint_t glyph,
-			       unsigned int point_index,
-			       hb_position_t *x,
-			       hb_position_t *y,
-			       void *user_data HB_UNUSED)
-{
-  /* TODO */
-  return false;
-}
-
-static hb_bool_t
-hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
-		      void *font_data,
-		      hb_codepoint_t glyph,
-		      char *name, unsigned int size,
-		      void *user_data HB_UNUSED)
-{
-  /* TODO */
-  return false;
-}
-
-static hb_bool_t
-hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
-			   void *font_data,
-			   const char *name, int len, /* -1 means nul-terminated */
-			   hb_codepoint_t *glyph,
-			   void *user_data HB_UNUSED)
-{
-  /* TODO */
-  return false;
-}
-
 
 static hb_font_funcs_t *static_ot_funcs = NULL;
 
@@ -425,14 +344,14 @@ retry:
     hb_font_funcs_set_glyph_func (funcs, hb_ot_get_glyph, NULL, NULL);
     hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, NULL, NULL);
     hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, NULL, NULL);
-    hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, NULL, NULL);
-    hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, NULL, NULL);
-    hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, NULL, NULL);
-    hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, NULL, NULL);
+    //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, NULL, NULL);
+    //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, NULL, NULL);
+    //hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, NULL, NULL); TODO
+    //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, NULL, NULL);
     hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, NULL, NULL);
-    hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, NULL, NULL);
-    hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, NULL, NULL);
-    hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, NULL, NULL);
+    //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, NULL, NULL); TODO
+    //hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, NULL, NULL); TODO
+    //hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, NULL, NULL); TODO
 
     hb_font_funcs_make_immutable (funcs);
 
commit 75ea2daa1d9bbe235cd4a8570efb1913d58c3c62
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Nov 4 20:43:59 2015 -0800

    [ot] Port ot font funcs to allocated object

diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 94c31b3..e68217d 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -402,22 +402,51 @@ hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
 }
 
 
+static hb_font_funcs_t *static_ot_funcs = NULL;
+
+#ifdef HB_USE_ATEXIT
+static
+void free_static_ot_funcs (void)
+{
+  hb_font_funcs_destroy (static_ot_funcs);
+}
+#endif
+
 static hb_font_funcs_t *
 _hb_ot_get_font_funcs (void)
 {
-  static const hb_font_funcs_t ot_ffuncs = {
-    HB_OBJECT_HEADER_STATIC,
+retry:
+  hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs);
 
-    true, /* immutable */
-
-    {
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_ot_get_##name,
-      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
+  if (unlikely (!funcs))
+  {
+    funcs = hb_font_funcs_create ();
+
+    hb_font_funcs_set_glyph_func (funcs, hb_ot_get_glyph, NULL, NULL);
+    hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, NULL, NULL);
+    hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, NULL, NULL);
+    hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, NULL, NULL);
+    hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, NULL, NULL);
+    hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, NULL, NULL);
+    hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, NULL, NULL);
+    hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, NULL, NULL);
+    hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, NULL, NULL);
+    hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, NULL, NULL);
+    hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, NULL, NULL);
+
+    hb_font_funcs_make_immutable (funcs);
+
+    if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, NULL, funcs)) {
+      hb_font_funcs_destroy (funcs);
+      goto retry;
     }
+
+#ifdef HB_USE_ATEXIT
+    atexit (free_static_ot_funcs); /* First person registers atexit() callback. */
+#endif
   };
 
-  return const_cast<hb_font_funcs_t *> (&ot_ffuncs);
+  return funcs;
 }
 
 
commit 44f82750807475aa5b16099ccccd917d488df703
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Nov 4 20:40:05 2015 -0800

    [ft] Remove font funcs that do nothing

diff --git a/src/hb-ft.cc b/src/hb-ft.cc
index fc33b19..5630964 100644
--- a/src/hb-ft.cc
+++ b/src/hb-ft.cc
@@ -217,18 +217,6 @@ hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED,
 }
 
 static hb_bool_t
-hb_ft_get_glyph_h_origin (hb_font_t *font HB_UNUSED,
-			  void *font_data HB_UNUSED,
-			  hb_codepoint_t glyph HB_UNUSED,
-			  hb_position_t *x HB_UNUSED,
-			  hb_position_t *y HB_UNUSED,
-			  void *user_data HB_UNUSED)
-{
-  /* We always work in the horizontal coordinates. */
-  return true;
-}
-
-static hb_bool_t
 hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED,
 			  void *font_data,
 			  hb_codepoint_t glyph,
@@ -272,17 +260,6 @@ hb_ft_get_glyph_h_kerning (hb_font_t *font,
   return kerningv.x;
 }
 
-static hb_position_t
-hb_ft_get_glyph_v_kerning (hb_font_t *font HB_UNUSED,
-			   void *font_data HB_UNUSED,
-			   hb_codepoint_t top_glyph HB_UNUSED,
-			   hb_codepoint_t bottom_glyph HB_UNUSED,
-			   void *user_data HB_UNUSED)
-{
-  /* FreeType API doesn't support vertical kerning */
-  return 0;
-}
-
 static hb_bool_t
 hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED,
 			 void *font_data,
@@ -403,15 +380,17 @@ retry:
     hb_font_funcs_set_glyph_func (funcs, hb_ft_get_glyph, NULL, NULL);
     hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, NULL, NULL);
     hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, NULL, NULL);
-    hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, NULL, NULL);
+    //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, NULL, NULL);
     hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, NULL, NULL);
     hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, NULL, NULL);
-    hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, NULL, NULL);
+    //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, NULL, NULL);
     hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, NULL, NULL);
     hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, NULL, NULL);
     hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, NULL, NULL);
     hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, NULL, NULL);
 
+    hb_font_funcs_make_immutable (funcs);
+
     if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, NULL, funcs)) {
       hb_font_funcs_destroy (funcs);
       goto retry;
commit 7918c261efd283e0428ce7836e9e42768a6aa05c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Nov 4 20:37:49 2015 -0800

    [ft] Port ft font funcs to allocated object

diff --git a/src/hb-ft.cc b/src/hb-ft.cc
index 2b11882..fc33b19 100644
--- a/src/hb-ft.cc
+++ b/src/hb-ft.cc
@@ -380,23 +380,50 @@ hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED,
 }
 
 
+static hb_font_funcs_t *static_ft_funcs = NULL;
+
+#ifdef HB_USE_ATEXIT
+static
+void free_static_ft_funcs (void)
+{
+  hb_font_funcs_destroy (static_ft_funcs);
+}
+#endif
+
 static void
 _hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref)
 {
-  static const hb_font_funcs_t ft_ffuncs = {
-    HB_OBJECT_HEADER_STATIC,
-
-    true, /* immutable */
+retry:
+  hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs);
 
-    {
-#define HB_FONT_FUNC_IMPLEMENT(name) hb_ft_get_##name,
-      HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
+  if (unlikely (!funcs))
+  {
+    funcs = hb_font_funcs_create ();
+
+    hb_font_funcs_set_glyph_func (funcs, hb_ft_get_glyph, NULL, NULL);
+    hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, NULL, NULL);
+    hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, NULL, NULL);
+    hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, NULL, NULL);
+    hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, NULL, NULL);
+    hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, NULL, NULL);
+    hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, NULL, NULL);
+    hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, NULL, NULL);
+    hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, NULL, NULL);
+    hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, NULL, NULL);
+    hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, NULL, NULL);
+
+    if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, NULL, funcs)) {
+      hb_font_funcs_destroy (funcs);
+      goto retry;
     }
+
+#ifdef HB_USE_ATEXIT
+    atexit (free_static_ft_funcs); /* First person registers atexit() callback. */
+#endif
   };
 
   hb_font_set_funcs (font,
-		     const_cast<hb_font_funcs_t *> (&ft_ffuncs),
+		     funcs,
 		     _hb_ft_font_create (ft_face, unref),
 		     (hb_destroy_func_t) _hb_ft_font_destroy);
 }
commit da29b43794cfa3f9a602c34b33c5d8a9c36f87b5
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Nov 4 20:22:44 2015 -0800

    Separate nil font-funcs from parent-peeking font-funcs
    
    API change: all fonts created with hb_font_create() now inherit from
    (ie have parent) hb_font_get_empty().

diff --git a/src/hb-font.cc b/src/hb-font.cc
index 6a69cae..a1f227c 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -45,130 +45,176 @@
  */
 
 static hb_bool_t
-hb_font_get_glyph_nil (hb_font_t *font,
+hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
 		       void *font_data HB_UNUSED,
 		       hb_codepoint_t unicode,
 		       hb_codepoint_t variation_selector,
 		       hb_codepoint_t *glyph,
 		       void *user_data HB_UNUSED)
 {
-  if (font->parent)
-    return font->parent->get_glyph (unicode, variation_selector, glyph);
-
   *glyph = 0;
   return false;
 }
+static hb_bool_t
+hb_font_get_glyph_parent (hb_font_t *font,
+			  void *font_data HB_UNUSED,
+			  hb_codepoint_t unicode,
+			  hb_codepoint_t variation_selector,
+			  hb_codepoint_t *glyph,
+			  void *user_data HB_UNUSED)
+{
+  return font->parent->get_glyph (unicode, variation_selector, glyph);
+}
 
 static hb_position_t
-hb_font_get_glyph_h_advance_nil (hb_font_t *font,
+hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED,
 				 void *font_data HB_UNUSED,
 				 hb_codepoint_t glyph,
 				 void *user_data HB_UNUSED)
 {
-  if (font->parent)
-    return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
-
   return font->x_scale;
 }
+static hb_position_t
+hb_font_get_glyph_h_advance_parent (hb_font_t *font,
+				    void *font_data HB_UNUSED,
+				    hb_codepoint_t glyph,
+				    void *user_data HB_UNUSED)
+{
+  return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph));
+}
 
 static hb_position_t
-hb_font_get_glyph_v_advance_nil (hb_font_t *font,
+hb_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED,
 				 void *font_data HB_UNUSED,
 				 hb_codepoint_t glyph,
 				 void *user_data HB_UNUSED)
 {
-  if (font->parent)
-    return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
-
   return font->y_scale;
 }
+static hb_position_t
+hb_font_get_glyph_v_advance_parent (hb_font_t *font,
+				    void *font_data HB_UNUSED,
+				    hb_codepoint_t glyph,
+				    void *user_data HB_UNUSED)
+{
+  return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph));
+}
 
 static hb_bool_t
-hb_font_get_glyph_h_origin_nil (hb_font_t *font,
+hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
 				void *font_data HB_UNUSED,
 				hb_codepoint_t glyph,
 				hb_position_t *x,
 				hb_position_t *y,
 				void *user_data HB_UNUSED)
 {
-  if (font->parent) {
-    hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y);
-    if (ret)
-      font->parent_scale_position (x, y);
-    return ret;
-  }
-
   *x = *y = 0;
   return false;
 }
+static hb_bool_t
+hb_font_get_glyph_h_origin_parent (hb_font_t *font,
+				   void *font_data HB_UNUSED,
+				   hb_codepoint_t glyph,
+				   hb_position_t *x,
+				   hb_position_t *y,
+				   void *user_data HB_UNUSED)
+{
+  hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y);
+  if (ret)
+    font->parent_scale_position (x, y);
+  return ret;
+}
 
 static hb_bool_t
-hb_font_get_glyph_v_origin_nil (hb_font_t *font,
+hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
 				void *font_data HB_UNUSED,
 				hb_codepoint_t glyph,
 				hb_position_t *x,
 				hb_position_t *y,
 				void *user_data HB_UNUSED)
 {
-  if (font->parent) {
-    hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
-    if (ret)
-      font->parent_scale_position (x, y);
-    return ret;
-  }
-
   *x = *y = 0;
   return false;
 }
+static hb_bool_t
+hb_font_get_glyph_v_origin_parent (hb_font_t *font,
+				   void *font_data HB_UNUSED,
+				   hb_codepoint_t glyph,
+				   hb_position_t *x,
+				   hb_position_t *y,
+				   void *user_data HB_UNUSED)
+{
+  hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
+  if (ret)
+    font->parent_scale_position (x, y);
+  return ret;
+}
 
 static hb_position_t
-hb_font_get_glyph_h_kerning_nil (hb_font_t *font,
+hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
 				 void *font_data HB_UNUSED,
 				 hb_codepoint_t left_glyph,
 				 hb_codepoint_t right_glyph,
 				 void *user_data HB_UNUSED)
 {
-  if (font->parent)
-    return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
-
   return 0;
 }
+static hb_position_t
+hb_font_get_glyph_h_kerning_parent (hb_font_t *font,
+				    void *font_data HB_UNUSED,
+				    hb_codepoint_t left_glyph,
+				    hb_codepoint_t right_glyph,
+				    void *user_data HB_UNUSED)
+{
+  return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph));
+}
 
 static hb_position_t
-hb_font_get_glyph_v_kerning_nil (hb_font_t *font,
+hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
 				 void *font_data HB_UNUSED,
 				 hb_codepoint_t top_glyph,
 				 hb_codepoint_t bottom_glyph,
 				 void *user_data HB_UNUSED)
 {
-  if (font->parent)
-    return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
-
   return 0;
 }
+static hb_position_t
+hb_font_get_glyph_v_kerning_parent (hb_font_t *font,
+				    void *font_data HB_UNUSED,
+				    hb_codepoint_t top_glyph,
+				    hb_codepoint_t bottom_glyph,
+				    void *user_data HB_UNUSED)
+{
+  return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph));
+}
 
 static hb_bool_t
-hb_font_get_glyph_extents_nil (hb_font_t *font,
+hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
 			       void *font_data HB_UNUSED,
 			       hb_codepoint_t glyph,
 			       hb_glyph_extents_t *extents,
 			       void *user_data HB_UNUSED)
 {
-  if (font->parent) {
-    hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
-    if (ret) {
-      font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
-      font->parent_scale_distance (&extents->width, &extents->height);
-    }
-    return ret;
-  }
-
   memset (extents, 0, sizeof (*extents));
   return false;
 }
+static hb_bool_t
+hb_font_get_glyph_extents_parent (hb_font_t *font,
+				  void *font_data HB_UNUSED,
+				  hb_codepoint_t glyph,
+				  hb_glyph_extents_t *extents,
+				  void *user_data HB_UNUSED)
+{
+  hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents);
+  if (ret) {
+    font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
+    font->parent_scale_distance (&extents->width, &extents->height);
+  }
+  return ret;
+}
 
 static hb_bool_t
-hb_font_get_glyph_contour_point_nil (hb_font_t *font,
+hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
 				     void *font_data HB_UNUSED,
 				     hb_codepoint_t glyph,
 				     unsigned int point_index,
@@ -176,44 +222,63 @@ hb_font_get_glyph_contour_point_nil (hb_font_t *font,
 				     hb_position_t *y,
 				     void *user_data HB_UNUSED)
 {
-  if (font->parent) {
-    hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
-    if (ret)
-      font->parent_scale_position (x, y);
-    return ret;
-  }
-
   *x = *y = 0;
   return false;
 }
+static hb_bool_t
+hb_font_get_glyph_contour_point_parent (hb_font_t *font,
+					void *font_data HB_UNUSED,
+					hb_codepoint_t glyph,
+					unsigned int point_index,
+					hb_position_t *x,
+					hb_position_t *y,
+					void *user_data HB_UNUSED)
+{
+  hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y);
+  if (ret)
+    font->parent_scale_position (x, y);
+  return ret;
+}
 
 static hb_bool_t
-hb_font_get_glyph_name_nil (hb_font_t *font,
+hb_font_get_glyph_name_nil (hb_font_t *font HB_UNUSED,
 			    void *font_data HB_UNUSED,
 			    hb_codepoint_t glyph,
 			    char *name, unsigned int size,
 			    void *user_data HB_UNUSED)
 {
-  if (font->parent)
-    return font->parent->get_glyph_name (glyph, name, size);
-
   if (size) *name = '\0';
   return false;
 }
+static hb_bool_t
+hb_font_get_glyph_name_parent (hb_font_t *font,
+			       void *font_data HB_UNUSED,
+			       hb_codepoint_t glyph,
+			       char *name, unsigned int size,
+			       void *user_data HB_UNUSED)
+{
+  return font->parent->get_glyph_name (glyph, name, size);
+}
 
 static hb_bool_t
-hb_font_get_glyph_from_name_nil (hb_font_t *font,
+hb_font_get_glyph_from_name_nil (hb_font_t *font HB_UNUSED,
 				 void *font_data HB_UNUSED,
 				 const char *name, int len, /* -1 means nul-terminated */
 				 hb_codepoint_t *glyph,
 				 void *user_data HB_UNUSED)
 {
-  if (font->parent)
-    return font->parent->get_glyph_from_name (name, len, glyph);
-
   *glyph = 0;
   return false;
 }
+static hb_bool_t
+hb_font_get_glyph_from_name_parent (hb_font_t *font,
+				    void *font_data HB_UNUSED,
+				    const char *name, int len, /* -1 means nul-terminated */
+				    hb_codepoint_t *glyph,
+				    void *user_data HB_UNUSED)
+{
+  return font->parent->get_glyph_from_name (name, len, glyph);
+}
 
 
 static const hb_font_funcs_t _hb_font_funcs_nil = {
@@ -227,6 +292,17 @@ static const hb_font_funcs_t _hb_font_funcs_nil = {
 #undef HB_FONT_FUNC_IMPLEMENT
   }
 };
+static const hb_font_funcs_t _hb_font_funcs_parent = {
+  HB_OBJECT_HEADER_STATIC,
+
+  true, /* immutable */
+
+  {
+#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_parent,
+    HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_FONT_FUNC_IMPLEMENT
+  }
+};
 
 
 /**
@@ -246,7 +322,7 @@ hb_font_funcs_create (void)
   if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
     return hb_font_funcs_get_empty ();
 
-  ffuncs->get = _hb_font_funcs_nil.get;
+  ffuncs->get = _hb_font_funcs_parent.get;
 
   return ffuncs;
 }
@@ -263,7 +339,7 @@ hb_font_funcs_create (void)
 hb_font_funcs_t *
 hb_font_funcs_get_empty (void)
 {
-  return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil);
+  return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_parent);
 }
 
 /**
@@ -402,7 +478,7 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t             *ffuncs,    \
     ffuncs->user_data.name = user_data;                                  \
     ffuncs->destroy.name = destroy;                                      \
   } else {                                                               \
-    ffuncs->get.name = hb_font_get_##name##_nil;                         \
+    ffuncs->get.name = hb_font_get_##name##_parent;                      \
     ffuncs->user_data.name = NULL;                                       \
     ffuncs->destroy.name = NULL;                                         \
   }                                                                      \
@@ -858,6 +934,7 @@ hb_font_create (hb_face_t *face)
     return hb_font_get_empty ();
 
   hb_face_make_immutable (face);
+  font->parent = hb_font_get_empty ();
   font->face = hb_face_reference (face);
   font->klass = hb_font_funcs_get_empty ();
 
@@ -917,8 +994,8 @@ hb_font_get_empty (void)
     NULL, /* parent */
     const_cast<hb_face_t *> (&_hb_face_nil),
 
-    0, /* x_scale */
-    0, /* y_scale */
+    1000, /* x_scale */
+    1000, /* y_scale */
 
     0, /* x_ppem */
     0, /* y_ppem */
diff --git a/test/api/test-font.c b/test/api/test-font.c
index ef5b08f..34f6c74 100644
--- a/test/api/test-font.c
+++ b/test/api/test-font.c
@@ -386,7 +386,7 @@ test_font_properties (void)
 
 
   g_assert (hb_font_get_face (font) == face);
-  g_assert (hb_font_get_parent (font) == NULL);
+  g_assert (hb_font_get_parent (font) == hb_font_get_empty ());
   subfont = hb_font_create_sub_font (font);
   g_assert (hb_font_get_parent (subfont) == font);
   hb_font_set_parent(subfont, NULL);


More information about the HarfBuzz mailing list