From 29faebe911a13916aa3d737e93d38deedc53567f Mon Sep 17 00:00:00 2001
From: Behdad Esfahbod <behdad@behdad.org>
Date: Thu, 13 Sep 2018 18:45:35 +0200
Subject: [PATCH] Allow Offset<>'s that have no 0==null

---
 src/hb-open-type.hh | 43 +++++++++++++++++++++----------------------
 1 file changed, 21 insertions(+), 22 deletions(-)

diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh
index 973dc5e11..b10d33b16 100644
--- a/src/hb-open-type.hh
+++ b/src/hb-open-type.hh
@@ -155,10 +155,10 @@ struct Index : HBUINT16 {
 DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
 
 /* Offset, Null offset = 0 */
-template <typename Type>
+template <typename Type, bool has_null=true>
 struct Offset : Type
 {
-  inline bool is_null (void) const { return 0 == *this; }
+  inline bool is_null (void) const { return has_null && 0 == *this; }
 
   inline void *serialize (hb_serialize_context_t *c, const void *base)
   {
@@ -226,20 +226,18 @@ struct FixedVersion
  * Use: (base+offset)
  */
 
-template <typename Type, typename OffsetType=HBUINT16>
-struct OffsetTo : Offset<OffsetType>
+template <typename Type, typename OffsetType=HBUINT16, bool has_null=true>
+struct OffsetTo : Offset<OffsetType, has_null>
 {
   inline const Type& operator () (const void *base) const
   {
-    unsigned int offset = *this;
-    if (unlikely (!offset)) return Null(Type);
-    return StructAtOffset<const Type> (base, offset);
+    if (unlikely (this->is_null ())) return Null(Type);
+    return StructAtOffset<const Type> (base, *this);
   }
   inline Type& operator () (void *base) const
   {
-    unsigned int offset = *this;
-    if (unlikely (!offset)) return Crap(Type);
-    return StructAtOffset<Type> (base, offset);
+    if (unlikely (this->is_null ())) return Crap(Type);
+    return StructAtOffset<Type> (base, *this);
   }
 
   inline Type& serialize (hb_serialize_context_t *c, const void *base)
@@ -264,9 +262,8 @@ struct OffsetTo : Offset<OffsetType>
   {
     TRACE_SANITIZE (this);
     if (unlikely (!c->check_struct (this))) return_trace (false);
-    unsigned int offset = *this;
-    if (unlikely (!offset)) return_trace (true);
-    if (unlikely (!c->check_range (base, offset))) return_trace (false);
+    if (unlikely (this->is_null ())) return_trace (true);
+    if (unlikely (!c->check_range (base, *this))) return_trace (false);
     return_trace (true);
   }
 
@@ -274,7 +271,7 @@ struct OffsetTo : Offset<OffsetType>
   {
     TRACE_SANITIZE (this);
     return_trace (sanitize_shallow (c, base) &&
-		  (!*this ||
+		  (this->is_null () ||
 		   StructAtOffset<Type> (base, *this).sanitize (c) ||
 		   neuter (c)));
   }
@@ -283,7 +280,7 @@ struct OffsetTo : Offset<OffsetType>
   {
     TRACE_SANITIZE (this);
     return_trace (sanitize_shallow (c, base) &&
-		  (!*this ||
+		  (this->is_null () ||
 		   StructAtOffset<Type> (base, *this).sanitize (c, d1) ||
 		   neuter (c)));
   }
@@ -292,7 +289,7 @@ struct OffsetTo : Offset<OffsetType>
   {
     TRACE_SANITIZE (this);
     return_trace (sanitize_shallow (c, base) &&
-		  (!*this ||
+		  (this->is_null () ||
 		   StructAtOffset<Type> (base, *this).sanitize (c, d1, d2) ||
 		   neuter (c)));
   }
@@ -301,22 +298,24 @@ struct OffsetTo : Offset<OffsetType>
   {
     TRACE_SANITIZE (this);
     return_trace (sanitize_shallow (c, base) &&
-		  (!*this ||
+		  (this->is_null () ||
 		   StructAtOffset<Type> (base, *this).sanitize (c, d1, d2, d3) ||
 		   neuter (c)));
   }
 
   /* Set the offset to Null */
-  inline bool neuter (hb_sanitize_context_t *c) const {
+  inline bool neuter (hb_sanitize_context_t *c) const
+  {
+    if (!has_null) return false;
     return c->try_set (this, 0);
   }
   DEFINE_SIZE_STATIC (sizeof(OffsetType));
 };
 template <typename Type> struct LOffsetTo : OffsetTo<Type, HBUINT32> {};
-template <typename Base, typename OffsetType, typename Type>
-static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType> &offset) { return offset (base); }
-template <typename Base, typename OffsetType, typename Type>
-static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType> &offset) { return offset (base); }
+template <typename Base, typename OffsetType, bool has_null, typename Type>
+static inline const Type& operator + (const Base &base, const OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
+template <typename Base, typename OffsetType, bool has_null, typename Type>
+static inline Type& operator + (Base &base, OffsetTo<Type, OffsetType, has_null> &offset) { return offset (base); }
 
 
 /*