shithub: freetype+ttf2subf

Download patch

ref: 0142e6aff1f0836a7ec3902969491ab6ac7182aa
parent: f20a4d35278312801d75613b54e771a9223a26b4
author: Wu, Chia-I (吳佳一) <[email protected]>
date: Mon Aug 15 21:54:59 EDT 2005

* src/truetype/ttinterp.c, src/truetype/ttinterp.h: Remove original
TT_Done_Context and rename TT_Destroy_Context to TT_Done_Context with
slight changes.

* src/truetype/ttobjs.h (tt_slot_init): New function.

* src/truetype/ttobjs.c (tt_driver_init): Initialize execution context
here.
(tt_slot_init): New function to create extra points for the internal
glyph loader. We then use it directly, instead of face's glyph loader,
when loading glyph.

* src/truetype/ttdriver.c: Use tt_slot_init for glyph slot
initialization.
(TT_Load_Glyph): Load flag dependencies are handled here.
Return error if size is NULL.

* src/truetype/ttgload.c: Heavy cleanup and refactor.
(TT_Hint_Glyph): New funcion to hint a zone, prepared by caller.
(TT_Process_Simple_Glyph): Use loader->pp's instead of recalculating.
Use TT_Hint_Glyph.
No need to save/restore loader->stream before/after
TT_Vary_Get_Glyph_Deltas now.
(TT_LOADER_SET_PP): New macro to calculate and set the four phantom points.
(TT_Process_Composite_Component, TT_Process_Composite_Glyph,
load_truetype_glyph): Refactor load_truetype_glyph into these three functions.
Never set exec->glyphSize to 0. (close #13107)
Forget glyph frame before calling TT_Process_Simple_Glyph.
(TT_Load_Glyph, load_sbit_image, tt_loader_init): Refactor TT_Load_Glyph into
these three functions.
Set various fields of `glyph' here, instead of in load_truetype_glyph
and compute_glyph_metrics.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,38 @@
+2005-08-16  Chia I Wu  <[email protected]>
+
+	* src/truetype/ttinterp.c, src/truetype/ttinterp.h: Remove original
+	TT_Done_Context and rename TT_Destroy_Context to TT_Done_Context with
+	slight changes.
+
+	* src/truetype/ttobjs.h (tt_slot_init): New function.
+
+	* src/truetype/ttobjs.c (tt_driver_init): Initialize execution context
+	here.
+	(tt_slot_init): New function to create extra points for the internal
+	glyph loader. We then use it directly, instead of face's glyph loader,
+	when loading glyph.
+
+	* src/truetype/ttdriver.c: Use tt_slot_init for glyph slot
+	initialization.
+	(TT_Load_Glyph): Load flag dependencies are handled here.
+	Return error if size is NULL.
+
+	* src/truetype/ttgload.c: Heavy cleanup and refactor.
+	(TT_Hint_Glyph): New funcion to hint a zone, prepared by caller.
+	(TT_Process_Simple_Glyph): Use loader->pp's instead of recalculating.
+	Use TT_Hint_Glyph.
+	No need to save/restore loader->stream before/after
+	TT_Vary_Get_Glyph_Deltas now.
+	(TT_LOADER_SET_PP): New macro to calculate and set the four phantom points.
+	(TT_Process_Composite_Component, TT_Process_Composite_Glyph,
+	load_truetype_glyph): Refactor load_truetype_glyph into these three functions.
+	Never set exec->glyphSize to 0. (close #13107)
+	Forget glyph frame before calling TT_Process_Simple_Glyph.
+	(TT_Load_Glyph, load_sbit_image, tt_loader_init): Refactor TT_Load_Glyph into
+	these three functions.
+	Set various fields of `glyph' here, instead of in load_truetype_glyph
+	and compute_glyph_metrics.
+
 2005-08-08  Werner Lemberg  <[email protected]>
 
 	* docs/INSTALL.ANY: Updated.
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -283,25 +283,14 @@
     if ( !slot )
       return TT_Err_Invalid_Slot_Handle;
 
-    /* check whether we want a scaled outline or bitmap */
-    if ( !size )
-      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+    if ( !size || !size->ttmetrics.valid )
+      return TT_Err_Invalid_Size_Handle;
 
-    if ( load_flags & FT_LOAD_NO_SCALE )
-      size = NULL;
-
-    /* reset the size object if necessary */
-    if ( size )
+    if ( load_flags & ( FT_LOAD_NO_RECURSE | FT_LOAD_NO_SCALE ) )
     {
-      /* these two object must have the same parent */
-      if ( size->root.face != slot->face )
-        return TT_Err_Invalid_Face_Handle;
-
-      if ( !size->ttmetrics.valid )
-      {
-        if ( FT_SET_ERROR( tt_size_reset( size ) ) )
-          return error;
-      }
+      load_flags |= FT_LOAD_NO_HINTING |
+                    FT_LOAD_NO_BITMAP  |
+                    FT_LOAD_NO_SCALE;
     }
 
     /* now load the glyph outline if necessary */
@@ -409,8 +398,8 @@
     tt_face_done,
     tt_size_init,
     tt_size_done,
-    0,                      /* FT_Slot_InitFunc        */
-    0,                      /* FT_Slot_DoneFunc        */
+    tt_slot_init,
+    0,                      /* FT_Slot_DoneFunc */
 
     Set_Char_Sizes,
     Set_Pixel_Sizes,
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -312,13 +312,6 @@
   }
 
 
-#define cur_to_org( n, zone ) \
-          FT_ARRAY_COPY( (zone)->org, (zone)->cur, (n) )
-
-#define org_to_cur( n, zone ) \
-          FT_ARRAY_COPY( (zone)->cur, (zone)->org, (n) )
-
-
   /*************************************************************************/
   /*                                                                       */
   /* Translates an array of coordinates.                                   */
@@ -342,21 +335,6 @@
   }
 
 
-  static void
-  tt_prepare_zone( TT_GlyphZone  zone,
-                   FT_GlyphLoad  load,
-                   FT_UInt       start_point,
-                   FT_UInt       start_contour )
-  {
-    zone->n_points   = (FT_UShort)( load->outline.n_points - start_point );
-    zone->n_contours = (FT_Short) ( load->outline.n_contours - start_contour );
-    zone->org        = load->extra_points + start_point;
-    zone->cur        = load->outline.points + start_point;
-    zone->tags       = (FT_Byte*)load->outline.tags + start_point;
-    zone->contours   = (FT_UShort*)load->outline.contours + start_contour;
-  }
-
-
 #undef  IS_HINTED
 #define IS_HINTED( flags )  ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
 
@@ -439,7 +417,6 @@
     FT_Int          n_contours = load->n_contours;
     FT_Outline*     outline;
     TT_Face         face       = (TT_Face)load->face;
-    TT_GlyphSlot    slot       = (TT_GlyphSlot)load->glyph;
     FT_UShort       n_ins;
     FT_Int          n, n_points;
     FT_Int          byte_len   = load->byte_len;
@@ -451,6 +428,11 @@
     FT_Short        *cont, *cont_limit;
 
 
+    /* check that we can add the contours to the glyph */
+    error = FT_GlyphLoader_CheckPoints( gloader, 0, n_contours );
+    if ( error )
+      goto Fail;
+
     /* reading the contours' endpoints & number of points */
     cont       = gloader->current.outline.contours;
     cont_limit = cont + n_contours;
@@ -467,6 +449,7 @@
     if ( n_contours > 0 )
       n_points = cont[-1] + 1;
 
+    /* note that we will add four phantom points later */
     error = FT_GlyphLoader_CheckPoints( gloader, n_points + 4, 0 );
     if ( error )
       goto Fail;
@@ -479,8 +462,8 @@
         goto Invalid_Outline;
 
     /* reading the bytecode instructions */
-    slot->control_len  = 0;
-    slot->control_data = 0;
+    load->glyph->control_len  = 0;
+    load->glyph->control_data = 0;
 
     n_ins = FT_GET_USHORT();
 
@@ -503,14 +486,12 @@
 
 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
-    if ( ( load->load_flags                        &
-         ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0 &&
-           load->instructions )
+    if ( IS_HINTED( load->load_flags ) )
     {
-      slot->control_len  = n_ins;
-      slot->control_data = load->instructions;
+      load->glyph->control_len  = n_ins;
+      load->glyph->control_data = load->exec->glyphIns;
 
-      FT_MEM_COPY( load->instructions, stream->cursor, (FT_Long)n_ins );
+      FT_MEM_COPY( load->exec->glyphIns, stream->cursor, (FT_Long)n_ins );
     }
 
 #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
@@ -723,6 +704,7 @@
     gloader->current.num_subglyphs = num_subglyphs;
 
 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
     {
       /* we must undo the FT_FRAME_ENTER in order to point to the */
       /* composite instructions, if we find some.               */
@@ -731,6 +713,7 @@
       loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
                                     stream->cursor - stream->limit );
     }
+
 #endif
 
     loader->byte_len = byte_len;
@@ -755,106 +738,156 @@
   }
 
 
+  static void
+  tt_prepare_zone( TT_GlyphZone  zone,
+                   FT_GlyphLoad  load,
+                   FT_UInt       start_point,
+                   FT_UInt       start_contour )
+  {
+    zone->n_points   = (FT_UShort)( load->outline.n_points - start_point );
+    zone->n_contours = (FT_Short) ( load->outline.n_contours - start_contour );
+    zone->org        = load->extra_points + start_point;
+    zone->cur        = load->outline.points + start_point;
+    zone->tags       = (FT_Byte*)load->outline.tags + start_point;
+    zone->contours   = (FT_UShort*)load->outline.contours + start_contour;
+  }
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
-  /*    TT_Process_Simple_Glyph                                            */
+  /*    TT_Hint_Glyph                                                      */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Once a simple glyph has been loaded, it needs to be processed.     */
-  /*    Usually, this means scaling and hinting through bytecode           */
-  /*    interpretation.                                                    */
+  /*    Hint the glyph using the zone prepared by the caller.  Note that   */
+  /*    the zone is supposed to include four phantom points.               */
   /*                                                                       */
+#define cur_to_org( n, zone ) \
+          FT_ARRAY_COPY( (zone)->org, (zone)->cur, (n) )
   static FT_Error
-  TT_Process_Simple_Glyph( TT_Loader  load,
-                           FT_Bool    debug )
+  TT_Hint_Glyph( TT_Loader     loader,
+                 FT_Bool       is_composite )
   {
-    FT_GlyphLoader  gloader  = load->gloader;
-    FT_Outline*     outline  = &gloader->current.outline;
-    FT_UInt         n_points = outline->n_points;
+    TT_GlyphZone  zone = &loader->zone;
+    FT_Pos        origin;
+
 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
-    FT_UInt         n_ins;
-#endif
-    TT_GlyphZone    zone     = &load->zone;
-    FT_Error        error    = TT_Err_Ok;
 
-    FT_UNUSED( debug );  /* used by truetype interpreter only */
+    FT_UInt       n_ins;
 
 
+    n_ins = loader->glyph->control_len;
+
+#endif
+
+    origin = zone->cur[zone->n_points - 4].x;
+    origin = FT_PIX_ROUND( origin ) - origin;
+    if ( origin )
+      translate_array( zone->n_points, zone->cur, origin, 0 );
+
 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
-    n_ins = load->glyph->control_len;
+
+    /* save original point positioin in org */
+    if ( n_ins > 0 )
+      cur_to_org( zone->n_points, zone );
+
 #endif
 
-    /* add shadow points */
+    /* round pp2 and pp4 */
+    zone->cur[zone->n_points - 3].x = FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
+    zone->cur[zone->n_points - 1].y = FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
 
-    /* Add two horizontal shadow points at n and n+1.   */
-    /* We need the left side bearing and advance width. */
-    /* Add two vertical shadow points at n+2 and n+3.   */
-    /* We need the top side bearing and advance height. */
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
+    if ( n_ins > 0 )
     {
-      FT_Vector*  pp1;
-      FT_Vector*  pp2;
-      FT_Vector*  pp3;
-      FT_Vector*  pp4;
+      FT_Bool   debug;
+      FT_Error  error;
 
 
-      /* pp1 = xMin - lsb */
-      pp1    = outline->points + n_points;
-      pp1->x = load->bbox.xMin - load->left_bearing;
-      pp1->y = 0;
+      error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph,
+                                loader->exec->glyphIns, n_ins );
+      if ( error )
+        return error;
 
-      /* pp2 = pp1 + aw */
-      pp2    = pp1 + 1;
-      pp2->x = pp1->x + load->advance;
-      pp2->y = 0;
+      loader->exec->is_composite     = is_composite;
+      loader->exec->pts              = *zone;
 
-      /* pp3 = top side bearing */
-      pp3    = pp1 + 2;
-      pp3->x = 0;
-      pp3->y = load->top_bearing + load->bbox.yMax;
+      debug = !( loader->load_flags & FT_LOAD_NO_SCALE ) &&
+              ( (TT_Size)loader->size )->debug;
 
-      /* pp4 = pp3 - ah */
-      pp4    = pp1 + 3;
-      pp4->x = 0;
-      pp4->y = pp3->y - load->vadvance;
+      error = TT_Run_Context( loader->exec, debug );
+      if ( error && loader->exec->pedantic_hinting )
+        return error;
+    }
 
-      outline->tags[n_points    ] = 0;
-      outline->tags[n_points + 1] = 0;
-      outline->tags[n_points + 2] = 0;
-      outline->tags[n_points + 3] = 0;
+#endif
+
+    /* save glyph phantom points */
+    if ( !loader->preserve_pps )
+    {
+      loader->pp1 = zone->cur[zone->n_points - 4];
+      loader->pp2 = zone->cur[zone->n_points - 3];
+      loader->pp3 = zone->cur[zone->n_points - 2];
+      loader->pp4 = zone->cur[zone->n_points - 1];
     }
 
-    /* Note that we return four more points that are not */
-    /* part of the glyph outline.                        */
+    return TT_Err_Ok;
+  }
 
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Process_Simple_Glyph                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Once a simple glyph has been loaded, it needs to be processed.     */
+  /*    Usually, this means scaling and hinting through bytecode           */
+  /*    interpretation.                                                    */
+  /*                                                                       */
+  static FT_Error
+  TT_Process_Simple_Glyph( TT_Loader  loader )
+  {
+    FT_GlyphLoader  gloader  = loader->gloader;
+    FT_Error        error    = TT_Err_Ok;
+    FT_Outline*     outline;
+    FT_UInt         n_points;
+
+
+    outline = &gloader->current.outline;
+    n_points = outline->n_points;
+
+    /* set phantom points */
+
+    outline->points[n_points    ] = loader->pp1;
+    outline->points[n_points + 1] = loader->pp2;
+    outline->points[n_points + 2] = loader->pp3;
+    outline->points[n_points + 3] = loader->pp4;
+
+    outline->tags[n_points    ] = 0;
+    outline->tags[n_points + 1] = 0;
+    outline->tags[n_points + 2] = 0;
+    outline->tags[n_points + 3] = 0;
+
     n_points += 4;
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 
-    if ( ((TT_Face)load->face)->doblend )
+    if ( ((TT_Face)loader->face)->doblend )
     {
       /* Deltas apply to the unscaled data. */
       FT_Vector*    deltas;
-      FT_Memory     memory       = load->face->memory;
-      FT_StreamRec  saved_stream = *(load->stream);
+      FT_Memory     memory = loader->face->memory;
       FT_UInt       i;
 
 
-      /* TT_Vary_Get_Glyph_Deltas uses a frame, thus we have to save */
-      /* (and restore) the current one                               */
-      load->stream->cursor = 0;
-      load->stream->limit  = 0;
-
-      error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(load->face),
-                                        load->glyph_index,
+      error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
+                                        loader->glyph_index,
                                         &deltas,
                                         n_points );
-
-      *(load->stream) = saved_stream;
-
       if ( error )
-        goto Exit;
+        return error;
 
       for ( i = 0; i < n_points; ++i )
       {
@@ -867,84 +900,290 @@
 
 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
 
-    /* set up zone for hinting */
-    tt_prepare_zone( zone, &gloader->current, 0, 0 );
-
-    /* eventually scale the glyph */
-    if ( !( load->load_flags & FT_LOAD_NO_SCALE ) )
+    /* scale the glyph */
+    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
     {
-      FT_Vector*  vec     = zone->cur;
-      FT_Vector*  limit   = vec + n_points;
-      FT_Fixed    x_scale = ((TT_Size)load->size)->metrics.x_scale;
-      FT_Fixed    y_scale = ((TT_Size)load->size)->metrics.y_scale;
+      FT_Vector*  vec     = outline->points;
+      FT_Vector*  limit   = outline->points + n_points;
+      FT_Fixed    x_scale = ((TT_Size)loader->size)->metrics.x_scale;
+      FT_Fixed    y_scale = ((TT_Size)loader->size)->metrics.y_scale;
 
-      /* first scale the glyph points */
+
       for ( ; vec < limit; vec++ )
       {
         vec->x = FT_MulFix( vec->x, x_scale );
         vec->y = FT_MulFix( vec->y, y_scale );
       }
+
+      loader->pp1 = outline->points[n_points - 4];
+      loader->pp2 = outline->points[n_points - 3];
+      loader->pp3 = outline->points[n_points - 2];
+      loader->pp4 = outline->points[n_points - 1];
     }
 
-    cur_to_org( n_points, zone );
+    if ( IS_HINTED( loader->load_flags ) )
+    {
+      tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
+      loader->zone.n_points += 4;
 
-    /* eventually hint the glyph */
-    if ( IS_HINTED( load->load_flags ) )
+      error = TT_Hint_Glyph( loader, 0 );
+    }
+
+    return error;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Process_Composite_Component                                     */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Once a composite component has been loaded, it needs to be         */
+  /*    processed.  Usually, this means transforming and translating.      */
+  /*                                                                       */
+  static FT_Error
+  TT_Process_Composite_Component( TT_Loader    loader,
+                                  FT_SubGlyph  subglyph,
+                                  FT_UInt      start_point,
+                                  FT_UInt      num_base_points )
+  {
+    FT_GlyphLoader  gloader    = loader->gloader;
+    FT_Vector*      base_vec   = gloader->base.outline.points;
+    FT_UInt         num_points = gloader->base.outline.n_points;
+    FT_Bool         have_scale;
+    FT_Pos          x, y;
+    
+
+    have_scale = ( subglyph->flags & ( WE_HAVE_A_SCALE     |
+                                       WE_HAVE_AN_XY_SCALE |
+                                       WE_HAVE_A_2X2       ) );
+
+    /* perform the transform required for this subglyph */
+    if ( have_scale )
     {
-      FT_Pos  x = zone->org[n_points-4].x;
+      FT_UInt i;
 
 
-      x = FT_PIX_ROUND( x ) - x;
-      translate_array( n_points, zone->org, x, 0 );
+      for ( i = num_base_points; i < num_points; i++ )
+        FT_Vector_Transform( base_vec + i, &subglyph->transform );
+    }
 
-      org_to_cur( n_points, zone );
+    /* get offset */
+    if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
+    {
+      FT_UInt     k = subglyph->arg1;
+      FT_UInt     l = subglyph->arg2;
+      FT_Vector*  p1;
+      FT_Vector*  p2;
 
-      zone->cur[n_points - 3].x = FT_PIX_ROUND( zone->cur[n_points - 3].x );
-      zone->cur[n_points - 1].y = FT_PIX_ROUND( zone->cur[n_points - 1].y );
 
-#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+      /* match l-th point of the newly loaded component to the k-th point of  */
+      /* the previously loaded components.                                    */
 
-      /* now consider hinting */
-      if ( n_ins > 0 )
+      /* change to the point numbers used by our outline */
+      k += start_point;
+      l += num_base_points;
+      if ( k >= (FT_UInt)num_base_points ||
+           l >= (FT_UInt)num_points  )
       {
-        error = TT_Set_CodeRange( load->exec, tt_coderange_glyph,
-                                  load->exec->glyphIns, n_ins );
-        if ( error )
-          goto Exit;
+        return TT_Err_Invalid_Composite;
+      }
 
-        load->exec->is_composite     = FALSE;
-        load->exec->pts              = *zone;
-        load->exec->pts.n_points    += 4;
+      p1 = gloader->base.outline.points + k;
+      p2 = gloader->base.outline.points + l;
 
-        error = TT_Run_Context( load->exec, debug );
-        if ( error && load->exec->pedantic_hinting )
-          goto Exit;
+      x = p1->x - p2->x;
+      y = p1->y - p2->y;
+    }
+    else
+    {
+      x = subglyph->arg1;
+      y = subglyph->arg2;
 
-        error = TT_Err_Ok;  /* ignore bytecode errors in non-pedantic mode */
+      if ( !x && !y )
+        return TT_Err_Ok;
+
+/* Use a default value dependent on                                     */
+/* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED.  This is useful for old TT */
+/* fonts which don't set the xxx_COMPONENT_OFFSET bit.                  */
+
+      if ( have_scale &&
+#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
+           !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
+#else
+            ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
+#endif
+      {
+#if 0
+
+/*************************************************************************/
+/*                                                                       */
+/* This algorithm is what Apple documents.  But it doesn't work.         */
+/*                                                                       */
+        int  a = subglyph->transform.xx > 0 ?  subglyph->transform.xx
+                                            : -subglyph->transform.xx;
+        int  b = subglyph->transform.yx > 0 ?  subglyph->transform.yx
+                                            : -subglyph->transform.yx;
+        int  c = subglyph->transform.xy > 0 ?  subglyph->transform.xy
+                                            : -subglyph->transform.xy;
+        int  d = subglyph->transform.yy > 0 ? subglyph->transform.yy
+                                            : -subglyph->transform.yy;
+        int  m = a > b ? a : b;
+        int  n = c > d ? c : d;
+
+
+        if ( a - b <= 33 && a - b >= -33 )
+          m *= 2;
+        if ( c - d <= 33 && c - d >= -33 )
+          n *= 2;
+        x = FT_MulFix( x, m );
+        y = FT_MulFix( y, n );
+
+#else /* 0 */
+
+/*************************************************************************/
+/*                                                                       */
+/* This algorithm is a guess and works much better than the above.       */
+/*                                                                       */
+        FT_Fixed  mac_xscale = FT_SqrtFixed(
+                                 FT_MulFix( subglyph->transform.xx,
+                                            subglyph->transform.xx ) +
+                                 FT_MulFix( subglyph->transform.xy,
+                                            subglyph->transform.xy) );
+        FT_Fixed  mac_yscale = FT_SqrtFixed(
+                                 FT_MulFix( subglyph->transform.yy,
+                                            subglyph->transform.yy ) +
+                                 FT_MulFix( subglyph->transform.yx,
+                                            subglyph->transform.yx ) );
+
+
+        x = FT_MulFix( x, mac_xscale );
+        y = FT_MulFix( y, mac_yscale );
+
+#endif /* 0 */
+
       }
 
-#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+      if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
+      {
+        FT_Fixed    x_scale = ((TT_Size)loader->size)->metrics.x_scale;
+        FT_Fixed    y_scale = ((TT_Size)loader->size)->metrics.y_scale;
 
+
+        x = FT_MulFix( x, x_scale );
+        y = FT_MulFix( y, y_scale );
+
+        if ( subglyph->flags & ROUND_XY_TO_GRID )
+        {
+          x = FT_PIX_ROUND( x );
+          y = FT_PIX_ROUND( y );
+        }
+      }
     }
 
-    /* save glyph phantom points */
-    if ( !load->preserve_pps )
+    if ( x || y )
+      translate_array( num_points - num_base_points,
+                       base_vec + num_base_points,
+                       x, y );
+
+    return TT_Err_Ok;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    TT_Process_Composite_Glyph                                         */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This is slightly different from TT_Process_Simple_Glyph, in that   */
+  /*    it's sole purpose is to hint the glyph.  Thus this function is     */
+  /*    only available when bytecode interpreter is enabled.               */
+  /*                                                                       */
+  static FT_Error
+  TT_Process_Composite_Glyph( TT_Loader  loader,
+                              FT_UInt    start_point,
+                              FT_UInt    start_contour )
+  {
+    FT_Error     error;
+    FT_Outline*  outline;
+
+
+    outline = &loader->gloader->base.outline;
+
+    /* make room for phantom points */
+    error = FT_GlyphLoader_CheckPoints( loader->gloader, outline->n_points + 4, 0 );
+    if ( error )
+      return error;
+
+    outline->points[outline->n_points    ] = loader->pp1;
+    outline->points[outline->n_points + 1] = loader->pp2;
+    outline->points[outline->n_points + 2] = loader->pp3;
+    outline->points[outline->n_points + 3] = loader->pp4;
+
+    outline->tags[outline->n_points    ] = 0;
+    outline->tags[outline->n_points + 1] = 0;
+    outline->tags[outline->n_points + 2] = 0;
+    outline->tags[outline->n_points + 3] = 0;
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
     {
-      load->pp1 = zone->cur[n_points - 4];
-      load->pp2 = zone->cur[n_points - 3];
-      load->pp3 = zone->cur[n_points - 2];
-      load->pp4 = zone->cur[n_points - 1];
+      FT_Stream  stream = loader->stream;
+      FT_UShort  n_ins;
+
+
+      /* TT_Load_Composite_Glyph only gives us the offset of instructions */
+      /* so we read them here */
+      if ( FT_STREAM_SEEK( loader->ins_pos ) ||
+           FT_READ_USHORT( n_ins ) )
+        return error;
+
+      FT_TRACE5(( "  Instructions size = %d\n", n_ins ));
+
+      /* check it */
+      if ( n_ins > ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions )
+      {
+        FT_TRACE0(( "Too many instructions (%d)\n", n_ins ));
+
+        return TT_Err_Too_Many_Hints;
+      }
+      else if ( n_ins == 0 )
+        return TT_Err_Ok;
+
+      if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) )
+        return error;
+
+      loader->glyph->control_data = loader->exec->glyphIns;
+      loader->glyph->control_len  = n_ins;
     }
 
-#if defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER ) || \
-    defined( TT_CONFIG_OPTION_GX_VAR_SUPPORT )
-  Exit:
 #endif
 
-    return error;
+    tt_prepare_zone( &loader->zone, &loader->gloader->base, start_point, start_contour );
+    loader->zone.n_points += 4;
+
+    return TT_Hint_Glyph( loader, 1 );
   }
 
 
+  /* Calculate the four phantom points.                     */
+  /* The first two stand for horizontal origin and advance. */
+  /* The last two stand for vertical origin and advance.    */
+#define TT_LOADER_SET_PP( loader )                                          \
+          do {                                                              \
+            (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
+            (loader)->pp1.y = 0;                                            \
+            (loader)->pp2.x = (loader)->pp1.x + (loader)->advance;          \
+            (loader)->pp2.y = 0;                                            \
+            (loader)->pp3.x = 0;                                            \
+            (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax;  \
+            (loader)->pp4.x = 0;                                            \
+            (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance;         \
+          } while ( 0 )
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -959,28 +1198,25 @@
                        FT_UInt    glyph_index,
                        FT_UInt    recurse_count )
   {
-
-#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
-    FT_Stream       stream = loader->stream;
-#endif
-
     FT_Error        error;
-    TT_Face         face = (TT_Face)loader->face;
-    FT_ULong        offset;
-    FT_Int          contours_count;
-    FT_UInt         num_points, count;
     FT_Fixed        x_scale, y_scale;
-    FT_GlyphLoader  gloader = loader->gloader;
+    FT_ULong        offset;
+    TT_Face         face         = (TT_Face)loader->face;
+    FT_GlyphLoader  gloader      = loader->gloader;
     FT_Bool         opened_frame = 0;
 
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
+    FT_Vector*      deltas       = NULL;
+
+#endif
+
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
+
     FT_StreamRec    inc_stream;
     FT_Data         glyph_data;
     FT_Bool         glyph_data_loaded = 0;
-#endif
 
-#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-    FT_Vector      *deltas;
 #endif
 
 
@@ -998,15 +1234,17 @@
     }
 
     loader->glyph_index = glyph_index;
-    num_points          = 0;
 
-    x_scale = 0x10000L;
-    y_scale = 0x10000L;
     if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
     {
       x_scale = ((TT_Size)loader->size)->metrics.x_scale;
       y_scale = ((TT_Size)loader->size)->metrics.y_scale;
     }
+    else
+    {
+      x_scale = 0x10000L;
+      y_scale = 0x10000L;
+    }
 
     /* get metrics, horizontal and vertical */
     {
@@ -1045,16 +1283,9 @@
           goto Exit;
         left_bearing  = (FT_Short)metrics.bearing_x;
         advance_width = (FT_UShort)metrics.advance;
-      }
-
 # if 0
-      /* GWW: Do I do the same for vertical metrics ??? */
-      if ( face->root.internal->incremental_interface &&
-           face->root.internal->incremental_interface->funcs->get_glyph_metrics )
-      {
-        FT_Incremental_MetricsRec  metrics;
 
-
+      /* GWW: Do I do the same for vertical metrics ??? */
         metrics.bearing_x = 0;
         metrics.bearing_y = top_bearing;
         metrics.advance = advance_height;
@@ -1065,9 +1296,11 @@
           goto Exit;
         top_bearing  = (FT_Short)metrics.bearing_y;
         advance_height = (FT_UShort)metrics.advance;
-      }
+
 # endif
 
+      }
+
 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
       loader->left_bearing = left_bearing;
@@ -1082,16 +1315,15 @@
       }
     }
 
+    /* Set `offset' to the start of the glyph relative to the start of */
+    /* the 'glyf' table, and `byte_len' to the length of the glyph in  */
+    /* bytes.                                                          */
+
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
 
-    /* Set `offset' to the start of the glyph program relative to the  */
-    /* start of the 'glyf' table, and `count' to the length of the     */
-    /* glyph program in bytes.                                         */
-    /*                                                                 */
     /* If we are loading glyph data via the incremental interface, set */
     /* the loader stream to a memory stream reading the data returned  */
     /* by the interface.                                               */
-
     if ( face->root.internal->incremental_interface )
     {
       error = face->root.internal->incremental_interface->funcs->get_glyph_data(
@@ -1102,7 +1334,7 @@
 
       glyph_data_loaded = 1;
       offset            = 0;
-      count             = glyph_data.length;
+      byte_len          = glyph_data.length;
 
       FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
       FT_Stream_OpenMemory( &inc_stream,
@@ -1114,23 +1346,21 @@
 
 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
 
-    offset = tt_face_get_location( face, glyph_index, &count );
+      offset = tt_face_get_location( face, glyph_index, (FT_UInt*)&loader->byte_len );
 
-    if ( count == 0 )
+    if ( loader->byte_len == 0 )
     {
-      /* as described by Frederic Loyer, these are spaces, and */
-      /* not the unknown glyph.                                */
+      /* as described by Frederic Loyer, these are spaces or */
+      /* the unknown glyph.                                  */
       loader->bbox.xMin = 0;
       loader->bbox.xMax = 0;
       loader->bbox.yMin = 0;
       loader->bbox.yMax = 0;
 
-      loader->pp1.x = 0;
-      loader->pp2.x = loader->advance;
-      loader->pp3.y = 0;
-      loader->pp4.y = loader->pp3.y-loader->vadvance;
+      TT_LOADER_SET_PP( loader );
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+
       if ( ((TT_Face)(loader->face))->doblend )
       {
         /* this must be done before scaling */
@@ -1149,31 +1379,24 @@
 
         FT_FREE( deltas );
       }
+
 #endif
 
       if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
       {
+        loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
         loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
+        loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
         loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
       }
 
-#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
-
-      if ( loader->exec )
-        loader->exec->glyphSize = 0;
-
-#endif
-
       error = TT_Err_Ok;
       goto Exit;
     }
 
-    loader->byte_len = (FT_Int)count;
-
-    offset = loader->glyf_offset + offset;
-
-    /* access glyph frame */
-    error = face->access_glyph_frame( loader, glyph_index, offset, count );
+    error = face->access_glyph_frame( loader, glyph_index,
+                                      loader->glyf_offset + offset,
+                                      loader->byte_len );
     if ( error )
       goto Exit;
 
@@ -1182,22 +1405,10 @@
     /* read first glyph header */
     error = face->read_glyph_header( loader );
     if ( error )
-      goto Fail;
+      goto Exit;
 
-    contours_count = loader->n_contours;
+    TT_LOADER_SET_PP( loader );
 
-    count -= 10;
-
-    loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
-    loader->pp1.y = 0;
-    loader->pp2.x = loader->pp1.x + loader->advance;
-    loader->pp2.y = 0;
-
-    loader->pp3.x = 0;
-    loader->pp3.y = loader->top_bearing + loader->bbox.yMax;
-    loader->pp4.x = 0;
-    loader->pp4.y = loader->pp3.y - loader->vadvance;
-
     /***********************************************************************/
     /***********************************************************************/
     /***********************************************************************/
@@ -1204,40 +1415,21 @@
 
     /* if it is a simple glyph, load it */
 
-    if ( contours_count >= 0 )
+    if ( loader->n_contours >= 0 )
     {
-      /* check that we can add the contours to the glyph */
-      error = FT_GlyphLoader_CheckPoints( gloader, 0, contours_count );
-      if ( error )
-        goto Fail;
-
       error = face->read_simple_glyph( loader );
       if ( error )
-        goto Fail;
+        goto Exit;
 
-#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+      /* all data have been read */
+      face->forget_glyph_frame( loader );
+      opened_frame = 0;
 
-      {
-        TT_Size  size = (TT_Size)loader->size;
-
-
-        error = TT_Process_Simple_Glyph( loader,
-                                         (FT_Bool)( size && size->debug ) );
-      }
-
-#else
-
-      error = TT_Process_Simple_Glyph( loader, 0 );
-
-#endif
-
+      error = TT_Process_Simple_Glyph( loader );
       if ( error )
-        goto Fail;
+        goto Exit;
 
       FT_GlyphLoader_Add( gloader );
-
-      /* Note: We could have put the simple loader source there */
-      /*       but the code is fat enough already :-)           */
     }
 
     /***********************************************************************/
@@ -1245,29 +1437,25 @@
     /***********************************************************************/
 
     /* otherwise, load a composite! */
-    else if ( contours_count == -1 )
+    else if ( loader->n_contours == -1 )
     {
-      TT_GlyphSlot  glyph = (TT_GlyphSlot)loader->glyph;
       FT_UInt       start_point;
-#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
       FT_UInt       start_contour;
       FT_ULong      ins_pos;  /* position of composite instructions, if any */
-#endif
 
 
-      /* for each subglyph, read composite header */
       start_point   = gloader->base.outline.n_points;
-#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
       start_contour = gloader->base.outline.n_contours;
-#endif
 
+      /* for each subglyph, read composite header */
       error = face->read_composite_glyph( loader );
       if ( error )
-        goto Fail;
+        goto Exit;
 
-#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+      /* store the offset of instructions */
       ins_pos = loader->ins_pos;
-#endif
+
+      /* all data we need are read */
       face->forget_glyph_frame( loader );
       opened_frame = 0;
 
@@ -1290,7 +1478,6 @@
                         gloader->current.num_subglyphs + 4 )) != 0 )
           goto Exit;
 
-        /* Note: No subglyph reallocation here, our pointers are stable. */
         subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
         limit    = gloader->current.num_subglyphs;
 
@@ -1327,13 +1514,9 @@
       /*                                                               */
       if ( loader->load_flags & FT_LOAD_NO_RECURSE )
       {
-        /* set up remaining glyph fields */
         FT_GlyphLoader_Add( gloader );
+        loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
 
-        glyph->num_subglyphs = gloader->base.num_subglyphs;
-        glyph->format        = FT_GLYPH_FORMAT_COMPOSITE;
-        glyph->subglyphs     = gloader->base.subglyphs;
-
         goto Exit;
       }
 
@@ -1341,11 +1524,11 @@
       /*********************************************************************/
       /*********************************************************************/
 
-      /* Now, read each subglyph independently. */
       {
-        FT_Int       n, num_base_points, num_new_points;
+        FT_Int       n, num_base_points;
         FT_SubGlyph  subglyph       = 0;
 
+        FT_UInt      num_points     = start_point;
         FT_UInt      num_subglyphs  = gloader->current.num_subglyphs;
         FT_UInt      num_base_subgs = gloader->base.num_subglyphs;
 
@@ -1352,10 +1535,10 @@
 
         FT_GlyphLoader_Add( gloader );
 
+        /* read each subglyph independently */
         for ( n = 0; n < (FT_Int)num_subglyphs; n++ )
         {
-          FT_Vector  pp1, pp2, pp3, pp4;
-          FT_Pos     x, y;
+          FT_Vector  pp[4];
 
 
           /* Each time we call load_truetype_glyph in this loop, the   */
@@ -1364,10 +1547,10 @@
           /* pointer on each iteration.                                */
           subglyph = gloader->base.subglyphs + num_base_subgs + n;
 
-          pp1 = loader->pp1;
-          pp2 = loader->pp2;
-          pp3 = loader->pp3;
-          pp4 = loader->pp4;
+          pp[0] = loader->pp1;
+          pp[1] = loader->pp2;
+          pp[2] = loader->pp3;
+          pp[3] = loader->pp4;
 
           num_base_points = gloader->base.outline.n_points;
 
@@ -1374,289 +1557,55 @@
           error = load_truetype_glyph( loader, subglyph->index,
                                        recurse_count + 1 );
           if ( error )
-            goto Fail;
+            goto Exit;
 
           /* restore subglyph pointer */
           subglyph = gloader->base.subglyphs + num_base_subgs + n;
 
-          if ( subglyph->flags & USE_MY_METRICS )
+          if ( !( subglyph->flags & USE_MY_METRICS ) )
           {
-            pp1 = loader->pp1;
-            pp2 = loader->pp2;
-            pp3 = loader->pp3;
-            pp4 = loader->pp4;
+            loader->pp1 = pp[0];
+            loader->pp2 = pp[1];
+            loader->pp3 = pp[2];
+            loader->pp4 = pp[3];
           }
-          else
-          {
-            loader->pp1 = pp1;
-            loader->pp2 = pp2;
-            loader->pp3 = pp3;
-            loader->pp4 = pp4;
-          }
 
           num_points = gloader->base.outline.n_points;
 
-          num_new_points = num_points - num_base_points;
+          if ( num_points == num_base_points )
+            continue;
 
-          /* now perform the transform required for this subglyph */
-
-          if ( subglyph->flags & ( WE_HAVE_A_SCALE     |
-                                   WE_HAVE_AN_XY_SCALE |
-                                   WE_HAVE_A_2X2       ) )
-          {
-            FT_Vector*  cur   = gloader->base.outline.points +
-                                  num_base_points;
-            FT_Vector*  org   = gloader->base.extra_points +
-                                  num_base_points;
-            FT_Vector*  limit = cur + num_new_points;
-
-
-            for ( ; cur < limit; cur++, org++ )
-            {
-              FT_Vector_Transform( cur, &subglyph->transform );
-              FT_Vector_Transform( org, &subglyph->transform );
-            }
-          }
-
-          /* apply offset */
-
-          if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
-          {
-            FT_UInt     k = subglyph->arg1;
-            FT_UInt     l = subglyph->arg2;
-            FT_Vector*  p1;
-            FT_Vector*  p2;
-
-
-            if ( start_point + k >= (FT_UInt)num_base_points ||
-                               l >= (FT_UInt)num_new_points  )
-            {
-              error = TT_Err_Invalid_Composite;
-              goto Fail;
-            }
-
-            l += num_base_points;
-
-            p1 = gloader->base.outline.points + start_point + k;
-            p2 = gloader->base.outline.points + start_point + l;
-
-            x = p1->x - p2->x;
-            y = p1->y - p2->y;
-          }
-          else
-          {
-            x = subglyph->arg1;
-            y = subglyph->arg2;
-
-  /* Use a default value dependent on                                     */
-  /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED.  This is useful for old TT */
-  /* fonts which don't set the xxx_COMPONENT_OFFSET bit.                  */
-
-#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
-            if ( !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) &&
-#else
-            if (  ( subglyph->flags & SCALED_COMPONENT_OFFSET ) &&
-#endif
-                  ( subglyph->flags & ( WE_HAVE_A_SCALE     |
-                                        WE_HAVE_AN_XY_SCALE |
-                                        WE_HAVE_A_2X2       )) )
-            {
-#if 0
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* This algorithm is what Apple documents.  But it doesn't work.         */
-  /*                                                                       */
-              int  a = subglyph->transform.xx > 0 ?  subglyph->transform.xx
-                                                  : -subglyph->transform.xx;
-              int  b = subglyph->transform.yx > 0 ?  subglyph->transform.yx
-                                                  : -subglyph->transform.yx;
-              int  c = subglyph->transform.xy > 0 ?  subglyph->transform.xy
-                                                  : -subglyph->transform.xy;
-              int  d = subglyph->transform.yy > 0 ? subglyph->transform.yy
-                                                  : -subglyph->transform.yy;
-              int  m = a > b ? a : b;
-              int  n = c > d ? c : d;
-
-
-              if ( a - b <= 33 && a - b >= -33 )
-                m *= 2;
-              if ( c - d <= 33 && c - d >= -33 )
-                n *= 2;
-              x = FT_MulFix( x, m );
-              y = FT_MulFix( y, n );
-
-#else /* 0 */
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* This algorithm is a guess and works much better than the above.       */
-  /*                                                                       */
-              FT_Fixed  mac_xscale = FT_SqrtFixed(
-                                       FT_MulFix( subglyph->transform.xx,
-                                                  subglyph->transform.xx ) +
-                                       FT_MulFix( subglyph->transform.xy,
-                                                  subglyph->transform.xy) );
-              FT_Fixed  mac_yscale = FT_SqrtFixed(
-                                       FT_MulFix( subglyph->transform.yy,
-                                                  subglyph->transform.yy ) +
-                                       FT_MulFix( subglyph->transform.yx,
-                                                  subglyph->transform.yx ) );
-
-
-              x = FT_MulFix( x, mac_xscale );
-              y = FT_MulFix( y, mac_yscale );
-#endif /* 0 */
-
-            }
-
-            if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
-            {
-              x = FT_MulFix( x, x_scale );
-              y = FT_MulFix( y, y_scale );
-
-              if ( subglyph->flags & ROUND_XY_TO_GRID )
-              {
-                x = FT_PIX_ROUND( x );
-                y = FT_PIX_ROUND( y );
-              }
-            }
-          }
-
-          if ( x || y )
-          {
-            translate_array( num_new_points,
-                             gloader->base.outline.points + num_base_points,
-                             x, y );
-
-            translate_array( num_new_points,
-                             gloader->base.extra_points + num_base_points,
-                             x, y );
-          }
+          /* gloader->base.outline consists of three part:                  */
+          /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points.   */
+          /*                                                                */
+          /* (1): exist from the beginning                                  */
+          /* (2): components that have been loaded so far                   */
+          /* (3): the newly loaded component                                */
+          TT_Process_Composite_Component( loader, subglyph, start_point,
+                                          num_base_points );
         }
 
-        /*******************************************************************/
-        /*******************************************************************/
-        /*******************************************************************/
 
-        /* we have finished loading all sub-glyphs; now, look for */
-        /* instructions for this composite!                       */
+        /* process the glyph */
+        loader->ins_pos = ins_pos;
+        if ( IS_HINTED( loader->load_flags ) &&
 
 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
-        if ( num_subglyphs > 0               &&
-             loader->exec                    &&
-             ins_pos > 0                     &&
-             subglyph->flags & WE_HAVE_INSTR )
-        {
-          FT_UShort       n_ins;
-          TT_ExecContext  exec = loader->exec;
-          TT_GlyphZone    pts;
-          FT_Vector*      pp1;
+             subglyph->flags & WE_HAVE_INSTR &&
 
+#endif
 
-          /* read size of instructions */
-          if ( FT_STREAM_SEEK( ins_pos ) ||
-               FT_READ_USHORT( n_ins ) )
-            goto Fail;
-          FT_TRACE5(( "  Instructions size = %d\n", n_ins ));
+             num_points > start_point )
+          TT_Process_Composite_Glyph( loader, start_point, start_contour );
 
-          /* in some fonts? */
-          if ( n_ins == 0xFFFFU )
-            n_ins = 0;
-
-          /* check it */
-          if ( n_ins > face->max_profile.maxSizeOfInstructions )
-          {
-            FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n",
-                        n_ins, subglyph->index ));
-            error = TT_Err_Too_Many_Hints;
-            goto Fail;
-          }
-
-          /* read the instructions */
-          if ( FT_STREAM_READ( exec->glyphIns, n_ins ) )
-            goto Fail;
-
-          glyph->control_data = exec->glyphIns;
-          glyph->control_len  = n_ins;
-
-          error = TT_Set_CodeRange( exec,
-                                    tt_coderange_glyph,
-                                    exec->glyphIns,
-                                    n_ins );
-          if ( error )
-            goto Fail;
-
-          error = FT_GlyphLoader_CheckPoints( gloader, num_points + 4, 0 );
-          if ( error )
-            goto Fail;
-
-          /* prepare the execution context */
-          tt_prepare_zone( &exec->pts, &gloader->base,
-                           start_point, start_contour );
-          pts = &exec->pts;
-
-          pts->n_points   = (short)( num_points + 4 );
-          pts->n_contours = gloader->base.outline.n_contours;
-
-          /* add phantom points */
-          pp1    = pts->cur + num_points;
-          pp1[0] = loader->pp1;
-          pp1[1] = loader->pp2;
-          pp1[2] = loader->pp3;
-          pp1[3] = loader->pp4;
-
-          pts->tags[num_points    ] = 0;
-          pts->tags[num_points + 1] = 0;
-          pts->tags[num_points + 2] = 0;
-          pts->tags[num_points + 3] = 0;
-
-          /* if hinting, round the phantom points */
-          if ( IS_HINTED( loader->load_flags ) )
-          {
-            pp1[0].x = FT_PIX_ROUND( loader->pp1.x );
-            pp1[1].x = FT_PIX_ROUND( loader->pp2.x );
-            pp1[2].y = FT_PIX_ROUND( loader->pp3.y );
-            pp1[3].y = FT_PIX_ROUND( loader->pp4.y );
-          }
-
-          {
-            FT_UInt  k;
-
-
-            for ( k = 0; k < num_points; k++ )
-              pts->tags[k] &= FT_CURVE_TAG_ON;
-          }
-
-          cur_to_org( num_points + 4, pts );
-
-          /* now consider hinting */
-          if ( IS_HINTED( loader->load_flags ) && n_ins > 0 )
-          {
-            exec->is_composite     = TRUE;
-            error = TT_Run_Context( exec, ((TT_Size)loader->size)->debug );
-            if ( error && exec->pedantic_hinting )
-              goto Fail;
-          }
-
-          /* save glyph origin and advance points */
-          loader->pp1 = pp1[0];
-          loader->pp2 = pp1[1];
-          loader->pp3 = pp1[2];
-          loader->pp4 = pp1[3];
-        }
-
-#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
-
       }
-      /* end of composite loading */
     }
     else
     {
       /* invalid composite count ( negative but not -1 ) */
       error = TT_Err_Invalid_Outline;
-      goto Fail;
+      goto Exit;
     }
 
     /***********************************************************************/
@@ -1663,17 +1612,18 @@
     /***********************************************************************/
     /***********************************************************************/
 
-  Fail:
+  Exit:
+
     if ( opened_frame )
       face->forget_glyph_frame( loader );
 
-  Exit:
-
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
+
     if ( glyph_data_loaded )
       face->root.internal->incremental_interface->funcs->free_glyph_data(
         face->root.internal->incremental_interface->object,
         &glyph_data );
+
 #endif
 
     return error;
@@ -1696,18 +1646,7 @@
       y_scale = size->root.metrics.y_scale;
 
     if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
-    {
-      glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
-
-      /* copy outline to our glyph slot */
-      FT_GlyphLoader_CopyPoints( glyph->internal->loader, loader->gloader );
-      glyph->outline = glyph->internal->loader->base.outline;
-
-      /* translate array so that (0,0) is the glyph's origin */
-      FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 );
-
       FT_Outline_Get_CBox( &glyph->outline, &bbox );
-    }
     else
       bbox = loader->bbox;
 
@@ -1852,7 +1791,7 @@
     }
 
     /* adjust advance width to the value contained in the hdmx table */
-    if ( !face->postscript.isFixedPitch && size &&
+    if ( !face->postscript.isFixedPitch &&
          IS_HINTED( loader->load_flags )        )
     {
       FT_Byte*  widthp = Get_Advance_WidthPtr( face,
@@ -1875,6 +1814,153 @@
   }
 
 
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+  static FT_Error
+  load_sbit_image( TT_Size       size,
+                   TT_GlyphSlot  glyph,
+                   FT_UInt       glyph_index,
+                   FT_Int32      load_flags )
+  {
+    TT_Face             face;
+    SFNT_Service        sfnt;
+    FT_Stream           stream;
+    FT_Error            error;
+    TT_SBit_MetricsRec  metrics;
+
+    face   = (TT_Face)glyph->face;
+    sfnt   = (SFNT_Service)face->sfnt;
+    stream = face->root.stream;
+
+    error = sfnt->load_sbit_image( face,
+                                   (FT_ULong)size->strike_index,
+                                   glyph_index,
+                                   (FT_Int)load_flags,
+                                   stream,
+                                   &glyph->bitmap,
+                                   &metrics );
+    if ( !error )
+    {
+      glyph->outline.n_points   = 0;
+      glyph->outline.n_contours = 0;
+
+      glyph->metrics.width  = (FT_Pos)metrics.width  << 6;
+      glyph->metrics.height = (FT_Pos)metrics.height << 6;
+
+      glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
+      glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
+      glyph->metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;
+
+      glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
+      glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
+      glyph->metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;
+
+      glyph->format = FT_GLYPH_FORMAT_BITMAP;
+      if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
+      {
+        glyph->bitmap_left = metrics.vertBearingX;
+        glyph->bitmap_top  = metrics.vertBearingY;
+      }
+      else
+      {
+        glyph->bitmap_left = metrics.horiBearingX;
+        glyph->bitmap_top  = metrics.horiBearingY;
+      }
+    }
+
+    return error;
+  }
+#endif
+
+
+  static FT_Error
+  tt_loader_init( TT_Loader     loader,
+                  TT_Size       size,
+                  TT_GlyphSlot  glyph,
+                  FT_Int32      load_flags )
+  {
+    TT_Face         face;
+    FT_Stream       stream;
+
+
+    face = (TT_Face)glyph->face;
+    stream = face->root.stream;
+
+    FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) );
+
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
+
+    /* load execution context */
+    {
+      TT_ExecContext  exec;
+
+
+      /* query new execution context */
+      exec = size->debug ? size->context
+                         : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
+      if ( !exec )
+        return TT_Err_Could_Not_Find_Context;
+
+      TT_Load_Context( exec, face, size );
+
+      /* see if the cvt program has disabled hinting */
+      if ( exec->GS.instruct_control & 1 )
+        load_flags |= FT_LOAD_NO_HINTING;
+
+      /* load default graphics state - if needed */
+      if ( exec->GS.instruct_control & 2 )
+        exec->GS = tt_default_graphics_state;
+
+      exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
+      exec->grayscale =
+        FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_LOAD_TARGET_MONO );
+
+      loader->exec = exec;
+      loader->instructions = exec->glyphIns;
+    }
+
+#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
+
+    /* seek to the beginning of the glyph table.  For Type 42 fonts      */
+    /* the table might be accessed from a Postscript stream or something */
+    /* else...                                                           */
+
+#ifdef FT_CONFIG_OPTION_INCREMENTAL
+
+    if ( face->root.internal->incremental_interface )
+      loader->glyf_offset = 0;
+    else
+
+#endif
+
+    {
+      FT_Error  error = face->goto_table( face, TTAG_glyf, stream, 0 );
+      if ( error )
+      {
+        FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" ));
+        return error;
+      }
+      loader->glyf_offset = FT_STREAM_POS();
+    }
+
+    /* get face's glyph loader */
+    {
+      FT_GlyphLoader  gloader = glyph->internal->loader;
+
+      FT_GlyphLoader_Rewind( gloader );
+      loader->gloader = gloader;
+    }
+
+    loader->load_flags    = load_flags;
+
+    loader->face   = (FT_Face)face;
+    loader->size   = (FT_Size)size;
+    loader->glyph  = (FT_GlyphSlot)glyph;
+    loader->stream = stream;
+
+    return TT_Err_Ok;
+  }
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -1908,7 +1994,6 @@
                  FT_UInt       glyph_index,
                  FT_Int32      load_flags )
   {
-    SFNT_Service  sfnt;
     TT_Face       face;
     FT_Stream     stream;
     FT_Error      error;
@@ -1916,21 +2001,9 @@
 
 
     face   = (TT_Face)glyph->face;
-    sfnt   = (SFNT_Service)face->sfnt;
     stream = face->root.stream;
     error  = TT_Err_Ok;
 
-    if ( !size || ( load_flags & FT_LOAD_NO_SCALE )   ||
-                  ( load_flags & FT_LOAD_NO_RECURSE ) )
-    {
-      size        = NULL;
-      load_flags |= FT_LOAD_NO_SCALE   |
-                    FT_LOAD_NO_HINTING |
-                    FT_LOAD_NO_BITMAP;
-    }
-
-    glyph->num_subglyphs = 0;
-
 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
     /* try to load embedded bitmap if any              */
@@ -1937,173 +2010,56 @@
     /*                                                 */
     /* XXX: The convention should be emphasized in     */
     /*      the documents because it can be confusing. */
-    if ( size                                    &&
-         size->strike_index != 0xFFFFU           &&
-         sfnt->load_sbits                        &&
+    if ( size->strike_index != 0xFFFFU &&
          ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
-
     {
-      TT_SBit_MetricsRec  metrics;
-
-
-      error = sfnt->load_sbit_image( face,
-                                     (FT_ULong)size->strike_index,
-                                     glyph_index,
-                                     (FT_Int)load_flags,
-                                     stream,
-                                     &glyph->bitmap,
-                                     &metrics );
+      error = load_sbit_image( size, glyph, glyph_index, load_flags );
       if ( !error )
-      {
-        glyph->outline.n_points   = 0;
-        glyph->outline.n_contours = 0;
-
-        glyph->metrics.width  = (FT_Pos)metrics.width  << 6;
-        glyph->metrics.height = (FT_Pos)metrics.height << 6;
-
-        glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
-        glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
-        glyph->metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;
-
-        glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
-        glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
-        glyph->metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;
-
-        glyph->format = FT_GLYPH_FORMAT_BITMAP;
-        if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
-        {
-          glyph->bitmap_left = metrics.vertBearingX;
-          glyph->bitmap_top  = metrics.vertBearingY;
-        }
-        else
-        {
-          glyph->bitmap_left = metrics.horiBearingX;
-          glyph->bitmap_top  = metrics.horiBearingY;
-        }
-        return error;
-      }
+        return TT_Err_Ok;
     }
 
 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
 
-    /* return immediately if we only want the embedded bitmaps */
     if ( load_flags & FT_LOAD_SBITS_ONLY )
       return TT_Err_Invalid_Argument;
 
-    /* seek to the beginning of the glyph table.  For Type 42 fonts      */
-    /* the table might be accessed from a Postscript stream or something */
-    /* else...                                                           */
+    error = tt_loader_init( &loader, size, glyph, load_flags );
+    if ( error )
+      return error;
 
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
+    glyph->format        = FT_GLYPH_FORMAT_OUTLINE;
+    glyph->num_subglyphs = 0;
+    glyph->outline.flags = 0;
 
-    /* Don't look for the glyph table if this is an incremental font. */
-    if ( !face->root.internal->incremental_interface )
-
-#endif
-
+    /* Main loading loop */
+    error = load_truetype_glyph( &loader, glyph_index, 0 );
+    if ( !error )
     {
-      error = face->goto_table( face, TTAG_glyf, stream, 0 );
-      if ( error )
+      if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
       {
-        FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" ));
-        goto Exit;
+        glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
+        glyph->subglyphs     = loader.gloader->base.subglyphs;
       }
-    }
+      else
+      {
+        glyph->outline = loader.gloader->base.outline;
+        glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
 
-    FT_MEM_ZERO( &loader, sizeof ( loader ) );
+        /* translate array so that (0,0) is the glyph's origin */
+        if ( loader.pp1.x )
+          FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
+      }
 
-    /* update the glyph zone bounds */
-    {
-      FT_GlyphLoader  gloader = FT_FACE_DRIVER( face )->glyph_loader;
-
-
-      loader.gloader = gloader;
-
-      FT_GlyphLoader_Rewind( gloader );
-
-      tt_prepare_zone( &loader.zone, &gloader->base, 0, 0 );
-      tt_prepare_zone( &loader.base, &gloader->base, 0, 0 );
+      compute_glyph_metrics( &loader, glyph_index );
     }
 
-#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
-
-    if ( size )
-    {
-      /* query new execution context */
-      loader.exec = size->debug ? size->context : TT_New_Context( face );
-      if ( !loader.exec )
-        return TT_Err_Could_Not_Find_Context;
-
-      TT_Load_Context( loader.exec, face, size );
-      loader.instructions = loader.exec->glyphIns;
-
-      /* load default graphics state - if needed */
-      if ( size->GS.instruct_control & 2 )
-        loader.exec->GS = tt_default_graphics_state;
-
-      loader.exec->pedantic_hinting =
-         FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
-
-      loader.exec->grayscale =
-         FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_LOAD_TARGET_MONO );
-    }
-
-#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
-
-    /* clear all outline flags, except the `owner' one */
-    glyph->outline.flags = 0;
-
-    /* let's initialize the rest of our loader now */
-
-    loader.load_flags    = load_flags;
-
-    loader.face   = (FT_Face)face;
-    loader.size   = (FT_Size)size;
-    loader.glyph  = (FT_GlyphSlot)glyph;
-    loader.stream = stream;
-
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
-
-    if ( face->root.internal->incremental_interface )
-      loader.glyf_offset = 0;
-    else
-
-#endif
-
-      loader.glyf_offset = FT_STREAM_POS();
-
-#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
-
-    /* if the cvt program has disabled hinting, the argument */
-    /* is ignored.                                           */
-    if ( size && ( size->GS.instruct_control & 1 ) )
-      loader.load_flags |= FT_LOAD_NO_HINTING;
-
-#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
-
-    /* Main loading loop */
-    glyph->format        = FT_GLYPH_FORMAT_OUTLINE;
-    glyph->num_subglyphs = 0;
-
-    error = load_truetype_glyph( &loader, glyph_index, 0 );
-    if ( !error )
-      compute_glyph_metrics( &loader, glyph_index );
-
-#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
-
-    if ( !size || !size->debug )
-      TT_Done_Context( loader.exec );
-
-#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
-
     /* Set the `high precision' bit flag.                           */
     /* This is _critical_ to get correct output for monochrome      */
     /* TrueType glyphs at all sizes using the bytecode interpreter. */
     /*                                                              */
-    if ( size && size->root.metrics.y_ppem < 24 )
+    if ( size->root.metrics.y_ppem < 24 )
       glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
 
-  Exit:
     return error;
   }
 
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -371,7 +371,7 @@
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
-  /*    TT_Destroy_Context                                                 */
+  /*    TT_Done_Context                                                    */
   /*                                                                       */
   /* <Description>                                                         */
   /*    Destroys a given context.                                          */
@@ -388,9 +388,11 @@
   /*    Only the glyph loader and debugger should call this function.      */
   /*                                                                       */
   FT_LOCAL_DEF( FT_Error )
-  TT_Destroy_Context( TT_ExecContext  exec,
-                      FT_Memory       memory )
+  TT_Done_Context( TT_ExecContext  exec )
   {
+    FT_Memory  memory = exec->memory;
+
+
     /* free composite load stack */
     FT_FREE( exec->loadStack );
     exec->loadSize = 0;
@@ -416,6 +418,7 @@
     exec->face = NULL;
 
     FT_FREE( exec );
+
     return TT_Err_Ok;
   }
 
@@ -431,8 +434,6 @@
   /* <Input>                                                               */
   /*    memory :: A handle to the parent memory object.                    */
   /*                                                                       */
-  /*    face   :: A handle to the source TrueType face object.             */
-  /*                                                                       */
   /* <InOut>                                                               */
   /*    exec   :: A handle to the target execution context.                */
   /*                                                                       */
@@ -441,14 +442,12 @@
   /*                                                                       */
   static FT_Error
   Init_Context( TT_ExecContext  exec,
-                TT_Face         face,
                 FT_Memory       memory )
   {
     FT_Error  error;
 
 
-    FT_TRACE1(( "Init_Context: new object at 0x%08p, parent = 0x%08p\n",
-                exec, face ));
+    FT_TRACE1(( "Init_Context: new object at 0x%08p\n", exec ));
 
     exec->memory   = memory;
     exec->callSize = 32;
@@ -469,7 +468,7 @@
     exec->loadStack = NULL;
     exec->glyphIns  = NULL;
 
-    exec->face = face;
+    exec->face = NULL;
     exec->size = NULL;
 
     return TT_Err_Ok;
@@ -477,7 +476,7 @@
   Fail_Memory:
     FT_ERROR(( "Init_Context: not enough memory for 0x%08lx\n",
                (FT_Long)exec ));
-    TT_Destroy_Context( exec, memory );
+    TT_Done_Context( exec );
 
     return error;
  }
@@ -770,18 +769,12 @@
   /* documentation is in ttinterp.h */
 
   FT_EXPORT_DEF( TT_ExecContext )
-  TT_New_Context( TT_Face  face )
+  TT_New_Context( TT_Driver  driver )
   {
-    TT_Driver       driver;
     TT_ExecContext  exec;
     FT_Memory       memory;
 
 
-    if ( !face )
-      return 0;
-
-    driver = (TT_Driver)face->root.driver;
-
     memory = driver->root.root.memory;
     exec   = driver->context;
 
@@ -795,7 +788,7 @@
         goto Exit;
 
       /* initialize it */
-      error = Init_Context( exec, face, memory );
+      error = Init_Context( exec, memory );
       if ( error )
         goto Fail;
 
@@ -811,34 +804,6 @@
 
     return 0;
   }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    TT_Done_Context                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Discards an execution context.                                     */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    exec :: A handle to the target execution context.                  */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    Only the glyph loader and debugger should call this function.      */
-  /*                                                                       */
-  FT_LOCAL_DEF( FT_Error )
-  TT_Done_Context( TT_ExecContext  exec )
-  {
-    /* Nothing at all for now */
-    FT_UNUSED( exec );
-
-    return TT_Err_Ok;
-  }
-
 
 
   /*************************************************************************/
--- a/src/truetype/ttinterp.h
+++ b/src/truetype/ttinterp.h
@@ -263,15 +263,10 @@
   /*    Only the glyph loader and debugger should call this function.      */
   /*                                                                       */
   FT_EXPORT( TT_ExecContext )
-  TT_New_Context( TT_Face  face );
+  TT_New_Context( TT_Driver  driver );
 
-
   FT_LOCAL( FT_Error )
   TT_Done_Context( TT_ExecContext  exec );
-
-  FT_LOCAL( FT_Error )
-  TT_Destroy_Context( TT_ExecContext  exec,
-                      FT_Memory       memory );
 
   FT_LOCAL( FT_Error )
   TT_Load_Context( TT_ExecContext  exec,
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -348,7 +348,7 @@
     if ( size->debug )
       exec = size->context;
     else
-      exec = TT_New_Context( face );
+      exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
 
     if ( !exec )
       return TT_Err_Could_Not_Find_Context;
@@ -403,9 +403,6 @@
     if ( !error )
       TT_Save_Context( exec, size );
 
-    if ( !size->debug )
-      TT_Done_Context( exec );
-
     return error;
   }
 
@@ -436,7 +433,7 @@
     if ( size->debug )
       exec = size->context;
     else
-      exec = TT_New_Context( face );
+      exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
 
     if ( !exec )
       return TT_Err_Could_Not_Find_Context;
@@ -470,9 +467,6 @@
 
     TT_Save_Context( exec, size );
 
-    if ( !size->debug )
-      TT_Done_Context( exec );
-
     return error;
   }
 
@@ -917,15 +911,24 @@
   /*    FreeType error code.  0 means success.                             */
   /*                                                                       */
   FT_LOCAL_DEF( FT_Error )
-  tt_driver_init( FT_Module  driver )       /* TT_Driver */
+  tt_driver_init( FT_Module  ttdriver )     /* TT_Driver */
   {
-    FT_Error  error;
 
+#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
 
-    /* set `extra' in glyph loader */
-    error = FT_GlyphLoader_CreateExtra( FT_DRIVER( driver )->glyph_loader );
+    TT_Driver  driver = (TT_Driver)ttdriver;
 
-    return error;
+
+    if ( !TT_New_Context( driver ) )
+      return TT_Err_Could_Not_Find_Context;
+
+#else
+
+    FT_UNUSED( ttdriver );
+
+#endif
+
+    return TT_Err_Ok;
   }
 
 
@@ -950,7 +953,7 @@
     /* destroy the execution context */
     if ( driver->context )
     {
-      TT_Destroy_Context( driver->context, driver->root.root.memory );
+      TT_Done_Context( driver->context );
       driver->context = NULL;
     }
 #else
@@ -957,6 +960,27 @@
     FT_UNUSED( ttdriver );
 #endif
 
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    tt_slot_init                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Initializes a new slot object.                                     */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    slot :: A handle to the slot object.                               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF( FT_Error )
+  tt_slot_init( FT_GlyphSlot  slot )
+  {
+    return FT_GlyphLoader_CreateExtra( slot->internal->loader );
   }
 
 
--- a/src/truetype/ttobjs.h
+++ b/src/truetype/ttobjs.h
@@ -442,6 +442,14 @@
   tt_driver_done( FT_Module  ttdriver );    /* TT_Driver */
 
 
+  /*************************************************************************/
+  /*                                                                       */
+  /* Slot functions                                                      */
+  /*                                                                       */
+  FT_LOCAL( FT_Error )
+  tt_slot_init( FT_GlyphSlot  slot );
+
+
 FT_END_HEADER
 
 #endif /* __TTOBJS_H__ */