shithub: freetype+ttf2subf

Download patch

ref: 4ba1c0ad6f057987fb378c76e9d9ab4827c016b4
parent: 7fdd1e528ba45d1803c7209eafa90208444ba2e1
author: Tom Kacvinsky <[email protected]>
date: Fri Dec 29 19:37:14 EST 2000

Added tables

    cff_isoadobe_charset
    cff_expert_charset
    cff_expertsubset_charset
    cff_standard_encoding
    cff_expert_encoding

Extended functions CFF_Load_Encoding, CFF_Load_Charset, CFF_Done_Encoding,
and CFF_Done_Charset to load and parse the charset/encoding tables, and
free the memory used by them when FreeType is finished with them.

git/fs: mount .git/fs: mount/attach disallowed
--- a/src/cff/cffload.c
+++ b/src/cff/cffload.c
@@ -27,7 +27,6 @@
 #include FT_SOURCE_FILE(cff,cffload.h)
 #include FT_SOURCE_FILE(cff,cffparse.h)
 
-
   /*************************************************************************/
   /*                                                                       */
   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
@@ -37,7 +36,1022 @@
 #undef  FT_COMPONENT
 #define FT_COMPONENT  trace_t2load
 
+  static const FT_UShort cff_isoadobe_charset[229] =
+  {
+    0,
+    1,
+    2,
+    3,
+    4,
+    5,
+    6,
+    7,
+    8,
+    9,
+    10,
+    11,
+    12,
+    13,
+    14,
+    15,
+    16,
+    17,
+    18,
+    19,
+    20,
+    21,
+    22,
+    23,
+    24,
+    25,
+    26,
+    27,
+    28,
+    29,
+    30,
+    31,
+    32,
+    33,
+    34,
+    35,
+    36,
+    37,
+    38,
+    39,
+    40,
+    41,
+    42,
+    43,
+    44,
+    45,
+    46,
+    47,
+    48,
+    49,
+    50,
+    51,
+    52,
+    53,
+    54,
+    55,
+    56,
+    57,
+    58,
+    59,
+    60,
+    61,
+    62,
+    63,
+    64,
+    65,
+    66,
+    67,
+    68,
+    69,
+    70,
+    71,
+    72,
+    73,
+    74,
+    75,
+    76,
+    77,
+    78,
+    79,
+    80,
+    81,
+    82,
+    83,
+    84,
+    85,
+    86,
+    87,
+    88,
+    89,
+    90,
+    91,
+    92,
+    93,
+    94,
+    95,
+    96,
+    97,
+    98,
+    99,
+    100,
+    101,
+    102,
+    103,
+    104,
+    105,
+    106,
+    107,
+    108,
+    109,
+    110,
+    111,
+    112,
+    113,
+    114,
+    115,
+    116,
+    117,
+    118,
+    119,
+    120,
+    121,
+    122,
+    123,
+    124,
+    125,
+    126,
+    127,
+    128,
+    129,
+    130,
+    131,
+    132,
+    133,
+    134,
+    135,
+    136,
+    137,
+    138,
+    139,
+    140,
+    141,
+    142,
+    143,
+    144,
+    145,
+    146,
+    147,
+    148,
+    149,
+    150,
+    151,
+    152,
+    153,
+    154,
+    155,
+    156,
+    157,
+    158,
+    159,
+    160,
+    161,
+    162,
+    163,
+    164,
+    165,
+    166,
+    167,
+    168,
+    169,
+    170,
+    171,
+    172,
+    173,
+    174,
+    175,
+    176,
+    177,
+    178,
+    179,
+    180,
+    181,
+    182,
+    183,
+    184,
+    185,
+    186,
+    187,
+    188,
+    189,
+    190,
+    191,
+    192,
+    193,
+    194,
+    195,
+    196,
+    197,
+    198,
+    199,
+    200,
+    201,
+    202,
+    203,
+    204,
+    205,
+    206,
+    207,
+    208,
+    209,
+    210,
+    211,
+    212,
+    213,
+    214,
+    215,
+    216,
+    217,
+    218,
+    219,
+    220,
+    221,
+    222,
+    223,
+    224,
+    225,
+    226,
+    227,
+    228
+  };
 
+  static const FT_UShort cff_expert_charset[166] =
+  {
+    0,
+    1,
+    229,
+    230,
+    231,
+    232,
+    233,
+    234,
+    235,
+    236,
+    237,
+    238,
+    13,
+    14,
+    15,
+    99,
+    239,
+    240,
+    241,
+    242,
+    243,
+    244,
+    245,
+    246,
+    247,
+    248,
+    27,
+    28,
+    249,
+    250,
+    251,
+    252,
+    253,
+    254,
+    255,
+    256,
+    257,
+    258,
+    259,
+    260,
+    261,
+    262,
+    263,
+    264,
+    265,
+    266,
+    109,
+    110,
+    267,
+    268,
+    269,
+    270,
+    271,
+    272,
+    273,
+    274,
+    275,
+    276,
+    277,
+    278,
+    279,
+    280,
+    281,
+    282,
+    283,
+    284,
+    285,
+    286,
+    287,
+    288,
+    289,
+    290,
+    291,
+    292,
+    293,
+    294,
+    295,
+    296,
+    297,
+    298,
+    299,
+    300,
+    301,
+    302,
+    303,
+    304,
+    305,
+    306,
+    307,
+    308,
+    309,
+    310,
+    311,
+    312,
+    313,
+    314,
+    315,
+    316,
+    317,
+    318,
+    158,
+    155,
+    163,
+    319,
+    320,
+    321,
+    322,
+    323,
+    324,
+    325,
+    326,
+    150,
+    164,
+    169,
+    327,
+    328,
+    329,
+    330,
+    331,
+    332,
+    333,
+    334,
+    335,
+    336,
+    337,
+    338,
+    339,
+    340,
+    341,
+    342,
+    343,
+    344,
+    345,
+    346,
+    347,
+    348,
+    349,
+    350,
+    351,
+    352,
+    353,
+    354,
+    355,
+    356,
+    357,
+    358,
+    359,
+    360,
+    361,
+    362,
+    363,
+    364,
+    365,
+    366,
+    367,
+    368,
+    369,
+    370,
+    371,
+    372,
+    373,
+    374,
+    375,
+    376,
+    377,
+    378
+  };
+
+  static const FT_UShort cff_expertsubset_charset[87] =
+  {
+    0,
+    1,
+    231,
+    232,
+    235,
+    236,
+    237,
+    238,
+    13,
+    14,
+    15,
+    99,
+    239,
+    240,
+    241,
+    242,
+    243,
+    244,
+    245,
+    246,
+    247,
+    248,
+    27,
+    28,
+    249,
+    250,
+    251,
+    253,
+    254,
+    255,
+    256,
+    257,
+    258,
+    259,
+    260,
+    261,
+    262,
+    263,
+    264,
+    265,
+    266,
+    109,
+    110,
+    267,
+    268,
+    269,
+    270,
+    272,
+    300,
+    301,
+    302,
+    305,
+    314,
+    315,
+    158,
+    155,
+    163,
+    320,
+    321,
+    322,
+    323,
+    324,
+    325,
+    326,
+    150,
+    164,
+    169,
+    327,
+    328,
+    329,
+    330,
+    331,
+    332,
+    333,
+    334,
+    335,
+    336,
+    337,
+    338,
+    339,
+    340,
+    341,
+    342,
+    343,
+    344,
+    345,
+    346
+  };
+
+  static const FT_UShort cff_standard_encoding[256] =
+  {
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    1,
+    2,
+    3,
+    4,
+    5,
+    6,
+    7,
+    8,
+    9,
+    10,
+    11,
+    12,
+    13,
+    14,
+    15,
+    16,
+    17,
+    18,
+    19,
+    20,
+    21,
+    22,
+    23,
+    24,
+    25,
+    26,
+    27,
+    28,
+    29,
+    30,
+    31,
+    32,
+    33,
+    34,
+    35,
+    36,
+    37,
+    38,
+    39,
+    40,
+    41,
+    42,
+    43,
+    44,
+    45,
+    46,
+    47,
+    48,
+    49,
+    50,
+    51,
+    52,
+    53,
+    54,
+    55,
+    56,
+    57,
+    58,
+    59,
+    60,
+    61,
+    62,
+    63,
+    64,
+    65,
+    66,
+    67,
+    68,
+    69,
+    70,
+    71,
+    72,
+    73,
+    74,
+    75,
+    76,
+    77,
+    78,
+    79,
+    80,
+    81,
+    82,
+    83,
+    84,
+    85,
+    86,
+    87,
+    88,
+    89,
+    90,
+    91,
+    92,
+    93,
+    94,
+    95,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    96,
+    97,
+    98,
+    99,
+    100,
+    101,
+    102,
+    103,
+    104,
+    105,
+    106,
+    107,
+    108,
+    109,
+    110,
+    0,
+    111,
+    112,
+    113,
+    114,
+    0,
+    115,
+    116,
+    117,
+    118,
+    119,
+    120,
+    121,
+    122,
+    0,
+    123,
+    0,
+    124,
+    125,
+    126,
+    127,
+    128,
+    129,
+    130,
+    131,
+    0,
+    132,
+    133,
+    0,
+    134,
+    135,
+    136,
+    137,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    138,
+    0,
+    139,
+    0,
+    0,
+    0,
+    0,
+    140,
+    141,
+    142,
+    143,
+    0,
+    0,
+    0,
+    0,
+    0,
+    144,
+    0,
+    0,
+    0,
+    145,
+    0,
+    0,
+    146,
+    147,
+    148,
+    149,
+    0,
+    0,
+    0,
+    0
+  };
+
+
+  static const FT_UShort cff_expert_encoding[256] =
+  {
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    1,
+    229,
+    230,
+    0,
+    231,
+    232,
+    233,
+    234,
+    235,
+    236,
+    237,
+    238,
+    13,
+    14,
+    15,
+    99,
+    239,
+    240,
+    241,
+    242,
+    243,
+    244,
+    245,
+    246,
+    247,
+    248,
+    27,
+    28,
+    249,
+    250,
+    251,
+    252,
+    0,
+    253,
+    254,
+    255,
+    256,
+    257,
+    0,
+    0,
+    0,
+    258,
+    0,
+    0,
+    259,
+    260,
+    261,
+    262,
+    0,
+    0,
+    263,
+    264,
+    265,
+    0,
+    266,
+    109,
+    110,
+    267,
+    268,
+    269,
+    0,
+    270,
+    271,
+    272,
+    273,
+    274,
+    275,
+    276,
+    277,
+    278,
+    279,
+    280,
+    281,
+    282,
+    283,
+    284,
+    285,
+    286,
+    287,
+    288,
+    289,
+    290,
+    291,
+    292,
+    293,
+    294,
+    295,
+    296,
+    297,
+    298,
+    299,
+    300,
+    301,
+    302,
+    303,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    304,
+    305,
+    306,
+    0,
+    0,
+    307,
+    308,
+    309,
+    310,
+    311,
+    0,
+    312,
+    0,
+    0,
+    312,
+    0,
+    0,
+    314,
+    315,
+    0,
+    0,
+    316,
+    317,
+    318,
+    0,
+    0,
+    0,
+    158,
+    155,
+    163,
+    319,
+    320,
+    321,
+    322,
+    323,
+    324,
+    325,
+    0,
+    0,
+    326,
+    150,
+    164,
+    169,
+    327,
+    328,
+    329,
+    330,
+    331,
+    332,
+    333,
+    334,
+    335,
+    336,
+    337,
+    338,
+    339,
+    340,
+    341,
+    342,
+    343,
+    344,
+    345,
+    346,
+    347,
+    348,
+    349,
+    350,
+    351,
+    352,
+    353,
+    354,
+    355,
+    356,
+    357,
+    358,
+    359,
+    360,
+    361,
+    362,
+    363,
+    364,
+    365,
+    366,
+    367,
+    368,
+    369,
+    370,
+    371,
+    372,
+    373,
+    374,
+    375,
+    376,
+    377,
+    378
+  };
+
+
   /* read a CFF offset from memory */
   static
   FT_ULong  cff_get_offset( FT_Byte*  p,
@@ -463,10 +1477,12 @@
     FT_Memory  memory = stream->memory;
 
 
-    FREE( encoding->bytes );
+    FREE( encoding->codes );
+    FREE( encoding->sids  );
     encoding->format = 0;
-    encoding->size   = 0;
     encoding->offset = 0;
+    encoding->codes  = 0;
+    encoding->sids   = 0;
   }
 
 
@@ -476,78 +1492,90 @@
   {
     FT_Memory  memory = stream->memory;
 
-
-    FREE( charset->bytes );
+    FREE( charset->sids );
     charset->format = 0;
     charset->offset = 0;
-    charset->size   = 0;
+    charset->sids   = 0;
   }
 
-
   static
-  FT_Error  CFF_Load_Charset( CFF_Charset*   charset,
-                              FT_UInt        num_glyphs,
-                              FT_Stream      stream,
-                              FT_ULong       base_offset,
-                              FT_ULong       offset )
+  FT_Error  CFF_Load_Charset( CFF_Charset*  charset,
+                              FT_UInt       num_glyphs,
+                              FT_Stream     stream,
+                              FT_ULong      base_offset,
+                              FT_ULong      offset )
   {
-    FT_Error   error  = 0;
-    FT_Memory  memory = stream->memory;
+    FT_Memory   memory     = stream->memory;
+    FT_Error    error      = 0;
+    FT_UShort   glyph_sid;
 
+    charset->offset = base_offset + offset;
 
+    /* Get the format of the table. */
+    if ( FILE_Seek( charset->offset ) ||
+         READ_Byte( charset->format ) )
+      goto Exit;
+
+    /* If the the offset is greater than 2, we have to parse the */
+    /* charset table.                                            */
     if ( offset > 2 )
     {
-      FT_ULong  size = 1;
+      FT_UInt  j;
 
-
-      charset->offset = base_offset + offset;
-
-      /* we need to parse the table to determine its size */
-      if ( FILE_Seek( charset->offset ) ||
-           READ_Byte( charset->format ) )
+      /* Allocate memory for sids. */
+      if ( ALLOC( charset->sids, num_glyphs * sizeof( FT_UShort ) ) )
         goto Exit;
 
+      /* assign the .notdef glyph */
+      charset->sids[0] = 0;
+
       switch ( charset->format )
       {
       case 0:
-        size += 2 * ( num_glyphs - 1 );
-        break;
 
-      case 1:
+        for ( j = 1; j < num_glyphs; j++ )
         {
-          FT_UInt  glyph, nleft;
+          if ( READ_UShort( glyph_sid ) )
+            goto Exit;
 
-
-          num_glyphs--;
-          while ( num_glyphs > 0 )
-          {
-            if ( READ_UShort( glyph ) ||
-                 READ_Byte( nleft )   )
-              goto Exit;
-
-            size += 3;
-            num_glyphs -= 1 + nleft;
-          }
-          break;
+          charset->sids[j] = glyph_sid;
         }
+        break;
 
+      case 1:
       case 2:
         {
-          FT_UInt  glyph, nleft;
+          FT_UInt  nleft;
+          FT_UInt  i;
 
+          j = 1;
 
-          num_glyphs--;
-          while ( num_glyphs > 0 )
+          while ( j < num_glyphs )
           {
-            if ( READ_UShort( glyph ) ||
-                 READ_UShort( nleft ) )
+
+            /* Read the first glyph sid of the range. */
+            if ( READ_UShort( glyph_sid ) )
               goto Exit;
 
-            size += 4;
-            num_glyphs -= 1 + nleft;
+            /* Read the number of glyphs in the range.  */
+            if ( charset->format == 2 )
+            {
+              if ( READ_UShort( nleft ) )
+                goto Exit;
+            }
+            else
+            {
+              if ( READ_Byte( nleft ) )
+                goto Exit;
+            }
+
+            /* Fill in the range of sids -- `nleft + 1' glyphs. */
+            for ( i = 0; i <= nleft; i++, j++, glyph_sid++ )
+              charset->sids[j] = glyph_sid;
+
           }
-          break;
         }
+        break;
 
       default:
         FT_ERROR(( "CFF_Load_Charset: invalid table format!\n" ));
@@ -555,40 +1583,155 @@
         goto Exit;
       }
 
-      charset->size = size;
+    }
+    else
+    {
 
-      if ( ALLOC( charset->bytes, size )     ||
-           FILE_Seek( charset->offset  )     ||
-           FILE_Read( charset->bytes, size ) )
+      /* Parse default tables corresponding to offset == 0, 1, or 2.  */
+      /* CFF specification intimates the following:                   */
+      /*                                                              */
+      /* In order to use a predefined charset, the following must be  */
+      /* true: the charset constructed for the glyphs in the font's   */
+      /* charstrings dictionary must match the predefined charset in  */
+      /* the first num_glyphs, and hence must match the predefined    */
+      /* charset *exactly*.                                           */
+
+      switch ( offset )
+      {
+
+      case 0:
+
+        if ( num_glyphs != 229 )
+        {
+          FT_ERROR(("CFF_Load_Charset: implicit charset not equal to predefined charset!\n" ));
+          error = FT_Err_Invalid_File_Format;
+          goto Exit;
+        }
+
+        /* Allocate memory for sids. */
+        if ( ALLOC( charset->sids, num_glyphs * sizeof( FT_UShort ) ) )
+          goto Exit;
+
+        /* Copy the predefined charset into the allocated memory.     */
+        MEM_Copy( charset->sids, cff_isoadobe_charset, 
+                   num_glyphs * sizeof( FT_UShort ) );
+
+        break;
+
+      case 1:
+
+        if ( num_glyphs != 166 )
+        {
+          FT_ERROR(( "CFF_Load_Charset: implicit charset not equal to predefined charset!\n" ));
+          error = FT_Err_Invalid_File_Format;
+          goto Exit;
+        }
+
+        /* Allocate memory for sids. */
+        if ( ALLOC( charset->sids, num_glyphs * sizeof( FT_UShort ) ) )
+          goto Exit;
+
+        /* Copy the predefined charset into the allocated memory.     */
+        MEM_Copy( charset->sids, cff_expert_charset,
+                  num_glyphs * sizeof( FT_UShort ) );
+
+        break;
+
+      case 2:
+
+        if ( num_glyphs != 87 )
+        {
+          FT_ERROR(( "CFF_Load_Charset: implicit charset not equal to predefined charset!\n" ));
+          error = FT_Err_Invalid_File_Format;
+          goto Exit;
+        }
+
+        /* Allocate memory for sids. */
+        if ( ALLOC( charset->sids, num_glyphs * sizeof( FT_UShort ) ) )
+          goto Exit;
+
+        /* Copy the predefined charset into the allocated memory.     */
+        MEM_Copy( charset->sids, cff_expertsubset_charset,
+                  num_glyphs * sizeof( FT_UShort ) );
+
+        break;
+
+      default:
+
+        error = FT_Err_Invalid_File_Format;
         goto Exit;
+
+      }
     }
-    else
-      charset->offset = offset;
 
   Exit:
+
+    /* Clean up if there was an error. */
+    if ( error )
+      if ( charset->sids )
+      {
+        FT_Memory  memory = stream->memory;
+
+        if ( charset->sids )
+          FREE( charset->sids );
+        charset->format = 0;
+        charset->offset = 0;
+        charset->sids   = 0;
+      }
+
     return error;
   }
 
-
   static
   FT_Error  CFF_Load_Encoding( CFF_Encoding*  encoding,
+                               CFF_Charset*   charset,
                                FT_UInt        num_glyphs,
                                FT_Stream      stream,
                                FT_ULong       base_offset,
                                FT_ULong       offset )
   {
-    FT_Error  error  = 0;
-    FT_Memory memory = stream->memory;
-    FT_UInt   count;
+    FT_Memory   memory      = stream->memory;
+    FT_Error    error       = 0;
+    FT_UInt     count;
+    FT_UInt     j;
+    FT_UShort   glyph_sid;
+    FT_Byte     glyph_code;
 
-    FT_UNUSED( num_glyphs );
+    /* Check for charset->sids.  If we do not have this, we fail.         */
+    if ( !charset->sids )
+    {
+      error = FT_Err_Invalid_File_Format;
+      goto Exit;
+    }
 
+    /* Allocate memory for sids/codes -- there are at most 256 sids/codes */
+    /* for an encoding.                                                   */
+    if ( ALLOC( encoding->sids,  256 * sizeof( FT_UShort ) ) ||
+         ALLOC( encoding->codes, 256 * sizeof( FT_UShort ) ) )
+      goto Exit;
 
-    if ( offset > 2 )
+    /* Zero out the code to gid/sid mappings.                             */
+    for ( j = 0; j < 255; j++ )
     {
-      FT_ULong  size = 1;
+      encoding->sids [j] = 0;
+      encoding->codes[j] = 0;
+    }
 
+    /* Note:  the encoding table in a CFF font is indexed by glyph index, */
+    /* where the first encoded glyph index is 1.  Hence, we read the char */
+    /* code (`glyph_code') at index j and make the assignment:            */
+    /*                                                                    */
+    /*    encoding->codes[glyph_code] = j + 1                             */
+    /*                                                                    */
+    /* We also make the assignment:                                       */
+    /*                                                                    */
+    /*    encoding->sids[glyph_code] = charset->sids[j + 1]               */
+    /*                                                                    */
+    /* This gives us both a code to GID and a code to SID mapping.        */
 
+    if ( offset > 1 )
+    {
+
       encoding->offset = base_offset + offset;
 
       /* we need to parse the table to determine its size */
@@ -600,15 +1743,65 @@
       switch ( encoding->format & 0x7F )
       {
       case 0:
-        size = 2 + count;
+
+        for ( j = 1; j <= count; j++ )
+        {
+          if ( READ_Byte( glyph_code ) )
+            goto Exit;
+
+          /* Make sure j is not too big. */
+          if ( j > num_glyphs )
+            goto Exit;
+
+          /* Assign code to GID mapping. */
+          encoding->codes[glyph_code] = j;
+
+          /* Assign code to SID mapping. */
+
+          encoding->sids[glyph_code] = charset->sids[j];
+        }
+
         break;
 
       case 1:
-        size = 2 + count * 2;
-        break;
+        {
+          FT_Byte  nleft;
+          FT_Byte  i = 1;
+          FT_Byte  k;
 
-      case 2:
-        size = 2 + count * 3;
+          /* Parse the Format1 ranges. */
+          for ( j = 0;  j < count; j++, i += nleft )
+          {
+
+            /* Read the first glyph code of the range.             */
+            if ( READ_Byte( glyph_code ) )
+              goto Exit;
+
+            /* Read the number of codes in the range.              */
+            if ( READ_Byte( nleft ) )
+              goto Exit;
+
+            /* Increment nleft, so we read `nleft + 1' codes/sids. */
+            nleft++;
+
+            /* Fill in the range of codes/sids.                    */
+            for ( k = i; k < nleft + i; k++, glyph_code++ )
+            {
+
+              /* Make sure k is not too big. */
+              if ( k > num_glyphs )
+                goto Exit;
+
+              /* Assign code to GID mapping. */
+              encoding->codes[glyph_code] = k;
+
+              /* Assign code to SID mapping. */
+              encoding->sids[glyph_code] = charset->sids[k];
+
+            }
+          }
+        }
+
         break;
 
       default:
@@ -617,28 +1810,158 @@
         goto Exit;
       }
 
+      /* Parse supplemental encodings, if any. */
       if ( encoding->format & 0x80 )
       {
+        FT_UInt glyph_id;
+
         /* count supplements */
-        if ( FILE_Seek( encoding->offset + size ) ||
-             READ_Byte( count )                   )
+        if ( READ_Byte( count ) )
           goto Exit;
-          
-        size += 1 + 3 * count;
+
+        for ( j = 0; j < count; j++ )
+        {
+
+          /* Read supplemental glyph code.                */
+          if ( READ_Byte( glyph_code ) )
+            goto Exit;
+
+          /* Read the SID associated with this glyph code */
+          if ( READ_UShort( glyph_sid ) )
+            goto Exit;
+
+          /* Assign code to SID mapping.                  */
+          encoding->sids[glyph_code] = glyph_sid;
+
+          /* Assign code to GID mapping.                  */
+
+          /* First, lookup GID which has been assigned    */
+          /* SID glyph_sid.                               */
+          for ( glyph_id = 0; glyph_id < num_glyphs; glyph_id++ )
+          {
+            if ( charset->sids[glyph_id] == glyph_sid )
+              break;
+          }
+
+          /* Now, make the assignment.                    */
+          encoding->codes[glyph_code] = glyph_id;
+
+        }
       }
-      
-      encoding->size = size;
 
-      if ( ALLOC( encoding->bytes, size )     ||
-           FILE_Seek( encoding->offset  )     ||
-           FILE_Read( encoding->bytes, size ) )
-        goto Exit;
     }
     else
-      encoding->offset = offset;
+    {
+      FT_UInt i;
 
+      /* We take into account the fact a CFF font can use a predefined  */
+      /* encoding without containing all of the glyphs encoded by this  */
+      /* encoding (see the note at the end of section 12 in the CFF     */
+      /* specification).                                                */
+
+      switch ( offset )
+      {
+
+      case 0:
+
+        /* First, copy the code to SID mapping.    */
+        MEM_Copy( encoding->sids, cff_standard_encoding,
+                  256 * sizeof( FT_UShort ) );
+
+        /* Construct code to GID mapping from code */
+        /* to SID mapping and charset.             */
+        for ( j = 0; j < 256; j++ )
+        {
+          /* If j is encoded, find the GID for it. */
+          if ( encoding->sids[j] )
+          {
+
+            for ( i = 1; i < num_glyphs; i++ )
+              /* We matched, so break. */
+              if ( charset->sids[i] == encoding->sids[j] )
+                break;
+
+            /* i will be equal to num_glyphs if we exited the above */
+            /* loop without a match.  In this case, we also have to */
+            /* fix the code to SID mapping.                         */
+            if ( i == num_glyphs )
+            {
+              encoding->codes[j] = 0;
+              encoding->sids [j] = 0;
+            }
+            else
+              encoding->codes[j] = i;
+          }
+        }
+
+        break;
+
+      case 1:
+
+        /* First, copy the code to SID mapping. */
+        MEM_Copy( encoding->sids, cff_expert_encoding,
+                  256 * sizeof( FT_UShort ) );
+
+        /* Construct code to GID mapping from code to SID mapping */
+        /* and charset.                                           */
+        for ( j = 0; j < 256; j++ )
+        {
+          /* If j is encoded, find the GID for it. */
+          if ( encoding->sids[j] )
+          {
+
+            for ( i = 1; i < num_glyphs; i++ )
+              /* We matched, so break. */
+              if ( charset->sids[i] == encoding->sids[j] )
+                break;
+
+            /* i will be equal to num_glyphs if we exited the above */
+            /* loop without a match.  In this case, we also have to */
+            /* fix the code to SID mapping.                         */
+            if ( i == num_glyphs )
+            {
+              encoding->codes[j] = 0;
+              encoding->sids [j] = 0;
+            }
+            else
+              encoding->codes[j] = i;
+          }
+        }
+
+        break;
+
+      default:
+        FT_ERROR(( "CFF.Load_Encoding: invalid table format!\n" ));
+        error = FT_Err_Invalid_File_Format;
+        goto Exit;
+       break;
+
+      }
+    }
+
   Exit:
+
+    /* Clean up if there was an error. */
+    if ( error )
+    {
+      if ( encoding->sids || encoding->codes )
+      {
+        FT_Memory  memory = stream->memory;
+
+        if ( encoding->sids )
+          FREE( encoding->sids );
+
+        if ( encoding->codes )
+          FREE( encoding->codes );
+
+        charset->format = 0;
+        charset->offset = 0;
+        charset->sids   = 0;
+      }
+    }
+
     return error;
+
   }
 
 
@@ -908,8 +2231,8 @@
     if ( error )
       goto Exit;
       
-    error = CFF_Load_Encoding( &font->encoding, font->num_glyphs, stream,
-                               base_offset, dict->encoding_offset );
+    error = CFF_Load_Encoding( &font->encoding, &font->charset, font->num_glyphs,
+                               stream, base_offset, dict->encoding_offset );
     if ( error )
       goto Exit;