[ot-font] Accelerate cmap format4 get_glyph
authorBehdad Esfahbod <behdad@behdad.org>
Wed, 24 Feb 2016 11:27:13 +0000 (20:27 +0900)
committerBehdad Esfahbod <behdad@behdad.org>
Wed, 24 Feb 2016 11:27:13 +0000 (20:27 +0900)
src/hb-ot-cmap-table.hh
src/hb-ot-font.cc

index 886d348..d7a94a1 100644 (file)
@@ -69,61 +69,78 @@ struct CmapSubtableFormat0
 
 struct CmapSubtableFormat4
 {
-  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  struct accelerator_t
   {
-    unsigned int segCount;
-    const USHORT *endCount;
-    const USHORT *startCount;
-    const USHORT *idDelta;
-    const USHORT *idRangeOffset;
-    const USHORT *glyphIdArray;
-    unsigned int glyphIdArrayLength;
+    inline void init (const CmapSubtableFormat4 *subtable)
+    {
+      segCount = subtable->segCountX2 / 2;
+      endCount = subtable->values;
+      startCount = endCount + segCount + 1;
+      idDelta = startCount + segCount;
+      idRangeOffset = idDelta + segCount;
+      glyphIdArray = idRangeOffset + segCount;
+      glyphIdArrayLength = (subtable->length - 16 - 8 * segCount) / 2;
+    }
 
-    segCount = this->segCountX2 / 2;
-    endCount = this->values;
-    startCount = endCount + segCount + 1;
-    idDelta = startCount + segCount;
-    idRangeOffset = idDelta + segCount;
-    glyphIdArray = idRangeOffset + segCount;
-    glyphIdArrayLength = (this->length - 16 - 8 * segCount) / 2;
-
-    /* Custom two-array bsearch. */
-    int min = 0, max = (int) segCount - 1;
-    unsigned int i;
-    while (min <= max)
+    static inline bool get_glyph_func (const void *obj, hb_codepoint_t codepoint, hb_codepoint_t *glyph)
     {
-      int mid = (min + max) / 2;
-      if (codepoint < startCount[mid])
-        max = mid - 1;
-      else if (codepoint > endCount[mid])
-        min = mid + 1;
+      const accelerator_t *thiz = (const accelerator_t *) obj;
+
+      /* Custom two-array bsearch. */
+      int min = 0, max = (int) thiz->segCount - 1;
+      const USHORT *startCount = thiz->startCount;
+      const USHORT *endCount = thiz->endCount;
+      unsigned int i;
+      while (min <= max)
+      {
+       int mid = (min + max) / 2;
+       if (codepoint < startCount[mid])
+         max = mid - 1;
+       else if (codepoint > endCount[mid])
+         min = mid + 1;
+       else
+       {
+         i = mid;
+         goto found;
+       }
+      }
+      return false;
+
+    found:
+      hb_codepoint_t gid;
+      unsigned int rangeOffset = thiz->idRangeOffset[i];
+      if (rangeOffset == 0)
+       gid = codepoint + thiz->idDelta[i];
       else
       {
-       i = mid;
-       goto found;
+       /* Somebody has been smoking... */
+       unsigned int index = rangeOffset / 2 + (codepoint - thiz->startCount[i]) + i - thiz->segCount;
+       if (unlikely (index >= thiz->glyphIdArrayLength))
+         return false;
+       gid = thiz->glyphIdArray[index];
+       if (unlikely (!gid))
+         return false;
+       gid += thiz->idDelta[i];
       }
-    }
-    return false;
-
-  found:
-    hb_codepoint_t gid;
-    unsigned int rangeOffset = idRangeOffset[i];
-    if (rangeOffset == 0)
-      gid = codepoint + idDelta[i];
-    else
-    {
-      /* Somebody has been smoking... */
-      unsigned int index = rangeOffset / 2 + (codepoint - startCount[i]) + i - segCount;
-      if (unlikely (index >= glyphIdArrayLength))
-       return false;
-      gid = glyphIdArray[index];
-      if (unlikely (!gid))
-       return false;
-      gid += idDelta[i];
+
+      *glyph = gid & 0xFFFFu;
+      return true;
     }
 
-    *glyph = gid & 0xFFFFu;
-    return true;
+    const USHORT *endCount;
+    const USHORT *startCount;
+    const USHORT *idDelta;
+    const USHORT *idRangeOffset;
+    const USHORT *glyphIdArray;
+    unsigned int segCount;
+    unsigned int glyphIdArrayLength;
+  };
+
+  inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
+  {
+    accelerator_t accel;
+    accel.init (this);
+    return accel.get_glyph_func (&accel, codepoint, glyph);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
index e7dbcff..61c7036 100644 (file)
@@ -218,6 +218,7 @@ struct hb_ot_face_cmap_accelerator_t
 {
   hb_cmap_get_glyph_func_t get_glyph_func;
   const void *get_glyph_data;
+  OT::CmapSubtableFormat4::accelerator_t format4_accel;
 
   const OT::CmapSubtableFormat14 *uvs_table;
   hb_blob_t *blob;
@@ -255,8 +256,19 @@ struct hb_ot_face_cmap_accelerator_t
 
     this->uvs_table = subtable_uvs;
 
-    this->get_glyph_func = get_glyph_from<OT::CmapSubtable>;
     this->get_glyph_data = subtable;
+    switch (subtable->u.format) {
+    /* Accelerate format 4 and format 12. */
+    default: this->get_glyph_func = get_glyph_from<OT::CmapSubtable>;          break;
+    case 12: this->get_glyph_func = get_glyph_from<OT::CmapSubtableFormat12>;  break;
+    case  4:
+      {
+        this->format4_accel.init (&subtable->u.format4);
+       this->get_glyph_data = &this->format4_accel;
+        this->get_glyph_func = this->format4_accel.get_glyph_func;
+      }
+      break;
+    }
   }
 
   inline void fini (void)