Add embedded bitmap support to CFF driver.

* src/cff/cffobjs.h (CFF_SizeRec): New structure.

* src/cff/cffgload.c (cff_builder_init): Updated.
(cff_slot_load): Updated.
[TT_CONFIG_OPTION_EMBEDDED_BITMAPS]: Load sbit.

* src/cff/cffobjs.c (sbit_size_reset)
[TT_CONFIG_OPTION_EMBEDDED_BITMAPS]: New function.
(cff_size_get_globals_funcs, cff_size_done, cff_size_init): Updated.
(cff_size_reset): Updated.
[TT_CONFIG_OPTION_EMBEDDED_BITMAPS]: Call sbit_size_reset.

* src/cff/cffdrivr.c (Load_Glyph): Updated.
(cff_driver_class): Use CFF_SizeRec.

* docs/CHANGES: Updated.
diff --git a/ChangeLog b/ChangeLog
index 7f1539d..d373cca 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,10 +1,31 @@
+2004-03-02  Werner Lemberg  <wl@gnu.org>
+
+	Add embedded bitmap support to CFF driver.
+
+	* src/cff/cffobjs.h (CFF_SizeRec): New structure.
+
+	* src/cff/cffgload.c (cff_builder_init): Updated.
+	(cff_slot_load): Updated.
+	[TT_CONFIG_OPTION_EMBEDDED_BITMAPS]: Load sbit.
+
+	* src/cff/cffobjs.c (sbit_size_reset)
+	[TT_CONFIG_OPTION_EMBEDDED_BITMAPS]: New function.
+	(cff_size_get_globals_funcs, cff_size_done, cff_size_init): Updated.
+	(cff_size_reset): Updated.
+	[TT_CONFIG_OPTION_EMBEDDED_BITMAPS]: Call sbit_size_reset.
+
+	* src/cff/cffdrivr.c (Load_Glyph): Updated.
+	(cff_driver_class): Use CFF_SizeRec.
+
+	* docs/CHANGES: Updated.
+
 2004-03-01  Werner Lemberg  <wl@gnu.org>
 
 	* src/pshinter/pshglob.c (psh_globals_scale_widths): Don't use
 	FT_RoundFix but FT_PIX_ROUND.
 	(psh_blues_snap_stem): Don't use blue_shift but blue_threshold.
 
-	*src/pshinter/pshalgo.c (PSH_STRONG_THRESHOLD_MAXIMUM): New macro.
+	* src/pshinter/pshalgo.c (PSH_STRONG_THRESHOLD_MAXIMUM): New macro.
 	(psh_glyph_find_string_points): Use PSH_STRONG_THRESHOLD_MAXIMUM. 
 	(psh_glyph_find_blue_points): New function.  Needed for fonts like
 	p052003l.pfb (URW Palladio L Roman) which have flex curves at the
diff --git a/docs/CHANGES b/docs/CHANGES
index 7c53264..4420df0 100644
--- a/docs/CHANGES
+++ b/docs/CHANGES
@@ -16,6 +16,8 @@
       correctly  treated as a  CID, similar  to FreeType's  CID driver
       module.  Note that CID CMap support is still missing.
 
+    - Embedded bitmaps in SFNT-based CFF fonts are now supported.
+
     - The FT_FACE_FLAGS_GLYPH_NAMES is now  set correctly for all font
       formats.
 
diff --git a/src/cff/cffcmap.c b/src/cff/cffcmap.c
index 0c2e44e..82e04d2 100644
--- a/src/cff/cffcmap.c
+++ b/src/cff/cffcmap.c
@@ -200,7 +200,7 @@
         if ( new_count != count && new_count < count / 2 )
         {
           (void)FT_RENEW_ARRAY( cmap->pairs, count, new_count );
-          error = 0;
+          error = CFF_Err_Ok;
         }
 
         /* sort the pairs table to allow efficient binary searches */
diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c
index 75c072b..60ee90a 100644
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -201,7 +201,7 @@
     if ( size )
     {
       /* these two object must have the same parent */
-      if ( size->face != slot->root.face )
+      if ( size->root.face != slot->root.face )
         return CFF_Err_Invalid_Face_Handle;
     }
 
@@ -453,7 +453,7 @@
 
     /* now the specific driver fields */
     sizeof( TT_FaceRec ),
-    sizeof( FT_SizeRec ),
+    sizeof( CFF_SizeRec ),
     sizeof( CFF_GlyphSlotRec ),
 
     (FT_Face_InitFunc)       cff_face_init,
diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c
index f8d6110..c5bf79e 100644
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -251,15 +251,15 @@
 
       if ( hinting && size )
       {
-        builder->hints_globals = size->internal;
+        builder->hints_globals = size->root.internal;
         builder->hints_funcs   = glyph->root.internal->glyph_hints;
       }
     }
 
     if ( size )
     {
-      builder->scale_x = size->metrics.x_scale;
-      builder->scale_y = size->metrics.y_scale;
+      builder->scale_x = size->root.metrics.x_scale;
+      builder->scale_y = size->root.metrics.y_scale;
     }
 
     builder->pos_x = 0;
@@ -485,7 +485,7 @@
                            FT_Pos        x,
                            FT_Pos        y )
   {
-    FT_Error  error = 0;
+    FT_Error  error = CFF_Err_Ok;
 
 
     /* test whether we are building a new contour */
@@ -2219,7 +2219,7 @@
   cff_compute_max_advance( TT_Face  face,
                            FT_Int*  max_advance )
   {
-    FT_Error     error = 0;
+    FT_Error     error = CFF_Err_Ok;
     CFF_Decoder  decoder;
     FT_Int       glyph_index;
     CFF_Font     cff = (CFF_Font)face->other;
@@ -2255,7 +2255,7 @@
       }
 
       /* ignore the error if one has occurred -- skip to next glyph */
-      error = 0;
+      error = CFF_Err_Ok;
     }
 
     *max_advance = decoder.builder.advance.x;
@@ -2289,14 +2289,19 @@
                  FT_Int         glyph_index,
                  FT_Int32       load_flags )
   {
-    FT_Error     error;
-    CFF_Decoder  decoder;
-    TT_Face      face = (TT_Face)glyph->root.face;
-    FT_Bool      hinting;
-    CFF_Font     cff = (CFF_Font)face->extra.data;
+    FT_Error      error;
+    CFF_Decoder   decoder;
+    TT_Face       face     = (TT_Face)glyph->root.face;
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+    CFF_Face      cff_face = (CFF_Face)size->root.face;
+    SFNT_Service  sfnt     = (SFNT_Service)cff_face->sfnt;
+    FT_Stream     stream   = cff_face->root.stream;
+#endif
+    FT_Bool       hinting;
+    CFF_Font      cff      = (CFF_Font)face->extra.data;
 
-    FT_Matrix    font_matrix;
-    FT_Vector    font_offset;
+    FT_Matrix     font_matrix;
+    FT_Vector     font_offset;
 
 
     if ( load_flags & FT_LOAD_NO_RECURSE )
@@ -2306,10 +2311,70 @@
     glyph->y_scale = 0x10000L;
     if ( size )
     {
-      glyph->x_scale = size->metrics.x_scale;
-      glyph->y_scale = size->metrics.y_scale;
+      glyph->x_scale = size->root.metrics.x_scale;
+      glyph->y_scale = size->root.metrics.y_scale;
     }
 
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+    /* try to load embedded bitmap if any              */
+    /*                                                 */
+    /* XXX: The convention should be emphasized in     */
+    /*      the documents because it can be confusing. */
+    if ( size                                    &&
+         size->strike_index != 0xFFFFU           &&
+         sfnt->load_sbits                        &&
+         ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
+    {
+      TT_SBit_MetricsRec  metrics;
+
+
+      error = sfnt->load_sbit_image( face,
+                                     (FT_ULong)size->strike_index,
+                                     (FT_UInt)glyph_index,
+                                     (FT_Int)load_flags,  
+                                     stream,
+                                     &glyph->root.bitmap,
+                                     &metrics );
+
+      if ( !error )
+      {
+        glyph->root.outline.n_points   = 0;
+        glyph->root.outline.n_contours = 0;
+
+        glyph->root.metrics.width  = (FT_Pos)metrics.width  << 6;
+        glyph->root.metrics.height = (FT_Pos)metrics.height << 6;
+
+        glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
+        glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
+        glyph->root.metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;
+
+        glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
+        glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
+        glyph->root.metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;
+
+        glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
+
+        if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
+        {
+          glyph->root.bitmap_left = metrics.vertBearingX;
+          glyph->root.bitmap_top  = metrics.vertBearingY;
+        }
+        else
+        {   
+          glyph->root.bitmap_left = metrics.horiBearingX;
+          glyph->root.bitmap_top  = metrics.horiBearingY;
+        }
+        return error;
+      }
+    }  
+
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+    /* return immediately if we only want the embedded bitmaps */
+    if ( load_flags & FT_LOAD_SBITS_ONLY )
+      return CFF_Err_Invalid_Argument;
+
     glyph->root.outline.n_points   = 0;
     glyph->root.outline.n_contours = 0;
 
@@ -2444,7 +2509,7 @@
         glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;
 
         glyph->root.outline.flags = 0;
-        if ( size && size->metrics.y_ppem < 24 )
+        if ( size && size->root.metrics.y_ppem < 24 )
           glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION;
 
         glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL;
diff --git a/src/cff/cffload.c b/src/cff/cffload.c
index bbec294..44f3254 100644
--- a/src/cff/cffload.c
+++ b/src/cff/cffload.c
@@ -1177,7 +1177,7 @@
   cff_index_get_pointers( CFF_Index   idx,
                           FT_Byte***  table )
   {
-    FT_Error   error  = 0;
+    FT_Error   error  = CFF_Err_Ok;
     FT_Memory  memory = idx->stream->memory;
     FT_ULong   n, offset, old_offset;
     FT_Byte**  t;
@@ -1516,7 +1516,7 @@
                     FT_Bool      invert )
   {
     FT_Memory  memory = stream->memory;
-    FT_Error   error  = 0;
+    FT_Error   error  = CFF_Err_Ok;
     FT_UShort  glyph_sid;
 
 
@@ -1722,7 +1722,7 @@
                      FT_ULong      base_offset,
                      FT_ULong      offset )
   {
-    FT_Error   error = 0;
+    FT_Error   error = CFF_Err_Ok;
     FT_UInt    count;
     FT_UInt    j;
     FT_UShort  glyph_sid;
diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c
index 6abb84b..5e9e70a 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType objects manager (body).                                     */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003 by                                     */
+/*  Copyright 1996-2001, 2002, 2003, 2004 by                               */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -52,16 +52,81 @@
   /*************************************************************************/
 
 
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+  static FT_Error
+  sbit_size_reset( CFF_Size  size )
+  {
+    CFF_Face          face;
+    FT_Error          error = CFF_Err_Ok;
+
+    FT_ULong          strike_index;
+    FT_Size_Metrics*  metrics;
+    FT_Size_Metrics*  sbit_metrics;
+    SFNT_Service      sfnt;
+
+
+    metrics = &size->root.metrics;
+
+    face = (CFF_Face)size->root.face;
+    sfnt = (SFNT_Service)face->sfnt;
+
+    sbit_metrics = &size->strike_metrics;
+
+    error = sfnt->set_sbit_strike( face, 
+                                   metrics->x_ppem, metrics->y_ppem,
+                                   &strike_index );
+
+    if ( !error )
+    {
+      TT_SBit_Strike  strike = face->sbit_strikes + strike_index;
+
+
+      sbit_metrics->x_ppem = metrics->x_ppem;
+      sbit_metrics->y_ppem = metrics->y_ppem;
+
+      sbit_metrics->ascender  = strike->hori.ascender << 6;
+      sbit_metrics->descender = strike->hori.descender << 6;
+
+      /* XXX: Is this correct? */
+      sbit_metrics->height = sbit_metrics->ascender -
+                             sbit_metrics->descender;
+
+      /* XXX: Is this correct? */
+      sbit_metrics->max_advance = ( strike->hori.min_origin_SB  +
+                                    strike->hori.max_width      +
+                                    strike->hori.min_advance_SB ) << 6;
+
+      size->strike_index = (FT_UInt)strike_index;
+    }
+    else
+    {   
+      size->strike_index = 0xFFFFU;
+
+      sbit_metrics->x_ppem      = 0;
+      sbit_metrics->y_ppem      = 0;
+      sbit_metrics->ascender    = 0;
+      sbit_metrics->descender   = 0;
+      sbit_metrics->height      = 0;
+      sbit_metrics->max_advance = 0;
+    }
+
+    return error;
+  }
+   
+#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
+
+
   static PSH_Globals_Funcs
   cff_size_get_globals_funcs( CFF_Size  size )
   {
-    CFF_Face          face     = (CFF_Face)size->face;
+    CFF_Face          face     = (CFF_Face)size->root.face;
     CFF_Font          font     = (CFF_FontRec *)face->extra.data;
     PSHinter_Service  pshinter = (PSHinter_Service)font->pshinter;
     FT_Module         module;
 
 
-    module = FT_Get_Module( size->face->driver->root.library,
+    module = FT_Get_Module( size->root.face->driver->root.library,
                             "pshinter" );
     return ( module && pshinter && pshinter->get_globals_funcs )
            ? pshinter->get_globals_funcs( module )
@@ -72,16 +137,16 @@
   FT_LOCAL_DEF( void )
   cff_size_done( CFF_Size  size )
   {
-    if ( size->internal )
+    if ( size->root.internal )
     {
       PSH_Globals_Funcs  funcs;
 
 
       funcs = cff_size_get_globals_funcs( size );
       if ( funcs )
-        funcs->destroy( (PSH_Globals)size->internal );
+        funcs->destroy( (PSH_Globals)size->root.internal );
 
-      size->internal = 0;
+      size->root.internal = 0;
     }
   }
 
@@ -89,14 +154,14 @@
   FT_LOCAL_DEF( FT_Error )
   cff_size_init( CFF_Size  size )
   {
-    FT_Error           error = 0;
+    FT_Error           error = CFF_Err_Ok;
     PSH_Globals_Funcs  funcs = cff_size_get_globals_funcs( size );
 
 
     if ( funcs )
     {
       PSH_Globals    globals;
-      CFF_Face       face    = (CFF_Face)size->face;
+      CFF_Face       face    = (CFF_Face)size->root.face;
       CFF_Font       font    = (CFF_FontRec *)face->extra.data;
       CFF_SubFont    subfont = &font->top_font;
 
@@ -150,9 +215,9 @@
         priv.lenIV          = cpriv->lenIV;
       }
 
-      error = funcs->create( size->face->memory, &priv, &globals );
+      error = funcs->create( size->root.face->memory, &priv, &globals );
       if ( !error )
-        size->internal = (FT_Size_Internal)(void*)globals;
+        size->root.internal = (FT_Size_Internal)(void*)globals;
     }
 
     return error;
@@ -163,15 +228,32 @@
   cff_size_reset( CFF_Size  size )
   {
     PSH_Globals_Funcs  funcs = cff_size_get_globals_funcs( size );
-    FT_Error           error = 0;
+    FT_Error           error = CFF_Err_Ok;
+    FT_Face            face  = size->root.face;
 
 
     if ( funcs )
-      error = funcs->set_scale( (PSH_Globals)size->internal,
-                                 size->metrics.x_scale,
-                                 size->metrics.y_scale,
+      error = funcs->set_scale( (PSH_Globals)size->root.internal,
+                                 size->root.metrics.x_scale,
+                                 size->root.metrics.y_scale,
                                  0, 0 );
-    return error;
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+    if ( face->face_flags & FT_FACE_FLAG_FIXED_SIZES )
+    {
+      error = sbit_size_reset( size );
+
+      if ( !error && !( face->face_flags & FT_FACE_FLAG_SCALABLE ) )
+        size->root.metrics = size->strike_metrics;
+    }
+
+#endif
+
+    if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
+      return CFF_Err_Ok;
+    else
+      return error;
   }
 
 
diff --git a/src/cff/cffobjs.h b/src/cff/cffobjs.h
index 49d5665..f02a5d7 100644
--- a/src/cff/cffobjs.h
+++ b/src/cff/cffobjs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType objects manager (specification).                            */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003 by                                     */
+/*  Copyright 1996-2001, 2002, 2003, 2004 by                               */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -51,7 +51,18 @@
   /* <Description>                                                         */
   /*    A handle to an OpenType size object.                               */
   /*                                                                       */
-  typedef FT_Size  CFF_Size;
+  typedef struct  CFF_SizeRec_
+  {
+    FT_SizeRec       root;
+
+#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+
+    FT_UInt          strike_index;    /* 0xFFFF to indicate invalid */
+    FT_Size_Metrics  strike_metrics;  /* current strike's metrics   */
+
+#endif
+
+  } CFF_SizeRec, *CFF_Size;
 
 
   /*************************************************************************/