shithub: freetype+ttf2subf

Download patch

ref: 9d636b6d14dc5decc9651757e15faab5267b0873
parent: 74abee8e2ea269b983916b8eb55bef385b98f2e2
author: David Turner <[email protected]>
date: Tue Jun 27 19:32:27 EDT 2000

various cleanups to reduce compiler warnings
+ support for CID-keyed fonts in the CFF driver
(still some unexpected bugs though..)

git/fs: mount .git/fs: mount/attach disallowed
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,39 @@
 LATEST CHANGES
 
+  - added support for CID-keyed fonts to the CFF driver. There are still
+    some unexplained bugs though... ???
+
+
+  - cleaned up source code in order to avoid two functions with the
+    same name. Also changed the names of the files in "type1z" from
+    "t1XXXX" to "z1XXXX" in order to avoid any conflicts.
+    
+    "make multi" now works well :-)
+    
+    
+
+  - CHANGES TO THE RENDERER MODULES
+  
+    the monochrome and smooth renderers are now in two distinct directories,
+    namely "src/raster1" and "src/smooth". Note that the old "src/renderer"
+    is now gone..
+    
+    I ditched the 5-gray-levels renderers. Basically, it involved a simple
+    #define toggle in 'src/raster1/ftraster.c'
+    
+    FT_Render_Glyph, FT_Outline_Render & FT_Outline_Get_Bitmap now select
+    the best renderer available, depending on render mode. If the current
+    renderer for a given glyph image format isn't capable of supporting
+    the render mode, another one will be found in the library's list.
+    
+    This means that client applications do not need to switch or set the
+    renderers themselves (as in the latest change), they'll get what they
+    want automatically... At last..
+    
+    Changed the demo programs accordingly..
+    
+    
+
   - MAJOR INTERNAL REDESIGN:
   
     A lot of internal modifications have been performed lately on the
--- a/config/win32/w32-dev.mk
+++ b/config/win32/w32-dev.mk
@@ -98,7 +98,7 @@
 #   ANSI compliance.
 #
 ifndef CFLAGS
-  CFLAGS := -c -g -O0 -Wall
+  CFLAGS := -c -g -O0 -Wall -W
 endif
 
 # ANSIFLAGS: Put there the flags used to make your compiler ANSI-compliant.
--- a/demos/src/ftmulti.c
+++ b/demos/src/ftmulti.c
@@ -13,7 +13,6 @@
 /****************************************************************************/
 
 #include <freetype/freetype.h>
-#include <freetype/ftrender.h>
 #include <freetype/ftmm.h>
 
 #include "common.h"
@@ -74,10 +73,6 @@
   int  render_mode = 1;
   int  use_grays   = 1;
 
-  /* the standard raster's interface */
-  FT_Renderer   std_renderer;
-  FT_Renderer   smooth_renderer;
-
   FT_Multi_Master  multimaster;
   FT_Long          design_pos[T1_MAX_MM_AXIS];
 
@@ -432,7 +427,6 @@
     grWriteln("  h         : toggle outline hinting" );
     grWriteln("  b         : toggle embedded bitmaps" );
     grWriteln("  l         : toggle low precision rendering" );
-    grWriteln("  g         : toggle between `smooth' and `standard' anti-aliaser" );
     grWriteln("  space     : toggle rendering mode" );
     grLn();
     grWriteln("  Up        : increase pointsize by 1 unit" );
@@ -457,16 +451,7 @@
   }
 
 
-  static
-  void  reset_raster( void )
-  {
-    if ( antialias && use_grays && smooth_renderer )
-      FT_Set_Renderer( library, smooth_renderer, 0, 0 );
-    else
-      FT_Set_Renderer( library, std_renderer, 0, 0 );
-  }
 
-
   static
   int  Process_Event( grEvent*  event )
   {
@@ -489,7 +474,6 @@
       antialias = !antialias;
       new_header = antialias ? "anti-aliasing is now on"
                              : "anti-aliasing is now off";
-      reset_raster();
       return 1;
 
     case grKEY( 'b' ):
@@ -502,13 +486,6 @@
     case grKEY( 'p' ):
       return (int)event->key;
 
-    case grKEY( 'g' ):
-      use_grays = !use_grays;
-      new_header = use_grays ? "now using the smooth anti-aliaser"
-                             : "now using the standard anti-aliaser";
-      reset_raster();
-      break;
-
     case grKEY( 'l' ):
       low_prec = !low_prec;
       new_header = low_prec ? "rendering precision is now forced to low"
@@ -713,13 +690,6 @@
     error = FT_Init_FreeType( &library );
     if ( error )
       PanicZ( "Could not initialize FreeType library" );
-
-    /* retrieve the standard raster's interface */
-    std_renderer = (FT_Renderer)FT_Get_Module( library, "standard renderer" );
-    if (!std_renderer)
-      PanicZ( "Could not retrieve standard renderer" );
-
-    smooth_renderer = (FT_Renderer)FT_Get_Module( library, "smooth renderer" );
 
   NewFile:
     ptsize      = orig_ptsize;
--- a/demos/src/ftstring.c
+++ b/demos/src/ftstring.c
@@ -11,7 +11,6 @@
 /****************************************************************************/
 
 #include <freetype/freetype.h>
-#include <freetype/ftrender.h>
 #include <freetype/ftglyph.h>
 #include "common.h"
 
@@ -60,12 +59,7 @@
 
   static int  graph_init  = 0;
   static int  render_mode = 1;
-  static int  use_grays   = 1;
 
-  /* the standard raster's interface */
-  FT_Renderer   std_renderer;
-  FT_Renderer   smooth_renderer;
-
   static FT_Matrix      trans_matrix;
   static int            transform = 0;
 
@@ -449,7 +443,6 @@
     grWriteln("  a         : toggle anti-aliasing" );
     grWriteln("  h         : toggle outline hinting" );
     grWriteln("  k         : toggle kerning" );
-    grWriteln("  g         : toggle between 'smooth' and 'standard' anti-aliaser" );
     grLn();
     grWriteln("  Up        : increase pointsize by 1 unit" );
     grWriteln("  Down      : decrease pointsize by 1 unit" );
@@ -468,15 +461,6 @@
   }
 
 
-  static void  reset_raster( void )
-  {
-    if ( antialias && use_grays && smooth_renderer )
-      FT_Set_Renderer( library, smooth_renderer, 0, 0 );
-    else
-      FT_Set_Renderer( library, std_renderer, 0, 0 );
-  }
-
-
   static int  Process_Event( grEvent*  event )
   {
     int  i;
@@ -499,7 +483,6 @@
       new_header = ( antialias
                    ? "anti-aliasing is now on"
                    : "anti-aliasing is now off" );
-      reset_raster();
       return 1;
 
     case grKEY('b'):
@@ -513,14 +496,6 @@
     case grKEY('p'):
       return (int)event->key;
 
-    case grKEY('g'):
-      use_grays = !use_grays;
-      new_header = ( use_grays
-                   ? "now using the smooth anti-aliaser"
-                   : "now using the standard anti-aliaser" );
-      reset_raster();
-      break;
-
     case grKEY('h'):
       hinted = !hinted;
       new_header = ( hinted
@@ -667,13 +642,6 @@
     /* Initialize engine */
     error = FT_Init_FreeType( &library );
     if (error) PanicZ( "Could not initialise FreeType library" );
-
-    /* retrieve the standard raster's interface */
-    std_renderer = (FT_Renderer)FT_Get_Module( library, "standard renderer" );
-    if (!std_renderer)
-      PanicZ( "Could not retrieve standard renderer" );
-
-    smooth_renderer = (FT_Renderer)FT_Get_Module( library, "smooth renderer" );
 
   NewFile:
     ptsize      = orig_ptsize;
--- a/demos/src/ftview.c
+++ b/demos/src/ftview.c
@@ -17,7 +17,6 @@
 
 
 #include <freetype/freetype.h>
-#include <freetype/ftrender.h>
 
   /* the following header shouldn't be used in normal programs */
 #include <freetype/internal/ftdebug.h>
@@ -64,7 +63,7 @@
   int  ptsize;                /* current point size */
 
   int  hinted      = 1;       /* is glyph hinting active?     */
-  int  antialias   = 0;       /* is anti-aliasing active?     */
+  int  antialias   = 1;       /* is anti-aliasing active?     */
   int  use_sbits   = 1;       /* do we use embedded bitmaps?  */
   int  low_prec    = 0;       /* force low precision          */
   int  Num;                   /* current first glyph index    */
@@ -78,15 +77,10 @@
   int  graph_init  = 0;
 
   int  render_mode = 1;
-  int  use_grays   = 1;
   int  debug       = 0;
   int  trace_level = 0;
 
-  /* the standard raster's interface */
-  FT_Renderer   std_renderer;
-  FT_Renderer   smooth_renderer;
 
-
 #define RASTER_BUFF_SIZE   32768
   char  raster_buff[RASTER_BUFF_SIZE];
 
@@ -152,80 +146,45 @@
 #define CEIL( x )   ( ( (x) + 63 ) & -64 )
 #define TRUNC( x )  (   (x) >> 6 )
 
-  static
-  char  bit_buffer[MAX_BUFFER];
 
-
   /* Render a single glyph with the `grays' component */
   static
   FT_Error  Render_Glyph( int  x_offset,
                           int  y_offset )
   {
-    /* first, render the glyph into an intermediate buffer */
-    FT_Bitmap  bit2;
-    grBitmap   bit3;
-    int        width, height, pitch, size;
-    int        left, right, top, bottom;
-    int        x_top, y_top;
-
-
-    left  = FLOOR( glyph->metrics.horiBearingX );
-    right = CEIL( glyph->metrics.horiBearingX + glyph->metrics.width );
-    width = TRUNC( right - left );
-
-    top    = CEIL( glyph->metrics.horiBearingY );
-    bottom = FLOOR( glyph->metrics.horiBearingY - glyph->metrics.height );
-    height = TRUNC( top - bottom );
-
-    if ( glyph->format == ft_glyph_format_outline )
+    grBitmap  bit3;
+    FT_Pos    x_top, y_top;
+    
+    /* first, render the glyph image into a bitmap */
+    if (glyph->format != ft_glyph_format_bitmap)
     {
-      pitch = antialias ? ( width + 3 ) & -4
-                        : ( width + 7 ) >> 3;
-      size  = pitch * height;
-
-      if ( size > MAX_BUFFER )
-        return FT_Err_Out_Of_Memory;
-
-      bit2.width      = width;
-      bit2.rows       = height;
-      bit2.pitch      = pitch;
-      bit2.pixel_mode = antialias ? ft_pixel_mode_grays : ft_pixel_mode_mono;
-      bit2.buffer     = bit_buffer;
-
-      bit3.rows   = bit2.rows;
-      bit3.width  = bit2.width;
-      bit3.pitch  = bit2.pitch;
-      bit3.mode   = antialias ? bit.mode : gr_pixel_mode_mono;
-      bit3.buffer = bit_buffer;
-      bit3.grays  = 256;
-
-      FT_Outline_Translate( &glyph->outline, -left, -bottom );
-      memset( bit_buffer, 0, size );
-
-      if ( low_prec )
-        glyph->outline.flags &= ~ft_outline_high_precision;
-
-      error = FT_Outline_Get_Bitmap( library, &glyph->outline, &bit2 );
+      error = FT_Render_Glyph( glyph, antialias ? 1 : 0 );
+      if (error) return error;                               
+                               
     }
-    else
+    
+    /* now blit it to our display screen */
+    bit3.rows   = glyph->bitmap.rows;
+    bit3.width  = glyph->bitmap.width;
+    bit3.pitch  = glyph->bitmap.pitch;
+    bit3.buffer = glyph->bitmap.buffer;
+
+    switch (glyph->bitmap.pixel_mode)
     {
-      bit3.rows   = glyph->bitmap.rows;
-      bit3.width  = glyph->bitmap.width;
-      bit3.pitch  = glyph->bitmap.pitch;
-      bit3.mode   = gr_pixel_mode_mono;
-      bit3.buffer = glyph->bitmap.buffer;
-      bit3.grays  = 0;
+      case ft_pixel_mode_mono:
+         bit3.mode   = gr_pixel_mode_mono;
+         bit3.grays  = 0;
+         break;
+         
+      case ft_pixel_mode_grays:
+         bit3.mode   = gr_pixel_mode_gray;
+         bit3.grays  = glyph->bitmap.num_grays;
     }
 
     /* Then, blit the image to the target surface */
-    x_top = x_offset + TRUNC( left );
-    y_top = y_offset - TRUNC( top );
+    x_top = x_offset + glyph->bitmap_left;
+    y_top = y_offset - glyph->bitmap_top;
 
-#if 0
-    if ( bit.pitch < 0 )
-      y_top = bit.rows - y_top;
-#endif
-
     grBlitGlyphToBitmap( &bit, &bit3, x_top, y_top, fore_color );
 
     return 0;
@@ -431,7 +390,6 @@
     grWriteln("  h         : toggle outline hinting" );
     grWriteln("  b         : toggle embedded bitmaps" );
     grWriteln("  l         : toggle low precision rendering" );
-    grWriteln("  g         : toggle between `smooth' and `standard' anti-aliaser" );
     grWriteln("  space     : toggle rendering mode" );
     grLn();
     grWriteln("  Up        : increase pointsize by 1 unit" );
@@ -456,16 +414,7 @@
   }
 
 
-  static
-  void  reset_raster( void )
-  {
-    if ( antialias && use_grays && smooth_renderer )
-      FT_Set_Renderer( library, smooth_renderer, 0, 0 );
-    else
-      FT_Set_Renderer( library, std_renderer, 0, 0 );
-  }
 
-
   static
   int  Process_Event( grEvent*  event )
   {
@@ -482,7 +431,6 @@
       antialias  = !antialias;
       new_header = antialias ? "anti-aliasing is now on"
                              : "anti-aliasing is now off";
-      reset_raster();
       return 1;
 
     case grKEY( 'b' ):
@@ -496,14 +444,6 @@
     case grKEY( 'p' ):
       return (int)event->key;
 
-    case grKEY( 'g' ):
-      use_grays  = !use_grays;
-      new_header = use_grays
-                     ? "now using the smooth anti-aliaser"
-                     : "now using the standard anti-aliaser";
-      reset_raster();
-      break;
-
     case grKEY( 'l' ):
       low_prec   = !low_prec;
       new_header = low_prec
@@ -672,13 +612,6 @@
     if ( error )
       PanicZ( "Could not initialize FreeType library" );
 
-    /* retrieve the standard raster's interface */
-    std_renderer = (FT_Renderer)FT_Get_Module( library, "standard renderer" );
-    if (!std_renderer)
-      PanicZ( "Could not retrieve standard renderer" );
-
-    smooth_renderer = (FT_Renderer)FT_Get_Module( library, "smooth renderer" );
-      
   NewFile:
     ptsize      = orig_ptsize;
     hinted      = 1;
--- a/include/freetype/config/ftmodule.h
+++ b/include/freetype/config/ftmodule.h
@@ -1,9 +1,9 @@
 FT_USE_MODULE(cff_driver_class)
 FT_USE_MODULE(t1cid_driver_class)
 FT_USE_MODULE(psnames_module_class)
-FT_USE_MODULE(ft_standard_renderer_class)
-FT_USE_MODULE(ft_smooth_renderer_class)
+FT_USE_MODULE(ft_raster1_renderer_class)
 FT_USE_MODULE(sfnt_module_class)
+FT_USE_MODULE(ft_smooth_renderer_class)
 FT_USE_MODULE(tt_driver_class)
 FT_USE_MODULE(t1_driver_class)
 FT_USE_MODULE(t1z_driver_class)
--- a/include/freetype/fterrors.h
+++ b/include/freetype/fterrors.h
@@ -55,6 +55,7 @@
 
   FT_ERRORDEF( FT_Err_Unimplemented_Feature,   0x0020, "unimplemented feature" )
   FT_ERRORDEF( FT_Err_Invalid_Glyph_Format,    0x0021, "invalid glyph image format" )
+  FT_ERRORDEF( FT_Err_Cannot_Render_Glyph,     0x0022, "cannot render this glyph format" )
 
   FT_ERRORDEF( FT_Err_Invalid_Library_Handle,  0x0030, "invalid library handle" )
   FT_ERRORDEF( FT_Err_Invalid_Driver_Handle,   0x0031, "invalid module handle" )
--- a/include/freetype/ftrender.h
+++ b/include/freetype/ftrender.h
@@ -49,7 +49,8 @@
 
   typedef FT_Error  (*FTRenderer_render)( FT_Renderer   renderer,
                                           FT_GlyphSlot  slot,
-                                          FT_UInt       mode );
+                                          FT_UInt       mode,
+                                          FT_Vector*    origin );
 
   typedef FT_Error  (*FTRenderer_transform)( FT_Renderer   renderer,
                                              FT_GlyphSlot  slot,
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -384,7 +384,7 @@
 
     FT_Generic          generic;
 
-    FT_Int              num_modules;
+    FT_UInt             num_modules;
     FT_Module           modules[ FT_MAX_MODULES ];  /* module objects  */
 
     FT_ListRec          renderers;     /* list of renderers        */
@@ -391,7 +391,7 @@
     FT_Renderer         cur_renderer;  /* current outline renderer */
 
     void*               raster_pool;      /* scan-line conversion render pool */
-    long                raster_pool_size; /* size of render pool in bytes     */
+    unsigned long       raster_pool_size; /* size of render pool in bytes     */
 
     FT_DebugHook_Func   debug_hooks[4];
 
@@ -410,6 +410,14 @@
                                               FT_UInt            hook_index,
                                               FT_DebugHook_Func  debug_hook );
 
+
+  BASE_DEF(FT_Renderer)  FT_Lookup_Renderer( FT_Library       library,
+                                             FT_Glyph_Format  format,
+                                             FT_ListNode     *node );
+
+  BASE_DEF(FT_Error)    FT_Render_Glyph_Internal( FT_Library    library,
+                                                  FT_GlyphSlot  slot,
+                                                  FT_UInt       render_mode );
 
 
 
--- a/include/freetype/internal/t2types.h
+++ b/include/freetype/internal/t2types.h
@@ -62,7 +62,7 @@
   } CFF_Index;
 
 
-  typedef struct CFF_Top_Dict_
+  typedef struct CFF_Font_Dict_
   {
     FT_UInt      version;
     FT_UInt      notice;
@@ -90,6 +90,7 @@
     FT_UInt      base_font_name;       
     FT_UInt      postscript;
 
+   /* these should only be used for the top-level font dict */
     FT_UInt      cid_registry;
     FT_UInt      cid_ordering;
     FT_ULong     cid_supplement;
@@ -103,8 +104,10 @@
     FT_ULong     cid_fd_select_offset;
     FT_UInt      cid_font_name;
 
-  } CFF_Top_Dict;
+  } CFF_Font_Dict;
   
+  
+  
   typedef struct CFF_Private_
   {
     FT_Byte  num_blue_values;
@@ -138,6 +141,42 @@
     FT_Pos   nominal_width;
   
   } CFF_Private;
+
+
+  typedef struct CFF_FD_Select_
+  {
+    FT_Byte   format;
+    FT_UInt   range_count;
+
+    /* that's the table, taken from the file 'as is' */    
+    FT_Byte*  data;
+    FT_UInt   data_size;
+
+    /* small cache for format 3 only */
+    FT_UInt   cache_first;
+    FT_UInt   cache_count;
+    FT_Byte   cache_fd;
+    
+  } CFF_FD_Select;
+
+
+
+ /* a SubFont packs a font dict and a private dict together. They're */
+ /* needed to support CID-keyde CFF fonts..                          */
+  typedef struct CFF_SubFont_
+  {
+    CFF_Font_Dict  font_dict;
+    CFF_Private    private_dict;
+    
+    CFF_Index      local_subrs_index;
+    FT_UInt        num_local_subrs;
+    FT_Byte**      local_subrs;
+
+  } CFF_SubFont;
+
+
+ /* maximum number of sub-fonts in a CID-keyed file */
+  #define CFF_MAX_CID_FONTS  16
   
   typedef struct CFF_Font_
   {
@@ -144,6 +183,7 @@
     FT_Stream  stream;
     FT_Memory  memory;
     FT_UInt    num_faces;
+    FT_UInt    num_glyphs;
     
     FT_Byte    version_major;
     FT_Byte    version_minor;
@@ -164,13 +204,14 @@
     CFF_Index  local_subrs_index;
 
     FT_String*     font_name;
-    CFF_Top_Dict   top_dict;
-    CFF_Private    private_dict;
-
     FT_UInt        num_global_subrs;
-    FT_UInt        num_local_subrs;
     FT_Byte**      global_subrs;
-    FT_Byte**      local_subrs;
+
+    CFF_SubFont    top_font;
+    FT_UInt        num_subfonts;
+    CFF_SubFont*   subfonts[ CFF_MAX_CID_FONTS ];
+
+    CFF_FD_Select  fd_select;
 
   } CFF_Font;
 
--- a/src/cff/t2gload.c
+++ b/src/cff/t2gload.c
@@ -345,18 +345,37 @@
     T2_Init_Builder( &decoder->builder, face, size, slot );
 
     /* initialize Type2 decoder */
-    decoder->num_locals   = cff->num_local_subrs;
     decoder->num_globals  = cff->num_global_subrs;
-    decoder->locals       = cff->local_subrs;
     decoder->globals      = cff->global_subrs;
-    decoder->locals_bias  = t2_compute_bias( decoder->num_locals );
     decoder->globals_bias = t2_compute_bias( decoder->num_globals );
-
-    decoder->glyph_width   = cff->private_dict.default_width;
-    decoder->nominal_width = cff->private_dict.nominal_width;
   }
 
 
+ /* this function is used to select the locals subrs array */
+  LOCAL_DEF
+  void   T2_Prepare_Decoder( T2_Decoder*  decoder,
+                             FT_UInt      glyph_index )
+  {
+    CFF_Font*     cff = (CFF_Font*)decoder->builder.face->extra.data;
+    CFF_SubFont*  sub = &cff->top_font;
+    
+    /* manage CID fonts */
+    if (cff->num_subfonts >= 1)
+    {
+      FT_Byte  fd_index = CFF_Get_FD( &cff->fd_select, glyph_index );
+      sub = cff->subfonts[fd_index];
+    }
+    
+    decoder->num_locals  = sub->num_local_subrs;
+    decoder->locals      = sub->local_subrs;
+    decoder->locals_bias = t2_compute_bias( decoder->num_locals );
+
+    decoder->glyph_width   = sub->private_dict.default_width;
+    decoder->nominal_width = sub->private_dict.nominal_width;
+  }                                 
+
+
+
   /* check that there is enough room for `count' more points */
   static
   FT_Error  check_points( T2_Builder*  builder,
@@ -509,7 +528,6 @@
     FT_Fixed            seed;
     FT_Fixed*           stack;
 
-
     /* set default width */
     decoder->num_hints  = 0;
     decoder->read_width = 1;
@@ -1572,6 +1590,7 @@
                                  &charstring, &charstring_len );
       if ( !error )
       {
+        T2_Prepare_Decoder( &decoder, glyph_index );
         error = T2_Parse_CharStrings( &decoder, charstring, charstring_len );
 
         T2_Forget_Element( &cff->charstrings_index, &charstring );
@@ -1648,6 +1667,7 @@
                                  &charstring, &charstring_len );
       if ( !error )
       {
+        T2_Prepare_Decoder( &decoder, glyph_index );
         error = T2_Parse_CharStrings( &decoder, charstring, charstring_len );
 
         T2_Forget_Element( &cff->charstrings_index, &charstring );
--- a/src/cff/t2gload.h
+++ b/src/cff/t2gload.h
@@ -166,6 +166,9 @@
                          T2_Size       size,
                          T2_GlyphSlot  slot );
 
+  LOCAL_DEF
+  void   T2_Prepare_Decoder( T2_Decoder*  decoder,
+                             FT_UInt     glyph_index );
 
 #if 0  /* unused until we support pure CFF fonts */
 
--- a/src/cff/t2load.c
+++ b/src/cff/t2load.c
@@ -318,8 +318,241 @@
 
 #endif /* 0 */
 
+ /**********************************************************************/
+ /**********************************************************************/
+ /***                                                                ***/
+ /***   FD Select table support                                      ***/
+ /***                                                                ***/
+ /***                                                                ***/
+ /**********************************************************************/
+ /**********************************************************************/
 
+  static
+  void  CFF_Done_FD_Select( CFF_FD_Select*  select,
+                            FT_Stream       stream )
+  {
+    if (select->data)
+      RELEASE_Frame( select->data );
+      
+    select->data_size   = 0;
+    select->format      = 0;
+    select->range_count = 0;
+  }                            
+
+
+  static
+  FT_Error  CFF_Load_FD_Select( CFF_FD_Select*  select,
+                                FT_UInt         num_glyphs,
+                                FT_Stream       stream,
+                                FT_ULong        offset )
+  {
+    FT_Error       error;
+    FT_Byte        format;
+    FT_UInt        num_ranges;
+    
+    /* read format */
+    if ( FILE_Seek(offset) || READ_Byte(format) )
+      goto Exit;
+    
+    select->format = format;
+    switch (format)
+    {
+      case 0:  /* format 0, that's simple */
+         {
+           select->data_size = num_glyphs;
+           goto Load_Data;
+         }
+         
+         
+      case 3:  /* format 3, a tad more complex */
+         {
+           if ( READ_UShort(num_ranges) )
+             goto Exit;
+             
+           select->data_size = num_ranges*3+2;
+           
+         Load_Data:  
+           if ( EXTRACT_Frame( select->data_size, select->data ) )
+             goto Exit;
+         }
+         break;
+         
+         
+      default: /* humm.. that's wrong */
+        error = FT_Err_Invalid_File_Format;
+    }
+  Exit:
+    return error;
+  }                                
+
+
   LOCAL_FUNC
+  FT_Byte  CFF_Get_FD( CFF_FD_Select*  select,
+                       FT_UInt         glyph_index )
+  {
+    FT_Byte  fd = 0;
+    
+    switch (select->format)
+    {
+      case 0:
+        fd = select->data[glyph_index];
+        break;
+        
+      case 3:
+        /* first, compare to cache */
+        if ((FT_UInt)(glyph_index-select->cache_first) < select->cache_count)
+        {
+          fd = select->cache_fd;
+          break;
+        }
+        
+        /* then, lookup the ranges array */
+        {
+          FT_Byte*  p       = select->data;
+          FT_Byte*  p_limit = p + select->data_size;
+          FT_Byte   fd2;
+          FT_UInt   first, limit;
+          
+          first = NEXT_UShort(p);
+          do
+          {
+            if (glyph_index < first)
+              break;
+              
+            fd2   = *p++;
+            limit = NEXT_UShort(p);
+            
+            if (glyph_index < limit)
+            {
+              fd = fd2;
+              
+              /* update cache */
+              select->cache_first = first;
+              select->cache_count = limit-first;
+              select->cache_fd    = fd2;
+              break;
+            }
+            first = limit;
+          }
+          while (p < p_limit);
+        }
+        break;
+        
+      default:
+        ;
+    }
+    return fd;
+  }                       
+
+
+ /**********************************************************************/
+ /**********************************************************************/
+ /***                                                                ***/
+ /***   CFF font support                                             ***/
+ /***                                                                ***/
+ /***                                                                ***/
+ /**********************************************************************/
+ /**********************************************************************/
+
+  static
+  FT_Error  CFF_Load_SubFont( CFF_SubFont*  font,
+                              CFF_Index*    index,
+                              FT_UInt       font_index,
+                              FT_Stream     stream,
+                              FT_ULong      base_offset )
+  {
+    FT_Error       error;
+    T2_Parser      parser;
+    FT_Byte*       dict;
+    FT_ULong       dict_len;
+    CFF_Font_Dict*  top  = &font->font_dict;
+    CFF_Private*   priv = &font->private_dict;
+
+    T2_Parser_Init( &parser, T2CODE_TOPDICT, &font->font_dict );
+
+    /* set defaults */
+    MEM_Set( top, 0, sizeof ( *top ) );
+
+    top->underline_position  = -100;
+    top->underline_thickness = 50;
+    top->charstring_type     = 2;
+    top->font_matrix.xx      = 0x10000L;
+    top->font_matrix.yy      = 0x10000L;
+    top->cid_count           = 8720;
+
+    error = T2_Access_Element( index, font_index, &dict, &dict_len ) ||
+            T2_Parser_Run( &parser, dict, dict + dict_len );
+
+    T2_Forget_Element( index, &dict );
+
+    if ( error )
+      goto Exit;
+
+    /* if it's a CID font, we stop there */
+    if ( top->cid_registry )
+      goto Exit;
+
+    /* parse the private dictionary, if any */
+    if ( top->private_offset && top->private_size)
+    {
+      /* set defaults */
+      MEM_Set( priv, 0, sizeof(*priv) );
+      
+      priv->blue_shift       = 7;
+      priv->blue_fuzz        = 1;
+      priv->lenIV            = -1;
+      priv->expansion_factor = (FT_Fixed)0.06 * 0x10000L;
+      priv->blue_scale       = (FT_Fixed)0.039625 * 0x10000L;
+
+      T2_Parser_Init( &parser, T2CODE_PRIVATE, priv );
+
+      if ( FILE_Seek( base_offset + font->font_dict.private_offset ) ||
+           ACCESS_Frame( font->font_dict.private_size )               )
+        goto Exit;
+
+      error = T2_Parser_Run( &parser,
+                             (FT_Byte*)stream->cursor,
+                             (FT_Byte*)stream->limit );
+      FORGET_Frame();
+      if ( error )
+        goto Exit;
+    }
+
+    /* read the local subrs, if any */
+    if ( priv->local_subrs_offset )
+    {
+      if ( FILE_Seek( base_offset + top->private_offset +
+                      priv->local_subrs_offset ) )
+        goto Exit;
+
+      error = t2_new_cff_index( &font->local_subrs_index, stream, 1 );
+      if ( error )
+        goto Exit;
+        
+      font->num_local_subrs = font->local_subrs_index.count;
+      error = t2_explicit_cff_index( &font->local_subrs_index,
+                                     &font->local_subrs );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  static
+  void  CFF_Done_SubFont( FT_Memory     memory,
+                          CFF_SubFont*  subfont )
+  {
+    if (subfont)
+    {
+      t2_done_cff_index( &subfont->local_subrs_index );
+      FREE( subfont->local_subrs );
+    }
+  }                          
+
+
+
+  LOCAL_FUNC
   FT_Error  T2_Load_CFF_Font( FT_Stream  stream,
                               FT_Int     face_index,
                               CFF_Font*  font )
@@ -334,14 +567,16 @@
       FT_FRAME_END
     };
 
-    FT_Error   error;
-    FT_Memory  memory = stream->memory;
-    FT_ULong   base_offset;
+    FT_Error        error;
+    FT_Memory       memory = stream->memory;
+    FT_ULong        base_offset;
+    CFF_Font_Dict*  dict;
 
 
     MEM_Set( font, 0, sizeof ( *font ) );
     font->stream = stream;
     font->memory = memory;
+    dict         = &font->top_font.font_dict;
     base_offset  = FILE_Pos();
 
     /* read CFF font header */
@@ -353,7 +588,7 @@
          font->header_size      < 4 ||
          font->absolute_offsize > 4 )
     {
-      FT_ERROR(( "incorrect CFF font header!\n" ));
+      FT_TRACE2(( "[not a CFF font header!]\n" ));
       error = FT_Err_Unknown_File_Format;
       goto Exit;
     }
@@ -363,7 +598,7 @@
 
     /* read the name, top dict, string and global subrs index */
     error = t2_new_cff_index( &font->name_index, stream, 0 )       ||
-            t2_new_cff_index( &font->top_dict_index, stream, 0 )   ||
+            t2_new_cff_index( &font->font_dict_index, stream, 0 )   ||
             t2_new_cff_index( &font->string_index, stream, 0 )     ||
             t2_new_cff_index( &font->global_subrs_index, stream, 1 );
     if ( error )
@@ -371,7 +606,7 @@
 
     /* well, we don't really forget the `disabled' fonts... */
     font->num_faces = font->name_index.count;
-    if ( face_index >= font->num_faces )
+    if ( face_index >= (FT_Int)font->num_faces )
     {
       FT_ERROR(( "T2_Load_CFF_Font: incorrect face index = %d\n",
                  face_index ));
@@ -379,111 +614,96 @@
     }
 
     /* in case of a font format check, simply exit now */
-    if ( face_index >= 0 )
+    if (face_index < 0)
+      goto Exit;
+      
+    /* now, parse the top-level font dictionary */
+    error = CFF_Load_SubFont( &font->top_font,
+                              &font->font_dict_index,
+                              face_index,
+                              stream,
+                              base_offset );
+    if (error)
+      goto Exit;
+
+    /* now, check for a CID font */
+    if ( dict->cid_registry )
     {
-      T2_Parser      parser;
-      FT_Byte*       dict;
-      FT_ULong       dict_len;
-      CFF_Index*     index = &font->top_dict_index;
-      CFF_Top_Dict*  top   = &font->top_dict;
+      CFF_Index     fd_index;
+      CFF_SubFont*  sub;
+      FT_UInt       index;
 
-
-      /* parse the top-level font dictionary */
-      T2_Parser_Init( &parser, T2CODE_TOPDICT, &font->top_dict );
-
-      /* set defaults */
-      memset( top, 0, sizeof ( *top ) );
-
-      top->underline_position  = -100;
-      top->underline_thickness = 50;
-      top->charstring_type     = 2;
-      top->font_matrix.xx      = 0x10000L;
-      top->font_matrix.yy      = 0x10000L;
-      top->cid_count           = 8720;
-
-      error = T2_Access_Element( index, face_index, &dict, &dict_len ) ||
-              T2_Parser_Run( &parser, dict, dict + dict_len );
-
-      T2_Forget_Element( &font->top_dict_index, &dict );
-
-      if ( error )
+      /* this is a CID-keyed font, we must now allocate a table of */
+      /* sub-fonts, then load each of them separately..            */
+      if ( FILE_Seek( base_offset + dict->cid_fd_array_offset ) )
         goto Exit;
-
-      /* parse the private dictionary, if any */
-      if (font->top_dict.private_offset && font->top_dict.private_size)
+        
+      error = t2_new_cff_index( &fd_index, stream, 0 );
+      if (error) goto Exit;
+      
+      if (fd_index.count > CFF_MAX_CID_FONTS)
       {
-        CFF_Private*  priv = &font->private_dict;
-
-
-        /* set defaults */
-        priv->blue_shift       = 7;
-        priv->blue_fuzz        = 1;
-        priv->lenIV            = -1;
-        priv->expansion_factor = (FT_Fixed)0.06 * 0x10000L;
-        priv->blue_scale       = (FT_Fixed)0.039625 * 0x10000L;
-
-        T2_Parser_Init( &parser, T2CODE_PRIVATE, priv );
-
-        if ( FILE_Seek( base_offset + font->top_dict.private_offset ) ||
-             ACCESS_Frame( font->top_dict.private_size )               )
-          goto Exit;
-
-        error = T2_Parser_Run( &parser,
-                               (FT_Byte*)stream->cursor,
-                               (FT_Byte*)stream->limit );
-        FORGET_Frame();
-        if ( error )
-          goto Exit;
+        FT_ERROR(( "T2_Load_CFF_Font: FD array too large in CID font\n" ));
+        goto Fail_CID;
       }
+      
+      /* allocate & read each font dict independently */
+      font->num_subfonts = fd_index.count;
+      if ( ALLOC_ARRAY( sub, fd_index.count, CFF_SubFont ) )
+        goto Fail_CID;
 
-      /* read the charstrings index now */
-      if ( font->top_dict.charstrings_offset == 0 )
+      /* setup pointer table */
+      for ( index = 0; index < fd_index.count; index++ )
+        font->subfonts[index] = sub + index;
+        
+      /* now load each sub font independently */
+      for ( index = 0; index < fd_index.count; index++ )
       {
-        FT_ERROR(( "T2_Load_CFF_Font: no charstrings offset!\n" ));
-        error = FT_Err_Unknown_File_Format;
-        goto Exit;
+        sub = font->subfonts[index];
+        error = CFF_Load_SubFont( sub, &fd_index, index, stream, base_offset );
+        if (error) goto Fail_CID;
       }
 
-      if ( FILE_Seek( base_offset + font->top_dict.charstrings_offset ) )
-        goto Exit;
+      /* now load the FD Select array */
+      error = CFF_Load_FD_Select( &font->fd_select,
+                                  dict->cid_count,
+                                  stream,
+                                  base_offset + dict->cid_fd_select_offset );
 
-      error = t2_new_cff_index( &font->charstrings_index, stream, 0 );
-      if ( error )
+   Fail_CID:
+      t2_done_cff_index( &fd_index );
+      
+      if (error)
         goto Exit;
+    }
+    else
+      font->num_subfonts = 0;
 
-      /* read the local subrs, if any */
+    /* read the charstrings index now */
+    if ( dict->charstrings_offset == 0 )
+    {
+      FT_ERROR(( "T2_Load_CFF_Font: no charstrings offset!\n" ));
+      error = FT_Err_Unknown_File_Format;
+      goto Exit;
+    }
 
-      if ( font->private_dict.local_subrs_offset )
-      {
-        if ( FILE_Seek( base_offset + font->top_dict.private_offset +
-                        font->private_dict.local_subrs_offset ) )
-          goto Exit;
+    if ( FILE_Seek( base_offset + dict->charstrings_offset ) )
+      goto Exit;
 
-        error = t2_new_cff_index( &font->local_subrs_index, stream, 1 );
-        if ( error )
-          goto Exit;
-      }
+    error = t2_new_cff_index( &font->charstrings_index, stream, 0 );
+    if ( error )
+      goto Exit;
 
-      /* explicit the global and local subrs */
+    /* explicit the global subrs */
+    font->num_global_subrs = font->global_subrs_index.count;
+    font->num_glyphs       = font->charstrings_index.count;
 
-      if ( font->private_dict.local_subrs_offset )
-        font->num_local_subrs = font->local_subrs_index.count;
-      else
-        font->num_local_subrs = 0;
+    error = t2_explicit_cff_index( &font->global_subrs_index,
+                                   &font->global_subrs ) ;
 
-      font->num_global_subrs = font->global_subrs_index.count;
+    if ( error )
+      goto Exit;
 
-      error = t2_explicit_cff_index( &font->global_subrs_index,
-                                     &font->global_subrs ) ;
-
-      if ( font->private_dict.local_subrs_offset )
-        error |= t2_explicit_cff_index( &font->local_subrs_index,
-                                        &font->local_subrs ) ;
-
-      if ( error )
-        goto Exit;
-    }
-
     /* get the font name */
     font->font_name = T2_Get_Name( &font->name_index, face_index );
 
@@ -492,19 +712,28 @@
   }
 
 
+
+
   LOCAL_FUNC
   void  T2_Done_CFF_Font( CFF_Font*  font )
   {
     FT_Memory  memory = font->memory;
+    FT_UInt    index;
 
-
     t2_done_cff_index( &font->global_subrs_index );
     t2_done_cff_index( &font->string_index );
-    t2_done_cff_index( &font->top_dict_index );
+    t2_done_cff_index( &font->font_dict_index );
     t2_done_cff_index( &font->name_index );
     t2_done_cff_index( &font->charstrings_index );
-
-    FREE( font->local_subrs );
+    
+    /* release font dictionaries */
+    for ( index = 0; index < font->num_subfonts; index++ )
+      CFF_Done_SubFont( memory, font->subfonts[index] );
+    
+    CFF_Done_SubFont( memory, &font->top_font );
+    
+    CFF_Done_FD_Select( &font->fd_select, font->stream );
+    
     FREE( font->global_subrs );
     FREE( font->font_name );
   }
--- a/src/cff/t2load.h
+++ b/src/cff/t2load.h
@@ -56,6 +56,10 @@
   LOCAL_DEF
   void  T2_Done_CFF_Font( CFF_Font*  font );
 
+  LOCAL_DEF
+  FT_Byte  CFF_Get_FD( CFF_FD_Select*  select,
+                       FT_UInt         glyph_index );
+
 
 #ifdef __cplusplus
   }
--- a/src/cff/t2objs.c
+++ b/src/cff/t2objs.c
@@ -198,6 +198,7 @@
 #ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
     return TT_Init_Extensions( driver );
 #else
+    UNUSED(driver);
     return T2_Err_Ok;
 #endif
   }
@@ -220,6 +221,8 @@
     /* destroy extensions registry if needed */
 #ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
     TT_Done_Extensions( driver );
+#else
+    UNUSED(driver);    
 #endif
   }
 
--- a/src/cff/t2parse.c
+++ b/src/cff/t2parse.c
@@ -279,7 +279,7 @@
   static
   FT_Error  parse_font_matrix( T2_Parser*  parser )
   {
-    CFF_Top_Dict*  dict   = (CFF_Top_Dict*)parser->object;
+    CFF_Font_Dict*  dict   = (CFF_Font_Dict*)parser->object;
     FT_Matrix*     matrix = &dict->font_matrix;
     FT_Byte**      data   = parser->stack;
     FT_Error       error;
@@ -303,7 +303,7 @@
   static
   FT_Error  parse_font_bbox( T2_Parser*  parser )
   {
-    CFF_Top_Dict*  dict   = (CFF_Top_Dict*)parser->object;
+    CFF_Font_Dict*  dict   = (CFF_Font_Dict*)parser->object;
     FT_BBox*       bbox   = &dict->font_bbox;
     FT_Byte**      data   = parser->stack;
     FT_Error       error;
@@ -327,7 +327,7 @@
   static
   FT_Error  parse_private_dict( T2_Parser*  parser )
   {
-    CFF_Top_Dict*  dict = (CFF_Top_Dict*)parser->object;
+    CFF_Font_Dict*  dict = (CFF_Font_Dict*)parser->object;
     FT_Byte**      data = parser->stack;
     FT_Error       error;
 
@@ -348,7 +348,7 @@
   static
   FT_Error  parse_cid_ros( T2_Parser*  parser )
   {
-    CFF_Top_Dict*  dict   = (CFF_Top_Dict*)parser->object;
+    CFF_Font_Dict*  dict   = (CFF_Font_Dict*)parser->object;
     FT_Byte**      data   = parser->stack;
     FT_Error       error;
 
@@ -395,7 +395,7 @@
             code | T2CODE,                           \
             (FT_UInt)(char*)&T2_REF( T2TYPE, name ), \
             sizeof( T2_REF( T2TYPE, name ) ),        \
-            0                                        \
+            0, 0, 0                               \
           },
 
 #undef  T2_FIELD_DELTA
@@ -478,7 +478,7 @@
         /* and look for it in our current list.                            */
 
         FT_UInt                  code;
-        FT_Int                   num_args = parser->top - parser->stack;
+        FT_UInt                   num_args = (FT_UInt)(parser->top - parser->stack);
         const T2_Field_Handler*  field;
 
 
@@ -498,7 +498,7 @@
 
         for ( field = t2_field_handlers; field->kind; field++ )
         {
-          if ( field->code == code )
+          if ( field->code == (FT_Int)code )
           {
             /* we found our field's handler; read it */
             FT_Long   val;
--- a/src/cff/t2tokens.h
+++ b/src/cff/t2tokens.h
@@ -18,7 +18,7 @@
 
 #undef  T2TYPE
 #undef  T2CODE
-#define T2TYPE  CFF_Top_Dict
+#define T2TYPE  CFF_Font_Dict
 #define T2CODE  T2CODE_TOPDICT
 
   T2_FIELD_STRING  ( 0, version )
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -244,6 +244,9 @@
     FT_Error         error;
     SFNT_Interface*  sfnt = (SFNT_Interface*)face->sfnt;
 
+    UNUSED(face_index);
+    UNUSED(num_params);
+    UNUSED(params);
 
     /* Load tables */
     if ( LOAD_( header )        ||