[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