shithub: freetype+ttf2subf

Download patch

ref: ed7f62aca5eab9d808daf0879607779bd2670173
parent: 7024ca1a37b7753e5c0de13330cb34fdbf28fb18
author: David Turner <[email protected]>
date: Tue Mar 28 06:19:28 EST 2000

support for FT_LOAD_NO_RECURSE needed by the auto-hinter

git/fs: mount .git/fs: mount/attach disallowed
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -474,7 +474,7 @@
     TT_ULong     ins_offset;
     
     /* check glyph index */
-    index = (TT_UInt)glyph_index;
+    index = glyph_index;
     if ( index >= (TT_UInt)face->root.num_glyphs )
     {
       error = TT_Err_Invalid_Glyph_Index;
@@ -698,10 +698,40 @@
         /* composite instructions, if we find some ..             */
         /* we will process them later..                           */
         ins_offset = FILE_Pos() + stream->cursor - stream->limit;
-        FORGET_Frame();
       }
 #endif
+      FORGET_Frame();
 
+      /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
+      /* "as is" in the glyph slot (the client application will be     */
+      /* responsible for interpreting this data..)                     */
+      if ( loader->load_flags & FT_LOAD_NO_RECURSE )
+      {
+        FT_GlyphSlot  glyph = loader->glyph;
+
+        /* reallocate subglyph array if necessary */        
+        if (glyph->max_subglyphs < num_subglyphs)
+        {
+          FT_Memory  memory = loader->face->root.memory;
+          
+          if ( REALLOC_ARRAY( glyph->subglyphs, glyph->max_subglyphs,
+                              num_subglyphs, FT_SubGlyph ) )
+            goto Fail;
+            
+          glyph->max_subglyphs = num_subglyphs;
+        }
+
+        /* copy subglyph array */
+        MEM_Copy( glyph->subglyphs, subglyphs,
+                  num_subglyphs*sizeof(FT_SubGlyph));
+                  
+        /* set up remaining glyph fields */
+        glyph->num_subglyphs = num_subglyphs;
+        glyph->format        = ft_glyph_format_composite;
+        goto Load_End;
+      }
+
+
     /*************************************************************************/
     /*************************************************************************/
     /*************************************************************************/
@@ -954,6 +984,7 @@
       y_scale = size->root.metrics.y_scale;
     }
     
+    if ( glyph->format != ft_glyph_format_composite )
     {
       TT_UInt  u;
       for ( u = 0; u < num_points + 2; u++ )
@@ -964,30 +995,31 @@
 
       for ( u = 0; u < num_contours; u++ )
         glyph->outline.contours[u] = loader->base.contours[u];
-    }
 
-    glyph->outline.n_points    = num_points;
-    glyph->outline.n_contours  = num_contours;
-    
-    /* glyph->outline.second_pass = TRUE; */
-    glyph->outline.flags &= ~ft_outline_single_pass;
+      /* glyph->outline.second_pass = TRUE; */
+      glyph->outline.flags      &= ~ft_outline_single_pass;
+      glyph->outline.n_points    = num_points;
+      glyph->outline.n_contours  = num_contours;
+  
+      /* translate array so that (0,0) is the glyph's origin */
+      translate_array( (TT_UShort)(num_points + 2),
+                       glyph->outline.points,
+                       -loader->pp1.x,
+                       0 );
+  
+      FT_Outline_Get_CBox( &glyph->outline, &bbox );
 
-    /* translate array so that (0,0) is the glyph's origin */
-    translate_array( (TT_UShort)(num_points + 2),
-                     glyph->outline.points,
-                     -loader->pp1.x,
-                     0 );
-
-    FT_Outline_Get_CBox( &glyph->outline, &bbox );
-
-    if ( IS_HINTED(loader->load_flags) )
-    {
-      /* grid-fit the bounding box */
-      bbox.xMin &= -64;
-      bbox.yMin &= -64;
-      bbox.xMax  = (bbox.xMax + 63) & -64;
-      bbox.yMax  = (bbox.yMax + 63) & -64;
+      if ( IS_HINTED(loader->load_flags) )
+      {
+        /* grid-fit the bounding box */
+        bbox.xMin &= -64;
+        bbox.yMin &= -64;
+        bbox.xMax  = (bbox.xMax + 63) & -64;
+        bbox.yMax  = (bbox.yMax + 63) & -64;
+      }
     }
+    else
+      bbox = loader->bbox;
 
     /* get the device-independent scaled horizontal metrics */
     /* take care of fixed-pitch fonts...                    */
@@ -1141,7 +1173,6 @@
     glyph->metrics.width  = bbox.xMax - bbox.xMin;
     glyph->metrics.height = bbox.yMax - bbox.yMin;
 
-    glyph->format = ft_glyph_format_outline;
   }
 
 
@@ -1174,8 +1205,9 @@
     stream = face->root.stream;
     memory = face->root.memory;
     error  = 0;
-    
-    if ( !size || (load_flags & FT_LOAD_NO_SCALE) )
+
+    if ( !size || (load_flags & FT_LOAD_NO_SCALE)  ||
+                  (load_flags & FT_LOAD_NO_RECURSE ))
     {
       size        = NULL;
       load_flags |= FT_LOAD_NO_SCALE   |
@@ -1183,6 +1215,8 @@
                     FT_LOAD_NO_BITMAP;
     }
 
+    glyph->num_subglyphs = 0;
+
 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
     /*********************************************************************/
     /* Try to load embedded bitmap if any                                */
@@ -1245,6 +1279,9 @@
       goto Exit;
     }
     loader.base = *zone;
+    
+    loader.zone.n_points   = 0;
+    loader.zone.n_contours = 0;
 
 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
     if ( size )
@@ -1289,6 +1326,7 @@
 #endif
 
     /* Main loading loop */
+    glyph->format = ft_glyph_format_outline;
     error = load_truetype_glyph( &loader, glyph_index );
     if (!error)
       compute_glyph_metrics( &loader, glyph_index );
@@ -1301,30 +1339,6 @@
   Exit:
     return error;
   }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 
 
 
--- a/src/type1/t1gload.c
+++ b/src/type1/t1gload.c
@@ -255,7 +255,7 @@
     cur->n_points   = 0;
     cur->n_contours = 0;
     cur->points     = base->points   + base->n_points;
-    cur->tags      = base->tags    + base->n_points;
+    cur->tags       = base->tags     + base->n_points;
     cur->contours   = base->contours + base->n_contours;
 
     error = T1_Parse_CharStrings( decoder,
@@ -268,48 +268,88 @@
 
     n_base_points   = cur->n_points;
 
-    /* save the left bearing and width of the base character */
-    /* as they will be erased by the next load..             */
-    left_bearing = decoder->builder.left_bearing;
-    advance      = decoder->builder.advance;
+    if ( decoder->builder.no_recurse )
+    {
+      /* if we're trying to load a composite glyph, do not load the */
+      /* accent character and return the array of subglyphs..       */
+      FT_GlyphSlot  glyph = (FT_GlyphSlot)decoder->builder.glyph;
+      FT_SubGlyph*  subg;
 
-    decoder->builder.left_bearing.x = 0;
-    decoder->builder.left_bearing.y = 0;    
+      /* reallocate subglyph array if necessary */        
+      if (glyph->max_subglyphs < 2)
+      {
+        FT_Memory  memory = decoder->builder.face->root.memory;
+        
+        if ( REALLOC_ARRAY( glyph->subglyphs, glyph->max_subglyphs,
+                            2, FT_SubGlyph ) )
+          return error;
+          
+        glyph->max_subglyphs = 2;
+      }
 
-    /* Now load "achar" on top of */
-    /* the base outline           */
-    /*                            */ 
-    cur->n_points   = 0;
-    cur->n_contours = 0;
-    cur->points     = base->points   + base->n_points;
-    cur->tags      = base->tags    + base->n_points;
-    cur->contours   = base->contours + base->n_contours;
+      subg = glyph->subglyphs;
+      
+      /* subglyph 0 = base character */
+      subg->index = bchar_index;
+      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
+                    FT_SUBGLYPH_FLAG_USE_MY_METRICS;
+      subg->arg1  = 0;
+      subg->arg2  = 0;
+      subg++;
+      
+      /* subglyph 1 = accent character */
+      subg->index = achar_index;
+      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
+      subg->arg1  = adx - asb;
+      subg->arg2  = ady;
 
-    error = T1_Parse_CharStrings( decoder,
-                                  type1->charstrings    [achar_index],
-                                  type1->charstrings_len[achar_index],
-                                  type1->num_subrs,
-                                  type1->subrs,
-                                  type1->subrs_len );
-    if (error) return error;
-
-    /* adjust contours in accented character outline */
+      /* set up remaining glyph fields */
+      glyph->num_subglyphs = 2;
+      glyph->format        = ft_glyph_format_composite;
+    }
+    else
     {
-      T1_Int  n;
-
-      for ( n = 0; n < cur->n_contours; n++ )
-        cur->contours[n] += n_base_points;
+      /* save the left bearing and width of the base character */
+      /* as they will be erased by the next load..             */
+      left_bearing = decoder->builder.left_bearing;
+      advance      = decoder->builder.advance;
+  
+      decoder->builder.left_bearing.x = 0;
+      decoder->builder.left_bearing.y = 0;    
+  
+      /* Now load "achar" on top of */
+      /* the base outline           */
+      /*                            */ 
+      cur->n_points   = 0;
+      cur->n_contours = 0;
+      cur->points     = base->points   + base->n_points;
+      cur->tags       = base->tags     + base->n_points;
+      cur->contours   = base->contours + base->n_contours;
+  
+      error = T1_Parse_CharStrings( decoder,
+                                    type1->charstrings    [achar_index],
+                                    type1->charstrings_len[achar_index],
+                                    type1->num_subrs,
+                                    type1->subrs,
+                                    type1->subrs_len );
+      if (error) return error;
+  
+      /* adjust contours in accented character outline */
+      {
+        T1_Int  n;
+  
+        for ( n = 0; n < cur->n_contours; n++ )
+          cur->contours[n] += n_base_points;
+      }
+  
+      /* restore the left side bearing and   */
+      /* advance width of the base character */
+      decoder->builder.left_bearing = left_bearing;
+      decoder->builder.advance      = advance;
+  
+      /* Finally, move the accent */
+      FT_Outline_Translate( cur, adx - asb, ady );
     }
-
-    /* restore the left side bearing and   */
-    /* advance width of the base character */
-    decoder->builder.left_bearing = left_bearing;
-    decoder->builder.advance      = advance;
-
-    /* Finally, move the accent */
-    FT_Outline_Translate( cur, adx - asb, ady );
-    
-    (void)asb;           /* ignore this parameter */
     return T1_Err_Ok;
   }
 
@@ -1416,6 +1456,9 @@
     T1_Bool         hinting;
     T1_Font*        type1 = &face->type1;
 
+    if (load_flags & FT_LOAD_NO_RECURSE)
+      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
     glyph->x_scale = size->root.metrics.x_scale;
     glyph->y_scale = size->root.metrics.y_scale;
 
@@ -1470,6 +1513,7 @@
                        &gload_builder_interface );
 
       decoder.builder.pass = 1;
+      decoder.builder.no_recurse = 0;
 
       error = T1_Parse_CharStrings( &decoder,
                                     type1->charstrings    [glyph_index],
@@ -1483,6 +1527,7 @@
     }
     else
 #endif
+
     {
       T1_Init_Decoder( &decoder, &gload_hinter_interface );
 
@@ -1489,6 +1534,8 @@
       T1_Init_Builder( &decoder.builder, face, size, glyph,
                        &gload_builder_interface );
   
+      decoder.builder.no_recurse = !!(load_flags & FT_LOAD_NO_RECURSE);
+  
       /* now load the unscaled outline */
       error = T1_Parse_CharStrings( &decoder,
                                     type1->charstrings    [glyph_index],
@@ -1507,82 +1554,92 @@
     /* bearing the yMax..                                   */
     if (!error)
     {
-      FT_BBox           cbox;
-      FT_Glyph_Metrics* metrics = &glyph->root.metrics;
-
-      FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
-
-      /* grid fit the bounding box if necessary */
-      if (hinting)
+      /* for composite glyphs, return only the left side bearing and the */
+      /* advance width..                                                 */
+      if ( load_flags & FT_LOAD_NO_RECURSE )
       {
-        cbox.xMin &= -64;
-        cbox.yMin &= -64;
-        cbox.xMax = ( cbox.xMax+63 ) & -64;
-        cbox.yMax = ( cbox.yMax+63 ) & -64;
+        glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+        glyph->root.metrics.horiAdvance  = decoder.builder.advance.x;
       }
-
-      metrics->width  = cbox.xMax - cbox.xMin;
-      metrics->height = cbox.yMax - cbox.yMin;
-
-      metrics->horiBearingX = cbox.xMin;
-      metrics->horiBearingY = cbox.yMax;
-
-      /* copy the _unscaled_ advance width */
-      metrics->horiAdvance  = decoder.builder.advance.x;
-
-      /* make up vertical metrics */
-      metrics->vertBearingX = 0;
-      metrics->vertBearingY = 0;
-      metrics->vertAdvance  = 0;
-
-      glyph->root.format = ft_glyph_format_outline;
-
-      glyph->root.outline.flags &= ft_outline_owner;
-      
-      if ( size->root.metrics.y_ppem < 24 )
-        glyph->root.outline.flags |= ft_outline_high_precision;
-      
-      /*
-      glyph->root.outline.second_pass    = TRUE;
-      glyph->root.outline.high_precision = ( size->root.metrics.y_ppem < 24 );
-      glyph->root.outline.dropout_mode   = 2;
-      */
-
-      if ( hinting )
+      else
       {
-        /* adjust the advance width                  */
-        /* XXX : TODO : consider stem hints grid-fit */
-        metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,
-                                           glyph->x_scale );
-      }
-      else if ( (load_flags & FT_LOAD_NO_SCALE) == 0 )
-      {
-        /* scale the outline and the metrics */
-        T1_Int       n;
-        FT_Outline*  cur = &decoder.builder.base;
-        T1_Vector*   vec = cur->points;
-        T1_Fixed     x_scale = glyph->x_scale;
-        T1_Fixed     y_scale = glyph->y_scale;
-
-        /* First of all, scale the points */
-        for ( n = cur->n_points; n > 0; n--, vec++ )
+        FT_BBox           cbox;
+        FT_Glyph_Metrics* metrics = &glyph->root.metrics;
+  
+        FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+  
+        /* grid fit the bounding box if necessary */
+        if (hinting)
         {
-          vec->x = FT_MulFix( vec->x, x_scale );
-          vec->y = FT_MulFix( vec->y, y_scale );
+          cbox.xMin &= -64;
+          cbox.yMin &= -64;
+          cbox.xMax = ( cbox.xMax+63 ) & -64;
+          cbox.yMax = ( cbox.yMax+63 ) & -64;
         }
-
-        /* Then scale the metrics */
-        metrics->width  = FT_MulFix( metrics->width,  x_scale );
-        metrics->height = FT_MulFix( metrics->height, y_scale );
-
-        metrics->horiBearingX = FT_MulFix( metrics->horiBearingX, x_scale );
-        metrics->horiBearingY = FT_MulFix( metrics->horiBearingY, y_scale );
-        metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
-
-        metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
-        metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
-        metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  x_scale );
-
+  
+        metrics->width  = cbox.xMax - cbox.xMin;
+        metrics->height = cbox.yMax - cbox.yMin;
+  
+        metrics->horiBearingX = cbox.xMin;
+        metrics->horiBearingY = cbox.yMax;
+  
+        /* copy the _unscaled_ advance width */
+        metrics->horiAdvance  = decoder.builder.advance.x;
+  
+        /* make up vertical metrics */
+        metrics->vertBearingX = 0;
+        metrics->vertBearingY = 0;
+        metrics->vertAdvance  = 0;
+  
+        glyph->root.format = ft_glyph_format_outline;
+  
+        glyph->root.outline.flags &= ft_outline_owner;
+        
+        if ( size->root.metrics.y_ppem < 24 )
+          glyph->root.outline.flags |= ft_outline_high_precision;
+        
+        /*
+        glyph->root.outline.second_pass    = TRUE;
+        glyph->root.outline.high_precision = ( size->root.metrics.y_ppem < 24 );
+        glyph->root.outline.dropout_mode   = 2;
+        */
+  
+        if ( hinting )
+        {
+          /* adjust the advance width                  */
+          /* XXX : TODO : consider stem hints grid-fit */
+          metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,
+                                             glyph->x_scale );
+        }
+        else if ( (load_flags & FT_LOAD_NO_SCALE) == 0 )
+        {
+          /* scale the outline and the metrics */
+          T1_Int       n;
+          FT_Outline*  cur = &decoder.builder.base;
+          T1_Vector*   vec = cur->points;
+          T1_Fixed     x_scale = glyph->x_scale;
+          T1_Fixed     y_scale = glyph->y_scale;
+  
+          /* First of all, scale the points */
+          for ( n = cur->n_points; n > 0; n--, vec++ )
+          {
+            vec->x = FT_MulFix( vec->x, x_scale );
+            vec->y = FT_MulFix( vec->y, y_scale );
+          }
+  
+          /* Then scale the metrics */
+          metrics->width  = FT_MulFix( metrics->width,  x_scale );
+          metrics->height = FT_MulFix( metrics->height, y_scale );
+  
+          metrics->horiBearingX = FT_MulFix( metrics->horiBearingX, x_scale );
+          metrics->horiBearingY = FT_MulFix( metrics->horiBearingY, y_scale );
+          metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
+  
+          metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+          metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+          metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  x_scale );
+  
+        }
       }
     }
 
--- a/src/type1/t1gload.h
+++ b/src/type1/t1gload.h
@@ -159,6 +159,7 @@
 
     T1_Vector     left_bearing;
     T1_Vector     advance;
+    T1_Bool       no_recurse;
 
     T1_BBox       bbox;          /* bounding box */
     T1_Bool       path_begun;
--- a/src/type1z/t1gload.c
+++ b/src/type1z/t1gload.c
@@ -475,50 +475,90 @@
 
     n_base_points   = cur->n_points;
 
-    /* save the left bearing and width of the base character */
-    /* as they will be erase by the next load..              */
-    left_bearing = decoder->builder.left_bearing;
-    advance      = decoder->builder.advance;
+    if ( decoder->builder.no_recurse )
+    {
+      /* if we're trying to load a composite glyph, do not load the */
+      /* accent character and return the array of subglyphs..       */
+      FT_GlyphSlot  glyph = (FT_GlyphSlot)decoder->builder.glyph;
+      FT_SubGlyph*  subg;
 
-    decoder->builder.left_bearing.x = 0;
-    decoder->builder.left_bearing.y = 0;    
+      /* reallocate subglyph array if necessary */        
+      if (glyph->max_subglyphs < 2)
+      {
+        FT_Memory  memory = decoder->builder.face->root.memory;
+        
+        if ( REALLOC_ARRAY( glyph->subglyphs, glyph->max_subglyphs,
+                            2, FT_SubGlyph ) )
+          return error;
+          
+        glyph->max_subglyphs = 2;
+      }
 
-    /* Now load "achar" on top of */
-    /* the base outline           */
-    /*                            */ 
-    cur->n_points   = 0;
-    cur->n_contours = 0;
-    cur->points     = base->points   + base->n_points;
-    cur->tags      = base->tags    + base->n_points;
-    cur->contours   = base->contours + base->n_contours;
+      subg = glyph->subglyphs;
+      
+      /* subglyph 0 = base character */
+      subg->index = bchar_index;
+      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
+                    FT_SUBGLYPH_FLAG_USE_MY_METRICS;
+      subg->arg1  = 0;
+      subg->arg2  = 0;
+      subg++;
+      
+      /* subglyph 1 = accent character */
+      subg->index = achar_index;
+      subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
+      subg->arg1  = adx - asb;
+      subg->arg2  = ady;
 
-    error = T1_Parse_CharStrings( decoder,
-                                  type1->charstrings    [achar_index],
-                                  type1->charstrings_len[achar_index],
-                                  type1->num_subrs,
-                                  type1->subrs,
-                                  type1->subrs_len );
-    if (error) return error;
-
-    /* adjust contours in accented character outline */
-    if (decoder->builder.load_points)
+      /* set up remaining glyph fields */
+      glyph->num_subglyphs = 2;
+      glyph->format        = ft_glyph_format_composite;
+    }
+    else
     {
-      T1_Int  n;
-
-      for ( n = 0; n < cur->n_contours; n++ )
-        cur->contours[n] += n_base_points;
+      /* save the left bearing and width of the base character */
+      /* as they will be erase by the next load..              */
+      left_bearing = decoder->builder.left_bearing;
+      advance      = decoder->builder.advance;
+  
+      decoder->builder.left_bearing.x = 0;
+      decoder->builder.left_bearing.y = 0;    
+  
+      /* Now load "achar" on top of */
+      /* the base outline           */
+      /*                            */ 
+      cur->n_points   = 0;
+      cur->n_contours = 0;
+      cur->points     = base->points   + base->n_points;
+      cur->tags      = base->tags    + base->n_points;
+      cur->contours   = base->contours + base->n_contours;
+  
+      error = T1_Parse_CharStrings( decoder,
+                                    type1->charstrings    [achar_index],
+                                    type1->charstrings_len[achar_index],
+                                    type1->num_subrs,
+                                    type1->subrs,
+                                    type1->subrs_len );
+      if (error) return error;
+  
+      /* adjust contours in accented character outline */
+      if (decoder->builder.load_points)
+      {
+        T1_Int  n;
+  
+        for ( n = 0; n < cur->n_contours; n++ )
+          cur->contours[n] += n_base_points;
+      }
+  
+      /* restore the left side bearing and   */
+      /* advance width of the base character */
+      decoder->builder.left_bearing = left_bearing;
+      decoder->builder.advance      = advance;
+  
+      /* Finally, move the accent */
+      if (decoder->builder.load_points)
+        FT_Outline_Translate( cur, adx - asb, ady );
     }
-
-    /* restore the left side bearing and   */
-    /* advance width of the base character */
-    decoder->builder.left_bearing = left_bearing;
-    decoder->builder.advance      = advance;
-
-    /* Finally, move the accent */
-    if (decoder->builder.load_points)
-      FT_Outline_Translate( cur, adx - asb, ady );
-    
-    (void)asb;           /* ignore this parameter */
     return T1_Err_Ok;
   }
 
@@ -1213,6 +1253,9 @@
     T1_Bool         hinting;
     T1_Font*        type1 = &face->type1;
 
+    if (load_flags & FT_LOAD_NO_RECURSE)
+      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+
     glyph->x_scale = size->root.metrics.x_scale;
     glyph->y_scale = size->root.metrics.y_scale;
 
@@ -1228,6 +1271,8 @@
       T1_Init_Decoder( &decoder );
       T1_Init_Builder( &decoder.builder, face, size, glyph );
   
+      decoder.builder.no_recurse = !!(load_flags & FT_LOAD_NO_RECURSE);
+      
       /* now load the unscaled outline */
       error = T1_Parse_CharStrings( &decoder,
                                     type1->charstrings    [glyph_index],
@@ -1245,72 +1290,82 @@
     /* bearing the yMax..                                   */
     if (!error)
     {
-      FT_BBox           cbox;
-      FT_Glyph_Metrics* metrics = &glyph->root.metrics;
-
-      FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
-
-      /* grid fit the bounding box if necessary */
-      if (hinting)
+      /* for composite glyphs, return only the left side bearing and the */
+      /* advance width..                                                 */
+      if ( load_flags & FT_LOAD_NO_RECURSE )
       {
-        cbox.xMin &= -64;
-        cbox.yMin &= -64;
-        cbox.xMax = ( cbox.xMax+63 ) & -64;
-        cbox.yMax = ( cbox.yMax+63 ) & -64;
+        glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
+        glyph->root.metrics.horiAdvance  = decoder.builder.advance.x;
       }
-
-      metrics->width  = cbox.xMax - cbox.xMin;
-      metrics->height = cbox.yMax - cbox.yMin;
-
-      metrics->horiBearingX = cbox.xMin;
-      metrics->horiBearingY = cbox.yMax;
-
-      /* copy the _unscaled_ advance width */
-      metrics->horiAdvance  = decoder.builder.advance.x;
-
-      /* make up vertical metrics */
-      metrics->vertBearingX = 0;
-      metrics->vertBearingY = 0;
-      metrics->vertAdvance  = 0;
-
-      glyph->root.format = ft_glyph_format_outline;
-
-      glyph->root.outline.flags &= ft_outline_owner;
-      if ( size->root.metrics.y_ppem < 24 )
-        glyph->root.outline.flags |= ft_outline_high_precision;
-      /*
-      glyph->root.outline.second_pass    = TRUE;
-      glyph->root.outline.high_precision = ( size->root.metrics.y_ppem < 24 );
-      glyph->root.outline.dropout_mode   = 2;
-      */
-
-      if ( (load_flags & FT_LOAD_NO_SCALE) == 0 )
+      else
       {
-        /* scale the outline and the metrics */
-        T1_Int       n;
-        FT_Outline*  cur = &decoder.builder.base;
-        T1_Vector*   vec = cur->points;
-        T1_Fixed     x_scale = glyph->x_scale;
-        T1_Fixed     y_scale = glyph->y_scale;
-
-        /* First of all, scale the points */
-        for ( n = cur->n_points; n > 0; n--, vec++ )
+        FT_BBox           cbox;
+        FT_Glyph_Metrics* metrics = &glyph->root.metrics;
+  
+        FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
+  
+        /* grid fit the bounding box if necessary */
+        if (hinting)
         {
-          vec->x = FT_MulFix( vec->x, x_scale );
-          vec->y = FT_MulFix( vec->y, y_scale );
+          cbox.xMin &= -64;
+          cbox.yMin &= -64;
+          cbox.xMax = ( cbox.xMax+63 ) & -64;
+          cbox.yMax = ( cbox.yMax+63 ) & -64;
         }
-
-        /* Then scale the metrics */
-        metrics->width  = FT_MulFix( metrics->width,  x_scale );
-        metrics->height = FT_MulFix( metrics->height, y_scale );
-
-        metrics->horiBearingX = FT_MulFix( metrics->horiBearingX, x_scale );
-        metrics->horiBearingY = FT_MulFix( metrics->horiBearingY, y_scale );
-        metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
-
-        metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
-        metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
-        metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  x_scale );
+  
+        metrics->width  = cbox.xMax - cbox.xMin;
+        metrics->height = cbox.yMax - cbox.yMin;
+  
+        metrics->horiBearingX = cbox.xMin;
+        metrics->horiBearingY = cbox.yMax;
+  
+        /* copy the _unscaled_ advance width */
+        metrics->horiAdvance  = decoder.builder.advance.x;
+  
+        /* make up vertical metrics */
+        metrics->vertBearingX = 0;
+        metrics->vertBearingY = 0;
+        metrics->vertAdvance  = 0;
+  
+        glyph->root.format = ft_glyph_format_outline;
+  
+        glyph->root.outline.flags &= ft_outline_owner;
+        if ( size->root.metrics.y_ppem < 24 )
+          glyph->root.outline.flags |= ft_outline_high_precision;
+        /*
+        glyph->root.outline.second_pass    = TRUE;
+        glyph->root.outline.high_precision = ( size->root.metrics.y_ppem < 24 );
+        glyph->root.outline.dropout_mode   = 2;
+        */
+  
+        if ( (load_flags & FT_LOAD_NO_SCALE) == 0 )
+        {
+          /* scale the outline and the metrics */
+          T1_Int       n;
+          FT_Outline*  cur = &decoder.builder.base;
+          T1_Vector*   vec = cur->points;
+          T1_Fixed     x_scale = glyph->x_scale;
+          T1_Fixed     y_scale = glyph->y_scale;
+  
+          /* First of all, scale the points */
+          for ( n = cur->n_points; n > 0; n--, vec++ )
+          {
+            vec->x = FT_MulFix( vec->x, x_scale );
+            vec->y = FT_MulFix( vec->y, y_scale );
+          }
+  
+          /* Then scale the metrics */
+          metrics->width  = FT_MulFix( metrics->width,  x_scale );
+          metrics->height = FT_MulFix( metrics->height, y_scale );
+  
+          metrics->horiBearingX = FT_MulFix( metrics->horiBearingX, x_scale );
+          metrics->horiBearingY = FT_MulFix( metrics->horiBearingY, y_scale );
+          metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
+  
+          metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
+          metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
+          metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  x_scale );
+        }
       }
     }
     return error;
--- a/src/type1z/t1gload.h
+++ b/src/type1z/t1gload.h
@@ -107,6 +107,7 @@
     T1_BBox       bbox;          /* bounding box */
     T1_Bool       path_begun;
     T1_Bool       load_points;
+    T1_Bool       no_recurse;
     
     T1_Error      error;         /* only used for memory errors */
     T1_Bool       metrics_only;