[post] Implement glyph_from_name()
authorBehdad Esfahbod <behdad@behdad.org>
Mon, 30 Oct 2017 19:15:05 +0000 (13:15 -0600)
committerBehdad Esfahbod <behdad@behdad.org>
Mon, 30 Oct 2017 19:15:05 +0000 (13:15 -0600)
This concludes https://github.com/behdad/harfbuzz/pull/568

src/hb-ot-post-table.hh
src/hb-private.hh
src/hb-sort-r.hh

index 7e164cb..580a6a9 100644 (file)
@@ -108,9 +108,97 @@ struct post
     inline void fini (void)
     {
       index_to_offset.finish ();
+      free (gids_sorted_by_name);
     }
 
-    inline hb_string_t _find_glyph_name (hb_codepoint_t glyph) const
+    inline bool get_glyph_name (hb_codepoint_t glyph,
+                               char *buf, unsigned int buf_len) const
+    {
+      hb_string_t s = find_glyph_name (glyph);
+      if (!s.len)
+        return false;
+      if (!buf_len)
+       return true;
+      if (buf_len <= s.len) /* What to do with truncation? Returning false for now. */
+        return false;
+      strncpy (buf, s.bytes, s.len);
+      buf[s.len] = '\0';
+      return true;
+    }
+
+    inline bool get_glyph_from_name (const char *name, int len,
+                                    hb_codepoint_t *glyph) const
+    {
+      unsigned int count = get_glyph_count ();
+      if (unlikely (!count))
+        return false;
+
+      if (len < 0)
+       len = strlen (name);
+
+      if (unlikely (!len))
+       return false;
+
+    retry:
+      uint16_t *gids = (uint16_t *) hb_atomic_ptr_get (&gids_sorted_by_name);
+
+      if (unlikely (!gids))
+      {
+       gids = (uint16_t *) malloc (count * sizeof (gids[0]));
+       if (unlikely (!gids))
+         return false; /* Anything better?! */
+
+       for (unsigned int i = 0; i < count; i++)
+         gids[i] = i;
+       hb_sort_r (gids, count, sizeof (gids[0]), cmp_gids, (void *) this);
+
+       if (!hb_atomic_ptr_cmpexch (&gids_sorted_by_name, nullptr, gids)) {
+         free (gids);
+         goto retry;
+       }
+      }
+
+      hb_string_t st (name, len);
+      const uint16_t *gid = (const uint16_t *) hb_bsearch_r (&st, gids, count, sizeof (gids[0]), cmp_key, (void *) this);
+      if (gid)
+      {
+       *glyph = *gid;
+       return true;
+      }
+
+      return false;
+    }
+
+    protected:
+
+    inline unsigned int get_glyph_count (void) const
+    {
+      if (version == 0x00010000)
+        return NUM_FORMAT1_NAMES;
+
+      if (version == 0x00020000)
+        return glyphNameIndex->len;
+
+      return 0;
+    }
+
+    static inline int cmp_gids (const void *pa, const void *pb, void *arg)
+    {
+      const accelerator_t *thiz = (const accelerator_t *) arg;
+      uint16_t a = * (const uint16_t *) pa;
+      uint16_t b = * (const uint16_t *) pb;
+      return thiz->find_glyph_name (b).cmp (thiz->find_glyph_name (a));
+    }
+
+    static inline int cmp_key (const void *pk, const void *po, void *arg)
+    {
+      const accelerator_t *thiz = (const accelerator_t *) arg;
+      const hb_string_t *key = (const hb_string_t *) pk;
+      uint16_t o = * (const uint16_t *) po;
+      return thiz->find_glyph_name (o).cmp (*key);
+    }
+
+    inline hb_string_t find_glyph_name (hb_codepoint_t glyph) const
     {
       if (version == 0x00010000)
       {
@@ -139,38 +227,11 @@ struct post
       return hb_string_t ((const char *) data, name_length);
     }
 
-    inline bool get_glyph_name (hb_codepoint_t glyph,
-                               char *buf, unsigned int buf_len) const
-    {
-      hb_string_t s = _find_glyph_name (glyph);
-      if (!s.len)
-        return false;
-      if (!buf_len)
-       return true;
-      if (buf_len <= s.len) /* What to do with truncation? Returning false for now. */
-        return false;
-      strncpy (buf, s.bytes, s.len);
-      buf[s.len] = '\0';
-      return true;
-    }
-
-    inline bool get_glyph_from_name (const char *name, int len,
-                                    hb_codepoint_t *glyph) const
-    {
-      if (len < 0)
-       len = strlen (name);
-
-      if (unlikely (!len))
-        return false;
-
-      /* TODO format2 */
-      return false;
-    }
-
     uint32_t version;
     const ArrayOf<USHORT> *glyphNameIndex;
     hb_prealloced_array_t<uint32_t, 1> index_to_offset;
     const uint8_t *pool;
+    mutable uint16_t *gids_sorted_by_name;
   };
 
   public:
index b88de08..6f2106e 100644 (file)
@@ -1145,18 +1145,18 @@ struct hb_string_t
   inline hb_string_t (void) : bytes (nullptr), len (0) {}
   inline hb_string_t (const char *bytes_, unsigned int len_) : bytes (bytes_), len (len_) {}
 
-  inline int cmp (const hb_string_t *a) const
+  inline int cmp (const hb_string_t &a) const
   {
-    if (len != a->len)
-      return (int) a->len - (int) len;
+    if (len != a.len)
+      return (int) a.len - (int) len;
 
-    return memcmp (a->bytes, bytes, len);
+    return memcmp (a.bytes, bytes, len);
   }
   static inline int cmp (const void *pa, const void *pb)
   {
     hb_string_t *a = (hb_string_t *) pa;
     hb_string_t *b = (hb_string_t *) pb;
-    return b->cmp (a);
+    return b->cmp (*a);
   }
 
   const char *bytes;
index 371a12b..7458b4b 100644 (file)
@@ -33,7 +33,7 @@
 static inline void *
 hb_bsearch_r(const void *key, const void *base,
             size_t nmemb, size_t size,
-            int (*compar)(const void *_a, const void *_b, const void *_arg),
+            int (*compar)(const void *_key, const void *_item, void *_arg),
             void *arg)
 {
   int min = 0, max = (int) nmemb - 1;