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

Behdad Esfahbod behdad at kemper.freedesktop.org
Mon Aug 6 13:39:37 UTC 2018


 src/Makefile.sources                       |    2 
 src/hb-blob-private.hh                     |    1 
 src/hb-blob.cc                             |   29 +-
 src/hb-buffer-private.hh                   |    4 
 src/hb-buffer.cc                           |   44 +--
 src/hb-dsalgs.hh                           |  340 +++--------------------------
 src/hb-face-private.hh                     |    6 
 src/hb-face.cc                             |    5 
 src/hb-font-private.hh                     |   10 
 src/hb-font.cc                             |   66 ++---
 src/hb-machinery-private.hh                |    6 
 src/hb-null.hh                             |  106 +++++++++
 src/hb-object-private.hh                   |  108 ++++++++-
 src/hb-open-type-private.hh                |    3 
 src/hb-ot-glyf-table.hh                    |    6 
 src/hb-ot-head-table.hh                    |    4 
 src/hb-ot-layout-base-table.hh             |  225 ++++++++-----------
 src/hb-ot-layout-common-private.hh         |    5 
 src/hb-ot-layout-gdef-table.hh             |    1 
 src/hb-ot-layout-gsubgpos-private.hh       |    1 
 src/hb-ot-layout-private.hh                |    4 
 src/hb-ot-layout.cc                        |    6 
 src/hb-ot-math-table.hh                    |    2 
 src/hb-ot-math.cc                          |    2 
 src/hb-ot-shape-complex-arabic-fallback.hh |   12 -
 src/hb-ot-var-fvar-table.hh                |    2 
 src/hb-ot-var.cc                           |    2 
 src/hb-private.hh                          |  123 ----------
 src/hb-shape-plan-private.hh               |    1 
 src/hb-shape-plan.cc                       |   50 ++--
 src/hb-static.cc                           |   10 
 src/hb-subset.cc                           |    2 
 src/hb-unicode-private.hh                  |    7 
 src/hb-unicode.cc                          |    5 
 src/hb-vector-private.hh                   |  238 ++++++++++++++++++++
 src/main.cc                                |    2 
 36 files changed, 763 insertions(+), 677 deletions(-)

New commits:
commit b912fbea17c50e229977345012227810ed7641e9
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Aug 6 06:30:12 2018 -0700

    Remove most uses of direct comparison to Null objects

diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh
index ce6ee1e2..bcf89e46 100644
--- a/src/hb-ot-glyf-table.hh
+++ b/src/hb-ot-glyf-table.hh
@@ -238,9 +238,9 @@ struct glyf
 
       hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (face);
       const head *head_table = head_blob->as<head> ();
-      if (head_table == &Null(head) || (unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
+      if (head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
       {
-	/* head table is not present, or in an unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
+	/* Unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
 	hb_blob_destroy (head_blob);
 	return;
       }
@@ -270,7 +270,7 @@ struct glyf
     inline bool get_composite (hb_codepoint_t glyph,
 			       CompositeGlyphHeader::Iterator *composite /* OUT */) const
     {
-      if (this->glyf_table == &Null(glyf) || !num_glyphs)
+      if (unlikely (!num_glyphs))
 	return false;
 
       unsigned int start_offset, end_offset;
diff --git a/src/hb-ot-head-table.hh b/src/hb-ot-head-table.hh
index 965e30a0..fded120b 100644
--- a/src/hb-ot-head-table.hh
+++ b/src/hb-ot-head-table.hh
@@ -141,8 +141,8 @@ struct head
 					 * -1: Only strongly right to left;
 					 * -2: Like -1 but also contains neutrals. */
   public:
-  HBINT16	indexToLocFormat;	/* 0 for short offsets, 1 for long. */
-  HBINT16	glyphDataFormat;	/* 0 for current format. */
+  HBUINT16	indexToLocFormat;	/* 0 for short offsets, 1 for long. */
+  HBUINT16	glyphDataFormat;	/* 0 for current format. */
 
   DEFINE_SIZE_STATIC (54);
 };
diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh
index 60a8d3ad..d2b41a8e 100644
--- a/src/hb-ot-layout-gdef-table.hh
+++ b/src/hb-ot-layout-gdef-table.hh
@@ -349,6 +349,7 @@ struct GDEF
     ComponentGlyph	= 4
   };
 
+  inline bool has_data (void) const { return version.to_int () != 0; }
   inline bool has_glyph_classes (void) const { return glyphClassDef != 0; }
   inline unsigned int get_glyph_class (hb_codepoint_t glyph) const
   { return (this+glyphClassDef).get_class (glyph); }
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index f3566ab1..40a2fc4c 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -2320,6 +2320,7 @@ struct Extension
 
 struct GSUBGPOS
 {
+  inline bool has_data (void) const { return version.to_int () != 0; }
   inline unsigned int get_script_count (void) const
   { return (this+scriptList).len; }
   inline const Tag& get_script_tag (unsigned int i) const
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index bfde063d..09ff0e6c 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -904,7 +904,7 @@ hb_ot_layout_feature_with_variations_get_lookups (hb_face_t    *face,
 hb_bool_t
 hb_ot_layout_has_substitution (hb_face_t *face)
 {
-  return &_get_gsub (face) != &Null(OT::GSUB);
+  return _get_gsub (face).has_data ();
 }
 
 /**
@@ -1006,7 +1006,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t      *face,
 hb_bool_t
 hb_ot_layout_has_positioning (hb_face_t *face)
 {
-  return &_get_gpos (face) != &Null(OT::GPOS);
+  return _get_gpos (face).has_data ();
 }
 
 void
@@ -1341,5 +1341,5 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
 // hb_bool_t
 // hb_ot_base_has_data (hb_face_t *face)
 // {
-//   return &_get_base (face) != &Null(OT::BASE);
+//   return _get_base (face).has_data ();
 // }
diff --git a/src/hb-ot-math-table.hh b/src/hb-ot-math-table.hh
index 5fef2d28..2dd71458 100644
--- a/src/hb-ot-math-table.hh
+++ b/src/hb-ot-math-table.hh
@@ -686,6 +686,8 @@ struct MATH
 {
   static const hb_tag_t tableTag	= HB_OT_TAG_MATH;
 
+  inline bool has_data (void) const { return version.to_int () != 0; }
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
diff --git a/src/hb-ot-math.cc b/src/hb-ot-math.cc
index e7cb4652..66ce207a 100644
--- a/src/hb-ot-math.cc
+++ b/src/hb-ot-math.cc
@@ -55,7 +55,7 @@ _get_math (hb_face_t *face)
 hb_bool_t
 hb_ot_math_has_data (hb_face_t *face)
 {
-  return &_get_math (face) != &Null(OT::MATH);
+  return _get_math (face).has_data ();
 }
 
 /**
diff --git a/src/hb-ot-shape-complex-arabic-fallback.hh b/src/hb-ot-shape-complex-arabic-fallback.hh
index 2803febb..a55511aa 100644
--- a/src/hb-ot-shape-complex-arabic-fallback.hh
+++ b/src/hb-ot-shape-complex-arabic-fallback.hh
@@ -313,6 +313,7 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
   if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font))
     return fallback_plan;
 
+  assert (fallback_plan->num_lookups == 0);
   free (fallback_plan);
   return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t));
 }
@@ -320,7 +321,7 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
 static void
 arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
 {
-  if (!fallback_plan || fallback_plan == &Null(arabic_fallback_plan_t))
+  if (!fallback_plan || fallback_plan->num_lookups == 0)
     return;
 
   for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
diff --git a/src/hb-ot-var-fvar-table.hh b/src/hb-ot-var-fvar-table.hh
index 82d29968..101476ed 100644
--- a/src/hb-ot-var-fvar-table.hh
+++ b/src/hb-ot-var-fvar-table.hh
@@ -87,6 +87,8 @@ struct fvar
 {
   static const hb_tag_t tableTag	= HB_OT_TAG_fvar;
 
+  inline bool has_data (void) const { return version.to_int () != 0; }
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
diff --git a/src/hb-ot-var.cc b/src/hb-ot-var.cc
index 366860d5..6081ddfc 100644
--- a/src/hb-ot-var.cc
+++ b/src/hb-ot-var.cc
@@ -65,7 +65,7 @@ _get_avar (hb_face_t *face)
 hb_bool_t
 hb_ot_var_has_data (hb_face_t *face)
 {
-  return &_get_fvar (face) != &Null(OT::fvar);
+  return _get_fvar (face).has_data ();
 }
 
 /**
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 9e8e2aff..411c6b86 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -83,7 +83,7 @@ _subset (hb_subset_plan_t *plan)
 
   hb_tag_t tag = TableType::tableTag;
   hb_bool_t result = false;
-  if (table != &Null(TableType))
+  if (source_blob->data)
   {
     result = table->subset(plan);
   } else {
diff --git a/src/main.cc b/src/main.cc
index c6e05fc3..98a1320b 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -53,7 +53,7 @@ main (int argc, char **argv)
 
   hb_blob_t *font_blob = hb_sanitize_context_t().sanitize_blob<OpenTypeFontFile> (blob);
   const OpenTypeFontFile* sanitized = font_blob->as<OpenTypeFontFile> ();
-  if (sanitized == &Null(OpenTypeFontFile))
+  if (!font_blob->data)
   {
     printf ("Sanitization of the file wasn't successful. Exit");
     return 1;
commit 3506672ce9d8685ce4e113716b0d06adbc7981b7
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Aug 6 06:17:48 2018 -0700

    Port _nil objects to Null() machinery
    
    Finally, unified!

diff --git a/src/hb-blob-private.hh b/src/hb-blob-private.hh
index 93fbc2d5..49ad68ec 100644
--- a/src/hb-blob-private.hh
+++ b/src/hb-blob-private.hh
@@ -76,6 +76,7 @@ struct hb_blob_t
   void *user_data;
   hb_destroy_func_t destroy;
 };
+DECLARE_NULL_INSTANCE (hb_blob_t);
 
 
 #endif /* HB_BLOB_PRIVATE_HH */
diff --git a/src/hb-blob.cc b/src/hb-blob.cc
index 5bab1abb..25c3e05a 100644
--- a/src/hb-blob.cc
+++ b/src/hb-blob.cc
@@ -45,6 +45,20 @@
 #include <stdlib.h>
 
 
+DEFINE_NULL_INSTANCE (hb_blob_t) =
+{
+  HB_OBJECT_HEADER_STATIC,
+
+  true, /* immutable */
+
+  nullptr, /* data */
+  0, /* length */
+  HB_MEMORY_MODE_READONLY, /* mode */
+
+  nullptr, /* user_data */
+  nullptr  /* destroy */
+};
+
 /**
  * hb_blob_create: (skip)
  * @data: Pointer to blob data.
@@ -182,20 +196,7 @@ hb_blob_copy_writable_or_fail (hb_blob_t *blob)
 hb_blob_t *
 hb_blob_get_empty (void)
 {
-  static const hb_blob_t _hb_blob_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    true, /* immutable */
-
-    nullptr, /* data */
-    0, /* length */
-    HB_MEMORY_MODE_READONLY, /* mode */
-
-    nullptr, /* user_data */
-    nullptr  /* destroy */
-  };
-
-  return const_cast<hb_blob_t *> (&_hb_blob_nil);
+  return const_cast<hb_blob_t *> (&Null(hb_blob_t));
 }
 
 /**
diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index f4581407..a6c4b696 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -83,7 +83,8 @@ HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);
  * hb_buffer_t
  */
 
-struct hb_buffer_t {
+struct hb_buffer_t
+{
   hb_object_header_t header;
   ASSERT_POD ();
 
@@ -352,6 +353,7 @@ struct hb_buffer_t {
       info[i].mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
   }
 };
+DECLARE_NULL_INSTANCE (hb_buffer_t);
 
 
 /* Loop over clusters. Duplicated in foreach_syllable(). */
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index d04e1e80..e79b45ae 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -701,6 +701,28 @@ hb_buffer_t::guess_segment_properties (void)
 
 /* Public API */
 
+DEFINE_NULL_INSTANCE (hb_buffer_t) =
+{
+  HB_OBJECT_HEADER_STATIC,
+
+  const_cast<hb_unicode_funcs_t *> (&_hb_Null_hb_unicode_funcs_t),
+  HB_BUFFER_FLAG_DEFAULT,
+  HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
+  HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
+  HB_BUFFER_SCRATCH_FLAG_DEFAULT,
+  HB_BUFFER_MAX_LEN_DEFAULT,
+  HB_BUFFER_MAX_OPS_DEFAULT,
+
+  HB_BUFFER_CONTENT_TYPE_INVALID,
+  HB_SEGMENT_PROPERTIES_DEFAULT,
+  false, /* successful */
+  true, /* have_output */
+  true  /* have_positions */
+
+  /* Zero is good enough for everything else. */
+};
+
+
 /**
  * hb_buffer_create: (Xconstructor)
  *
@@ -743,27 +765,7 @@ hb_buffer_create (void)
 hb_buffer_t *
 hb_buffer_get_empty (void)
 {
-  static const hb_buffer_t _hb_buffer_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil),
-    HB_BUFFER_FLAG_DEFAULT,
-    HB_BUFFER_CLUSTER_LEVEL_DEFAULT,
-    HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT,
-    HB_BUFFER_SCRATCH_FLAG_DEFAULT,
-    HB_BUFFER_MAX_LEN_DEFAULT,
-    HB_BUFFER_MAX_OPS_DEFAULT,
-
-    HB_BUFFER_CONTENT_TYPE_INVALID,
-    HB_SEGMENT_PROPERTIES_DEFAULT,
-    false, /* successful */
-    true, /* have_output */
-    true  /* have_positions */
-
-    /* Zero is good enough for everything else. */
-  };
-
-  return const_cast<hb_buffer_t *> (&_hb_buffer_nil);
+  return const_cast<hb_buffer_t *> (&Null(hb_buffer_t));
 }
 
 /**
diff --git a/src/hb-face-private.hh b/src/hb-face-private.hh
index 73a68461..a4b2cd36 100644
--- a/src/hb-face-private.hh
+++ b/src/hb-face-private.hh
@@ -39,7 +39,8 @@
  * hb_face_t
  */
 
-struct hb_face_t {
+struct hb_face_t
+{
   hb_object_header_t header;
   ASSERT_POD ();
 
@@ -94,8 +95,7 @@ struct hb_face_t {
   HB_INTERNAL void load_upem (void) const;
   HB_INTERNAL void load_num_glyphs (void) const;
 };
-
-extern HB_INTERNAL const hb_face_t _hb_face_nil;
+DECLARE_NULL_INSTANCE (hb_face_t);
 
 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, face);
diff --git a/src/hb-face.cc b/src/hb-face.cc
index 9d17c4a5..e1492756 100644
--- a/src/hb-face.cc
+++ b/src/hb-face.cc
@@ -63,7 +63,8 @@ hb_face_count (hb_blob_t *blob)
  * hb_face_t
  */
 
-const hb_face_t _hb_face_nil = {
+DEFINE_NULL_INSTANCE (hb_face_t) =
+{
   HB_OBJECT_HEADER_STATIC,
 
   true, /* immutable */
@@ -215,7 +216,7 @@ hb_face_create (hb_blob_t    *blob,
 hb_face_t *
 hb_face_get_empty (void)
 {
-  return const_cast<hb_face_t *> (&_hb_face_nil);
+  return const_cast<hb_face_t *> (&Null(hb_face_t));
 }
 
 
diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index 9f657db6..4950e0bb 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -35,7 +35,6 @@
 #include "hb-shaper-private.hh"
 
 
-
 /*
  * hb_font_funcs_t
  */
@@ -57,7 +56,8 @@
   HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
   /* ^--- Add new callbacks here */
 
-struct hb_font_funcs_t {
+struct hb_font_funcs_t
+{
   hb_object_header_t header;
   ASSERT_POD ();
 
@@ -89,14 +89,15 @@ struct hb_font_funcs_t {
 		]) (void);
   } get;
 };
-
+DECLARE_NULL_INSTANCE (hb_font_funcs_t);
 
 
 /*
  * hb_font_t
  */
 
-struct hb_font_t {
+struct hb_font_t
+{
   hb_object_header_t header;
   ASSERT_POD ();
 
@@ -553,6 +554,7 @@ struct hb_font_t {
     return (float) v * scale / face->get_upem ();
   }
 };
+DECLARE_NULL_INSTANCE (hb_font_t);
 
 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
 #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, font);
diff --git a/src/hb-font.cc b/src/hb-font.cc
index 4d62b9e9..7d8de6d0 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -341,7 +341,8 @@ hb_font_get_glyph_from_name_parent (hb_font_t *font,
   return font->parent->get_glyph_from_name (name, len, glyph);
 }
 
-static const hb_font_funcs_t _hb_font_funcs_nil = {
+DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
+{
   HB_OBJECT_HEADER_STATIC,
 
   true, /* immutable */
@@ -364,6 +365,7 @@ static const hb_font_funcs_t _hb_font_funcs_nil = {
     }
   }
 };
+
 static const hb_font_funcs_t _hb_font_funcs_parent = {
   HB_OBJECT_HEADER_STATIC,
 
@@ -1100,6 +1102,37 @@ hb_font_glyph_from_string (hb_font_t *font,
  * hb_font_t
  */
 
+DEFINE_NULL_INSTANCE (hb_font_t) =
+{
+  HB_OBJECT_HEADER_STATIC,
+
+  true, /* immutable */
+
+  nullptr, /* parent */
+  const_cast<hb_face_t *> (&_hb_Null_hb_face_t),
+
+  1000, /* x_scale */
+  1000, /* y_scale */
+
+  0, /* x_ppem */
+  0, /* y_ppem */
+  0, /* ptem */
+
+  0, /* num_coords */
+  nullptr, /* coords */
+
+  const_cast<hb_font_funcs_t *> (&_hb_Null_hb_font_funcs_t), /* klass */
+  nullptr, /* user_data */
+  nullptr, /* destroy */
+
+  {
+#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+  }
+};
+
+
 /**
  * hb_font_create: (Xconstructor)
  * @face: a face.
@@ -1187,36 +1220,7 @@ hb_font_create_sub_font (hb_font_t *parent)
 hb_font_t *
 hb_font_get_empty (void)
 {
-  static const hb_font_t _hb_font_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    true, /* immutable */
-
-    nullptr, /* parent */
-    const_cast<hb_face_t *> (&_hb_face_nil),
-
-    1000, /* x_scale */
-    1000, /* y_scale */
-
-    0, /* x_ppem */
-    0, /* y_ppem */
-    0, /* ptem */
-
-    0, /* num_coords */
-    nullptr, /* coords */
-
-    const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil), /* klass */
-    nullptr, /* user_data */
-    nullptr, /* destroy */
-
-    {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-    }
-  };
-
-  return const_cast<hb_font_t *> (&_hb_font_nil);
+  return const_cast<hb_font_t *> (&Null(hb_font_t));
 }
 
 /**
diff --git a/src/hb-null.hh b/src/hb-null.hh
index 5ab3289e..91efee64 100644
--- a/src/hb-null.hh
+++ b/src/hb-null.hh
@@ -59,10 +59,19 @@ template <> \
 } \
 namespace Namespace { \
 static_assert (true, "Just so we take semicolon after.")
-
 #define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
 const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size]
 
+/* Specializaitons for arbitrary-content Null objects expressed as struct initializer. */
+#define DECLARE_NULL_INSTANCE(Type) \
+extern HB_INTERNAL const Type _hb_Null_##Type; \
+template <> \
+/*static*/ inline const Type& Null<Type> (void) { \
+  return _hb_Null_##Type; \
+} \
+static_assert (true, "Just so we take semicolon after.")
+#define DEFINE_NULL_INSTANCE(Type) \
+const Type _hb_Null_##Type
 
 /* Global writable pool.  Enlarge as necessary. */
 
diff --git a/src/hb-ot-shape-complex-arabic-fallback.hh b/src/hb-ot-shape-complex-arabic-fallback.hh
index 40c5015c..2803febb 100644
--- a/src/hb-ot-shape-complex-arabic-fallback.hh
+++ b/src/hb-ot-shape-complex-arabic-fallback.hh
@@ -205,8 +205,6 @@ struct arabic_fallback_plan_t
   hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
 };
 
-static const arabic_fallback_plan_t arabic_fallback_plan_nil = {};
-
 #if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_WIN1256)
 #define HB_WITH_WIN1256
 #endif
@@ -215,7 +213,8 @@ static const arabic_fallback_plan_t arabic_fallback_plan_nil = {};
 #include "hb-ot-shape-complex-arabic-win1256.hh"
 #endif
 
-struct ManifestLookup {
+struct ManifestLookup
+{
   OT::Tag tag;
   OT::OffsetTo<OT::SubstLookup> lookupOffset;
 };
@@ -299,7 +298,7 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
 {
   arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) calloc (1, sizeof (arabic_fallback_plan_t));
   if (unlikely (!fallback_plan))
-    return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
+    return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t));
 
   fallback_plan->num_lookups = 0;
   fallback_plan->free_lookups = false;
@@ -315,13 +314,13 @@ arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
     return fallback_plan;
 
   free (fallback_plan);
-  return const_cast<arabic_fallback_plan_t *> (&arabic_fallback_plan_nil);
+  return const_cast<arabic_fallback_plan_t *> (&Null(arabic_fallback_plan_t));
 }
 
 static void
 arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
 {
-  if (!fallback_plan || fallback_plan == &arabic_fallback_plan_nil)
+  if (!fallback_plan || fallback_plan == &Null(arabic_fallback_plan_t))
     return;
 
   for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
diff --git a/src/hb-shape-plan-private.hh b/src/hb-shape-plan-private.hh
index c2c4987e..7d020ff1 100644
--- a/src/hb-shape-plan-private.hh
+++ b/src/hb-shape-plan-private.hh
@@ -51,6 +51,7 @@ struct hb_shape_plan_t
 
   struct hb_shaper_data_t shaper_data;
 };
+DECLARE_NULL_INSTANCE (hb_shape_plan_t);
 
 #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS \
 	, const hb_feature_t *user_features \
diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc
index 37ff1a6e..cc1834c4 100644
--- a/src/hb-shape-plan.cc
+++ b/src/hb-shape-plan.cc
@@ -88,6 +88,31 @@ hb_shape_plan_plan (hb_shape_plan_t    *shape_plan,
  * hb_shape_plan_t
  */
 
+DEFINE_NULL_INSTANCE (hb_shape_plan_t) =
+{
+  HB_OBJECT_HEADER_STATIC,
+
+  true, /* default_shaper_list */
+  nullptr, /* face */
+  HB_SEGMENT_PROPERTIES_DEFAULT, /* props */
+
+  nullptr, /* shaper_func */
+  nullptr, /* shaper_name */
+
+  nullptr, /* user_features */
+  0,    /* num_user_featurs */
+
+  nullptr, /* coords */
+  0,    /* num_coords */
+
+  {
+#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+  }
+};
+
+
 /**
  * hb_shape_plan_create: (Xconstructor)
  * @face: 
@@ -188,30 +213,7 @@ hb_shape_plan_create2 (hb_face_t                     *face,
 hb_shape_plan_t *
 hb_shape_plan_get_empty (void)
 {
-  static const hb_shape_plan_t _hb_shape_plan_nil = {
-    HB_OBJECT_HEADER_STATIC,
-
-    true, /* default_shaper_list */
-    nullptr, /* face */
-    HB_SEGMENT_PROPERTIES_DEFAULT, /* props */
-
-    nullptr, /* shaper_func */
-    nullptr, /* shaper_name */
-
-    nullptr, /* user_features */
-    0,    /* num_user_featurs */
-
-    nullptr, /* coords */
-    0,    /* num_coords */
-
-    {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID,
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-    }
-  };
-
-  return const_cast<hb_shape_plan_t *> (&_hb_shape_plan_nil);
+  return const_cast<hb_shape_plan_t *> (&Null(hb_shape_plan_t));
 }
 
 /**
diff --git a/src/hb-unicode-private.hh b/src/hb-unicode-private.hh
index b2c203d2..fb16ba43 100644
--- a/src/hb-unicode-private.hh
+++ b/src/hb-unicode-private.hh
@@ -60,7 +60,8 @@ extern HB_INTERNAL const uint8_t _hb_modified_combining_class[256];
   HB_UNICODE_FUNC_IMPLEMENT (hb_script_t, script) \
   /* ^--- Add new simple callbacks here */
 
-struct hb_unicode_funcs_t {
+struct hb_unicode_funcs_t
+{
   hb_object_header_t header;
   ASSERT_POD ();
 
@@ -263,9 +264,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
 #undef HB_UNICODE_FUNC_IMPLEMENT
   } destroy;
 };
-
-
-extern HB_INTERNAL const hb_unicode_funcs_t _hb_unicode_funcs_nil;
+DECLARE_NULL_INSTANCE (hb_unicode_funcs_t);
 
 
 /* Modified combining marks */
diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc
index 2d16c2e3..8cb41723 100644
--- a/src/hb-unicode.cc
+++ b/src/hb-unicode.cc
@@ -185,7 +185,8 @@ hb_unicode_funcs_create (hb_unicode_funcs_t *parent)
 }
 
 
-const hb_unicode_funcs_t _hb_unicode_funcs_nil = {
+DEFINE_NULL_INSTANCE (hb_unicode_funcs_t) =
+{
   HB_OBJECT_HEADER_STATIC,
 
   nullptr, /* parent */
@@ -209,7 +210,7 @@ const hb_unicode_funcs_t _hb_unicode_funcs_nil = {
 hb_unicode_funcs_t *
 hb_unicode_funcs_get_empty (void)
 {
-  return const_cast<hb_unicode_funcs_t *> (&_hb_unicode_funcs_nil);
+  return const_cast<hb_unicode_funcs_t *> (&Null(hb_unicode_funcs_t));
 }
 
 /**
commit 1abd427acfb7229b8607646bdde59f29306b86e1
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Aug 6 05:53:35 2018 -0700

    [BASE] Rename horzi/vert to h/v

diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh
index 70b954b8..96da07fb 100644
--- a/src/hb-ot-layout-base-table.hh
+++ b/src/hb-ot-layout-base-table.hh
@@ -525,78 +525,78 @@ struct BASE
 {
   static const hb_tag_t tableTag = HB_OT_TAG_BASE;
 
-  inline bool has_vert_axis(void) { return vertAxis != 0; }
+  inline bool has_v_axis(void) { return vAxis != 0; }
 
-  inline bool has_horiz_axis(void) { return horizAxis != 0; }
+  inline bool has_h_axis(void) { return hAxis != 0; }
 
-  inline unsigned int get_horiz_base_tag_index (Tag baselineTag) const
+  inline unsigned int get_h_base_tag_index (Tag baselineTag) const
   {
-    return (this+horizAxis).get_base_tag_index(baselineTag);
+    return (this+hAxis).get_base_tag_index(baselineTag);
   }
 
-  inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
+  inline unsigned int get_h_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
   {
-    return (this+horizAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
+    return (this+hAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
   }
 
-  inline int get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
+  inline int get_h_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
   {
-    return (this+horizAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
+    return (this+hAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
   }
 
-  inline unsigned int get_vert_base_tag_index(Tag baselineTag) const
+  inline unsigned int get_v_base_tag_index(Tag baselineTag) const
   {
-    return (this+vertAxis).get_base_tag_index(baselineTag);
+    return (this+vAxis).get_base_tag_index(baselineTag);
   }
 
-  inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
+  inline unsigned int get_v_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
   {
-    return (this+vertAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
+    return (this+vAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
   }
 
-  inline int get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
+  inline int get_v_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
   {
-    return (this+vertAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
+    return (this+vAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
   }
 
-  inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+  inline unsigned int get_h_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
   {
-    return (this+horizAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
+    return (this+hAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
   }
 
-  inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+  inline unsigned int get_h_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
   {
-    return (this+horizAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
+    return (this+hAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
   }
 
-  inline int get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  inline int get_h_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
   {
-    return (this+horizAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+    return (this+hAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
   }
 
-  inline int get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  inline int get_h_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
   {
-    return (this+horizAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+    return (this+hAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
   }
 
-  inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+  inline unsigned int get_v_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
   {
-    return (this+vertAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
+    return (this+vAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
   }
 
-  inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+  inline unsigned int get_v_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
   {
-    return (this+vertAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
+    return (this+vAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
   }
 
-  inline int get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  inline int get_v_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
   {
-    return (this+vertAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+    return (this+vAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
   }
 
-  inline int get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  inline int get_v_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
   {
-    return (this+vertAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+    return (this+vAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -604,15 +604,15 @@ struct BASE
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
 		  likely (version.major == 1) &&
-		  horizAxis.sanitize (c, this) &&
-		  vertAxis.sanitize (c, this) &&
+		  hAxis.sanitize (c, this) &&
+		  vAxis.sanitize (c, this) &&
 		  (version.to_int () < 0x00010001u || varStore.sanitize (c, this)));
   }
 
   protected:
   FixedVersion<>  version;
-  OffsetTo<Axis>  horizAxis;
-  OffsetTo<Axis>  vertAxis;
+  OffsetTo<Axis>  hAxis;
+  OffsetTo<Axis>  vAxis;
   LOffsetTo<VariationStore>
 		varStore;		/* Offset to the table of Item Variation
 					 * Store--from beginning of BASE
commit da48aca1be89efbb8b3ca4471f542aa54aff17c4
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Aug 6 05:52:12 2018 -0700

    [BASE] Misc fixes
    
    The code was badly broken.  In better shape now, but still, needs
    a full review before ever working.

diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh
index 33dce890..70b954b8 100644
--- a/src/hb-ot-layout-base-table.hh
+++ b/src/hb-ot-layout-base-table.hh
@@ -33,13 +33,16 @@
 
 namespace OT {
 
-#define NOT_INDEXED   ((unsigned int) -1)
-
 /*
  * BASE -- Baseline
  * https://docs.microsoft.com/en-us/typography/opentype/spec/base
  */
 
+
+/* XXX Review this. */
+#define NOT_INDEXED		((unsigned int) -1)
+
+
 struct BaseCoordFormat1
 {
   inline int get_coord (void) const { return coordinate; }
@@ -52,7 +55,7 @@ struct BaseCoordFormat1
 
   protected:
   HBUINT16	format;		/* Format identifier--format = 1 */
-  HBINT16	coordinate;	/* X or Y value, in design units */
+  FWORD		coordinate;	/* X or Y value, in design units */
   public:
   DEFINE_SIZE_STATIC (4);
 };
@@ -73,7 +76,7 @@ struct BaseCoordFormat2
 
   protected:
   HBUINT16	format;		/* Format identifier--format = 2 */
-  HBINT16	coordinate;	/* X or Y value, in design units */
+  FWORD		coordinate;	/* X or Y value, in design units */
   GlyphID	referenceGlyph;	/* Glyph ID of control glyph */
   HBUINT16	coordPoint;	/* Index of contour point on the
 				 * reference glyph */
@@ -97,7 +100,7 @@ struct BaseCoordFormat3
 
   protected:
   HBUINT16		format;		/* Format identifier--format = 3 */
-  HBINT16		coordinate;	/* X or Y value, in design units */
+  FWORD			coordinate;	/* X or Y value, in design units */
   OffsetTo<Device>	deviceTable;	/* Offset to Device table for X or
 					 * Y value, from beginning of
 					 * BaseCoord table (may be NULL). */
@@ -109,6 +112,7 @@ struct BaseCoord
 {
   inline int get_coord (void) const
   {
+    /* XXX wire up direction and font. */
     switch (u.format) {
     case 1: return u.format1.get_coord ();
     case 2: return u.format2.get_coord ();
@@ -142,14 +146,10 @@ struct BaseCoord
 
 struct FeatMinMaxRecord
 {
-  inline int get_min_value (void) const
-  { return (this+minCoord).get_coord(); }
-
-  inline int get_max_value (void) const
-  { return (this+maxCoord).get_coord(); }
+  inline int get_min_value (void) const { return (this+minCoord).get_coord(); }
+  inline int get_max_value (void) const { return (this+maxCoord).get_coord(); }
 
-  inline const Tag &get_tag () const
-  { return tag; }
+  inline const Tag& get_tag () const { return tag; }
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
@@ -181,7 +181,7 @@ struct MinMax
     unsigned int count = featMinMaxRecords.len;
     for (unsigned int i = 0; i < count; i++)
     {
-      Tag tag = featMinMaxRecords[i].get_tag();
+      Tag tag = featMinMaxRecords[i].get_tag ();
       int cmp = tag.cmp(featureTableTag);
       if (cmp == 0) return i;
       if (cmp > 0)  return NOT_INDEXED;
@@ -233,13 +233,13 @@ struct BaseLangSysRecord
   { return baseLangSysTag; }
 
   inline unsigned int get_feature_tag_index (Tag featureTableTag) const
-  { return (this+minMax).get_feature_tag_index(featureTableTag); }
+  { return (this+minMax).get_feature_tag_index( featureTableTag); }
 
   inline int get_min_value (unsigned int featureTableTagIndex) const
-  { return (this+minMax).get_min_value(featureTableTagIndex); }
+  { return (this+minMax).get_min_value( featureTableTagIndex); }
 
   inline int get_max_value (unsigned int featureTableTagIndex) const
-  { return (this+minMax).get_max_value(featureTableTagIndex); }
+  { return (this+minMax).get_max_value (featureTableTagIndex); }
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
@@ -263,34 +263,34 @@ struct BaseValues
 
   inline int get_base_coord (unsigned int baselineTagIndex) const
   {
-    return (this+baseCoords[baselineTagIndex]).get_coord();
+    return (this+baseCoords[baselineTagIndex]).get_coord ();
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-      defaultIndex <= baseCoordCount &&
-      baseCoords.sanitize (c, this));
+		  baseCoords.sanitize (c, this));
   }
 
   protected:
   Index				defaultIndex;
-  HBUINT16			baseCoordCount;
   OffsetArrayOf<BaseCoord>	baseCoords;
   public:
-  DEFINE_SIZE_ARRAY (6, baseCoords);
-
+  DEFINE_SIZE_ARRAY (4, baseCoords);
 };
 
 struct BaseScript {
 
   inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
   {
+    /* XXX bsearch */
     Tag tag;
     int cmp;
-    for (unsigned int i = 0; i < baseLangSysCount; i++) {
-      tag = baseLangSysRecords[i].get_tag();
+    unsigned int count = baseLangSysRecords.len;
+    for (unsigned int i = 0; i < count; i++)
+    {
+      tag = baseLangSysRecords[i].get_tag ();
       // taking advantage of alphabetical order
       cmp = tag.cmp(baseLangSysTag);
       if (cmp == 0) return i;
@@ -301,51 +301,50 @@ struct BaseScript {
 
   inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
   {
-    if (baseLangSysIndex == NOT_INDEXED) {
+    if (baseLangSysIndex == NOT_INDEXED)
+    {
       if (unlikely(defaultMinMax)) return NOT_INDEXED;
-      return (this+defaultMinMax).get_feature_tag_index(featureTableTag);
+      return (this+defaultMinMax).get_feature_tag_index (featureTableTag);
     }
-    if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NOT_INDEXED;
-    return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index(featureTableTag);
+    return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index (featureTableTag);
   }
 
   inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
   {
     if (baseLangSysIndex == NOT_INDEXED)
-      return (this+defaultMinMax).get_min_value(featureTableTagIndex);
-    return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
+      return (this+defaultMinMax).get_min_value (featureTableTagIndex);
+    return baseLangSysRecords[baseLangSysIndex].get_max_value (featureTableTagIndex);
   }
 
   inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
   {
     if (baseLangSysIndex == NOT_INDEXED)
-      return (this+defaultMinMax).get_min_value(featureTableTagIndex);
-    return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
+      return (this+defaultMinMax).get_min_value (featureTableTagIndex);
+    return baseLangSysRecords[baseLangSysIndex].get_max_value (featureTableTagIndex);
   }
 
   inline unsigned int get_default_base_tag_index (void) const
-  { return (this+baseValues).get_default_base_tag_index(); }
+  { return (this+baseValues).get_default_base_tag_index (); }
 
   inline int get_base_coord (unsigned int baselineTagIndex) const
-  { return (this+baseValues).get_base_coord(baselineTagIndex); }
+  { return (this+baseValues).get_base_coord (baselineTagIndex); }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-      baseValues.sanitize (c, this) &&
-      defaultMinMax.sanitize (c, this) &&
-      baseLangSysRecords.sanitize (c, this));
+		  baseValues.sanitize (c, this) &&
+		  defaultMinMax.sanitize (c, this) &&
+		  baseLangSysRecords.sanitize (c, this));
   }
 
   protected:
-  OffsetTo<BaseValues>        baseValues;
-  OffsetTo<MinMax>            defaultMinMax;
-  HBUINT16                      baseLangSysCount;
-  ArrayOf<BaseLangSysRecord>  baseLangSysRecords;
+  OffsetTo<BaseValues>		baseValues;
+  OffsetTo<MinMax>		defaultMinMax;
+  ArrayOf<BaseLangSysRecord>	baseLangSysRecords;
 
   public:
-    DEFINE_SIZE_ARRAY (8, baseLangSysRecords);
+    DEFINE_SIZE_ARRAY (6, baseLangSysRecords);
 };
 
 
@@ -355,29 +354,28 @@ struct BaseScriptRecord {
   { return baseScriptTag; }
 
   inline unsigned int get_default_base_tag_index(void) const
-  { return (this+baseScript).get_default_base_tag_index(); }
+  { return (this+baseScript).get_default_base_tag_index (); }
 
   inline int get_base_coord(unsigned int baselineTagIndex) const
-  { return (this+baseScript).get_base_coord(baselineTagIndex); }
+  { return (this+baseScript).get_base_coord (baselineTagIndex); }
 
   inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
-  { return (this+baseScript).get_lang_tag_index(baseLangSysTag); }
+  { return (this+baseScript).get_lang_tag_index (baseLangSysTag); }
 
   inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
-  { return (this+baseScript).get_feature_tag_index(baseLangSysIndex, featureTableTag); }
+  { return (this+baseScript).get_feature_tag_index (baseLangSysIndex, featureTableTag); }
 
   inline int get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  { return (this+baseScript).get_max_value(baseLangSysIndex, featureTableTagIndex); }
+  { return (this+baseScript).get_max_value (baseLangSysIndex, featureTableTagIndex); }
 
   inline int get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  { return (this+baseScript).get_min_value(baseLangSysIndex, featureTableTagIndex); }
+  { return (this+baseScript).get_min_value (baseLangSysIndex, featureTableTagIndex); }
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-      baseScript != Null(OffsetTo<BaseScript>) &&
-      baseScript.sanitize (c, base));
+		  baseScript.sanitize (c, base));
   }
 
   protected:
@@ -392,7 +390,9 @@ struct BaseScriptList {
 
   inline unsigned int get_base_script_index (Tag baseScriptTag) const
   {
-    for (unsigned int i = 0; i < baseScriptCount; i++)
+    /* XXX bsearch? */
+    unsigned int count = baseScriptRecords.len;
+    for (unsigned int i = 0; i < count; i++)
       if (baseScriptRecords[i].get_tag() == baseScriptTag)
         return i;
     return NOT_INDEXED;
@@ -400,7 +400,6 @@ struct BaseScriptList {
 
   inline unsigned int get_default_base_tag_index (unsigned int baseScriptIndex) const
   {
-    if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
     return baseScriptRecords[baseScriptIndex].get_default_base_tag_index();
   }
 
@@ -411,13 +410,11 @@ struct BaseScriptList {
 
   inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
   {
-    if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
     return baseScriptRecords[baseScriptIndex].get_lang_tag_index(baseLangSysTag);
   }
 
   inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
   {
-    if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
     return baseScriptRecords[baseScriptIndex].get_feature_tag_index(baseLangSysIndex, featureTableTag);
   }
 
@@ -435,24 +432,23 @@ struct BaseScriptList {
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-      baseScriptRecords.sanitize (c, this));
+		  baseScriptRecords.sanitize (c, this));
   }
 
   protected:
-  HBUINT16                    baseScriptCount;
-  ArrayOf<BaseScriptRecord> baseScriptRecords;
+  ArrayOf<BaseScriptRecord>	baseScriptRecords;
 
   public:
-  DEFINE_SIZE_ARRAY (4, baseScriptRecords);
-
+  DEFINE_SIZE_ARRAY (2, baseScriptRecords);
 };
 
 struct BaseTagList
 {
-
-  inline unsigned int get_tag_index(Tag baselineTag) const
+  inline unsigned int get_tag_index (Tag baselineTag) const
   {
-    for (unsigned int i = 0; i < baseTagCount; i++)
+    /* TODO bsearch? */
+    unsigned int count = baselineTags.len;
+    for (unsigned int i = 0; i < count; i++)
       if (baselineTags[i] == baselineTag)
         return i;
     return NOT_INDEXED;
@@ -465,42 +461,37 @@ struct BaseTagList
   }
 
   protected:
-  HBUINT16        baseTagCount;
   SortedArrayOf<Tag>  baselineTags;
 
   public:
-  DEFINE_SIZE_ARRAY (4, baselineTags);
+  DEFINE_SIZE_ARRAY (2, baselineTags);
 };
 
 struct Axis
 {
 
-  inline unsigned int get_base_tag_index(Tag baselineTag) const
+  inline unsigned int get_base_tag_index (Tag baselineTag) const
   {
-    if (unlikely(baseTagList == Null(OffsetTo<BaseTagList>))) return NOT_INDEXED;
     return (this+baseTagList).get_tag_index(baselineTag);
   }
 
   inline unsigned int get_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
   {
-    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
     return (this+baseScriptList).get_default_base_tag_index(baseScriptIndex);
   }
 
-  inline int get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
+  inline int get_base_coord (unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
   {
     return (this+baseScriptList).get_base_coord(baseScriptIndex, baselineTagIndex);
   }
 
   inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
   {
-    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
     return (this+baseScriptList).get_lang_tag_index(baseScriptIndex, baseLangSysTag);
   }
 
   inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
   {
-    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
     return (this+baseScriptList).get_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag);
   }
 
@@ -518,13 +509,13 @@ struct Axis
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-      baseTagList.sanitize (c, this) &&
-      baseScriptList.sanitize (c, this));
+		  baseTagList.sanitize (c, this) &&
+		  baseScriptList.sanitize (c, this));
   }
 
   protected:
-  OffsetTo<BaseTagList>     baseTagList;
-  OffsetTo<BaseScriptList>  baseScriptList;
+  OffsetTo<BaseTagList>		baseTagList;
+  OffsetTo<BaseScriptList>	baseScriptList;
 
   public:
   DEFINE_SIZE_STATIC (4);
@@ -534,23 +525,17 @@ struct BASE
 {
   static const hb_tag_t tableTag = HB_OT_TAG_BASE;
 
-  inline bool has_vert_axis(void)
-  { return vertAxis != Null(OffsetTo<Axis>); }
+  inline bool has_vert_axis(void) { return vertAxis != 0; }
 
-  inline bool has_horiz_axis(void)
-  { return horizAxis != Null(OffsetTo<Axis>); }
+  inline bool has_horiz_axis(void) { return horizAxis != 0; }
 
-  // horizontal axis base coords:
-
-  inline unsigned int get_horiz_base_tag_index(Tag baselineTag) const
+  inline unsigned int get_horiz_base_tag_index (Tag baselineTag) const
   {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
     return (this+horizAxis).get_base_tag_index(baselineTag);
   }
 
   inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
   {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
     return (this+horizAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
   }
 
@@ -559,17 +544,13 @@ struct BASE
     return (this+horizAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
   }
 
-  // vertical axis base coords:
-
   inline unsigned int get_vert_base_tag_index(Tag baselineTag) const
   {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
     return (this+vertAxis).get_base_tag_index(baselineTag);
   }
 
   inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
   {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
     return (this+vertAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
   }
 
@@ -578,17 +559,13 @@ struct BASE
     return (this+vertAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
   }
 
-  // horizontal axis min/max coords:
-
   inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
   {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
     return (this+horizAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
   }
 
   inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
   {
-    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
     return (this+horizAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
   }
 
@@ -602,17 +579,13 @@ struct BASE
     return (this+horizAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
   }
 
-    // vertical axis min/max coords:
-
   inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
   {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
     return (this+vertAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
   }
 
   inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
   {
-    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
     return (this+vertAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
   }
 
commit f9cfa5cb0e70203279e74fb6adb0cd4570238ff8
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Aug 6 05:29:15 2018 -0700

    Change null-pool specialization to min_size again

diff --git a/src/hb-null.hh b/src/hb-null.hh
index ca7492eb..5ab3289e 100644
--- a/src/hb-null.hh
+++ b/src/hb-null.hh
@@ -49,19 +49,19 @@ static inline Type const & Null (void) {
 }
 #define Null(Type) Null<Type>()
 
-/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
+/* Specializaitons for arbitrary-content Null objects expressed in bytes. */
 #define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \
 } /* Close namespace. */ \
-extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[sizeof (Namespace::Type)]; \
+extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size]; \
 template <> \
 /*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \
   return *reinterpret_cast<const Namespace::Type *> (_hb_Null_##Namespace##_##Type); \
 } \
 namespace Namespace { \
-static_assert (Namespace::Type::min_size <= sizeof (Type), "Null pool too small.  Enlarge."); \
+static_assert (true, "Just so we take semicolon after.")
 
 #define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
-const unsigned char _hb_Null_##Namespace##_##Type[sizeof (Namespace::Type)]
+const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::min_size]
 
 
 /* Global writable pool.  Enlarge as necessary. */
commit 25147ff8086ab65995fe046cfdf8007604de6962
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Aug 6 05:01:52 2018 -0700

    Move Null system to hb-null.hh

diff --git a/src/Makefile.sources b/src/Makefile.sources
index 0a383dfc..b981b0e2 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -19,6 +19,7 @@ HB_BASE_sources = \
 	hb-map.cc \
 	hb-machinery-private.hh \
 	hb-mutex-private.hh \
+	hb-null.hh \
 	hb-object-private.hh \
 	hb-open-file-private.hh \
 	hb-open-type-private.hh \
diff --git a/src/hb-null.hh b/src/hb-null.hh
new file mode 100644
index 00000000..ca7492eb
--- /dev/null
+++ b/src/hb-null.hh
@@ -0,0 +1,97 @@
+/*
+ * Copyright © 2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_NULL_HH
+#define HB_NULL_HH
+
+#include "hb-private.hh"
+
+
+/*
+ * Static pools
+ */
+
+/* Global nul-content Null pool.  Enlarge as necessary. */
+
+#define HB_NULL_POOL_SIZE 264
+
+extern HB_INTERNAL
+hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
+
+/* Generic nul-content Null objects. */
+template <typename Type>
+static inline Type const & Null (void) {
+  static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
+  return *reinterpret_cast<Type const *> (_hb_NullPool);
+}
+#define Null(Type) Null<Type>()
+
+/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
+#define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \
+} /* Close namespace. */ \
+extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[sizeof (Namespace::Type)]; \
+template <> \
+/*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \
+  return *reinterpret_cast<const Namespace::Type *> (_hb_Null_##Namespace##_##Type); \
+} \
+namespace Namespace { \
+static_assert (Namespace::Type::min_size <= sizeof (Type), "Null pool too small.  Enlarge."); \
+
+#define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
+const unsigned char _hb_Null_##Namespace##_##Type[sizeof (Namespace::Type)]
+
+
+/* Global writable pool.  Enlarge as necessary. */
+
+/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool
+ * for correct operation. It only exist to catch and divert program logic bugs instead of
+ * causing bad memory access. So, races there are not actually introducing incorrectness
+ * in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */
+extern HB_INTERNAL
+/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
+
+/* CRAP pool: Common Region for Access Protection. */
+template <typename Type>
+static inline Type& Crap (void) {
+  static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
+  Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
+  *obj = Null(Type);
+  return *obj;
+}
+#define Crap(Type) Crap<Type>()
+
+template <typename Type>
+struct CrapOrNull {
+  static inline Type & get (void) { return Crap(Type); }
+};
+template <typename Type>
+struct CrapOrNull<const Type> {
+  static inline Type const & get (void) { return Null(Type); }
+};
+#define CrapOrNull(Type) CrapOrNull<Type>::get ()
+
+
+#endif /* HB_NULL_HH */
diff --git a/src/hb-private.hh b/src/hb-private.hh
index 5d12fb05..1bc996ed 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -368,70 +368,6 @@ typedef uint64_t hb_vector_size_impl_t;
 #endif
 
 
-/*
- * Static pools
- */
-
-/* Global nul-content Null pool.  Enlarge as necessary. */
-
-#define HB_NULL_POOL_SIZE 264
-
-extern HB_INTERNAL
-hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
-
-/* Generic nul-content Null objects. */
-template <typename Type>
-static inline Type const & Null (void) {
-  static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
-  return *reinterpret_cast<Type const *> (_hb_NullPool);
-}
-#define Null(Type) Null<Type>()
-
-/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
-#define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \
-} /* Close namespace. */ \
-extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[sizeof (Namespace::Type)]; \
-template <> \
-/*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \
-  return *reinterpret_cast<const Namespace::Type *> (_hb_Null_##Namespace##_##Type); \
-} \
-namespace Namespace { \
-static_assert (Namespace::Type::min_size <= sizeof (Type), "Null pool too small.  Enlarge."); \
-
-#define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
-const unsigned char _hb_Null_##Namespace##_##Type[sizeof (Namespace::Type)]
-
-
-/* Global writable pool.  Enlarge as necessary. */
-
-/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool
- * for correct operation. It only exist to catch and divert program logic bugs instead of
- * causing bad memory access. So, races there are not actually introducing incorrectness
- * in the code. Has ~12kb binary size overhead to have it, also clang build fails with it. */
-extern HB_INTERNAL
-/*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)];
-
-/* CRAP pool: Common Region for Access Protection. */
-template <typename Type>
-static inline Type& Crap (void) {
-  static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
-  Type *obj = reinterpret_cast<Type *> (_hb_CrapPool);
-  *obj = Null(Type);
-  return *obj;
-}
-#define Crap(Type) Crap<Type>()
-
-template <typename Type>
-struct CrapOrNull {
-  static inline Type & get (void) { return Crap(Type); }
-};
-template <typename Type>
-struct CrapOrNull<const Type> {
-  static inline Type const & get (void) { return Null(Type); }
-};
-#define CrapOrNull(Type) CrapOrNull<Type>::get ()
-
-
 /* HB_NDEBUG disables some sanity checks that are very safe to disable and
  * should be disabled in production systems.  If NDEBUG is defined, enable
  * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
@@ -525,6 +461,7 @@ _hb_memalign(void **memptr, size_t alignment, size_t size)
 #include "hb-debug.hh"
 #include "hb-dsalgs.hh"
 #include "hb-mutex-private.hh"
+#include "hb-null.hh"
 #include "hb-object-private.hh"
 
 #endif /* HB_PRIVATE_HH */
commit f800368df33e7ec15c3e77bdb9f4b464899322d3
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Aug 6 04:58:34 2018 -0700

    Remove unused macros

diff --git a/src/hb-object-private.hh b/src/hb-object-private.hh
index 66a35df0..47255488 100644
--- a/src/hb-object-private.hh
+++ b/src/hb-object-private.hh
@@ -42,7 +42,6 @@
  * Lockable set
  */
 
-#define HB_LOCKABLE_SET_INIT {HB_VECTOR_INIT}
 template <typename item_t, typename lock_t>
 struct hb_lockable_set_t
 {
diff --git a/src/hb-vector-private.hh b/src/hb-vector-private.hh
index 157fbd51..1ef20d43 100644
--- a/src/hb-vector-private.hh
+++ b/src/hb-vector-private.hh
@@ -31,7 +31,6 @@
 #include "hb-private.hh"
 
 
-#define HB_VECTOR_INIT {0, 0, false, nullptr}
 template <typename Type, unsigned int StaticSize=8>
 struct hb_vector_t
 {
commit 19e0091299f06856002c702792b448b06da637a8
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Aug 6 04:54:31 2018 -0700

    Minor

diff --git a/src/hb-private.hh b/src/hb-private.hh
index 35881607..5d12fb05 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -285,13 +285,12 @@ static int errno = 0; /* Use something better? */
 #define HB_STMT_START do
 #define HB_STMT_END   while (0)
 
+/* Static-assert as expression. */
 template <unsigned int cond> class hb_assert_constant_t;
 template <> class hb_assert_constant_t<1> {};
-
 #define ASSERT_STATIC_EXPR_ZERO(_cond) (0 * (unsigned int) sizeof (hb_assert_constant_t<_cond>))
 
 /* Lets assert int types.  Saves trouble down the road. */
-
 static_assert ((sizeof (int8_t) == 1), "");
 static_assert ((sizeof (uint8_t) == 1), "");
 static_assert ((sizeof (int16_t) == 2), "");
@@ -300,7 +299,6 @@ static_assert ((sizeof (int32_t) == 4), "");
 static_assert ((sizeof (uint32_t) == 4), "");
 static_assert ((sizeof (int64_t) == 8), "");
 static_assert ((sizeof (uint64_t) == 8), "");
-
 static_assert ((sizeof (hb_codepoint_t) == 4), "");
 static_assert ((sizeof (hb_position_t) == 4), "");
 static_assert ((sizeof (hb_mask_t) == 4), "");
commit 37be774af921812018f723521b90f2ab54f661c5
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Aug 6 04:51:38 2018 -0700

    Minor

diff --git a/src/hb-private.hh b/src/hb-private.hh
index 98a21188..35881607 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -86,7 +86,7 @@ extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size);
 
 /*
  * Compiler attributes
- * */
+ */
 
 #if __cplusplus < 201103L
 
@@ -98,7 +98,6 @@ extern "C" int hb_memalign_impl(void **memptr, size_t alignment, size_t size);
 #define constexpr const
 #endif
 
-// Static assertions
 #ifndef static_assert
 #define static_assert(e, msg) \
 	HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1]
@@ -124,7 +123,7 @@ struct _hb_alignof
 };
 #ifndef alignof
 #define alignof(x) (_hb_alignof<x>::value)
-#endif // alignof
+#endif
 
 #endif // __cplusplus < 201103L
 
commit e1acff806b469e58f568bf5ad6ba578207821e87
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Aug 6 04:42:46 2018 -0700

    Move hb_vector_t to hb-vector-private.hh

diff --git a/src/Makefile.sources b/src/Makefile.sources
index 80b8e261..0a383dfc 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -52,6 +52,7 @@ HB_BASE_sources = \
 	hb-string-array.hh \
 	hb-unicode-private.hh \
 	hb-unicode.cc \
+	hb-vector-private.hh \
 	hb-utf-private.hh \
 	hb-warning.cc \
 	$(NULL)
diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh
index 36395db2..8cbe6584 100644
--- a/src/hb-dsalgs.hh
+++ b/src/hb-dsalgs.hh
@@ -488,303 +488,6 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o
 }
 
 
-#define HB_VECTOR_INIT {0, 0, false, nullptr}
-template <typename Type, unsigned int StaticSize=8>
-struct hb_vector_t
-{
-  unsigned int len;
-  unsigned int allocated; /* == 0 means allocation failed. */
-  Type *arrayZ;
-  Type static_array[StaticSize];
-
-  void init (void)
-  {
-    len = 0;
-    allocated = ARRAY_LENGTH (static_array);
-    arrayZ = static_array;
-  }
-
-  inline Type& operator [] (unsigned int i)
-  {
-    if (unlikely (i >= len))
-      return Crap (Type);
-    return arrayZ[i];
-  }
-  inline const Type& operator [] (unsigned int i) const
-  {
-    if (unlikely (i >= len))
-      return Null(Type);
-    return arrayZ[i];
-  }
-
-  inline Type *push (void)
-  {
-    if (unlikely (!resize (len + 1)))
-      return &Crap(Type);
-    return &arrayZ[len - 1];
-  }
-  inline Type *push (const Type& v)
-  {
-    Type *p = push ();
-    *p = v;
-    return p;
-  }
-
-  /* Allocate for size but don't adjust len. */
-  inline bool alloc (unsigned int size)
-  {
-    if (unlikely (!allocated))
-      return false;
-
-    if (likely (size <= allocated))
-      return true;
-
-    /* Reallocate */
-
-    unsigned int new_allocated = allocated;
-    while (size >= new_allocated)
-      new_allocated += (new_allocated >> 1) + 8;
-
-    Type *new_array = nullptr;
-
-    if (arrayZ == static_array)
-    {
-      new_array = (Type *) calloc (new_allocated, sizeof (Type));
-      if (new_array)
-        memcpy (new_array, arrayZ, len * sizeof (Type));
-    }
-    else
-    {
-      bool overflows = (new_allocated < allocated) || hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
-      if (likely (!overflows))
-        new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type));
-    }
-
-    if (unlikely (!new_array))
-    {
-      allocated = 0;
-      return false;
-    }
-
-    arrayZ = new_array;
-    allocated = new_allocated;
-
-    return true;
-  }
-
-  inline bool resize (int size_)
-  {
-    unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
-    if (!alloc (size))
-      return false;
-
-    if (size > len)
-      memset (arrayZ + len, 0, (size - len) * sizeof (*arrayZ));
-
-    len = size;
-    return true;
-  }
-
-  inline void pop (void)
-  {
-    if (!len) return;
-    len--;
-  }
-
-  inline void remove (unsigned int i)
-  {
-     if (unlikely (i >= len))
-       return;
-     memmove (static_cast<void *> (&arrayZ[i]),
-	      static_cast<void *> (&arrayZ[i + 1]),
-	      (len - i - 1) * sizeof (Type));
-     len--;
-  }
-
-  inline void shrink (int size_)
-  {
-    unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
-     if (size < len)
-       len = size;
-  }
-
-  template <typename T>
-  inline Type *find (T v) {
-    for (unsigned int i = 0; i < len; i++)
-      if (arrayZ[i] == v)
-	return &arrayZ[i];
-    return nullptr;
-  }
-  template <typename T>
-  inline const Type *find (T v) const {
-    for (unsigned int i = 0; i < len; i++)
-      if (arrayZ[i] == v)
-	return &arrayZ[i];
-    return nullptr;
-  }
-
-  inline void qsort (int (*cmp)(const void*, const void*))
-  {
-    ::qsort (arrayZ, len, sizeof (Type), cmp);
-  }
-
-  inline void qsort (void)
-  {
-    ::qsort (arrayZ, len, sizeof (Type), Type::cmp);
-  }
-
-  inline void qsort (unsigned int start, unsigned int end)
-  {
-    ::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp);
-  }
-
-  template <typename T>
-  inline Type *lsearch (const T &x)
-  {
-    for (unsigned int i = 0; i < len; i++)
-      if (0 == this->arrayZ[i].cmp (&x))
-	return &arrayZ[i];
-    return nullptr;
-  }
-
-  template <typename T>
-  inline Type *bsearch (const T &x)
-  {
-    unsigned int i;
-    return bfind (x, &i) ? &arrayZ[i] : nullptr;
-  }
-  template <typename T>
-  inline const Type *bsearch (const T &x) const
-  {
-    unsigned int i;
-    return bfind (x, &i) ? &arrayZ[i] : nullptr;
-  }
-  template <typename T>
-  inline bool bfind (const T &x, unsigned int *i) const
-  {
-    int min = 0, max = (int) this->len - 1;
-    while (min <= max)
-    {
-      int mid = (min + max) / 2;
-      int c = this->arrayZ[mid].cmp (&x);
-      if (c < 0)
-        max = mid - 1;
-      else if (c > 0)
-        min = mid + 1;
-      else
-      {
-        *i = mid;
-	return true;
-      }
-    }
-    if (max < 0 || (max < (int) this->len && this->arrayZ[max].cmp (&x) > 0))
-      max++;
-    *i = max;
-    return false;
-  }
-
-  inline void fini (void)
-  {
-    if (arrayZ != static_array)
-      free (arrayZ);
-    arrayZ = nullptr;
-    allocated = len = 0;
-  }
-};
-
-
-#define HB_LOCKABLE_SET_INIT {HB_VECTOR_INIT}
-template <typename item_t, typename lock_t>
-struct hb_lockable_set_t
-{
-  hb_vector_t <item_t, 1> items;
-
-  inline void init (void) { items.init (); }
-
-  template <typename T>
-  inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (item) {
-      if (replace) {
-	item_t old = *item;
-	*item = v;
-	l.unlock ();
-	old.fini ();
-      }
-      else {
-        item = nullptr;
-	l.unlock ();
-      }
-    } else {
-      item = items.push (v);
-      l.unlock ();
-    }
-    return item;
-  }
-
-  template <typename T>
-  inline void remove (T v, lock_t &l)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (item) {
-      item_t old = *item;
-      *item = items[items.len - 1];
-      items.pop ();
-      l.unlock ();
-      old.fini ();
-    } else {
-      l.unlock ();
-    }
-  }
-
-  template <typename T>
-  inline bool find (T v, item_t *i, lock_t &l)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (item)
-      *i = *item;
-    l.unlock ();
-    return !!item;
-  }
-
-  template <typename T>
-  inline item_t *find_or_insert (T v, lock_t &l)
-  {
-    l.lock ();
-    item_t *item = items.find (v);
-    if (!item) {
-      item = items.push (v);
-    }
-    l.unlock ();
-    return item;
-  }
-
-  inline void fini (lock_t &l)
-  {
-    if (!items.len) {
-      /* No need for locking. */
-      items.fini ();
-      return;
-    }
-    l.lock ();
-    while (items.len) {
-      item_t old = items[items.len - 1];
-	items.pop ();
-	l.unlock ();
-	old.fini ();
-	l.lock ();
-    }
-    items.fini ();
-    l.unlock ();
-  }
-
-};
-
-
 template <typename Type>
 struct hb_auto_t : Type
 {
diff --git a/src/hb-object-private.hh b/src/hb-object-private.hh
index 36d27a89..66a35df0 100644
--- a/src/hb-object-private.hh
+++ b/src/hb-object-private.hh
@@ -35,9 +35,108 @@
 #include "hb-private.hh"
 #include "hb-atomic-private.hh"
 #include "hb-mutex-private.hh"
+#include "hb-vector-private.hh"
 
 
-/* reference_count */
+/*
+ * Lockable set
+ */
+
+#define HB_LOCKABLE_SET_INIT {HB_VECTOR_INIT}
+template <typename item_t, typename lock_t>
+struct hb_lockable_set_t
+{
+  hb_vector_t <item_t, 1> items;
+
+  inline void init (void) { items.init (); }
+
+  template <typename T>
+  inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
+  {
+    l.lock ();
+    item_t *item = items.find (v);
+    if (item) {
+      if (replace) {
+	item_t old = *item;
+	*item = v;
+	l.unlock ();
+	old.fini ();
+      }
+      else {
+        item = nullptr;
+	l.unlock ();
+      }
+    } else {
+      item = items.push (v);
+      l.unlock ();
+    }
+    return item;
+  }
+
+  template <typename T>
+  inline void remove (T v, lock_t &l)
+  {
+    l.lock ();
+    item_t *item = items.find (v);
+    if (item) {
+      item_t old = *item;
+      *item = items[items.len - 1];
+      items.pop ();
+      l.unlock ();
+      old.fini ();
+    } else {
+      l.unlock ();
+    }
+  }
+
+  template <typename T>
+  inline bool find (T v, item_t *i, lock_t &l)
+  {
+    l.lock ();
+    item_t *item = items.find (v);
+    if (item)
+      *i = *item;
+    l.unlock ();
+    return !!item;
+  }
+
+  template <typename T>
+  inline item_t *find_or_insert (T v, lock_t &l)
+  {
+    l.lock ();
+    item_t *item = items.find (v);
+    if (!item) {
+      item = items.push (v);
+    }
+    l.unlock ();
+    return item;
+  }
+
+  inline void fini (lock_t &l)
+  {
+    if (!items.len) {
+      /* No need for locking. */
+      items.fini ();
+      return;
+    }
+    l.lock ();
+    while (items.len) {
+      item_t old = items[items.len - 1];
+	items.pop ();
+	l.unlock ();
+	old.fini ();
+	l.lock ();
+    }
+    items.fini ();
+    l.unlock ();
+  }
+
+};
+
+
+/*
+ * Reference-count.
+ */
 
 #define HB_REFERENCE_COUNT_INERT_VALUE 0
 #define HB_REFERENCE_COUNT_POISON_VALUE -0x0000DEAD
@@ -89,7 +188,9 @@ struct hb_user_data_array_t
 };
 
 
-/* object_header */
+/*
+ * Object header
+ */
 
 struct hb_object_header_t
 {
@@ -103,7 +204,9 @@ struct hb_object_header_t
 };
 
 
-/* object */
+/*
+ * Object
+ */
 
 template <typename Type>
 static inline void hb_object_trace (const Type *obj, const char *function)
diff --git a/src/hb-vector-private.hh b/src/hb-vector-private.hh
new file mode 100644
index 00000000..157fbd51
--- /dev/null
+++ b/src/hb-vector-private.hh
@@ -0,0 +1,239 @@
+/*
+ * Copyright © 2017,2018  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_VECTOR_PRIVATE_HH
+#define HB_VECTOR_PRIVATE_HH
+
+#include "hb-private.hh"
+
+
+#define HB_VECTOR_INIT {0, 0, false, nullptr}
+template <typename Type, unsigned int StaticSize=8>
+struct hb_vector_t
+{
+  unsigned int len;
+  unsigned int allocated; /* == 0 means allocation failed. */
+  Type *arrayZ;
+  Type static_array[StaticSize];
+
+  void init (void)
+  {
+    len = 0;
+    allocated = ARRAY_LENGTH (static_array);
+    arrayZ = static_array;
+  }
+
+  inline Type& operator [] (unsigned int i)
+  {
+    if (unlikely (i >= len))
+      return Crap (Type);
+    return arrayZ[i];
+  }
+  inline const Type& operator [] (unsigned int i) const
+  {
+    if (unlikely (i >= len))
+      return Null(Type);
+    return arrayZ[i];
+  }
+
+  inline Type *push (void)
+  {
+    if (unlikely (!resize (len + 1)))
+      return &Crap(Type);
+    return &arrayZ[len - 1];
+  }
+  inline Type *push (const Type& v)
+  {
+    Type *p = push ();
+    *p = v;
+    return p;
+  }
+
+  /* Allocate for size but don't adjust len. */
+  inline bool alloc (unsigned int size)
+  {
+    if (unlikely (!allocated))
+      return false;
+
+    if (likely (size <= allocated))
+      return true;
+
+    /* Reallocate */
+
+    unsigned int new_allocated = allocated;
+    while (size >= new_allocated)
+      new_allocated += (new_allocated >> 1) + 8;
+
+    Type *new_array = nullptr;
+
+    if (arrayZ == static_array)
+    {
+      new_array = (Type *) calloc (new_allocated, sizeof (Type));
+      if (new_array)
+        memcpy (new_array, arrayZ, len * sizeof (Type));
+    }
+    else
+    {
+      bool overflows = (new_allocated < allocated) || hb_unsigned_mul_overflows (new_allocated, sizeof (Type));
+      if (likely (!overflows))
+        new_array = (Type *) realloc (arrayZ, new_allocated * sizeof (Type));
+    }
+
+    if (unlikely (!new_array))
+    {
+      allocated = 0;
+      return false;
+    }
+
+    arrayZ = new_array;
+    allocated = new_allocated;
+
+    return true;
+  }
+
+  inline bool resize (int size_)
+  {
+    unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
+    if (!alloc (size))
+      return false;
+
+    if (size > len)
+      memset (arrayZ + len, 0, (size - len) * sizeof (*arrayZ));
+
+    len = size;
+    return true;
+  }
+
+  inline void pop (void)
+  {
+    if (!len) return;
+    len--;
+  }
+
+  inline void remove (unsigned int i)
+  {
+     if (unlikely (i >= len))
+       return;
+     memmove (static_cast<void *> (&arrayZ[i]),
+	      static_cast<void *> (&arrayZ[i + 1]),
+	      (len - i - 1) * sizeof (Type));
+     len--;
+  }
+
+  inline void shrink (int size_)
+  {
+    unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
+     if (size < len)
+       len = size;
+  }
+
+  template <typename T>
+  inline Type *find (T v) {
+    for (unsigned int i = 0; i < len; i++)
+      if (arrayZ[i] == v)
+	return &arrayZ[i];
+    return nullptr;
+  }
+  template <typename T>
+  inline const Type *find (T v) const {
+    for (unsigned int i = 0; i < len; i++)
+      if (arrayZ[i] == v)
+	return &arrayZ[i];
+    return nullptr;
+  }
+
+  inline void qsort (int (*cmp)(const void*, const void*))
+  {
+    ::qsort (arrayZ, len, sizeof (Type), cmp);
+  }
+
+  inline void qsort (void)
+  {
+    ::qsort (arrayZ, len, sizeof (Type), Type::cmp);
+  }
+
+  inline void qsort (unsigned int start, unsigned int end)
+  {
+    ::qsort (arrayZ + start, end - start, sizeof (Type), Type::cmp);
+  }
+
+  template <typename T>
+  inline Type *lsearch (const T &x)
+  {
+    for (unsigned int i = 0; i < len; i++)
+      if (0 == this->arrayZ[i].cmp (&x))
+	return &arrayZ[i];
+    return nullptr;
+  }
+
+  template <typename T>
+  inline Type *bsearch (const T &x)
+  {
+    unsigned int i;
+    return bfind (x, &i) ? &arrayZ[i] : nullptr;
+  }
+  template <typename T>
+  inline const Type *bsearch (const T &x) const
+  {
+    unsigned int i;
+    return bfind (x, &i) ? &arrayZ[i] : nullptr;
+  }
+  template <typename T>
+  inline bool bfind (const T &x, unsigned int *i) const
+  {
+    int min = 0, max = (int) this->len - 1;
+    while (min <= max)
+    {
+      int mid = (min + max) / 2;
+      int c = this->arrayZ[mid].cmp (&x);
+      if (c < 0)
+        max = mid - 1;
+      else if (c > 0)
+        min = mid + 1;
+      else
+      {
+        *i = mid;
+	return true;
+      }
+    }
+    if (max < 0 || (max < (int) this->len && this->arrayZ[max].cmp (&x) > 0))
+      max++;
+    *i = max;
+    return false;
+  }
+
+  inline void fini (void)
+  {
+    if (arrayZ != static_array)
+      free (arrayZ);
+    arrayZ = nullptr;
+    allocated = len = 0;
+  }
+};
+
+
+#endif /* HB_VECTOR_PRIVATE_HH */
commit be336dadc07460a53de51be32dd5d1f218b398b6
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Aug 6 04:32:51 2018 -0700

    Move some more code around

diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh
index fc7d1f0a..36395db2 100644
--- a/src/hb-dsalgs.hh
+++ b/src/hb-dsalgs.hh
@@ -232,6 +232,18 @@ hb_ctz (T v)
  * Tiny stuff.
  */
 
+/* ASCII tag/character handling */
+static inline bool ISALPHA (unsigned char c)
+{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
+static inline bool ISALNUM (unsigned char c)
+{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
+static inline bool ISSPACE (unsigned char c)
+{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
+static inline unsigned char TOUPPER (unsigned char c)
+{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
+static inline unsigned char TOLOWER (unsigned char c)
+{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
+
 #undef MIN
 template <typename Type>
 static inline Type MIN (const Type &a, const Type &b) { return a < b ? a : b; }
@@ -262,6 +274,37 @@ hb_ceil_to_4 (unsigned int v)
   return ((v - 1) | 3) + 1;
 }
 
+template <typename T> class hb_assert_unsigned_t;
+template <> class hb_assert_unsigned_t<unsigned char> {};
+template <> class hb_assert_unsigned_t<unsigned short> {};
+template <> class hb_assert_unsigned_t<unsigned int> {};
+template <> class hb_assert_unsigned_t<unsigned long> {};
+
+template <typename T> static inline bool
+hb_in_range (T u, T lo, T hi)
+{
+  /* The sizeof() is here to force template instantiation.
+   * I'm sure there are better ways to do this but can't think of
+   * one right now.  Declaring a variable won't work as HB_UNUSED
+   * is unusable on some platforms and unused types are less likely
+   * to generate a warning than unused variables. */
+  static_assert ((sizeof (hb_assert_unsigned_t<T>) >= 0), "");
+
+  /* The casts below are important as if T is smaller than int,
+   * the subtract results will become a signed int! */
+  return (T)(u - lo) <= (T)(hi - lo);
+}
+template <typename T> static inline bool
+hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
+{
+  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
+}
+template <typename T> static inline bool
+hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
+{
+  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
+}
+
 
 /*
  * Sort and search.
diff --git a/src/hb-private.hh b/src/hb-private.hh
index d912fe33..98a21188 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -435,20 +435,6 @@ struct CrapOrNull<const Type> {
 #define CrapOrNull(Type) CrapOrNull<Type>::get ()
 
 
-/* ASCII tag/character handling */
-
-static inline bool ISALPHA (unsigned char c)
-{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); }
-static inline bool ISALNUM (unsigned char c)
-{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'); }
-static inline bool ISSPACE (unsigned char c)
-{ return c == ' ' || c =='\f'|| c =='\n'|| c =='\r'|| c =='\t'|| c =='\v'; }
-static inline unsigned char TOUPPER (unsigned char c)
-{ return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c; }
-static inline unsigned char TOLOWER (unsigned char c)
-{ return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c; }
-
-
 /* HB_NDEBUG disables some sanity checks that are very safe to disable and
  * should be disabled in production systems.  If NDEBUG is defined, enable
  * HB_NDEBUG; but if it's desirable that normal assert()s (which are very
@@ -459,41 +445,7 @@ static inline unsigned char TOLOWER (unsigned char c)
 #endif
 
 
-/* Misc */
-
-template <typename T> class hb_assert_unsigned_t;
-template <> class hb_assert_unsigned_t<unsigned char> {};
-template <> class hb_assert_unsigned_t<unsigned short> {};
-template <> class hb_assert_unsigned_t<unsigned int> {};
-template <> class hb_assert_unsigned_t<unsigned long> {};
-
-template <typename T> static inline bool
-hb_in_range (T u, T lo, T hi)
-{
-  /* The sizeof() is here to force template instantiation.
-   * I'm sure there are better ways to do this but can't think of
-   * one right now.  Declaring a variable won't work as HB_UNUSED
-   * is unusable on some platforms and unused types are less likely
-   * to generate a warning than unused variables. */
-  static_assert ((sizeof (hb_assert_unsigned_t<T>) >= 0), "");
-
-  /* The casts below are important as if T is smaller than int,
-   * the subtract results will become a signed int! */
-  return (T)(u - lo) <= (T)(hi - lo);
-}
-
-template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2)
-{
-  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2);
-}
-
-template <typename T> static inline bool
-hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
-{
-  return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
-}
-
+/* Flags */
 
 /* Enable bitwise ops on enums marked as flags_t */
 /* To my surprise, looks like the function resolver is happy to silently cast
@@ -517,7 +469,6 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
 	  static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
 	}
 
-
 /* Useful for set-operations on small enums.
  * For example, for testing "x ∈ {x1, x2, x3}" use:
  * (FLAG_UNSAFE(x) & (FLAG(x1) | FLAG(x2) | FLAG(x3)))
commit 92806ee055c8efb68fcbe9e1750ce2532a1f8ab3
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sun Aug 5 21:41:52 2018 -0700

    Move null data definitions to hb-static.cc
    
    Also remove "    " null data for Tag.  Just use zeroes.

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index bae2eed8..5580565f 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -140,7 +140,6 @@ struct Tag : HBUINT32
   public:
   DEFINE_SIZE_STATIC (4);
 };
-DEFINE_NULL_DATA (OT, Tag, "    ");
 
 /* Glyph index number, same as uint16 (length = 16 bits) */
 typedef HBUINT16 GlyphID;
@@ -152,7 +151,7 @@ typedef HBUINT16 NameID;
 struct Index : HBUINT16 {
   static const unsigned int NOT_FOUND_INDEX = 0xFFFFu;
 };
-DEFINE_NULL_DATA (OT, Index, "\xff\xff");
+DECLARE_NULL_NAMESPACE_BYTES (OT, Index);
 
 /* Offset, Null offset = 0 */
 template <typename Type>
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 2da6e315..89d5eae4 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -173,7 +173,7 @@ struct RangeRecord
   public:
   DEFINE_SIZE_STATIC (6);
 };
-DEFINE_NULL_DATA (OT, RangeRecord, "\000\001");
+DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord);
 
 
 struct IndexArray : ArrayOf<Index>
@@ -240,8 +240,7 @@ struct LangSys
   public:
   DEFINE_SIZE_ARRAY (6, featureIndex);
 };
-DEFINE_NULL_DATA (OT, LangSys, "\0\0\xFF\xFF");
-
+DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys);
 
 struct Script
 {
diff --git a/src/hb-private.hh b/src/hb-private.hh
index 32e1edff..d912fe33 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -391,16 +391,18 @@ static inline Type const & Null (void) {
 #define Null(Type) Null<Type>()
 
 /* Specializaiton for arbitrary-content arbitrary-sized Null objects. */
-#define DEFINE_NULL_DATA(Namespace, Type, data) \
+#define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \
 } /* Close namespace. */ \
-static const char _Null##Type[sizeof (Namespace::Type) + 1] = data; /* +1 is for nul-termination in data */ \
+extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[sizeof (Namespace::Type)]; \
 template <> \
 /*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \
-  return *reinterpret_cast<const Namespace::Type *> (_Null##Type); \
+  return *reinterpret_cast<const Namespace::Type *> (_hb_Null_##Namespace##_##Type); \
 } \
 namespace Namespace { \
-/* The following line really exists such that we end in a place needing semicolon */ \
-static_assert (Namespace::Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small.  Enlarge.")
+static_assert (Namespace::Type::min_size <= sizeof (Type), "Null pool too small.  Enlarge."); \
+
+#define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
+const unsigned char _hb_Null_##Namespace##_##Type[sizeof (Namespace::Type)]
 
 
 /* Global writable pool.  Enlarge as necessary. */
diff --git a/src/hb-static.cc b/src/hb-static.cc
index bd0943f5..ddecbba1 100644
--- a/src/hb-static.cc
+++ b/src/hb-static.cc
@@ -25,8 +25,11 @@
  */
 
 #include "hb-private.hh"
-#include "hb-face-private.hh"
+
 #include "hb-open-type-private.hh"
+#include "hb-ot-layout-common-private.hh"
+
+#include "hb-face-private.hh"
 #include "hb-ot-head-table.hh"
 #include "hb-ot-maxp-table.hh"
 
@@ -35,6 +38,11 @@
 hb_vector_size_impl_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
 /*thread_local*/ hb_vector_size_impl_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (hb_vector_size_impl_t) - 1) / sizeof (hb_vector_size_impl_t)] = {};
 
+DEFINE_NULL_NAMESPACE_BYTES (OT, Index) =  {0xFF,0xFF};
+DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00};
+DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00};
+
+
 void
 hb_face_t::load_num_glyphs (void) const
 {
commit 1b4d5a2402302e90867c178b6b2ad07541091a74
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Aug 3 19:55:09 2018 -0700

    Minor

diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index b03b8252..2a74135c 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -193,10 +193,10 @@ struct hb_ot_layout_t
     HB_INTERNAL void fini (void);
 
 #define HB_OT_LAYOUT_TABLE_ORDER(Namespace, Type) \
-      HB_PASTE (TABLE_ORDER_, HB_PASTE (Namespace, HB_PASTE (_, Type)))
+      HB_PASTE (ORDER_, HB_PASTE (Namespace, HB_PASTE (_, Type)))
     enum order_t
     {
-      TABLE_ORDER_ZERO,
+      ORDER_ZERO,
 #define HB_OT_LAYOUT_TABLE(Namespace, Type) \
 	HB_OT_LAYOUT_TABLE_ORDER (Namespace, Type),
       HB_OT_LAYOUT_TABLES
commit 7df7963b46223f47e89a5a38c597c874aaa93141
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Aug 3 19:54:33 2018 -0700

    Make lazy loader deal with OOM

diff --git a/src/hb-machinery-private.hh b/src/hb-machinery-private.hh
index 0d2dbc3c..119625c4 100644
--- a/src/hb-machinery-private.hh
+++ b/src/hb-machinery-private.hh
@@ -623,7 +623,11 @@ struct hb_lazy_loader_t
     if (unlikely (!p))
     {
       hb_face_t *face = *(((hb_face_t **) this) - WheresFace);
-      p = thiz ()->create (face);
+      if (likely (!p))
+	p = thiz ()->create (face);
+      if (unlikely (!p))
+	p = thiz ()->create (nullptr); /* Produce nil object. */
+      assert (p);
       if (unlikely (!hb_atomic_ptr_cmpexch (const_cast<Stored **>(&this->instance), nullptr, p)))
       {
         thiz ()->destroy (p);


More information about the HarfBuzz mailing list