In trampoline implementation of get_glyph(), don't destroy user data twice!
authorBehdad Esfahbod <behdad@behdad.org>
Thu, 25 Feb 2016 00:16:05 +0000 (09:16 +0900)
committerBehdad Esfahbod <behdad@behdad.org>
Thu, 25 Feb 2016 00:16:05 +0000 (09:16 +0900)
src/hb-font.cc

index 6742b49..4953d00 100644 (file)
@@ -1546,6 +1546,7 @@ struct hb_trampoline_closure_t
 {
   void *user_data;
   hb_destroy_func_t destroy;
+  unsigned int ref_count;
 };
 
 template <typename FuncType>
@@ -1566,23 +1567,30 @@ trampoline_create (FuncType           func,
   trampoline_t *trampoline = (trampoline_t *) calloc (1, sizeof (trampoline_t));
 
   if (unlikely (!trampoline))
-  {
-    if (destroy)
-      destroy (user_data);
     return NULL;
-  }
 
   trampoline->closure.user_data = user_data;
   trampoline->closure.destroy = destroy;
+  trampoline->closure.ref_count = 1;
   trampoline->func = func;
 
   return trampoline;
 }
 
 static void
+trampoline_reference (hb_trampoline_closure_t *closure)
+{
+  closure->ref_count++;
+}
+
+static void
 trampoline_destroy (void *user_data)
 {
   hb_trampoline_closure_t *closure = (hb_trampoline_closure_t *) user_data;
+
+  if (--closure->ref_count)
+    return;
+
   if (closure->destroy)
     closure->destroy (closure->user_data);
   free (closure);
@@ -1634,16 +1642,21 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
   hb_font_get_glyph_trampoline_t *trampoline;
 
   trampoline = trampoline_create (func, user_data, destroy);
-  if (likely (trampoline))
-    hb_font_funcs_set_nominal_glyph_func (ffuncs,
-                                         hb_font_get_nominal_glyph_trampoline,
+  if (unlikely (!trampoline))
+  {
+    if (destroy)
+      destroy (user_data);
+    return;
+  }
+
+  hb_font_funcs_set_nominal_glyph_func (ffuncs,
+                                       hb_font_get_nominal_glyph_trampoline,
+                                       trampoline,
+                                       trampoline_destroy);
+
+  trampoline_reference (&trampoline->closure);
+  hb_font_funcs_set_variation_glyph_func (ffuncs,
+                                         hb_font_get_variation_glyph_trampoline,
                                          trampoline,
                                          trampoline_destroy);
-
-  trampoline = trampoline_create (func, user_data, destroy);
-  if (likely (trampoline))
-    hb_font_funcs_set_variation_glyph_func (ffuncs,
-                                           hb_font_get_variation_glyph_trampoline,
-                                           trampoline,
-                                           trampoline_destroy);
 }