[cff2] Malloc-free draw of var blends
diff --git a/src/hb-cff2-interp-cs.hh b/src/hb-cff2-interp-cs.hh
index 06fbb72..790aae3 100644
--- a/src/hb-cff2-interp-cs.hh
+++ b/src/hb-cff2-interp-cs.hh
@@ -71,7 +71,8 @@
   template <typename ACC>
   cff2_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd,
 			const int *coords_=nullptr, unsigned int num_coords_=0)
-    : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs)
+    : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs),
+      cached_scalars_vector (&acc.cached_scalars_vector)
   {
     coords = coords_;
     num_coords = num_coords_;
@@ -80,9 +81,39 @@
     set_ivs (acc.privateDicts[fd].ivs);
   }
 
-  void fini ()
+  ~cff2_cs_interp_env_t ()
   {
-    SUPER::fini ();
+    release_scalars_vector (scalars);
+  }
+
+  hb_vector_t<float> *acquire_scalars_vector () const
+  {
+    hb_vector_t<float> *scalars = cached_scalars_vector->get_acquire ();
+
+    if (!scalars || !cached_scalars_vector->cmpexch (scalars, nullptr))
+    {
+      scalars = (hb_vector_t<float> *) hb_calloc (1, sizeof (hb_vector_t<float>));
+      if (unlikely (!scalars))
+	return nullptr;
+      scalars->init ();
+    }
+
+    return scalars;
+  }
+
+  void release_scalars_vector (hb_vector_t<float> *scalars) const
+  {
+    if (!scalars)
+      return;
+
+    scalars->clear ();
+
+    if (!cached_scalars_vector->cmpexch (nullptr, scalars))
+    {
+      scalars->fini ();
+      hb_free (scalars);
+    }
+    scalars = nullptr;
   }
 
   op_code_t fetch_op ()
@@ -111,14 +142,20 @@
   {
     if (!seen_blend)
     {
-      region_count = varStore->varStore.get_region_index_count (get_ivs ());
-      if (do_blend)
+      scalars = acquire_scalars_vector ();
+      if (unlikely (!scalars))
+	SUPER::set_error ();
+      else
       {
-	if (unlikely (!scalars.resize_exact (region_count)))
-	  SUPER::set_error ();
-	else
-	  varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords,
-						 &scalars[0], region_count);
+	region_count = varStore->varStore.get_region_index_count (get_ivs ());
+	if (do_blend)
+	{
+	  if (unlikely (!scalars->resize_exact (region_count)))
+	    SUPER::set_error ();
+	  else
+	    varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords,
+						   &(*scalars)[0], region_count);
+	}
       }
       seen_blend = true;
     }
@@ -149,11 +186,11 @@
     double v = 0;
     if (do_blend)
     {
-      if (likely (scalars.length == deltas.length))
+      if (likely (scalars && scalars->length == deltas.length))
       {
-        unsigned count = scalars.length;
+        unsigned count = scalars->length;
 	for (unsigned i = 0; i < count; i++)
-	  v += (double) scalars.arrayZ[i] * deltas.arrayZ[i].to_real ();
+	  v += (double) scalars->arrayZ[i] * deltas.arrayZ[i].to_real ();
       }
     }
     return v;
@@ -167,7 +204,8 @@
   const	 CFF2ItemVariationStore *varStore;
   unsigned int  region_count;
   unsigned int  ivs;
-  hb_vector_t<float>  scalars;
+  hb_vector_t<float>  *scalars = nullptr;
+  hb_atomic_t<hb_vector_t<float> *> *cached_scalars_vector = nullptr;
   bool	  do_blend;
   bool	  seen_vsindex_ = false;
   bool	  seen_blend = false;
diff --git a/src/hb-ot-cff2-table.hh b/src/hb-ot-cff2-table.hh
index f3b80a6..536c918 100644
--- a/src/hb-ot-cff2-table.hh
+++ b/src/hb-ot-cff2-table.hh
@@ -482,6 +482,13 @@
       privateDicts.fini ();
       hb_blob_destroy (blob);
       blob = nullptr;
+
+      auto *scalars = cached_scalars_vector.get_acquire ();
+      if (scalars && cached_scalars_vector.cmpexch (scalars, nullptr))
+      {
+	scalars->fini ();
+	hb_free (scalars);
+      }
     }
 
     hb_vector_t<uint16_t> *create_glyph_to_sid_map () const
@@ -509,6 +516,8 @@
     hb_vector_t<cff2_font_dict_values_t>     fontDicts;
     hb_vector_t<PRIVDICTVAL>  privateDicts;
 
+    mutable hb_atomic_t<hb_vector_t<float> *> cached_scalars_vector;
+
     unsigned int	      num_glyphs = 0;
   };