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

Behdad Esfahbod behdad at kemper.freedesktop.org
Thu Nov 15 13:11:20 PST 2012


 src/hb-buffer.cc            |  222 ++++++++++++++++++++++++++++++++++++++++++++
 src/hb-buffer.h             |   42 ++++++++
 src/hb-open-type-private.hh |    4 
 util/hb-shape.cc            |   21 +++-
 util/options.cc             |   57 +++--------
 util/options.hh             |    7 -
 6 files changed, 306 insertions(+), 47 deletions(-)

New commits:
commit f9edf1672511c3bcc3796cc79578ffea43b2bda1
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Nov 15 12:14:09 2012 -0800

    Add buffer serialization / deserialization API
    
    Two output formats for now: TEXT, and JSON.  For example:
    
      hb-shape --output-format=json
    
    Deserialization API is added, but not implemented yet.

diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index 7a8cb15..a599153 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -1023,3 +1023,225 @@ hb_buffer_normalize_glyphs (hb_buffer_t *buffer)
     }
   normalize_glyphs_cluster (buffer, start, end, backward);
 }
+
+
+/*
+ * Serialize
+ */
+
+static const char *serialize_formats[] = {
+  "TEXT",
+  "JSON",
+  NULL
+};
+
+hb_buffer_serialize_format_t
+hb_buffer_serialize_format_from_string (const char *str, int len)
+{
+  /* Upper-case it. */
+  return (hb_buffer_serialize_format_t) (hb_tag_from_string (str, len) & ~0x20202020);
+}
+
+const char *
+hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format)
+{
+  switch (format)
+  {
+    case HB_BUFFER_SERIALIZE_FORMAT_TEXT:	return serialize_formats[0];
+    case HB_BUFFER_SERIALIZE_FORMAT_JSON:	return serialize_formats[1];
+    default:
+    case HB_BUFFER_SERIALIZE_FORMAT_INVALID:	return NULL;
+  }
+}
+
+static unsigned int
+_hb_buffer_serialize_glyphs_json (hb_buffer_t *buffer,
+				  unsigned int start,
+				  unsigned int end,
+				  char *buf,
+				  unsigned int buf_size,
+				  unsigned int *buf_consumed,
+				  hb_font_t *font,
+				  hb_buffer_serialize_flags_t flags)
+{
+  hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL);
+  hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL);
+
+  *buf_consumed = 0;
+  for (unsigned int i = start; i < end; i++)
+  {
+    char b[1024];
+    char *p = b;
+
+    /* In the following code, we know b is large enough that no overflow can happen. */
+
+#define APPEND(s) HB_STMT_START { strcpy (p, s); p += strlen (s); } HB_STMT_END
+
+    if (i)
+      *p++ = ',';
+
+    *p++ = '{';
+
+    APPEND ("\"g\":");
+    if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES))
+    {
+      char g[128];
+      hb_font_glyph_to_string (font, info[i].codepoint, g, sizeof (g));
+      *p++ = '"';
+      for (char *q = g; *q; q++) {
+        if (*q == '"')
+	  *p++ = '\\';
+	*p++ = *q;
+      }
+      *p++ = '"';
+    }
+    else
+      p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint);
+
+    if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) {
+      p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"cl\":%u", info[i].cluster);
+    }
+
+    if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
+    {
+      p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"dx\":%d,\"dy\":%d",
+		     pos[i].x_offset, pos[i].y_offset);
+      p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",\"ax\":%d,\"ay\":%d",
+		     pos[i].x_advance, pos[i].y_advance);
+    }
+
+    *p++ = '}';
+
+    if (buf_size > (p - b))
+    {
+      unsigned int l = p - b;
+      memcpy (buf, b, l);
+      buf += l;
+      buf_size -= l;
+      *buf_consumed += l;
+      *buf = '\0';
+    } else
+      return i - start;
+  }
+
+  return end - start;
+}
+
+static unsigned int
+_hb_buffer_serialize_glyphs_text (hb_buffer_t *buffer,
+				  unsigned int start,
+				  unsigned int end,
+				  char *buf,
+				  unsigned int buf_size,
+				  unsigned int *buf_consumed,
+				  hb_font_t *font,
+				  hb_buffer_serialize_flags_t flags)
+{
+  hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL);
+  hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL);
+  hb_direction_t direction = hb_buffer_get_direction (buffer);
+
+  *buf_consumed = 0;
+  for (unsigned int i = start; i < end; i++)
+  {
+    char b[1024];
+    char *p = b;
+
+    /* In the following code, we know b is large enough that no overflow can happen. */
+
+    if (i)
+      *p++ = '|';
+
+    if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES))
+    {
+      hb_font_glyph_to_string (font, info[i].codepoint, p, 128);
+      p += strlen (p);
+    }
+    else
+      p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "%u", info[i].codepoint);
+
+    if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS)) {
+      p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "=%u", info[i].cluster);
+    }
+
+    if (!(flags & HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS))
+    {
+      if (pos[i].x_offset || pos[i].y_offset)
+	p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "@%d,%d", pos[i].x_offset, pos[i].y_offset);
+
+      *p++ = '+';
+      if (HB_DIRECTION_IS_HORIZONTAL (direction) || pos[i].x_advance)
+	p += snprintf (p, ARRAY_LENGTH (b) - (p - b), "%d", pos[i].x_advance);
+      if (HB_DIRECTION_IS_VERTICAL (direction) || pos->y_advance)
+	p += snprintf (p, ARRAY_LENGTH (b) - (p - b), ",%d", pos[i].y_advance);
+    }
+
+    if (buf_size > (p - b))
+    {
+      unsigned int l = p - b;
+      memcpy (buf, b, l);
+      buf += l;
+      buf_size -= l;
+      *buf_consumed += l;
+      *buf = '\0';
+    } else
+      return i - start;
+  }
+
+  return end - start;
+}
+
+/* Returns number of items, starting at start, that were serialized. */
+unsigned int
+hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
+			    unsigned int start,
+			    unsigned int end,
+			    char *buf,
+			    unsigned int buf_size,
+			    unsigned int *buf_consumed,
+			    hb_font_t *font, /* May be NULL */
+			    hb_buffer_serialize_format_t format,
+			    hb_buffer_serialize_flags_t flags)
+{
+  assert (start <= end && end <= buffer->len);
+
+  *buf_consumed = 0;
+
+  assert ((!buffer->len && buffer->content_type == HB_BUFFER_CONTENT_TYPE_INVALID) ||
+	  buffer->content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS);
+
+  if (unlikely (start == end))
+    return 0;
+
+  if (!font)
+    font = hb_font_get_empty ();
+
+  switch (format)
+  {
+    case HB_BUFFER_SERIALIZE_FORMAT_TEXT:
+      return _hb_buffer_serialize_glyphs_text (buffer, start, end,
+					       buf, buf_size, buf_consumed,
+					       font, flags);
+
+    case HB_BUFFER_SERIALIZE_FORMAT_JSON:
+      return _hb_buffer_serialize_glyphs_json (buffer, start, end,
+					       buf, buf_size, buf_consumed,
+					       font, flags);
+
+    default:
+    case HB_BUFFER_SERIALIZE_FORMAT_INVALID:
+      return 0;
+
+  }
+}
+
+hb_bool_t
+hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
+			      const char *buf,
+			      unsigned int buf_len,
+			      unsigned int *buf_consumed,
+			      hb_font_t *font, /* May be NULL */
+			      hb_buffer_serialize_format_t format)
+{
+  return false;
+}
diff --git a/src/hb-buffer.h b/src/hb-buffer.h
index 8e1690d..ba9cd1d 100644
--- a/src/hb-buffer.h
+++ b/src/hb-buffer.h
@@ -36,6 +36,7 @@
 
 #include "hb-common.h"
 #include "hb-unicode.h"
+#include "hb-font.h"
 
 HB_BEGIN_DECLS
 
@@ -238,6 +239,47 @@ hb_buffer_normalize_glyphs (hb_buffer_t *buffer);
 */
 
 
+typedef enum {
+  HB_BUFFER_SERIALIZE_FLAGS_DEFAULT		= 0x00000000,
+  HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS		= 0x00000001,
+  HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS		= 0x00000002,
+  HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES	= 0x00000004
+} hb_buffer_serialize_flags_t;
+
+typedef enum {
+  HB_BUFFER_SERIALIZE_FORMAT_TEXT	= HB_TAG('T','E','X','T'),
+  HB_BUFFER_SERIALIZE_FORMAT_JSON	= HB_TAG('J','S','O','N'),
+  HB_BUFFER_SERIALIZE_FORMAT_INVALID	= HB_TAG_NONE
+} hb_buffer_serialize_format_t;
+
+/* len=-1 means str is NUL-terminated. */
+hb_buffer_serialize_format_t
+hb_buffer_serialize_format_from_string (const char *str, int len);
+
+const char *
+hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format);
+
+/* Returns number of items, starting at start, that were serialized. */
+unsigned int
+hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
+			    unsigned int start,
+			    unsigned int end,
+			    char *buf,
+			    unsigned int buf_size,
+			    unsigned int *buf_consumed,
+			    hb_font_t *font, /* May be NULL */
+			    hb_buffer_serialize_format_t format,
+			    hb_buffer_serialize_flags_t flags);
+
+hb_bool_t
+hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
+			      const char *buf,
+			      unsigned int buf_len,
+			      unsigned int *buf_consumed,
+			      hb_font_t *font, /* May be NULL */
+			      hb_buffer_serialize_format_t format);
+
+
 HB_END_DECLS
 
 #endif /* HB_BUFFER_H */
diff --git a/util/hb-shape.cc b/util/hb-shape.cc
index b23519b..ef926da 100644
--- a/util/hb-shape.cc
+++ b/util/hb-shape.cc
@@ -40,6 +40,20 @@ struct output_buffer_t
     gs = g_string_new (NULL);
     line_no = 0;
     font = hb_font_reference (font_opts->get_font ());
+
+    if (!options.output_format)
+      output_format = HB_BUFFER_SERIALIZE_FORMAT_TEXT;
+    else
+      output_format = hb_buffer_serialize_format_from_string (options.output_format, -1);
+
+    unsigned int flags = HB_BUFFER_SERIALIZE_FLAGS_DEFAULT;
+    if (!format.show_glyph_names)
+      flags |= HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES;
+    if (!format.show_clusters)
+      flags |= HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS;
+    if (!format.show_positions)
+      flags |= HB_BUFFER_SERIALIZE_FLAG_NO_POSITIONS;
+    format_flags = (hb_buffer_serialize_flags_t) flags;
   }
   void new_line (void)
   {
@@ -51,7 +65,7 @@ struct output_buffer_t
 		     hb_bool_t     utf8_clusters)
   {
     g_string_set_size (gs, 0);
-    format.serialize_buffer_of_text (buffer, line_no, text, text_len, font, utf8_clusters, gs);
+    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,
@@ -69,7 +83,8 @@ struct output_buffer_t
 		       hb_bool_t     utf8_clusters)
   {
     g_string_set_size (gs, 0);
-    format.serialize_buffer_of_glyphs (buffer, line_no, text, text_len, font, utf8_clusters, gs);
+    format.serialize_buffer_of_glyphs (buffer, line_no, text, text_len, font,
+				       output_format, format_flags, gs);
     fprintf (options.fp, "%s", gs->str);
   }
   void finish (const font_options_t *font_opts)
@@ -87,6 +102,8 @@ struct output_buffer_t
   GString *gs;
   unsigned int line_no;
   hb_font_t *font;
+  hb_buffer_serialize_format_t output_format;
+  hb_buffer_serialize_flags_t format_flags;
 };
 
 int
diff --git a/util/options.cc b/util/options.cc
index ca621bf..44c9173 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -615,46 +615,23 @@ format_options_t::serialize_unicode (hb_buffer_t *buffer,
 void
 format_options_t::serialize_glyphs (hb_buffer_t *buffer,
 				    hb_font_t   *font,
-				    hb_bool_t    utf8_clusters,
+				    hb_buffer_serialize_format_t output_format,
+				    hb_buffer_serialize_flags_t flags,
 				    GString     *gs)
 {
-  unsigned int num_glyphs = hb_buffer_get_length (buffer);
-  hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, NULL);
-  hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, NULL);
-  hb_direction_t direction = hb_buffer_get_direction (buffer);
-
   g_string_append_c (gs, '[');
-  for (unsigned int i = 0; i < num_glyphs; i++)
-  {
-    if (i)
-      g_string_append_c (gs, '|');
-
-    char glyph_name[128];
-    if (show_glyph_names) {
-      hb_font_glyph_to_string (font, info->codepoint, glyph_name, sizeof (glyph_name));
-      g_string_append_printf (gs, "%s", glyph_name);
-    } else
-      g_string_append_printf (gs, "%u", info->codepoint);
-
-    if (show_clusters) {
-      g_string_append_printf (gs, "=%u", info->cluster);
-      if (utf8_clusters)
-	g_string_append (gs, "u8");
-    }
-
-    if (show_positions && (pos->x_offset || pos->y_offset)) {
-      g_string_append_printf (gs, "@%d,%d", pos->x_offset, pos->y_offset);
-    }
-    if (show_positions) {
-      g_string_append_c (gs, '+');
-      if (HB_DIRECTION_IS_HORIZONTAL (direction) || pos->x_advance)
-	g_string_append_printf (gs, "%d", pos->x_advance);
-      if (HB_DIRECTION_IS_VERTICAL (direction) || pos->y_advance)
-	g_string_append_printf (gs, ",%d", pos->y_advance);
-    }
-
-    info++;
-    pos++;
+  unsigned int num_glyphs = hb_buffer_get_length (buffer);
+  unsigned int start = 0;
+
+  while (start < num_glyphs) {
+    char buf[1024];
+    unsigned int consumed;
+    start += hb_buffer_serialize_glyphs (buffer, start, num_glyphs,
+					 buf, sizeof (buf), &consumed,
+					 font, output_format, flags);
+    if (!consumed)
+      break;
+    g_string_append (gs, buf);
   }
   g_string_append_c (gs, ']');
 }
@@ -671,7 +648,6 @@ format_options_t::serialize_buffer_of_text (hb_buffer_t  *buffer,
 					    const char   *text,
 					    unsigned int  text_len,
 					    hb_font_t    *font,
-					    hb_bool_t     utf8_clusters,
 					    GString      *gs)
 {
   if (show_text) {
@@ -703,10 +679,11 @@ format_options_t::serialize_buffer_of_glyphs (hb_buffer_t  *buffer,
 					      const char   *text,
 					      unsigned int  text_len,
 					      hb_font_t    *font,
-					      hb_bool_t     utf8_clusters,
+					      hb_buffer_serialize_format_t output_format,
+					      hb_buffer_serialize_flags_t format_flags,
 					      GString      *gs)
 {
   serialize_line_no (line_no, gs);
-  serialize_glyphs (buffer, font, utf8_clusters, gs);
+  serialize_glyphs (buffer, font, output_format, format_flags, gs);
   g_string_append_c (gs, '\n');
 }
diff --git a/util/options.hh b/util/options.hh
index be6878b..093f052 100644
--- a/util/options.hh
+++ b/util/options.hh
@@ -364,7 +364,8 @@ struct format_options_t : option_group_t
 			  GString      *gs);
   void serialize_glyphs (hb_buffer_t  *buffer,
 			 hb_font_t    *font,
-			 hb_bool_t    utf8_clusters,
+			 hb_buffer_serialize_format_t format,
+			 hb_buffer_serialize_flags_t flags,
 			 GString      *gs);
   void serialize_line_no (unsigned int  line_no,
 			  GString      *gs);
@@ -373,7 +374,6 @@ struct format_options_t : option_group_t
 				 const char   *text,
 				 unsigned int  text_len,
 				 hb_font_t    *font,
-				 hb_bool_t     utf8_clusters,
 				 GString      *gs);
   void serialize_message (unsigned int  line_no,
 			  const char   *msg,
@@ -383,7 +383,8 @@ struct format_options_t : option_group_t
 				   const char   *text,
 				   unsigned int  text_len,
 				   hb_font_t    *font,
-				   hb_bool_t     utf8_clusters,
+				   hb_buffer_serialize_format_t output_format,
+				   hb_buffer_serialize_flags_t format_flags,
 				   GString      *gs);
 
 
commit fd0de881f4fc004da6f36d50a91d0e62f8eb4d8c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Thu Nov 15 10:47:14 2012 -0800

    Avoid C++ undefined behavior
    
    https://bugzilla.mozilla.org/show_bug.cgi?id=810823

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 3067b90..8595038 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -138,13 +138,13 @@ static const void *_NullPool[64 / sizeof (void *)];
 /* Generic nul-content Null objects. */
 template <typename Type>
 static inline const Type& Null (void) {
-  ASSERT_STATIC (Type::min_size <= sizeof (_NullPool));
+  ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool));
   return *CastP<Type> (_NullPool);
 }
 
 /* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
 #define DEFINE_NULL_DATA(Type, data) \
-static const char _Null##Type[Type::min_size + 1] = data; /* +1 is for nul-termination in data */ \
+static const char _Null##Type[sizeof (Type) + 1] = data; /* +1 is for nul-termination in data */ \
 template <> \
 inline const Type& Null<Type> (void) { \
   return *CastP<Type> (_Null##Type); \



More information about the HarfBuzz mailing list