Commit 4a32dce92a0ff00d824b3ec512b8f6dff28dcaa2

Werner Lemberg 2017-03-14T19:32:12

[sfnt] Implement PS names for font instances [1/3]. Add 128bit MurmurHash 3 function. Everything is guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT. * src/sfnt/sfdriver.c (ROTL32): New macro. (fmix32, murmur_hash_3_128): New functions.

diff --git a/ChangeLog b/ChangeLog
index 091724f..181ade9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2017-03-14  Werner Lemberg  <wl@gnu.org>
+
+	[sfnt] Implement PS names for font instances [1/3].
+
+	Add 128bit MurmurHash 3 function.
+
+	Everything is guarded with TT_CONFIG_OPTION_GX_VAR_SUPPORT.
+
+	* src/sfnt/sfdriver.c (ROTL32): New macro.
+	(fmix32, murmur_hash_3_128): New functions.
+
 2017-03-13  Werner Lemberg  <wl@gnu.org>
 
 	[truetype] Ignore invalid MVAR tags.
diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c
index f132669..455c490 100644
--- a/src/sfnt/sfdriver.c
+++ b/src/sfnt/sfdriver.c
@@ -250,6 +250,195 @@
   }
 
 
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
+  /* the implementation of MurmurHash3 is taken and adapted from          */
+  /* https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp */
+
+#define ROTL32( x, r )  ( x << r ) | ( x >> ( 32 - r ) )
+
+
+  FT_UInt32
+  fmix32( FT_UInt32  h )
+  {
+    h ^= h >> 16;
+    h *= 0x85ebca6b;
+    h ^= h >> 13;
+    h *= 0xc2b2ae35;
+    h ^= h >> 16;
+
+    return h;
+  }
+
+
+  void
+  murmur_hash_3_128( const void*  key,
+                     const int    len,
+                     FT_UInt32    seed,
+                     void*        out )
+  {
+    const FT_Byte*  data    = (const FT_Byte*)key;
+    const int       nblocks = len / 16;
+
+    FT_UInt32  h1 = seed;
+    FT_UInt32  h2 = seed;
+    FT_UInt32  h3 = seed;
+    FT_UInt32  h4 = seed;
+
+    const FT_UInt32  c1 = 0x239b961b;
+    const FT_UInt32  c2 = 0xab0e9789;
+    const FT_UInt32  c3 = 0x38b34ae5;
+    const FT_UInt32  c4 = 0xa1e38b93;
+
+    const FT_UInt32*  blocks = (const FT_UInt32*)( data + nblocks * 16 );
+
+    int  i;
+
+
+    for( i = -nblocks; i; i++ )
+    {
+      FT_UInt32  k1 = blocks[i * 4 + 0];
+      FT_UInt32  k2 = blocks[i * 4 + 1];
+      FT_UInt32  k3 = blocks[i * 4 + 2];
+      FT_UInt32  k4 = blocks[i * 4 + 3];
+
+
+      k1 *= c1;
+      k1  = ROTL32( k1, 15 );
+      k1 *= c2;
+      h1 ^= k1;
+
+      h1  = ROTL32( h1, 19 );
+      h1 += h2;
+      h1  = h1 * 5 + 0x561ccd1b;
+
+      k2 *= c2;
+      k2  = ROTL32( k2, 16 );
+      k2 *= c3;
+      h2 ^= k2;
+
+      h2  = ROTL32( h2, 17 );
+      h2 += h3;
+      h2  = h2 * 5 + 0x0bcaa747;
+
+      k3 *= c3;
+      k3  = ROTL32( k3, 17 );
+      k3 *= c4;
+      h3 ^= k3;
+
+      h3  = ROTL32( h3, 15 );
+      h3 += h4;
+      h3  = h3 * 5 + 0x96cd1c35;
+
+      k4 *= c4;
+      k4  = ROTL32( k4, 18 );
+      k4 *= c1;
+      h4 ^= k4;
+
+      h4  = ROTL32( h4, 13 );
+      h4 += h1;
+      h4  = h4 * 5 + 0x32ac3b17;
+    }
+
+    {
+      const FT_Byte*  tail = (const FT_Byte*)( data + nblocks * 16 );
+
+      FT_UInt32  k1 = 0;
+      FT_UInt32  k2 = 0;
+      FT_UInt32  k3 = 0;
+      FT_UInt32  k4 = 0;
+
+
+      switch ( len & 15 )
+      {
+      case 15:
+        k4 ^= tail[14] << 16;
+      case 14:
+        k4 ^= tail[13] << 8;
+      case 13:
+        k4 ^= tail[12] << 0;
+        k4 *= c4;
+        k4  = ROTL32( k4, 18 );
+        k4 *= c1;
+        h4 ^= k4;
+
+      case 12:
+        k3 ^= tail[11] << 24;
+      case 11:
+        k3 ^= tail[10] << 16;
+      case 10:
+        k3 ^= tail[9] << 8;
+      case 9:
+        k3 ^= tail[8] << 0;
+        k3 *= c3;
+        k3  = ROTL32( k3, 17 );
+        k3 *= c4;
+        h3 ^= k3;
+
+      case 8:
+        k2 ^= tail[7] << 24;
+      case 7:
+        k2 ^= tail[6] << 16;
+      case 6:
+        k2 ^= tail[5] << 8;
+      case 5:
+        k2 ^= tail[4] << 0;
+        k2 *= c2;
+        k2  = ROTL32( k2, 16 );
+        k2 *= c3;
+        h2 ^= k2;
+
+      case 4:
+        k1 ^= tail[3] << 24;
+      case 3:
+        k1 ^= tail[2] << 16;
+      case 2:
+        k1 ^= tail[1] << 8;
+      case 1:
+        k1 ^= tail[0] << 0;
+        k1 *= c1;
+        k1  = ROTL32( k1, 15 );
+        k1 *= c2;
+        h1 ^= k1;
+      }
+    }
+
+    h1 ^= len;
+    h2 ^= len;
+    h3 ^= len;
+    h4 ^= len;
+
+    h1 += h2;
+    h1 += h3;
+    h1 += h4;
+
+    h2 += h1;
+    h3 += h1;
+    h4 += h1;
+
+    h1 = fmix32( h1 );
+    h2 = fmix32( h2 );
+    h3 = fmix32( h3 );
+    h4 = fmix32( h4 );
+
+    h1 += h2;
+    h1 += h3;
+    h1 += h4;
+
+    h2 += h1;
+    h3 += h1;
+    h4 += h1;
+
+    ((FT_UInt32*)out)[0] = h1;
+    ((FT_UInt32*)out)[1] = h2;
+    ((FT_UInt32*)out)[2] = h3;
+    ((FT_UInt32*)out)[3] = h4;
+  }
+
+
+#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
+
+
   typedef int (*char_type_func)( int  c );