[HarfBuzz] harfbuzz: Branch 'master'

Behdad Esfahbod behdad at kemper.freedesktop.org
Fri Aug 11 22:18:38 UTC 2017


 util/hb-shape.cc       |    7 ++-----
 util/options.cc        |    2 ++
 util/options.hh        |   42 +++++++++++++++++++++++++++++++++++++++---
 util/shape-consumer.hh |   12 ++++++++----
 util/view-cairo.hh     |    7 ++-----
 5 files changed, 53 insertions(+), 17 deletions(-)

New commits:
commit d2052278f24b3279503d5fa215a7834c2d21f91c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Aug 11 15:12:25 2017 -0700

    [util] Add --verify to hb-shape / hb-view that verifies shape results
    
    Right now it checks for monotone cluster values.  Other checks to be added.

diff --git a/util/hb-shape.cc b/util/hb-shape.cc
index 6adfbadd..cab0eb21 100644
--- a/util/hb-shape.cc
+++ b/util/hb-shape.cc
@@ -94,13 +94,10 @@ struct output_buffer_t
     format.serialize_buffer_of_text (buffer, line_no, text, text_len, font, gs);
     fprintf (options.fp, "%s", gs->str);
   }
-  void shape_failed (hb_buffer_t  *buffer,
-		     const char   *text,
-		     unsigned int  text_len,
-		     hb_bool_t     utf8_clusters)
+  void error (const char *message)
   {
     g_string_set_size (gs, 0);
-    format.serialize_message (line_no, "msg: all shapers failed", gs);
+    format.serialize_message (line_no, message, gs);
     fprintf (options.fp, "%s", gs->str);
   }
   void consume_glyphs (hb_buffer_t  *buffer,
diff --git a/util/options.cc b/util/options.cc
index 2aba6d40..1269ba65 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -338,6 +338,7 @@ shape_options_t::add_options (option_parser_t *parser)
     {"utf8-clusters",	0, 0, G_OPTION_ARG_NONE,	&this->utf8_clusters,		"Use UTF8 byte indices, not char indices",	NULL},
     {"cluster-level",	0, 0, G_OPTION_ARG_INT,		&this->cluster_level,		"Cluster merging level (default: 0)",	"0/1/2"},
     {"normalize-glyphs",0, 0, G_OPTION_ARG_NONE,	&this->normalize_glyphs,	"Rearrange glyph clusters in nominal order",	NULL},
+    {"verify",		0, 0, G_OPTION_ARG_NONE,	&this->verify,			"Perform sanity checks on shaping results",	NULL},
     {"num-iterations",	0, 0, G_OPTION_ARG_INT,		&this->num_iterations,		"Run shaper N times (default: 1)",	"N"},
     {NULL}
   };
@@ -874,6 +875,7 @@ format_options_t::serialize_message (unsigned int  line_no,
 				     GString      *gs)
 {
   serialize_line_no (line_no, gs);
+  g_string_append_printf (gs, "message: ");
   g_string_append_printf (gs, "%s", msg);
   g_string_append_c (gs, '\n');
 }
diff --git a/util/options.hh b/util/options.hh
index 521263d5..fedd1217 100644
--- a/util/options.hh
+++ b/util/options.hh
@@ -187,6 +187,7 @@ struct shape_options_t : option_group_t
     utf8_clusters = false;
     cluster_level = HB_BUFFER_CLUSTER_LEVEL_DEFAULT;
     normalize_glyphs = false;
+    verify = false;
     num_iterations = 1;
 
     add_options (parser);
@@ -243,12 +244,46 @@ struct shape_options_t : option_group_t
     setup_buffer (buffer);
   }
 
-  hb_bool_t shape (hb_font_t *font, hb_buffer_t *buffer)
+  hb_bool_t shape (hb_font_t *font, hb_buffer_t *buffer, const char **error=NULL)
   {
-    hb_bool_t res = hb_shape_full (font, buffer, features, num_features, shapers);
+    if (!hb_shape_full (font, buffer, features, num_features, shapers))
+    {
+      if (error)
+        *error = "all shapers failed.";
+      return false;
+    }
+
     if (normalize_glyphs)
       hb_buffer_normalize_glyphs (buffer);
-    return res;
+
+    if (verify && !verify_buffer (buffer, error))
+      return false;
+
+    return true;
+  }
+
+  bool verify_buffer (hb_buffer_t *buffer, const char **error=NULL)
+  {
+    /* Check that clusters are monotone. */
+    if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES ||
+	cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+    {
+      bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
+
+      unsigned int num_glyphs;
+      hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
+
+      for (unsigned int i = 1; i < num_glyphs; i++)
+	if (info[i-1].cluster != info[i].cluster &&
+	    (info[i-1].cluster < info[i].cluster) != is_forward)
+	{
+	  if (error)
+	    *error = "clusters are not monotone.";
+	  return false;
+	}
+    }
+
+    return true;
   }
 
   void shape_closure (const char *text, int text_len,
@@ -277,6 +312,7 @@ struct shape_options_t : option_group_t
   hb_bool_t utf8_clusters;
   hb_buffer_cluster_level_t cluster_level;
   hb_bool_t normalize_glyphs;
+  hb_bool_t verify;
   unsigned int num_iterations;
 };
 
diff --git a/util/shape-consumer.hh b/util/shape-consumer.hh
index cfab4497..0a09053e 100644
--- a/util/shape-consumer.hh
+++ b/util/shape-consumer.hh
@@ -58,15 +58,19 @@ struct shape_consumer_t
 
     for (unsigned int n = shaper.num_iterations; n; n--)
     {
+      const char *error = NULL;
+
       shaper.populate_buffer (buffer, text, text_len, text_before, text_after);
       if (n == 1)
 	output.consume_text (buffer, text, text_len, shaper.utf8_clusters);
-      if (!shaper.shape (font, buffer))
+      if (!shaper.shape (font, buffer, &error))
       {
 	failed = true;
-	hb_buffer_set_length (buffer, 0);
-	output.shape_failed (buffer, text, text_len, shaper.utf8_clusters);
-	return;
+	output.error (error);
+	if (hb_buffer_get_content_type (buffer) == HB_BUFFER_CONTENT_TYPE_GLYPHS)
+	  break;
+	else
+	  return;
       }
     }
 
diff --git a/util/view-cairo.hh b/util/view-cairo.hh
index ef229ff7..d3e59afa 100644
--- a/util/view-cairo.hh
+++ b/util/view-cairo.hh
@@ -57,12 +57,9 @@ struct view_cairo_t
 		     hb_bool_t     utf8_clusters)
   {
   }
-  void shape_failed (hb_buffer_t  *buffer,
-		     const char   *text,
-		     unsigned int  text_len,
-		     hb_bool_t     utf8_clusters)
+  void error (const char *message)
   {
-    fail (false, "all shapers failed");
+    fail (false, "%s", message);
   }
   void consume_glyphs (hb_buffer_t  *buffer,
 		       const char   *text,


More information about the HarfBuzz mailing list