shithub: freetype+ttf2subf

Download patch

ref: bcc438b15ef0b22055ae6f4ed55e0981794f483a
parent: 4c6234d963bb7543503eee63dcf32aa35dbf9c91
author: Wu, Chia-I (吳佳一) <[email protected]>
date: Mon Jan 23 09:12:40 EST 2006

* include/freetype/freetype.h (FT_Select_Size): Rename the second
argument from `idx' to `strike_index'.
(FT_Size_Request_Type): Add FT_SIZE_REQUEST_TYPE_MAX to the end of
this enum.

* include/freetype/internal/ftobjs.h (FT_REQUEST_WIDTH,
FT_REQUEST_HEIGHT): New macros to get the width and height of a
request, in fractional pixels.

* include/freetype/internal/ftobjs.h (FT_Select_Metrics,
FT_Request_Metrics), src/base/ftobjs.c (FT_Select_Metrics,
FT_Request_Metrics): New base functions to set the font metrics.  They
were part of FT_Select_Size/FT_Request_Size and are made independent
functions so that metrics are not set again and again.

* src/base/ftobjs.c (FT_Select_Size, FT_Request_Size): Metrics are set
only when driver's size_select/size_request is NULL.  That is, drivers
should set the metrics themselves.
(FT_Match_Size): Round before matching.  This was what we did and it
does cause some problems without rounding.

* src/cff/cffobjs.c (cff_size_select), src/truetype/ttdriver.c
(tt_size_select): Set the font metrics.
s/index/strike_index/.
The scaled metrics are always preferred over strikes' metrics, even
when some strike is selected.  This is done because the strikes'
metrics are not reliable, e.g., the sign of the descender is wrong for
some fonts.

* src/cff/cffobjs.c (cff_size_request), src/truetype/ttdriver.c
(tt_size_request): Set the font metrics.
Call cff_size_select/tt_size_select when some strike is matched.

* src/bdf/bdfdrivr.c, src/cff/cffobjs.c, src/cid/cidobjs.c,
src/pcf/pcfdrivr.c, src/truetype/ttdriver.c, src/type1/t1objs.c,
src/type1/t1objs.h, src/type42/t42objs.c, src/winfonts/winfnt.c:
Set the font metrics.
s/index/strike_index/.

* src/tools/test_afm.c, src/psaux/psconv.c: Older versions of these
files were committed.  Just a catch-up.
(PS_Conv_ToFixed): Remove the `goto'.
(PS_Conv_ASCIIHexDecode, PS_Conv_EexecDecode): Speed up a little.

* src/sfnt/ttsbit.c (tt_face_load_sbit_strikes,
tt_face_load_strike_metrics), src/sfnt/ttsbit0.c
(tt_face_load_sbit_strikes, tt_face_load_strike_metrics): The
advertised metrics in `available_sizes' are different from those
actually used.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,57 @@
 2006-01-23  Chia-I Wu  <[email protected]>
 
+	* include/freetype/freetype.h (FT_Select_Size): Rename the second
+	argument from `idx' to `strike_index'.
+	(FT_Size_Request_Type): Add FT_SIZE_REQUEST_TYPE_MAX to the end of
+	this enum.
+
+	* include/freetype/internal/ftobjs.h (FT_REQUEST_WIDTH,
+	FT_REQUEST_HEIGHT): New macros to get the width and height of a
+	request, in fractional pixels.
+
+	* include/freetype/internal/ftobjs.h (FT_Select_Metrics,
+	FT_Request_Metrics), src/base/ftobjs.c (FT_Select_Metrics,
+	FT_Request_Metrics): New base functions to set the font metrics.  They
+	were part of FT_Select_Size/FT_Request_Size and are made independent
+	functions so that metrics are not set again and again.
+
+	* src/base/ftobjs.c (FT_Select_Size, FT_Request_Size): Metrics are set
+	only when driver's size_select/size_request is NULL.  That is, drivers
+	should set the metrics themselves.
+	(FT_Match_Size): Round before matching.  This was what we did and it
+	does cause some problems without rounding.
+
+	* src/cff/cffobjs.c (cff_size_select), src/truetype/ttdriver.c
+	(tt_size_select): Set the font metrics.
+	s/index/strike_index/.
+	The scaled metrics are always preferred over strikes' metrics, even
+	when some strike is selected.  This is done because the strikes'
+	metrics are not reliable, e.g., the sign of the descender is wrong for
+	some fonts.
+
+	* src/cff/cffobjs.c (cff_size_request), src/truetype/ttdriver.c
+	(tt_size_request): Set the font metrics.
+	Call cff_size_select/tt_size_select when some strike is matched.
+
+	* src/bdf/bdfdrivr.c, src/cff/cffobjs.c, src/cid/cidobjs.c,
+	src/pcf/pcfdrivr.c, src/truetype/ttdriver.c, src/type1/t1objs.c,
+	src/type1/t1objs.h, src/type42/t42objs.c, src/winfonts/winfnt.c:
+	Set the font metrics.
+	s/index/strike_index/.
+
+	* src/tools/test_afm.c, src/psaux/psconv.c: Older versions of these
+	files were committed.  Just a catch-up.
+	(PS_Conv_ToFixed): Remove the `goto'.
+	(PS_Conv_ASCIIHexDecode, PS_Conv_EexecDecode): Speed up a little.
+
+	* src/sfnt/ttsbit.c (tt_face_load_sbit_strikes,
+	tt_face_load_strike_metrics), src/sfnt/ttsbit0.c
+	(tt_face_load_sbit_strikes, tt_face_load_strike_metrics): The
+	advertised metrics in `available_sizes' are different from those
+	actually used.
+
+2006-01-23  Chia-I Wu  <[email protected]>
+
 	* src/psaux/psaux.c src/psaux/psauxmod.c src/type1/t1driver.c: Make
 	AFM parser optional, controlled by `T1_CONFIG_OPTION_NO_AFM'.
 
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -1975,11 +1975,11 @@
   /*    Select a bitmap strike.                                            */
   /*                                                                       */
   /* <InOut>                                                               */
-  /*    face :: A handle to a target face object.                          */
+  /*    face         :: A handle to a target face object.                  */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    idx  :: The index of the bitmap strike in the `available_sizes'    */
-  /*            field of @FT_FaceRec structure.                            */
+  /*    strike_index :: The index of the bitmap strike in the              */
+  /*                    `available_sizes' field of @FT_FaceRec structure.  */
   /*                                                                       */
   /* <Return>                                                              */
   /*    FreeType error code.  0 means success.                             */
@@ -1986,7 +1986,7 @@
   /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Select_Size( FT_Face  face,
-                  FT_Int   idx );
+                  FT_Int   strike_index );
 
 
   /*************************************************************************/
@@ -2032,7 +2032,9 @@
     FT_SIZE_REQUEST_TYPE_NOMINAL,
     FT_SIZE_REQUEST_TYPE_REAL_DIM,
     FT_SIZE_REQUEST_TYPE_BBOX,
-    FT_SIZE_REQUEST_TYPE_CELL
+    FT_SIZE_REQUEST_TYPE_CELL,
+
+    FT_SIZE_REQUEST_TYPE_MAX
 
   } FT_Size_Request_Type;
 
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -451,6 +451,28 @@
 
  /* */
 
+#define FT_REQUEST_WIDTH( req )                                          \
+    ( ( req )->horiResolution                                            \
+        ? (FT_Pos)( ( req )->width * ( req )->horiResolution + 36 ) / 72 \
+        : ( req )->width )
+
+#define FT_REQUEST_HEIGHT( req )                                          \
+    ( ( req )->vertResolution                                             \
+        ? (FT_Pos)( ( req )->height * ( req )->vertResolution + 36 ) / 72 \
+        : ( req )->height )
+
+  /* set the metrics according to a bitmap strike */
+  FT_BASE( void )
+  FT_Select_Metrics( FT_Face   face,
+                     FT_ULong  strike_index );
+
+
+  /* set the metrics according to a size request */
+  FT_BASE( void )
+  FT_Request_Metrics( FT_Face          face,
+                      FT_Size_Request  req );
+
+
   /*
    * Match a size request against `available_sizes'.
    */
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -2006,28 +2006,26 @@
     if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
       return FT_Err_Unimplemented_Feature;
 
-    if ( req->horiResolution )
-      w = ( req->width * req->horiResolution + 36 ) / 72;
-    else
-      w = req->width;
+    w = FT_REQUEST_WIDTH( req );
+    h = FT_REQUEST_HEIGHT( req );
 
-    if ( req->vertResolution )
-      h = ( req->height * req->vertResolution + 36 ) / 72;
-    else
-      h = req->height;
-
     if ( req->width && !req->height )
       h = w;
     else if ( !req->width && req->height )
       w = h;
 
+    w = FT_PIX_ROUND( w );
+    h = FT_PIX_ROUND( h );
+
     for ( i = 0; i < face->num_fixed_sizes; i++ )
     {
-      if ( h != face->available_sizes[i].y_ppem )
+      FT_Bitmap_Size*  bsize = face->available_sizes + i;
+
+
+      if ( h != FT_PIX_ROUND( bsize->y_ppem ) )
         continue;
 
-      if ( w == face->available_sizes[i].x_ppem ||
-           ignore_width                         )
+      if ( w == FT_PIX_ROUND( bsize->x_ppem ) || ignore_width )
       {
         if ( index )
           *index = (FT_ULong)i;
@@ -2076,28 +2074,17 @@
   }
 
 
-  /* documentation is in freetype.h */
-
-  FT_EXPORT_DEF( FT_Error )
-  FT_Select_Size( FT_Face  face,
-                  FT_Int   index )
+  FT_BASE_DEF( void )
+  FT_Select_Metrics( FT_Face   face,
+                     FT_ULong  strike_index )
   {
-    FT_Driver_Class   clazz;
     FT_Size_Metrics*  metrics;
     FT_Bitmap_Size*   bsize;
 
 
-    if ( !face || !FT_HAS_FIXED_SIZES( face ) )
-      return FT_Err_Invalid_Face_Handle;
-
-    if ( index < 0 || index >= face->num_fixed_sizes )
-      return FT_Err_Invalid_Argument;
-
-    clazz   = face->driver->clazz;
     metrics = &face->size->metrics;
+    bsize   = face->available_sizes + strike_index;
 
-    bsize   = face->available_sizes + index;
-
     metrics->x_ppem = ( bsize->x_ppem + 32 ) >> 6;
     metrics->y_ppem = ( bsize->y_ppem + 32 ) >> 6;
 
@@ -2119,32 +2106,17 @@
       metrics->height      = bsize->height << 6;
       metrics->max_advance = bsize->x_ppem;
     }
-
-    if ( clazz->select_size )
-      return clazz->select_size( face->size, (FT_ULong)index );
-    else
-      return FT_Err_Ok;
   }
 
 
-  /* documentation is in freetype.h */
-
-  FT_EXPORT_DEF( FT_Error )
-  FT_Request_Size( FT_Face          face,
-                   FT_Size_Request  req )
+  FT_BASE_DEF( void )
+  FT_Request_Metrics( FT_Face          face,
+                      FT_Size_Request  req )
   {
     FT_Driver_Class   clazz;
     FT_Size_Metrics*  metrics;
-    FT_Error          error;
-    FT_Bool           bitmap_only = 0;
 
 
-    if ( !face )
-      return FT_Err_Invalid_Face_Handle;
-
-    if ( !req || req->width < 0 || req->height < 0 )
-      return FT_Err_Invalid_Argument;
-
     clazz   = face->driver->clazz;
     metrics = &face->size->metrics;
 
@@ -2174,10 +2146,12 @@
         break;
 
       default:
-        return FT_Err_Unimplemented_Feature;
+        /* this never happens */
+        return;
         break;
       }
 
+      /* to be on the safe side */
       if ( w < 0 )
         w = -w;
 
@@ -2184,16 +2158,9 @@
       if ( h < 0 )
         h = -h;
 
-      if ( req->horiResolution )
-        scaled_w = ( req->width * req->horiResolution + 36 ) / 72;
-      else
-        scaled_w = req->width;
+      scaled_w = FT_REQUEST_WIDTH( req );
+      scaled_h = FT_REQUEST_HEIGHT( req );
 
-      if ( req->vertResolution )
-        scaled_h = ( req->height * req->vertResolution + 36 ) / 72;
-      else
-        scaled_h = req->height;
-
       /* determine scales */
       if ( req->width )
       {
@@ -2223,7 +2190,7 @@
         scaled_w = FT_MulDiv( scaled_h, w, h );
       }
 
-      /* calculate ppem */
+      /* calculate the ppems */
       if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
       {
         scaled_w = FT_MulFix( face->units_per_EM, metrics->x_scale );
@@ -2234,8 +2201,6 @@
       metrics->y_ppem = ( scaled_h + 32 ) >> 6;
 
       ft_recompute_scaled_metrics( face, metrics );
-
-      error = FT_Err_Ok;
     }
     else
     {
@@ -2242,15 +2207,58 @@
       FT_ZERO( metrics );
       metrics->x_scale = 1L << 22;
       metrics->y_scale = 1L << 22;
+    }
+  }
 
-      if ( FT_HAS_FIXED_SIZES( face ) )
-        bitmap_only = 1;
 
-      error = FT_Err_Invalid_Pixel_Size;
-    }
+  /* documentation is in freetype.h */
 
+  FT_EXPORT_DEF( FT_Error )
+  FT_Select_Size( FT_Face  face,
+                  FT_Int   strike_index )
+  {
+    FT_Driver_Class   clazz;
+
+
+    if ( !face || !FT_HAS_FIXED_SIZES( face ) )
+      return FT_Err_Invalid_Face_Handle;
+
+    if ( strike_index < 0 || strike_index >= face->num_fixed_sizes )
+      return FT_Err_Invalid_Argument;
+
+    clazz = face->driver->clazz;
+
+    if ( clazz->select_size )
+      return clazz->select_size( face->size, (FT_ULong)strike_index );
+
+    FT_Select_Metrics( face, (FT_ULong)strike_index );
+
+    return FT_Err_Ok;
+  }
+
+
+  /* documentation is in freetype.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Request_Size( FT_Face          face,
+                   FT_Size_Request  req )
+  {
+    FT_Driver_Class   clazz;
+    FT_ULong          strike_index;
+
+
+    if ( !face )
+      return FT_Err_Invalid_Face_Handle;
+
+    if ( !req || req->width < 0 || req->height < 0 ||
+         req->type >= FT_SIZE_REQUEST_TYPE_MAX )
+      return FT_Err_Invalid_Argument;
+
+    clazz = face->driver->clazz;
+
     if ( clazz->request_size )
-      error = clazz->request_size( face->size, req );
+      return clazz->request_size( face->size, req );
+
     /*
      * The reason that a driver doesn't have `request_size' defined is
      * either that the scaling here suffices or that the supported formats
@@ -2258,20 +2266,23 @@
      *
      * In the latter case, a simple size matching is done.
      */
-    else if ( bitmap_only )
+    if ( !FT_IS_SCALABLE( face ) && FT_HAS_FIXED_SIZES( face ) )
     {
-      FT_ULong  index;
+      FT_Error  error;
 
 
-      if ( !FT_Match_Size( face, req, 0, &index ) )
-      {
-        FT_TRACE3(( "FT_Request_Size: bitmap strike %lu matched\n", index ));
+      error = FT_Match_Size( face, req, 0, &strike_index );
+      if ( error )
+        return error;
 
-        error = FT_Select_Size( face, index );
-      }
+      FT_TRACE3(( "FT_Request_Size: bitmap strike %lu matched\n", strike_index ));
+
+      return FT_Select_Size( face, (FT_Int)strike_index );
     }
 
-    return error;
+    FT_Request_Metrics( face, req );
+
+    return FT_Err_Ok;
   }
 
 
--- a/src/bdf/bdfdrivr.c
+++ b/src/bdf/bdfdrivr.c
@@ -583,17 +583,15 @@
 
   FT_CALLBACK_DEF( FT_Error )
   BDF_Size_Select( FT_Size   size,
-                   FT_ULong  index )
+                   FT_ULong  strike_index )
   {
     bdf_font_t*  bdffont = ( (BDF_Face)size->face )->bdffont;
 
-    FT_UNUSED( index );
 
+    FT_Select_Metrics( size->face, strike_index );
 
     size->metrics.ascender    = bdffont->font_ascent << 6;
     size->metrics.descender   = -bdffont->font_descent << 6;
-    size->metrics.height      = ( bdffont->font_ascent +
-                                  bdffont->font_descent ) << 6;
     size->metrics.max_advance = bdffont->bbx.width << 6;
 
     return BDF_Err_Ok;
@@ -611,11 +609,7 @@
     FT_Long          height;
 
 
-    if ( req->vertResolution )
-      height = ( req->height * req->vertResolution + 36 ) / 72;
-    else
-      height = req->height;
-
+    height = FT_REQUEST_HEIGHT( req );
     height = ( height + 32 ) >> 6;
 
     switch ( req->type )
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -165,39 +165,20 @@
   }
 
 
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
   FT_LOCAL_DEF( FT_Error )
-  cff_size_request( FT_Size          size,
-                    FT_Size_Request  req )
+  cff_size_select( FT_Size   size,
+                   FT_ULong  strike_index )
   {
     CFF_Size           cffsize = (CFF_Size)size;
     PSH_Globals_Funcs  funcs;
 
-#ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
-    FT_UNUSED( req );
-    
-#else
+    cffsize->strike_index = strike_index;
 
-    if ( FT_HAS_FIXED_SIZES( size->face ) )
-    {
-      CFF_Face          cffface = (CFF_Face)size->face;
-      SFNT_Service      sfnt    = cffface->sfnt;
-      FT_Size_Metrics*  metrics = &size->metrics;
-      FT_ULong          index;
-      FT_Error          error;
+    FT_Select_Metrics( size->face, strike_index );
 
-
-      if ( !( error = sfnt->set_sbit_strike(
-                              cffface, req, &index ) )    &&
-           !( error = sfnt->load_strike_metrics(
-                              cffface, index, metrics ) ) )
-        cffsize->strike_index = index;
-      else
-        cffsize->strike_index = 0xFFFFFFFFUL;
-    }
-
-#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
-
     funcs = cff_size_get_globals_funcs( cffsize );
 
     if ( funcs )
@@ -209,21 +190,35 @@
     return CFF_Err_Ok;
   }
 
+#endif
 
-#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
   FT_LOCAL_DEF( FT_Error )
-  cff_size_select( FT_Size   size,
-                   FT_ULong  index )
+  cff_size_request( FT_Size          size,
+                    FT_Size_Request  req )
   {
-    CFF_Face           cffface = (CFF_Face)size->face;
     CFF_Size           cffsize = (CFF_Size)size;
-    FT_Size_Metrics*   metrics = &size->metrics;
-    SFNT_Interface*    sfnt    = cffface->sfnt;
-    FT_Error           error;
     PSH_Globals_Funcs  funcs;
 
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
+    if ( FT_HAS_FIXED_SIZES( size->face ) )
+    {
+      CFF_Face      cffface = (CFF_Face)size->face;
+      SFNT_Service  sfnt    = cffface->sfnt;
+      FT_ULong      index;
+
+
+      if ( sfnt->set_sbit_strike( cffface, req, &index ) )
+        cffsize->strike_index = 0xFFFFFFFFUL;
+      else
+        return cff_size_select( size, index );
+    }
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+    FT_Request_Metrics( size->face, req );
+
     funcs = cff_size_get_globals_funcs( cffsize );
 
     if ( funcs )
@@ -232,16 +227,8 @@
                         size->metrics.y_scale,
                         0, 0 );
 
-    error = sfnt->load_strike_metrics( cffface, index, metrics );
-    if ( error )
-      cffsize->strike_index = 0xFFFFFFFFUL;
-    else
-      cffsize->strike_index = index;
-
-    return error;
+    return CFF_Err_Ok;
   }
-
-#endif
 
 
   /*************************************************************************/
--- a/src/cid/cidobjs.c
+++ b/src/cid/cidobjs.c
@@ -158,8 +158,8 @@
   {
     PSH_Globals_Funcs  funcs;
 
-    FT_UNUSED( req );
 
+    FT_Request_Metrics( size->face, req );
 
     funcs = cid_size_get_globals_funcs( (CID_Size)size );
 
--- a/src/pcf/pcfdrivr.c
+++ b/src/pcf/pcfdrivr.c
@@ -364,22 +364,16 @@
 
   FT_CALLBACK_DEF( FT_Error )
   PCF_Size_Select( FT_Size   size,
-                   FT_ULong  index )
+                   FT_ULong  strike_index )
   {
-    PCF_Face  face  = (PCF_Face)size->face;
+    PCF_Accel  accel = &( (PCF_Face)size->face )->accel;
 
-    FT_UNUSED( index );
 
+    FT_Select_Metrics( size->face, strike_index );
 
-    size->metrics.ascender    = face->accel.fontAscent << 6;
-    size->metrics.descender   = -face->accel.fontDescent << 6;
-#if 0
-    size->metrics.height      = face->accel.maxbounds.ascent << 6;
-#else
-    size->metrics.height      = size->metrics.ascender -
-                                size->metrics.descender;
-#endif
-    size->metrics.max_advance = face->accel.maxbounds.characterWidth << 6;
+    size->metrics.ascender    =  accel->fontAscent << 6;
+    size->metrics.descender   = -accel->fontDescent << 6;
+    size->metrics.max_advance =  accel->maxbounds.characterWidth << 6;
 
     return PCF_Err_Ok;
   }
@@ -389,17 +383,13 @@
   PCF_Size_Request( FT_Size          size,
                     FT_Size_Request  req )
   {
-    PCF_Face         face    = (PCF_Face)size->face;
-    FT_Bitmap_Size*  bsize   = size->face->available_sizes;
-    FT_Error         error   = PCF_Err_Invalid_Pixel_Size;
+    PCF_Face         face  = (PCF_Face)size->face;
+    FT_Bitmap_Size*  bsize = size->face->available_sizes;
+    FT_Error         error = PCF_Err_Invalid_Pixel_Size;
     FT_Long          height;
 
 
-    if ( req->vertResolution )
-      height = ( req->height * req->vertResolution + 36 ) / 72;
-    else
-      height = req->height;
-
+    height = FT_REQUEST_HEIGHT( req );
     height = ( height + 32 ) >> 6;
 
     switch ( req->type )
--- a/src/pcf/pcfread.c
+++ b/src/pcf/pcfread.c
@@ -1101,6 +1101,9 @@
 
         FT_MEM_ZERO( bsize, sizeof ( FT_Bitmap_Size ) );
 
+#if 0
+        bsize->height = face->accel.maxbounds.ascent << 6;
+#endif
         bsize->height = (FT_Short)( face->accel.fontAscent +
                                     face->accel.fontDescent );
 
--- a/src/psaux/psconv.c
+++ b/src/psaux/psconv.c
@@ -164,17 +164,12 @@
     }
 
     if ( *p != '.' )
-    {
       integral = PS_Conv_ToInt( &p, limit ) << 16;
-
-      if ( p == limit )
-        goto Exit;
-    }
     else
       integral = 0;
 
     /* read the decimal part */
-    if ( *p == '.' )
+    if ( p < limit && *p == '.' )
     {
       p++;
 
@@ -206,7 +201,6 @@
       power_ten += PS_Conv_ToInt( &p, limit );
     }
 
-  Exit:
     while ( power_ten > 0 )
     {
       integral *= 10;
@@ -339,7 +333,8 @@
     FT_UInt   r = 0;
 
 
-    for ( p = *cursor; r < 2 * n && p < limit; p++ )
+    n *= 2;
+    for ( p = *cursor; r < n && p < limit; p++ )
     {
       char  c;
 
@@ -376,20 +371,22 @@
   		       FT_UInt     n,
   		       FT_UShort*  seed )
   {
-    FT_Byte*  p;
-    FT_UInt   r;
+    FT_Byte*   p;
+    FT_UInt    r;
+    FT_UShort  s = *seed;
 
 
     for ( r = 0, p = *cursor; r < n && p < limit; r++, p++ )
     {
-      FT_Byte  b = ( *p ^ ( *seed >> 8 ) );
+      FT_Byte  b = ( *p ^ ( s >> 8 ) );
 
 
-      *seed = (FT_UShort)( ( *p + *seed ) * 52845U + 22719 );
+      s = (FT_UShort)( ( *p + s ) * 52845U + 22719 );
       *buffer++ = b;
     }
 
     *cursor = p;
+    *seed   = s;
 
     return r;
   }
--- a/src/sfnt/ttsbit.c
+++ b/src/sfnt/ttsbit.c
@@ -599,18 +599,17 @@
         FT_Bitmap_Size*  bsize  = root->available_sizes + n;
         TT_SBit_Strike   strike = face->sbit_strikes + n;
         FT_UShort        fupem  = face->header.Units_Per_EM;
-        FT_Short         height = (FT_Short)( face->horizontal.Ascender -
-                                              face->horizontal.Descender +
-                                              face->horizontal.Line_Gap );
         FT_Short         avg    = face->os2.xAvgCharWidth;
 
 
-        /* assume 72dpi */
-        bsize->height =
-          (FT_Short)( ( height * strike->y_ppem + fupem / 2 ) / fupem );
+        /* XXX: Is this correct? */
+        bsize->height = strike->hori.ascender - strike->hori.descender;
         bsize->width  =
           (FT_Short)( ( avg * strike->y_ppem + fupem / 2 ) / fupem );
+
+        /* assume 72dpi */
         bsize->size   = strike->y_ppem << 6;
+
         bsize->x_ppem = strike->x_ppem << 6;
         bsize->y_ppem = strike->y_ppem << 6;
       }
@@ -692,6 +691,8 @@
 
     strike = face->sbit_strikes + strike_index;
 
+    metrics->x_ppem = strike->x_ppem;
+    metrics->y_ppem = strike->y_ppem;
 
     metrics->ascender  = strike->hori.ascender << 6;
     metrics->descender = strike->hori.descender << 6;
@@ -701,7 +702,6 @@
                              strike->hori.max_width      +
                              strike->hori.min_advance_SB ) << 6;
 
-    /* XXX: Is this correct? */
     metrics->height = metrics->ascender - metrics->descender;
 
     return SFNT_Err_Ok;
--- a/src/sfnt/ttsbit0.c
+++ b/src/sfnt/ttsbit0.c
@@ -148,12 +148,8 @@
      *  depths in the FT_Bitmap_Size record.  This is a design error.
      */
     {
-      FT_Memory  memory  = face->root.stream->memory;
-      FT_UInt    em_size = (FT_UInt) face->header.Units_Per_EM;
-      FT_Short   height  = (FT_Short)( face->horizontal.Ascender -
-                                       face->horizontal.Descender +
-                                       face->horizontal.Line_Gap );
-
+      FT_Memory  memory   = face->root.stream->memory;
+      FT_UInt    em_size  = (FT_UInt)face->header.Units_Per_EM;
       FT_Short   avgwidth = face->os2.xAvgCharWidth;
 
 
@@ -164,16 +160,22 @@
       {
         FT_Bitmap_Size*  bsize = face->root.available_sizes + nn;
         FT_UInt          x_ppem, y_ppem;
+        FT_Char          ascender, descender;
 
 
-        x_ppem = p[44];
-        y_ppem = p[45];
+        ascender  = (FT_Char)p[16];
+        descender = (FT_Char)p[17];
+        x_ppem    = p[44];
+        y_ppem    = p[45];
 
         bsize->x_ppem = (FT_Pos)(x_ppem << 6);
         bsize->y_ppem = (FT_Pos)(y_ppem << 6);
 
-        bsize->height = (FT_Short)( height*y_ppem   + em_size / 2 ) / em_size;
-        bsize->width  = (FT_Short)( avgwidth*y_ppem + em_size / 2 ) / em_size;
+        /* XXX: Is this correct? */
+        bsize->height = ascender - descender;
+        bsize->width  = (FT_Short)( avgwidth * y_ppem + em_size / 2 ) / em_size;
+
+        /* assume 72dpi */
         bsize->size   = bsize->y_ppem;
 
         p += 48;
@@ -219,18 +221,20 @@
                                FT_ULong          strike_index,
                                FT_Size_Metrics*  metrics )
   {
-    FT_Byte*  strike;
+    FT_Bitmap_Size*  bsize;
+    FT_Byte*         strike;
     
-#ifdef FT_OPTIMIZE_MEMORY
+
     if ( strike_index >= (FT_ULong)face->sbit_num_strikes )
       return SFNT_Err_Invalid_Argument;
-#else
-    if ( strike_index >= (FT_ULong)face->num_sbit_strikes )
-      return SFNT_Err_Invalid_Argument;
-#endif
 
+    bsize  = ( (FT_Face)face )->available_sizes + strike_index;
     strike = face->sbit_table + 8 + strike_index * 48;
 
+    metrics->x_ppem = bsize->x_ppem >> 6;
+    metrics->y_ppem = bsize->y_ppem >> 6;
+    metrics->height = bsize->height << 6;
+
     metrics->ascender  = (FT_Char)strike[16] << 6;  /* hori.ascender  */
     metrics->descender = (FT_Char)strike[17] << 6;  /* hori.descender */
 
@@ -239,9 +243,6 @@
                                       strike[18] + /* max_width      */
                              (FT_Char)strike[23]   /* min_advance_SB */
                                                  ) << 6;
-
-    /* XXX: Is this correct? */
-    metrics->height = metrics->ascender - metrics->descender;
 
     return SFNT_Err_Ok;
   }
--- a/src/tools/test_afm.c
+++ b/src/tools/test_afm.c
@@ -1,3 +1,7 @@
+/*
+ * gcc -I../../include -o test_afm test_afm.c \
+ *     -L../../objs/.libs -lfreetype -lz -static
+ */
 #include <ft2build.h>
 #include FT_FREETYPE_H
 #include FT_INTERNAL_STREAM_H
@@ -31,7 +35,7 @@
 
     printf( "\n" );
 
-    if ( fi->NumTrackKern )
+    if ( fi->NumKernPair )
       printf( "There are %d kerning pairs:\n",
               fi->NumKernPair );
     else
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -134,71 +134,77 @@
   /*************************************************************************/
 
 
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
   static FT_Error
-  tt_size_request( FT_Size          size,
-                   FT_Size_Request  req )
+  tt_size_select( FT_Size   size,
+                  FT_ULong  strike_index )
   {
     TT_Face   ttface = (TT_Face)size->face;
     TT_Size   ttsize = (TT_Size)size;
     FT_Error  error  = TT_Err_Ok;
 
-#ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
-    FT_UNUSED( req );
+    ttsize->strike_index = strike_index;
 
-#else
+    if ( FT_IS_SCALABLE( size->face ) )
+    {
+      /* use the scaled metrics, even when tt_size_reset fails */
+      FT_Select_Metrics( size->face, strike_index );
 
-    if ( FT_HAS_FIXED_SIZES( size->face ) )
+      tt_size_reset( ttsize );
+    }
+    else
     {
       SFNT_Service      sfnt    = ttface->sfnt;
       FT_Size_Metrics*  metrics = &size->metrics;
-      FT_ULong          index;
 
 
-      if ( !( error = sfnt->set_sbit_strike(
-                              ttface, req, &index ) )    &&
-           !( error = sfnt->load_strike_metrics(
-                              ttface, index, metrics ) ) )
-        ttsize->strike_index = index;
-      else
+      error = sfnt->load_strike_metrics( ttface, strike_index, metrics );
+      if ( error )
         ttsize->strike_index = 0xFFFFFFFFUL;
     }
 
-#endif /*  TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
-
-    if ( FT_IS_SCALABLE( size->face ) )
-      error = tt_size_reset( ttsize );
-
     return error;
   }
 
+#endif
 
-#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
   static FT_Error
-  tt_size_select( FT_Size   size,
-                  FT_ULong  index )
+  tt_size_request( FT_Size          size,
+                   FT_Size_Request  req )
   {
-    TT_Face           ttface  = (TT_Face)size->face;
-    TT_Size           ttsize  = (TT_Size)size;
-    FT_Size_Metrics*  metrics = &size->metrics;
-    SFNT_Service      sfnt    = ttface->sfnt;
-    FT_Error          error;
+    TT_Face   ttface = (TT_Face)size->face;
+    TT_Size   ttsize = (TT_Size)size;
+    FT_Error  error  = TT_Err_Ok;
 
 
-    if ( FT_IS_SCALABLE( size->face ) )
-      tt_size_reset( ttsize );
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
-    error = sfnt->load_strike_metrics( ttface, index, metrics );
-    if ( error )
-      ttsize->strike_index = 0xFFFFFFFFUL;
-    else
-      ttsize->strike_index = index;
+    if ( FT_HAS_FIXED_SIZES( size->face ) )
+    {
+      SFNT_Service  sfnt = ttface->sfnt;
+      FT_ULong      index;
 
+
+      error = sfnt->set_sbit_strike( ttface, req, &index );
+
+      if ( error )
+        ttsize->strike_index = 0xFFFFFFFFUL;
+      else
+        return tt_size_select( size, index );
+    }
+
+#endif /*  TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+    FT_Request_Metrics( size->face, req );
+
+    if ( FT_IS_SCALABLE( size->face ) )
+      error = tt_size_reset( ttsize );
+
     return error;
   }
-
-#endif
 
 
   /*************************************************************************/
--- a/src/type1/t1objs.c
+++ b/src/type1/t1objs.c
@@ -111,10 +111,13 @@
 
 
   FT_LOCAL_DEF( FT_Error )
-  T1_Size_Request( T1_Size  size )
+  T1_Size_Request( T1_Size          size,
+                   FT_Size_Request  req )
   {
     PSH_Globals_Funcs  funcs = T1_Size_Get_Globals_Funcs( size );
-
+    
+    
+    FT_Request_Metrics( size->root.face, req );
 
     if ( funcs )
       funcs->set_scale( (PSH_Globals)size->root.internal,
--- a/src/type1/t1objs.h
+++ b/src/type1/t1objs.h
@@ -109,7 +109,8 @@
   T1_Size_Done( T1_Size  size );
 
   FT_LOCAL( FT_Error )
-  T1_Size_Request( T1_Size  size );
+  T1_Size_Request( T1_Size          size,
+                   FT_Size_Request  req );
 
   FT_LOCAL( FT_Error )
   T1_Size_Init( T1_Size  size );
--- a/src/type42/t42objs.c
+++ b/src/type42/t42objs.c
@@ -494,24 +494,35 @@
                     FT_Size_Request  req )
   {
     T42_Face  face = (T42_Face)size->root.face;
+    FT_Error  error;
 
 
     FT_Activate_Size( size->ttsize );
 
-    return FT_Request_Size( face->ttf_face, req );
+    error = FT_Request_Size( face->ttf_face, req );
+    if ( !error )
+      ( (FT_Size)size )->metrics = face->ttf_face->size->metrics;
+
+    return error;
   }
 
 
   FT_LOCAL_DEF( FT_Error )
   T42_Size_Select( T42_Size  size,
-                   FT_ULong  index )
+                   FT_ULong  strike_index )
   {
     T42_Face  face = (T42_Face)size->root.face;
+    FT_Error  error;
 
 
     FT_Activate_Size( size->ttsize );
 
-    return FT_Select_Size( face->ttf_face, index );
+    error = FT_Select_Size( face->ttf_face, strike_index );
+    if ( !error )
+      ( (FT_Size)size )->metrics = face->ttf_face->size->metrics;
+
+    return error;
+
   }
 
 
--- a/src/winfonts/winfnt.c
+++ b/src/winfonts/winfnt.c
@@ -574,15 +574,15 @@
   static FT_Error
   FNT_Size_Select( FT_Size  size )
   {
-    FNT_Face          face    = (FNT_Face)size->face;
-    FT_WinFNT_Header  header  = &face->font->header;
+    FNT_Face          face   = (FNT_Face)size->face;
+    FT_WinFNT_Header  header = &face->font->header;
 
 
+    FT_Select_Metrics( size->face, 0 );
+
     size->metrics.ascender    = header->ascent * 64;
     size->metrics.descender   = -( header->pixel_height -
                                    header->ascent ) * 64;
-    size->metrics.height      = ( header->pixel_height +
-                                  header->external_leading ) * 64;
     size->metrics.max_advance = header->max_width * 64;
 
     return FNT_Err_Ok;
@@ -600,11 +600,7 @@
     FT_Long           height;
 
 
-    if ( req->vertResolution )
-      height = ( req->height * req->vertResolution + 36 ) / 72;
-    else
-      height = req->height;
-
+    height = FT_REQUEST_HEIGHT( req );
     height = ( height + 32 ) >> 6;
 
     switch ( req->type )