Add hb_font_glyph_from/to_string
authorBehdad Esfahbod <behdad@behdad.org>
Wed, 8 Aug 2012 02:13:25 +0000 (22:13 -0400)
committerBehdad Esfahbod <behdad@behdad.org>
Wed, 8 Aug 2012 02:13:25 +0000 (22:13 -0400)
src/hb-font-private.hh
src/hb-font.cc
src/hb-font.h
src/hb-private.hh
src/test-would-substitute.cc
util/options.cc

index 56c5913..6bbf8d8 100644 (file)
@@ -254,6 +254,7 @@ struct hb_font_t {
   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,
@@ -263,6 +264,8 @@ struct hb_font_t {
   inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
                                        hb_codepoint_t *glyph)
   {
+    *glyph = 0;
+    if (len == -1) len = strlen (name);
     return klass->get.glyph_from_name (this, user_data,
                                       name, len,
                                       glyph,
@@ -377,6 +380,46 @@ struct hb_font_t {
     return ret;
   }
 
+  /* Generates gidDDD if glyph has no name. */
+  inline void
+  glyph_to_string (hb_codepoint_t glyph,
+                  char *s, unsigned int size)
+  {
+    if (get_glyph_name (glyph, s, size)) return;
+
+    snprintf (s, size, "gid%u", glyph);
+  }
+
+  /* Parses gidDDD and uniUUUU strings automatically. */
+  inline hb_bool_t
+  glyph_from_string (const char *s, int len, /* -1 means nul-terminated */
+                    hb_codepoint_t *glyph)
+  {
+    if (get_glyph_from_name (s, len, glyph)) return true;
+
+    if (len == -1) len = strlen (s);
+
+    /* Straight glyph index. */
+    if (hb_codepoint_parse (s, len, 10, glyph))
+      return true;
+
+    if (len > 3)
+    {
+      /* gidDDD syntax for glyph indices. */
+      if (0 == strncmp (s, "gid", 3) &&
+         hb_codepoint_parse (s + 3, len - 3, 10, glyph))
+       return true;
+
+      /* uniUUUU and other Unicode character indices. */
+      hb_codepoint_t unichar;
+      if (0 == strncmp (s, "uni", 3) &&
+         hb_codepoint_parse (s + 3, len - 3, 16, &unichar) &&
+         get_glyph (unichar, 0, glyph))
+       return true;
+    }
+
+    return false;
+  }
 
   private:
   inline hb_position_t em_scale (int16_t v, int scale) { return v * (int64_t) scale / hb_face_get_upem (this->face); }
index 409b9e8..e5e4af7 100644 (file)
@@ -200,6 +200,7 @@ hb_font_get_glyph_name_nil (hb_font_t *font,
   if (font->parent)
     return hb_font_get_glyph_name (font->parent, glyph, name, size);
 
+  if (size) *name = '\0';
   return false;
 }
 
@@ -410,10 +411,7 @@ hb_font_get_glyph_name (hb_font_t *font,
                        hb_codepoint_t glyph,
                        char *name, unsigned int size)
 {
-  hb_bool_t ret = font->get_glyph_name (glyph, name, size);
-  if (!ret)
-    snprintf (name, size, "gid%u", glyph);
-  return ret;
+  return font->get_glyph_name (glyph, name, size);
 }
 
 hb_bool_t
@@ -490,6 +488,24 @@ hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
   return font->get_glyph_contour_point_for_origin (glyph, point_index, direction, x, y);
 }
 
+/* Generates gidDDD if glyph has no name. */
+void
+hb_font_glyph_to_string (hb_font_t *font,
+                        hb_codepoint_t glyph,
+                        char *s, unsigned int size)
+{
+  font->glyph_to_string (glyph, s, size);
+}
+
+/* Parses gidDDD and uniUUUU strings automatically. */
+hb_bool_t
+hb_font_glyph_from_string (hb_font_t *font,
+                          const char *s, int len, /* -1 means nul-terminated */
+                          hb_codepoint_t *glyph)
+{
+  return font->glyph_from_string (s, len, glyph);
+}
+
 
 /*
  * hb_face_t
index ae4fc9b..0fde258 100644 (file)
@@ -346,6 +346,17 @@ hb_font_get_glyph_contour_point_for_origin (hb_font_t *font,
                                            hb_direction_t direction,
                                            hb_position_t *x, hb_position_t *y);
 
+/* Generates gidDDD if glyph has no name. */
+void
+hb_font_glyph_to_string (hb_font_t *font,
+                        hb_codepoint_t glyph,
+                        char *s, unsigned int size);
+/* Parses gidDDD and uniUUUU strings automatically. */
+hb_bool_t
+hb_font_glyph_from_string (hb_font_t *font,
+                          const char *s, int len, /* -1 means nul-terminated */
+                          hb_codepoint_t *glyph);
+
 
 /*
  * hb_font_t
index 0f1e5ce..8655020 100644 (file)
@@ -791,6 +791,22 @@ hb_bubble_sort (T *array, unsigned int len, int(*compar)(const T *, const T *))
   hb_bubble_sort (array, len, compar, (int *) NULL);
 }
 
+static inline hb_bool_t
+hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *out)
+{
+  /* Pain because we don't know whether s is nul-terminated. */
+  char buf[64];
+  strncpy (buf, s, MIN (ARRAY_LENGTH (buf) - 1, len));
+  buf[MIN (ARRAY_LENGTH (buf) - 1, len)] = '\0';
+
+  char *end;
+  errno = 0;
+  unsigned long v = strtoul (buf, &end, base);
+  if (errno) return false;
+  if (*end) return false;
+  *out = v;
+  return true;
+}
 
 
 #endif /* HB_PRIVATE_HH */
index bf64a29..95626ed 100644 (file)
@@ -88,7 +88,16 @@ main (int argc, char **argv)
   hb_blob_destroy (blob);
   blob = NULL;
 
+  hb_font_t *font = hb_font_create (face);
+#ifdef HAVE_FREETYPE
+  hb_ft_font_set_funcs (font);
+#endif
+
   unsigned int len = argc - 3;
-  hb_codepoint_t glyphs[2] = {strtol (argv[3], NULL, 0), argc > 4 ? strtol (argv[4], NULL, 0) : (hb_codepoint_t) -1};
+  hb_codepoint_t glyphs[2];
+  if (!hb_font_glyph_from_string (font, argv[3], -1, &glyphs[0]) ||
+      (argc > 4 &&
+       !hb_font_glyph_from_string (font, argv[4], -1, &glyphs[1])))
+    return 2;
   return !hb_ot_layout_would_substitute_lookup (face, glyphs, len, strtol (argv[2], NULL, 0));
 }
index d2a3846..c05cee6 100644 (file)
@@ -749,7 +749,7 @@ format_options_t::serialize_glyphs (hb_buffer_t *buffer,
 
     char glyph_name[128];
     if (show_glyph_names) {
-      hb_font_get_glyph_name (font, info->codepoint, glyph_name, sizeof (glyph_name));
+      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);