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

Behdad Esfahbod behdad at kemper.freedesktop.org
Sun Feb 18 19:36:17 UTC 2018


 configure.ac                   |    4 
 src/hb-buffer-private.hh       |    3 
 src/hb-coretext.cc             |    4 
 src/hb-directwrite.cc          |    2 
 src/hb-graphite2.cc            |    1 
 src/hb-ot-layout-gpos-table.hh |    2 
 src/hb-ot-map.cc               |    2 
 src/hb-private.hh              |  215 +++++++++++++++++++++++++++++++----------
 src/hb-set-private.hh          |   61 ++++-------
 src/hb-uniscribe.cc            |    2 
 test/api/hb-subset-test.h      |    4 
 test/api/hb-test.h             |    9 +
 12 files changed, 203 insertions(+), 106 deletions(-)

New commits:
commit 79d0d791b9ee920e1f687a93de5adf5d113cc829
Merge: 21646cc4 97a71102
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sun Feb 18 11:35:51 2018 -0800

    Merge pull request #800 from harfbuzz/bitops
    
    Optimize set through optimized bit operations

commit 97a71102153d28982297a190739c7d82e76b109e
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sun Feb 18 10:50:24 2018 -0800

    Fix BitScanForward() usage
    
    Should fix Win64 bot.

diff --git a/src/hb-private.hh b/src/hb-private.hh
index 583b5615..daa496e9 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -458,14 +458,14 @@ _hb_ctz (T v)
   {
     unsigned long where;
     _BitScanForward (&where, v);
-    return 1 + where;
+    return where;
   }
 # if _WIN64
   if (sizeof (T) <= 8)
   {
     unsigned long where;
     _BitScanForward64 (&where, v);
-    return 1 + where;
+    return where;
   }
 # endif
 #endif
commit fe8f40a4180e7b02831a264c0b3c66763156abb6
Merge: cd11107b 21646cc4
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sun Feb 18 10:45:33 2018 -0800

    Merge branch 'master' into bitops

commit 21646cc4a6160088933774e179df9be4865a9f4b
Author: David Corbett <corbett.dav at husky.neu.edu>
Date:   Fri Feb 16 12:08:55 2018 -0500

    Do not mark the first glyph as unsafe to break
    
    Fixes #791.

diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index a72376de..af4767f5 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -344,8 +344,7 @@ struct hb_buffer_t {
   inline void
   unsafe_to_break_all (void)
   {
-    for (unsigned int i = 0; i < len; i++)
-      info[i].mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
+    unsafe_to_break_impl (0, len);
   }
   inline void
   safe_to_break_all (void)
diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc
index 752dea8a..aba7cf44 100644
--- a/src/hb-coretext.cc
+++ b/src/hb-coretext.cc
@@ -1244,8 +1244,6 @@ resize_and_retry:
 	pos->x_offset = info->var1.i32;
 	pos->y_offset = info->var2.i32;
 
-	info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-
 	info++, pos++;
       }
     else
@@ -1255,8 +1253,6 @@ resize_and_retry:
 	pos->x_offset = info->var1.i32;
 	pos->y_offset = info->var2.i32;
 
-	info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
-
 	info++, pos++;
       }
 
diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc
index 5429255a..69a8aa20 100644
--- a/src/hb-directwrite.cc
+++ b/src/hb-directwrite.cc
@@ -878,8 +878,6 @@ retry_getglyphs:
     pos->x_offset =
       x_mult * (isRightToLeft ? -info->var1.i32 : info->var1.i32);
     pos->y_offset = y_mult * info->var2.i32;
-
-    info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
   }
 
   if (isRightToLeft)
diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc
index 3b55b475..46fe1399 100644
--- a/src/hb-graphite2.cc
+++ b/src/hb-graphite2.cc
@@ -360,7 +360,6 @@ _hb_graphite2_shape (hb_shape_plan_t    *shape_plan,
       hb_glyph_info_t *info = &buffer->info[clusters[i].base_glyph + j];
       info->codepoint = gids[clusters[i].base_glyph + j];
       info->cluster = clusters[i].cluster;
-      info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
       info->var1.i32 = clusters[i].advance;     // all glyphs in the cluster get the same advance
     }
   }
diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc
index 5e05baa8..cd25769d 100644
--- a/src/hb-uniscribe.cc
+++ b/src/hb-uniscribe.cc
@@ -1025,8 +1025,6 @@ retry:
     pos->x_advance = x_mult * (int32_t) info->mask;
     pos->x_offset = x_mult * (backward ? -info->var1.i32 : info->var1.i32);
     pos->y_offset = y_mult * info->var2.i32;
-
-    info->mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
   }
 
   if (backward)
commit cd11107bb44ac719709e10264e9e6ba6a1cfae0c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Feb 16 18:28:58 2018 -0800

    Another bitops fallback fix
    
    I'm confident that all bugs are hashed out now.

diff --git a/src/hb-private.hh b/src/hb-private.hh
index 8461f641..583b5615 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -474,7 +474,7 @@ _hb_ctz (T v)
   {
     /* "bithacks" */
     unsigned int c = 32;
-    v &= -signed(v);
+    v &= - (int32_t) v;
     if (v) c--;
     if (v & 0x0000FFFF) c -= 16;
     if (v & 0x00FF00FF) c -= 8;
@@ -487,7 +487,7 @@ _hb_ctz (T v)
   {
     /* "bithacks" */
     unsigned int c = 64;
-    v &= -signed(v);
+    v &= - (int64_t) (v);
     if (v) c--;
     if (v & 0x00000000FFFFFFFF) c -= 32;
     if (v & 0x0000FFFF0000FFFF) c -= 16;
commit 4e517ecb6b7c27d4053a6476bb9262858e2567ed
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Feb 16 18:20:12 2018 -0800

    Another bitops fallback impl fix

diff --git a/src/hb-private.hh b/src/hb-private.hh
index c9e5a5ca..8461f641 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -402,28 +402,28 @@ _hb_bit_storage (T v)
     /* "bithacks" */
     const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
     const unsigned int S[] = {1, 2, 4, 8, 16};
-    unsigned int r = 1;
+    unsigned int r = 0;
     for (int i = 4; i >= 0; i--)
       if (v & b[i])
       {
 	v >>= S[i];
 	r |= S[i];
       }
-    return r;
+    return r + 1;
   }
   if (sizeof (T) <= 8)
   {
     /* "bithacks" */
     const uint64_t b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000, 0xFFFFFFFF00000000};
     const unsigned int S[] = {1, 2, 4, 8, 16, 32};
-    unsigned int r = 1;
+    unsigned int r = 0;
     for (int i = 5; i >= 0; i--)
       if (v & b[i])
       {
 	v >>= S[i];
 	r |= S[i];
       }
-    return r;
+    return r + 1;
   }
   if (sizeof (T) == 16)
   {
commit f18b9fbf6583dff72675be7859fc147ec24a0dd2
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Feb 16 18:14:41 2018 -0800

    [set] Implement iteration using bitop intrinsics

diff --git a/src/hb-set-private.hh b/src/hb-set-private.hh
index 55a52919..49cd7912 100644
--- a/src/hb-set-private.hh
+++ b/src/hb-set-private.hh
@@ -109,21 +109,16 @@ struct hb_set_t
       unsigned int i = m / ELT_BITS;
       unsigned int j = m & ELT_MASK;
 
-      for (; j < ELT_BITS; j++)
-        if (v[i] & (elt_t (1) << j))
-	  goto found;
-      for (i++; i < len (); i++)
-        if (v[i])
-	  for (j = 0; j < ELT_BITS; j++)
-	    if (v[i] & (elt_t (1) << j))
-	      goto found;
+      const elt_t vv = v[i] & ~((elt_t (1) << j) - 1);
+      for (const elt_t *p = &vv; i < len (); p = &v[++i])
+	if (*p)
+	{
+	  *codepoint = i * ELT_BITS + elt_get_min (*p);
+	  return true;
+	}
 
       *codepoint = INVALID;
       return false;
-
-    found:
-      *codepoint = i * ELT_BITS + j;
-      return true;
     }
     inline bool previous (hb_codepoint_t *codepoint) const
     {
@@ -136,44 +131,29 @@ struct hb_set_t
       unsigned int i = m / ELT_BITS;
       unsigned int j = m & ELT_MASK;
 
-      for (; (int) j >= 0; j--)
-        if (v[i] & (elt_t (1) << j))
-	  goto found;
-      for (i--; (int) i >= 0; i--)
-        if (v[i])
-	  for (j = ELT_BITS - 1; (int) j >= 0; j--)
-	    if (v[i] & (elt_t (1) << j))
-	      goto found;
+      const elt_t vv = v[i] & ((elt_t (1) << (j + 1)) - 1);
+      for (const elt_t *p = &vv; (int) i >= 0; p = &v[--i])
+	if (*p)
+	{
+	  *codepoint = i * ELT_BITS + elt_get_max (*p);
+	  return true;
+	}
 
       *codepoint = INVALID;
       return false;
-
-    found:
-      *codepoint = i * ELT_BITS + j;
-      return true;
     }
     inline hb_codepoint_t get_min (void) const
     {
       for (unsigned int i = 0; i < len (); i++)
         if (v[i])
-	{
-	  elt_t e = v[i];
-	  for (unsigned int j = 0; j < ELT_BITS; j++)
-	    if (e & (elt_t (1) << j))
-	      return i * ELT_BITS + j;
-	}
+	  return i * ELT_BITS + elt_get_min (v[i]);
       return INVALID;
     }
     inline hb_codepoint_t get_max (void) const
     {
       for (int i = len () - 1; i >= 0; i--)
         if (v[i])
-	{
-	  elt_t e = v[i];
-	  for (int j = ELT_BITS - 1; j >= 0; j--)
-	    if (e & (elt_t (1) << j))
-	      return i * ELT_BITS + j;
-	}
+	  return i * ELT_BITS + elt_get_max (v[i]);
       return 0;
     }
 
@@ -181,6 +161,9 @@ struct hb_set_t
     static const unsigned int PAGE_BITS = 1024;
     static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
 
+    static inline unsigned int elt_get_min (const elt_t &elt) { return _hb_ctz (elt); }
+    static inline unsigned int elt_get_max (const elt_t &elt) { return _hb_bit_storage (elt) - 1; }
+
 #if 0 && HAVE_VECTOR_SIZE
     /* The vectorized version does not work with clang as non-const
      * elt() errs "non-const reference cannot bind to vector element". */
commit 6a91a2eb04951f6e33706c2b8e9cd987b429fce9
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Feb 16 17:49:41 2018 -0800

    Fix wide bitops implemenetation

diff --git a/src/hb-private.hh b/src/hb-private.hh
index a8bc5ed1..c9e5a5ca 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -374,10 +374,10 @@ _hb_bit_storage (T v)
     return sizeof (unsigned int) * 8 - __builtin_clz (v);
 
   if (sizeof (T) <= sizeof (unsigned long))
-    return sizeof (unsigned int) * 8 - __builtin_clzl (v);
+    return sizeof (unsigned long) * 8 - __builtin_clzl (v);
 
   if (sizeof (T) <= sizeof (unsigned long long))
-    return sizeof (unsigned int) * 8 - __builtin_clzll (v);
+    return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
 #endif
 
 #if defined(_MSC_VER) || defined(__MINGW32__)
commit d25c3e69e9b0cb9d947e98845b9e3a14ce58e350
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Feb 16 17:45:09 2018 -0800

    [set] Readjust parameters

diff --git a/src/hb-set-private.hh b/src/hb-set-private.hh
index 0c73d32d..55a52919 100644
--- a/src/hb-set-private.hh
+++ b/src/hb-set-private.hh
@@ -177,9 +177,8 @@ struct hb_set_t
       return 0;
     }
 
-    typedef uint32_t elt_t;
-    static const unsigned int ELT_BITS = sizeof (elt_t) * 8;
-    static const unsigned int PAGE_BITS = ELT_BITS * ELT_BITS; /* 1024. Use to tune. */
+    typedef unsigned long long elt_t;
+    static const unsigned int PAGE_BITS = 1024;
     static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
 
 #if 0 && HAVE_VECTOR_SIZE
@@ -192,6 +191,7 @@ struct hb_set_t
 
     vector_t v;
 
+    static const unsigned int ELT_BITS = sizeof (elt_t) * 8;
     static const unsigned int ELT_MASK = ELT_BITS - 1;
     static const unsigned int BITS = sizeof (vector_t) * 8;
     static const unsigned int MASK = BITS - 1;
commit 6d5c0bf8b18ed53e8d40dcbae83ec66ed2116843
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Feb 16 17:33:26 2018 -0800

    Fix bitops fallback impl

diff --git a/src/hb-private.hh b/src/hb-private.hh
index 7c2de152..a8bc5ed1 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -402,7 +402,7 @@ _hb_bit_storage (T v)
     /* "bithacks" */
     const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
     const unsigned int S[] = {1, 2, 4, 8, 16};
-    unsigned int r = 0;
+    unsigned int r = 1;
     for (int i = 4; i >= 0; i--)
       if (v & b[i])
       {
@@ -416,7 +416,7 @@ _hb_bit_storage (T v)
     /* "bithacks" */
     const uint64_t b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000, 0xFFFFFFFF00000000};
     const unsigned int S[] = {1, 2, 4, 8, 16, 32};
-    unsigned int r = 0;
+    unsigned int r = 1;
     for (int i = 5; i >= 0; i--)
       if (v & b[i])
       {
commit 82eb1dac163cb4aef8a2e4ebad542378f4e28dca
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Feb 16 16:52:09 2018 -0800

    Flesh out other bit ops some more for 128bit as well

diff --git a/src/hb-private.hh b/src/hb-private.hh
index d9cacbe0..7c2de152 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -322,102 +322,189 @@ static_assert ((sizeof (hb_var_int_t) == 4), "");
 typedef const struct _hb_void_t *hb_void_t;
 #define HB_VOID ((const _hb_void_t *) nullptr)
 
-/* Return the number of 1 bits in mask. */
+/* Return the number of 1 bits in v. */
 template <typename T>
 static inline HB_CONST_FUNC unsigned int
-_hb_popcount (T mask)
+_hb_popcount (T v)
 {
 #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && defined(__OPTIMIZE__)
-  if (sizeof (unsigned int) >= sizeof (mask))
-    return __builtin_popcount (mask);
+  if (sizeof (T) <= sizeof (unsigned int))
+    return __builtin_popcount (v);
 
-  if (sizeof (unsigned long) >= sizeof (mask))
-      return __builtin_popcountl (mask);
+  if (sizeof (T) <= sizeof (unsigned long))
+    return __builtin_popcountl (v);
 
-  if (sizeof (unsigned long long) >= sizeof (mask))
-      return __builtin_popcountll (mask);
+  if (sizeof (T) <= sizeof (unsigned long long))
+    return __builtin_popcountll (v);
 #endif
 
   if (sizeof (T) <= 4)
   {
     /* "HACKMEM 169" */
     uint32_t y;
-    y = (mask >> 1) &033333333333;
-    y = mask - y - ((y >>1) & 033333333333);
+    y = (v >> 1) &033333333333;
+    y = v - y - ((y >>1) & 033333333333);
     return (((y + (y >> 3)) & 030707070707) % 077);
   }
 
   if (sizeof (T) == 8)
   {
     unsigned int shift = 32;
-    return _hb_popcount<uint32_t> ((uint32_t) mask) + _hb_popcount ((uint32_t) (mask >> shift));
+    return _hb_popcount<uint32_t> ((uint32_t) v) + _hb_popcount ((uint32_t) (v >> shift));
   }
 
   if (sizeof (T) == 16)
   {
     unsigned int shift = 64;
-    return _hb_popcount<uint64_t> ((uint64_t) mask) + _hb_popcount ((uint64_t) (mask >> shift));
+    return _hb_popcount<uint64_t> ((uint64_t) v) + _hb_popcount ((uint64_t) (v >> shift));
   }
 
-  unsigned int count = 0;
-  while (mask)
-  {
-    count += _hb_popcount<uint64_t> ((uint64_t) mask);
-    unsigned int shift = 64;
-    mask = (T) (mask >> shift);
-  }
+  assert (0);
 }
 
 /* Returns the number of bits needed to store number */
+template <typename T>
 static inline HB_CONST_FUNC unsigned int
-_hb_bit_storage (unsigned int number)
+_hb_bit_storage (T v)
 {
-  if (unlikely (!number)) return 0;
+  if (unlikely (!v)) return 0;
 
 #if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
-  return sizeof (unsigned int) * 8 - __builtin_clz (number);
+  if (sizeof (T) <= sizeof (unsigned int))
+    return sizeof (unsigned int) * 8 - __builtin_clz (v);
+
+  if (sizeof (T) <= sizeof (unsigned long))
+    return sizeof (unsigned int) * 8 - __builtin_clzl (v);
+
+  if (sizeof (T) <= sizeof (unsigned long long))
+    return sizeof (unsigned int) * 8 - __builtin_clzll (v);
 #endif
 
 #if defined(_MSC_VER) || defined(__MINGW32__)
+  if (sizeof (T) <= sizeof (unsigned int))
   {
     unsigned long where;
-    _BitScanReverse (&where, number);
+    _BitScanReverse (&where, v);
     return 1 + where;
   }
+# if _WIN64
+  if (sizeof (T) <= 8)
+  {
+    unsigned long where;
+    _BitScanReverse64 (&where, v);
+    return 1 + where;
+  }
+# endif
 #endif
 
-  unsigned int n_bits = 0;
-  while (number) {
-    n_bits++;
-    number >>= 1;
+  if (sizeof (T) <= 4)
+  {
+    /* "bithacks" */
+    const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
+    const unsigned int S[] = {1, 2, 4, 8, 16};
+    unsigned int r = 0;
+    for (int i = 4; i >= 0; i--)
+      if (v & b[i])
+      {
+	v >>= S[i];
+	r |= S[i];
+      }
+    return r;
+  }
+  if (sizeof (T) <= 8)
+  {
+    /* "bithacks" */
+    const uint64_t b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000, 0xFFFFFFFF00000000};
+    const unsigned int S[] = {1, 2, 4, 8, 16, 32};
+    unsigned int r = 0;
+    for (int i = 5; i >= 0; i--)
+      if (v & b[i])
+      {
+	v >>= S[i];
+	r |= S[i];
+      }
+    return r;
+  }
+  if (sizeof (T) == 16)
+  {
+    unsigned int shift = 64;
+    return (v >> shift) ? _hb_bit_storage<uint64_t> ((uint64_t) v >> shift) + shift :
+			  _hb_bit_storage<uint64_t> ((uint64_t) v);
   }
-  return n_bits;
+
+  assert (0);
 }
 
-/* Returns the number of zero bits in the least significant side of number */
+/* Returns the number of zero bits in the least significant side of v */
+template <typename T>
 static inline HB_CONST_FUNC unsigned int
-_hb_ctz (unsigned int number)
+_hb_ctz (T v)
 {
-  if (unlikely (!number)) return 0;
+  if (unlikely (!v)) return 0;
 
 #if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
-  return __builtin_ctz (number);
+  if (sizeof (T) <= sizeof (unsigned int))
+    return __builtin_ctz (v);
+
+  if (sizeof (T) <= sizeof (unsigned long))
+    return __builtin_ctzl (v);
+
+  if (sizeof (T) <= sizeof (unsigned long long))
+    return __builtin_ctzll (v);
 #endif
 
 #if defined(_MSC_VER) || defined(__MINGW32__)
+  if (sizeof (T) <= sizeof (unsigned int))
+  {
+    unsigned long where;
+    _BitScanForward (&where, v);
+    return 1 + where;
+  }
+# if _WIN64
+  if (sizeof (T) <= 8)
   {
     unsigned long where;
-    _BitScanForward (&where, number);
-     return where;
+    _BitScanForward64 (&where, v);
+    return 1 + where;
   }
+# endif
 #endif
 
-  unsigned int n_bits = 0;
-  while (!(number & 1)) {
-    n_bits++;
-    number >>= 1;
+  if (sizeof (T) <= 4)
+  {
+    /* "bithacks" */
+    unsigned int c = 32;
+    v &= -signed(v);
+    if (v) c--;
+    if (v & 0x0000FFFF) c -= 16;
+    if (v & 0x00FF00FF) c -= 8;
+    if (v & 0x0F0F0F0F) c -= 4;
+    if (v & 0x33333333) c -= 2;
+    if (v & 0x55555555) c -= 1;
+    return c;
+  }
+  if (sizeof (T) <= 8)
+  {
+    /* "bithacks" */
+    unsigned int c = 64;
+    v &= -signed(v);
+    if (v) c--;
+    if (v & 0x00000000FFFFFFFF) c -= 32;
+    if (v & 0x0000FFFF0000FFFF) c -= 16;
+    if (v & 0x00FF00FF00FF00FF) c -= 8;
+    if (v & 0x0F0F0F0F0F0F0F0F) c -= 4;
+    if (v & 0x3333333333333333) c -= 2;
+    if (v & 0x5555555555555555) c -= 1;
+    return c;
   }
-  return n_bits;
+  if (sizeof (T) == 16)
+  {
+    unsigned int shift = 64;
+    return (uint64_t) v ? _hb_bit_storage<uint64_t> ((uint64_t) v) :
+			  _hb_bit_storage<uint64_t> ((uint64_t) v >> shift) + shift;
+  }
+
+  assert (0);
 }
 
 static inline bool
commit 864a2dddae9eb1303c59d0d3717fce307a72a524
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Feb 16 14:21:40 2018 -0800

    Clean up bit functions
    
    Compile all code-paths possible, to better catch errors.
    Also enable MSVC ones on mingw which seems to support them.

diff --git a/src/hb-private.hh b/src/hb-private.hh
index f4a31a69..d9cacbe0 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -51,7 +51,7 @@
 #include <stdio.h>
 #include <stdarg.h>
 
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) || defined(__MINGW32__)
 #include <intrin.h>
 #endif
 
@@ -372,41 +372,52 @@ _hb_popcount (T mask)
 static inline HB_CONST_FUNC unsigned int
 _hb_bit_storage (unsigned int number)
 {
+  if (unlikely (!number)) return 0;
+
 #if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
-  return likely (number) ? (sizeof (unsigned int) * 8 - __builtin_clz (number)) : 0;
-#elif defined(_MSC_VER)
-  unsigned long where;
-  if (_BitScanReverse (&where, number)) return 1 + where;
-  return 0;
-#else
+  return sizeof (unsigned int) * 8 - __builtin_clz (number);
+#endif
+
+#if defined(_MSC_VER) || defined(__MINGW32__)
+  {
+    unsigned long where;
+    _BitScanReverse (&where, number);
+    return 1 + where;
+  }
+#endif
+
   unsigned int n_bits = 0;
   while (number) {
     n_bits++;
     number >>= 1;
   }
   return n_bits;
-#endif
 }
 
 /* Returns the number of zero bits in the least significant side of number */
 static inline HB_CONST_FUNC unsigned int
 _hb_ctz (unsigned int number)
 {
+  if (unlikely (!number)) return 0;
+
 #if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__)
-  return likely (number) ? __builtin_ctz (number) : 0;
-#elif defined(_MSC_VER)
-  unsigned long where;
-  if (_BitScanForward (&where, number)) return where;
-  return 0;
-#else
+  return __builtin_ctz (number);
+#endif
+
+#if defined(_MSC_VER) || defined(__MINGW32__)
+  {
+    unsigned long where;
+    _BitScanForward (&where, number);
+     return where;
+  }
+#endif
+
   unsigned int n_bits = 0;
-  if (unlikely (!number)) return 0;
   while (!(number & 1)) {
     n_bits++;
     number >>= 1;
   }
   return n_bits;
-#endif
 }
 
 static inline bool
commit 978ace6fbbc828adc20f21591d138f41d8508ebc
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Feb 16 16:06:17 2018 -0800

    Improve _hb_popcount()
    
    Support 128bit type.

diff --git a/configure.ac b/configure.ac
index 7dbd553d..02a4a897 100644
--- a/configure.ac
+++ b/configure.ac
@@ -76,7 +76,8 @@ GTK_DOC_CHECK([1.15],[--flavour no-tmpl])
 	AM_CONDITIONAL([ENABLE_GTK_DOC], false)
 ])
 
-# Functions and headers
+# Types, functions, and headers
+AC_CHECK_TYPES(unsigned __int128)
 AC_CHECK_FUNCS(atexit mprotect sysconf getpagesize mmap isatty newlocale strtod_l setlinebuf)
 AC_CHECK_HEADERS(unistd.h sys/mman.h xlocale.h)
 
diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index 14ee3713..5b1bc6ab 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -99,7 +99,7 @@ struct ValueFormat : HBUINT16
 #endif
 
   inline unsigned int get_len (void) const
-  { return _hb_popcount32 ((unsigned int) *this); }
+  { return _hb_popcount ((unsigned int) *this); }
   inline unsigned int get_size (void) const
   { return get_len () * Value::static_size; }
 
diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc
index 6f07a7e2..54b0ce37 100644
--- a/src/hb-ot-map.cc
+++ b/src/hb-ot-map.cc
@@ -139,7 +139,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t  &m,
 {
   static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), "");
   unsigned int global_bit_mask = HB_GLYPH_FLAG_DEFINED + 1;
-  unsigned int global_bit_shift = _hb_popcount32 (HB_GLYPH_FLAG_DEFINED);
+  unsigned int global_bit_shift = _hb_popcount (HB_GLYPH_FLAG_DEFINED);
 
   m.global_mask = global_bit_mask;
 
diff --git a/src/hb-private.hh b/src/hb-private.hh
index aeed58ae..f4a31a69 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -323,31 +323,50 @@ typedef const struct _hb_void_t *hb_void_t;
 #define HB_VOID ((const _hb_void_t *) nullptr)
 
 /* Return the number of 1 bits in mask. */
+template <typename T>
 static inline HB_CONST_FUNC unsigned int
-_hb_popcount32 (uint32_t mask)
+_hb_popcount (T mask)
 {
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
-  return __builtin_popcount (mask);
-#else
-  /* "HACKMEM 169" */
-  uint32_t y;
-  y = (mask >> 1) &033333333333;
-  y = mask - y - ((y >>1) & 033333333333);
-  return (((y + (y >> 3)) & 030707070707) % 077);
-#endif
-}
-static inline HB_CONST_FUNC unsigned int
-_hb_popcount64 (uint64_t mask)
-{
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
-  if (sizeof (long) >= sizeof (mask))
-    return __builtin_popcountl (mask);
+#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) && defined(__OPTIMIZE__)
+  if (sizeof (unsigned int) >= sizeof (mask))
+    return __builtin_popcount (mask);
+
+  if (sizeof (unsigned long) >= sizeof (mask))
+      return __builtin_popcountl (mask);
+
+  if (sizeof (unsigned long long) >= sizeof (mask))
+      return __builtin_popcountll (mask);
 #endif
-  return _hb_popcount32 (mask & 0xFFFFFFFF) + _hb_popcount32 (mask >> 32);
+
+  if (sizeof (T) <= 4)
+  {
+    /* "HACKMEM 169" */
+    uint32_t y;
+    y = (mask >> 1) &033333333333;
+    y = mask - y - ((y >>1) & 033333333333);
+    return (((y + (y >> 3)) & 030707070707) % 077);
+  }
+
+  if (sizeof (T) == 8)
+  {
+    unsigned int shift = 32;
+    return _hb_popcount<uint32_t> ((uint32_t) mask) + _hb_popcount ((uint32_t) (mask >> shift));
+  }
+
+  if (sizeof (T) == 16)
+  {
+    unsigned int shift = 64;
+    return _hb_popcount<uint64_t> ((uint64_t) mask) + _hb_popcount ((uint64_t) (mask >> shift));
+  }
+
+  unsigned int count = 0;
+  while (mask)
+  {
+    count += _hb_popcount<uint64_t> ((uint64_t) mask);
+    unsigned int shift = 64;
+    mask = (T) (mask >> shift);
+  }
 }
-template <typename T> static inline unsigned int _hb_popcount (T mask);
-template <> inline unsigned int _hb_popcount<uint32_t> (uint32_t mask) { return _hb_popcount32 (mask); }
-template <> inline unsigned int _hb_popcount<uint64_t> (uint64_t mask) { return _hb_popcount64 (mask); }
 
 /* Returns the number of bits needed to store number */
 static inline HB_CONST_FUNC unsigned int
commit 7b5ce7404716a17f91ff86d374c7b76ee7ce3247
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Feb 16 15:37:22 2018 -0800

    Fix warnings

diff --git a/src/hb-ot-os2-table.hh b/src/hb-ot-os2-table.hh
index 18dc4ab0..5f4e2db0 100644
--- a/src/hb-ot-os2-table.hh
+++ b/src/hb-ot-os2-table.hh
@@ -78,7 +78,7 @@ struct os2
   {
     hb_codepoint_t min = -1, max = 0;
 
-    for (int i = 0; i < codepoints.len; i++)
+    for (unsigned int i = 0; i < codepoints.len; i++)
     {
       hb_codepoint_t cp = codepoints[i];
       if (cp < min)
diff --git a/test/api/hb-subset-test.h b/test/api/hb-subset-test.h
index 12d402d3..49e5db48 100644
--- a/test/api/hb-subset-test.h
+++ b/test/api/hb-subset-test.h
@@ -86,6 +86,7 @@ hb_subset_test_open_font (const char *font_path)
     return face;
   }
   g_assert (false);
+  return NULL; /* Shut up, compiler! */
 }
 
 static inline hb_face_t *
@@ -114,7 +115,7 @@ hb_subset_test_check (hb_face_t *expected,
 {
   hb_blob_t *expected_blob = hb_face_reference_table (expected, table);
   hb_blob_t *actual_blob = hb_face_reference_table (actual, table);
-  hb_test_assert_blob_eq(expected_blob, actual_blob);  
+  hb_test_assert_blobs_equal (expected_blob, actual_blob);
   hb_blob_destroy (expected_blob);
   hb_blob_destroy (actual_blob);
 }
diff --git a/test/api/hb-test.h b/test/api/hb-test.h
index 48ccc3b2..a88b00c4 100644
--- a/test/api/hb-test.h
+++ b/test/api/hb-test.h
@@ -160,8 +160,14 @@ typedef void (*hb_test_fixture_func_t) (void);
 #if !GLIB_CHECK_VERSION(2,30,0)
 #define g_test_fail() g_error("Test failed")
 #endif
+#ifndef g_assert_true
+#define g_assert_true g_assert
+#endif
+#ifndef g_assert_cmpmem
+#define g_assert_cmpmem(m1, l1, m2, l2) g_assert_true (l1 == l2 && memcmp (m1, m2, l1) == 0)
+#endif
 
-static inline void hb_test_assert_blob_eq(hb_blob_t *expected_blob, hb_blob_t *actual_blob)
+static inline void hb_test_assert_blobs_equal (hb_blob_t *expected_blob, hb_blob_t *actual_blob)
 {
   unsigned int expected_length, actual_length;
   const char *raw_expected = hb_blob_get_data (expected_blob, &expected_length);
@@ -170,7 +176,6 @@ static inline void hb_test_assert_blob_eq(hb_blob_t *expected_blob, hb_blob_t *a
   g_assert_cmpint(0, ==, memcmp(raw_expected, raw_actual, expected_length));
 }
 
-
 static inline void
 hb_test_add_func (const char *test_path,
 		  hb_test_func_t   test_func)
commit 94d32d1b83892ed4f124463cf4322bf74b3e850d
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Feb 16 15:36:20 2018 -0800

    Enable C99 if available
    
    Hopefully we can now mix-and-match code and declaration in the C test files.

diff --git a/configure.ac b/configure.ac
index d8c38fe2..7dbd553d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,6 +20,7 @@ LT_INIT([disable-static])
 # Check for programs
 AC_USE_SYSTEM_EXTENSIONS
 AC_PROG_CC
+AC_PROG_CC_C99
 AM_PROG_CC_C_O
 AC_PROG_CXX
 dnl AX_CXX_COMPILE_STDCXX(11, noext, optional)


More information about the HarfBuzz mailing list