[shaper] Rewrite shaper data code to be more template-driven than macro-driven
diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc
index 3cedb5b..cccc2d0 100644
--- a/src/hb-coretext.cc
+++ b/src/hb-coretext.cc
@@ -26,8 +26,6 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#define HB_SHAPER coretext
-
 #include "hb.hh"
 #include "hb-shaper-impl.hh"
 
@@ -101,8 +99,8 @@
 }
 
 
-HB_SHAPER_DATA_ENSURE_DEFINE(coretext, face);
-HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font,
+/* XXX TODO */
+//HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(coretext, font,
 	fabs (CTFontGetSize((CTFontRef) data) - coretext_font_size_from_ptem (font->ptem)) <= .5
 );
 
@@ -312,8 +310,7 @@
 CGFontRef
 hb_coretext_face_get_cg_font (hb_face_t *face)
 {
-  if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
-  return (CGFontRef) HB_SHAPER_DATA_GET (face);
+  return (CGFontRef) (const void *) face->data.coretext;
 }
 
 
@@ -322,7 +319,7 @@
 {
   hb_face_t *face = font->face;
   if (unlikely (!hb_coretext_shaper_face_data_ensure (face))) return nullptr;
-  CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
+  CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext;
 
   CTFontRef ct_font = create_ct_font (cg_font, coretext_font_size_from_ptem (font->ptem));
 
@@ -368,7 +365,7 @@
 hb_coretext_font_get_ct_font (hb_font_t *font)
 {
   if (unlikely (!hb_coretext_shaper_font_data_ensure (font))) return nullptr;
-  return (CTFontRef) HB_SHAPER_DATA_GET (font);
+  return (CTFontRef) (const void *) font->data.coretext;
 }
 
 
@@ -427,8 +424,8 @@
                     unsigned int        num_features)
 {
   hb_face_t *face = font->face;
-  CGFontRef cg_font = (CGFontRef) HB_SHAPER_DATA_GET (face);
-  CTFontRef ct_font = (CTFontRef) HB_SHAPER_DATA_GET (font);
+  CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext;
+  CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
 
   CGFloat ct_font_size = CTFontGetSize (ct_font);
   CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc
index b34ae60..4ae6e7f 100644
--- a/src/hb-directwrite.cc
+++ b/src/hb-directwrite.cc
@@ -23,7 +23,6 @@
  */
 
 #include "hb.hh"
-#define HB_SHAPER directwrite
 #include "hb-shaper-impl.hh"
 
 #include <DWrite_1.h>
@@ -31,10 +30,6 @@
 #include "hb-directwrite.h"
 
 
-HB_SHAPER_DATA_ENSURE_DEFINE (directwrite, face);
-HB_SHAPER_DATA_ENSURE_DEFINE (directwrite, font);
-
-
 /*
  * hb-directwrite uses new/delete syntatically but as we let users
  * to override malloc/free, we will redefine new/delete so users
@@ -534,8 +529,8 @@
   float               lineWidth)
 {
   hb_face_t *face = font->face;
-  hb_directwrite_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
-  hb_directwrite_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
+  const hb_directwrite_face_data_t *face_data = face->data.directwrite;
+  const hb_directwrite_font_data_t *font_data = font->data.directwrite;
   IDWriteFactory *dwriteFactory = face_data->dwriteFactory;
   IDWriteFontFace *fontFace = face_data->fontFace;
 
diff --git a/src/hb-face.cc b/src/hb-face.cc
index 3294ed4..e23842f 100644
--- a/src/hb-face.cc
+++ b/src/hb-face.cc
@@ -90,12 +90,6 @@
   HB_ATOMIC_INT_INIT (1000), /* upem */
   HB_ATOMIC_INT_INIT (0),    /* num_glyphs */
 
-  {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_ATOMIC_PTR_INIT (HB_SHAPER_DATA_INVALID),
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-  },
-
   /* Zero for the rest is fine. */
 };
 
@@ -131,6 +125,7 @@
 
   face->num_glyphs.set_relaxed (-1);
 
+  face->data.init0 (face);
   face->table.init0 (face);
 
   return face;
@@ -272,10 +267,7 @@
     node = next;
   }
 
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, face);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-
+  face->data.fini ();
   face->table.fini ();
 
   if (face->destroy)
diff --git a/src/hb-face.hh b/src/hb-face.hh
index 002fb2c..0b67233 100644
--- a/src/hb-face.hh
+++ b/src/hb-face.hh
@@ -40,6 +40,10 @@
  * hb_face_t
  */
 
+#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, face);
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+
 struct hb_face_t
 {
   hb_object_header_t header;
@@ -52,8 +56,7 @@
   mutable hb_atomic_int_t upem;		/* Units-per-EM. */
   mutable hb_atomic_int_t num_glyphs;	/* Number of glyphs. */
 
-  struct hb_shaper_data_t shaper_data;	/* Various shaper data. */
-
+  hb_shaper_object_dataset_t<hb_face_t> data;/* Various shaper data. */
   hb_ot_face_t table;			/* All the face's tables. */
 
   /* Cache */
@@ -102,11 +105,5 @@
 };
 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);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-
 
 #endif /* HB_FACE_HH */
diff --git a/src/hb-fallback-shape.cc b/src/hb-fallback-shape.cc
index 40f8dad..09f0290 100644
--- a/src/hb-fallback-shape.cc
+++ b/src/hb-fallback-shape.cc
@@ -24,14 +24,9 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#define HB_SHAPER fallback
 #include "hb-shaper-impl.hh"
 
 
-HB_SHAPER_DATA_ENSURE_DEFINE(fallback, face);
-HB_SHAPER_DATA_ENSURE_DEFINE(fallback, font);
-
-
 /*
  * shaper face data
  */
diff --git a/src/hb-font.cc b/src/hb-font.cc
index ca710a6..237b2a5 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -1307,14 +1307,8 @@
   nullptr, /* coords */
 
   const_cast<hb_font_funcs_t *> (&_hb_Null_hb_font_funcs_t),
-  nullptr, /* user_data */
-  nullptr, /* destroy */
 
-  {
-#define HB_SHAPER_IMPLEMENT(shaper) HB_ATOMIC_PTR_INIT (HB_SHAPER_DATA_INVALID),
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-  }
+  /* Zero for the rest is fine. */
 };
 
 
@@ -1332,7 +1326,7 @@
   font->parent = hb_font_get_empty ();
   font->face = hb_face_reference (face);
   font->klass = hb_font_funcs_get_empty ();
-
+  font->data.init0 (font);
   font->x_scale = font->y_scale = hb_face_get_upem (face);
 
   return font;
@@ -1448,9 +1442,7 @@
 {
   if (!hb_object_destroy (font)) return;
 
-#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_DESTROY(shaper, font);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
+  font->data.fini ();
 
   if (font->destroy)
     font->destroy (font->user_data);
diff --git a/src/hb-font.hh b/src/hb-font.hh
index fb29bcc..73733b3 100644
--- a/src/hb-font.hh
+++ b/src/hb-font.hh
@@ -96,6 +96,10 @@
  * hb_font_t
  */
 
+#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, font);
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+
 struct hb_font_t
 {
   hb_object_header_t header;
@@ -119,7 +123,7 @@
   void              *user_data;
   hb_destroy_func_t  destroy;
 
-  struct hb_shaper_data_t shaper_data;
+  hb_shaper_object_dataset_t<hb_font_t> data; /* Various shaper data. */
 
 
   /* Convert from font-space to user-space */
@@ -609,11 +613,5 @@
 };
 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);
-#include "hb-shaper-list.hh"
-#undef HB_SHAPER_IMPLEMENT
-#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS
-
 
 #endif /* HB_FONT_HH */
diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc
index 8dce817..a1c602c 100644
--- a/src/hb-graphite2.cc
+++ b/src/hb-graphite2.cc
@@ -26,7 +26,6 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#define HB_SHAPER graphite2
 #include "hb-shaper-impl.hh"
 
 #include "hb-graphite2.h"
@@ -46,10 +45,6 @@
  **/
 
 
-HB_SHAPER_DATA_ENSURE_DEFINE(graphite2, face);
-HB_SHAPER_DATA_ENSURE_DEFINE(graphite2, font);
-
-
 /*
  * shaper face data
  */
@@ -185,8 +180,8 @@
 gr_face *
 hb_graphite2_face_get_gr_face (hb_face_t *face)
 {
-  if (unlikely (!hb_graphite2_shaper_face_data_ensure (face))) return nullptr;
-  return HB_SHAPER_DATA_GET (face)->grface;
+  const hb_graphite2_face_data_t *data = face->data.graphite2;
+  return data ? data->grface : nullptr;
 }
 
 
@@ -241,7 +236,7 @@
 		     unsigned int        num_features)
 {
   hb_face_t *face = font->face;
-  gr_face *grface = HB_SHAPER_DATA_GET (face)->grface;
+  gr_face *grface = face->data.graphite2->grface;
 
   const char *lang = hb_language_to_string (hb_buffer_get_language (buffer));
   const char *lang_end = lang ? strchr (lang, '-') : nullptr;
diff --git a/src/hb-machinery.hh b/src/hb-machinery.hh
index ffc9627..134aab6 100644
--- a/src/hb-machinery.hh
+++ b/src/hb-machinery.hh
@@ -755,10 +755,7 @@
   inline bool is_inert (void) const { return !get_data (); }
 
   template <typename Stored, typename Subclass>
-  inline Stored * call_create (void) const
-  {
-    return Subclass::create (this->get_data ());
-  }
+  inline Stored * call_create (void) const { return Subclass::create (get_data ()); }
 };
 template <>
 struct hb_data_wrapper_t<void, 0>
@@ -766,10 +763,7 @@
   inline bool is_inert (void) const { return false; }
 
   template <typename Stored, typename Funcs>
-  inline Stored * call_create (void) const
-  {
-    return Funcs::create ();
-  }
+  inline Stored * call_create (void) const { return Funcs::create (); }
 };
 
 template <typename T1, typename T2> struct hb_non_void_t { typedef T1 value; };
@@ -809,6 +803,8 @@
 
   inline const Returned * operator -> (void) const { return get (); }
   inline const Returned & operator * (void) const { return *get (); }
+  explicit_operator inline operator bool (void) const
+  { return get_stored () != Funcs::get_null (); }
   template <typename C> inline operator const C * (void) const { return get (); }
 
   inline Stored * get_stored (void) const
@@ -877,7 +873,7 @@
     free (p);
   }
 
-  private:
+//  private:
   /* Must only have one pointer. */
   hb_atomic_ptr_t<Stored *> instance;
 };
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index ba65e76..093511e 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -26,7 +26,6 @@
  * Google Author(s): Behdad Esfahbod
  */
 
-#define HB_SHAPER ot
 #include "hb-shaper-impl.hh"
 
 #include "hb-ot-shape.hh"
@@ -320,8 +319,6 @@
  * shaper face data
  */
 
-HB_SHAPER_DATA_ENSURE_DEFINE(ot, face);
-
 struct hb_ot_face_data_t {};
 
 hb_ot_face_data_t *
@@ -340,8 +337,6 @@
  * shaper font data
  */
 
-HB_SHAPER_DATA_ENSURE_DEFINE(ot, font);
-
 struct hb_ot_font_data_t {};
 
 hb_ot_font_data_t *
diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc
index 460d77b..bc3d816 100644
--- a/src/hb-shape-plan.cc
+++ b/src/hb-shape-plan.cc
@@ -87,7 +87,7 @@
 
 #define HB_SHAPER_PLAN(shaper) \
 	HB_STMT_START { \
-	  if (hb_##shaper##_shaper_face_data_ensure (face)) \
+	  if (face->data.shaper) \
 	  { \
 	    this->shaper_func = _hb_##shaper##_shape; \
 	    this->shaper_name = #shaper; \
@@ -386,7 +386,7 @@
 
 #define HB_SHAPER_EXECUTE(shaper) \
 	HB_STMT_START { \
-	  return hb_##shaper##_shaper_font_data_ensure (font) && \
+	  return font->data.shaper && \
 		 _hb_##shaper##_shape (shape_plan, font, buffer, features, num_features); \
 	} HB_STMT_END
 
diff --git a/src/hb-shaper-impl.hh b/src/hb-shaper-impl.hh
index d40cb08..b674fce 100644
--- a/src/hb-shaper-impl.hh
+++ b/src/hb-shaper-impl.hh
@@ -30,14 +30,9 @@
 #include "hb.hh"
 
 #include "hb-shaper.hh"
-#include "hb-shape-plan.hh"
+#include "hb-face.hh"
 #include "hb-font.hh"
+#include "hb-shape-plan.hh"
 #include "hb-buffer.hh"
 
-
-#ifdef HB_SHAPER
-#define HB_SHAPER_DATA_GET(object) HB_SHAPER_DATA (HB_SHAPER, object).get ()
-#endif
-
-
 #endif /* HB_SHAPER_IMPL_HH */
diff --git a/src/hb-shaper.hh b/src/hb-shaper.hh
index 07e88b0..0a8bb0d 100644
--- a/src/hb-shaper.hh
+++ b/src/hb-shaper.hh
@@ -28,6 +28,7 @@
 #define HB_SHAPER_HH
 
 #include "hb.hh"
+#include "hb-machinery.hh"
 
 typedef hb_bool_t hb_shape_func_t (hb_shape_plan_t    *shape_plan,
 				   hb_font_t          *font,
@@ -49,36 +50,7 @@
 _hb_shapers_get (void);
 
 
-/* Means: succeeded, but don't need to keep any data. */
-#define HB_SHAPER_DATA_SUCCEEDED ((void *) +1)
-/* Means: tried but failed to create. */
-#define HB_SHAPER_DATA_INVALID ((void *) -1)
-
-#define HB_SHAPER_DATA_TYPE_NAME(shaper, object)	hb_##shaper##_##object##_data_t
-#define HB_SHAPER_DATA_TYPE(shaper, object)		struct HB_SHAPER_DATA_TYPE_NAME(shaper, object)
-#define HB_SHAPER_DATA_INSTANCE(shaper, object, instance)	(* reinterpret_cast<hb_atomic_ptr_t<HB_SHAPER_DATA_TYPE(shaper, object) *> *> (&(instance)->shaper_data.shaper))
-#define HB_SHAPER_DATA(shaper, object)			HB_SHAPER_DATA_INSTANCE(shaper, object, object)
-#define HB_SHAPER_DATA_CREATE_FUNC(shaper, object)	_hb_##shaper##_shaper_##object##_data_create
-#define HB_SHAPER_DATA_DESTROY_FUNC(shaper, object)	_hb_##shaper##_shaper_##object##_data_destroy
-#define HB_SHAPER_DATA_ENSURE_FUNC(shaper, object)	hb_##shaper##_shaper_##object##_data_ensure
-
-#define HB_SHAPER_DATA_PROTOTYPE(shaper, object) \
-	HB_SHAPER_DATA_TYPE (shaper, object); /* Type forward declaration. */ \
-	extern "C" HB_INTERNAL HB_SHAPER_DATA_TYPE (shaper, object) * \
-	HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (hb_##object##_t *object HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS); \
-	extern "C" HB_INTERNAL void \
-	HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *data); \
-	extern "C" HB_INTERNAL bool \
-	HB_SHAPER_DATA_ENSURE_FUNC (shaper, object) (hb_##object##_t *object)
-
-#define HB_SHAPER_DATA_DESTROY(shaper, object) \
-    if (HB_SHAPER_DATA_TYPE (shaper, object) *data = HB_SHAPER_DATA (shaper, object).get ()) \
-      if (data != HB_SHAPER_DATA_INVALID && data != HB_SHAPER_DATA_SUCCEEDED) \
-        HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data);
-
-#define HB_SHAPER_DATA_ENSURE_DEFINE(shaper, object) \
-	HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(shaper, object, true)
-
+#if 0
 #define HB_SHAPER_DATA_ENSURE_DEFINE_WITH_CONDITION(shaper, object, condition) \
 bool \
 HB_SHAPER_DATA_ENSURE_FUNC(shaper, object) (hb_##object##_t *object) \
@@ -111,9 +83,7 @@
     if (unlikely (!data)) \
       data = (HB_SHAPER_DATA_TYPE (shaper, object) *) HB_SHAPER_DATA_INVALID; \
     if (unlikely (!HB_SHAPER_DATA (shaper, object).cmpexch (nullptr, data))) { \
-      if (data && \
-	  data != HB_SHAPER_DATA_INVALID && \
-	  data != HB_SHAPER_DATA_SUCCEEDED) \
+      if (data) \
 	HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (data); \
       goto retry; \
     } \
@@ -121,15 +91,88 @@
   return data != nullptr && (void *) data != HB_SHAPER_DATA_INVALID; \
 } \
 static_assert (true, "") /* Require semicolon. */
+#endif
 
 
-/* For embedding in face / font / ... */
-struct hb_shaper_data_t {
-#define HB_SHAPER_IMPLEMENT(shaper) hb_atomic_ptr_t<void *> shaper;
+template <typename Data, unsigned int WheresData, typename T>
+struct hb_shaper_lazy_loader_t;
+
+#define HB_SHAPER_ORDER(Shaper) \
+  HB_PASTE (HB_SHAPER_ORDER_, Shaper)
+enum hb_shaper_order_t
+{
+  _HB_SHAPER_ORDER_ORDER_ZERO,
+#define HB_SHAPER_IMPLEMENT(Shaper) \
+      HB_SHAPER_ORDER (Shaper),
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+  _HB_SHAPERS_COUNT_PLUS_ONE,
+  HB_SHAPERS_COUNT = _HB_SHAPERS_COUNT_PLUS_ONE - 1,
+};
+
+template <enum hb_shaper_order_t order, typename Object> struct hb_shaper_object_data_type_t;
+
+#define HB_SHAPER_DATA_SUCCEEDED ((void *) +1)
+#define HB_SHAPER_DATA_TYPE(shaper, object)		hb_##shaper##_##object##_data_t
+#define HB_SHAPER_DATA_CREATE_FUNC(shaper, object)	_hb_##shaper##_shaper_##object##_data_create
+#define HB_SHAPER_DATA_DESTROY_FUNC(shaper, object)	_hb_##shaper##_shaper_##object##_data_destroy
+
+#define HB_SHAPER_DATA_INSTANTIATE_SHAPERS(shaper, object) \
+	\
+	struct HB_SHAPER_DATA_TYPE (shaper, object); /* Type forward declaration. */ \
+	extern "C" HB_INTERNAL HB_SHAPER_DATA_TYPE (shaper, object) * \
+	HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (hb_##object##_t *object); \
+	extern "C" HB_INTERNAL void \
+	HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (HB_SHAPER_DATA_TYPE (shaper, object) *shaper##_##object); \
+	\
+	template <> \
+	struct hb_shaper_object_data_type_t<HB_SHAPER_ORDER (shaper), hb_##object##_t> \
+	{ \
+	  typedef HB_SHAPER_DATA_TYPE(shaper, object) value; \
+	}; \
+	\
+	template <unsigned int WheresData> \
+	struct hb_shaper_lazy_loader_t<hb_##object##_t, WheresData, HB_SHAPER_DATA_TYPE(shaper, object)> \
+		: hb_lazy_loader_t<HB_SHAPER_DATA_TYPE(shaper, object), \
+				   hb_shaper_lazy_loader_t<hb_##object##_t, \
+							   WheresData, \
+							   HB_SHAPER_DATA_TYPE(shaper, object)>, \
+				   hb_##object##_t, WheresData> \
+	{ \
+	  typedef HB_SHAPER_DATA_TYPE(shaper, object) Type; \
+	  static inline Type* create (hb_##object##_t *data) \
+	  { return HB_SHAPER_DATA_CREATE_FUNC (shaper, object) (data); } \
+	  static inline Type *get_null (void) { return nullptr; } \
+	  static inline void destroy (Type *p) { HB_SHAPER_DATA_DESTROY_FUNC (shaper, object) (p); } \
+	}; \
+	\
+	static_assert (true, "") /* Require semicolon. */
+
+
+template <typename Object>
+struct hb_shaper_object_dataset_t
+{
+  inline void init0 (Object *parent_data)
+  {
+    this->parent_data = parent_data;
+#define HB_SHAPER_IMPLEMENT(shaper) shaper.init0 ();
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+  }
+  inline void fini (void)
+  {
+#define HB_SHAPER_IMPLEMENT(shaper) shaper.fini ();
+#include "hb-shaper-list.hh"
+#undef HB_SHAPER_IMPLEMENT
+  }
+
+  Object *parent_data; /* MUST be JUST before the lazy loaders. */
+#define HB_SHAPER_IMPLEMENT(shaper) \
+	hb_shaper_lazy_loader_t<Object, HB_SHAPER_ORDER(shaper), \
+				typename hb_shaper_object_data_type_t<HB_SHAPER_ORDER(shaper), Object>::value \
+			       > shaper;
 #include "hb-shaper-list.hh"
 #undef HB_SHAPER_IMPLEMENT
 };
-#define HB_SHAPERS_COUNT (sizeof (hb_shaper_data_t) / sizeof (void *))
-
 
 #endif /* HB_SHAPER_HH */
diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc
index dc82d6b..1331704 100644
--- a/src/hb-uniscribe.cc
+++ b/src/hb-uniscribe.cc
@@ -25,7 +25,6 @@
  */
 
 #include "hb.hh"
-#define HB_SHAPER uniscribe
 #include "hb-shaper-impl.hh"
 
 #include <windows.h>
@@ -314,9 +313,6 @@
   unsigned int index_last;  /* == end - 1 */
 };
 
-HB_SHAPER_DATA_ENSURE_DEFINE(uniscribe, face);
-HB_SHAPER_DATA_ENSURE_DEFINE(uniscribe, font);
-
 
 /*
  * shaper face data
@@ -503,11 +499,12 @@
  * shaper font data
  */
 
-struct hb_uniscribe_font_data_t {
+struct hb_uniscribe_font_data_t
+{
   HDC hdc;
-  LOGFONTW log_font;
+  mutable LOGFONTW log_font;
   HFONT hfont;
-  SCRIPT_CACHE script_cache;
+  mutable SCRIPT_CACHE script_cache;
   double x_mult, y_mult; /* From LOGFONT space to HB space. */
 };
 
@@ -520,10 +517,7 @@
   lf->lfHeight = - (int) font_size;
   lf->lfCharSet = DEFAULT_CHARSET;
 
-  hb_face_t *face = font->face;
-  hb_uniscribe_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
-
-  memcpy (lf->lfFaceName, face_data->face_name, sizeof (lf->lfFaceName));
+  memcpy (lf->lfFaceName, font->face->data.uniscribe->face_name, sizeof (lf->lfFaceName));
 
   return true;
 }
@@ -531,8 +525,6 @@
 hb_uniscribe_font_data_t *
 _hb_uniscribe_shaper_font_data_create (hb_font_t *font)
 {
-  if (unlikely (!hb_uniscribe_shaper_face_data_ensure (font->face))) return nullptr;
-
   hb_uniscribe_font_data_t *data = (hb_uniscribe_font_data_t *) calloc (1, sizeof (hb_uniscribe_font_data_t));
   if (unlikely (!data))
     return nullptr;
@@ -586,17 +578,15 @@
 LOGFONTW *
 hb_uniscribe_font_get_logfontw (hb_font_t *font)
 {
-  if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return nullptr;
-  hb_uniscribe_font_data_t *font_data =  HB_SHAPER_DATA_GET (font);
-  return &font_data->log_font;
+  const hb_uniscribe_font_data_t *data =  font->data.uniscribe;
+  return data ? &data->log_font : nullptr;
 }
 
 HFONT
 hb_uniscribe_font_get_hfont (hb_font_t *font)
 {
-  if (unlikely (!hb_uniscribe_shaper_font_data_ensure (font))) return nullptr;
-  hb_uniscribe_font_data_t *font_data =  HB_SHAPER_DATA_GET (font);
-  return font_data->hfont;
+  const hb_uniscribe_font_data_t *data =  font->data.uniscribe;
+  return data ? data->hfont : nullptr;
 }
 
 
@@ -613,8 +603,8 @@
 		     unsigned int        num_features)
 {
   hb_face_t *face = font->face;
-  hb_uniscribe_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
-  hb_uniscribe_font_data_t *font_data = HB_SHAPER_DATA_GET (font);
+  const hb_uniscribe_face_data_t *face_data = face->data.uniscribe;
+  const hb_uniscribe_font_data_t *font_data = font->data.uniscribe;
   hb_uniscribe_shaper_funcs_t *funcs = face_data->funcs;
 
   /*