Improve CFF string (especially glyphname) lookup performance.

We do this by avoiding memory allocation and file I/O.  This is
Savannah patch #7104.

* src/cff/cfftypes.h: Include PS cmaps service and
FT_INTERNAL_POSTSCRIPT_HINTS_H.
(CFF_SubFontRec): Remove `num_local_subrs'.
(CFF_FontRec): Add `num_strings', `strings', and `string_pool'
fields.
Remove `string_index' and `num_global_subrs' fields.
Use real types instead of `void' for `pshinter' and `psnames' fields.

* src/cff/cffload.c: Don't include PS cmaps service.
(cff_index_get_pointers): Add `pool' parameter which allows to
insert an extra NUL character for each String INDEX entry.
(cff_index_get_name): Make it a local function.
(cff_index_get_string): New function.
(cff_subfont_load): Updated.
(cff_font_load): Initialize `num_strings', `strings', and
`string_pool' fields in the `CFF_FontRec' structure.
(cff_index_get_sid_string): Use `cff_index_get_string' instead of
`cff_index_get_name'.
(cff_font_done): Updated.

* src/cff/cffload.h: Don't include PS cmaps service.
(cff_index_get_string): Added.
(cff_index_get_sid_string): Updated.

* src/cff/cffobjs.c: Don't include PS cmaps service and
FT_INTERNAL_POSTSCRIPT_HINTS_H.
(cff_size_get_globals_funcs, cff_slot_init): Updated.
(cff_face_init): Follow `cff_index_get_name',
`cff_index_get_string', and `cff_index_get_sid_string' changes.

* src/cff/cffcmap.c (cff_sid_free_glyph_name): Removed.
(cff_sid_to_glyph_name): Use `cff_index_get_cid_string'.
(cff_cmap_unicode_init): Updated.

* src/cff/cffdrivr.c: Don't include PS cmap service.
(cff_get_glyph_name): Avoid unnecessary lookup for POSTSCRIPT_CMAPS
service.
(cff_get_glyph_name, cff_ps_get_font_info, cff_get_ros): Follow API
`cff_index_get_sid_string' change.
(cff_get_name_index): Use `cff_index_get_string' instead of
`cff_index_get_name'.

* src/cff/cffgload.c: Don't include FT_INTERNAL_POSTSCRIPT_HINTS_H.
(cff_decoder_init, cff_decoder_prepare): Updated.
diff --git a/ChangeLog b/ChangeLog
index c0aaa70..e08e996 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,55 @@
+2010-03-02  John Tytgat  <John.Tytgat@esko.com>
+
+	Improve CFF string (especially glyphname) lookup performance.
+
+	We do this by avoiding memory allocation and file I/O.  This is
+	Savannah patch #7104.
+
+	* src/cff/cfftypes.h: Include PS cmaps service and
+	FT_INTERNAL_POSTSCRIPT_HINTS_H.
+	(CFF_SubFontRec): Remove `num_local_subrs'.
+	(CFF_FontRec): Add `num_strings', `strings', and `string_pool'
+	fields.
+	Remove `string_index' and `num_global_subrs' fields.
+	Use real types instead of `void' for `pshinter' and `psnames' fields.
+
+	* src/cff/cffload.c: Don't include PS cmaps service.
+	(cff_index_get_pointers): Add `pool' parameter which allows to
+	insert an extra NUL character for each String INDEX entry.
+	(cff_index_get_name): Make it a local function.
+	(cff_index_get_string): New function.
+	(cff_subfont_load): Updated.
+	(cff_font_load): Initialize `num_strings', `strings', and
+	`string_pool' fields in the `CFF_FontRec' structure.
+	(cff_index_get_sid_string): Use `cff_index_get_string' instead of
+	`cff_index_get_name'.
+	(cff_font_done): Updated.
+
+	* src/cff/cffload.h: Don't include PS cmaps service.
+	(cff_index_get_string): Added.
+	(cff_index_get_sid_string): Updated.
+
+	* src/cff/cffobjs.c: Don't include PS cmaps service and
+	FT_INTERNAL_POSTSCRIPT_HINTS_H.
+	(cff_size_get_globals_funcs, cff_slot_init): Updated.
+	(cff_face_init): Follow `cff_index_get_name',
+	`cff_index_get_string', and `cff_index_get_sid_string' changes.
+
+	* src/cff/cffcmap.c (cff_sid_free_glyph_name): Removed.
+	(cff_sid_to_glyph_name): Use `cff_index_get_cid_string'.
+	(cff_cmap_unicode_init): Updated.
+
+	* src/cff/cffdrivr.c: Don't include PS cmap service.
+	(cff_get_glyph_name): Avoid unnecessary lookup for POSTSCRIPT_CMAPS
+	service.
+	(cff_get_glyph_name, cff_ps_get_font_info, cff_get_ros): Follow API
+	`cff_index_get_sid_string' change.
+	(cff_get_name_index): Use `cff_index_get_string' instead of
+	`cff_index_get_name'.
+
+	* src/cff/cffgload.c: Don't include FT_INTERNAL_POSTSCRIPT_HINTS_H.
+	(cff_decoder_init, cff_decoder_prepare): Updated.
+
 2010-02-27  Werner Lemberg  <wl@gnu.org>
 
 	Simplify code.
diff --git a/src/cff/cffcmap.c b/src/cff/cffcmap.c
index 46d603e..6a98907 100644
--- a/src/cff/cffcmap.c
+++ b/src/cff/cffcmap.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    CFF character mapping table (cmap) support (body).                   */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2004, 2005, 2006, 2007 by                        */
+/*  Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2010 by                  */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -120,27 +120,15 @@
   /*************************************************************************/
 
   FT_CALLBACK_DEF( const char* )
-  cff_sid_to_glyph_name( TT_Face   face,
-                         FT_UInt   idx )
+  cff_sid_to_glyph_name( TT_Face  face,
+                         FT_UInt  idx )
   {
-    CFF_Font            cff     = (CFF_Font)face->extra.data;
-    CFF_Charset         charset = &cff->charset;
-    FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)cff->psnames;
-    FT_UInt             sid     = charset->sids[idx];
+    CFF_Font     cff     = (CFF_Font)face->extra.data;
+    CFF_Charset  charset = &cff->charset;
+    FT_UInt      sid     = charset->sids[idx];
 
 
-    return cff_index_get_sid_string( &cff->string_index, sid, psnames );
-  }
-
-
-  FT_CALLBACK_DEF( void )
-  cff_sid_free_glyph_name( TT_Face      face,
-                           const char*  gname )
-  {
-    FT_Memory  memory = FT_FACE_MEMORY( face );
-
-
-    FT_FREE( gname );
+    return cff_index_get_sid_string( cff, sid );
   }
 
 
@@ -162,7 +150,7 @@
                                    unicodes,
                                    cff->num_glyphs,
                                    (PS_GetGlyphNameFunc)&cff_sid_to_glyph_name,
-                                   (PS_FreeGlyphNameFunc)&cff_sid_free_glyph_name,
+                                   (PS_FreeGlyphNameFunc)NULL,
                                    (FT_Pointer)face );
   }
 
diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c
index dad0b65..3885eea 100644
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -4,7 +4,8 @@
 /*                                                                         */
 /*    OpenType font driver implementation (body).                          */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
+/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
+/*            2010 by                                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -22,7 +23,6 @@
 #include FT_INTERNAL_STREAM_H
 #include FT_INTERNAL_SFNT_H
 #include FT_SERVICE_CID_H
-#include FT_SERVICE_POSTSCRIPT_CMAPS_H
 #include FT_SERVICE_POSTSCRIPT_INFO_H
 #include FT_SERVICE_POSTSCRIPT_NAME_H
 #include FT_SERVICE_TT_CMAP_H
@@ -228,16 +228,13 @@
                       FT_Pointer  buffer,
                       FT_UInt     buffer_max )
   {
-    CFF_Font            font   = (CFF_Font)face->extra.data;
-    FT_Memory           memory = FT_FACE_MEMORY( face );
-    FT_String*          gname;
-    FT_UShort           sid;
-    FT_Service_PsCMaps  psnames;
-    FT_Error            error;
+    CFF_Font    font   = (CFF_Font)face->extra.data;
+    FT_String*  gname;
+    FT_UShort   sid;
+    FT_Error    error;
 
 
-    FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
-    if ( !psnames )
+    if ( !font->psnames )
     {
       FT_ERROR(( "cff_get_glyph_name:"
                  " cannot get glyph name from CFF & CEF fonts\n"
@@ -251,12 +248,11 @@
     sid = font->charset.sids[glyph_index];
 
     /* now, lookup the name itself */
-    gname = cff_index_get_sid_string( &font->string_index, sid, psnames );
+    gname = cff_index_get_sid_string( font, sid );
 
     if ( gname )
       FT_STRCPYN( buffer, gname, buffer_max );
 
-    FT_FREE( gname );
     error = CFF_Err_Ok;
 
   Exit:
@@ -271,11 +267,9 @@
     CFF_Font            cff;
     CFF_Charset         charset;
     FT_Service_PsCMaps  psnames;
-    FT_Memory           memory = FT_FACE_MEMORY( face );
     FT_String*          name;
     FT_UShort           sid;
     FT_UInt             i;
-    FT_Int              result;
 
 
     cff     = (CFF_FontRec *)face->extra.data;
@@ -290,19 +284,14 @@
       sid = charset->sids[i];
 
       if ( sid > 390 )
-        name = cff_index_get_name( &cff->string_index, sid - 391 );
+        name = cff_index_get_string( cff, sid - 391 );
       else
         name = (FT_String *)psnames->adobe_std_strings( sid );
 
       if ( !name )
         continue;
 
-      result = ft_strcmp( glyph_name, name );
-
-      if ( sid > 390 )
-        FT_FREE( name );
-
-      if ( !result )
+      if ( !ft_strcmp( glyph_name, name ) )
         return i;
     }
 
@@ -338,30 +327,24 @@
 
     if ( cff && cff->font_info == NULL )
     {
-      CFF_FontRecDict     dict    = &cff->top_font.font_dict;
-      PS_FontInfoRec     *font_info;
-      FT_Memory           memory  = face->root.memory;
-      FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)cff->psnames;
+      CFF_FontRecDict  dict   = &cff->top_font.font_dict;
+      PS_FontInfoRec  *font_info;
+      FT_Memory        memory = face->root.memory;
 
 
       if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) )
         goto Fail;
 
-      font_info->version     = cff_index_get_sid_string( &cff->string_index,
-                                                         dict->version,
-                                                         psnames );
-      font_info->notice      = cff_index_get_sid_string( &cff->string_index,
-                                                         dict->notice,
-                                                         psnames );
-      font_info->full_name   = cff_index_get_sid_string( &cff->string_index,
-                                                         dict->full_name,
-                                                         psnames );
-      font_info->family_name = cff_index_get_sid_string( &cff->string_index,
-                                                         dict->family_name,
-                                                         psnames );
-      font_info->weight      = cff_index_get_sid_string( &cff->string_index,
-                                                         dict->weight,
-                                                         psnames );
+      font_info->version     = cff_index_get_sid_string( cff,
+                                                         dict->version );
+      font_info->notice      = cff_index_get_sid_string( cff,
+                                                         dict->notice );
+      font_info->full_name   = cff_index_get_sid_string( cff,
+                                                         dict->full_name );
+      font_info->family_name = cff_index_get_sid_string( cff,
+                                                         dict->family_name );
+      font_info->weight      = cff_index_get_sid_string( cff,
+                                                         dict->weight );
       font_info->italic_angle        = dict->italic_angle;
       font_info->is_fixed_pitch      = dict->is_fixed_pitch;
       font_info->underline_position  = (FT_Short)dict->underline_position;
@@ -467,8 +450,7 @@
 
     if ( cff )
     {
-      CFF_FontRecDict     dict    = &cff->top_font.font_dict;
-      FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)cff->psnames;
+      CFF_FontRecDict  dict = &cff->top_font.font_dict;
 
 
       if ( dict->cid_registry == 0xFFFFU )
@@ -480,18 +462,16 @@
       if ( registry )
       {
         if ( cff->registry == NULL )
-          cff->registry = cff_index_get_sid_string( &cff->string_index,
-                                                    dict->cid_registry,
-                                                    psnames );
+          cff->registry = cff_index_get_sid_string( cff,
+                                                    dict->cid_registry );
         *registry = cff->registry;
       }
       
       if ( ordering )
       {
         if ( cff->ordering == NULL )
-          cff->ordering = cff_index_get_sid_string( &cff->string_index,
-                                                    dict->cid_ordering,
-                                                    psnames );
+          cff->ordering = cff_index_get_sid_string( cff,
+                                                    dict->cid_ordering );
         *ordering = cff->ordering;
       }
 
diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c
index 9330c05..f241bb4 100644
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -22,7 +22,6 @@
 #include FT_INTERNAL_STREAM_H
 #include FT_INTERNAL_SFNT_H
 #include FT_OUTLINE_H
-#include FT_INTERNAL_POSTSCRIPT_HINTS_H
 
 #include "cffobjs.h"
 #include "cffload.h"
@@ -394,7 +393,7 @@
 
     /* initialize Type2 decoder */
     decoder->cff          = cff;
-    decoder->num_globals  = cff->num_global_subrs;
+    decoder->num_globals  = cff->global_subrs_index.count;
     decoder->globals      = cff->global_subrs;
     decoder->globals_bias = cff_compute_bias(
                               cff->top_font.font_dict.charstring_type,
@@ -448,7 +447,7 @@
       FT_TRACE4(( "glyph index %d:\n", glyph_index ));
 #endif
 
-    decoder->num_locals    = sub->num_local_subrs;
+    decoder->num_locals    = sub->local_subrs_index.count;
     decoder->locals        = sub->local_subrs;
     decoder->locals_bias   = cff_compute_bias(
                                decoder->cff->top_font.font_dict.charstring_type,
diff --git a/src/cff/cffload.c b/src/cff/cffload.c
index 64d1395..1d0ec15 100644
--- a/src/cff/cffload.c
+++ b/src/cff/cffload.c
@@ -4,7 +4,8 @@
 /*                                                                         */
 /*    OpenType and CFF data/program tables loader (body).                  */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
+/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
+/*            2010 by                                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -20,7 +21,6 @@
 #include FT_INTERNAL_DEBUG_H
 #include FT_INTERNAL_OBJECTS_H
 #include FT_INTERNAL_STREAM_H
-#include FT_SERVICE_POSTSCRIPT_CMAPS_H
 #include FT_TRUETYPE_TAGS_H
 #include FT_TYPE1_TABLES_H
 
@@ -377,18 +377,21 @@
   }
 
 
-  /* allocate a table containing pointers to an index's elements */
+  /* Allocate a table containing pointers to an index's elements. */
+  /* The `pool' argument makes this function convert the index    */
+  /* entries to C-style strings (this is, NULL-terminated).       */
   static FT_Error
   cff_index_get_pointers( CFF_Index   idx,
-                          FT_Byte***  table )
+                          FT_Byte***  table,
+                          FT_Byte**   pool )
   {
     FT_Error   error  = CFF_Err_Ok;
     FT_Memory  memory = idx->stream->memory;
-    FT_ULong   n, offset, old_offset;
     FT_Byte**  t;
+    FT_Byte*   new_bytes;
 
 
-    *table = 0;
+    *table = NULL;
 
     if ( idx->offsets == NULL )
     {
@@ -397,28 +400,56 @@
         goto Exit;
     }
 
-    if ( idx->count > 0 && !FT_NEW_ARRAY( t, idx->count + 1 ) )
+    if ( idx->count > 0                                        &&
+         !FT_NEW_ARRAY( t, idx->count + 1 )                    &&
+         ( !pool || !FT_ALLOC( new_bytes,
+                               idx->data_size + idx->count ) ) )
     {
-      old_offset = 1;
-      for ( n = 0; n <= idx->count; n++ )
+      FT_ULong  n, cur_offset;
+      FT_ULong  extra = 0;
+      FT_Byte*  org_bytes = idx->bytes;
+
+
+      /* at this point, `idx->offsets' can't be NULL */
+      cur_offset = idx->offsets[0] - 1;
+
+      if ( !pool )
+        t[0] = org_bytes + cur_offset;
+      else
+        t[0] = new_bytes + cur_offset;
+
+      for ( n = 1; n <= idx->count; n++ )
       {
-        /* at this point, `idx->offsets' can't be NULL */
-        offset = idx->offsets[n];
-        if ( !offset )
-          offset = old_offset;
+        FT_ULong  next_offset = idx->offsets[n] - 1;
 
-        /* two sanity checks for invalid offset tables */
-        else if ( offset < old_offset )
-          offset = old_offset;
 
-        else if ( offset - 1 >= idx->data_size && n < idx->count )
-          offset = old_offset;
+        /* empty slot + two sanity checks for invalid offset tables */
+        if ( next_offset == 0                                    ||
+             next_offset < cur_offset                            ||
+             ( next_offset >= idx->data_size && n < idx->count ) )
+          next_offset = cur_offset;
 
-        t[n] = idx->bytes + offset - 1;
+        if ( !pool )
+          t[n] = org_bytes + next_offset;
+        else
+        {
+          t[n] = new_bytes + next_offset + extra;
 
-        old_offset = offset;
+          if ( next_offset != cur_offset )
+          {
+            FT_MEM_COPY( t[n - 1], org_bytes + cur_offset, t[n] - t[n - 1] );
+            t[n][0] = '\0';
+            t[n]   += 1;
+            extra++;
+          }
+        }
+
+        cur_offset = next_offset;
       }
       *table = t;
+
+      if ( pool )
+        *pool = new_bytes;
     }
 
   Exit:
@@ -526,10 +557,12 @@
   }
 
 
-  FT_LOCAL_DEF( FT_String* )
-  cff_index_get_name( CFF_Index  idx,
-                      FT_UInt    element )
+  /* get an entry from Name INDEX */
+  static FT_String*
+  cff_index_get_name( CFF_Font  font,
+                      FT_UInt   element )
   {
+    CFF_Index   idx = &font->name_index;
     FT_Memory   memory = idx->stream->memory;
     FT_Byte*    bytes;
     FT_ULong    byte_len;
@@ -553,42 +586,35 @@
   }
 
 
+  /* get an entry from String INDEX */
   FT_LOCAL_DEF( FT_String* )
-  cff_index_get_sid_string( CFF_Index           idx,
-                            FT_UInt             sid,
-                            FT_Service_PsCMaps  psnames )
+  cff_index_get_string( CFF_Font  font,
+                        FT_UInt   element )
+  {
+    return ( element < font->num_strings )
+             ? (FT_String*)font->strings[element]
+             : NULL;
+  }
+
+
+  FT_LOCAL_DEF( FT_String* )
+  cff_index_get_sid_string( CFF_Font  font,
+                            FT_UInt   sid )
   {
     /* value 0xFFFFU indicates a missing dictionary entry */
     if ( sid == 0xFFFFU )
-      return 0;
+      return NULL;
 
     /* if it is not a standard string, return it */
     if ( sid > 390 )
-      return cff_index_get_name( idx, sid - 391 );
+      return cff_index_get_string( font, sid - 391 );
 
     /* CID-keyed CFF fonts don't have glyph names */
-    if ( !psnames )
-      return 0;
+    if ( !font->psnames )
+      return NULL;
 
-    /* that's a standard string, fetch a copy from the PSName module */
-    {
-      FT_String*   name       = 0;
-      const char*  adobe_name = psnames->adobe_std_strings( sid );
-
-
-      if ( adobe_name )
-      {
-        FT_Memory  memory = idx->stream->memory;
-        FT_Error   error;
-
-
-        (void)FT_STRDUP( name, adobe_name );
-
-        FT_UNUSED( error );
-      }
-
-      return name;
-    }
+    /* this is a standard string */
+    return (FT_String *)font->psnames->adobe_std_strings( sid );
   }
 
 
@@ -1361,9 +1387,8 @@
       if ( error )
         goto Exit;
 
-      font->num_local_subrs = font->local_subrs_index.count;
       error = cff_index_get_pointers( &font->local_subrs_index,
-                                      &font->local_subrs );
+                                      &font->local_subrs, NULL );
       if ( error )
         goto Exit;
     }
@@ -1409,9 +1434,11 @@
     FT_Memory        memory = stream->memory;
     FT_ULong         base_offset;
     CFF_FontRecDict  dict;
+    CFF_IndexRec     string_index;
 
 
     FT_ZERO( font );
+    FT_ZERO( &string_index );
 
     font->stream = stream;
     font->memory = memory;
@@ -1438,15 +1465,20 @@
 
     /* read the name, top dict, string and global subrs index */
     if ( FT_SET_ERROR( cff_index_init( &font->name_index,
-                                       stream, 0 ) )              ||
+                                       stream, 0 ) )                  ||
          FT_SET_ERROR( cff_index_init( &font->font_dict_index,
-                                       stream, 0 ) )              ||
-         FT_SET_ERROR( cff_index_init( &font->string_index,
-                                       stream, 0 ) )              ||
+                                       stream, 0 ) )                  ||
+         FT_SET_ERROR( cff_index_init( &string_index,
+                                       stream, 1 ) )                  ||
          FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
-                                       stream, 1 ) )              )
+                                       stream, 1 ) )                  ||
+         FT_SET_ERROR( cff_index_get_pointers( &string_index,
+                                               &font->strings,
+                                               &font->string_pool ) ) )
       goto Exit;
 
+    font->num_strings = string_index.count;
+
     /* well, we don't really forget the `disabled' fonts... */
     font->num_faces = font->name_index.count;
     if ( face_index >= (FT_Int)font->num_faces )
@@ -1542,12 +1574,10 @@
       goto Exit;
     }
 
-    /* explicit the global subrs */
-    font->num_global_subrs = font->global_subrs_index.count;
-    font->num_glyphs       = font->charstrings_index.count;
+    font->num_glyphs = font->charstrings_index.count;
 
     error = cff_index_get_pointers( &font->global_subrs_index,
-                                    &font->global_subrs ) ;
+                                    &font->global_subrs, NULL );
 
     if ( error )
       goto Exit;
@@ -1579,9 +1609,11 @@
 
     /* get the font name (/CIDFontName for CID-keyed fonts, */
     /* /FontName otherwise)                                 */
-    font->font_name = cff_index_get_name( &font->name_index, face_index );
+    font->font_name = cff_index_get_name( font, face_index );
 
   Exit:
+    cff_index_done( &string_index );
+
     return error;
   }
 
@@ -1594,7 +1626,6 @@
 
 
     cff_index_done( &font->global_subrs_index );
-    cff_index_done( &font->string_index );
     cff_index_done( &font->font_dict_index );
     cff_index_done( &font->name_index );
     cff_index_done( &font->charstrings_index );
@@ -1617,21 +1648,12 @@
 
     CFF_Done_FD_Select( &font->fd_select, font->stream );
 
-    if (font->font_info != NULL)
-    {
-      FT_FREE( font->font_info->version );
-      FT_FREE( font->font_info->notice );
-      FT_FREE( font->font_info->full_name );
-      FT_FREE( font->font_info->family_name );
-      FT_FREE( font->font_info->weight );
-      FT_FREE( font->font_info );
-    }
+    FT_FREE( font->font_info );
 
-    FT_FREE( font->registry );
-    FT_FREE( font->ordering );
-
-    FT_FREE( font->global_subrs );
     FT_FREE( font->font_name );
+    FT_FREE( font->global_subrs );
+    FT_FREE( font->strings );
+    FT_FREE( font->string_pool );
   }
 
 
diff --git a/src/cff/cffload.h b/src/cff/cffload.h
index 2b313ac..4e54eb5 100644
--- a/src/cff/cffload.h
+++ b/src/cff/cffload.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType & CFF data/program tables loader (specification).           */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2007, 2008 by                         */
+/*  Copyright 1996-2001, 2002, 2003, 2007, 2008, 2010 by                   */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -22,7 +22,6 @@
 
 #include <ft2build.h>
 #include "cfftypes.h"
-#include FT_SERVICE_POSTSCRIPT_CMAPS_H
 
 
 FT_BEGIN_HEADER
@@ -32,13 +31,12 @@
 
 
   FT_LOCAL( FT_String* )
-  cff_index_get_name( CFF_Index  idx,
-                      FT_UInt    element );
+  cff_index_get_string( CFF_Font  font,
+                        FT_UInt   element );
 
   FT_LOCAL( FT_String* )
-  cff_index_get_sid_string( CFF_Index          idx,
-                            FT_UInt            sid,
-                            FT_Service_PsCMaps psnames );
+  cff_index_get_sid_string( CFF_Font  font,
+                            FT_UInt   sid );
 
 
   FT_LOCAL( FT_Error )
diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c
index bd56c4b..6a2b8c8 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -4,7 +4,8 @@
 /*                                                                         */
 /*    OpenType objects manager (body).                                     */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */
+/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
+/*            2010 by                                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -24,8 +25,6 @@
 #include FT_TRUETYPE_IDS_H
 #include FT_TRUETYPE_TAGS_H
 #include FT_INTERNAL_SFNT_H
-#include FT_SERVICE_POSTSCRIPT_CMAPS_H
-#include FT_INTERNAL_POSTSCRIPT_HINTS_H
 #include "cffobjs.h"
 #include "cffload.h"
 #include "cffcmap.h"
@@ -58,7 +57,7 @@
   {
     CFF_Face          face     = (CFF_Face)size->root.face;
     CFF_Font          font     = (CFF_Font)face->extra.data;
-    PSHinter_Service  pshinter = (PSHinter_Service)font->pshinter;
+    PSHinter_Service  pshinter = font->pshinter;
     FT_Module         module;
 
 
@@ -349,7 +348,7 @@
   {
     CFF_Face          face     = (CFF_Face)slot->face;
     CFF_Font          font     = (CFF_Font)face->extra.data;
-    PSHinter_Service  pshinter = (PSHinter_Service)font->pshinter;
+    PSHinter_Service  pshinter = font->pshinter;
 
 
     if ( pshinter )
@@ -412,14 +411,6 @@
     FT_Library library = cffface->driver->root.library;
 
 
-#if 0
-    FT_FACE_FIND_GLOBAL_SERVICE( face, sfnt,     SFNT );
-    FT_FACE_FIND_GLOBAL_SERVICE( face, psnames,  POSTSCRIPT_NAMES );
-    FT_FACE_FIND_GLOBAL_SERVICE( face, pshinter, POSTSCRIPT_HINTER );
-
-    if ( !sfnt )
-      goto Bad_Format;
-#else
     sfnt = (SFNT_Service)FT_Get_Module_Interface(
              library, "sfnt" );
     if ( !sfnt )
@@ -429,7 +420,6 @@
 
     pshinter = (PSHinter_Service)FT_Get_Module_Interface(
                  library, "pshinter" );
-#endif
 
     /* create input stream from resource */
     if ( FT_STREAM_SEEK( 0 ) )
@@ -514,7 +504,7 @@
         goto Exit;
 
       cff->pshinter = pshinter;
-      cff->psnames  = (void*)psnames;
+      cff->psnames  = psnames;
 
       cffface->face_index = face_index;
 
@@ -678,24 +668,20 @@
           (FT_Short)( dict->underline_thickness >> 16 );
 
         /* retrieve font family & style name */
-        cffface->family_name = cff_index_get_name( &cff->name_index,
-                                                   face_index );
-
+        cffface->family_name = cff_index_get_name( cff, face_index );
         if ( cffface->family_name )
         {
-          char*  full   = cff_index_get_sid_string( &cff->string_index,
-                                                    dict->full_name,
-                                                    psnames );
+          char*  full   = cff_index_get_sid_string( cff,
+                                                    dict->full_name );
           char*  fullp  = full;
           char*  family = cffface->family_name;
-          char*  family_name = 0;
+          char*  family_name = NULL;
 
 
           if ( dict->family_name )
           {
-            family_name = cff_index_get_sid_string( &cff->string_index,
-                                                    dict->family_name,
-                                                    psnames);
+            family_name = cff_index_get_sid_string( cff,
+                                                    dict->family_name );
             if ( family_name )
               family = family_name;
           }
@@ -738,23 +724,18 @@
               }
               break;
             }
-
-            if ( family_name )
-              FT_FREE( family_name );
-            FT_FREE( full );
           }
         }
         else
         {
           char  *cid_font_name =
-                   cff_index_get_sid_string( &cff->string_index,
-                                             dict->cid_font_name,
-                                             psnames );
+                   cff_index_get_sid_string( cff,
+                                             dict->cid_font_name );
 
 
           /* do we have a `/FontName' for a CID-keyed font? */
           if ( cid_font_name )
-            cffface->family_name = cid_font_name;
+            cffface->family_name = cff_strcpy( memory, cid_font_name );
         }
 
         if ( style_name )
@@ -797,16 +778,14 @@
           flags |= FT_STYLE_FLAG_ITALIC;
 
         {
-          char  *weight = cff_index_get_sid_string( &cff->string_index,
-                                                    dict->weight,
-                                                    psnames );
+          char  *weight = cff_index_get_sid_string( cff,
+                                                    dict->weight );
 
 
           if ( weight )
             if ( !ft_strcmp( weight, "Bold"  ) ||
                  !ft_strcmp( weight, "Black" ) )
               flags |= FT_STYLE_FLAG_BOLD;
-          FT_FREE( weight );
         }
 
         /* double check */
diff --git a/src/cff/cfftypes.h b/src/cff/cfftypes.h
index df92e9a..d405357 100644
--- a/src/cff/cfftypes.h
+++ b/src/cff/cfftypes.h
@@ -5,7 +5,7 @@
 /*    Basic OpenType/CFF type definitions and interface (specification     */
 /*    only).                                                               */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2006, 2007, 2008 by                   */
+/*  Copyright 1996-2001, 2002, 2003, 2006, 2007, 2008, 2010 by             */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -24,6 +24,9 @@
 #include <ft2build.h>
 #include FT_FREETYPE_H
 #include FT_TYPE1_TABLES_H
+#include FT_INTERNAL_SERVICE_H
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+#include FT_INTERNAL_POSTSCRIPT_HINTS_H
 
 
 FT_BEGIN_HEADER
@@ -204,8 +207,7 @@
     CFF_PrivateRec      private_dict;
 
     CFF_IndexRec        local_subrs_index;
-    FT_UInt             num_local_subrs;
-    FT_Byte**           local_subrs;
+    FT_Byte**           local_subrs; /* array of pointers into Local Subrs INDEX data */
 
   } CFF_SubFontRec, *CFF_SubFont;
 
@@ -229,7 +231,6 @@
 
     CFF_IndexRec     name_index;
     CFF_IndexRec     top_dict_index;
-    CFF_IndexRec     string_index;
     CFF_IndexRec     global_subrs_index;
 
     CFF_EncodingRec  encoding;
@@ -241,9 +242,15 @@
     CFF_IndexRec     local_subrs_index;
 
     FT_String*       font_name;
-    FT_UInt          num_global_subrs;
+
+    /* array of pointers into Global Subrs INDEX data */
     FT_Byte**        global_subrs;
 
+    /* array of pointers into String INDEX data stored at string_pool */
+    FT_UInt          num_strings;
+    FT_Byte**        strings;
+    FT_Byte*         string_pool;
+
     CFF_SubFontRec   top_font;
     FT_UInt          num_subfonts;
     CFF_SubFont      subfonts[CFF_MAX_CID_FONTS];
@@ -251,10 +258,10 @@
     CFF_FDSelectRec  fd_select;
 
     /* interface to PostScript hinter */
-    void*            pshinter;
+    PSHinter_Service  pshinter;
 
     /* interface to Postscript Names service */
-    void*            psnames;
+    FT_Service_PsCMaps  psnames;
 
     /* since version 2.3.0 */
     PS_FontInfoRec*  font_info;   /* font info dictionary */