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

Behdad Esfahbod behdad at kemper.freedesktop.org
Mon Nov 12 22:55:34 UTC 2018


 src/hb-dsalgs.hh     |   17 +-
 src/hb-set.hh        |    2 
 src/hb-shape-plan.cc |  328 ++++++++++++++++++++++-----------------------------
 src/hb-shape-plan.hh |   39 ++++--
 src/hb-shape.cc      |    2 
 src/hb-shaper.cc     |   16 +-
 src/hb-shaper.hh     |    4 
 7 files changed, 199 insertions(+), 209 deletions(-)

New commits:
commit 7ac03f88a22325fb4d6b77ee7694ad11f6a99bcb
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Nov 12 17:50:30 2018 -0500

    [shape-plan] Minor

diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc
index ecef784a..4c3ae062 100644
--- a/src/hb-shape-plan.cc
+++ b/src/hb-shape-plan.cc
@@ -303,6 +303,22 @@ hb_shape_plan_get_user_data (hb_shape_plan_t    *shape_plan,
   return hb_object_get_user_data (shape_plan, key);
 }
 
+/**
+ * hb_shape_plan_get_shaper:
+ * @shape_plan: a shape plan.
+ *
+ * 
+ *
+ * Return value: (transfer none):
+ *
+ * Since: 0.9.7
+ **/
+const char *
+hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan)
+{
+  return shape_plan->key.shaper_name;
+}
+
 
 /**
  * hb_shape_plan_execute:
@@ -520,19 +536,3 @@ retry:
 
   return hb_shape_plan_reference (shape_plan);
 }
-
-/**
- * hb_shape_plan_get_shaper:
- * @shape_plan: a shape plan.
- *
- * 
- *
- * Return value: (transfer none):
- *
- * Since: 0.9.7
- **/
-const char *
-hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan)
-{
-  return shape_plan->key.shaper_name;
-}
commit c7be933439af1bc8251b2b19df75b42bd0f3bdb5
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Nov 12 17:49:15 2018 -0500

    [shape-plan] Refactor some more

diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc
index 8b1dbd4e..ecef784a 100644
--- a/src/hb-shape-plan.cc
+++ b/src/hb-shape-plan.cc
@@ -44,22 +44,50 @@
  **/
 
 
-static void
-hb_shape_plan_key_choose_shaper (hb_shape_plan_key_t *key,
-				 hb_face_t           *face,
-				 const hb_feature_t  *user_features,
-				 unsigned int         num_user_features,
-				 const int           *coords,
-				 unsigned int         num_coords,
-				 const char * const  *shaper_list)
+/*
+ * hb_shape_plan_key_t
+ */
+
+bool
+hb_shape_plan_key_t::init (bool                           copy,
+			   hb_face_t                     *face,
+			   const hb_segment_properties_t *props,
+			   const hb_feature_t            *user_features,
+			   unsigned int                   num_user_features,
+			   const int                     *orig_coords,
+			   unsigned int                   num_coords,
+			   const char * const            *shaper_list)
 {
+  hb_feature_t *features = nullptr;
+  int *coords = nullptr;
+  if (copy && num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t))))
+    goto bail;
+  if (copy && num_coords && !(coords = (int *) calloc (num_coords, sizeof (int))))
+    goto bail;
+
+  this->props = *props;
+  this->num_user_features = num_user_features;
+  this->user_features = copy ? features : user_features;
+  if (copy && num_user_features)
+    memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
+  this->num_coords = num_coords;
+  this->coords = copy ? coords : orig_coords;
+  if (copy && num_coords)
+    memcpy (coords, orig_coords, num_coords * sizeof (int));
+  this->shaper_func = nullptr;
+  this->shaper_name = nullptr;
+
+  /*
+   * Choose shaper.
+   */
+
 #define HB_SHAPER_PLAN(shaper) \
 	HB_STMT_START { \
 	  if (hb_##shaper##_shaper_face_data_ensure (face)) \
 	  { \
-	    key->shaper_func = _hb_##shaper##_shape; \
-	    key->shaper_name = #shaper; \
-	    return; \
+	    this->shaper_func = _hb_##shaper##_shape; \
+	    this->shaper_name = #shaper; \
+	    return true; \
 	  } \
 	} HB_STMT_END
 
@@ -74,18 +102,24 @@ hb_shape_plan_key_choose_shaper (hb_shape_plan_key_t *key,
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
   }
-
-  const hb_shaper_pair_static_t *shapers = _hb_shapers_get ();
-  for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++)
-    if (false)
-      ;
+  else
+  {
+    const hb_shaper_pair_static_t *shapers = _hb_shapers_get ();
+    for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++)
+      if (false)
+	;
 #define HB_SHAPER_IMPLEMENT(shaper) \
-    else if (shapers[i].func == _hb_##shaper##_shape) \
-      HB_SHAPER_PLAN (shaper);
+      else if (shapers[i].func == _hb_##shaper##_shape) \
+	HB_SHAPER_PLAN (shaper);
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
-
+  }
 #undef HB_SHAPER_PLAN
+
+bail:
+  ::free (coords);
+  ::free (features);
+  return false;
 }
 
 
@@ -126,7 +160,7 @@ hb_shape_plan_create2 (hb_face_t                     *face,
 		       const hb_segment_properties_t *props,
 		       const hb_feature_t            *user_features,
 		       unsigned int                   num_user_features,
-		       const int                     *orig_coords,
+		       const int                     *coords,
 		       unsigned int                   num_coords,
 		       const char * const            *shaper_list)
 {
@@ -140,16 +174,9 @@ hb_shape_plan_create2 (hb_face_t                     *face,
   assert (props->direction != HB_DIRECTION_INVALID);
 
   hb_shape_plan_t *shape_plan;
-  hb_feature_t *features = nullptr;
-  int *coords = nullptr;
 
   if (unlikely (!props))
     goto bail;
-  if (num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t))))
-    goto bail;
-  if (num_coords && !(coords = (int *) calloc (num_coords, sizeof (int))))
-    goto bail;
-
   if (!(shape_plan = hb_object_create<hb_shape_plan_t> ()))
     goto bail;
 
@@ -158,37 +185,30 @@ hb_shape_plan_create2 (hb_face_t                     *face,
   hb_face_make_immutable (face);
   shape_plan->face_unsafe = face;
 
-  {
-    hb_shape_plan_key_t *key = &shape_plan->key;
-    key->props = *props;
-    key->num_user_features = num_user_features;
-    key->user_features = features;
-    if (num_user_features)
-      memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
-    key->num_coords = num_coords;
-    key->coords = coords;
-    if (num_coords)
-      memcpy (coords, orig_coords, num_coords * sizeof (int));
-    hb_shape_plan_key_choose_shaper (key,
-				     face,
-				     user_features, num_user_features,
-				     coords, num_coords,
-				     shaper_list);
-  }
-
+  if (unlikely (!shape_plan->key.init (true,
+				       face,
+				       props,
+				       user_features,
+				       num_user_features,
+				       coords,
+				       num_coords,
+				       shaper_list)))
+    goto bail2;
   if (unlikely (!shape_plan->ot.init0 (face,
 				       props,
 				       user_features,
 				       num_user_features,
 				       coords,
 				       num_coords)))
-    goto bail;
+    goto bail3;
 
   return shape_plan;
 
+bail3:
+  shape_plan->key.free ();
+bail2:
+  free (shape_plan);
 bail:
-  free (coords);
-  free (features);
   return hb_shape_plan_get_empty ();
 }
 
@@ -237,10 +257,7 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan)
   if (!hb_object_destroy (shape_plan)) return;
 
   shape_plan->ot.fini ();
-
-  free ((void *) shape_plan->key.user_features);
-  free ((void *) shape_plan->key.coords);
-
+  shape_plan->key.free ();
   free (shape_plan);
 }
 
@@ -347,7 +364,7 @@ hb_shape_plan_execute (hb_shape_plan_t    *shape_plan,
 
 
 /*
- * caching
+ * Caching
  */
 
 static inline bool
@@ -453,20 +470,16 @@ hb_shape_plan_create_cached2 (hb_face_t                     *face,
 		  num_user_features,
 		  shaper_list);
 
-  hb_shape_plan_key_t key =
-  {
-    *props,
-    user_features,
-    num_user_features,
-    coords,
-    num_coords,
-    nullptr
-  };
-  hb_shape_plan_key_choose_shaper (&key,
-				   face,
-				   user_features, num_user_features,
-				   coords, num_coords,
-				   shaper_list);
+  hb_shape_plan_key_t key;
+  if (!key.init (false,
+		 face,
+		 props,
+		 user_features,
+		 num_user_features,
+		 coords,
+		 num_coords,
+		 shaper_list))
+    return hb_shape_plan_get_empty ();
 
 retry:
   hb_face_t::plan_node_t *cached_plan_nodes = face->shape_plans;
diff --git a/src/hb-shape-plan.hh b/src/hb-shape-plan.hh
index 98688f54..8b34fa0a 100644
--- a/src/hb-shape-plan.hh
+++ b/src/hb-shape-plan.hh
@@ -44,6 +44,21 @@ struct hb_shape_plan_key_t
 
   hb_shape_func_t         *shaper_func;
   const char              *shaper_name;
+
+  HB_INTERNAL inline bool init (bool                           copy,
+				hb_face_t                     *face,
+				const hb_segment_properties_t *props,
+				const hb_feature_t            *user_features,
+				unsigned int                   num_user_features,
+				const int                     *orig_coords,
+				unsigned int                   num_coords,
+				const char * const            *shaper_list);
+
+  HB_INTERNAL inline void free (void)
+  {
+    ::free ((void *) user_features);
+    ::free ((void *) coords);
+  }
 };
 
 struct hb_shape_plan_t
commit fc27777833e052dab91ca5777802e6c4e956deb4
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Nov 12 17:27:34 2018 -0500

    [shape-plan] Refactor more

diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc
index 186ae88b..8b1dbd4e 100644
--- a/src/hb-shape-plan.cc
+++ b/src/hb-shape-plan.cc
@@ -382,12 +382,15 @@ hb_shape_plan_key_equal (const hb_shape_plan_key_t *key1,
 	 key1->shaper_func == key2->shaper_func;
 }
 
-static inline hb_bool_t
-hb_non_global_user_features_present (const hb_feature_t *user_features,
-				     unsigned int        num_user_features)
+static inline bool
+hb_shape_plan_key_has_non_global_user_features (const hb_shape_plan_key_t *key)
 {
-  while (num_user_features) {
-    if (user_features->start != 0 || user_features->end != (unsigned int) -1)
+  unsigned int num_user_features = key->num_user_features;
+  const hb_feature_t *user_features = key->user_features;
+  while (num_user_features)
+  {
+    if (user_features->start != HB_FEATURE_GLOBAL_START ||
+	user_features->end   != HB_FEATURE_GLOBAL_END)
       return true;
     num_user_features--;
     user_features++;
@@ -395,11 +398,17 @@ hb_non_global_user_features_present (const hb_feature_t *user_features,
   return false;
 }
 
-static inline hb_bool_t
-hb_coords_present (const int *coords HB_UNUSED,
-		   unsigned int num_coords)
+static inline bool
+hb_shape_plan_key_has_coords (const hb_shape_plan_key_t *key)
 {
-  return num_coords != 0;
+  return key->num_coords;
+}
+
+static inline bool
+hb_shape_plan_key_dont_cache (const hb_shape_plan_key_t *key)
+{
+  return hb_shape_plan_key_has_non_global_user_features (key) ||
+	 hb_shape_plan_key_has_coords (key);
 }
 
 /**
@@ -462,8 +471,10 @@ hb_shape_plan_create_cached2 (hb_face_t                     *face,
 retry:
   hb_face_t::plan_node_t *cached_plan_nodes = face->shape_plans;
 
-  /* Don't look for plan in the cache if there were variation coordinates XXX Fix me. */
-  if (!hb_coords_present (coords, num_coords))
+  bool dont_cache = hb_shape_plan_key_dont_cache (&key) ||
+		    hb_object_is_inert (face);
+
+  if (!dont_cache)
     for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next)
       if (hb_shape_plan_key_equal (&node->shape_plan->key, &key))
       {
@@ -471,21 +482,12 @@ retry:
         return hb_shape_plan_reference (node->shape_plan);
       }
 
-  /* Not found. */
   hb_shape_plan_t *shape_plan = hb_shape_plan_create2 (face, props,
 						       user_features, num_user_features,
 						       coords, num_coords,
 						       shaper_list);
 
-  /* Don't add to the cache if face is inert. */
-  if (unlikely (hb_object_is_inert (face)))
-    return shape_plan;
-
-  /* Don't add the plan to the cache if there were user features with non-global ranges */
-  if (hb_non_global_user_features_present (user_features, num_user_features))
-    return shape_plan;
-  /* Don't add the plan to the cache if there were variation coordinates XXX Fix me. */
-  if (hb_coords_present (coords, num_coords))
+  if (dont_cache)
     return shape_plan;
 
   hb_face_t::plan_node_t *node = (hb_face_t::plan_node_t *) calloc (1, sizeof (hb_face_t::plan_node_t));
commit 566612295b7c9bc003e9f1723f2491113724b788
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Nov 12 17:19:45 2018 -0500

    [shape-plan] Turn hb_shape_plan_proposal_t into hb_shape_plan_key_t
    
    And include it in hb_shape_plan_t itself.

diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc
index a2467101..186ae88b 100644
--- a/src/hb-shape-plan.cc
+++ b/src/hb-shape-plan.cc
@@ -45,41 +45,26 @@
 
 
 static void
-hb_shape_plan_choose_shaper (hb_shape_plan_t    *shape_plan,
-			     const hb_feature_t *user_features,
-			     unsigned int        num_user_features,
-			     const int          *coords,
-			     unsigned int        num_coords,
-			     const char * const *shaper_list)
+hb_shape_plan_key_choose_shaper (hb_shape_plan_key_t *key,
+				 hb_face_t           *face,
+				 const hb_feature_t  *user_features,
+				 unsigned int         num_user_features,
+				 const int           *coords,
+				 unsigned int         num_coords,
+				 const char * const  *shaper_list)
 {
-  DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
-		  "num_features=%d num_coords=%d shaper_list=%p",
-		  num_user_features,
-		  num_coords,
-		  shaper_list);
-
-  const hb_shaper_pair_static_t *shapers = _hb_shapers_get ();
-
 #define HB_SHAPER_PLAN(shaper) \
 	HB_STMT_START { \
-	  if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) \
+	  if (hb_##shaper##_shaper_face_data_ensure (face)) \
 	  { \
-	    shape_plan->shaper_func = _hb_##shaper##_shape; \
-	    shape_plan->shaper_name = #shaper; \
+	    key->shaper_func = _hb_##shaper##_shape; \
+	    key->shaper_name = #shaper; \
 	    return; \
 	  } \
 	} HB_STMT_END
 
-  if (likely (!shaper_list)) {
-    for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++)
-      if (false)
-	;
-#define HB_SHAPER_IMPLEMENT(shaper) \
-      else if (shapers[i].func == _hb_##shaper##_shape) \
-	HB_SHAPER_PLAN (shaper);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-  } else {
+  if (unlikely (shaper_list))
+  {
     for (; *shaper_list; shaper_list++)
       if (false)
 	;
@@ -90,6 +75,16 @@ hb_shape_plan_choose_shaper (hb_shape_plan_t    *shape_plan,
 #undef HB_SHAPER_IMPLEMENT
   }
 
+  const hb_shaper_pair_static_t *shapers = _hb_shapers_get ();
+  for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++)
+    if (false)
+      ;
+#define HB_SHAPER_IMPLEMENT(shaper) \
+    else if (shapers[i].func == _hb_##shaper##_shape) \
+      HB_SHAPER_PLAN (shaper);
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+
 #undef HB_SHAPER_PLAN
 }
 
@@ -142,6 +137,8 @@ hb_shape_plan_create2 (hb_face_t                     *face,
 		  num_coords,
 		  shaper_list);
 
+  assert (props->direction != HB_DIRECTION_INVALID);
+
   hb_shape_plan_t *shape_plan;
   hb_feature_t *features = nullptr;
   int *coords = nullptr;
@@ -152,30 +149,32 @@ hb_shape_plan_create2 (hb_face_t                     *face,
     goto bail;
   if (num_coords && !(coords = (int *) calloc (num_coords, sizeof (int))))
     goto bail;
+
   if (!(shape_plan = hb_object_create<hb_shape_plan_t> ()))
     goto bail;
 
-  assert (props->direction != HB_DIRECTION_INVALID);
-
   if (unlikely (!face))
     face = hb_face_get_empty ();
   hb_face_make_immutable (face);
-
   shape_plan->face_unsafe = face;
-  shape_plan->props = *props;
-  shape_plan->num_user_features = num_user_features;
-  shape_plan->user_features = features;
-  if (num_user_features)
-    memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
-  shape_plan->num_coords = num_coords;
-  shape_plan->coords = coords;
-  if (num_coords)
-    memcpy (coords, orig_coords, num_coords * sizeof (int));
-  shape_plan->custom_shaper_list = shaper_list;
-  hb_shape_plan_choose_shaper (shape_plan,
-			       user_features, num_user_features,
-			       coords, num_coords,
-			       shaper_list);
+
+  {
+    hb_shape_plan_key_t *key = &shape_plan->key;
+    key->props = *props;
+    key->num_user_features = num_user_features;
+    key->user_features = features;
+    if (num_user_features)
+      memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
+    key->num_coords = num_coords;
+    key->coords = coords;
+    if (num_coords)
+      memcpy (coords, orig_coords, num_coords * sizeof (int));
+    hb_shape_plan_key_choose_shaper (key,
+				     face,
+				     user_features, num_user_features,
+				     coords, num_coords,
+				     shaper_list);
+  }
 
   if (unlikely (!shape_plan->ot.init0 (face,
 				       props,
@@ -239,8 +238,8 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan)
 
   shape_plan->ot.fini ();
 
-  free (shape_plan->user_features);
-  free (shape_plan->coords);
+  free ((void *) shape_plan->key.user_features);
+  free ((void *) shape_plan->key.coords);
 
   free (shape_plan);
 }
@@ -312,8 +311,8 @@ hb_shape_plan_execute (hb_shape_plan_t    *shape_plan,
   DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
 		  "num_features=%d shaper_func=%p, shaper_name=%s",
 		  num_features,
-		  shape_plan->shaper_func,
-		  shape_plan->shaper_name);
+		  shape_plan->key.shaper_func,
+		  shape_plan->key.shaper_name);
 
   if (unlikely (!buffer->len))
     return true;
@@ -325,7 +324,7 @@ hb_shape_plan_execute (hb_shape_plan_t    *shape_plan,
     return false;
 
   assert (shape_plan->face_unsafe == font->face);
-  assert (hb_segment_properties_equal (&shape_plan->props, &buffer->props));
+  assert (hb_segment_properties_equal (&shape_plan->key.props, &buffer->props));
 
 #define HB_SHAPER_EXECUTE(shaper) \
 	HB_STMT_START { \
@@ -336,7 +335,7 @@ hb_shape_plan_execute (hb_shape_plan_t    *shape_plan,
   if (false)
     ;
 #define HB_SHAPER_IMPLEMENT(shaper) \
-  else if (shape_plan->shaper_func == _hb_##shaper##_shape) \
+  else if (shape_plan->key.shaper_func == _hb_##shaper##_shape) \
     HB_SHAPER_EXECUTE (shaper);
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
@@ -351,67 +350,36 @@ hb_shape_plan_execute (hb_shape_plan_t    *shape_plan,
  * caching
  */
 
-#if 0
-static unsigned int
-hb_shape_plan_hash (const hb_shape_plan_t *shape_plan)
-{
-  return hb_segment_properties_hash (&shape_plan->props) +
-	 shape_plan->custom_shaper_list ? (intptr_t) shape_plan->shaper_func : 0;
-}
-#endif
-
-/* User-feature caching is currently somewhat dumb:
- * it only finds matches where the feature array is identical,
- * not cases where the feature lists would be compatible for plan purposes
- * but have different ranges, for example.
- */
-struct hb_shape_plan_proposal_t
-{
-  const hb_segment_properties_t  props;
-  const hb_feature_t            *user_features;
-  unsigned int                   num_user_features;
-  const int                     *coords;
-  unsigned int                   num_coords;
-  bool                           custom_shaper_list;
-  hb_shape_func_t               *shaper_func;
-};
-
-static inline hb_bool_t
-hb_shape_plan_user_features_match (const hb_shape_plan_t          *shape_plan,
-				   const hb_shape_plan_proposal_t *proposal)
+static inline bool
+hb_shape_plan_key_user_features_equal (const hb_shape_plan_key_t *key1,
+				       const hb_shape_plan_key_t *key2)
 {
-  if (proposal->num_user_features != shape_plan->num_user_features)
+  if (key1->num_user_features != key2->num_user_features)
     return false;
-  for (unsigned int i = 0, n = proposal->num_user_features; i < n; i++)
-    if (proposal->user_features[i].tag   != shape_plan->user_features[i].tag   ||
-        proposal->user_features[i].value != shape_plan->user_features[i].value ||
-        proposal->user_features[i].start != shape_plan->user_features[i].start ||
-        proposal->user_features[i].end   != shape_plan->user_features[i].end)
-      return false;
-  return true;
+  return 0 == hb_memcmp(key1->user_features,
+			key2->user_features,
+			key1->num_user_features * sizeof (key1->user_features[0]));
 }
 
-static inline hb_bool_t
-hb_shape_plan_coords_match (const hb_shape_plan_t          *shape_plan,
-			    const hb_shape_plan_proposal_t *proposal)
+static inline bool
+hb_shape_plan_key_coords_equal (const hb_shape_plan_key_t *key2,
+				const hb_shape_plan_key_t *key1)
 {
-  if (proposal->num_coords != shape_plan->num_coords)
+  if (key1->num_coords != key2->num_coords)
     return false;
-  for (unsigned int i = 0, n = proposal->num_coords; i < n; i++)
-    if (proposal->coords[i] != shape_plan->coords[i])
-      return false;
-  return true;
+  return 0 == hb_memcmp(key1->coords,
+			key2->coords,
+			key1->num_coords * sizeof (key1->coords[0]));
 }
 
-static hb_bool_t
-hb_shape_plan_matches (const hb_shape_plan_t          *shape_plan,
-		       const hb_shape_plan_proposal_t *proposal)
+static bool
+hb_shape_plan_key_equal (const hb_shape_plan_key_t *key1,
+			 const hb_shape_plan_key_t *key2)
 {
-  return hb_segment_properties_equal (&shape_plan->props, &proposal->props) &&
-	 hb_shape_plan_user_features_match (shape_plan, proposal) &&
-	 hb_shape_plan_coords_match (shape_plan, proposal) &&
-	 ((!shape_plan->custom_shaper_list && !proposal->custom_shaper_list) ||
-	  (shape_plan->shaper_func == proposal->shaper_func));
+  return hb_segment_properties_equal (&key1->props, &key2->props) &&
+	 hb_shape_plan_key_user_features_equal (key1, key2) &&
+	 hb_shape_plan_key_coords_equal (key1, key2) &&
+	 key1->shaper_func == key2->shaper_func;
 }
 
 static inline hb_bool_t
@@ -476,38 +444,20 @@ hb_shape_plan_create_cached2 (hb_face_t                     *face,
 		  num_user_features,
 		  shaper_list);
 
-  hb_shape_plan_proposal_t proposal =
+  hb_shape_plan_key_t key =
   {
     *props,
     user_features,
     num_user_features,
     coords,
     num_coords,
-    shaper_list,
     nullptr
   };
-
-  if (shaper_list)
-  {
-    /* Choose shaper.  Adapted from hb_shape_plan_choose_shaper().
-     * Must choose shaper exactly the same way as that function. */
-    for (const char * const *shaper_item = shaper_list; *shaper_item; shaper_item++)
-      if (false)
-	;
-#define HB_SHAPER_IMPLEMENT(shaper) \
-      else if (0 == strcmp (*shaper_item, #shaper) && \
-	       hb_##shaper##_shaper_face_data_ensure (face)) \
-      { \
-	proposal.shaper_func = _hb_##shaper##_shape; \
-	break; \
-      }
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-
-    if (unlikely (!proposal.shaper_func))
-      return hb_shape_plan_get_empty ();
-  }
-
+  hb_shape_plan_key_choose_shaper (&key,
+				   face,
+				   user_features, num_user_features,
+				   coords, num_coords,
+				   shaper_list);
 
 retry:
   hb_face_t::plan_node_t *cached_plan_nodes = face->shape_plans;
@@ -515,7 +465,7 @@ retry:
   /* Don't look for plan in the cache if there were variation coordinates XXX Fix me. */
   if (!hb_coords_present (coords, num_coords))
     for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next)
-      if (hb_shape_plan_matches (node->shape_plan, &proposal))
+      if (hb_shape_plan_key_equal (&node->shape_plan->key, &key))
       {
         DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache");
         return hb_shape_plan_reference (node->shape_plan);
@@ -569,5 +519,5 @@ retry:
 const char *
 hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan)
 {
-  return shape_plan->shaper_name;
+  return shape_plan->key.shaper_name;
 }
diff --git a/src/hb-shape-plan.hh b/src/hb-shape-plan.hh
index 2849e180..98688f54 100644
--- a/src/hb-shape-plan.hh
+++ b/src/hb-shape-plan.hh
@@ -32,24 +32,25 @@
 #include "hb-ot-shape.hh"
 
 
-struct hb_shape_plan_t
+struct hb_shape_plan_key_t
 {
-  hb_object_header_t header;
-
-  hb_face_t *face_unsafe; /* We don't carry a reference to face. */
-
-  hb_segment_properties_t props;
+  hb_segment_properties_t  props;
 
-  hb_feature_t *user_features;
-  unsigned int num_user_features;
+  const hb_feature_t      *user_features;
+  unsigned int             num_user_features;
 
-  int *coords;
-  unsigned int num_coords;
+  const int               *coords;
+  unsigned int             num_coords;
 
-  bool custom_shaper_list;
-  hb_shape_func_t *shaper_func;
-  const char *shaper_name;
+  hb_shape_func_t         *shaper_func;
+  const char              *shaper_name;
+};
 
+struct hb_shape_plan_t
+{
+  hb_object_header_t header;
+  hb_face_t *face_unsafe; /* We don't carry a reference to face. */
+  hb_shape_plan_key_t key;
   hb_ot_shape_plan_t ot;
 };
 
commit af123bd1b814b4fb881ea3d11f1ef0bcced75942
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Nov 12 16:27:08 2018 -0500

    Add hb_memcmp()

diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh
index 2540d438..7a207f5d 100644
--- a/src/hb-dsalgs.hh
+++ b/src/hb-dsalgs.hh
@@ -264,6 +264,17 @@ static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; }
 /* A const version, but does not detect erratically being called on pointers. */
 #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0])))
 
+
+static inline int
+hb_memcmp (const void *a, const void *b, unsigned int len)
+{
+  /* It's illegal to pass NULL to memcmp(), even if len is zero.
+   * So, wrap it.
+   * https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */
+  if (!len) return 0;
+  return memcmp (a, b, len);
+}
+
 static inline bool
 hb_unsigned_mul_overflows (unsigned int count, unsigned int size)
 {
@@ -535,11 +546,7 @@ struct hb_bytes_t
   {
     if (len != a.len)
       return (int) a.len - (int) len;
-
-    if (!len)
-      return 0; /* glibc's memcmp() declares args non-NULL, and UBSan doesn't like that. :( */
-
-    return memcmp (a.arrayZ, arrayZ, len);
+    return hb_memcmp (a.arrayZ, arrayZ, len);
   }
   static inline int cmp (const void *pa, const void *pb)
   {
diff --git a/src/hb-set.hh b/src/hb-set.hh
index c47f77b7..bc26ed3c 100644
--- a/src/hb-set.hh
+++ b/src/hb-set.hh
@@ -90,7 +90,7 @@ struct hb_set_t
 
     inline bool is_equal (const page_t *other) const
     {
-      return 0 == memcmp (&v, &other->v, sizeof (v));
+      return 0 == hb_memcmp (&v, &other->v, sizeof (v));
     }
 
     inline unsigned int get_population (void) const
commit 65456bff37ef61094c35574a35c96f6437fd6015
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Nov 12 16:15:26 2018 -0500

    [shape-plan] Minor

diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc
index 4bd50abd..a2467101 100644
--- a/src/hb-shape-plan.cc
+++ b/src/hb-shape-plan.cc
@@ -161,7 +161,6 @@ hb_shape_plan_create2 (hb_face_t                     *face,
     face = hb_face_get_empty ();
   hb_face_make_immutable (face);
 
-  shape_plan->custom_shaper_list = shaper_list;
   shape_plan->face_unsafe = face;
   shape_plan->props = *props;
   shape_plan->num_user_features = num_user_features;
@@ -172,7 +171,7 @@ hb_shape_plan_create2 (hb_face_t                     *face,
   shape_plan->coords = coords;
   if (num_coords)
     memcpy (coords, orig_coords, num_coords * sizeof (int));
-
+  shape_plan->custom_shaper_list = shaper_list;
   hb_shape_plan_choose_shaper (shape_plan,
 			       user_features, num_user_features,
 			       coords, num_coords,
@@ -369,11 +368,11 @@ hb_shape_plan_hash (const hb_shape_plan_t *shape_plan)
 struct hb_shape_plan_proposal_t
 {
   const hb_segment_properties_t  props;
-  const char * const            *shaper_list;
   const hb_feature_t            *user_features;
   unsigned int                   num_user_features;
   const int                     *coords;
   unsigned int                   num_coords;
+  bool                           custom_shaper_list;
   hb_shape_func_t               *shaper_func;
 };
 
@@ -411,7 +410,7 @@ hb_shape_plan_matches (const hb_shape_plan_t          *shape_plan,
   return hb_segment_properties_equal (&shape_plan->props, &proposal->props) &&
 	 hb_shape_plan_user_features_match (shape_plan, proposal) &&
 	 hb_shape_plan_coords_match (shape_plan, proposal) &&
-	 ((!shape_plan->custom_shaper_list && !proposal->shaper_list) ||
+	 ((!shape_plan->custom_shaper_list && !proposal->custom_shaper_list) ||
 	  (shape_plan->shaper_func == proposal->shaper_func));
 }
 
@@ -477,17 +476,19 @@ hb_shape_plan_create_cached2 (hb_face_t                     *face,
 		  num_user_features,
 		  shaper_list);
 
-  hb_shape_plan_proposal_t proposal = {
+  hb_shape_plan_proposal_t proposal =
+  {
     *props,
-    shaper_list,
     user_features,
     num_user_features,
     coords,
     num_coords,
+    shaper_list,
     nullptr
   };
 
-  if (shaper_list) {
+  if (shaper_list)
+  {
     /* Choose shaper.  Adapted from hb_shape_plan_choose_shaper().
      * Must choose shaper exactly the same way as that function. */
     for (const char * const *shaper_item = shaper_list; *shaper_item; shaper_item++)
diff --git a/src/hb-shape-plan.hh b/src/hb-shape-plan.hh
index eaa84fd4..2849e180 100644
--- a/src/hb-shape-plan.hh
+++ b/src/hb-shape-plan.hh
@@ -37,11 +37,8 @@ struct hb_shape_plan_t
   hb_object_header_t header;
 
   hb_face_t *face_unsafe; /* We don't carry a reference to face. */
-  bool custom_shaper_list;
-  hb_segment_properties_t props;
 
-  hb_shape_func_t *shaper_func;
-  const char *shaper_name;
+  hb_segment_properties_t props;
 
   hb_feature_t *user_features;
   unsigned int num_user_features;
@@ -49,6 +46,10 @@ struct hb_shape_plan_t
   int *coords;
   unsigned int num_coords;
 
+  bool custom_shaper_list;
+  hb_shape_func_t *shaper_func;
+  const char *shaper_name;
+
   hb_ot_shape_plan_t ot;
 };
 
commit 1db672a5e903de39f955e70b8814c275ccbe1b5c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Nov 12 16:05:09 2018 -0500

    [shaper] Rename

diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc
index 0d51165f..4bd50abd 100644
--- a/src/hb-shape-plan.cc
+++ b/src/hb-shape-plan.cc
@@ -58,7 +58,7 @@ hb_shape_plan_choose_shaper (hb_shape_plan_t    *shape_plan,
 		  num_coords,
 		  shaper_list);
 
-  const hb_shaper_pair_t *shapers = _hb_shapers_get ();
+  const hb_shaper_pair_static_t *shapers = _hb_shapers_get ();
 
 #define HB_SHAPER_PLAN(shaper) \
 	HB_STMT_START { \
diff --git a/src/hb-shape.cc b/src/hb-shape.cc
index f98bc6e5..325be0f1 100644
--- a/src/hb-shape.cc
+++ b/src/hb-shape.cc
@@ -63,7 +63,7 @@ static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_t<const char *,
     if (unlikely (!shaper_list))
       return nullptr;
 
-    const hb_shaper_pair_t *shapers = _hb_shapers_get ();
+    const hb_shaper_pair_static_t *shapers = _hb_shapers_get ();
     unsigned int i;
     for (i = 0; i < HB_SHAPERS_COUNT; i++)
       shaper_list[i] = shapers[i].name;
diff --git a/src/hb-shaper.cc b/src/hb-shaper.cc
index 52418c08..58a5e497 100644
--- a/src/hb-shaper.cc
+++ b/src/hb-shaper.cc
@@ -29,7 +29,7 @@
 #include "hb-machinery.hh"
 
 
-static const hb_shaper_pair_t all_shapers[] = {
+static const hb_shaper_pair_static_t all_shapers[] = {
 #define HB_SHAPER_IMPLEMENT(name) {#name, _hb_##name##_shape},
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
@@ -39,16 +39,16 @@ static const hb_shaper_pair_t all_shapers[] = {
 static void free_static_shapers (void);
 #endif
 
-static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_pair_t,
+static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_pair_static_t,
 							  hb_shapers_lazy_loader_t>
 {
-  static inline hb_shaper_pair_t *create (void)
+  static inline hb_shaper_pair_static_t *create (void)
   {
     char *env = getenv ("HB_SHAPER_LIST");
     if (!env || !*env)
       return nullptr;
 
-    hb_shaper_pair_t *shapers = (hb_shaper_pair_t *) calloc (1, sizeof (all_shapers));
+    hb_shaper_pair_static_t *shapers = (hb_shaper_pair_static_t *) calloc (1, sizeof (all_shapers));
     if (unlikely (!shapers))
       return nullptr;
 
@@ -68,7 +68,7 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_pair_t
 	    0 == strncmp (shapers[j].name, p, end - p))
 	{
 	  /* Reorder this shaper to position i */
-	 struct hb_shaper_pair_t t = shapers[j];
+	 struct hb_shaper_pair_static_t t = shapers[j];
 	 memmove (&shapers[i + 1], &shapers[i], sizeof (shapers[i]) * (j - i));
 	 shapers[i] = t;
 	 i++;
@@ -86,11 +86,11 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_pair_t
 
     return shapers;
   }
-  static inline void destroy (const hb_shaper_pair_t *p)
+  static inline void destroy (const hb_shaper_pair_static_t *p)
   {
     free ((void *) p);
   }
-  static inline const hb_shaper_pair_t *get_null (void)
+  static inline const hb_shaper_pair_static_t *get_null (void)
   {
     return all_shapers;
   }
@@ -104,7 +104,7 @@ void free_static_shapers (void)
 }
 #endif
 
-const hb_shaper_pair_t *
+const hb_shaper_pair_static_t *
 _hb_shapers_get (void)
 {
   return static_shapers.get_unconst ();
diff --git a/src/hb-shaper.hh b/src/hb-shaper.hh
index e3be4119..f29b29f9 100644
--- a/src/hb-shaper.hh
+++ b/src/hb-shaper.hh
@@ -40,12 +40,12 @@ typedef hb_bool_t hb_shape_func_t (hb_shape_plan_t    *shape_plan,
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
 
-struct hb_shaper_pair_t {
+struct hb_shaper_pair_static_t {
   char name[16];
   hb_shape_func_t *func;
 };
 
-HB_INTERNAL const hb_shaper_pair_t *
+HB_INTERNAL const hb_shaper_pair_static_t *
 _hb_shapers_get (void);
 
 


More information about the HarfBuzz mailing list