[HarfBuzz] harfbuzz-ng: Branch 'master' - 22 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Wed Apr 21 01:52:20 PDT 2010


 src/hb-blob.c                        |    6 -
 src/hb-open-file-private.hh          |    7 -
 src/hb-open-type-private.hh          |  153 +++++++++++++------------
 src/hb-ot-layout-common-private.hh   |   28 +++-
 src/hb-ot-layout-gdef-private.hh     |    2 
 src/hb-ot-layout-gpos-private.hh     |  206 +++++++++++++++++++++++++----------
 src/hb-ot-layout-gsub-private.hh     |    4 
 src/hb-ot-layout-gsubgpos-private.hh |   51 ++++----
 src/hb-private.h                     |  125 +++++++++------------
 9 files changed, 339 insertions(+), 243 deletions(-)

New commits:
commit 1922ffe7013c46014803a9f18c42e193a25b1968
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 21 04:19:51 2010 -0400

    Const correctness

diff --git a/src/hb-ot-layout-gsub-private.hh b/src/hb-ot-layout-gsub-private.hh
index d0cec7b..d979749 100644
--- a/src/hb-ot-layout-gsub-private.hh
+++ b/src/hb-ot-layout-gsub-private.hh
@@ -591,10 +591,10 @@ struct ReverseChainSingleSubstFormat1
 
     if (match_backtrack (APPLY_ARG,
 			 backtrack.len, (USHORT *) backtrack.const_array(),
-			 match_coverage, DECONST_CHARP(this)) &&
+			 match_coverage, CONST_CHARP(this)) &&
         match_lookahead (APPLY_ARG,
 			 lookahead.len, (USHORT *) lookahead.const_array(),
-			 match_coverage, DECONST_CHARP(this),
+			 match_coverage, CONST_CHARP(this),
 			 1))
     {
       IN_CURGLYPH () = substitute[index];
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index ee9db67..c006191 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -81,7 +81,7 @@
 	TRACE_APPLY_ARG_INIT
 
 
-typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, char *data);
+typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const USHORT &value, const char *data);
 typedef bool (*apply_lookup_func_t) (APPLY_ARG_DEF, unsigned int lookup_index);
 
 struct ContextFuncs
@@ -91,18 +91,18 @@ struct ContextFuncs
 };
 
 
-static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, char *data HB_GNUC_UNUSED)
+static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, const char *data HB_GNUC_UNUSED)
 {
   return glyph_id == value;
 }
 
-static inline bool match_class (hb_codepoint_t glyph_id, const USHORT &value, char *data)
+static inline bool match_class (hb_codepoint_t glyph_id, const USHORT &value, const char *data)
 {
   const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
   return class_def.get_class (glyph_id) == value;
 }
 
-static inline bool match_coverage (hb_codepoint_t glyph_id, const USHORT &value, char *data)
+static inline bool match_coverage (hb_codepoint_t glyph_id, const USHORT &value, const char *data)
 {
   const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
   return (data+coverage) (glyph_id) != NOT_COVERED;
@@ -113,7 +113,7 @@ static inline bool match_input (APPLY_ARG_DEF,
 				unsigned int count, /* Including the first glyph (not matched) */
 				const USHORT input[], /* Array of input values--start with second glyph */
 				match_func_t match_func,
-				char *match_data,
+				const char *match_data,
 				unsigned int *context_length_out)
 {
   unsigned int i, j;
@@ -143,7 +143,7 @@ static inline bool match_backtrack (APPLY_ARG_DEF,
 				    unsigned int count,
 				    const USHORT backtrack[],
 				    match_func_t match_func,
-				    char *match_data)
+				    const char *match_data)
 {
   if (HB_UNLIKELY (buffer->out_pos < count))
     return false;
@@ -168,7 +168,7 @@ static inline bool match_lookahead (APPLY_ARG_DEF,
 				    unsigned int count,
 				    const USHORT lookahead[],
 				    match_func_t match_func,
-				    char *match_data,
+				    const char *match_data,
 				    unsigned int offset)
 {
   unsigned int i, j;
@@ -271,7 +271,7 @@ static inline bool apply_lookup (APPLY_ARG_DEF,
 struct ContextLookupContext
 {
   ContextFuncs funcs;
-  char *match_data;
+  const char *match_data;
 };
 
 static inline bool context_lookup (APPLY_ARG_DEF,
@@ -411,7 +411,7 @@ struct ContextFormat2
      */
     struct ContextLookupContext lookup_context = {
      {match_class, apply_func},
-      DECONST_CHARP(&class_def)
+      CONST_CHARP(&class_def)
     };
     return rule_set.apply (APPLY_ARG, lookup_context);
   }
@@ -451,7 +451,7 @@ struct ContextFormat3
     const LookupRecord *lookupRecord = &CONST_CAST(LookupRecord, coverage, coverage[0].get_size () * glyphCount);
     struct ContextLookupContext lookup_context = {
       {match_coverage, apply_func},
-      DECONST_CHARP(this)
+       CONST_CHARP(this)
     };
     return context_lookup (APPLY_ARG,
 			   glyphCount, (const USHORT *) (coverage + 1),
@@ -522,7 +522,7 @@ struct Context
 struct ChainContextLookupContext
 {
   ContextFuncs funcs;
-  char *match_data[3];
+  const char *match_data[3];
 };
 
 static inline bool chain_context_lookup (APPLY_ARG_DEF,
@@ -696,9 +696,9 @@ struct ChainContextFormat2
      */
     struct ChainContextLookupContext lookup_context = {
      {match_class, apply_func},
-     {DECONST_CHARP(&backtrack_class_def),
-      DECONST_CHARP(&input_class_def),
-      DECONST_CHARP(&lookahead_class_def)}
+     {CONST_CHARP(&backtrack_class_def),
+      CONST_CHARP(&input_class_def),
+      CONST_CHARP(&lookahead_class_def)}
     };
     return rule_set.apply (APPLY_ARG, lookup_context);
   }
@@ -752,7 +752,7 @@ struct ChainContextFormat3
     const ArrayOf<LookupRecord> &lookup = CONST_NEXT (ArrayOf<LookupRecord>, lookahead);
     struct ChainContextLookupContext lookup_context = {
       {match_coverage, apply_func},
-      {DECONST_CHARP(this), DECONST_CHARP(this), DECONST_CHARP(this)}
+      {CONST_CHARP(this), CONST_CHARP(this), CONST_CHARP(this)}
     };
     return chain_context_lookup (APPLY_ARG,
 				 backtrack.len, (const USHORT *) backtrack.const_array(),
commit e032ed9f75d4a0f365649a25706871bbb5ae6651
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 21 03:11:46 2010 -0400

    Use templates for defining int typess

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index ec65ba2..94d5b5e 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -338,29 +338,51 @@ struct Sanitizer
  * Int types
  */
 
-#define DEFINE_INT_TYPE1(NAME, TYPE, BIG_ENDIAN, BYTES) \
-  struct NAME \
-  { \
-    static inline unsigned int get_size () { return BYTES; } \
-    inline void set (TYPE i) { BIG_ENDIAN##_put (v, i); } \
-    inline operator TYPE(void) const { return BIG_ENDIAN##_get (v); } \
-    inline bool operator == (const NAME &o) const { return BIG_ENDIAN##_cmp (v, o.v); } \
-    inline bool sanitize (SANITIZE_ARG_DEF) { \
-      TRACE_SANITIZE (); \
-      return SANITIZE_SELF (); \
-    } \
-    private: unsigned char v[BYTES]; \
-  }; \
-  ASSERT_SIZE (NAME, BYTES)
-#define DEFINE_INT_TYPE0(NAME, type, b)	DEFINE_INT_TYPE1 (NAME, type##_t, hb_be_##type, b)
-#define DEFINE_INT_TYPE(NAME, u, w)	DEFINE_INT_TYPE0 (NAME, u##int##w, (w / 8))
-
-
-DEFINE_INT_TYPE (USHORT, u, 16);	/* 16-bit unsigned integer. */
-DEFINE_INT_TYPE (SHORT,	  , 16);	/* 16-bit signed integer. */
-DEFINE_INT_TYPE (ULONG,	 u, 32);	/* 32-bit unsigned integer. */
-DEFINE_INT_TYPE (LONG,	  , 32);	/* 32-bit signed integer. */
 
+template <typename Type, int Bytes> class BEInt;
+
+template <typename Type>
+class BEInt<Type, 2>
+{
+  public:
+  inline void put (Type i) { hb_be_uint16_put (v,i); }
+  inline Type get () const { return hb_be_uint16_get (v); }
+  inline bool cmp (const BEInt<Type, 2> o) const { return hb_be_uint16_cmp (v, o.v); }
+  private: uint8_t v[2];
+};
+template <typename Type>
+class BEInt<Type, 4>
+{
+  public:
+  inline void put (Type i) { hb_be_uint32_put (v,i); }
+  inline Type get () const { return hb_be_uint32_get (v); }
+  inline bool cmp (const BEInt<Type, 4> o) const { return hb_be_uint32_cmp (v, o.v); }
+  private: uint8_t v[4];
+};
+
+template <typename Type>
+struct IntType
+{
+  static inline unsigned int get_size () { return sizeof (Type); }
+  inline void set (Type i) { v.put (i); }
+  inline operator Type(void) const { return v.get (); }
+  inline bool operator == (const IntType<Type> &o) const { return v.cmp (o.v); }
+  inline bool sanitize (SANITIZE_ARG_DEF) {
+    TRACE_SANITIZE ();
+    return SANITIZE_SELF ();
+  }
+  private: BEInt<Type, sizeof (Type)> v;
+};
+
+typedef IntType<uint16_t> USHORT;	/* 16-bit unsigned integer. */
+typedef IntType<int16_t>  SHORT;	/* 16-bit signed integer. */
+typedef IntType<uint32_t> ULONG;	/* 32-bit unsigned integer. */
+typedef IntType<int32_t>  LONG;		/* 32-bit signed integer. */
+
+ASSERT_SIZE (USHORT, 2);
+ASSERT_SIZE (SHORT, 2);
+ASSERT_SIZE (ULONG, 4);
+ASSERT_SIZE (LONG, 4);
 
 /* Array of four uint8s (length = 32 bits) used to identify a script, language
  * system, feature, or baseline */
diff --git a/src/hb-private.h b/src/hb-private.h
index af47664..1c52744 100644
--- a/src/hb-private.h
+++ b/src/hb-private.h
@@ -216,19 +216,13 @@ typedef int hb_mutex_t;
 
 #define hb_be_uint16(v)		((uint16_t) ((((const uint8_t *)&(v))[0] << 8) + (((const uint8_t *)&(v))[1])))
 
-#define hb_be_uint16_put(v,V)	(v[0] = (V>>8), v[1] = (V), 0)
+#define hb_be_uint16_put(v,V)	HB_STMT_START { v[0] = (V>>8); v[1] = (V); } HB_STMT_END
 #define hb_be_uint16_get(v)	(uint16_t) ((v[0] << 8) + v[1])
 #define hb_be_uint16_cmp(a,b)	(a[0] == b[0] && a[1] == b[1])
-#define hb_be_int16_put		hb_be_uint16_put
-#define hb_be_int16_get		(int16_t) hb_be_uint16_get
-#define hb_be_int16_cmp		hb_be_uint16_cmp
 
-#define hb_be_uint32_put(v,V)	(v[0] = (V>>24), v[1] = (V>>16), v[2] = (V>>8), v[3] = (V), 0)
+#define hb_be_uint32_put(v,V)	HB_STMT_START { v[0] = (V>>24); v[1] = (V>>16); v[2] = (V>>8); v[3] = (V); } HB_STMT_END
 #define hb_be_uint32_get(v)	(uint32_t) ((v[0] << 24) + (v[1] << 16) + (v[2] << 8) + v[3])
 #define hb_be_uint32_cmp(a,b)	(a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3])
-#define hb_be_int32_put		hb_be_uint32_put
-#define hb_be_int32_get		(int32_t) hb_be_uint32_get
-#define hb_be_int32_cmp		hb_be_uint32_cmp
 
 
 
commit 2c9fd2adce5a6a9dcd62c874bd64613ea68d8d9b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 21 02:15:39 2010 -0400

    Remove unused macro

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 2a19755..ec65ba2 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -338,21 +338,6 @@ struct Sanitizer
  * Int types
  */
 
-/* TODO On machines that allow unaligned access, use this version. */
-#define _DEFINE_INT_TYPE1_UNALIGNED(NAME, TYPE, BIG_ENDIAN, BYTES) \
-  struct NAME \
-  { \
-    inline NAME& set (TYPE i) { (TYPE&) v = BIG_ENDIAN (i); return *this; } \
-    inline operator TYPE(void) const { return BIG_ENDIAN ((TYPE&) v); } \
-    inline bool operator == (const NAME &o) const { return (TYPE&) v == (TYPE&) o.v; } \
-    inline bool sanitize (SANITIZE_ARG_DEF) { \
-      TRACE_SANITIZE (); \
-      return SANITIZE_SELF (); \
-    } \
-    private: unsigned char v[BYTES]; \
-  }; \
-  ASSERT_SIZE (NAME, BYTES)
-
 #define DEFINE_INT_TYPE1(NAME, TYPE, BIG_ENDIAN, BYTES) \
   struct NAME \
   { \
commit 7a52f281178867379adb6e6c6fb0022102f75d17
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 21 02:14:44 2010 -0400

    Rename macros

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 9d81d67..2a19755 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -357,9 +357,9 @@ struct Sanitizer
   struct NAME \
   { \
     static inline unsigned int get_size () { return BYTES; } \
-    inline void set (TYPE i) { BIG_ENDIAN##_put_unaligned(v, i); } \
-    inline operator TYPE(void) const { return BIG_ENDIAN##_get_unaligned (v); } \
-    inline bool operator == (const NAME &o) const { return BIG_ENDIAN##_cmp_unaligned (v, o.v); } \
+    inline void set (TYPE i) { BIG_ENDIAN##_put (v, i); } \
+    inline operator TYPE(void) const { return BIG_ENDIAN##_get (v); } \
+    inline bool operator == (const NAME &o) const { return BIG_ENDIAN##_cmp (v, o.v); } \
     inline bool sanitize (SANITIZE_ARG_DEF) { \
       TRACE_SANITIZE (); \
       return SANITIZE_SELF (); \
diff --git a/src/hb-private.h b/src/hb-private.h
index b444935..af47664 100644
--- a/src/hb-private.h
+++ b/src/hb-private.h
@@ -214,21 +214,21 @@ typedef int hb_mutex_t;
 
 /* Big-endian handling */
 
-#define hb_be_uint16(v)			((uint16_t) ((((const uint8_t *)&(v))[0] << 8) + (((const uint8_t *)&(v))[1])))
-
-#define hb_be_uint16_put_unaligned(v,V)	(v[0] = (V>>8), v[1] = (V), 0)
-#define hb_be_uint16_get_unaligned(v)	(uint16_t) ((v[0] << 8) + v[1])
-#define hb_be_uint16_cmp_unaligned(a,b)	(a[0] == b[0] && a[1] == b[1])
-#define hb_be_int16_put_unaligned	hb_be_uint16_put_unaligned
-#define hb_be_int16_get_unaligned	(int16_t) hb_be_uint16_get_unaligned
-#define hb_be_int16_cmp_unaligned	hb_be_uint16_cmp_unaligned
-
-#define hb_be_uint32_put_unaligned(v,V)	(v[0] = (V>>24), v[1] = (V>>16), v[2] = (V>>8), v[3] = (V), 0)
-#define hb_be_uint32_get_unaligned(v)	(uint32_t) ((v[0] << 24) + (v[1] << 16) + (v[2] << 8) + v[3])
-#define hb_be_uint32_cmp_unaligned(a,b)	(a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3])
-#define hb_be_int32_put_unaligned	hb_be_uint32_put_unaligned
-#define hb_be_int32_get_unaligned	(int32_t) hb_be_uint32_get_unaligned
-#define hb_be_int32_cmp_unaligned	hb_be_uint32_cmp_unaligned
+#define hb_be_uint16(v)		((uint16_t) ((((const uint8_t *)&(v))[0] << 8) + (((const uint8_t *)&(v))[1])))
+
+#define hb_be_uint16_put(v,V)	(v[0] = (V>>8), v[1] = (V), 0)
+#define hb_be_uint16_get(v)	(uint16_t) ((v[0] << 8) + v[1])
+#define hb_be_uint16_cmp(a,b)	(a[0] == b[0] && a[1] == b[1])
+#define hb_be_int16_put		hb_be_uint16_put
+#define hb_be_int16_get		(int16_t) hb_be_uint16_get
+#define hb_be_int16_cmp		hb_be_uint16_cmp
+
+#define hb_be_uint32_put(v,V)	(v[0] = (V>>24), v[1] = (V>>16), v[2] = (V>>8), v[3] = (V), 0)
+#define hb_be_uint32_get(v)	(uint32_t) ((v[0] << 24) + (v[1] << 16) + (v[2] << 8) + v[3])
+#define hb_be_uint32_cmp(a,b)	(a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3])
+#define hb_be_int32_put		hb_be_uint32_put
+#define hb_be_int32_get		(int32_t) hb_be_uint32_get
+#define hb_be_int32_cmp		hb_be_uint32_cmp
 
 
 
commit ffff7dc44cb2a35a60f92831165e9d3c3a61ce19
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 21 02:13:55 2010 -0400

    Minor

diff --git a/src/hb-private.h b/src/hb-private.h
index 463c27a..b444935 100644
--- a/src/hb-private.h
+++ b/src/hb-private.h
@@ -200,14 +200,14 @@ typedef GStaticMutex hb_mutex_t;
 typedef int hb_atomic_int_t;
 #define hb_atomic_int_fetch_and_add(AI, V)	((AI) += (V), (AI) - (V))
 #define hb_atomic_int_get(AI)			(AI)
-#define hb_atomic_int_set(AI, V)		do { (AI) = (V); } while (0)
+#define hb_atomic_int_set(AI, V)		HB_STMT_START { (AI) = (V); } HB_STMT_END
 
 typedef int hb_mutex_t;
-#define HB_MUTEX_INIT			0
-#define hb_mutex_init(M)		do { (M) = 0; } while (0)
-#define hb_mutex_lock(M)		do { (M) = 1; } while (0)
-#define hb_mutex_trylock(M)		((M) = 1, 1)
-#define hb_mutex_unlock(M)		do { (M) = 0; } while (0)
+#define HB_MUTEX_INIT				0
+#define hb_mutex_init(M)			HB_STMT_START { (M) = 0; } HB_STMT_END
+#define hb_mutex_lock(M)			HB_STMT_START { (M) = 1; } HB_STMT_END
+#define hb_mutex_trylock(M)			((M) = 1, 1)
+#define hb_mutex_unlock(M)			HB_STMT_START { (M) = 0; } HB_STMT_END
 
 #endif
 
commit f60f2166c48d07f556ff83f04e95181946eb03df
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 21 02:12:45 2010 -0400

    Move macros around

diff --git a/src/hb-private.h b/src/hb-private.h
index 9a3a1ba..463c27a 100644
--- a/src/hb-private.h
+++ b/src/hb-private.h
@@ -47,66 +47,6 @@
 #include "hb-common.h"
 
 
-/* We need external help for these */
-
-#ifdef HAVE_GLIB
-
-#include <glib.h>
-
-typedef int hb_atomic_int_t;
-#define hb_atomic_int_fetch_and_add(AI, V)	g_atomic_int_exchange_and_add (&(AI), V)
-#define hb_atomic_int_get(AI)			g_atomic_int_get (&(AI))
-#define hb_atomic_int_set(AI, V)		g_atomic_int_set (&(AI), V)
-
-typedef GStaticMutex hb_mutex_t;
-#define HB_MUTEX_INIT			G_STATIC_MUTEX_INIT
-#define hb_mutex_init(M)		g_static_mutex_init (&M)
-#define hb_mutex_lock(M)		g_static_mutex_lock (&M)
-#define hb_mutex_trylock(M)		g_static_mutex_trylock (&M)
-#define hb_mutex_unlock(M)		g_static_mutex_unlock (&M)
-
-#else
-
-#ifdef _MSC_VER
-#pragma message(__LOC__"Could not find any system to define platform macros, library will NOT be thread-safe")
-#else
-#warning "Could not find any system to define platform macros, library will NOT be thread-safe"
-#endif
-
-typedef int hb_atomic_int_t;
-#define hb_atomic_int_fetch_and_add(AI, V)	((AI) += (V), (AI) - (V))
-#define hb_atomic_int_get(AI)			(AI)
-#define hb_atomic_int_set(AI, V)		do { (AI) = (V); } while (0)
-
-typedef int hb_mutex_t;
-#define HB_MUTEX_INIT			0
-#define hb_mutex_init(M)		do { (M) = 0; } while (0)
-#define hb_mutex_lock(M)		do { (M) = 1; } while (0)
-#define hb_mutex_trylock(M)		((M) = 1, 1)
-#define hb_mutex_unlock(M)		do { (M) = 0; } while (0)
-
-#endif
-
-
-/* Big-endian handling */
-
-#define hb_be_uint16(v)			((uint16_t) ((((const uint8_t *)&(v))[0] << 8) + (((const uint8_t *)&(v))[1])))
-
-#define hb_be_uint16_put_unaligned(v,V)	(v[0] = (V>>8), v[1] = (V), 0)
-#define hb_be_uint16_get_unaligned(v)	(uint16_t) ((v[0] << 8) + v[1])
-#define hb_be_uint16_cmp_unaligned(a,b)	(a[0] == b[0] && a[1] == b[1])
-#define hb_be_int16_put_unaligned	hb_be_uint16_put_unaligned
-#define hb_be_int16_get_unaligned	(int16_t) hb_be_uint16_get_unaligned
-#define hb_be_int16_cmp_unaligned	hb_be_uint16_cmp_unaligned
-
-#define hb_be_uint32_put_unaligned(v,V)	(v[0] = (V>>24), v[1] = (V>>16), v[2] = (V>>8), v[3] = (V), 0)
-#define hb_be_uint32_get_unaligned(v)	(uint32_t) ((v[0] << 24) + (v[1] << 16) + (v[2] << 8) + v[3])
-#define hb_be_uint32_cmp_unaligned(a,b)	(a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3])
-#define hb_be_int32_put_unaligned	hb_be_uint32_put_unaligned
-#define hb_be_int32_get_unaligned	(int32_t) hb_be_uint32_get_unaligned
-#define hb_be_int32_cmp_unaligned	hb_be_uint32_cmp_unaligned
-
-
 /* Basics */
 
 #undef MIN
@@ -230,6 +170,68 @@ _hb_popcount32 (uint32_t mask)
 /* Multiplies a 16dot16 value by another value, then truncates the result */
 #define _hb_16dot16_mul_round(A,B) (((int64_t) (A) * (B) + 0x8000) / 0x10000)
 
+
+/* We need external help for these */
+
+#ifdef HAVE_GLIB
+
+#include <glib.h>
+
+typedef int hb_atomic_int_t;
+#define hb_atomic_int_fetch_and_add(AI, V)	g_atomic_int_exchange_and_add (&(AI), V)
+#define hb_atomic_int_get(AI)			g_atomic_int_get (&(AI))
+#define hb_atomic_int_set(AI, V)		g_atomic_int_set (&(AI), V)
+
+typedef GStaticMutex hb_mutex_t;
+#define HB_MUTEX_INIT			G_STATIC_MUTEX_INIT
+#define hb_mutex_init(M)		g_static_mutex_init (&M)
+#define hb_mutex_lock(M)		g_static_mutex_lock (&M)
+#define hb_mutex_trylock(M)		g_static_mutex_trylock (&M)
+#define hb_mutex_unlock(M)		g_static_mutex_unlock (&M)
+
+#else
+
+#ifdef _MSC_VER
+#pragma message(__LOC__"Could not find any system to define platform macros, library will NOT be thread-safe")
+#else
+#warning "Could not find any system to define platform macros, library will NOT be thread-safe"
+#endif
+
+typedef int hb_atomic_int_t;
+#define hb_atomic_int_fetch_and_add(AI, V)	((AI) += (V), (AI) - (V))
+#define hb_atomic_int_get(AI)			(AI)
+#define hb_atomic_int_set(AI, V)		do { (AI) = (V); } while (0)
+
+typedef int hb_mutex_t;
+#define HB_MUTEX_INIT			0
+#define hb_mutex_init(M)		do { (M) = 0; } while (0)
+#define hb_mutex_lock(M)		do { (M) = 1; } while (0)
+#define hb_mutex_trylock(M)		((M) = 1, 1)
+#define hb_mutex_unlock(M)		do { (M) = 0; } while (0)
+
+#endif
+
+
+/* Big-endian handling */
+
+#define hb_be_uint16(v)			((uint16_t) ((((const uint8_t *)&(v))[0] << 8) + (((const uint8_t *)&(v))[1])))
+
+#define hb_be_uint16_put_unaligned(v,V)	(v[0] = (V>>8), v[1] = (V), 0)
+#define hb_be_uint16_get_unaligned(v)	(uint16_t) ((v[0] << 8) + v[1])
+#define hb_be_uint16_cmp_unaligned(a,b)	(a[0] == b[0] && a[1] == b[1])
+#define hb_be_int16_put_unaligned	hb_be_uint16_put_unaligned
+#define hb_be_int16_get_unaligned	(int16_t) hb_be_uint16_get_unaligned
+#define hb_be_int16_cmp_unaligned	hb_be_uint16_cmp_unaligned
+
+#define hb_be_uint32_put_unaligned(v,V)	(v[0] = (V>>24), v[1] = (V>>16), v[2] = (V>>8), v[3] = (V), 0)
+#define hb_be_uint32_get_unaligned(v)	(uint32_t) ((v[0] << 24) + (v[1] << 16) + (v[2] << 8) + v[3])
+#define hb_be_uint32_cmp_unaligned(a,b)	(a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3])
+#define hb_be_int32_put_unaligned	hb_be_uint32_put_unaligned
+#define hb_be_int32_get_unaligned	(int32_t) hb_be_uint32_get_unaligned
+#define hb_be_int32_cmp_unaligned	hb_be_uint32_cmp_unaligned
+
+
+
 #include "hb-object-private.h"
 
 #endif /* HB_PRIVATE_H */
commit 649a4344ca363da3d44cdd908350449ec40ed0f9
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 21 02:11:59 2010 -0400

    Remove unused macros

diff --git a/src/hb-private.h b/src/hb-private.h
index 7c48a87..9a3a1ba 100644
--- a/src/hb-private.h
+++ b/src/hb-private.h
@@ -92,13 +92,6 @@ typedef int hb_mutex_t;
 
 #define hb_be_uint16(v)			((uint16_t) ((((const uint8_t *)&(v))[0] << 8) + (((const uint8_t *)&(v))[1])))
 
-#define hb_be_uint8_put_unaligned(v,V)	(v[0] = (V), 0)
-#define hb_be_uint8_get_unaligned(v)	(uint8_t) (v[0])
-#define hb_be_uint8_cmp_unaligned(a,b)	(a[0] == b[0])
-#define hb_be_int8_put_unaligned	hb_be_uint8_put_unaligned
-#define hb_be_int8_get_unaligned	(int8_t) hb_be_uint8_get_unaligned
-#define hb_be_int8_cmp_unaligned	hb_be_uint8_cmp_unaligned
-
 #define hb_be_uint16_put_unaligned(v,V)	(v[0] = (V>>8), v[1] = (V), 0)
 #define hb_be_uint16_get_unaligned(v)	(uint16_t) ((v[0] << 8) + v[1])
 #define hb_be_uint16_cmp_unaligned(a,b)	(a[0] == b[0] && a[1] == b[1])
commit eba8b4f644701cc6b78b0fcb4e932dce15561598
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Mar 29 00:04:12 2010 -0400

    GNOME Bug 613015 - [HB] Does not sanitize Device tables referenced from ValueRecords

diff --git a/src/hb-ot-layout-gpos-private.hh b/src/hb-ot-layout-gpos-private.hh
index 60eb439..9598831 100644
--- a/src/hb-ot-layout-gpos-private.hh
+++ b/src/hb-ot-layout-gpos-private.hh
@@ -51,9 +51,9 @@ struct ValueFormat : USHORT
     xAdvDevice	= 0x0040,	/* Includes horizontal Device table for advance */
     yAdvDevice	= 0x0080,	/* Includes vertical Device table for advance */
     ignored	= 0x0F00,	/* Was used in TrueType Open for MM fonts */
-    reserved	= 0xF000 	/* For future use */
+    reserved	= 0xF000,	/* For future use */
 
-    devices	= 0x00F0,	/* Mask for having any Device table */
+    devices	= 0x00F0	/* Mask for having any Device table */
   };
 
 /* All fields are options.  Only those available advance the value pointer. */
@@ -422,7 +422,7 @@ struct SinglePosFormat1
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
     return SANITIZE_SELF () && SANITIZE_THIS (coverage) &&
-	   SANITIZE_MEM (values, valueFormat.get_size ());
+	   valueFormat.sanitize_value (SANITIZE_ARG, CHARP(this), values);
   }
 
   private:
@@ -464,7 +464,7 @@ struct SinglePosFormat2
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
     return SANITIZE_SELF () && SANITIZE_THIS (coverage) &&
-	   SANITIZE_MEM (values, valueFormat.get_size () * valueCount);
+	   valueFormat.sanitize_values (SANITIZE_ARG, CHARP(this), values, valueCount);
   }
 
   private:
@@ -531,6 +531,7 @@ struct PairSet
 {
   friend struct PairPosFormat1;
 
+  /* Note: Doesn't sanitize the Device entries in the ValueRecord */
   inline bool sanitize (SANITIZE_ARG_DEF, unsigned int format_len) {
     TRACE_SANITIZE ();
     if (!SANITIZE_SELF ()) return false;
@@ -570,12 +571,11 @@ struct PairPosFormat1
       j++;
     }
 
-    const PairSet &pair_set = this+pairSet[index];
-
     unsigned int len1 = valueFormat1.get_len ();
     unsigned int len2 = valueFormat2.get_len ();
     unsigned int record_size = USHORT::get_size () * (1 + len1 + len2);
 
+    const PairSet &pair_set = this+pairSet[index];
     unsigned int count = pair_set.len;
     const PairValueRecord *record = pair_set.array;
     for (unsigned int i = 0; i < count; i++)
@@ -597,9 +597,29 @@ struct PairPosFormat1
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
-    return SANITIZE_SELF () && SANITIZE_THIS (coverage) &&
-	   pairSet.sanitize (SANITIZE_ARG, CONST_CHARP(this),
-			     valueFormat1.get_len () + valueFormat2.get_len ());
+
+    unsigned int len1 = valueFormat1.get_len ();
+    unsigned int len2 = valueFormat2.get_len ();
+
+    if (!(SANITIZE_SELF () && SANITIZE_THIS (coverage) &&
+	  pairSet.sanitize (SANITIZE_ARG, CONST_CHARP(this), len1 + len2))) return false;
+
+    if (!(valueFormat1.has_device () || valueFormat2.has_device ())) return true;
+
+    unsigned int stride = 1 + len1 + len2;
+    unsigned int count1 = pairSet.len;
+    for (unsigned int i = 0; i < count1; i++)
+    {
+      const PairSet &pair_set = this+pairSet[i];
+
+      unsigned int count2 = pair_set.len;
+      const PairValueRecord *record = pair_set.array;
+      if (!(valueFormat1.sanitize_values_stride_unsafe (SANITIZE_ARG, CHARP(this), &record->values[0], count2, stride) &&
+	    valueFormat2.sanitize_values_stride_unsafe (SANITIZE_ARG, CHARP(this), &record->values[len1], count2, stride)))
+        return false;
+    }
+
+    return true;
   }
 
   private:
@@ -668,9 +688,14 @@ struct PairPosFormat2
     if (!(SANITIZE_SELF () && SANITIZE_THIS (coverage) &&
 	  SANITIZE_THIS2 (classDef1, classDef2))) return false;
 
+    unsigned int len1 = valueFormat1.get_len ();
+    unsigned int len2 = valueFormat2.get_len ();
+    unsigned int stride = len1 + len2;
     unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
-    unsigned int len = class1Count * class2Count;
-    return SANITIZE_ARRAY (values, record_size, len);
+    unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
+    return SANITIZE_ARRAY (values, record_size, count) &&
+	   valueFormat1.sanitize_values_stride_unsafe (SANITIZE_ARG, CHARP(this), &values[0], count, stride) &&
+	   valueFormat2.sanitize_values_stride_unsafe (SANITIZE_ARG, CHARP(this), &values[len1], count, stride);
   }
 
   private:
commit 673a4efcbc72a62105a24d9b0b54047417160f7d
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 21 02:02:57 2010 -0400

    WIP

diff --git a/src/hb-ot-layout-gpos-private.hh b/src/hb-ot-layout-gpos-private.hh
index bd72aae..60eb439 100644
--- a/src/hb-ot-layout-gpos-private.hh
+++ b/src/hb-ot-layout-gpos-private.hh
@@ -52,29 +52,12 @@ struct ValueFormat : USHORT
     yAdvDevice	= 0x0080,	/* Includes vertical Device table for advance */
     ignored	= 0x0F00,	/* Was used in TrueType Open for MM fonts */
     reserved	= 0xF000 	/* For future use */
-  };
-
-  inline unsigned int get_len () const
-  { return _hb_popcount32 ((unsigned int) *this); }
-  inline unsigned int get_size () const
-  { return get_len () * Value::get_size (); }
 
-  void apply_value (hb_ot_layout_context_t *context,
-		    const char             *base,
-		    const Value            *values,
-		    hb_internal_glyph_position_t *glyph_pos) const
-  {
-    unsigned int x_ppem, y_ppem;
-    hb_16dot16_t x_scale, y_scale;
-    unsigned int format = *this;
-
-    if (!format)
-      return;
+    devices	= 0x00F0,	/* Mask for having any Device table */
+  };
 
-    /* All fields are options.  Only those available advance the value
-     * pointer. */
+/* All fields are options.  Only those available advance the value pointer. */
 #if 0
-struct ValueRecord {
   SHORT		xPlacement;		/* Horizontal adjustment for
 					 * placement--in design units */
   SHORT		yPlacement;		/* Vertical adjustment for
@@ -97,9 +80,24 @@ struct ValueRecord {
   Offset	yAdvDevice;		/* Offset to Device table for vertical
 					 * advance--measured from beginning of
 					 * PosTable (may be NULL) */
-};
 #endif
 
+  inline unsigned int get_len () const
+  { return _hb_popcount32 ((unsigned int) *this); }
+  inline unsigned int get_size () const
+  { return get_len () * Value::get_size (); }
+
+  void apply_value (hb_ot_layout_context_t       *context,
+		    const char                   *base,
+		    const Value                  *values,
+		    hb_internal_glyph_position_t *glyph_pos) const
+  {
+    unsigned int x_ppem, y_ppem;
+    hb_16dot16_t x_scale, y_scale;
+    unsigned int format = *this;
+
+    if (!format) return;
+
     x_scale = context->font->x_scale;
     y_scale = context->font->y_scale;
     /* design units -> fractional pixel */
@@ -124,6 +122,68 @@ struct ValueRecord {
       if (y_ppem) glyph_pos->y_advance += (base+*(OffsetTo<Device>*)values++).get_delta (y_ppem) << 16; else values++;
     }
   }
+
+  private:
+  inline bool sanitize_value_devices (SANITIZE_ARG_DEF, void *base, const Value *values) {
+    unsigned int format = *this;
+
+    if (format & xPlacement) values++;
+    if (format & yPlacement) values++;
+    if (format & xAdvance)   values++;
+    if (format & yAdvance)   values++;
+
+    if ((format & xPlaDevice) && !SANITIZE_BASE (*(OffsetTo<Device>*)values++, base)) return false;
+    if ((format & yPlaDevice) && !SANITIZE_BASE (*(OffsetTo<Device>*)values++, base)) return false;
+    if ((format & xAdvDevice) && !SANITIZE_BASE (*(OffsetTo<Device>*)values++, base)) return false;
+    if ((format & yAdvDevice) && !SANITIZE_BASE (*(OffsetTo<Device>*)values++, base)) return false;
+
+    return true;
+  }
+
+  public:
+
+  inline bool has_device () {
+    unsigned int format = *this;
+    return (format & devices) != 0;
+  }
+
+  inline bool sanitize_value (SANITIZE_ARG_DEF, void *base, const Value *values) {
+    TRACE_SANITIZE ();
+
+    return SANITIZE_MEM (values, get_size ()) &&
+	   (!has_device () || sanitize_value_devices (SANITIZE_ARG, base, values));
+  }
+
+  inline bool sanitize_values (SANITIZE_ARG_DEF, void *base, const Value *values, unsigned int count) {
+    TRACE_SANITIZE ();
+    unsigned int len = get_len ();
+
+    if (!SANITIZE_ARRAY (values, get_size (), count)) return false;
+
+    if (!has_device ()) return true;
+
+    for (unsigned int i = 0; i < count; i++) {
+      if (!sanitize_value_devices (SANITIZE_ARG, base, values))
+        return false;
+      values += len;
+    }
+
+    return true;
+  }
+
+  inline bool sanitize_values_stride_unsafe (SANITIZE_ARG_DEF, void *base, const Value *values, unsigned int count, unsigned int stride) {
+    TRACE_SANITIZE ();
+
+    if (!has_device ()) return true;
+
+    for (unsigned int i = 0; i < count; i++) {
+      if (!sanitize_value_devices (SANITIZE_ARG, base, values))
+        return false;
+      values += stride;
+    }
+
+    return true;
+  }
 };
 ASSERT_SIZE (ValueFormat, 2);
 
commit 40d73bc68dd828cf68f90fde0f9499a6ce9fbb19
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 21 00:49:40 2010 -0400

    Improve comments

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 7a1ccee..9d81d67 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -523,11 +523,14 @@ struct GenericArrayOf
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
     if (!SANITIZE_GET_SIZE()) return false;
-    /* Note:
-     * for non-recursive types, this is not much needed.
-     * But we keep the code to make sure the objects pointed to
-     * do have a simple sanitize(). */
+    /* Note: for structs that do not reference other structs,
+     * we do not need to call their sanitize() as we already did
+     * a bound check on the aggregate array size, hence the return.
+     */
     return true;
+    /* We do keep this code though to make sure the structs pointed
+     * to do have a simple sanitize(), ie. they do not reference
+     * other structs. */
     unsigned int count = len;
     for (unsigned int i = 0; i < count; i++)
       if (!SANITIZE (array()[i]))
@@ -626,11 +629,14 @@ struct HeadlessArrayOf
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
     if (!SANITIZE_GET_SIZE()) return false;
-    /* Note:
-     * for non-recursive types, this is not much needed.
-     * But we keep the code to make sure the objects pointed to
-     * do have a simple sanitize(). */
+    /* Note: for structs that do not reference other structs,
+     * we do not need to call their sanitize() as we already did
+     * a bound check on the aggregate array size, hence the return.
+     */
     return true;
+    /* We do keep this code though to make sure the structs pointed
+     * to do have a simple sanitize(), ie. they do not reference
+     * other structs. */
     unsigned int count = len ? len - 1 : 0;
     Type *a = array();
     for (unsigned int i = 0; i < count; i++)
commit 394bad41a76f90e441e327cef76efb99997e9ae0
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 21 00:40:50 2010 -0400

    Remove stale TODO item

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 77f935e..7a1ccee 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -248,7 +248,6 @@ _hb_sanitize_edit (SANITIZE_ARG_DEF,
 #define SANITIZE_OBJ(X) SANITIZE_MEM(&(X), sizeof (X))
 #define SANITIZE_GET_SIZE() SANITIZE_SELF() && SANITIZE_MEM (this, this->get_size ())
 
-/* TODO Optimize this if L is fixed (gcc magic) */
 #define SANITIZE_MEM(B,L) HB_LIKELY (_hb_sanitize_check (SANITIZE_ARG, CONST_CHARP(B), (L)))
 
 #define SANITIZE_ARRAY(A,S,L) HB_LIKELY (_hb_sanitize_array (SANITIZE_ARG, CONST_CHARP(A), S, L))
commit 9d3677899f90abdc7fb3e3d854db654a8707a84b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 21 00:32:47 2010 -0400

    Use a function template instead of struct template for Null

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 9c88f25..77f935e 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -61,27 +61,25 @@
 /* Null objects */
 
 /* Global nul-content Null pool.  Enlarge as necessary. */
-static const void *NullPool[32 / sizeof (void *)];
+static const void *_NullPool[32 / sizeof (void *)];
 
 /* Generic template for nul-content sizeof-sized Null objects. */
 template <typename Type>
-struct Null
-{
-  ASSERT_STATIC (sizeof (Type) <= sizeof (NullPool));
-  static inline const Type &get () { return CONST_CAST (Type, *NullPool, 0); }
-};
+static inline const Type& Null () {
+  ASSERT_STATIC (sizeof (Type) <= sizeof (_NullPool));
+  return CONST_CAST (Type, *_NullPool, 0);
+}
 
 /* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
 #define DEFINE_NULL_DATA(Type, size, data) \
-static const char _Null##Type[size] = data; \
+static const char _Null##Type[size + 1] = data; \
 template <> \
-struct Null <Type> \
-{ \
-  static inline const Type &get () { return CONST_CAST (Type, *_Null##Type, 0); } \
+inline const Type& Null<Type> () { \
+  return CONST_CAST (Type, *_Null##Type, 0); \
 }
 
 /* Accessor macro. */
-#define Null(Type) (Null<Type>::get())
+#define Null(Type) Null<Type>()
 
 
 /* get_for_data() is a static class method returning a reference to an
@@ -398,9 +396,7 @@ struct Tag : ULONG
   }
 };
 ASSERT_SIZE (Tag, 4);
-#define _NULL_TAG_INIT  {' ', ' ', ' ', ' '}
-DEFINE_NULL_DATA (Tag, 4, _NULL_TAG_INIT);
-#undef _NULL_TAG_INIT
+DEFINE_NULL_DATA (Tag, 4, "    ");
 
 /* Glyph index number, same as uint16 (length = 16 bits) */
 typedef USHORT GlyphID;
commit ffd321afd91429c5de7ab03d71ef1030044f53cb
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Apr 21 00:14:12 2010 -0400

    Simplify Tag struct

diff --git a/src/hb-open-file-private.hh b/src/hb-open-file-private.hh
index e72a098..ce5140f 100644
--- a/src/hb-open-file-private.hh
+++ b/src/hb-open-file-private.hh
@@ -84,7 +84,8 @@ typedef struct OffsetTable
   }
   inline bool find_table_index (hb_tag_t tag, unsigned int *table_index) const
   {
-    const Tag t = tag;
+    Tag t;
+    t.set (tag);
     // TODO bsearch
     unsigned int count = numTables;
     for (unsigned int i = 0; i < count; i++)
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 0df9e8c..9c88f25 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -360,7 +360,7 @@ struct Sanitizer
   struct NAME \
   { \
     static inline unsigned int get_size () { return BYTES; } \
-    inline NAME& set (TYPE i) { BIG_ENDIAN##_put_unaligned(v, i); return *this; } \
+    inline void set (TYPE i) { BIG_ENDIAN##_put_unaligned(v, i); } \
     inline operator TYPE(void) const { return BIG_ENDIAN##_get_unaligned (v); } \
     inline bool operator == (const NAME &o) const { return BIG_ENDIAN##_cmp_unaligned (v, o.v); } \
     inline bool sanitize (SANITIZE_ARG_DEF) { \
@@ -384,10 +384,6 @@ DEFINE_INT_TYPE (LONG,	  , 32);	/* 32-bit signed integer. */
  * system, feature, or baseline */
 struct Tag : ULONG
 {
-  inline Tag (const Tag &o) { *(ULONG*)this = (ULONG&) o; }
-  inline Tag (uint32_t i) { (*(ULONG*)this).set (i); }
-  inline Tag (const char *c) { *(ULONG*)this = *(ULONG*)c; }
-  inline bool operator == (const char *c) const { return *(ULONG*)this == *(ULONG*)c; }
   /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
   inline operator const char* (void) const { return CONST_CHARP(this); }
   inline operator char* (void) { return CHARP(this); }
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index ad5e5c5..6c6d7ac 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -85,7 +85,8 @@ struct RecordArrayOf : ArrayOf<Record<Type> > {
   }
   inline bool find_index (hb_tag_t tag, unsigned int *index) const
   {
-    const Tag t = tag;
+    Tag t;
+    t.set (tag);
     // TODO bsearch
     const Record<Type> *a = this->const_array();
     unsigned int count = this->len;
commit 00e23fcc6fd0eee5c582251bf3de6a2703fbbd3e
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Apr 20 23:50:45 2010 -0400

    Cosmetic

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 74b1e2e..0df9e8c 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -347,7 +347,7 @@ struct Sanitizer
   { \
     inline NAME& set (TYPE i) { (TYPE&) v = BIG_ENDIAN (i); return *this; } \
     inline operator TYPE(void) const { return BIG_ENDIAN ((TYPE&) v); } \
-    inline bool operator== (const NAME &o) const { return (TYPE&) v == (TYPE&) o.v; } \
+    inline bool operator == (const NAME &o) const { return (TYPE&) v == (TYPE&) o.v; } \
     inline bool sanitize (SANITIZE_ARG_DEF) { \
       TRACE_SANITIZE (); \
       return SANITIZE_SELF (); \
@@ -362,7 +362,7 @@ struct Sanitizer
     static inline unsigned int get_size () { return BYTES; } \
     inline NAME& set (TYPE i) { BIG_ENDIAN##_put_unaligned(v, i); return *this; } \
     inline operator TYPE(void) const { return BIG_ENDIAN##_get_unaligned (v); } \
-    inline bool operator== (const NAME &o) const { return BIG_ENDIAN##_cmp_unaligned (v, o.v); } \
+    inline bool operator == (const NAME &o) const { return BIG_ENDIAN##_cmp_unaligned (v, o.v); } \
     inline bool sanitize (SANITIZE_ARG_DEF) { \
       TRACE_SANITIZE (); \
       return SANITIZE_SELF (); \
@@ -387,7 +387,7 @@ struct Tag : ULONG
   inline Tag (const Tag &o) { *(ULONG*)this = (ULONG&) o; }
   inline Tag (uint32_t i) { (*(ULONG*)this).set (i); }
   inline Tag (const char *c) { *(ULONG*)this = *(ULONG*)c; }
-  inline bool operator== (const char *c) const { return *(ULONG*)this == *(ULONG*)c; }
+  inline bool operator == (const char *c) const { return *(ULONG*)this == *(ULONG*)c; }
   /* What the char* converters return is NOT nul-terminated.  Print using "%.4s" */
   inline operator const char* (void) const { return CONST_CHARP(this); }
   inline operator char* (void) { return CHARP(this); }
@@ -460,7 +460,7 @@ ASSERT_SIZE (FixedVersion, 4);
 template <typename OffsetType, typename Type>
 struct GenericOffsetTo : OffsetType
 {
-  inline const Type& operator() (const void *base) const
+  inline const Type& operator () (const void *base) const
   {
     unsigned int offset = *this;
     if (HB_UNLIKELY (!offset)) return Null(Type);
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 72b50c0..ad5e5c5 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -415,7 +415,7 @@ ASSERT_SIZE (CoverageFormat2, 4);
 
 struct Coverage
 {
-  inline unsigned int operator() (hb_codepoint_t glyph_id) const { return get_coverage (glyph_id); }
+  inline unsigned int operator () (hb_codepoint_t glyph_id) const { return get_coverage (glyph_id); }
 
   inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
   {
@@ -533,7 +533,7 @@ ASSERT_SIZE (ClassDefFormat2, 4);
 
 struct ClassDef
 {
-  inline hb_ot_layout_class_t operator() (hb_codepoint_t glyph_id) const { return get_class (glyph_id); }
+  inline hb_ot_layout_class_t operator () (hb_codepoint_t glyph_id) const { return get_class (glyph_id); }
 
   inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const
   {
@@ -569,7 +569,7 @@ struct ClassDef
 
 struct Device
 {
-  inline int operator() (unsigned int ppem_size) const { return get_delta (ppem_size); }
+  inline int operator () (unsigned int ppem_size) const { return get_delta (ppem_size); }
 
   inline int get_delta (unsigned int ppem_size) const
   {
commit a87072db5d41e25b2e31191545298bca4838c65c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Apr 20 15:52:47 2010 -0400

    Fix Class operator return type

diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index d3c5bef..72b50c0 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -533,7 +533,7 @@ ASSERT_SIZE (ClassDefFormat2, 4);
 
 struct ClassDef
 {
-  inline unsigned int operator() (hb_codepoint_t glyph_id) const { return get_class (glyph_id); }
+  inline hb_ot_layout_class_t operator() (hb_codepoint_t glyph_id) const { return get_class (glyph_id); }
 
   inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const
   {
commit f9b37727985191c9b4aedb0e9835736027e59260
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Apr 20 15:51:53 2010 -0400

    Add couple consts to operators

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 38d3108..74b1e2e 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007,2008,2009  Red Hat, Inc.
+ * Copyright (C) 2007,2008,2009,2010  Red Hat, Inc.
  *
  *  This is part of HarfBuzz, an OpenType Layout engine library.
  *
@@ -347,7 +347,7 @@ struct Sanitizer
   { \
     inline NAME& set (TYPE i) { (TYPE&) v = BIG_ENDIAN (i); return *this; } \
     inline operator TYPE(void) const { return BIG_ENDIAN ((TYPE&) v); } \
-    inline bool operator== (NAME o) const { return (TYPE&) v == (TYPE&) o.v; } \
+    inline bool operator== (const NAME &o) const { return (TYPE&) v == (TYPE&) o.v; } \
     inline bool sanitize (SANITIZE_ARG_DEF) { \
       TRACE_SANITIZE (); \
       return SANITIZE_SELF (); \
@@ -362,7 +362,7 @@ struct Sanitizer
     static inline unsigned int get_size () { return BYTES; } \
     inline NAME& set (TYPE i) { BIG_ENDIAN##_put_unaligned(v, i); return *this; } \
     inline operator TYPE(void) const { return BIG_ENDIAN##_get_unaligned (v); } \
-    inline bool operator== (NAME o) const { return BIG_ENDIAN##_cmp_unaligned (v, o.v); } \
+    inline bool operator== (const NAME &o) const { return BIG_ENDIAN##_cmp_unaligned (v, o.v); } \
     inline bool sanitize (SANITIZE_ARG_DEF) { \
       TRACE_SANITIZE (); \
       return SANITIZE_SELF (); \
commit 53d237ec6352d7c6fab3b2805b48154a25506beb
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Apr 20 15:25:27 2010 -0400

    Remove ASSERT_SIZE_DATA

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 36e565f..38d3108 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -84,10 +84,6 @@ struct Null <Type> \
 #define Null(Type) (Null<Type>::get())
 
 
-#define ASSERT_SIZE_DATA(Type, size, data) \
-  ASSERT_SIZE (Type, size); \
-  DEFINE_NULL_DATA (Type, size, data)
-
 /* get_for_data() is a static class method returning a reference to an
  * instance of Type located at the input data location.  It's just a
  * fancy, NULL-safe, cast! */
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 85f228e..d3c5bef 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -174,7 +174,8 @@ struct LangSys
 				 * = 0xFFFF */
   IndexArray	featureIndex;	/* Array of indices into the FeatureList */
 };
-ASSERT_SIZE_DATA (LangSys, 6, "\0\0\xFF\xFF");
+ASSERT_SIZE (LangSys, 6);
+DEFINE_NULL_DATA (LangSys, 6, "\0\0\xFF\xFF");
 
 
 struct Script
@@ -377,7 +378,8 @@ struct CoverageRangeRecord
   USHORT	startCoverageIndex;	/* Coverage Index of first GlyphID in
 					 * range */
 };
-ASSERT_SIZE_DATA (CoverageRangeRecord, 6, "\000\001");
+ASSERT_SIZE (CoverageRangeRecord, 6);
+DEFINE_NULL_DATA (CoverageRangeRecord, 6, "\000\001");
 
 struct CoverageFormat2
 {
@@ -496,7 +498,8 @@ struct ClassRangeRecord
   GlyphID	end;		/* Last GlyphID in the range */
   USHORT	classValue;	/* Applied to all glyphs in the range */
 };
-ASSERT_SIZE_DATA (ClassRangeRecord, 6, "\000\001");
+ASSERT_SIZE (ClassRangeRecord, 6);
+DEFINE_NULL_DATA (ClassRangeRecord, 6, "\000\001");
 
 struct ClassDefFormat2
 {
commit 06558d2a745b8f3af11a8d6dce956ae52187a7e5
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 19 02:34:10 2010 -0400

    Round instead of trunc

diff --git a/src/hb-ot-layout-gpos-private.hh b/src/hb-ot-layout-gpos-private.hh
index e72e7b3..bd72aae 100644
--- a/src/hb-ot-layout-gpos-private.hh
+++ b/src/hb-ot-layout-gpos-private.hh
@@ -103,10 +103,10 @@ struct ValueRecord {
     x_scale = context->font->x_scale;
     y_scale = context->font->y_scale;
     /* design units -> fractional pixel */
-    if (format & xPlacement) glyph_pos->x_offset  += _hb_16dot16_mul_trunc (x_scale, *(SHORT*)values++);
-    if (format & yPlacement) glyph_pos->y_offset  += _hb_16dot16_mul_trunc (y_scale, *(SHORT*)values++);
-    if (format & xAdvance)   glyph_pos->x_advance += _hb_16dot16_mul_trunc (x_scale, *(SHORT*)values++);
-    if (format & yAdvance)   glyph_pos->y_advance += _hb_16dot16_mul_trunc (y_scale, *(SHORT*)values++);
+    if (format & xPlacement) glyph_pos->x_offset  += _hb_16dot16_mul_round (x_scale, *(SHORT*)values++);
+    if (format & yPlacement) glyph_pos->y_offset  += _hb_16dot16_mul_round (y_scale, *(SHORT*)values++);
+    if (format & xAdvance)   glyph_pos->x_advance += _hb_16dot16_mul_round (x_scale, *(SHORT*)values++);
+    if (format & yAdvance)   glyph_pos->y_advance += _hb_16dot16_mul_round (y_scale, *(SHORT*)values++);
 
     x_ppem = context->font->x_ppem;
     y_ppem = context->font->y_ppem;
@@ -136,8 +136,8 @@ struct AnchorFormat1
   inline void get_anchor (hb_ot_layout_context_t *context, hb_codepoint_t glyph_id HB_GNUC_UNUSED,
 			  hb_position_t *x, hb_position_t *y) const
   {
-      *x = _hb_16dot16_mul_trunc (context->font->x_scale, xCoordinate);
-      *y = _hb_16dot16_mul_trunc (context->font->y_scale, yCoordinate);
+      *x = _hb_16dot16_mul_round (context->font->x_scale, xCoordinate);
+      *y = _hb_16dot16_mul_round (context->font->y_scale, yCoordinate);
   }
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
@@ -162,8 +162,8 @@ struct AnchorFormat2
   {
       /* TODO Contour
        * NOTE only adjust directions with nonzero ppem */
-      *x = _hb_16dot16_mul_trunc (context->font->x_scale, xCoordinate);
-      *y = _hb_16dot16_mul_trunc (context->font->y_scale, yCoordinate);
+      *x = _hb_16dot16_mul_round (context->font->x_scale, xCoordinate);
+      *y = _hb_16dot16_mul_round (context->font->y_scale, yCoordinate);
   }
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
@@ -187,8 +187,8 @@ struct AnchorFormat3
   inline void get_anchor (hb_ot_layout_context_t *context, hb_codepoint_t glyph_id HB_GNUC_UNUSED,
 			  hb_position_t *x, hb_position_t *y) const
   {
-      *x = _hb_16dot16_mul_trunc (context->font->x_scale, xCoordinate);
-      *y = _hb_16dot16_mul_trunc (context->font->y_scale, yCoordinate);
+      *x = _hb_16dot16_mul_round (context->font->x_scale, xCoordinate);
+      *y = _hb_16dot16_mul_round (context->font->y_scale, yCoordinate);
 
       /* pixel -> fractional pixel */
       if (context->font->x_ppem)
diff --git a/src/hb-private.h b/src/hb-private.h
index 854a208..7c48a87 100644
--- a/src/hb-private.h
+++ b/src/hb-private.h
@@ -235,7 +235,7 @@ _hb_popcount32 (uint32_t mask)
 
 
 /* Multiplies a 16dot16 value by another value, then truncates the result */
-#define _hb_16dot16_mul_trunc(A,B) ((int64_t) (A) * (B) / 0x10000)
+#define _hb_16dot16_mul_round(A,B) (((int64_t) (A) * (B) + 0x8000) / 0x10000)
 
 #include "hb-object-private.h"
 
commit 0e206de98621ed8a55824b42e9e6bf320f4c6cc8
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 19 02:29:04 2010 -0400

    Fix warnings

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 9977a6e..36e565f 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -118,7 +118,7 @@ struct Null <Type> \
 
 #if HB_DEBUG_SANITIZE
 #include <stdio.h>
-#define TRACE_SANITIZE_ARG_DEF	, unsigned int sanitize_depth
+#define TRACE_SANITIZE_ARG_DEF	, unsigned int sanitize_depth HB_GNUC_UNUSED
 #define TRACE_SANITIZE_ARG	, sanitize_depth + 1
 #define TRACE_SANITIZE_ARG_INIT	, 1
 #define TRACE_SANITIZE() \
diff --git a/src/hb-ot-layout-gdef-private.hh b/src/hb-ot-layout-gdef-private.hh
index a047cb2..d9b0005 100644
--- a/src/hb-ot-layout-gdef-private.hh
+++ b/src/hb-ot-layout-gdef-private.hh
@@ -133,7 +133,7 @@ struct CaretValueFormat3
 {
   friend struct CaretValue;
 
-  inline int get_caret_value (hb_ot_layout_context_t *context, hb_codepoint_t glyph_id) const
+  inline int get_caret_value (hb_ot_layout_context_t *context, hb_codepoint_t glyph_id HB_GNUC_UNUSED) const
   {
     /* TODO vertical */
     return context->font->x_scale * coordinate / 0x10000 +
diff --git a/src/hb-ot-layout-gpos-private.hh b/src/hb-ot-layout-gpos-private.hh
index 08f8151..e72e7b3 100644
--- a/src/hb-ot-layout-gpos-private.hh
+++ b/src/hb-ot-layout-gpos-private.hh
@@ -133,7 +133,7 @@ struct AnchorFormat1
   friend struct Anchor;
 
   private:
-  inline void get_anchor (hb_ot_layout_context_t *context, hb_codepoint_t glyph_id,
+  inline void get_anchor (hb_ot_layout_context_t *context, hb_codepoint_t glyph_id HB_GNUC_UNUSED,
 			  hb_position_t *x, hb_position_t *y) const
   {
       *x = _hb_16dot16_mul_trunc (context->font->x_scale, xCoordinate);
@@ -184,7 +184,7 @@ struct AnchorFormat3
   friend struct Anchor;
 
   private:
-  inline void get_anchor (hb_ot_layout_context_t *context, hb_codepoint_t glyph_id,
+  inline void get_anchor (hb_ot_layout_context_t *context, hb_codepoint_t glyph_id HB_GNUC_UNUSED,
 			  hb_position_t *x, hb_position_t *y) const
   {
       *x = _hb_16dot16_mul_trunc (context->font->x_scale, xCoordinate);
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index 4561aa3..ee9db67 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -37,7 +37,7 @@
 
 #if HB_DEBUG_APPLY
 #include <stdio.h>
-#define TRACE_APPLY_ARG_DEF	, unsigned int apply_depth
+#define TRACE_APPLY_ARG_DEF	, unsigned int apply_depth HB_GNUC_UNUSED
 #define TRACE_APPLY_ARG		, apply_depth + 1
 #define TRACE_APPLY_ARG_INIT	, 1
 #define TRACE_APPLY() \
@@ -60,7 +60,7 @@
 	hb_buffer_t    *buffer, \
 	unsigned int    context_length HB_GNUC_UNUSED, \
 	unsigned int    nesting_level_left HB_GNUC_UNUSED, \
-	unsigned int    lookup_flag, \
+	unsigned int    lookup_flag HB_GNUC_UNUSED, \
 	unsigned int    property HB_GNUC_UNUSED /* propety of first glyph */ \
 	TRACE_APPLY_ARG_DEF
 #define APPLY_ARG \
@@ -91,7 +91,7 @@ struct ContextFuncs
 };
 
 
-static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, char *data)
+static inline bool match_glyph (hb_codepoint_t glyph_id, const USHORT &value, char *data HB_GNUC_UNUSED)
 {
   return glyph_id == value;
 }
commit d5943407a4251cb947fbfc130c0facb2f6216bd6
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Apr 19 02:27:56 2010 -0400

    Fix debug build

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 836a98f..9977a6e 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -125,7 +125,7 @@ struct Null <Type> \
 	HB_STMT_START { \
 	    if (sanitize_depth < HB_DEBUG_SANITIZE) \
 		fprintf (stderr, "SANITIZE(%p) %-*d-> %s\n", \
-			 (CONST_CHARP (this) == NullPool) ? 0 : this, \
+			 (CONST_CHARP (this) == CONST_CHARP (&NullPool)) ? 0 : this, \
 			 sanitize_depth, sanitize_depth, \
 			 __PRETTY_FUNCTION__); \
 	} HB_STMT_END
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index 43f3d75..4561aa3 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -44,7 +44,7 @@
 	HB_STMT_START { \
 	    if (apply_depth < HB_DEBUG_APPLY) \
 		fprintf (stderr, "APPLY(%p) %-*d-> %s\n", \
-			 (CONST_CHARP (this) == NullPool) ? 0 : this, \
+			 (CONST_CHARP (this) == CONST_CHARP (&NullPool)) ? 0 : this, \
 			 apply_depth, apply_depth, \
 			 __PRETTY_FUNCTION__); \
 	} HB_STMT_END
commit 12b27ed91de0192deee4e9feffcaf4aca4c78113
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sat Mar 27 17:00:19 2010 -0400

    Fix leak when duplicating blob

diff --git a/src/hb-blob.c b/src/hb-blob.c
index b4eccb6..3afad8a 100644
--- a/src/hb-blob.c
+++ b/src/hb-blob.c
@@ -366,9 +366,11 @@ hb_blob_try_writable (hb_blob_t *blob)
       fprintf (stderr, "%p %s: dupped successfully -> %p\n", blob, __FUNCTION__, blob->data);
 #endif
       memcpy (new_data, blob->data, blob->length);
-      blob->data = new_data;
-      blob->mode = HB_MEMORY_MODE_WRITABLE;
       _hb_blob_destroy_user_data (blob);
+      blob->mode = HB_MEMORY_MODE_WRITABLE;
+      blob->data = new_data;
+      blob->destroy = free;
+      blob->user_data = new_data;
     }
   }
   else if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE)
commit 4b8487d83e0c10076a6c573cb3487790ce366607
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue Mar 16 03:46:17 2010 -0400

    Fix the mystery bug!
    
    A couple bugs joined forces to exhibit the mystery behavior of
    crashes / infinite loops on OS X / wrong kerning / invalid memory
    access.  Pooh!
    
    The bugs were involved:
    
      - Wrong pointer math with ValueRecord in PairPosFormat1
    
      - Fallout from avoiding flex arrays, code not correctly updated
        to remove sizeof() usage.
    
    We strictly never use sizeof() directly now.  And the PairPos code
    is cleaned up.  Should fix them all.  Bugs are:
    
      Bug 605655 - Pango 1.26.2 introduces kerning bug
      Bug 611229 - Pango reads from uninitialized memory
      Bug 593240 - (pangoosx) Crash / infinite loop with Mac OS X
    
    We were also doing wrong math converting Device adjustments to
    hb_position_t.  Fallout from FreeType days.  Should shift 16, not
    6.  Fixed that too.
    
    There's still another bug: we don't sanitize Device records
    referenced from value records.  Fixing that also.

diff --git a/src/hb-open-file-private.hh b/src/hb-open-file-private.hh
index 7b83813..e72a098 100644
--- a/src/hb-open-file-private.hh
+++ b/src/hb-open-file-private.hh
@@ -47,6 +47,8 @@ struct TTCHeader;
 
 typedef struct TableDirectory
 {
+  static inline unsigned int get_size () { return sizeof (TableDirectory); }
+
   inline bool sanitize (SANITIZE_ARG_DEF, const void *base) {
     TRACE_SANITIZE ();
     return SANITIZE_SELF () && SANITIZE (tag) &&
@@ -108,7 +110,7 @@ typedef struct OffsetTable
   public:
   inline bool sanitize (SANITIZE_ARG_DEF, const void *base) {
     TRACE_SANITIZE ();
-    if (!(SANITIZE_SELF () && SANITIZE_MEM (tableDir, sizeof (tableDir[0]) * numTables))) return false;
+    if (!(SANITIZE_SELF () && SANITIZE_MEM (tableDir, tableDir[0].get_size () * numTables))) return false;
     unsigned int count = numTables;
     for (unsigned int i = 0; i < count; i++)
       if (!SANITIZE_BASE (tableDir[i], base))
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 6dc3e30..836a98f 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -50,8 +50,8 @@
 #define CONST_NEXT(T,X)		(*(reinterpret_cast<const T *>(CONST_CHARP(&(X)) + (X).get_size ())))
 #define NEXT(T,X)		(*(reinterpret_cast<T *>(CHARP(&(X)) + (X).get_size ())))
 
-#define CONST_ARRAY_AFTER(T,X)	((reinterpret_cast<const T *>(CONST_CHARP(&(X)) + sizeof (X))))
-#define ARRAY_AFTER(T,X)	((reinterpret_cast<T *>(CHARP(&(X)) + sizeof (X))))
+#define CONST_ARRAY_AFTER(T,X)	((reinterpret_cast<const T *>(CONST_CHARP(&(X)) + X.get_size ())))
+#define ARRAY_AFTER(T,X)	((reinterpret_cast<T *>(CHARP(&(X)) + X.get_size ())))
 
 /*
  * Class features
@@ -363,6 +363,7 @@ struct Sanitizer
 #define DEFINE_INT_TYPE1(NAME, TYPE, BIG_ENDIAN, BYTES) \
   struct NAME \
   { \
+    static inline unsigned int get_size () { return BYTES; } \
     inline NAME& set (TYPE i) { BIG_ENDIAN##_put_unaligned(v, i); return *this; } \
     inline operator TYPE(void) const { return BIG_ENDIAN##_get_unaligned (v); } \
     inline bool operator== (NAME o) const { return BIG_ENDIAN##_cmp_unaligned (v, o.v); } \
@@ -425,7 +426,7 @@ struct CheckSum : ULONG
   static uint32_t CalcTableChecksum (ULONG *Table, uint32_t Length)
   {
     uint32_t Sum = 0L;
-    ULONG *EndPtr = Table+((Length+3) & ~3) / sizeof(ULONG);
+    ULONG *EndPtr = Table+((Length+3) & ~3) / ULONG::get_size ();
 
     while (Table < EndPtr)
       Sum += *Table++;
@@ -530,7 +531,7 @@ struct GenericArrayOf
     return const_array()[i];
   }
   inline unsigned int get_size () const
-  { return sizeof (len) + len * sizeof (Type); }
+  { return len.get_size () + len * Type::get_size (); }
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
@@ -633,7 +634,7 @@ struct HeadlessArrayOf
     return const_array()[i-1];
   }
   inline unsigned int get_size () const
-  { return sizeof (len) + (len ? len - 1 : 0) * sizeof (Type); }
+  { return len.get_size () + (len ? len - 1 : 0) * Type::get_size (); }
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 9a0abe5..85f228e 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -51,6 +51,8 @@
 template <typename Type>
 struct Record
 {
+  static inline unsigned int get_size () { return sizeof (Record<Type>); }
+
   inline bool sanitize (SANITIZE_ARG_DEF, const void *base) {
     TRACE_SANITIZE ();
     return SANITIZE (tag) && SANITIZE_BASE (offset, base);
@@ -353,6 +355,8 @@ struct CoverageRangeRecord
 {
   friend struct CoverageFormat2;
 
+  static inline unsigned int get_size () { return sizeof (CoverageRangeRecord); }
+
   private:
   inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
   {
@@ -471,6 +475,8 @@ struct ClassRangeRecord
 {
   friend struct ClassDefFormat2;
 
+  static inline unsigned int get_size () { return sizeof (ClassRangeRecord); }
+
   private:
   inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const
   {
@@ -588,8 +594,8 @@ struct Device
   inline unsigned int get_size () const
   {
     unsigned int f = deltaFormat;
-    if (HB_UNLIKELY (f < 1 || f > 3 || startSize > endSize)) return sizeof (*this);
-    return sizeof (*this) + ((endSize - startSize + (1 << (4 - f)) - 1) >> (4 - f));
+    if (HB_UNLIKELY (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::get_size ();
+    return 3 * USHORT::get_size () + ((endSize - startSize + (1 << (4 - f)) - 1) >> (4 - f));
   }
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
diff --git a/src/hb-ot-layout-gpos-private.hh b/src/hb-ot-layout-gpos-private.hh
index e0d8cb7..08f8151 100644
--- a/src/hb-ot-layout-gpos-private.hh
+++ b/src/hb-ot-layout-gpos-private.hh
@@ -57,7 +57,7 @@ struct ValueFormat : USHORT
   inline unsigned int get_len () const
   { return _hb_popcount32 ((unsigned int) *this); }
   inline unsigned int get_size () const
-  { return get_len () * sizeof (Value); }
+  { return get_len () * Value::get_size (); }
 
   void apply_value (hb_ot_layout_context_t *context,
 		    const char             *base,
@@ -112,16 +112,16 @@ struct ValueRecord {
     y_ppem = context->font->y_ppem;
     /* pixel -> fractional pixel */
     if (format & xPlaDevice) {
-      if (x_ppem) glyph_pos->x_offset  += (base+*(OffsetTo<Device>*)values++).get_delta (x_ppem) << 6; else values++;
+      if (x_ppem) glyph_pos->x_offset  += (base+*(OffsetTo<Device>*)values++).get_delta (x_ppem) << 16; else values++;
     }
     if (format & yPlaDevice) {
-      if (y_ppem) glyph_pos->y_offset  += (base+*(OffsetTo<Device>*)values++).get_delta (y_ppem) << 6; else values++;
+      if (y_ppem) glyph_pos->y_offset  += (base+*(OffsetTo<Device>*)values++).get_delta (y_ppem) << 16; else values++;
     }
     if (format & xAdvDevice) {
-      if (x_ppem) glyph_pos->x_advance += (base+*(OffsetTo<Device>*)values++).get_delta (x_ppem) << 6; else values++;
+      if (x_ppem) glyph_pos->x_advance += (base+*(OffsetTo<Device>*)values++).get_delta (x_ppem) << 16; else values++;
     }
     if (format & yAdvDevice) {
-      if (y_ppem) glyph_pos->y_advance += (base+*(OffsetTo<Device>*)values++).get_delta (y_ppem) << 6; else values++;
+      if (y_ppem) glyph_pos->y_advance += (base+*(OffsetTo<Device>*)values++).get_delta (y_ppem) << 16; else values++;
     }
   }
 };
@@ -190,10 +190,11 @@ struct AnchorFormat3
       *x = _hb_16dot16_mul_trunc (context->font->x_scale, xCoordinate);
       *y = _hb_16dot16_mul_trunc (context->font->y_scale, yCoordinate);
 
+      /* pixel -> fractional pixel */
       if (context->font->x_ppem)
-	*x += (this+xDeviceTable).get_delta (context->font->x_ppem) << 6;
+	*x += (this+xDeviceTable).get_delta (context->font->x_ppem) << 16;
       if (context->font->y_ppem)
-	*y += (this+yDeviceTable).get_delta (context->font->y_ppem) << 6;
+	*y += (this+yDeviceTable).get_delta (context->font->y_ppem) << 16;
   }
 
   inline bool sanitize (SANITIZE_ARG_DEF) {
@@ -262,7 +263,7 @@ struct AnchorMatrix
     TRACE_SANITIZE ();
     if (!SANITIZE_SELF ()) return false;
     unsigned int count = rows * cols;
-    if (!SANITIZE_ARRAY (matrix, sizeof (matrix[0]), count)) return false;
+    if (!SANITIZE_ARRAY (matrix, matrix[0].get_size (), count)) return false;
     for (unsigned int i = 0; i < count; i++)
       if (!SANITIZE_THIS (matrix[i])) return false;
     return true;
@@ -281,6 +282,8 @@ struct MarkRecord
 {
   friend struct MarkArray;
 
+  static inline unsigned int get_size () { return sizeof (MarkRecord); }
+
   inline bool sanitize (SANITIZE_ARG_DEF, const void *base) {
     TRACE_SANITIZE ();
     return SANITIZE_SELF () && SANITIZE_BASE (markAnchor, base);
@@ -391,7 +394,7 @@ struct SinglePosFormat2
       return false;
 
     valueFormat.apply_value (context, CONST_CHARP(this),
-			     values + index * valueFormat.get_len (),
+			     &values[index * valueFormat.get_len ()],
 			     CURPOSITION ());
 
     buffer->in_pos++;
@@ -472,7 +475,7 @@ struct PairSet
     TRACE_SANITIZE ();
     if (!SANITIZE_SELF ()) return false;
     unsigned int count = (1 + format_len) * len;
-    return SANITIZE_MEM (array, sizeof (array[0]) * count);
+    return SANITIZE_MEM (array, USHORT::get_size () * count);
   }
 
   private:
@@ -511,7 +514,7 @@ struct PairPosFormat1
 
     unsigned int len1 = valueFormat1.get_len ();
     unsigned int len2 = valueFormat2.get_len ();
-    unsigned int record_len = 1 + len1 + len2;
+    unsigned int record_size = USHORT::get_size () * (1 + len1 + len2);
 
     unsigned int count = pair_set.len;
     const PairValueRecord *record = pair_set.array;
@@ -519,14 +522,14 @@ struct PairPosFormat1
     {
       if (IN_GLYPH (j) == record->secondGlyph)
       {
-	valueFormat1.apply_value (context, CONST_CHARP(this), record->values, CURPOSITION ());
-	valueFormat2.apply_value (context, CONST_CHARP(this), record->values + len1, POSITION (j));
+	valueFormat1.apply_value (context, CONST_CHARP(this), &record->values[0], CURPOSITION ());
+	valueFormat2.apply_value (context, CONST_CHARP(this), &record->values[len1], POSITION (j));
 	if (len2)
 	  j++;
 	buffer->in_pos = j;
 	return true;
       }
-      record += record_len;
+      record = &CONST_CAST (PairValueRecord, *record, record_size);
     }
 
     return false;
@@ -589,7 +592,7 @@ struct PairPosFormat2
     if (HB_UNLIKELY (klass1 >= class1Count || klass2 >= class2Count))
       return false;
 
-    const Value *v = values + record_len * (klass1 * class2Count + klass2);
+    const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
     valueFormat1.apply_value (context, CONST_CHARP(this), v, CURPOSITION ());
     valueFormat2.apply_value (context, CONST_CHARP(this), v + len1, POSITION (j));
 
@@ -605,7 +608,7 @@ struct PairPosFormat2
     if (!(SANITIZE_SELF () && SANITIZE_THIS (coverage) &&
 	  SANITIZE_THIS2 (classDef1, classDef2))) return false;
 
-    unsigned int record_size =valueFormat1.get_size () + valueFormat2.get_size ();
+    unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
     unsigned int len = class1Count * class2Count;
     return SANITIZE_ARRAY (values, record_size, len);
   }
@@ -675,6 +678,8 @@ struct PairPos
 
 struct EntryExitRecord
 {
+  static inline unsigned int get_size () { return sizeof (EntryExitRecord); }
+
   inline bool sanitize (SANITIZE_ARG_DEF, const void *base) {
     TRACE_SANITIZE ();
     return SANITIZE_BASE2 (entryAnchor, exitAnchor, base);
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index 41665a7..43f3d75 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -195,7 +195,8 @@ static inline bool match_lookahead (APPLY_ARG_DEF,
 
 struct LookupRecord
 {
-  public:
+  static inline unsigned int get_size () { return sizeof (LookupRecord); }
+
   inline bool sanitize (SANITIZE_ARG_DEF) {
     TRACE_SANITIZE ();
     return SANITIZE_SELF ();
@@ -298,7 +299,7 @@ struct Rule
   inline bool apply (APPLY_ARG_DEF, ContextLookupContext &lookup_context) const
   {
     TRACE_APPLY ();
-    const LookupRecord *lookupRecord = &CONST_CAST (LookupRecord, input, sizeof (input[0]) * (inputCount ? inputCount - 1 : 0));
+    const LookupRecord *lookupRecord = &CONST_CAST (LookupRecord, input, input[0].get_size () * (inputCount ? inputCount - 1 : 0));
     return context_lookup (APPLY_ARG,
 			   inputCount, input,
 			   lookupCount, lookupRecord,
@@ -310,8 +311,8 @@ struct Rule
     TRACE_SANITIZE ();
     if (!(SANITIZE (inputCount) && SANITIZE (lookupCount))) return false;
     return SANITIZE_MEM (input,
-			 sizeof (input[0]) * inputCount +
-			 sizeof (lookupRecordX[0]) * lookupCount);
+			 input[0].get_size () * inputCount +
+			 lookupRecordX[0].get_size () * lookupCount);
   }
 
   private:
@@ -447,7 +448,7 @@ struct ContextFormat3
     if (HB_LIKELY (index == NOT_COVERED))
       return false;
 
-    const LookupRecord *lookupRecord = &CONST_CAST(LookupRecord, coverage, sizeof (coverage[0]) * glyphCount);
+    const LookupRecord *lookupRecord = &CONST_CAST(LookupRecord, coverage, coverage[0].get_size () * glyphCount);
     struct ContextLookupContext lookup_context = {
       {match_coverage, apply_func},
       DECONST_CHARP(this)
@@ -464,8 +465,8 @@ struct ContextFormat3
     unsigned int count = glyphCount;
     for (unsigned int i = 0; i < count; i++)
       if (!SANITIZE_THIS (coverage[i])) return false;
-    LookupRecord *lookupRecord = &CAST(LookupRecord, coverage, sizeof (coverage[0]) * glyphCount);
-    return SANITIZE_MEM (lookupRecord, sizeof (lookupRecord[0]) * lookupCount);
+    LookupRecord *lookupRecord = &CAST(LookupRecord, coverage, coverage[0].get_size () * glyphCount);
+    return SANITIZE_MEM (lookupRecord, lookupRecord[0].get_size () * lookupCount);
   }
 
   private:



More information about the HarfBuzz mailing list