[HarfBuzz] harfbuzz-ng: Branch 'master' - 18 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Tue May 10 21:38:38 PDT 2011


 Makefile.am                          |    6 
 configure.ac                         |    1 
 harfbuzz.doap                        |   24 ++
 src/hb-common.cc                     |   26 +-
 src/hb-font-private.hh               |   77 ++++++-
 src/hb-font.cc                       |  374 ++++++++++++++++++++---------------
 src/hb-font.h                        |  114 ++++------
 src/hb-ft.cc                         |  112 +++++-----
 src/hb-mutex-private.hh              |   76 ++-----
 src/hb-object-private.hh             |    6 
 src/hb-ot-layout-common-private.hh   |    8 
 src/hb-ot-layout-gdef-private.hh     |   34 +--
 src/hb-ot-layout-gpos-private.hh     |  121 +++++------
 src/hb-ot-layout-gsub-private.hh     |   24 +-
 src/hb-ot-layout-gsubgpos-private.hh |   11 -
 src/hb-ot-layout-private.hh          |   13 -
 src/hb-ot-layout.cc                  |   15 -
 src/hb-ot-shape.cc                   |   15 +
 src/hb-private.hh                    |  117 ++++++++--
 src/hb-unicode.h                     |   32 +-
 test/Makefile.am                     |    4 
 test/hb-test.h                       |    1 
 test/test-object.c                   |   24 ++
 23 files changed, 715 insertions(+), 520 deletions(-)

New commits:
commit a513dbcf73ab1cc39a7c9653034904d0c6cd9fe9
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed May 11 00:24:34 2011 -0400

    [API] Change signature of get_contour_point and get_kerning ffuncs
    
    get_contour_point now takes glyph id before point_index.
    
    get_kerning now takes a vector to fill-in.

diff --git a/src/hb-font.cc b/src/hb-font.cc
index 280b27a..6cd436d 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -44,16 +44,16 @@ HB_BEGIN_DECLS
 static hb_bool_t
 hb_font_get_contour_point_nil (hb_font_t *font HB_UNUSED,
 			       const void *font_data HB_UNUSED,
-			       unsigned int point_index HB_UNUSED,
-			       hb_codepoint_t glyph HB_UNUSED,
-			       hb_position_t *x HB_UNUSED,
-			       hb_position_t *y HB_UNUSED,
+			       hb_codepoint_t glyph,
+			       unsigned int point_index,
+			       hb_position_t *x,
+			       hb_position_t *y,
 			       const void *user_data HB_UNUSED)
 {
   if (font->parent) {
     hb_bool_t ret;
     ret = hb_font_get_contour_point (font->parent,
-				     point_index, glyph,
+				     glyph, point_index,
 				     x, y);
     font->parent_scale_position (x, y);
     return ret;
@@ -67,9 +67,9 @@ hb_font_get_contour_point_nil (hb_font_t *font HB_UNUSED,
 static void
 hb_font_get_glyph_advance_nil (hb_font_t *font HB_UNUSED,
 			       const void *font_data HB_UNUSED,
-			       hb_codepoint_t glyph HB_UNUSED,
-			       hb_position_t *x_advance HB_UNUSED,
-			       hb_position_t *y_advance HB_UNUSED,
+			       hb_codepoint_t glyph,
+			       hb_position_t *x_advance,
+			       hb_position_t *y_advance,
 			       const void *user_data HB_UNUSED)
 {
   if (font->parent) {
@@ -84,8 +84,8 @@ hb_font_get_glyph_advance_nil (hb_font_t *font HB_UNUSED,
 static void
 hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
 			       const void *font_data HB_UNUSED,
-			       hb_codepoint_t glyph HB_UNUSED,
-			       hb_glyph_extents_t *extents HB_UNUSED,
+			       hb_codepoint_t glyph,
+			       hb_glyph_extents_t *extents,
 			       const void *user_data HB_UNUSED)
 {
   if (font->parent) {
@@ -102,8 +102,8 @@ hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
 static hb_codepoint_t
 hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
 		       const void *font_data HB_UNUSED,
-		       hb_codepoint_t unicode HB_UNUSED,
-		       hb_codepoint_t variation_selector HB_UNUSED,
+		       hb_codepoint_t unicode,
+		       hb_codepoint_t variation_selector,
 		       const void *user_data HB_UNUSED)
 {
   if (font->parent)
@@ -112,21 +112,22 @@ hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
   return 0;
 }
 
-static hb_position_t
+static void
 hb_font_get_kerning_nil (hb_font_t *font HB_UNUSED,
 			 const void *font_data HB_UNUSED,
-			 hb_codepoint_t first_glyph HB_UNUSED,
-			 hb_codepoint_t second_glyph HB_UNUSED,
+			 hb_codepoint_t first_glyph,
+			 hb_codepoint_t second_glyph,
+			 hb_position_t *x_kern,
+			 hb_position_t *y_kern,
 			 const void *user_data HB_UNUSED)
 {
   if (font->parent) {
-    hb_position_t ret;
-    ret = hb_font_get_kerning (font->parent, first_glyph, second_glyph);
-    ret = font->parent_scale_x_distance (ret);
-    return ret;
+    hb_font_get_kerning (font->parent, first_glyph, second_glyph, x_kern, y_kern);
+    font->parent_scale_distance (x_kern, y_kern);
+    return;
   }
 
-  return 0;
+  *x_kern = *y_kern = 0;
 }
 
 
@@ -249,13 +250,13 @@ IMPLEMENT (kerning);
 
 hb_bool_t
 hb_font_get_contour_point (hb_font_t *font,
-			   unsigned int point_index,
-			   hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y)
+			   hb_codepoint_t glyph, unsigned int point_index,
+			   hb_position_t *x, hb_position_t *y)
 {
   *x = 0; *y = 0;
   return font->klass->get.contour_point (font, font->user_data,
-					 point_index,
-					 glyph, x, y,
+					 glyph, point_index,
+					 x, y,
 					 font->klass->user_data.contour_point);
 }
 
@@ -289,12 +290,15 @@ hb_font_get_glyph (hb_font_t *font,
 				 font->klass->user_data.glyph);
 }
 
-hb_position_t
+void
 hb_font_get_kerning (hb_font_t *font,
-		     hb_codepoint_t first_glyph, hb_codepoint_t second_glyph)
+		     hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+		     hb_position_t *x_kern, hb_position_t *y_kern)
 {
+  *x_kern = *y_kern = 0;
   return font->klass->get.kerning (font, font->user_data,
 				   first_glyph, second_glyph,
+				   x_kern, y_kern,
 				   font->klass->user_data.kerning);
 }
 
diff --git a/src/hb-font.h b/src/hb-font.h
index d4a5441..ce81985 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -123,7 +123,7 @@ typedef struct _hb_glyph_extents_t
 
 
 typedef hb_bool_t (*hb_font_get_contour_point_func_t) (hb_font_t *font, const void *font_data,
-						       unsigned int point_index, hb_codepoint_t glyph,
+						       hb_codepoint_t glyph, unsigned int point_index,
 						       hb_position_t *x, hb_position_t *y,
 						       const void *user_data);
 typedef void (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, const void *font_data,
@@ -137,9 +137,10 @@ typedef void (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, const void *f
 typedef hb_codepoint_t (*hb_font_get_glyph_func_t) (hb_font_t *font, const void *font_data,
 						    hb_codepoint_t unicode, hb_codepoint_t variation_selector,
 						    const void *user_data);
-typedef hb_position_t (*hb_font_get_kerning_func_t) (hb_font_t *font, const void *font_data,
-						     hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
-						     const void *user_data);
+typedef void (*hb_font_get_kerning_func_t) (hb_font_t *font, const void *font_data,
+					    hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+					    hb_position_t *x_kern, hb_position_t *y_kern,
+					    const void *user_data);
 
 
 void
@@ -170,7 +171,7 @@ hb_font_funcs_set_kerning_func (hb_font_funcs_t *ffuncs,
 
 hb_bool_t
 hb_font_get_contour_point (hb_font_t *font,
-			   unsigned int point_index, hb_codepoint_t glyph,
+			   hb_codepoint_t glyph, unsigned int point_index,
 			   hb_position_t *x, hb_position_t *y);
 
 void
@@ -187,9 +188,10 @@ hb_codepoint_t
 hb_font_get_glyph (hb_font_t *font,
 		   hb_codepoint_t unicode, hb_codepoint_t variation_selector);
 
-hb_position_t
+void
 hb_font_get_kerning (hb_font_t *font,
-		     hb_codepoint_t first_glyph, hb_codepoint_t second_glyph);
+		     hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+		     hb_position_t *x_kern, hb_position_t *y_kern);
 
 
 /*
diff --git a/src/hb-ft.cc b/src/hb-ft.cc
index 50ab09f..2566c05 100644
--- a/src/hb-ft.cc
+++ b/src/hb-ft.cc
@@ -39,8 +39,8 @@ HB_BEGIN_DECLS
 static hb_bool_t
 hb_ft_get_contour_point (hb_font_t *font HB_UNUSED,
 			 const void *font_data,
-			 unsigned int point_index,
 			 hb_codepoint_t glyph,
+			 unsigned int point_index,
 			 hb_position_t *x,
 			 hb_position_t *y,
 			 const void *user_data HB_UNUSED)
@@ -128,11 +128,13 @@ hb_ft_get_glyph (hb_font_t *font HB_UNUSED,
   return FT_Get_Char_Index (ft_face, unicode);
 }
 
-static hb_position_t
+static void
 hb_ft_get_kerning (hb_font_t *font HB_UNUSED,
 		   const void *font_data,
 		   hb_codepoint_t first_glyph,
 		   hb_codepoint_t second_glyph,
+		   hb_position_t *x_kern,
+		   hb_position_t *y_kern,
 		   const void *user_data HB_UNUSED)
 {
   FT_Face ft_face = (FT_Face) font_data;
@@ -140,9 +142,10 @@ hb_ft_get_kerning (hb_font_t *font HB_UNUSED,
 
   /* TODO: Kern type? */
   if (FT_Get_Kerning (ft_face, first_glyph, second_glyph, FT_KERNING_DEFAULT, &kerning))
-      return 0;
+    return;
 
-  return kerning.x;
+  *x_kern = kerning.x;
+  *y_kern = kerning.y;
 }
 
 static hb_font_funcs_t ft_ffuncs = {
diff --git a/src/hb-ot-layout-gdef-private.hh b/src/hb-ot-layout-gdef-private.hh
index 910f32d..d06d7c2 100644
--- a/src/hb-ot-layout-gdef-private.hh
+++ b/src/hb-ot-layout-gdef-private.hh
@@ -121,7 +121,7 @@ struct CaretValueFormat2
   inline int get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
   {
     hb_position_t x, y;
-    if (hb_font_get_contour_point (font, caretValuePoint, glyph_id, &x, &y))
+    if (hb_font_get_contour_point (font, glyph_id, caretValuePoint, &x, &y))
       return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
     else
       return 0;
diff --git a/src/hb-ot-layout-gpos-private.hh b/src/hb-ot-layout-gpos-private.hh
index 21c6241..100be67 100644
--- a/src/hb-ot-layout-gpos-private.hh
+++ b/src/hb-ot-layout-gpos-private.hh
@@ -243,7 +243,7 @@ struct AnchorFormat2
       hb_bool_t ret = false;
 
       if (x_ppem || y_ppem)
-	ret = hb_font_get_contour_point (font, anchorPoint, glyph_id, &cx, &cy);
+	ret = hb_font_get_contour_point (font, glyph_id, anchorPoint, &cx, &cy);
       *x = x_ppem && ret ? cx : font->em_scale_x (xCoordinate);
       *y = y_ppem && ret ? cy : font->em_scale_y (yCoordinate);
   }
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 306bb41..4f90027 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -271,13 +271,20 @@ hb_truetype_kern (hb_ot_shape_context_t *c)
   /* TODO Check for kern=0 */
   unsigned int count = c->buffer->len;
   for (unsigned int i = 1; i < count; i++) {
-    hb_position_t kern, kern1, kern2;
-    kern = hb_font_get_kerning (c->font, c->buffer->info[i - 1].codepoint, c->buffer->info[i].codepoint);
-    kern1 = kern >> 1;
-    kern2 = kern - kern1;
+    hb_position_t x_kern, y_kern, kern1, kern2;
+    hb_font_get_kerning (c->font, c->buffer->info[i - 1].codepoint, c->buffer->info[i].codepoint, &x_kern, &y_kern);
+
+    kern1 = x_kern >> 1;
+    kern2 = x_kern - kern1;
     c->buffer->pos[i - 1].x_advance += kern1;
     c->buffer->pos[i].x_advance += kern2;
     c->buffer->pos[i].x_offset += kern2;
+
+    kern1 = y_kern >> 1;
+    kern2 = y_kern - kern1;
+    c->buffer->pos[i - 1].y_advance += kern1;
+    c->buffer->pos[i].y_advance += kern2;
+    c->buffer->pos[i].y_offset += kern2;
   }
 }
 
commit 63d646fb2933c2765ce526d321a498d0f7fae2f5
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed May 11 00:15:37 2011 -0400

    [font] Do user-space conversion when chaining up to parent font

diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index 203cd23..f60ce97 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -118,6 +118,34 @@ struct _hb_font_t {
   inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); }
   inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); }
 
+  /* Convert from parent-font user-space to our user-space */
+  inline hb_position_t parent_scale_x_distance (hb_position_t v) {
+    if (unlikely (parent && parent->x_scale != x_scale))
+      return v * (int64_t) this->x_scale / this->parent->x_scale;
+    return v;
+  }
+  inline hb_position_t parent_scale_y_distance (hb_position_t v) {
+    if (unlikely (parent && parent->y_scale != y_scale))
+      return v * (int64_t) this->y_scale / this->parent->y_scale;
+    return v;
+  }
+  inline hb_position_t parent_scale_x_position (hb_position_t v) {
+    return parent_scale_x_distance (v); /* We don't have translation right now */
+  }
+  inline hb_position_t parent_scale_y_position (hb_position_t v) {
+    return parent_scale_y_distance (v); /* We don't have translation right now */
+  }
+
+  inline void parent_scale_distance (hb_position_t *x, hb_position_t *y) {
+    *x = parent_scale_x_distance (*x);
+    *y = parent_scale_y_distance (*y);
+  }
+  inline void parent_scale_position (hb_position_t *x, hb_position_t *y) {
+    *x = parent_scale_x_position (*x);
+    *y = parent_scale_y_position (*y);
+  }
+
+
   private:
   inline hb_position_t em_scale (int16_t v, int scale) { return v * (int64_t) scale / this->face->upem; }
 };
diff --git a/src/hb-font.cc b/src/hb-font.cc
index 3dcc417..280b27a 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -50,10 +50,14 @@ hb_font_get_contour_point_nil (hb_font_t *font HB_UNUSED,
 			       hb_position_t *y HB_UNUSED,
 			       const void *user_data HB_UNUSED)
 {
-  if (font->parent)
-    return hb_font_get_contour_point (font->parent,
-				      point_index, glyph,
-				      x, y);
+  if (font->parent) {
+    hb_bool_t ret;
+    ret = hb_font_get_contour_point (font->parent,
+				     point_index, glyph,
+				     x, y);
+    font->parent_scale_position (x, y);
+    return ret;
+  }
 
   *x = *y = 0;
 
@@ -70,6 +74,7 @@ hb_font_get_glyph_advance_nil (hb_font_t *font HB_UNUSED,
 {
   if (font->parent) {
     hb_font_get_glyph_advance (font->parent, glyph, x_advance, y_advance);
+    font->parent_scale_distance (x_advance, y_advance);
     return;
   }
 
@@ -85,6 +90,8 @@ hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
 {
   if (font->parent) {
     hb_font_get_glyph_extents (font->parent, glyph, extents);
+    font->parent_scale_position (&extents->x_bearing, &extents->y_bearing);
+    font->parent_scale_distance (&extents->width, &extents->height);
     return;
   }
 
@@ -112,8 +119,12 @@ hb_font_get_kerning_nil (hb_font_t *font HB_UNUSED,
 			 hb_codepoint_t second_glyph HB_UNUSED,
 			 const void *user_data HB_UNUSED)
 {
-  if (font->parent)
-    return hb_font_get_kerning (font->parent, first_glyph, second_glyph);
+  if (font->parent) {
+    hb_position_t ret;
+    ret = hb_font_get_kerning (font->parent, first_glyph, second_glyph);
+    ret = font->parent_scale_x_distance (ret);
+    return ret;
+  }
 
   return 0;
 }
commit b6f902a1a9c8b72b5d6a241a14a7bacfaea3a56a
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed May 11 00:04:15 2011 -0400

    Minor

diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index bd3000a..203cd23 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -115,11 +115,11 @@ struct _hb_font_t {
 
 
   /* Convert from font-space to user-space */
-  inline hb_position_t scale_x (int16_t v) { return scale (v, this->x_scale); }
-  inline hb_position_t scale_y (int16_t v) { return scale (v, this->y_scale); }
+  inline hb_position_t em_scale_x (int16_t v) { return em_scale (v, this->x_scale); }
+  inline hb_position_t em_scale_y (int16_t v) { return em_scale (v, this->y_scale); }
 
   private:
-  inline hb_position_t scale (int16_t v, int scale) { return v * (int64_t) scale / this->face->upem; }
+  inline hb_position_t em_scale (int16_t v, int scale) { return v * (int64_t) scale / this->face->upem; }
 };
 
 
diff --git a/src/hb-ot-layout-gdef-private.hh b/src/hb-ot-layout-gdef-private.hh
index 52ac064..910f32d 100644
--- a/src/hb-ot-layout-gdef-private.hh
+++ b/src/hb-ot-layout-gdef-private.hh
@@ -98,7 +98,7 @@ struct CaretValueFormat1
   private:
   inline int get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const
   {
-    return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->scale_x (coordinate) : font->scale_y (coordinate);
+    return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_x (coordinate) : font->em_scale_y (coordinate);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) {
@@ -146,8 +146,8 @@ struct CaretValueFormat3
   inline int get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
   {
     return HB_DIRECTION_IS_HORIZONTAL (direction) ?
-           font->scale_x (coordinate) + (this+deviceTable).get_x_delta (font) :
-           font->scale_y (coordinate) + (this+deviceTable).get_y_delta (font);
+           font->em_scale_x (coordinate) + (this+deviceTable).get_x_delta (font) :
+           font->em_scale_y (coordinate) + (this+deviceTable).get_y_delta (font);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) {
diff --git a/src/hb-ot-layout-gpos-private.hh b/src/hb-ot-layout-gpos-private.hh
index e8b5046..21c6241 100644
--- a/src/hb-ot-layout-gpos-private.hh
+++ b/src/hb-ot-layout-gpos-private.hh
@@ -105,10 +105,10 @@ struct ValueFormat : USHORT
     if (!format) return;
 
     /* design units -> fractional pixel */
-    if (format & xPlacement) glyph_pos.x_offset  += font->scale_x (get_short (values++));
-    if (format & yPlacement) glyph_pos.y_offset  += font->scale_y (get_short (values++));
-    if (format & xAdvance)   glyph_pos.x_advance += font->scale_x (get_short (values++));
-    if (format & yAdvance)   glyph_pos.y_advance += font->scale_y (get_short (values++));
+    if (format & xPlacement) glyph_pos.x_offset  += font->em_scale_x (get_short (values++));
+    if (format & yPlacement) glyph_pos.y_offset  += font->em_scale_y (get_short (values++));
+    if (format & xAdvance)   glyph_pos.x_advance += font->em_scale_x (get_short (values++));
+    if (format & yAdvance)   glyph_pos.y_advance += font->em_scale_y (get_short (values++));
 
     if (!has_device ()) return;
 
@@ -212,8 +212,8 @@ struct AnchorFormat1
   inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED,
 			  hb_position_t *x, hb_position_t *y) const
   {
-      *x = font->scale_x (xCoordinate);
-      *y = font->scale_y (yCoordinate);
+      *x = font->em_scale_x (xCoordinate);
+      *y = font->em_scale_y (yCoordinate);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) {
@@ -244,8 +244,8 @@ struct AnchorFormat2
 
       if (x_ppem || y_ppem)
 	ret = hb_font_get_contour_point (font, anchorPoint, glyph_id, &cx, &cy);
-      *x = x_ppem && ret ? cx : font->scale_x (xCoordinate);
-      *y = y_ppem && ret ? cy : font->scale_y (yCoordinate);
+      *x = x_ppem && ret ? cx : font->em_scale_x (xCoordinate);
+      *y = y_ppem && ret ? cy : font->em_scale_y (yCoordinate);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) {
@@ -270,8 +270,8 @@ struct AnchorFormat3
   inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED,
 			  hb_position_t *x, hb_position_t *y) const
   {
-      *x = font->scale_x (xCoordinate);
-      *y = font->scale_y (yCoordinate);
+      *x = font->em_scale_x (xCoordinate);
+      *y = font->em_scale_y (yCoordinate);
 
       /* pixel -> fractional pixel */
       if (font->x_ppem)
commit abcfe9b59b4475eb02dd679aac4bc59616713b28
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed May 11 00:02:02 2011 -0400

    Remove hb_ot_layout_context_t, simplify code

diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index e6c79fb..bd3000a 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -85,9 +85,9 @@ struct _hb_face_t {
   void                *user_data;
   hb_destroy_func_t    destroy;
 
-  hb_blob_t *head_blob;
-
   struct hb_ot_layout_t *ot_layout;
+
+  unsigned int upem;
 };
 
 
@@ -112,6 +112,14 @@ struct _hb_font_t {
   hb_font_funcs_t   *klass;
   void              *user_data;
   hb_destroy_func_t  destroy;
+
+
+  /* Convert from font-space to user-space */
+  inline hb_position_t scale_x (int16_t v) { return scale (v, this->x_scale); }
+  inline hb_position_t scale_y (int16_t v) { return scale (v, this->y_scale); }
+
+  private:
+  inline hb_position_t scale (int16_t v, int scale) { return v * (int64_t) scale / this->face->upem; }
 };
 
 
diff --git a/src/hb-font.cc b/src/hb-font.cc
index ace9694..3dcc417 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -299,7 +299,9 @@ static hb_face_t _hb_face_nil = {
   NULL, /* user_data */
   NULL, /* destroy */
 
-  NULL  /* ot_layout */
+  NULL, /* ot_layout */
+
+  1000
 };
 
 
@@ -322,6 +324,8 @@ hb_face_create_for_tables (hb_get_table_func_t  get_table,
 
   face->ot_layout = _hb_ot_layout_create (face);
 
+  face->upem = _hb_ot_layout_get_upem (face);
+
   return face;
 }
 
diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh
index 7ef214e..1381964 100644
--- a/src/hb-ot-layout-common-private.hh
+++ b/src/hb-ot-layout-common-private.hh
@@ -526,11 +526,11 @@ struct ClassDef
 struct Device
 {
 
-  inline hb_position_t get_x_delta (hb_ot_layout_context_t *c) const
-  { return get_delta (c->font->x_ppem, c->font->x_scale); }
+  inline hb_position_t get_x_delta (hb_font_t *font) const
+  { return get_delta (font->x_ppem, font->x_scale); }
 
-  inline hb_position_t get_y_delta (hb_ot_layout_context_t *c) const
-  { return get_delta (c->font->y_ppem, c->font->y_scale); }
+  inline hb_position_t get_y_delta (hb_font_t *font) const
+  { return get_delta (font->y_ppem, font->y_scale); }
 
   inline int get_delta (unsigned int ppem, int scale) const
   {
diff --git a/src/hb-ot-layout-gdef-private.hh b/src/hb-ot-layout-gdef-private.hh
index 010f819..52ac064 100644
--- a/src/hb-ot-layout-gdef-private.hh
+++ b/src/hb-ot-layout-gdef-private.hh
@@ -96,9 +96,9 @@ struct CaretValueFormat1
   friend struct CaretValue;
 
   private:
-  inline int get_caret_value (hb_ot_layout_context_t *c, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const
+  inline int get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id HB_UNUSED) const
   {
-    return HB_DIRECTION_IS_HORIZONTAL (direction) ? c->scale_x (coordinate) : c->scale_y (coordinate);
+    return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->scale_x (coordinate) : font->scale_y (coordinate);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) {
@@ -118,10 +118,10 @@ struct CaretValueFormat2
   friend struct CaretValue;
 
   private:
-  inline int get_caret_value (hb_ot_layout_context_t *c, hb_direction_t direction, hb_codepoint_t glyph_id) const
+  inline int get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
   {
     hb_position_t x, y;
-    if (hb_font_get_contour_point (c->font, caretValuePoint, glyph_id, &x, &y))
+    if (hb_font_get_contour_point (font, caretValuePoint, glyph_id, &x, &y))
       return HB_DIRECTION_IS_HORIZONTAL (direction) ? x : y;
     else
       return 0;
@@ -143,11 +143,11 @@ struct CaretValueFormat3
 {
   friend struct CaretValue;
 
-  inline int get_caret_value (hb_ot_layout_context_t *c, hb_direction_t direction, hb_codepoint_t glyph_id) const
+  inline int get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
   {
     return HB_DIRECTION_IS_HORIZONTAL (direction) ?
-           c->scale_x (coordinate) + (this+deviceTable).get_x_delta (c) :
-           c->scale_y (coordinate) + (this+deviceTable).get_y_delta (c);
+           font->scale_x (coordinate) + (this+deviceTable).get_x_delta (font) :
+           font->scale_y (coordinate) + (this+deviceTable).get_y_delta (font);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) {
@@ -169,12 +169,12 @@ struct CaretValueFormat3
 
 struct CaretValue
 {
-  inline int get_caret_value (hb_ot_layout_context_t *c, hb_direction_t direction, hb_codepoint_t glyph_id) const
+  inline int get_caret_value (hb_font_t *font, hb_direction_t direction, hb_codepoint_t glyph_id) const
   {
     switch (u.format) {
-    case 1: return u.format1.get_caret_value (c, direction, glyph_id);
-    case 2: return u.format2.get_caret_value (c, direction, glyph_id);
-    case 3: return u.format3.get_caret_value (c, direction, glyph_id);
+    case 1: return u.format1.get_caret_value (font, direction, glyph_id);
+    case 2: return u.format2.get_caret_value (font, direction, glyph_id);
+    case 3: return u.format3.get_caret_value (font, direction, glyph_id);
     default:return 0;
     }
   }
@@ -203,7 +203,7 @@ struct CaretValue
 
 struct LigGlyph
 {
-  inline unsigned int get_lig_carets (hb_ot_layout_context_t *c,
+  inline unsigned int get_lig_carets (hb_font_t *font,
 				      hb_direction_t direction,
 				      hb_codepoint_t glyph_id,
 				      unsigned int start_offset,
@@ -214,7 +214,7 @@ struct LigGlyph
       const OffsetTo<CaretValue> *array = carets.sub_array (start_offset, caret_count);
       unsigned int count = *caret_count;
       for (unsigned int i = 0; i < count; i++)
-	caret_array[i] = (this+array[i]).get_caret_value (c, direction, glyph_id);
+	caret_array[i] = (this+array[i]).get_caret_value (font, direction, glyph_id);
     }
 
     return carets.len;
@@ -236,7 +236,7 @@ struct LigGlyph
 
 struct LigCaretList
 {
-  inline unsigned int get_lig_carets (hb_ot_layout_context_t *c,
+  inline unsigned int get_lig_carets (hb_font_t *font,
 				      hb_direction_t direction,
 				      hb_codepoint_t glyph_id,
 				      unsigned int start_offset,
@@ -251,7 +251,7 @@ struct LigCaretList
       return 0;
     }
     const LigGlyph &lig_glyph = this+ligGlyph[index];
-    return lig_glyph.get_lig_carets (c, direction, glyph_id, start_offset, caret_count, caret_array);
+    return lig_glyph.get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) {
@@ -352,13 +352,13 @@ struct GDEF
   { return (this+attachList).get_attach_points (glyph_id, start_offset, point_count, point_array); }
 
   inline bool has_lig_carets (void) const { return ligCaretList != 0; }
-  inline unsigned int get_lig_carets (hb_ot_layout_context_t *c,
+  inline unsigned int get_lig_carets (hb_font_t *font,
 				      hb_direction_t direction,
 				      hb_codepoint_t glyph_id,
 				      unsigned int start_offset,
 				      unsigned int *caret_count /* IN/OUT */,
 				      int *caret_array /* OUT */) const
-  { return (this+ligCaretList).get_lig_carets (c, direction, glyph_id, start_offset, caret_count, caret_array); }
+  { return (this+ligCaretList).get_lig_carets (font, direction, glyph_id, start_offset, caret_count, caret_array); }
 
   inline bool has_mark_sets (void) const { return version >= 0x00010002 && markGlyphSetsDef[0] != 0; }
   inline bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
diff --git a/src/hb-ot-layout-gpos-private.hh b/src/hb-ot-layout-gpos-private.hh
index 1e277ce..e8b5046 100644
--- a/src/hb-ot-layout-gpos-private.hh
+++ b/src/hb-ot-layout-gpos-private.hh
@@ -94,10 +94,10 @@ struct ValueFormat : USHORT
   inline unsigned int get_size (void) const
   { return get_len () * Value::static_size; }
 
-  void apply_value (hb_ot_layout_context_t *layout,
-		    const void             *base,
-		    const Value            *values,
-		    hb_glyph_position_t    &glyph_pos) const
+  void apply_value (hb_font_t            *font,
+		    const void           *base,
+		    const Value          *values,
+		    hb_glyph_position_t  &glyph_pos) const
   {
     unsigned int x_ppem, y_ppem;
     unsigned int format = *this;
@@ -105,30 +105,30 @@ struct ValueFormat : USHORT
     if (!format) return;
 
     /* design units -> fractional pixel */
-    if (format & xPlacement) glyph_pos.x_offset  += layout->scale_x (get_short (values++));
-    if (format & yPlacement) glyph_pos.y_offset  += layout->scale_y (get_short (values++));
-    if (format & xAdvance)   glyph_pos.x_advance += layout->scale_x (get_short (values++));
-    if (format & yAdvance)   glyph_pos.y_advance += layout->scale_y (get_short (values++));
+    if (format & xPlacement) glyph_pos.x_offset  += font->scale_x (get_short (values++));
+    if (format & yPlacement) glyph_pos.y_offset  += font->scale_y (get_short (values++));
+    if (format & xAdvance)   glyph_pos.x_advance += font->scale_x (get_short (values++));
+    if (format & yAdvance)   glyph_pos.y_advance += font->scale_y (get_short (values++));
 
     if (!has_device ()) return;
 
-    x_ppem = layout->font->x_ppem;
-    y_ppem = layout->font->y_ppem;
+    x_ppem = font->x_ppem;
+    y_ppem = font->y_ppem;
 
     if (!x_ppem && !y_ppem) return;
 
     /* pixel -> fractional pixel */
     if (format & xPlaDevice) {
-      if (x_ppem) glyph_pos.x_offset  += (base + get_device (values++)).get_x_delta (layout); else values++;
+      if (x_ppem) glyph_pos.x_offset  += (base + get_device (values++)).get_x_delta (font); else values++;
     }
     if (format & yPlaDevice) {
-      if (y_ppem) glyph_pos.y_offset  += (base + get_device (values++)).get_y_delta (layout); else values++;
+      if (y_ppem) glyph_pos.y_offset  += (base + get_device (values++)).get_y_delta (font); else values++;
     }
     if (format & xAdvDevice) {
-      if (x_ppem) glyph_pos.x_advance += (base + get_device (values++)).get_x_delta (layout); else values++;
+      if (x_ppem) glyph_pos.x_advance += (base + get_device (values++)).get_x_delta (font); else values++;
     }
     if (format & yAdvDevice) {
-      if (y_ppem) glyph_pos.y_advance += (base + get_device (values++)).get_y_delta (layout); else values++;
+      if (y_ppem) glyph_pos.y_advance += (base + get_device (values++)).get_y_delta (font); else values++;
     }
   }
 
@@ -209,11 +209,11 @@ struct AnchorFormat1
   friend struct Anchor;
 
   private:
-  inline void get_anchor (hb_ot_layout_context_t *layout, hb_codepoint_t glyph_id HB_UNUSED,
+  inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED,
 			  hb_position_t *x, hb_position_t *y) const
   {
-      *x = layout->scale_x (xCoordinate);
-      *y = layout->scale_y (yCoordinate);
+      *x = font->scale_x (xCoordinate);
+      *y = font->scale_y (yCoordinate);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) {
@@ -234,18 +234,18 @@ struct AnchorFormat2
   friend struct Anchor;
 
   private:
-  inline void get_anchor (hb_ot_layout_context_t *layout, hb_codepoint_t glyph_id,
+  inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id,
 			  hb_position_t *x, hb_position_t *y) const
   {
-      unsigned int x_ppem = layout->font->x_ppem;
-      unsigned int y_ppem = layout->font->y_ppem;
+      unsigned int x_ppem = font->x_ppem;
+      unsigned int y_ppem = font->y_ppem;
       hb_position_t cx, cy;
       hb_bool_t ret = false;
 
       if (x_ppem || y_ppem)
-	ret = hb_font_get_contour_point (layout->font, anchorPoint, glyph_id, &cx, &cy);
-      *x = x_ppem && ret ? cx : layout->scale_x (xCoordinate);
-      *y = y_ppem && ret ? cy : layout->scale_y (yCoordinate);
+	ret = hb_font_get_contour_point (font, anchorPoint, glyph_id, &cx, &cy);
+      *x = x_ppem && ret ? cx : font->scale_x (xCoordinate);
+      *y = y_ppem && ret ? cy : font->scale_y (yCoordinate);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) {
@@ -267,17 +267,17 @@ struct AnchorFormat3
   friend struct Anchor;
 
   private:
-  inline void get_anchor (hb_ot_layout_context_t *layout, hb_codepoint_t glyph_id HB_UNUSED,
+  inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id HB_UNUSED,
 			  hb_position_t *x, hb_position_t *y) const
   {
-      *x = layout->scale_x (xCoordinate);
-      *y = layout->scale_y (yCoordinate);
+      *x = font->scale_x (xCoordinate);
+      *y = font->scale_y (yCoordinate);
 
       /* pixel -> fractional pixel */
-      if (layout->font->x_ppem)
-	*x += (this+xDeviceTable).get_x_delta (layout);
-      if (layout->font->y_ppem)
-	*y += (this+yDeviceTable).get_x_delta (layout);
+      if (font->x_ppem)
+	*x += (this+xDeviceTable).get_x_delta (font);
+      if (font->y_ppem)
+	*y += (this+yDeviceTable).get_x_delta (font);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) {
@@ -305,15 +305,15 @@ struct AnchorFormat3
 
 struct Anchor
 {
-  inline void get_anchor (hb_ot_layout_context_t *layout, hb_codepoint_t glyph_id,
+  inline void get_anchor (hb_font_t *font, hb_codepoint_t glyph_id,
 			  hb_position_t *x, hb_position_t *y) const
   {
     *x = *y = 0;
     switch (u.format) {
-    case 1: u.format1.get_anchor (layout, glyph_id, x, y); return;
-    case 2: u.format2.get_anchor (layout, glyph_id, x, y); return;
-    case 3: u.format3.get_anchor (layout, glyph_id, x, y); return;
-    default:						    return;
+    case 1: u.format1.get_anchor (font, glyph_id, x, y); return;
+    case 2: u.format2.get_anchor (font, glyph_id, x, y); return;
+    case 3: u.format3.get_anchor (font, glyph_id, x, y); return;
+    default:						 return;
     }
   }
 
@@ -403,8 +403,8 @@ struct MarkArray : ArrayOf<MarkRecord>	/* Array of MarkRecords--in Coverage orde
 
     hb_position_t mark_x, mark_y, base_x, base_y;
 
-    mark_anchor.get_anchor (c->layout, c->buffer->info[c->buffer->i].codepoint, &mark_x, &mark_y);
-    glyph_anchor.get_anchor (c->layout, c->buffer->info[glyph_pos].codepoint, &base_x, &base_y);
+    mark_anchor.get_anchor (c->font, c->buffer->info[c->buffer->i].codepoint, &mark_x, &mark_y);
+    glyph_anchor.get_anchor (c->font, c->buffer->info[glyph_pos].codepoint, &base_x, &base_y);
 
     hb_glyph_position_t &o = c->buffer->pos[c->buffer->i];
     o.x_offset = base_x - mark_x;
@@ -436,7 +436,7 @@ struct SinglePosFormat1
     if (likely (index == NOT_COVERED))
       return false;
 
-    valueFormat.apply_value (c->layout, this, values, c->buffer->pos[c->buffer->i]);
+    valueFormat.apply_value (c->font, this, values, c->buffer->pos[c->buffer->i]);
 
     c->buffer->i++;
     return true;
@@ -478,7 +478,7 @@ struct SinglePosFormat2
     if (likely (index >= valueCount))
       return false;
 
-    valueFormat.apply_value (c->layout, this,
+    valueFormat.apply_value (c->font, this,
 			     &values[index * valueFormat.get_len ()],
 			     c->buffer->pos[c->buffer->i]);
 
@@ -574,8 +574,8 @@ struct PairSet
     {
       if (c->buffer->info[pos].codepoint == record->secondGlyph)
       {
-	valueFormats[0].apply_value (c->layout, this, &record->values[0], c->buffer->pos[c->buffer->i]);
-	valueFormats[1].apply_value (c->layout, this, &record->values[len1], c->buffer->pos[pos]);
+	valueFormats[0].apply_value (c->font, this, &record->values[0], c->buffer->pos[c->buffer->i]);
+	valueFormats[1].apply_value (c->font, this, &record->values[len1], c->buffer->pos[pos]);
 	if (len2)
 	  pos++;
 	c->buffer->i = pos;
@@ -630,7 +630,7 @@ struct PairPosFormat1
       return false;
 
     unsigned int j = c->buffer->i + 1;
-    while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL))
+    while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[j], c->lookup_props, NULL))
     {
       if (unlikely (j == end))
 	return false;
@@ -692,7 +692,7 @@ struct PairPosFormat2
       return false;
 
     unsigned int j = c->buffer->i + 1;
-    while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL))
+    while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[j], c->lookup_props, NULL))
     {
       if (unlikely (j == end))
 	return false;
@@ -709,8 +709,8 @@ struct PairPosFormat2
       return false;
 
     const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
-    valueFormat1.apply_value (c->layout, this, v, c->buffer->pos[c->buffer->i]);
-    valueFormat2.apply_value (c->layout, this, v + len1, c->buffer->pos[j]);
+    valueFormat1.apply_value (c->font, this, v, c->buffer->pos[c->buffer->i]);
+    valueFormat2.apply_value (c->font, this, v + len1, c->buffer->pos[j]);
 
     if (len2)
       j++;
@@ -845,7 +845,7 @@ struct CursivePosFormat1
       return false;
 
     unsigned int j = c->buffer->i + 1;
-    while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL))
+    while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[j], c->lookup_props, NULL))
     {
       if (unlikely (j == end))
 	return false;
@@ -859,8 +859,8 @@ struct CursivePosFormat1
     unsigned int i = c->buffer->i;
 
     hb_position_t entry_x, entry_y, exit_x, exit_y;
-    (this+this_record.exitAnchor).get_anchor (c->layout, c->buffer->info[i].codepoint, &exit_x, &exit_y);
-    (this+next_record.entryAnchor).get_anchor (c->layout, c->buffer->info[j].codepoint, &entry_x, &entry_y);
+    (this+this_record.exitAnchor).get_anchor (c->font, c->buffer->info[i].codepoint, &exit_x, &exit_y);
+    (this+next_record.entryAnchor).get_anchor (c->font, c->buffer->info[j].codepoint, &entry_x, &entry_y);
 
     hb_direction_t direction = c->buffer->props.direction;
 
@@ -976,7 +976,7 @@ struct MarkBasePosFormat1
       if (unlikely (!j))
 	return false;
       j--;
-    } while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], LookupFlag::IgnoreMarks, &property));
+    } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[j], LookupFlag::IgnoreMarks, &property));
 
     /* The following assertion is too strong, so we've disabled it. */
     if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH))
@@ -1078,7 +1078,7 @@ struct MarkLigPosFormat1
       if (unlikely (!j))
 	return false;
       j--;
-    } while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], LookupFlag::IgnoreMarks, &property));
+    } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[j], LookupFlag::IgnoreMarks, &property));
 
     /* The following assertion is too strong, so we've disabled it. */
     if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE))
@@ -1197,7 +1197,7 @@ struct MarkMarkPosFormat1
       if (unlikely (!j))
 	return false;
       j--;
-    } while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, &property));
+    } while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[j], c->lookup_props, &property));
 
     if (!(property & HB_OT_LAYOUT_GLYPH_CLASS_MARK))
       return false;
@@ -1402,7 +1402,7 @@ struct PosLookup : Lookup
   inline const PosLookupSubTable& get_subtable (unsigned int i) const
   { return this+CastR<OffsetArrayOf<PosLookupSubTable> > (subTable)[i]; }
 
-  inline bool apply_once (hb_ot_layout_context_t *layout,
+  inline bool apply_once (hb_font_t *font,
 			  hb_buffer_t *buffer,
 			  hb_mask_t lookup_mask,
 			  unsigned int context_length,
@@ -1411,14 +1411,15 @@ struct PosLookup : Lookup
     unsigned int lookup_type = get_type ();
     hb_apply_context_t c[1] = {{0}};
 
-    c->layout = layout;
+    c->font = font;
+    c->face = font->face;
     c->buffer = buffer;
     c->lookup_mask = lookup_mask;
     c->context_length = context_length;
     c->nesting_level_left = nesting_level_left;
     c->lookup_props = get_props ();
 
-    if (!_hb_ot_layout_check_glyph_property (c->layout->face, &c->buffer->info[c->buffer->i], c->lookup_props, &c->property))
+    if (!_hb_ot_layout_check_glyph_property (c->face, &c->buffer->info[c->buffer->i], c->lookup_props, &c->property))
       return false;
 
     for (unsigned int i = 0; i < get_subtable_count (); i++)
@@ -1428,7 +1429,7 @@ struct PosLookup : Lookup
     return false;
   }
 
-   inline bool apply_string (hb_ot_layout_context_t *layout,
+   inline bool apply_string (hb_font_t   *font,
 			     hb_buffer_t *buffer,
 			     hb_mask_t    mask) const
   {
@@ -1441,7 +1442,7 @@ struct PosLookup : Lookup
     while (buffer->i < buffer->len)
     {
       if ((buffer->info[buffer->i].mask & mask) &&
-	  apply_once (layout, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
+	  apply_once (font, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
 	ret = true;
       else
 	buffer->i++;
@@ -1471,11 +1472,11 @@ struct GPOS : GSUBGPOS
   inline const PosLookup& get_lookup (unsigned int i) const
   { return CastR<PosLookup> (GSUBGPOS::get_lookup (i)); }
 
-  inline bool position_lookup (hb_ot_layout_context_t *layout,
+  inline bool position_lookup (hb_font_t    *font,
 			       hb_buffer_t  *buffer,
 			       unsigned int  lookup_index,
 			       hb_mask_t     mask) const
-  { return get_lookup (lookup_index).apply_string (layout, buffer, mask); }
+  { return get_lookup (lookup_index).apply_string (font, buffer, mask); }
 
   static inline void position_finish (hb_buffer_t *buffer);
 
@@ -1566,7 +1567,7 @@ inline bool ExtensionPos::sanitize (hb_sanitize_context_t *c)
 
 static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_index)
 {
-  const GPOS &gpos = *(c->layout->face->ot_layout->gpos);
+  const GPOS &gpos = *(c->face->ot_layout->gpos);
   const PosLookup &l = gpos.get_lookup (lookup_index);
 
   if (unlikely (c->nesting_level_left == 0))
@@ -1575,7 +1576,7 @@ static inline bool position_lookup (hb_apply_context_t *c, unsigned int lookup_i
   if (unlikely (c->context_length < 1))
     return false;
 
-  return l.apply_once (c->layout, c->buffer, c->lookup_mask, c->context_length, c->nesting_level_left - 1);
+  return l.apply_once (c->font, c->buffer, c->lookup_mask, c->context_length, c->nesting_level_left - 1);
 }
 
 
diff --git a/src/hb-ot-layout-gsub-private.hh b/src/hb-ot-layout-gsub-private.hh
index 1bd5984..56dc817 100644
--- a/src/hb-ot-layout-gsub-private.hh
+++ b/src/hb-ot-layout-gsub-private.hh
@@ -354,7 +354,7 @@ struct Ligature
     for (i = 1, j = c->buffer->i + 1; i < count; i++, j++)
     {
       unsigned int property;
-      while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, &property))
+      while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[j], c->lookup_props, &property))
       {
 	if (unlikely (j + count - i == end))
 	  return false;
@@ -392,7 +392,7 @@ struct Ligature
 
       for (i = 1; i < count; i++)
       {
-	while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[c->buffer->i], c->lookup_props, NULL))
+	while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[c->buffer->i], c->lookup_props, NULL))
 	{
 	  c->buffer->info[c->buffer->i].lig_comp() = i;
 	  c->buffer->info[c->buffer->i].lig_id() = lig_id;
@@ -762,7 +762,7 @@ struct SubstLookup : Lookup
   }
 
 
-  inline bool apply_once (hb_ot_layout_context_t *layout,
+  inline bool apply_once (hb_face_t *face,
 			  hb_buffer_t *buffer,
 			  hb_mask_t lookup_mask,
 			  unsigned int context_length,
@@ -771,14 +771,14 @@ struct SubstLookup : Lookup
     unsigned int lookup_type = get_type ();
     hb_apply_context_t c[1] = {{0}};
 
-    c->layout = layout;
+    c->face = face;
     c->buffer = buffer;
     c->lookup_mask = lookup_mask;
     c->context_length = context_length;
     c->nesting_level_left = nesting_level_left;
     c->lookup_props = get_props ();
 
-    if (!_hb_ot_layout_check_glyph_property (c->layout->face, &c->buffer->info[c->buffer->i], c->lookup_props, &c->property))
+    if (!_hb_ot_layout_check_glyph_property (c->face, &c->buffer->info[c->buffer->i], c->lookup_props, &c->property))
       return false;
 
     if (unlikely (lookup_type == SubstLookupSubTable::Extension))
@@ -803,7 +803,7 @@ struct SubstLookup : Lookup
     return false;
   }
 
-  inline bool apply_string (hb_ot_layout_context_t *layout,
+  inline bool apply_string (hb_face_t   *face,
 			    hb_buffer_t *buffer,
 			    hb_mask_t    mask) const
   {
@@ -820,7 +820,7 @@ struct SubstLookup : Lookup
 	while (buffer->i < buffer->len)
 	{
 	  if ((buffer->info[buffer->i].mask & mask) &&
-	      apply_once (layout, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
+	      apply_once (face, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
 	    ret = true;
 	  else
 	    buffer->next_glyph ();
@@ -836,7 +836,7 @@ struct SubstLookup : Lookup
 	do
 	{
 	  if ((buffer->info[buffer->i].mask & mask) &&
-	      apply_once (layout, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
+	      apply_once (face, buffer, mask, NO_CONTEXT, MAX_NESTING_LEVEL))
 	    ret = true;
 	  else
 	    buffer->i--;
@@ -869,11 +869,11 @@ struct GSUB : GSUBGPOS
   inline const SubstLookup& get_lookup (unsigned int i) const
   { return CastR<SubstLookup> (GSUBGPOS::get_lookup (i)); }
 
-  inline bool substitute_lookup (hb_ot_layout_context_t *layout,
+  inline bool substitute_lookup (hb_face_t    *face,
 				 hb_buffer_t  *buffer,
 			         unsigned int  lookup_index,
 				 hb_mask_t     mask) const
-  { return get_lookup (lookup_index).apply_string (layout, buffer, mask); }
+  { return get_lookup (lookup_index).apply_string (face, buffer, mask); }
 
   inline bool sanitize (hb_sanitize_context_t *c) {
     TRACE_SANITIZE ();
@@ -913,7 +913,7 @@ inline bool ExtensionSubst::is_reverse (void) const
 
 static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup_index)
 {
-  const GSUB &gsub = *(c->layout->face->ot_layout->gsub);
+  const GSUB &gsub = *(c->face->ot_layout->gsub);
   const SubstLookup &l = gsub.get_lookup (lookup_index);
 
   if (unlikely (c->nesting_level_left == 0))
@@ -922,7 +922,7 @@ static inline bool substitute_lookup (hb_apply_context_t *c, unsigned int lookup
   if (unlikely (c->context_length < 1))
     return false;
 
-  return l.apply_once (c->layout, c->buffer, c->lookup_mask, c->context_length, c->nesting_level_left - 1);
+  return l.apply_once (c->face, c->buffer, c->lookup_mask, c->context_length, c->nesting_level_left - 1);
 }
 
 
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index 8d6122b..422ee43 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -53,7 +53,8 @@ HB_BEGIN_DECLS
 struct hb_apply_context_t
 {
   unsigned int debug_depth;
-  hb_ot_layout_context_t *layout;
+  hb_font_t *font;
+  hb_face_t *face;
   hb_buffer_t *buffer;
   hb_mask_t lookup_mask;
   unsigned int context_length;
@@ -133,7 +134,7 @@ static inline bool match_input (hb_apply_context_t *c,
 
   for (i = 1, j = c->buffer->i + 1; i < count; i++, j++)
   {
-    while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL))
+    while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[j], c->lookup_props, NULL))
     {
       if (unlikely (j + count - i == end))
 	return false;
@@ -160,7 +161,7 @@ static inline bool match_backtrack (hb_apply_context_t *c,
 
   for (unsigned int i = 0, j = c->buffer->backtrack_len () - 1; i < count; i++, j--)
   {
-    while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->out_info[j], c->lookup_props, NULL))
+    while (_hb_ot_layout_skip_mark (c->face, &c->buffer->out_info[j], c->lookup_props, NULL))
     {
       if (unlikely (j + 1 == count - i))
 	return false;
@@ -188,7 +189,7 @@ static inline bool match_lookahead (hb_apply_context_t *c,
 
   for (i = 0, j = c->buffer->i + offset; i < count; i++, j++)
   {
-    while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[j], c->lookup_props, NULL))
+    while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[j], c->lookup_props, NULL))
     {
       if (unlikely (j + count - i == end))
 	return false;
@@ -242,7 +243,7 @@ static inline bool apply_lookup (hb_apply_context_t *c,
    */
   for (unsigned int i = 0; i < count; /* NOP */)
   {
-    while (_hb_ot_layout_skip_mark (c->layout->face, &c->buffer->info[c->buffer->i], c->lookup_props, NULL))
+    while (_hb_ot_layout_skip_mark (c->face, &c->buffer->info[c->buffer->i], c->lookup_props, NULL))
     {
       if (unlikely (c->buffer->i == end))
 	return true;
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index 5870248..ef24e8d 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -96,19 +96,6 @@ struct hb_ot_layout_t
   const struct head *head;
 };
 
-struct hb_ot_layout_context_t
-{
-  hb_face_t *face;
-  hb_font_t *font;
-
-  /* Convert from font-space to user-space */
-  inline hb_position_t scale_x (int16_t v) { return scale (v, this->font->x_scale); }
-  inline hb_position_t scale_y (int16_t v) { return scale (v, this->font->y_scale); }
-
-  private:
-  inline hb_position_t scale (int16_t v, int scale) { return v * (int64_t) scale / _hb_ot_layout_get_upem (this->face); }
-};
-
 
 HB_INTERNAL hb_ot_layout_t *
 _hb_ot_layout_create (hb_face_t *face);
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 7e1e966..4f26e11 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -203,10 +203,7 @@ hb_ot_layout_get_ligature_carets (hb_font_t      *font,
 				  unsigned int   *caret_count /* IN/OUT */,
 				  int            *caret_array /* OUT */)
 {
-  hb_ot_layout_context_t c;
-  c.font = font;
-  c.face = font->face;
-  return _get_gdef (c.face).get_lig_carets (&c, direction, glyph, start_offset, caret_count, caret_array);
+  return _get_gdef (font->face).get_lig_carets (font, direction, glyph, start_offset, caret_count, caret_array);
 }
 
 /*
@@ -448,10 +445,7 @@ hb_ot_layout_substitute_lookup (hb_face_t    *face,
 				unsigned int  lookup_index,
 				hb_mask_t     mask)
 {
-  hb_ot_layout_context_t c;
-  c.font = NULL;
-  c.face = face;
-  return _get_gsub (face).substitute_lookup (&c, buffer, lookup_index, mask);
+  return _get_gsub (face).substitute_lookup (face, buffer, lookup_index, mask);
 }
 
 
@@ -477,10 +471,7 @@ hb_ot_layout_position_lookup   (hb_font_t    *font,
 				unsigned int  lookup_index,
 				hb_mask_t     mask)
 {
-  hb_ot_layout_context_t c;
-  c.font = font;
-  c.face = font->face;
-  return _get_gpos (c.face).position_lookup (&c, buffer, lookup_index, mask);
+  return _get_gpos (font->face).position_lookup (font, buffer, lookup_index, mask);
 }
 
 void
commit 1ded6d8bbf93b7dabf2b1f620c07bd3236e7a60f
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue May 10 20:49:02 2011 -0400

    Make default font-funcs chain-up to the parent

diff --git a/src/hb-font.cc b/src/hb-font.cc
index 6fd247c..ace9694 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -49,7 +49,16 @@ hb_font_get_contour_point_nil (hb_font_t *font HB_UNUSED,
 			       hb_position_t *x HB_UNUSED,
 			       hb_position_t *y HB_UNUSED,
 			       const void *user_data HB_UNUSED)
-{ return false; }
+{
+  if (font->parent)
+    return hb_font_get_contour_point (font->parent,
+				      point_index, glyph,
+				      x, y);
+
+  *x = *y = 0;
+
+  return false;
+}
 
 static void
 hb_font_get_glyph_advance_nil (hb_font_t *font HB_UNUSED,
@@ -58,7 +67,14 @@ hb_font_get_glyph_advance_nil (hb_font_t *font HB_UNUSED,
 			       hb_position_t *x_advance HB_UNUSED,
 			       hb_position_t *y_advance HB_UNUSED,
 			       const void *user_data HB_UNUSED)
-{ }
+{
+  if (font->parent) {
+    hb_font_get_glyph_advance (font->parent, glyph, x_advance, y_advance);
+    return;
+  }
+
+  *x_advance = *y_advance = 0;
+}
 
 static void
 hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
@@ -66,7 +82,15 @@ hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
 			       hb_codepoint_t glyph HB_UNUSED,
 			       hb_glyph_extents_t *extents HB_UNUSED,
 			       const void *user_data HB_UNUSED)
-{ }
+{
+  if (font->parent) {
+    hb_font_get_glyph_extents (font->parent, glyph, extents);
+    return;
+  }
+
+  extents->x_bearing = extents->y_bearing = 0;
+  extents->width = extents->height = 0;
+}
 
 static hb_codepoint_t
 hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
@@ -74,7 +98,12 @@ hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
 		       hb_codepoint_t unicode HB_UNUSED,
 		       hb_codepoint_t variation_selector HB_UNUSED,
 		       const void *user_data HB_UNUSED)
-{ return 0; }
+{
+  if (font->parent)
+    return hb_font_get_glyph (font->parent, unicode, variation_selector);
+
+  return 0;
+}
 
 static hb_position_t
 hb_font_get_kerning_nil (hb_font_t *font HB_UNUSED,
@@ -82,7 +111,12 @@ hb_font_get_kerning_nil (hb_font_t *font HB_UNUSED,
 			 hb_codepoint_t first_glyph HB_UNUSED,
 			 hb_codepoint_t second_glyph HB_UNUSED,
 			 const void *user_data HB_UNUSED)
-{ return 0; }
+{
+  if (font->parent)
+    return hb_font_get_kerning (font->parent, first_glyph, second_glyph);
+
+  return 0;
+}
 
 
 static hb_font_funcs_t _hb_font_funcs_nil = {
diff --git a/src/hb-font.h b/src/hb-font.h
index d937eab..d4a5441 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -121,9 +121,11 @@ typedef struct _hb_glyph_extents_t
     hb_position_t height;
 } hb_glyph_extents_t;
 
-typedef hb_codepoint_t (*hb_font_get_glyph_func_t) (hb_font_t *font, const void *font_data,
-						    hb_codepoint_t unicode, hb_codepoint_t variation_selector,
-						    const void *user_data);
+
+typedef hb_bool_t (*hb_font_get_contour_point_func_t) (hb_font_t *font, const void *font_data,
+						       unsigned int point_index, hb_codepoint_t glyph,
+						       hb_position_t *x, hb_position_t *y,
+						       const void *user_data);
 typedef void (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, const void *font_data,
 						  hb_codepoint_t glyph,
 						  hb_position_t *x_advance, hb_position_t *y_advance,
@@ -132,19 +134,18 @@ typedef void (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, const void *f
 						  hb_codepoint_t glyph,
 						  hb_glyph_extents_t *extents,
 						  const void *user_data);
-typedef hb_bool_t (*hb_font_get_contour_point_func_t) (hb_font_t *font, const void *font_data,
-						       unsigned int point_index, hb_codepoint_t glyph,
-						       hb_position_t *x, hb_position_t *y,
-						       const void *user_data);
+typedef hb_codepoint_t (*hb_font_get_glyph_func_t) (hb_font_t *font, const void *font_data,
+						    hb_codepoint_t unicode, hb_codepoint_t variation_selector,
+						    const void *user_data);
 typedef hb_position_t (*hb_font_get_kerning_func_t) (hb_font_t *font, const void *font_data,
 						     hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
 						     const void *user_data);
 
 
 void
-hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
-			      hb_font_get_glyph_func_t glyph_func,
-			      void *user_data, hb_destroy_func_t destroy);
+hb_font_funcs_set_contour_point_func (hb_font_funcs_t *ffuncs,
+				      hb_font_get_contour_point_func_t contour_point_func,
+				      void *user_data, hb_destroy_func_t destroy);
 
 void
 hb_font_funcs_set_glyph_advance_func (hb_font_funcs_t *ffuncs,
@@ -157,9 +158,9 @@ hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs,
 				      void *user_data, hb_destroy_func_t destroy);
 
 void
-hb_font_funcs_set_contour_point_func (hb_font_funcs_t *ffuncs,
-				      hb_font_get_contour_point_func_t contour_point_func,
-				      void *user_data, hb_destroy_func_t destroy);
+hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
+			      hb_font_get_glyph_func_t glyph_func,
+			      void *user_data, hb_destroy_func_t destroy);
 
 void
 hb_font_funcs_set_kerning_func (hb_font_funcs_t *ffuncs,
@@ -167,9 +168,10 @@ hb_font_funcs_set_kerning_func (hb_font_funcs_t *ffuncs,
 				void *user_data, hb_destroy_func_t destroy);
 
 
-hb_codepoint_t
-hb_font_get_glyph (hb_font_t *font,
-		   hb_codepoint_t unicode, hb_codepoint_t variation_selector);
+hb_bool_t
+hb_font_get_contour_point (hb_font_t *font,
+			   unsigned int point_index, hb_codepoint_t glyph,
+			   hb_position_t *x, hb_position_t *y);
 
 void
 hb_font_get_glyph_advance (hb_font_t *font,
@@ -181,10 +183,9 @@ hb_font_get_glyph_extents (hb_font_t *font,
 			   hb_codepoint_t glyph,
 			   hb_glyph_extents_t *extents);
 
-hb_bool_t
-hb_font_get_contour_point (hb_font_t *font,
-			   unsigned int point_index, hb_codepoint_t glyph,
-			   hb_position_t *x, hb_position_t *y);
+hb_codepoint_t
+hb_font_get_glyph (hb_font_t *font,
+		   hb_codepoint_t unicode, hb_codepoint_t variation_selector);
 
 hb_position_t
 hb_font_get_kerning (hb_font_t *font,
commit b9d975b931d6310f25fab5ac280f523cdc27bf94
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue May 10 20:41:13 2011 -0400

    [API] Pass down closure user_data to font funcs

diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index 66ebfd8..e6c79fb 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -46,13 +46,31 @@ struct _hb_font_funcs_t {
 
   hb_bool_t immutable;
 
+  /* Don't access these directly.  Call hb_font_get_*() instead. */
+
+  struct {
+    hb_font_get_contour_point_func_t	contour_point;
+    hb_font_get_glyph_advance_func_t	glyph_advance;
+    hb_font_get_glyph_extents_func_t	glyph_extents;
+    hb_font_get_glyph_func_t		glyph;
+    hb_font_get_kerning_func_t		kerning;
+  } get;
+
+  struct {
+    void				*contour_point;
+    void				*glyph_advance;
+    void				*glyph_extents;
+    void				*glyph;
+    void				*kerning;
+  } user_data;
+
   struct {
-    hb_font_get_glyph_func_t		get_glyph;
-    hb_font_get_glyph_advance_func_t	get_glyph_advance;
-    hb_font_get_glyph_extents_func_t	get_glyph_extents;
-    hb_font_get_contour_point_func_t	get_contour_point;
-    hb_font_get_kerning_func_t		get_kerning;
-  } v;
+    hb_destroy_func_t			contour_point;
+    hb_destroy_func_t			glyph_advance;
+    hb_destroy_func_t			glyph_extents;
+    hb_destroy_func_t			glyph;
+    hb_destroy_func_t			kerning;
+  } destroy;
 };
 
 
diff --git a/src/hb-font.cc b/src/hb-font.cc
index ae0beaa..6fd247c 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -41,42 +41,47 @@ HB_BEGIN_DECLS
  * hb_font_funcs_t
  */
 
-static hb_codepoint_t
-hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
-		       const void *user_data HB_UNUSED,
-		       hb_codepoint_t unicode HB_UNUSED,
-		       hb_codepoint_t variation_selector HB_UNUSED)
-{ return 0; }
+static hb_bool_t
+hb_font_get_contour_point_nil (hb_font_t *font HB_UNUSED,
+			       const void *font_data HB_UNUSED,
+			       unsigned int point_index HB_UNUSED,
+			       hb_codepoint_t glyph HB_UNUSED,
+			       hb_position_t *x HB_UNUSED,
+			       hb_position_t *y HB_UNUSED,
+			       const void *user_data HB_UNUSED)
+{ return false; }
 
 static void
 hb_font_get_glyph_advance_nil (hb_font_t *font HB_UNUSED,
-			       const void *user_data HB_UNUSED,
+			       const void *font_data HB_UNUSED,
 			       hb_codepoint_t glyph HB_UNUSED,
 			       hb_position_t *x_advance HB_UNUSED,
-			       hb_position_t *y_advance HB_UNUSED)
+			       hb_position_t *y_advance HB_UNUSED,
+			       const void *user_data HB_UNUSED)
 { }
 
 static void
 hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
-			       const void *user_data HB_UNUSED,
+			       const void *font_data HB_UNUSED,
 			       hb_codepoint_t glyph HB_UNUSED,
-			       hb_glyph_extents_t *extents HB_UNUSED)
+			       hb_glyph_extents_t *extents HB_UNUSED,
+			       const void *user_data HB_UNUSED)
 { }
 
-static hb_bool_t
-hb_font_get_contour_point_nil (hb_font_t *font HB_UNUSED,
-			       const void *user_data HB_UNUSED,
-			       unsigned int point_index HB_UNUSED,
-			       hb_codepoint_t glyph HB_UNUSED,
-			       hb_position_t *x HB_UNUSED,
-			       hb_position_t *y HB_UNUSED)
-{ return false; }
+static hb_codepoint_t
+hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED,
+		       const void *font_data HB_UNUSED,
+		       hb_codepoint_t unicode HB_UNUSED,
+		       hb_codepoint_t variation_selector HB_UNUSED,
+		       const void *user_data HB_UNUSED)
+{ return 0; }
 
 static hb_position_t
 hb_font_get_kerning_nil (hb_font_t *font HB_UNUSED,
-			 const void *user_data HB_UNUSED,
+			 const void *font_data HB_UNUSED,
 			 hb_codepoint_t first_glyph HB_UNUSED,
-			 hb_codepoint_t second_glyph HB_UNUSED)
+			 hb_codepoint_t second_glyph HB_UNUSED,
+			 const void *user_data HB_UNUSED)
 { return 0; }
 
 
@@ -84,11 +89,12 @@ static hb_font_funcs_t _hb_font_funcs_nil = {
   HB_OBJECT_HEADER_STATIC,
 
   TRUE, /* immutable */
+
   {
-    hb_font_get_glyph_nil,
+    hb_font_get_contour_point_nil,
     hb_font_get_glyph_advance_nil,
     hb_font_get_glyph_extents_nil,
-    hb_font_get_contour_point_nil,
+    hb_font_get_glyph_nil,
     hb_font_get_kerning_nil
   }
 };
@@ -102,7 +108,7 @@ hb_font_funcs_create (void)
   if (!(ffuncs = hb_object_create<hb_font_funcs_t> ()))
     return &_hb_font_funcs_nil;
 
-  ffuncs->v = _hb_font_funcs_nil.v;
+  ffuncs->get = _hb_font_funcs_nil.get;
 
   return ffuncs;
 }
@@ -118,6 +124,14 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
 {
   if (!hb_object_destroy (ffuncs)) return;
 
+#define DESTROY(name) if (ffuncs->destroy.name) ffuncs->destroy.name (ffuncs->user_data.name)
+  DESTROY (contour_point);
+  DESTROY (glyph_advance);
+  DESTROY (glyph_extents);
+  DESTROY (glyph);
+  DESTROY (kerning);
+#undef DESTROY
+
   free (ffuncs);
 }
 
@@ -154,63 +168,50 @@ hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs)
 }
 
 
-void
-hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
-			      hb_font_get_glyph_func_t glyph_func)
-{
-  if (ffuncs->immutable)
-    return;
-
-  ffuncs->v.get_glyph = glyph_func ? glyph_func : hb_font_get_glyph_nil;
-}
+#define IMPLEMENT(name)                                                  \
+                                                                         \
+void                                                                     \
+hb_font_funcs_set_##name##_func (hb_font_funcs_t             *ffuncs,    \
+                                 hb_font_get_##name##_func_t  func,      \
+                                 void                        *user_data, \
+                                 hb_destroy_func_t            destroy)   \
+{                                                                        \
+  if (ffuncs->immutable)                                                 \
+    return;                                                              \
+                                                                         \
+  if (ffuncs->destroy.name)                                              \
+    ffuncs->destroy.name (ffuncs->user_data.name);                       \
+                                                                         \
+  if (func) {                                                            \
+    ffuncs->get.name = func;                                             \
+    ffuncs->user_data.name = user_data;                                  \
+    ffuncs->destroy.name = destroy;                                      \
+  } else {                                                               \
+    ffuncs->get.name = hb_font_get_##name##_nil;                         \
+    ffuncs->user_data.name = NULL;                                       \
+    ffuncs->destroy.name = NULL;                                         \
+  }                                                                      \
+}
+
+IMPLEMENT (contour_point);
+IMPLEMENT (glyph_advance);
+IMPLEMENT (glyph_extents);
+IMPLEMENT (glyph);
+IMPLEMENT (kerning);
+
+#undef IMPLEMENT
 
-void
-hb_font_funcs_set_glyph_advance_func (hb_font_funcs_t *ffuncs,
-				      hb_font_get_glyph_advance_func_t glyph_advance_func)
-{
-  if (ffuncs->immutable)
-    return;
-
-  ffuncs->v.get_glyph_advance = glyph_advance_func ? glyph_advance_func : hb_font_get_glyph_advance_nil;
-}
 
-void
-hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs,
-				      hb_font_get_glyph_extents_func_t glyph_extents_func)
-{
-  if (ffuncs->immutable)
-    return;
-
-  ffuncs->v.get_glyph_extents = glyph_extents_func ? glyph_extents_func : hb_font_get_glyph_extents_nil;
-}
-
-void
-hb_font_funcs_set_contour_point_func (hb_font_funcs_t *ffuncs,
-				      hb_font_get_contour_point_func_t contour_point_func)
-{
-  if (ffuncs->immutable)
-    return;
-
-  ffuncs->v.get_contour_point = contour_point_func ? contour_point_func : hb_font_get_contour_point_nil;
-}
-
-void
-hb_font_funcs_set_kerning_func (hb_font_funcs_t *ffuncs,
-				hb_font_get_kerning_func_t kerning_func)
-{
-  if (ffuncs->immutable)
-    return;
-
-  ffuncs->v.get_kerning = kerning_func ? kerning_func : hb_font_get_kerning_nil;
-}
-
-
-hb_codepoint_t
-hb_font_get_glyph (hb_font_t *font,
-		   hb_codepoint_t unicode, hb_codepoint_t variation_selector)
+hb_bool_t
+hb_font_get_contour_point (hb_font_t *font,
+			   unsigned int point_index,
+			   hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y)
 {
-  return font->klass->v.get_glyph (font, font->user_data,
-				   unicode, variation_selector);
+  *x = 0; *y = 0;
+  return font->klass->get.contour_point (font, font->user_data,
+					 point_index,
+					 glyph, x, y,
+					 font->klass->user_data.contour_point);
 }
 
 void
@@ -219,8 +220,9 @@ hb_font_get_glyph_advance (hb_font_t *font,
 			   hb_position_t *x_advance, hb_position_t *y_advance)
 {
   *x_advance = *y_advance = 0;
-  return font->klass->v.get_glyph_advance (font, font->user_data,
-					   glyph, x_advance, y_advance);
+  return font->klass->get.glyph_advance (font, font->user_data,
+					 glyph, x_advance, y_advance,
+					 font->klass->user_data.glyph_advance);
 }
 
 void
@@ -228,27 +230,27 @@ hb_font_get_glyph_extents (hb_font_t *font,
 			   hb_codepoint_t glyph, hb_glyph_extents_t *extents)
 {
   memset (extents, 0, sizeof (*extents));
-  return font->klass->v.get_glyph_extents (font, font->user_data,
-					   glyph, extents);
+  return font->klass->get.glyph_extents (font, font->user_data,
+					 glyph, extents,
+					 font->klass->user_data.glyph_extents);
 }
 
-hb_bool_t
-hb_font_get_contour_point (hb_font_t *font,
-			   unsigned int point_index,
-			   hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y)
+hb_codepoint_t
+hb_font_get_glyph (hb_font_t *font,
+		   hb_codepoint_t unicode, hb_codepoint_t variation_selector)
 {
-  *x = 0; *y = 0;
-  return font->klass->v.get_contour_point (font, font->user_data,
-					   point_index,
-					   glyph, x, y);
+  return font->klass->get.glyph (font, font->user_data,
+				 unicode, variation_selector,
+				 font->klass->user_data.glyph);
 }
 
 hb_position_t
 hb_font_get_kerning (hb_font_t *font,
 		     hb_codepoint_t first_glyph, hb_codepoint_t second_glyph)
 {
-  return font->klass->v.get_kerning (font, font->user_data,
-				     first_glyph, second_glyph);
+  return font->klass->get.kerning (font, font->user_data,
+				   first_glyph, second_glyph,
+				   font->klass->user_data.kerning);
 }
 
 
diff --git a/src/hb-font.h b/src/hb-font.h
index 78a6c83..d937eab 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -121,40 +121,50 @@ typedef struct _hb_glyph_extents_t
     hb_position_t height;
 } hb_glyph_extents_t;
 
-typedef hb_codepoint_t (*hb_font_get_glyph_func_t) (hb_font_t *font, const void *user_data,
-						    hb_codepoint_t unicode, hb_codepoint_t variation_selector);
-typedef void (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, const void *user_data,
+typedef hb_codepoint_t (*hb_font_get_glyph_func_t) (hb_font_t *font, const void *font_data,
+						    hb_codepoint_t unicode, hb_codepoint_t variation_selector,
+						    const void *user_data);
+typedef void (*hb_font_get_glyph_advance_func_t) (hb_font_t *font, const void *font_data,
 						  hb_codepoint_t glyph,
-						  hb_position_t *x_advance, hb_position_t *y_advance);
-typedef void (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, const void *user_data,
+						  hb_position_t *x_advance, hb_position_t *y_advance,
+						  const void *user_data);
+typedef void (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, const void *font_data,
 						  hb_codepoint_t glyph,
-						  hb_glyph_extents_t *extents);
-typedef hb_bool_t (*hb_font_get_contour_point_func_t) (hb_font_t *font, const void *user_data,
+						  hb_glyph_extents_t *extents,
+						  const void *user_data);
+typedef hb_bool_t (*hb_font_get_contour_point_func_t) (hb_font_t *font, const void *font_data,
 						       unsigned int point_index, hb_codepoint_t glyph,
-						       hb_position_t *x, hb_position_t *y);
-typedef hb_position_t (*hb_font_get_kerning_func_t) (hb_font_t *font, const void *user_data,
-						     hb_codepoint_t first_glyph, hb_codepoint_t second_glyph);
+						       hb_position_t *x, hb_position_t *y,
+						       const void *user_data);
+typedef hb_position_t (*hb_font_get_kerning_func_t) (hb_font_t *font, const void *font_data,
+						     hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
+						     const void *user_data);
 
 
 void
 hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
-			      hb_font_get_glyph_func_t glyph_func);
+			      hb_font_get_glyph_func_t glyph_func,
+			      void *user_data, hb_destroy_func_t destroy);
 
 void
 hb_font_funcs_set_glyph_advance_func (hb_font_funcs_t *ffuncs,
-				      hb_font_get_glyph_advance_func_t glyph_advance_func);
+				      hb_font_get_glyph_advance_func_t glyph_advance_func,
+				      void *user_data, hb_destroy_func_t destroy);
 
 void
 hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t *ffuncs,
-				      hb_font_get_glyph_extents_func_t glyph_extents_func);
+				      hb_font_get_glyph_extents_func_t glyph_extents_func,
+				      void *user_data, hb_destroy_func_t destroy);
 
 void
 hb_font_funcs_set_contour_point_func (hb_font_funcs_t *ffuncs,
-				      hb_font_get_contour_point_func_t contour_point_func);
+				      hb_font_get_contour_point_func_t contour_point_func,
+				      void *user_data, hb_destroy_func_t destroy);
 
 void
 hb_font_funcs_set_kerning_func (hb_font_funcs_t *ffuncs,
-				hb_font_get_kerning_func_t kerning_func);
+				hb_font_get_kerning_func_t kerning_func,
+				void *user_data, hb_destroy_func_t destroy);
 
 
 hb_codepoint_t
@@ -226,7 +236,7 @@ hb_font_get_face (hb_font_t *font);
 void
 hb_font_set_funcs (hb_font_t         *font,
 		   hb_font_funcs_t   *klass,
-		   void              *user_data,
+		   void              *font_data,
 		   hb_destroy_func_t  destroy);
 
 
diff --git a/src/hb-ft.cc b/src/hb-ft.cc
index 9d1dbd1..50ab09f 100644
--- a/src/hb-ft.cc
+++ b/src/hb-ft.cc
@@ -36,33 +36,44 @@
 HB_BEGIN_DECLS
 
 
-static hb_codepoint_t
-hb_ft_get_glyph (hb_font_t *font HB_UNUSED,
-		 const void *user_data,
-		 hb_codepoint_t unicode,
-		 hb_codepoint_t variation_selector)
+static hb_bool_t
+hb_ft_get_contour_point (hb_font_t *font HB_UNUSED,
+			 const void *font_data,
+			 unsigned int point_index,
+			 hb_codepoint_t glyph,
+			 hb_position_t *x,
+			 hb_position_t *y,
+			 const void *user_data HB_UNUSED)
 {
-  FT_Face ft_face = (FT_Face) user_data;
+  FT_Face ft_face = (FT_Face) font_data;
+  int load_flags = FT_LOAD_DEFAULT;
 
-#ifdef HAVE_FT_FACE_GETCHARVARIANTINDEX
-  if (unlikely (variation_selector)) {
-    hb_codepoint_t glyph = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector);
-    if (glyph)
-      return glyph;
-  }
-#endif
+  /* TODO: load_flags, embolden, etc */
 
-  return FT_Get_Char_Index (ft_face, unicode);
+  if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
+      return FALSE;
+
+  if (unlikely (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE))
+      return FALSE;
+
+  if (unlikely (point_index >= (unsigned int) ft_face->glyph->outline.n_points))
+      return FALSE;
+
+  *x = ft_face->glyph->outline.points[point_index].x;
+  *y = ft_face->glyph->outline.points[point_index].y;
+
+  return TRUE;
 }
 
 static void
 hb_ft_get_glyph_advance (hb_font_t *font HB_UNUSED,
-			 const void *user_data,
+			 const void *font_data,
 			 hb_codepoint_t glyph,
 			 hb_position_t *x_advance,
-			 hb_position_t *y_advance)
+			 hb_position_t *y_advance,
+			 const void *user_data HB_UNUSED)
 {
-  FT_Face ft_face = (FT_Face) user_data;
+  FT_Face ft_face = (FT_Face) font_data;
   int load_flags = FT_LOAD_DEFAULT;
 
   /* TODO: load_flags, embolden, etc */
@@ -76,11 +87,12 @@ hb_ft_get_glyph_advance (hb_font_t *font HB_UNUSED,
 
 static void
 hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED,
-			 const void *user_data,
+			 const void *font_data,
 			 hb_codepoint_t glyph,
-			 hb_glyph_extents_t *extents)
+			 hb_glyph_extents_t *extents,
+			 const void *user_data HB_UNUSED)
 {
-  FT_Face ft_face = (FT_Face) user_data;
+  FT_Face ft_face = (FT_Face) font_data;
   int load_flags = FT_LOAD_DEFAULT;
 
   /* TODO: load_flags, embolden, etc */
@@ -95,41 +107,35 @@ hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED,
   }
 }
 
-static hb_bool_t
-hb_ft_get_contour_point (hb_font_t *font HB_UNUSED,
-			 const void *user_data,
-			 unsigned int point_index,
-			 hb_codepoint_t glyph,
-			 hb_position_t *x,
-			 hb_position_t *y)
-{
-  FT_Face ft_face = (FT_Face) user_data;
-  int load_flags = FT_LOAD_DEFAULT;
-
-  /* TODO: load_flags, embolden, etc */
-
-  if (unlikely (FT_Load_Glyph (ft_face, glyph, load_flags)))
-      return FALSE;
-
-  if (unlikely (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE))
-      return FALSE;
+static hb_codepoint_t
+hb_ft_get_glyph (hb_font_t *font HB_UNUSED,
+		 const void *font_data,
+		 hb_codepoint_t unicode,
+		 hb_codepoint_t variation_selector,
+		 const void *user_data HB_UNUSED)
 
-  if (unlikely (point_index >= (unsigned int) ft_face->glyph->outline.n_points))
-      return FALSE;
+{
+  FT_Face ft_face = (FT_Face) font_data;
 
-  *x = ft_face->glyph->outline.points[point_index].x;
-  *y = ft_face->glyph->outline.points[point_index].y;
+#ifdef HAVE_FT_FACE_GETCHARVARIANTINDEX
+  if (unlikely (variation_selector)) {
+    hb_codepoint_t glyph = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector);
+    if (glyph)
+      return glyph;
+  }
+#endif
 
-  return TRUE;
+  return FT_Get_Char_Index (ft_face, unicode);
 }
 
 static hb_position_t
 hb_ft_get_kerning (hb_font_t *font HB_UNUSED,
-		   const void *user_data,
+		   const void *font_data,
 		   hb_codepoint_t first_glyph,
-		   hb_codepoint_t second_glyph)
+		   hb_codepoint_t second_glyph,
+		   const void *user_data HB_UNUSED)
 {
-  FT_Face ft_face = (FT_Face) user_data;
+  FT_Face ft_face = (FT_Face) font_data;
   FT_Vector kerning;
 
   /* TODO: Kern type? */
@@ -143,11 +149,12 @@ static hb_font_funcs_t ft_ffuncs = {
   HB_OBJECT_HEADER_STATIC,
 
   TRUE, /* immutable */
+
   {
-    hb_ft_get_glyph,
+    hb_ft_get_contour_point,
     hb_ft_get_glyph_advance,
     hb_ft_get_glyph_extents,
-    hb_ft_get_contour_point,
+    hb_ft_get_glyph,
     hb_ft_get_kerning
   }
 };
commit 446df9cdb1fddb51819b731436fca54146d0bb23
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue May 10 20:14:44 2011 -0400

    Whitespace

diff --git a/src/hb-unicode.h b/src/hb-unicode.h
index 388256f..9e590d8 100644
--- a/src/hb-unicode.h
+++ b/src/hb-unicode.h
@@ -88,47 +88,47 @@ hb_unicode_funcs_get_parent (hb_unicode_funcs_t *ufuncs);
 /* typedefs */
 
 typedef unsigned int                  (*hb_unicode_get_combining_class_func_t)  (hb_unicode_funcs_t *ufuncs,
-                                                                                 hb_codepoint_t      unicode,
-                                                                                 void               *user_data);
+										 hb_codepoint_t      unicode,
+										 void               *user_data);
 typedef unsigned int                  (*hb_unicode_get_eastasian_width_func_t)  (hb_unicode_funcs_t *ufuncs,
-                                                                                 hb_codepoint_t      unicode,
-                                                                                 void               *user_data);
+										 hb_codepoint_t      unicode,
+										 void               *user_data);
 typedef hb_unicode_general_category_t (*hb_unicode_get_general_category_func_t) (hb_unicode_funcs_t *ufuncs,
-                                                                                 hb_codepoint_t      unicode,
-                                                                                 void               *user_data);
+										 hb_codepoint_t      unicode,
+										 void               *user_data);
 typedef hb_codepoint_t                (*hb_unicode_get_mirroring_func_t)        (hb_unicode_funcs_t *ufuncs,
-                                                                                 hb_codepoint_t      unicode,
-                                                                                 void               *user_data);
+										 hb_codepoint_t      unicode,
+										 void               *user_data);
 typedef hb_script_t                   (*hb_unicode_get_script_func_t)           (hb_unicode_funcs_t *ufuncs,
-                                                                                 hb_codepoint_t      unicode,
-                                                                                 void               *user_data);
+										 hb_codepoint_t      unicode,
+										 void               *user_data);
 
 /* setters */
 
 void
 hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t *ufuncs,
 					   hb_unicode_get_combining_class_func_t combining_class_func,
-                                           void *user_data, hb_destroy_func_t destroy);
+					   void *user_data, hb_destroy_func_t destroy);
 
 void
 hb_unicode_funcs_set_eastasian_width_func (hb_unicode_funcs_t *ufuncs,
 					   hb_unicode_get_eastasian_width_func_t eastasian_width_func,
-                                           void *user_data, hb_destroy_func_t destroy);
+					   void *user_data, hb_destroy_func_t destroy);
 
 void
 hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t *ufuncs,
 					    hb_unicode_get_general_category_func_t general_category_func,
-                                            void *user_data, hb_destroy_func_t destroy);
+					    void *user_data, hb_destroy_func_t destroy);
 
 void
 hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t *ufuncs,
 				     hb_unicode_get_mirroring_func_t mirroring_func,
-                                     void *user_data, hb_destroy_func_t destroy);
+				     void *user_data, hb_destroy_func_t destroy);
 
 void
 hb_unicode_funcs_set_script_func (hb_unicode_funcs_t *ufuncs,
 				  hb_unicode_get_script_func_t script_func,
-                                  void *user_data, hb_destroy_func_t destroy);
+				  void *user_data, hb_destroy_func_t destroy);
 
 
 
commit 686c2d165dfb284b74b78f6b902d04b585dcaef3
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue May 10 20:04:26 2011 -0400

    [API] Remove font_funcs func getter functions

diff --git a/src/hb-font.cc b/src/hb-font.cc
index b189797..ae0beaa 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -205,38 +205,6 @@ hb_font_funcs_set_kerning_func (hb_font_funcs_t *ffuncs,
 }
 
 
-hb_font_get_glyph_func_t
-hb_font_funcs_get_glyph_func (hb_font_funcs_t *ffuncs)
-{
-  return ffuncs->v.get_glyph;
-}
-
-hb_font_get_glyph_advance_func_t
-hb_font_funcs_get_glyph_advance_func (hb_font_funcs_t *ffuncs)
-{
-  return ffuncs->v.get_glyph_advance;
-}
-
-hb_font_get_glyph_extents_func_t
-hb_font_funcs_get_glyph_extents_func (hb_font_funcs_t *ffuncs)
-{
-  return ffuncs->v.get_glyph_extents;
-}
-
-hb_font_get_contour_point_func_t
-hb_font_funcs_get_contour_point_func (hb_font_funcs_t *ffuncs)
-{
-  return ffuncs->v.get_contour_point;
-}
-
-hb_font_get_kerning_func_t
-hb_font_funcs_get_kerning_func (hb_font_funcs_t *ffuncs)
-{
-  return ffuncs->v.get_kerning;
-}
-
-
-
 hb_codepoint_t
 hb_font_get_glyph (hb_font_t *font,
 		   hb_codepoint_t unicode, hb_codepoint_t variation_selector)
diff --git a/src/hb-font.h b/src/hb-font.h
index 1ab22ec..78a6c83 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -157,24 +157,6 @@ hb_font_funcs_set_kerning_func (hb_font_funcs_t *ffuncs,
 				hb_font_get_kerning_func_t kerning_func);
 
 
-/* These never return NULL.  Return fallback defaults instead. */
-
-hb_font_get_glyph_func_t
-hb_font_funcs_get_glyph_func (hb_font_funcs_t *ffuncs);
-
-hb_font_get_glyph_advance_func_t
-hb_font_funcs_get_glyph_advance_func (hb_font_funcs_t *ffuncs);
-
-hb_font_get_glyph_extents_func_t
-hb_font_funcs_get_glyph_extents_func (hb_font_funcs_t *ffuncs);
-
-hb_font_get_contour_point_func_t
-hb_font_funcs_get_contour_point_func (hb_font_funcs_t *ffuncs);
-
-hb_font_get_kerning_func_t
-hb_font_funcs_get_kerning_func (hb_font_funcs_t *ffuncs);
-
-
 hb_codepoint_t
 hb_font_get_glyph (hb_font_t *font,
 		   hb_codepoint_t unicode, hb_codepoint_t variation_selector);
commit defc45be6d75aba4a67fa7814b91b73bad953fe6
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue May 10 20:02:49 2011 -0400

    [API] Add hb_font_create_sub_font() and hb_font_get_parent()
    
    Not quite useful just yet.

diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index 3c6cc1c..66ebfd8 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -82,6 +82,7 @@ struct _hb_font_t {
 
   hb_bool_t immutable;
 
+  hb_font_t *parent;
   hb_face_t *face;
 
   int x_scale;
diff --git a/src/hb-font.cc b/src/hb-font.cc
index 656b8ad..b189797 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -83,7 +83,7 @@ hb_font_get_kerning_nil (hb_font_t *font HB_UNUSED,
 static hb_font_funcs_t _hb_font_funcs_nil = {
   HB_OBJECT_HEADER_STATIC,
 
-  TRUE,  /* immutable */
+  TRUE, /* immutable */
   {
     hb_font_get_glyph_nil,
     hb_font_get_glyph_advance_nil,
@@ -448,8 +448,9 @@ hb_face_get_upem (hb_face_t *face)
 static hb_font_t _hb_font_nil = {
   HB_OBJECT_HEADER_STATIC,
 
-  TRUE,  /* immutable */
+  TRUE, /* immutable */
 
+  NULL, /* parent */
   &_hb_face_nil,
 
   0, /* x_scale */
@@ -458,7 +459,7 @@ static hb_font_t _hb_font_nil = {
   0, /* x_ppem */
   0, /* y_ppem */
 
-  NULL, /* klass */
+  &_hb_font_funcs_nil, /* klass */
   NULL, /* user_data */
   NULL  /* destroy */
 };
@@ -482,6 +483,34 @@ hb_font_create (hb_face_t *face)
 }
 
 hb_font_t *
+hb_font_create_sub_font (hb_font_t *parent)
+{
+  if (unlikely (!parent))
+    return &_hb_font_nil;
+
+  hb_font_t *font = hb_font_create (parent->face);
+
+  if (unlikely (hb_object_is_inert (font)))
+    return font;
+
+  hb_font_make_immutable (parent);
+  font->parent = hb_font_reference (parent);
+
+  font->x_scale = parent->x_scale;
+  font->y_scale = parent->y_scale;
+  font->x_ppem = parent->x_ppem;
+  font->y_ppem = parent->y_ppem;
+
+  /* We can safely copy user_data from parent since we hold a reference
+   * onto it and it's immutable.  We should not copy the destroy notifiers
+   * though. */
+  font->klass = hb_font_funcs_reference (parent->klass);
+  font->user_data = parent->user_data;
+
+  return font;
+}
+
+hb_font_t *
 hb_font_reference (hb_font_t *font)
 {
   return hb_object_reference (font);
@@ -492,6 +521,7 @@ hb_font_destroy (hb_font_t *font)
 {
   if (!hb_object_destroy (font)) return;
 
+  hb_font_destroy (font->parent);
   hb_face_destroy (font->face);
   hb_font_funcs_destroy (font->klass);
   if (font->destroy)
@@ -531,6 +561,11 @@ hb_font_is_immutable (hb_font_t *font)
   return font->immutable;
 }
 
+hb_font_t *
+hb_font_get_parent (hb_font_t *font)
+{
+  return font->parent;
+}
 
 hb_face_t *
 hb_font_get_face (hb_font_t *font)
diff --git a/src/hb-font.h b/src/hb-font.h
index 358eee2..1ab22ec 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -209,6 +209,9 @@ hb_font_t *
 hb_font_create (hb_face_t *face);
 
 hb_font_t *
+hb_font_create_sub_font (hb_font_t *parent);
+
+hb_font_t *
 hb_font_reference (hb_font_t *font);
 
 void
@@ -231,6 +234,8 @@ hb_font_make_immutable (hb_font_t *font);
 hb_bool_t
 hb_font_is_immutable (hb_font_t *font);
 
+hb_font_t *
+hb_font_get_parent (hb_font_t *font);
 
 hb_face_t *
 hb_font_get_face (hb_font_t *font);
diff --git a/src/hb-unicode.h b/src/hb-unicode.h
index c7e35ba..388256f 100644
--- a/src/hb-unicode.h
+++ b/src/hb-unicode.h
@@ -51,7 +51,7 @@ hb_unicode_funcs_get_default (void);
 
 
 hb_unicode_funcs_t *
-hb_unicode_funcs_create (hb_unicode_funcs_t *parent_funcs);
+hb_unicode_funcs_create (hb_unicode_funcs_t *parent);
 
 hb_unicode_funcs_t *
 hb_unicode_funcs_reference (hb_unicode_funcs_t *ufuncs);
commit 11bb8fe7b3925bc9b019ad0c0218a231e581f152
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue May 10 19:57:00 2011 -0400

    [font] Fix internal sign of x/y_scale
    
    Should have been done as part of da975419884a535281745f30f4b32fee0bc8a7a1

diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index cd74e08..3c6cc1c 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -84,8 +84,8 @@ struct _hb_font_t {
 
   hb_face_t *face;
 
-  unsigned int x_scale;
-  unsigned int y_scale;
+  int x_scale;
+  int y_scale;
 
   unsigned int x_ppem;
   unsigned int y_ppem;
commit 85e6218e3306165d69ef44277459511d5b54b9ff
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue May 10 19:40:44 2011 -0400

    [API] Remove broken-by-design hb_font_unset_funcs()

diff --git a/src/hb-font.cc b/src/hb-font.cc
index f04fadb..656b8ad 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -561,28 +561,6 @@ hb_font_set_funcs (hb_font_t         *font,
   font->destroy = destroy;
 }
 
-void
-hb_font_unset_funcs (hb_font_t          *font,
-		     hb_font_funcs_t   **klass,
-		     void              **user_data,
-		     hb_destroy_func_t  *destroy)
-{
-  if (font->immutable)
-    return;
-
-  /* None of the input arguments can be NULL. */
-
-  *klass = font->klass;
-  *user_data = font->user_data;
-  *destroy = font->destroy;
-
-  if (hb_object_is_inert (font))
-    return;
-
-  font->klass = NULL;
-  font->user_data = NULL;
-  font->destroy = NULL;
-}
 
 void
 hb_font_set_scale (hb_font_t *font,
diff --git a/src/hb-font.h b/src/hb-font.h
index fc3518c..358eee2 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -242,22 +242,6 @@ hb_font_set_funcs (hb_font_t         *font,
 		   void              *user_data,
 		   hb_destroy_func_t  destroy);
 
-/* Returns what was set and unsets it, but doesn't destroy(user_data).
- * This is useful for wrapping / chaining font_funcs_t's.
- *
- * The client is responsible for:
- *
- *   - Take ownership of the reference on the returned klass,
- *
- *   - Calling "destroy(user_data)" exactly once if returned destroy func
- *     is not NULL and the returned info is not needed anymore.
- */
-void
-hb_font_unset_funcs (hb_font_t          *font,
-		     hb_font_funcs_t   **klass,
-		     void              **user_data,
-		     hb_destroy_func_t  *destroy);
-
 
 /*
  * We should add support for full matrices.
commit 74f1d896f2479500d65649cf3ec86dd201f0663a
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue May 10 19:39:32 2011 -0400

    Add hb_font_make/is_immutable()

diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh
index 683eab5..cd74e08 100644
--- a/src/hb-font-private.hh
+++ b/src/hb-font-private.hh
@@ -80,6 +80,8 @@ struct _hb_face_t {
 struct _hb_font_t {
   hb_object_header_t header;
 
+  hb_bool_t immutable;
+
   hb_face_t *face;
 
   unsigned int x_scale;
diff --git a/src/hb-font.cc b/src/hb-font.cc
index 1e7734b..f04fadb 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -448,6 +448,8 @@ hb_face_get_upem (hb_face_t *face)
 static hb_font_t _hb_font_nil = {
   HB_OBJECT_HEADER_STATIC,
 
+  TRUE,  /* immutable */
+
   &_hb_face_nil,
 
   0, /* x_scale */
@@ -514,6 +516,21 @@ hb_font_get_user_data (hb_font_t          *font,
   return hb_object_get_user_data (font, key);
 }
 
+void
+hb_font_make_immutable (hb_font_t *font)
+{
+  if (hb_object_is_inert (font))
+    return;
+
+  font->immutable = true;
+}
+
+hb_bool_t
+hb_font_is_immutable (hb_font_t *font)
+{
+  return font->immutable;
+}
+
 
 hb_face_t *
 hb_font_get_face (hb_font_t *font)
@@ -528,7 +545,7 @@ hb_font_set_funcs (hb_font_t         *font,
 		   void              *user_data,
 		   hb_destroy_func_t  destroy)
 {
-  if (hb_object_is_inert (font))
+  if (font->immutable)
     return;
 
   if (font->destroy)
@@ -550,6 +567,9 @@ hb_font_unset_funcs (hb_font_t          *font,
 		     void              **user_data,
 		     hb_destroy_func_t  *destroy)
 {
+  if (font->immutable)
+    return;
+
   /* None of the input arguments can be NULL. */
 
   *klass = font->klass;
@@ -569,7 +589,7 @@ hb_font_set_scale (hb_font_t *font,
 		   int x_scale,
 		   int y_scale)
 {
-  if (hb_object_is_inert (font))
+  if (font->immutable)
     return;
 
   font->x_scale = x_scale;
@@ -590,7 +610,7 @@ hb_font_set_ppem (hb_font_t *font,
 		  unsigned int x_ppem,
 		  unsigned int y_ppem)
 {
-  if (hb_object_is_inert (font))
+  if (font->immutable)
     return;
 
   font->x_ppem = x_ppem;
diff --git a/src/hb-font.h b/src/hb-font.h
index e8e344d..fc3518c 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -225,6 +225,12 @@ void *
 hb_font_get_user_data (hb_font_t          *font,
 		       hb_user_data_key_t *key);
 
+void
+hb_font_make_immutable (hb_font_t *font);
+
+hb_bool_t
+hb_font_is_immutable (hb_font_t *font);
+
 
 hb_face_t *
 hb_font_get_face (hb_font_t *font);
diff --git a/test/test-object.c b/test/test-object.c
index 6937280..1abe65c 100644
--- a/test/test-object.c
+++ b/test/test-object.c
@@ -161,8 +161,8 @@ static const object_t objects[] =
 {
   OBJECT_WITHOUT_IMMUTABILITY (buffer),
   OBJECT_WITHOUT_IMMUTABILITY (face),
-  OBJECT_WITHOUT_IMMUTABILITY (font),
   OBJECT_WITH_IMMUTABILITY (blob),
+  OBJECT_WITH_IMMUTABILITY (font),
   OBJECT_WITH_IMMUTABILITY (font_funcs),
   OBJECT_WITH_IMMUTABILITY (unicode_funcs)
 };
commit 8c7a100a4d0f3a257fb7563cb08ed4356c3af669
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue May 10 19:21:07 2011 -0400

    Fix build without mutex

diff --git a/src/hb-mutex-private.hh b/src/hb-mutex-private.hh
index 5a74337..3cc47e9 100644
--- a/src/hb-mutex-private.hh
+++ b/src/hb-mutex-private.hh
@@ -71,13 +71,13 @@ typedef CRITICAL_SECTION hb_mutex_t;
 
 #warning "Could not find any system to define platform macros, library will NOT be thread-safe"
 
-typedef volatile int hb_mutex_t;
+typedef struct { volatile int m; } hb_mutex_t;
 #define HB_MUTEX_INIT				0
-#define hb_mutex_init(M)			((void) (*(M) = 0))
-#define hb_mutex_lock(M)			((void) (*(M) = 1))
-#define hb_mutex_trylock(M)			(*(M) = 1, 1)
-#define hb_mutex_unlock(M)			((void) (*(M) = 0))
-#define hb_mutex_free(M)			((void) (*(M) = 2))
+#define hb_mutex_init(M)			((void) ((M)->m = 0))
+#define hb_mutex_lock(M)			((void) ((M)->m = 1))
+#define hb_mutex_trylock(M)			((M)->m = 1, 1)
+#define hb_mutex_unlock(M)			((void) ((M)->m = 0))
+#define hb_mutex_free(M)			((void) ((M)-M = 2))
 
 
 #endif
commit 19d3035c40e73923bcad709dc5eefe31cb34d681
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue May 10 19:18:12 2011 -0400

    Remove duplicate atomic_int implementation

diff --git a/src/hb-mutex-private.hh b/src/hb-mutex-private.hh
index 32b387c..5a74337 100644
--- a/src/hb-mutex-private.hh
+++ b/src/hb-mutex-private.hh
@@ -45,11 +45,6 @@ HB_BEGIN_DECLS
 
 #include <glib.h>
 
-typedef volatile int hb_atomic_int_t;
-#define hb_atomic_int_fetch_and_add(AI, V)	g_atomic_int_exchange_and_add (&(AI), V)
-#define hb_atomic_int_get(AI)			g_atomic_int_get (&(AI))
-#define hb_atomic_int_set(AI, V)		g_atomic_int_set (&(AI), V)
-
 typedef GStaticMutex hb_mutex_t;
 #define HB_MUTEX_INIT			G_STATIC_MUTEX_INIT
 #define hb_mutex_init(M)		g_static_mutex_init (M)
@@ -61,13 +56,6 @@ typedef GStaticMutex hb_mutex_t;
 
 #elif defined(_MSC_VER)
 
-#include <intrin.h>
-
-typedef long hb_atomic_int_t;
-#define hb_atomic_int_fetch_and_add(AI, V)	_InterlockedExchangeAdd (&(AI), V)
-#define hb_atomic_int_get(AI)			(_ReadBarrier (), (AI))
-#define hb_atomic_int_set(AI, V)		((void) _InterlockedExchange (&(AI), (V)))
-
 #include <Windows.h>
 
 typedef CRITICAL_SECTION hb_mutex_t;
@@ -83,11 +71,6 @@ typedef CRITICAL_SECTION hb_mutex_t;
 
 #warning "Could not find any system to define platform macros, library will NOT be thread-safe"
 
-typedef volatile int hb_atomic_int_t;
-#define hb_atomic_int_fetch_and_add(AI, V)	((AI) += (V), (AI) - (V))
-#define hb_atomic_int_get(AI)			(AI)
-#define hb_atomic_int_set(AI, V)		((void) ((AI) = (V)))
-
 typedef volatile int hb_mutex_t;
 #define HB_MUTEX_INIT				0
 #define hb_mutex_init(M)			((void) (*(M) = 0))
commit 45bfa99034512e886d75b1d45a5a649647f4711f
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue May 10 19:12:49 2011 -0400

    Fix set implementation to be truly threadsafe even with destroy() callbacks
    
    The test/object test is passing again, instead of deadlocking.

diff --git a/src/hb-common.cc b/src/hb-common.cc
index 02314b3..782d85a 100644
--- a/src/hb-common.cc
+++ b/src/hb-common.cc
@@ -162,7 +162,7 @@ struct hb_language_item_t {
   void finish (void) { free (lang); }
 };
 
-static hb_threadsafe_set_t<hb_language_item_t> langs;
+static hb_static_threadsafe_set_t<hb_language_item_t> langs;
 
 hb_language_t
 hb_language_from_string (const char *str)
@@ -293,8 +293,7 @@ hb_script_get_horizontal_direction (hb_script_t script)
  * should switch to using that insted for these too.
  */
 
-/* XXX  this can result in deadlocks because we call user callbacks */
-static hb_static_mutex_t user_data_mutex;
+static hb_static_mutex_t user_data_lock;
 
 bool
 hb_user_data_array_t::set (hb_user_data_key_t *key,
@@ -304,16 +303,12 @@ hb_user_data_array_t::set (hb_user_data_key_t *key,
   if (!key)
     return false;
 
-  hb_mutex_lock (&user_data_mutex);
-
   if (!data && !destroy) {
-    items.remove (key);
+    items.remove (key, user_data_lock);
     return true;
   }
   hb_user_data_item_t item = {key, data, destroy};
-  bool ret = !!items.insert (item);
-
-  hb_mutex_unlock (&user_data_mutex);
+  bool ret = !!items.replace_or_insert (item, user_data_lock);
 
   return ret;
 }
@@ -321,14 +316,15 @@ hb_user_data_array_t::set (hb_user_data_key_t *key,
 void *
 hb_user_data_array_t::get (hb_user_data_key_t *key)
 {
-  hb_mutex_lock (&user_data_mutex);
+  hb_user_data_item_t item = {NULL };
 
-  hb_user_data_item_t *item = items.find (key);
-  void *ret = item ? item->data : NULL;
-
-  hb_mutex_unlock (&user_data_mutex);
+  return items.find (key, &item, user_data_lock) ? item.data : NULL;
+}
 
-  return ret;
+void
+hb_user_data_array_t::finish (void)
+{
+  items.finish (user_data_lock);
 }
 
 
diff --git a/src/hb-mutex-private.hh b/src/hb-mutex-private.hh
index b52d970..32b387c 100644
--- a/src/hb-mutex-private.hh
+++ b/src/hb-mutex-private.hh
@@ -105,62 +105,49 @@ struct hb_static_mutex_t : hb_mutex_t
   hb_static_mutex_t (void) {
     hb_mutex_init (this);
   }
+
+  inline void lock (void) { hb_mutex_lock (this); }
+  inline void unlock (void) { hb_mutex_unlock (this); }
 };
 
 
 HB_END_DECLS
 
 
-/* XXX If the finish() callbacks of items in the set recursively try to
- * modify the set, deadlock occurs.  This needs fixing in set proper in
- * fact. */
-
 template <typename item_t>
-struct hb_threadsafe_set_t
+struct hb_static_threadsafe_set_t
 {
-  hb_set_t <item_t> set;
-  hb_static_mutex_t mutex;
+  hb_lockable_set_t <item_t, hb_static_mutex_t> set;
+  hb_static_mutex_t lock;
 
   template <typename T>
-  inline item_t *insert (T v)
+  inline item_t *replace_or_insert (T v)
   {
-    hb_mutex_lock (&mutex);
-    item_t *item = set.insert (v);
-    hb_mutex_unlock (&mutex);
-    return item;
+    return set.replace_or_insert (v, lock);
   }
 
   template <typename T>
   inline void remove (T v)
   {
-    hb_mutex_lock (&mutex);
-    set.remove (v);
-    hb_mutex_unlock (&mutex);
+    set.remove (v, lock);
   }
 
   template <typename T>
-  inline item_t *find (T v)
+  inline bool find (T v, item_t *i)
   {
-    hb_mutex_lock (&mutex);
-    item_t *item = set.find (v);
-    hb_mutex_unlock (&mutex);
-    return item;
+    return set.find (v, i, lock);
   }
 
   template <typename T>
-  inline item_t *find_or_insert (T v) {
-    hb_mutex_lock (&mutex);
-    item_t *item = set.find_or_insert (v);
-    hb_mutex_unlock (&mutex);
-    return item;
+  inline item_t *find_or_insert (T v)
+  {
+    return set.find_or_insert (v, lock);
   }
 
-  void finish (void) {
-    hb_mutex_lock (&mutex);
-    set.finish ();
-    hb_mutex_unlock (&mutex);
+  void finish (void)
+  {
+    set.finish (lock);
   }
-
 };
 
 
diff --git a/src/hb-object-private.hh b/src/hb-object-private.hh
index a0d5fe8..08f4bb1 100644
--- a/src/hb-object-private.hh
+++ b/src/hb-object-private.hh
@@ -34,6 +34,8 @@
 
 #include "hb-private.hh"
 
+#include "hb-mutex-private.hh"
+
 HB_BEGIN_DECLS
 
 
@@ -117,7 +119,7 @@ struct hb_user_data_array_t {
     void finish (void) { if (destroy) destroy (data); }
   };
 
-  hb_set_t<hb_user_data_item_t> items;
+  hb_lockable_set_t<hb_user_data_item_t, hb_static_mutex_t> items;
 
   HB_INTERNAL bool set (hb_user_data_key_t *key,
 			void *              data,
@@ -125,7 +127,7 @@ struct hb_user_data_array_t {
 
   HB_INTERNAL void *get (hb_user_data_key_t *key);
 
-  void finish (void) { items.finish (); }
+  HB_INTERNAL void finish (void);
 };
 
 
diff --git a/src/hb-private.hh b/src/hb-private.hh
index 577389d..f22e0d2 100644
--- a/src/hb-private.hh
+++ b/src/hb-private.hh
@@ -319,56 +319,131 @@ template <typename Type>
 struct hb_array_t : hb_prealloced_array_t<Type, 2> {};
 
 
-template <typename item_t>
-struct hb_set_t
+template <typename item_t, typename lock_t>
+struct hb_lockable_set_t
 {
   hb_array_t <item_t> items;
 
   template <typename T>
-  inline item_t *insert (T v)
+  inline item_t *replace_or_insert (T v, lock_t &l)
   {
+    l.lock ();
     item_t *item = items.find (v);
-    if (item)
-      item->finish ();
-    else
+    if (item) {
+      item_t old = *item;
+      *item = v;
+      l.unlock ();
+      old.finish ();
+    } else {
       item = items.push ();
-    if (unlikely (!item)) return NULL;
-    *item = v;
+      if (likely (item))
+	*item = v;
+      l.unlock ();
+    }
     return item;
   }
 
   template <typename T>
-  inline void remove (T v)
+  inline void remove (T v, lock_t &l)
   {
+    l.lock ();
     item_t *item = items.find (v);
-    if (!item) return;
-
-    item->finish ();
-    *item = items[items.len - 1];
-    items.pop ();
+    if (item) {
+      item_t old = *item;
+      *item = items[items.len - 1];
+      items.pop ();
+      l.unlock ();
+      old.finish ();
+    } else {
+      l.unlock ();
+    }
   }
 
   template <typename T>
-  inline item_t *find (T v)
+  inline bool find (T v, item_t *i, lock_t &l)
   {
-    return items.find (v);
+    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) {
-    item_t *item = find (v);
+  inline item_t *find_or_insert (T v, lock_t &l)
+  {
+    l.lock ();
+    item_t *item = items.find (v);
     if (!item) {
       item = items.push ();
       if (likely (item))
         *item = v;
     }
+    l.unlock ();
     return item;
   }
 
-  void finish (void) {
-    for (unsigned i = 0; i < items.len; i++)
-      items[i].finish ();
+  inline void finish (lock_t &l)
+  {
+    l.lock ();
+    while (items.len) {
+      item_t old = items[items.len - 1];
+	items.pop ();
+	l.unlock ();
+	old.finish ();
+	l.lock ();
+    }
     items.shrink (0);
+    l.unlock ();
+  }
+
+};
+
+template <typename item_t>
+struct hb_set_t
+{
+  struct lock_t {
+    int unused;
+
+    inline void lock (void) {}
+    inline void unlock (void) {}
+  };
+
+  hb_lockable_set_t <item_t, lock_t> set;
+
+  template <typename T>
+  inline item_t *replace_or_insert (T v)
+  {
+    lock_t lock;
+    return set.replace_or_insert (v, lock);
+  }
+
+  template <typename T>
+  inline void remove (T v)
+  {
+    lock_t lock;
+    set.remove (v, lock);
+  }
+
+  template <typename T>
+  inline bool find (T v, item_t *i)
+  {
+    lock_t lock;
+    return set.find (v, i, lock);
+  }
+
+  template <typename T>
+  inline item_t *find_or_insert (T v)
+  {
+    lock_t lock;
+    return set.find_or_insert (v, lock);
+  }
+
+  void finish (void)
+  {
+    lock_t lock;
+    set.finish (lock);
   }
 
 };
commit 0c2ec1d78bfa0166ffd4afc204c2668d4f456ed9
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue May 10 19:11:27 2011 -0400

    [test] Always initialize gthread such that our mutex() stuff is tested
    
    Now the test/object test deadlocks as expected.  Fix coming.

diff --git a/configure.ac b/configure.ac
index 2eb6c11..96dbca5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -58,6 +58,7 @@ fi
 dnl ==========================================================================
 
 PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.16, have_glib=true, have_glib=false)
+PKG_CHECK_MODULES(GTHREAD, gthread-2.0, , have_glib=false)
 if $have_glib; then
 	AC_DEFINE(HAVE_GLIB, 1, [Have glib2 library])
 fi
diff --git a/test/Makefile.am b/test/Makefile.am
index cc4519c..e58a91a 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -3,8 +3,8 @@ include Makefile.decl
 NULL =
 
 if HAVE_GLIB
-AM_CPPFLAGS = -I$(top_srcdir)/src/ $(GLIB_CFLAGS)
-LDADD = $(top_builddir)/src/libharfbuzz.la $(GLIB_LIBS)
+AM_CPPFLAGS = -I$(top_srcdir)/src/ $(GLIB_CFLAGS) $(GTHREAD_CFLAGS)
+LDADD = $(top_builddir)/src/libharfbuzz.la $(GLIB_LIBS) $(GTHREAD_LIBS)
 
 EXTRA_DIST += hb-test.h
 
diff --git a/test/hb-test.h b/test/hb-test.h
index 5f72a05..938b700 100644
--- a/test/hb-test.h
+++ b/test/hb-test.h
@@ -54,6 +54,7 @@ HB_BEGIN_DECLS
 static inline void
 hb_test_init (int *argc, char ***argv)
 {
+  g_thread_init (NULL);
   g_test_init (argc, argv, NULL);
 }
 
commit 6a9093cc486c1899197cd7cc9a3eb907c2e756f7
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue May 10 19:00:07 2011 -0400

    [test/object] Test user_data with destroy() callback that calls user_data
    
    Exposes the non-atomicity of user_data opertaions at this time because
    we call finish() while still locked and modifying the object.  In fact,
    I'm surprised that it doesn't deadlock.  It should.

diff --git a/test/test-object.c b/test/test-object.c
index 4936172..6937280 100644
--- a/test/test-object.c
+++ b/test/test-object.c
@@ -202,6 +202,21 @@ static void free_up1 (void *p)
   data->freed = TRUE;
 }
 
+
+typedef struct {
+  const object_t *klass;
+  void *object;
+  hb_user_data_key_t key;
+} deadlock_test_t;
+
+static void free_deadlock_test (void *p)
+{
+  deadlock_test_t *t = (deadlock_test_t *) p;
+
+  g_assert (NULL == t->klass->get_user_data (t->object, &t->key));
+}
+
+
 static void
 test_object (void)
 {
@@ -215,6 +230,7 @@ test_object (void)
     {
       unsigned int i;
       data_t data[2] = {{MAGIC0, FALSE}, {MAGIC1, FALSE}};
+      deadlock_test_t deadlock_test;
 
       g_test_message ("Testing object %s", o->name);
 
@@ -275,6 +291,12 @@ test_object (void)
 	g_assert (!o->get_user_data (obj, &key[i]));
       g_assert_cmpuint (global_data, ==, 900);
 
+      /* Test set_user_data where the destroy() func calls user_data functions.
+       * Make sure it doesn't deadlock or corrupt memory. */
+      deadlock_test.klass = o;
+      deadlock_test.object = obj;
+      g_assert (o->set_user_data (obj, &deadlock_test.key, &deadlock_test, free_deadlock_test));
+      g_assert (o->set_user_data (obj, &deadlock_test.key, NULL, NULL));
 
       g_assert (!data[1].freed);
       o->destroy (obj);
commit abe636b8761e47ea60b193c7e72a044de224d172
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue May 10 17:55:40 2011 -0400

    Add DOAP file

diff --git a/Makefile.am b/Makefile.am
index 95c5701..446c18a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,10 +1,14 @@
+NULL =
+
 SUBDIRS = src test
 
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = harfbuzz.pc
 
 EXTRA_DIST = \
-	autogen.sh
+	autogen.sh \
+	harfbuzz.doap \
+	$(NULL)
 
 MAINTAINERCLEANFILES = \
 	$(srcdir)/INSTALL \
diff --git a/harfbuzz.doap b/harfbuzz.doap
new file mode 100644
index 0000000..5bf1827
--- /dev/null
+++ b/harfbuzz.doap
@@ -0,0 +1,24 @@
+<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+         xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
+         xmlns:foaf="http://xmlns.com/foaf/0.1/"
+         xmlns="http://usefulinc.com/ns/doap#">
+
+  <name xml:lang="en">harfbuzz</name>
+  <shortdesc xml:lang="en">Internationalized text layout and rendering library</shortdesc>
+
+  <homepage
+  rdf:resource="http://freedesktop.org/wiki/Software/harfbuzz" />
+  <mailing-list
+  rdf:resource="http://lists.freedesktop.org/mailman/listinfo/harfbuzz" />
+  <!--download-page
+  rdf:resource=""/-->
+  <bug-database
+  rdf:resource="http://bugs.freedesktop.org/enter_bug.cgi?product=harfbuzz"/>
+
+  <maintainer>
+    <foaf:Person>
+      <foaf:name>Behdad Esfahbod</foaf:name>
+      <foaf:mbox rdf:resource="mailto:harfbuzz at behdad.org" />
+    </foaf:Person>
+  </maintainer>
+</Project>



More information about the HarfBuzz mailing list