Home | History | Annotate | Download | only in cff
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  cffload.c                                                              */
      4 /*                                                                         */
      5 /*    OpenType and CFF data/program tables loader (body).                  */
      6 /*                                                                         */
      7 /*  Copyright 1996-2011 by                                                 */
      8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
      9 /*                                                                         */
     10 /*  This file is part of the FreeType project, and may only be used,       */
     11 /*  modified, and distributed under the terms of the FreeType project      */
     12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
     13 /*  this file you indicate that you have read the license and              */
     14 /*  understand and accept it fully.                                        */
     15 /*                                                                         */
     16 /***************************************************************************/
     17 
     18 
     19 #include <ft2build.h>
     20 #include FT_INTERNAL_DEBUG_H
     21 #include FT_INTERNAL_OBJECTS_H
     22 #include FT_INTERNAL_STREAM_H
     23 #include FT_TRUETYPE_TAGS_H
     24 #include FT_TYPE1_TABLES_H
     25 
     26 #include "cffload.h"
     27 #include "cffparse.h"
     28 
     29 #include "cfferrs.h"
     30 
     31 
     32 #if 1
     33 
     34   static const FT_UShort  cff_isoadobe_charset[229] =
     35   {
     36       0,   1,   2,   3,   4,   5,   6,   7,
     37       8,   9,  10,  11,  12,  13,  14,  15,
     38      16,  17,  18,  19,  20,  21,  22,  23,
     39      24,  25,  26,  27,  28,  29,  30,  31,
     40      32,  33,  34,  35,  36,  37,  38,  39,
     41      40,  41,  42,  43,  44,  45,  46,  47,
     42      48,  49,  50,  51,  52,  53,  54,  55,
     43      56,  57,  58,  59,  60,  61,  62,  63,
     44      64,  65,  66,  67,  68,  69,  70,  71,
     45      72,  73,  74,  75,  76,  77,  78,  79,
     46      80,  81,  82,  83,  84,  85,  86,  87,
     47      88,  89,  90,  91,  92,  93,  94,  95,
     48      96,  97,  98,  99, 100, 101, 102, 103,
     49     104, 105, 106, 107, 108, 109, 110, 111,
     50     112, 113, 114, 115, 116, 117, 118, 119,
     51     120, 121, 122, 123, 124, 125, 126, 127,
     52     128, 129, 130, 131, 132, 133, 134, 135,
     53     136, 137, 138, 139, 140, 141, 142, 143,
     54     144, 145, 146, 147, 148, 149, 150, 151,
     55     152, 153, 154, 155, 156, 157, 158, 159,
     56     160, 161, 162, 163, 164, 165, 166, 167,
     57     168, 169, 170, 171, 172, 173, 174, 175,
     58     176, 177, 178, 179, 180, 181, 182, 183,
     59     184, 185, 186, 187, 188, 189, 190, 191,
     60     192, 193, 194, 195, 196, 197, 198, 199,
     61     200, 201, 202, 203, 204, 205, 206, 207,
     62     208, 209, 210, 211, 212, 213, 214, 215,
     63     216, 217, 218, 219, 220, 221, 222, 223,
     64     224, 225, 226, 227, 228
     65   };
     66 
     67   static const FT_UShort  cff_expert_charset[166] =
     68   {
     69       0,   1, 229, 230, 231, 232, 233, 234,
     70     235, 236, 237, 238,  13,  14,  15,  99,
     71     239, 240, 241, 242, 243, 244, 245, 246,
     72     247, 248,  27,  28, 249, 250, 251, 252,
     73     253, 254, 255, 256, 257, 258, 259, 260,
     74     261, 262, 263, 264, 265, 266, 109, 110,
     75     267, 268, 269, 270, 271, 272, 273, 274,
     76     275, 276, 277, 278, 279, 280, 281, 282,
     77     283, 284, 285, 286, 287, 288, 289, 290,
     78     291, 292, 293, 294, 295, 296, 297, 298,
     79     299, 300, 301, 302, 303, 304, 305, 306,
     80     307, 308, 309, 310, 311, 312, 313, 314,
     81     315, 316, 317, 318, 158, 155, 163, 319,
     82     320, 321, 322, 323, 324, 325, 326, 150,
     83     164, 169, 327, 328, 329, 330, 331, 332,
     84     333, 334, 335, 336, 337, 338, 339, 340,
     85     341, 342, 343, 344, 345, 346, 347, 348,
     86     349, 350, 351, 352, 353, 354, 355, 356,
     87     357, 358, 359, 360, 361, 362, 363, 364,
     88     365, 366, 367, 368, 369, 370, 371, 372,
     89     373, 374, 375, 376, 377, 378
     90   };
     91 
     92   static const FT_UShort  cff_expertsubset_charset[87] =
     93   {
     94       0,   1, 231, 232, 235, 236, 237, 238,
     95      13,  14,  15,  99, 239, 240, 241, 242,
     96     243, 244, 245, 246, 247, 248,  27,  28,
     97     249, 250, 251, 253, 254, 255, 256, 257,
     98     258, 259, 260, 261, 262, 263, 264, 265,
     99     266, 109, 110, 267, 268, 269, 270, 272,
    100     300, 301, 302, 305, 314, 315, 158, 155,
    101     163, 320, 321, 322, 323, 324, 325, 326,
    102     150, 164, 169, 327, 328, 329, 330, 331,
    103     332, 333, 334, 335, 336, 337, 338, 339,
    104     340, 341, 342, 343, 344, 345, 346
    105   };
    106 
    107   static const FT_UShort  cff_standard_encoding[256] =
    108   {
    109       0,   0,   0,   0,   0,   0,   0,   0,
    110       0,   0,   0,   0,   0,   0,   0,   0,
    111       0,   0,   0,   0,   0,   0,   0,   0,
    112       0,   0,   0,   0,   0,   0,   0,   0,
    113       1,   2,   3,   4,   5,   6,   7,   8,
    114       9,  10,  11,  12,  13,  14,  15,  16,
    115      17,  18,  19,  20,  21,  22,  23,  24,
    116      25,  26,  27,  28,  29,  30,  31,  32,
    117      33,  34,  35,  36,  37,  38,  39,  40,
    118      41,  42,  43,  44,  45,  46,  47,  48,
    119      49,  50,  51,  52,  53,  54,  55,  56,
    120      57,  58,  59,  60,  61,  62,  63,  64,
    121      65,  66,  67,  68,  69,  70,  71,  72,
    122      73,  74,  75,  76,  77,  78,  79,  80,
    123      81,  82,  83,  84,  85,  86,  87,  88,
    124      89,  90,  91,  92,  93,  94,  95,   0,
    125       0,   0,   0,   0,   0,   0,   0,   0,
    126       0,   0,   0,   0,   0,   0,   0,   0,
    127       0,   0,   0,   0,   0,   0,   0,   0,
    128       0,   0,   0,   0,   0,   0,   0,   0,
    129       0,  96,  97,  98,  99, 100, 101, 102,
    130     103, 104, 105, 106, 107, 108, 109, 110,
    131       0, 111, 112, 113, 114,   0, 115, 116,
    132     117, 118, 119, 120, 121, 122,   0, 123,
    133       0, 124, 125, 126, 127, 128, 129, 130,
    134     131,   0, 132, 133,   0, 134, 135, 136,
    135     137,   0,   0,   0,   0,   0,   0,   0,
    136       0,   0,   0,   0,   0,   0,   0,   0,
    137       0, 138,   0, 139,   0,   0,   0,   0,
    138     140, 141, 142, 143,   0,   0,   0,   0,
    139       0, 144,   0,   0,   0, 145,   0,   0,
    140     146, 147, 148, 149,   0,   0,   0,   0
    141   };
    142 
    143   static const FT_UShort  cff_expert_encoding[256] =
    144   {
    145       0,   0,   0,   0,   0,   0,   0,   0,
    146       0,   0,   0,   0,   0,   0,   0,   0,
    147       0,   0,   0,   0,   0,   0,   0,   0,
    148       0,   0,   0,   0,   0,   0,   0,   0,
    149       1, 229, 230,   0, 231, 232, 233, 234,
    150     235, 236, 237, 238,  13,  14,  15,  99,
    151     239, 240, 241, 242, 243, 244, 245, 246,
    152     247, 248,  27,  28, 249, 250, 251, 252,
    153       0, 253, 254, 255, 256, 257,   0,   0,
    154       0, 258,   0,   0, 259, 260, 261, 262,
    155       0,   0, 263, 264, 265,   0, 266, 109,
    156     110, 267, 268, 269,   0, 270, 271, 272,
    157     273, 274, 275, 276, 277, 278, 279, 280,
    158     281, 282, 283, 284, 285, 286, 287, 288,
    159     289, 290, 291, 292, 293, 294, 295, 296,
    160     297, 298, 299, 300, 301, 302, 303,   0,
    161       0,   0,   0,   0,   0,   0,   0,   0,
    162       0,   0,   0,   0,   0,   0,   0,   0,
    163       0,   0,   0,   0,   0,   0,   0,   0,
    164       0,   0,   0,   0,   0,   0,   0,   0,
    165       0, 304, 305, 306,   0,   0, 307, 308,
    166     309, 310, 311,   0, 312,   0,   0, 312,
    167       0,   0, 314, 315,   0,   0, 316, 317,
    168     318,   0,   0,   0, 158, 155, 163, 319,
    169     320, 321, 322, 323, 324, 325,   0,   0,
    170     326, 150, 164, 169, 327, 328, 329, 330,
    171     331, 332, 333, 334, 335, 336, 337, 338,
    172     339, 340, 341, 342, 343, 344, 345, 346,
    173     347, 348, 349, 350, 351, 352, 353, 354,
    174     355, 356, 357, 358, 359, 360, 361, 362,
    175     363, 364, 365, 366, 367, 368, 369, 370,
    176     371, 372, 373, 374, 375, 376, 377, 378
    177   };
    178 
    179 #endif /* 1 */
    180 
    181 
    182   FT_LOCAL_DEF( FT_UShort )
    183   cff_get_standard_encoding( FT_UInt  charcode )
    184   {
    185     return (FT_UShort)( charcode < 256 ? cff_standard_encoding[charcode]
    186                                        : 0 );
    187   }
    188 
    189 
    190   /*************************************************************************/
    191   /*                                                                       */
    192   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
    193   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
    194   /* messages during execution.                                            */
    195   /*                                                                       */
    196 #undef  FT_COMPONENT
    197 #define FT_COMPONENT  trace_cffload
    198 
    199 
    200   /* read an offset from the index's stream current position */
    201   static FT_ULong
    202   cff_index_read_offset( CFF_Index  idx,
    203                          FT_Error  *errorp )
    204   {
    205     FT_Error   error;
    206     FT_Stream  stream = idx->stream;
    207     FT_Byte    tmp[4];
    208     FT_ULong   result = 0;
    209 
    210 
    211     if ( !FT_STREAM_READ( tmp, idx->off_size ) )
    212     {
    213       FT_Int  nn;
    214 
    215 
    216       for ( nn = 0; nn < idx->off_size; nn++ )
    217         result = ( result << 8 ) | tmp[nn];
    218     }
    219 
    220     *errorp = error;
    221     return result;
    222   }
    223 
    224 
    225   static FT_Error
    226   cff_index_init( CFF_Index  idx,
    227                   FT_Stream  stream,
    228                   FT_Bool    load )
    229   {
    230     FT_Error   error;
    231     FT_Memory  memory = stream->memory;
    232     FT_UShort  count;
    233 
    234 
    235     FT_MEM_ZERO( idx, sizeof ( *idx ) );
    236 
    237     idx->stream = stream;
    238     idx->start  = FT_STREAM_POS();
    239     if ( !FT_READ_USHORT( count ) &&
    240          count > 0                )
    241     {
    242       FT_Byte   offsize;
    243       FT_ULong  size;
    244 
    245 
    246       /* there is at least one element; read the offset size,           */
    247       /* then access the offset table to compute the index's total size */
    248       if ( FT_READ_BYTE( offsize ) )
    249         goto Exit;
    250 
    251       if ( offsize < 1 || offsize > 4 )
    252       {
    253         error = CFF_Err_Invalid_Table;
    254         goto Exit;
    255       }
    256 
    257       idx->count    = count;
    258       idx->off_size = offsize;
    259       size          = (FT_ULong)( count + 1 ) * offsize;
    260 
    261       idx->data_offset = idx->start + 3 + size;
    262 
    263       if ( FT_STREAM_SKIP( size - offsize ) )
    264         goto Exit;
    265 
    266       size = cff_index_read_offset( idx, &error );
    267       if ( error )
    268         goto Exit;
    269 
    270       if ( size == 0 )
    271       {
    272         error = CFF_Err_Invalid_Table;
    273         goto Exit;
    274       }
    275 
    276       idx->data_size = --size;
    277 
    278       if ( load )
    279       {
    280         /* load the data */
    281         if ( FT_FRAME_EXTRACT( size, idx->bytes ) )
    282           goto Exit;
    283       }
    284       else
    285       {
    286         /* skip the data */
    287         if ( FT_STREAM_SKIP( size ) )
    288           goto Exit;
    289       }
    290     }
    291 
    292   Exit:
    293     if ( error )
    294       FT_FREE( idx->offsets );
    295 
    296     return error;
    297   }
    298 
    299 
    300   static void
    301   cff_index_done( CFF_Index  idx )
    302   {
    303     if ( idx->stream )
    304     {
    305       FT_Stream  stream = idx->stream;
    306       FT_Memory  memory = stream->memory;
    307 
    308 
    309       if ( idx->bytes )
    310         FT_FRAME_RELEASE( idx->bytes );
    311 
    312       FT_FREE( idx->offsets );
    313       FT_MEM_ZERO( idx, sizeof ( *idx ) );
    314     }
    315   }
    316 
    317 
    318   static FT_Error
    319   cff_index_load_offsets( CFF_Index  idx )
    320   {
    321     FT_Error   error  = CFF_Err_Ok;
    322     FT_Stream  stream = idx->stream;
    323     FT_Memory  memory = stream->memory;
    324 
    325 
    326     if ( idx->count > 0 && idx->offsets == NULL )
    327     {
    328       FT_Byte    offsize = idx->off_size;
    329       FT_ULong   data_size;
    330       FT_Byte*   p;
    331       FT_Byte*   p_end;
    332       FT_ULong*  poff;
    333 
    334 
    335       data_size = (FT_ULong)( idx->count + 1 ) * offsize;
    336 
    337       if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) ||
    338            FT_STREAM_SEEK( idx->start + 3 )             ||
    339            FT_FRAME_ENTER( data_size )                  )
    340         goto Exit;
    341 
    342       poff   = idx->offsets;
    343       p      = (FT_Byte*)stream->cursor;
    344       p_end  = p + data_size;
    345 
    346       switch ( offsize )
    347       {
    348       case 1:
    349         for ( ; p < p_end; p++, poff++ )
    350           poff[0] = p[0];
    351         break;
    352 
    353       case 2:
    354         for ( ; p < p_end; p += 2, poff++ )
    355           poff[0] = FT_PEEK_USHORT( p );
    356         break;
    357 
    358       case 3:
    359         for ( ; p < p_end; p += 3, poff++ )
    360           poff[0] = FT_PEEK_OFF3( p );
    361         break;
    362 
    363       default:
    364         for ( ; p < p_end; p += 4, poff++ )
    365           poff[0] = FT_PEEK_ULONG( p );
    366       }
    367 
    368       FT_FRAME_EXIT();
    369     }
    370 
    371   Exit:
    372     if ( error )
    373       FT_FREE( idx->offsets );
    374 
    375     return error;
    376   }
    377 
    378 
    379   /* Allocate a table containing pointers to an index's elements. */
    380   /* The `pool' argument makes this function convert the index    */
    381   /* entries to C-style strings (this is, NULL-terminated).       */
    382   static FT_Error
    383   cff_index_get_pointers( CFF_Index   idx,
    384                           FT_Byte***  table,
    385                           FT_Byte**   pool )
    386   {
    387     FT_Error   error     = CFF_Err_Ok;
    388     FT_Memory  memory    = idx->stream->memory;
    389     FT_Byte**  t = NULL;
    390     FT_Byte*   new_bytes = NULL;
    391 
    392 
    393     *table = NULL;
    394 
    395     if ( idx->offsets == NULL )
    396     {
    397       error = cff_index_load_offsets( idx );
    398       if ( error )
    399         goto Exit;
    400     }
    401 
    402     if ( idx->count > 0                                        &&
    403          !FT_NEW_ARRAY( t, idx->count + 1 )                    &&
    404          ( !pool || !FT_ALLOC( new_bytes,
    405                                idx->data_size + idx->count ) ) )
    406     {
    407       FT_ULong  n, cur_offset;
    408       FT_ULong  extra = 0;
    409       FT_Byte*  org_bytes = idx->bytes;
    410 
    411 
    412       /* at this point, `idx->offsets' can't be NULL */
    413       cur_offset = idx->offsets[0] - 1;
    414 
    415       /* sanity check */
    416       if ( cur_offset >= idx->data_size )
    417       {
    418         FT_TRACE0(( "cff_index_get_pointers:"
    419                     " invalid first offset value %d set to zero\n",
    420                     cur_offset ));
    421         cur_offset = 0;
    422       }
    423 
    424       if ( !pool )
    425         t[0] = org_bytes + cur_offset;
    426       else
    427         t[0] = new_bytes + cur_offset;
    428 
    429       for ( n = 1; n <= idx->count; n++ )
    430       {
    431         FT_ULong  next_offset = idx->offsets[n] - 1;
    432 
    433 
    434         /* empty slot + two sanity checks for invalid offset tables */
    435         if ( next_offset == 0                                    ||
    436              next_offset < cur_offset                            ||
    437              ( next_offset >= idx->data_size && n < idx->count ) )
    438           next_offset = cur_offset;
    439 
    440         if ( !pool )
    441           t[n] = org_bytes + next_offset;
    442         else
    443         {
    444           t[n] = new_bytes + next_offset + extra;
    445 
    446           if ( next_offset != cur_offset )
    447           {
    448             FT_MEM_COPY( t[n - 1], org_bytes + cur_offset, t[n] - t[n - 1] );
    449             t[n][0] = '\0';
    450             t[n]   += 1;
    451             extra++;
    452           }
    453         }
    454 
    455         cur_offset = next_offset;
    456       }
    457       *table = t;
    458 
    459       if ( pool )
    460         *pool = new_bytes;
    461     }
    462 
    463   Exit:
    464     return error;
    465   }
    466 
    467 
    468   FT_LOCAL_DEF( FT_Error )
    469   cff_index_access_element( CFF_Index  idx,
    470                             FT_UInt    element,
    471                             FT_Byte**  pbytes,
    472                             FT_ULong*  pbyte_len )
    473   {
    474     FT_Error  error = CFF_Err_Ok;
    475 
    476 
    477     if ( idx && idx->count > element )
    478     {
    479       /* compute start and end offsets */
    480       FT_Stream  stream = idx->stream;
    481       FT_ULong   off1, off2 = 0;
    482 
    483 
    484       /* load offsets from file or the offset table */
    485       if ( !idx->offsets )
    486       {
    487         FT_ULong  pos = element * idx->off_size;
    488 
    489 
    490         if ( FT_STREAM_SEEK( idx->start + 3 + pos ) )
    491           goto Exit;
    492 
    493         off1 = cff_index_read_offset( idx, &error );
    494         if ( error )
    495           goto Exit;
    496 
    497         if ( off1 != 0 )
    498         {
    499           do
    500           {
    501             element++;
    502             off2 = cff_index_read_offset( idx, &error );
    503           }
    504           while ( off2 == 0 && element < idx->count );
    505         }
    506       }
    507       else   /* use offsets table */
    508       {
    509         off1 = idx->offsets[element];
    510         if ( off1 )
    511         {
    512           do
    513           {
    514             element++;
    515             off2 = idx->offsets[element];
    516 
    517           } while ( off2 == 0 && element < idx->count );
    518         }
    519       }
    520 
    521       /* XXX: should check off2 does not exceed the end of this entry; */
    522       /*      at present, only truncate off2 at the end of this stream */
    523       if ( off2 > stream->size + 1                    ||
    524            idx->data_offset > stream->size - off2 + 1 )
    525       {
    526         FT_ERROR(( "cff_index_access_element:"
    527                    " offset to next entry (%d)"
    528                    " exceeds the end of stream (%d)\n",
    529                    off2, stream->size - idx->data_offset + 1 ));
    530         off2 = stream->size - idx->data_offset + 1;
    531       }
    532 
    533       /* access element */
    534       if ( off1 && off2 > off1 )
    535       {
    536         *pbyte_len = off2 - off1;
    537 
    538         if ( idx->bytes )
    539         {
    540           /* this index was completely loaded in memory, that's easy */
    541           *pbytes = idx->bytes + off1 - 1;
    542         }
    543         else
    544         {
    545           /* this index is still on disk/file, access it through a frame */
    546           if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) ||
    547                FT_FRAME_EXTRACT( off2 - off1, *pbytes )      )
    548             goto Exit;
    549         }
    550       }
    551       else
    552       {
    553         /* empty index element */
    554         *pbytes    = 0;
    555         *pbyte_len = 0;
    556       }
    557     }
    558     else
    559       error = CFF_Err_Invalid_Argument;
    560 
    561   Exit:
    562     return error;
    563   }
    564 
    565 
    566   FT_LOCAL_DEF( void )
    567   cff_index_forget_element( CFF_Index  idx,
    568                             FT_Byte**  pbytes )
    569   {
    570     if ( idx->bytes == 0 )
    571     {
    572       FT_Stream  stream = idx->stream;
    573 
    574 
    575       FT_FRAME_RELEASE( *pbytes );
    576     }
    577   }
    578 
    579 
    580   /* get an entry from Name INDEX */
    581   FT_LOCAL_DEF( FT_String* )
    582   cff_index_get_name( CFF_Font  font,
    583                       FT_UInt   element )
    584   {
    585     CFF_Index   idx = &font->name_index;
    586     FT_Memory   memory = idx->stream->memory;
    587     FT_Byte*    bytes;
    588     FT_ULong    byte_len;
    589     FT_Error    error;
    590     FT_String*  name = 0;
    591 
    592 
    593     error = cff_index_access_element( idx, element, &bytes, &byte_len );
    594     if ( error )
    595       goto Exit;
    596 
    597     if ( !FT_ALLOC( name, byte_len + 1 ) )
    598     {
    599       FT_MEM_COPY( name, bytes, byte_len );
    600       name[byte_len] = 0;
    601     }
    602     cff_index_forget_element( idx, &bytes );
    603 
    604   Exit:
    605     return name;
    606   }
    607 
    608 
    609   /* get an entry from String INDEX */
    610   FT_LOCAL_DEF( FT_String* )
    611   cff_index_get_string( CFF_Font  font,
    612                         FT_UInt   element )
    613   {
    614     return ( element < font->num_strings )
    615              ? (FT_String*)font->strings[element]
    616              : NULL;
    617   }
    618 
    619 
    620   FT_LOCAL_DEF( FT_String* )
    621   cff_index_get_sid_string( CFF_Font  font,
    622                             FT_UInt   sid )
    623   {
    624     /* value 0xFFFFU indicates a missing dictionary entry */
    625     if ( sid == 0xFFFFU )
    626       return NULL;
    627 
    628     /* if it is not a standard string, return it */
    629     if ( sid > 390 )
    630       return cff_index_get_string( font, sid - 391 );
    631 
    632     /* CID-keyed CFF fonts don't have glyph names */
    633     if ( !font->psnames )
    634       return NULL;
    635 
    636     /* this is a standard string */
    637     return (FT_String *)font->psnames->adobe_std_strings( sid );
    638   }
    639 
    640 
    641   /*************************************************************************/
    642   /*************************************************************************/
    643   /***                                                                   ***/
    644   /***   FD Select table support                                         ***/
    645   /***                                                                   ***/
    646   /*************************************************************************/
    647   /*************************************************************************/
    648 
    649 
    650   static void
    651   CFF_Done_FD_Select( CFF_FDSelect  fdselect,
    652                       FT_Stream     stream )
    653   {
    654     if ( fdselect->data )
    655       FT_FRAME_RELEASE( fdselect->data );
    656 
    657     fdselect->data_size   = 0;
    658     fdselect->format      = 0;
    659     fdselect->range_count = 0;
    660   }
    661 
    662 
    663   static FT_Error
    664   CFF_Load_FD_Select( CFF_FDSelect  fdselect,
    665                       FT_UInt       num_glyphs,
    666                       FT_Stream     stream,
    667                       FT_ULong      offset )
    668   {
    669     FT_Error  error;
    670     FT_Byte   format;
    671     FT_UInt   num_ranges;
    672 
    673 
    674     /* read format */
    675     if ( FT_STREAM_SEEK( offset ) || FT_READ_BYTE( format ) )
    676       goto Exit;
    677 
    678     fdselect->format      = format;
    679     fdselect->cache_count = 0;   /* clear cache */
    680 
    681     switch ( format )
    682     {
    683     case 0:     /* format 0, that's simple */
    684       fdselect->data_size = num_glyphs;
    685       goto Load_Data;
    686 
    687     case 3:     /* format 3, a tad more complex */
    688       if ( FT_READ_USHORT( num_ranges ) )
    689         goto Exit;
    690 
    691       fdselect->data_size = num_ranges * 3 + 2;
    692 
    693     Load_Data:
    694       if ( FT_FRAME_EXTRACT( fdselect->data_size, fdselect->data ) )
    695         goto Exit;
    696       break;
    697 
    698     default:    /* hmm... that's wrong */
    699       error = CFF_Err_Invalid_File_Format;
    700     }
    701 
    702   Exit:
    703     return error;
    704   }
    705 
    706 
    707   FT_LOCAL_DEF( FT_Byte )
    708   cff_fd_select_get( CFF_FDSelect  fdselect,
    709                      FT_UInt       glyph_index )
    710   {
    711     FT_Byte  fd = 0;
    712 
    713 
    714     switch ( fdselect->format )
    715     {
    716     case 0:
    717       fd = fdselect->data[glyph_index];
    718       break;
    719 
    720     case 3:
    721       /* first, compare to cache */
    722       if ( (FT_UInt)( glyph_index - fdselect->cache_first ) <
    723                         fdselect->cache_count )
    724       {
    725         fd = fdselect->cache_fd;
    726         break;
    727       }
    728 
    729       /* then, lookup the ranges array */
    730       {
    731         FT_Byte*  p       = fdselect->data;
    732         FT_Byte*  p_limit = p + fdselect->data_size;
    733         FT_Byte   fd2;
    734         FT_UInt   first, limit;
    735 
    736 
    737         first = FT_NEXT_USHORT( p );
    738         do
    739         {
    740           if ( glyph_index < first )
    741             break;
    742 
    743           fd2   = *p++;
    744           limit = FT_NEXT_USHORT( p );
    745 
    746           if ( glyph_index < limit )
    747           {
    748             fd = fd2;
    749 
    750             /* update cache */
    751             fdselect->cache_first = first;
    752             fdselect->cache_count = limit-first;
    753             fdselect->cache_fd    = fd2;
    754             break;
    755           }
    756           first = limit;
    757 
    758         } while ( p < p_limit );
    759       }
    760       break;
    761 
    762     default:
    763       ;
    764     }
    765 
    766     return fd;
    767   }
    768 
    769 
    770   /*************************************************************************/
    771   /*************************************************************************/
    772   /***                                                                   ***/
    773   /***   CFF font support                                                ***/
    774   /***                                                                   ***/
    775   /*************************************************************************/
    776   /*************************************************************************/
    777 
    778   static FT_Error
    779   cff_charset_compute_cids( CFF_Charset  charset,
    780                             FT_UInt      num_glyphs,
    781                             FT_Memory    memory )
    782   {
    783     FT_Error   error   = CFF_Err_Ok;
    784     FT_UInt    i;
    785     FT_Long    j;
    786     FT_UShort  max_cid = 0;
    787 
    788 
    789     if ( charset->max_cid > 0 )
    790       goto Exit;
    791 
    792     for ( i = 0; i < num_glyphs; i++ )
    793     {
    794       if ( charset->sids[i] > max_cid )
    795         max_cid = charset->sids[i];
    796     }
    797 
    798     if ( FT_NEW_ARRAY( charset->cids, (FT_ULong)max_cid + 1 ) )
    799       goto Exit;
    800 
    801     /* When multiple GIDs map to the same CID, we choose the lowest */
    802     /* GID.  This is not described in any spec, but it matches the  */
    803     /* behaviour of recent Acroread versions.                       */
    804     for ( j = num_glyphs - 1; j >= 0 ; j-- )
    805       charset->cids[charset->sids[j]] = (FT_UShort)j;
    806 
    807     charset->max_cid    = max_cid;
    808     charset->num_glyphs = num_glyphs;
    809 
    810   Exit:
    811     return error;
    812   }
    813 
    814 
    815   FT_LOCAL_DEF( FT_UInt )
    816   cff_charset_cid_to_gindex( CFF_Charset  charset,
    817                              FT_UInt      cid )
    818   {
    819     FT_UInt  result = 0;
    820 
    821 
    822     if ( cid <= charset->max_cid )
    823       result = charset->cids[cid];
    824 
    825     return result;
    826   }
    827 
    828 
    829   static void
    830   cff_charset_free_cids( CFF_Charset  charset,
    831                          FT_Memory    memory )
    832   {
    833     FT_FREE( charset->cids );
    834     charset->max_cid = 0;
    835   }
    836 
    837 
    838   static void
    839   cff_charset_done( CFF_Charset  charset,
    840                     FT_Stream    stream )
    841   {
    842     FT_Memory  memory = stream->memory;
    843 
    844 
    845     cff_charset_free_cids( charset, memory );
    846 
    847     FT_FREE( charset->sids );
    848     charset->format = 0;
    849     charset->offset = 0;
    850   }
    851 
    852 
    853   static FT_Error
    854   cff_charset_load( CFF_Charset  charset,
    855                     FT_UInt      num_glyphs,
    856                     FT_Stream    stream,
    857                     FT_ULong     base_offset,
    858                     FT_ULong     offset,
    859                     FT_Bool      invert )
    860   {
    861     FT_Memory  memory = stream->memory;
    862     FT_Error   error  = CFF_Err_Ok;
    863     FT_UShort  glyph_sid;
    864 
    865 
    866     /* If the the offset is greater than 2, we have to parse the */
    867     /* charset table.                                            */
    868     if ( offset > 2 )
    869     {
    870       FT_UInt  j;
    871 
    872 
    873       charset->offset = base_offset + offset;
    874 
    875       /* Get the format of the table. */
    876       if ( FT_STREAM_SEEK( charset->offset ) ||
    877            FT_READ_BYTE( charset->format )   )
    878         goto Exit;
    879 
    880       /* Allocate memory for sids. */
    881       if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
    882         goto Exit;
    883 
    884       /* assign the .notdef glyph */
    885       charset->sids[0] = 0;
    886 
    887       switch ( charset->format )
    888       {
    889       case 0:
    890         if ( num_glyphs > 0 )
    891         {
    892           if ( FT_FRAME_ENTER( ( num_glyphs - 1 ) * 2 ) )
    893             goto Exit;
    894 
    895           for ( j = 1; j < num_glyphs; j++ )
    896             charset->sids[j] = FT_GET_USHORT();
    897 
    898           FT_FRAME_EXIT();
    899         }
    900         break;
    901 
    902       case 1:
    903       case 2:
    904         {
    905           FT_UInt  nleft;
    906           FT_UInt  i;
    907 
    908 
    909           j = 1;
    910 
    911           while ( j < num_glyphs )
    912           {
    913             /* Read the first glyph sid of the range. */
    914             if ( FT_READ_USHORT( glyph_sid ) )
    915               goto Exit;
    916 
    917             /* Read the number of glyphs in the range.  */
    918             if ( charset->format == 2 )
    919             {
    920               if ( FT_READ_USHORT( nleft ) )
    921                 goto Exit;
    922             }
    923             else
    924             {
    925               if ( FT_READ_BYTE( nleft ) )
    926                 goto Exit;
    927             }
    928 
    929             /* try to rescue some of the SIDs if `nleft' is too large */
    930             if ( glyph_sid > 0xFFFFL - nleft )
    931             {
    932               FT_ERROR(( "cff_charset_load: invalid SID range trimmed"
    933                          " nleft=%d -> %d\n", nleft, 0xFFFFL - glyph_sid ));
    934               nleft = ( FT_UInt )( 0xFFFFL - glyph_sid );
    935             }
    936 
    937             /* Fill in the range of sids -- `nleft + 1' glyphs. */
    938             for ( i = 0; j < num_glyphs && i <= nleft; i++, j++, glyph_sid++ )
    939               charset->sids[j] = glyph_sid;
    940           }
    941         }
    942         break;
    943 
    944       default:
    945         FT_ERROR(( "cff_charset_load: invalid table format\n" ));
    946         error = CFF_Err_Invalid_File_Format;
    947         goto Exit;
    948       }
    949     }
    950     else
    951     {
    952       /* Parse default tables corresponding to offset == 0, 1, or 2.  */
    953       /* CFF specification intimates the following:                   */
    954       /*                                                              */
    955       /* In order to use a predefined charset, the following must be  */
    956       /* true: The charset constructed for the glyphs in the font's   */
    957       /* charstrings dictionary must match the predefined charset in  */
    958       /* the first num_glyphs.                                        */
    959 
    960       charset->offset = offset;  /* record charset type */
    961 
    962       switch ( (FT_UInt)offset )
    963       {
    964       case 0:
    965         if ( num_glyphs > 229 )
    966         {
    967           FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
    968                      "predefined charset (Adobe ISO-Latin)\n" ));
    969           error = CFF_Err_Invalid_File_Format;
    970           goto Exit;
    971         }
    972 
    973         /* Allocate memory for sids. */
    974         if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
    975           goto Exit;
    976 
    977         /* Copy the predefined charset into the allocated memory. */
    978         FT_ARRAY_COPY( charset->sids, cff_isoadobe_charset, num_glyphs );
    979 
    980         break;
    981 
    982       case 1:
    983         if ( num_glyphs > 166 )
    984         {
    985           FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
    986                      "predefined charset (Adobe Expert)\n" ));
    987           error = CFF_Err_Invalid_File_Format;
    988           goto Exit;
    989         }
    990 
    991         /* Allocate memory for sids. */
    992         if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
    993           goto Exit;
    994 
    995         /* Copy the predefined charset into the allocated memory.     */
    996         FT_ARRAY_COPY( charset->sids, cff_expert_charset, num_glyphs );
    997 
    998         break;
    999 
   1000       case 2:
   1001         if ( num_glyphs > 87 )
   1002         {
   1003           FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
   1004                      "predefined charset (Adobe Expert Subset)\n" ));
   1005           error = CFF_Err_Invalid_File_Format;
   1006           goto Exit;
   1007         }
   1008 
   1009         /* Allocate memory for sids. */
   1010         if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
   1011           goto Exit;
   1012 
   1013         /* Copy the predefined charset into the allocated memory.     */
   1014         FT_ARRAY_COPY( charset->sids, cff_expertsubset_charset, num_glyphs );
   1015 
   1016         break;
   1017 
   1018       default:
   1019         error = CFF_Err_Invalid_File_Format;
   1020         goto Exit;
   1021       }
   1022     }
   1023 
   1024     /* we have to invert the `sids' array for subsetted CID-keyed fonts */
   1025     if ( invert )
   1026       error = cff_charset_compute_cids( charset, num_glyphs, memory );
   1027 
   1028   Exit:
   1029     /* Clean up if there was an error. */
   1030     if ( error )
   1031     {
   1032       FT_FREE( charset->sids );
   1033       FT_FREE( charset->cids );
   1034       charset->format = 0;
   1035       charset->offset = 0;
   1036       charset->sids   = 0;
   1037     }
   1038 
   1039     return error;
   1040   }
   1041 
   1042 
   1043   static void
   1044   cff_encoding_done( CFF_Encoding  encoding )
   1045   {
   1046     encoding->format = 0;
   1047     encoding->offset = 0;
   1048     encoding->count  = 0;
   1049   }
   1050 
   1051 
   1052   static FT_Error
   1053   cff_encoding_load( CFF_Encoding  encoding,
   1054                      CFF_Charset   charset,
   1055                      FT_UInt       num_glyphs,
   1056                      FT_Stream     stream,
   1057                      FT_ULong      base_offset,
   1058                      FT_ULong      offset )
   1059   {
   1060     FT_Error   error = CFF_Err_Ok;
   1061     FT_UInt    count;
   1062     FT_UInt    j;
   1063     FT_UShort  glyph_sid;
   1064     FT_UInt    glyph_code;
   1065 
   1066 
   1067     /* Check for charset->sids.  If we do not have this, we fail. */
   1068     if ( !charset->sids )
   1069     {
   1070       error = CFF_Err_Invalid_File_Format;
   1071       goto Exit;
   1072     }
   1073 
   1074     /* Zero out the code to gid/sid mappings. */
   1075     for ( j = 0; j < 256; j++ )
   1076     {
   1077       encoding->sids [j] = 0;
   1078       encoding->codes[j] = 0;
   1079     }
   1080 
   1081     /* Note: The encoding table in a CFF font is indexed by glyph index;  */
   1082     /* the first encoded glyph index is 1.  Hence, we read the character  */
   1083     /* code (`glyph_code') at index j and make the assignment:            */
   1084     /*                                                                    */
   1085     /*    encoding->codes[glyph_code] = j + 1                             */
   1086     /*                                                                    */
   1087     /* We also make the assignment:                                       */
   1088     /*                                                                    */
   1089     /*    encoding->sids[glyph_code] = charset->sids[j + 1]               */
   1090     /*                                                                    */
   1091     /* This gives us both a code to GID and a code to SID mapping.        */
   1092 
   1093     if ( offset > 1 )
   1094     {
   1095       encoding->offset = base_offset + offset;
   1096 
   1097       /* we need to parse the table to determine its size */
   1098       if ( FT_STREAM_SEEK( encoding->offset ) ||
   1099            FT_READ_BYTE( encoding->format )   ||
   1100            FT_READ_BYTE( count )              )
   1101         goto Exit;
   1102 
   1103       switch ( encoding->format & 0x7F )
   1104       {
   1105       case 0:
   1106         {
   1107           FT_Byte*  p;
   1108 
   1109 
   1110           /* By convention, GID 0 is always ".notdef" and is never */
   1111           /* coded in the font.  Hence, the number of codes found  */
   1112           /* in the table is `count+1'.                            */
   1113           /*                                                       */
   1114           encoding->count = count + 1;
   1115 
   1116           if ( FT_FRAME_ENTER( count ) )
   1117             goto Exit;
   1118 
   1119           p = (FT_Byte*)stream->cursor;
   1120 
   1121           for ( j = 1; j <= count; j++ )
   1122           {
   1123             glyph_code = *p++;
   1124 
   1125             /* Make sure j is not too big. */
   1126             if ( j < num_glyphs )
   1127             {
   1128               /* Assign code to GID mapping. */
   1129               encoding->codes[glyph_code] = (FT_UShort)j;
   1130 
   1131               /* Assign code to SID mapping. */
   1132               encoding->sids[glyph_code] = charset->sids[j];
   1133             }
   1134           }
   1135 
   1136           FT_FRAME_EXIT();
   1137         }
   1138         break;
   1139 
   1140       case 1:
   1141         {
   1142           FT_UInt  nleft;
   1143           FT_UInt  i = 1;
   1144           FT_UInt  k;
   1145 
   1146 
   1147           encoding->count = 0;
   1148 
   1149           /* Parse the Format1 ranges. */
   1150           for ( j = 0;  j < count; j++, i += nleft )
   1151           {
   1152             /* Read the first glyph code of the range. */
   1153             if ( FT_READ_BYTE( glyph_code ) )
   1154               goto Exit;
   1155 
   1156             /* Read the number of codes in the range. */
   1157             if ( FT_READ_BYTE( nleft ) )
   1158               goto Exit;
   1159 
   1160             /* Increment nleft, so we read `nleft + 1' codes/sids. */
   1161             nleft++;
   1162 
   1163             /* compute max number of character codes */
   1164             if ( (FT_UInt)nleft > encoding->count )
   1165               encoding->count = nleft;
   1166 
   1167             /* Fill in the range of codes/sids. */
   1168             for ( k = i; k < nleft + i; k++, glyph_code++ )
   1169             {
   1170               /* Make sure k is not too big. */
   1171               if ( k < num_glyphs && glyph_code < 256 )
   1172               {
   1173                 /* Assign code to GID mapping. */
   1174                 encoding->codes[glyph_code] = (FT_UShort)k;
   1175 
   1176                 /* Assign code to SID mapping. */
   1177                 encoding->sids[glyph_code] = charset->sids[k];
   1178               }
   1179             }
   1180           }
   1181 
   1182           /* simple check; one never knows what can be found in a font */
   1183           if ( encoding->count > 256 )
   1184             encoding->count = 256;
   1185         }
   1186         break;
   1187 
   1188       default:
   1189         FT_ERROR(( "cff_encoding_load: invalid table format\n" ));
   1190         error = CFF_Err_Invalid_File_Format;
   1191         goto Exit;
   1192       }
   1193 
   1194       /* Parse supplemental encodings, if any. */
   1195       if ( encoding->format & 0x80 )
   1196       {
   1197         FT_UInt  gindex;
   1198 
   1199 
   1200         /* count supplements */
   1201         if ( FT_READ_BYTE( count ) )
   1202           goto Exit;
   1203 
   1204         for ( j = 0; j < count; j++ )
   1205         {
   1206           /* Read supplemental glyph code. */
   1207           if ( FT_READ_BYTE( glyph_code ) )
   1208             goto Exit;
   1209 
   1210           /* Read the SID associated with this glyph code. */
   1211           if ( FT_READ_USHORT( glyph_sid ) )
   1212             goto Exit;
   1213 
   1214           /* Assign code to SID mapping. */
   1215           encoding->sids[glyph_code] = glyph_sid;
   1216 
   1217           /* First, look up GID which has been assigned to */
   1218           /* SID glyph_sid.                                */
   1219           for ( gindex = 0; gindex < num_glyphs; gindex++ )
   1220           {
   1221             if ( charset->sids[gindex] == glyph_sid )
   1222             {
   1223               encoding->codes[glyph_code] = (FT_UShort)gindex;
   1224               break;
   1225             }
   1226           }
   1227         }
   1228       }
   1229     }
   1230     else
   1231     {
   1232       /* We take into account the fact a CFF font can use a predefined */
   1233       /* encoding without containing all of the glyphs encoded by this */
   1234       /* encoding (see the note at the end of section 12 in the CFF    */
   1235       /* specification).                                               */
   1236 
   1237       switch ( (FT_UInt)offset )
   1238       {
   1239       case 0:
   1240         /* First, copy the code to SID mapping. */
   1241         FT_ARRAY_COPY( encoding->sids, cff_standard_encoding, 256 );
   1242         goto Populate;
   1243 
   1244       case 1:
   1245         /* First, copy the code to SID mapping. */
   1246         FT_ARRAY_COPY( encoding->sids, cff_expert_encoding, 256 );
   1247 
   1248       Populate:
   1249         /* Construct code to GID mapping from code to SID mapping */
   1250         /* and charset.                                           */
   1251 
   1252         encoding->count = 0;
   1253 
   1254         error = cff_charset_compute_cids( charset, num_glyphs,
   1255                                           stream->memory );
   1256         if ( error )
   1257           goto Exit;
   1258 
   1259         for ( j = 0; j < 256; j++ )
   1260         {
   1261           FT_UInt  sid = encoding->sids[j];
   1262           FT_UInt  gid = 0;
   1263 
   1264 
   1265           if ( sid )
   1266             gid = cff_charset_cid_to_gindex( charset, sid );
   1267 
   1268           if ( gid != 0 )
   1269           {
   1270             encoding->codes[j] = (FT_UShort)gid;
   1271             encoding->count    = j + 1;
   1272           }
   1273           else
   1274           {
   1275             encoding->codes[j] = 0;
   1276             encoding->sids [j] = 0;
   1277           }
   1278         }
   1279         break;
   1280 
   1281       default:
   1282         FT_ERROR(( "cff_encoding_load: invalid table format\n" ));
   1283         error = CFF_Err_Invalid_File_Format;
   1284         goto Exit;
   1285       }
   1286     }
   1287 
   1288   Exit:
   1289 
   1290     /* Clean up if there was an error. */
   1291     return error;
   1292   }
   1293 
   1294 
   1295   static FT_Error
   1296   cff_subfont_load( CFF_SubFont  font,
   1297                     CFF_Index    idx,
   1298                     FT_UInt      font_index,
   1299                     FT_Stream    stream,
   1300                     FT_ULong     base_offset,
   1301                     FT_Library   library )
   1302   {
   1303     FT_Error         error;
   1304     CFF_ParserRec    parser;
   1305     FT_Byte*         dict = NULL;
   1306     FT_ULong         dict_len;
   1307     CFF_FontRecDict  top  = &font->font_dict;
   1308     CFF_Private      priv = &font->private_dict;
   1309 
   1310 
   1311     cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict, library );
   1312 
   1313     /* set defaults */
   1314     FT_MEM_ZERO( top, sizeof ( *top ) );
   1315 
   1316     top->underline_position  = -100L << 16;
   1317     top->underline_thickness = 50L << 16;
   1318     top->charstring_type     = 2;
   1319     top->font_matrix.xx      = 0x10000L;
   1320     top->font_matrix.yy      = 0x10000L;
   1321     top->cid_count           = 8720;
   1322 
   1323     /* we use the implementation specific SID value 0xFFFF to indicate */
   1324     /* missing entries                                                 */
   1325     top->version             = 0xFFFFU;
   1326     top->notice              = 0xFFFFU;
   1327     top->copyright           = 0xFFFFU;
   1328     top->full_name           = 0xFFFFU;
   1329     top->family_name         = 0xFFFFU;
   1330     top->weight              = 0xFFFFU;
   1331     top->embedded_postscript = 0xFFFFU;
   1332 
   1333     top->cid_registry        = 0xFFFFU;
   1334     top->cid_ordering        = 0xFFFFU;
   1335     top->cid_font_name       = 0xFFFFU;
   1336 
   1337     error = cff_index_access_element( idx, font_index, &dict, &dict_len );
   1338     if ( !error )
   1339     {
   1340       FT_TRACE4(( " top dictionary:\n" ));
   1341       error = cff_parser_run( &parser, dict, dict + dict_len );
   1342     }
   1343 
   1344     cff_index_forget_element( idx, &dict );
   1345 
   1346     if ( error )
   1347       goto Exit;
   1348 
   1349     /* if it is a CID font, we stop there */
   1350     if ( top->cid_registry != 0xFFFFU )
   1351       goto Exit;
   1352 
   1353     /* parse the private dictionary, if any */
   1354     if ( top->private_offset && top->private_size )
   1355     {
   1356       /* set defaults */
   1357       FT_MEM_ZERO( priv, sizeof ( *priv ) );
   1358 
   1359       priv->blue_shift       = 7;
   1360       priv->blue_fuzz        = 1;
   1361       priv->lenIV            = -1;
   1362       priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
   1363       priv->blue_scale       = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
   1364 
   1365       cff_parser_init( &parser, CFF_CODE_PRIVATE, priv, library );
   1366 
   1367       if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) ||
   1368            FT_FRAME_ENTER( font->font_dict.private_size )                 )
   1369         goto Exit;
   1370 
   1371       FT_TRACE4(( " private dictionary:\n" ));
   1372       error = cff_parser_run( &parser,
   1373                               (FT_Byte*)stream->cursor,
   1374                               (FT_Byte*)stream->limit );
   1375       FT_FRAME_EXIT();
   1376       if ( error )
   1377         goto Exit;
   1378 
   1379       /* ensure that `num_blue_values' is even */
   1380       priv->num_blue_values &= ~1;
   1381     }
   1382 
   1383     /* read the local subrs, if any */
   1384     if ( priv->local_subrs_offset )
   1385     {
   1386       if ( FT_STREAM_SEEK( base_offset + top->private_offset +
   1387                            priv->local_subrs_offset ) )
   1388         goto Exit;
   1389 
   1390       error = cff_index_init( &font->local_subrs_index, stream, 1 );
   1391       if ( error )
   1392         goto Exit;
   1393 
   1394       error = cff_index_get_pointers( &font->local_subrs_index,
   1395                                       &font->local_subrs, NULL );
   1396       if ( error )
   1397         goto Exit;
   1398     }
   1399 
   1400   Exit:
   1401     return error;
   1402   }
   1403 
   1404 
   1405   static void
   1406   cff_subfont_done( FT_Memory    memory,
   1407                     CFF_SubFont  subfont )
   1408   {
   1409     if ( subfont )
   1410     {
   1411       cff_index_done( &subfont->local_subrs_index );
   1412       FT_FREE( subfont->local_subrs );
   1413     }
   1414   }
   1415 
   1416 
   1417   FT_LOCAL_DEF( FT_Error )
   1418   cff_font_load( FT_Library library,
   1419                  FT_Stream  stream,
   1420                  FT_Int     face_index,
   1421                  CFF_Font   font,
   1422                  FT_Bool    pure_cff )
   1423   {
   1424     static const FT_Frame_Field  cff_header_fields[] =
   1425     {
   1426 #undef  FT_STRUCTURE
   1427 #define FT_STRUCTURE  CFF_FontRec
   1428 
   1429       FT_FRAME_START( 4 ),
   1430         FT_FRAME_BYTE( version_major ),
   1431         FT_FRAME_BYTE( version_minor ),
   1432         FT_FRAME_BYTE( header_size ),
   1433         FT_FRAME_BYTE( absolute_offsize ),
   1434       FT_FRAME_END
   1435     };
   1436 
   1437     FT_Error         error;
   1438     FT_Memory        memory = stream->memory;
   1439     FT_ULong         base_offset;
   1440     CFF_FontRecDict  dict;
   1441     CFF_IndexRec     string_index;
   1442 
   1443 
   1444     FT_ZERO( font );
   1445     FT_ZERO( &string_index );
   1446 
   1447     font->stream = stream;
   1448     font->memory = memory;
   1449     dict         = &font->top_font.font_dict;
   1450     base_offset  = FT_STREAM_POS();
   1451 
   1452     /* read CFF font header */
   1453     if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) )
   1454       goto Exit;
   1455 
   1456     /* check format */
   1457     if ( font->version_major   != 1 ||
   1458          font->header_size      < 4 ||
   1459          font->absolute_offsize > 4 )
   1460     {
   1461       FT_TRACE2(( "  not a CFF font header\n" ));
   1462       error = CFF_Err_Unknown_File_Format;
   1463       goto Exit;
   1464     }
   1465 
   1466     /* skip the rest of the header */
   1467     if ( FT_STREAM_SKIP( font->header_size - 4 ) )
   1468       goto Exit;
   1469 
   1470     /* read the name, top dict, string and global subrs index */
   1471     if ( FT_SET_ERROR( cff_index_init( &font->name_index,
   1472                                        stream, 0 ) )                  ||
   1473          FT_SET_ERROR( cff_index_init( &font->font_dict_index,
   1474                                        stream, 0 ) )                  ||
   1475          FT_SET_ERROR( cff_index_init( &string_index,
   1476                                        stream, 1 ) )                  ||
   1477          FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
   1478                                        stream, 1 ) )                  ||
   1479          FT_SET_ERROR( cff_index_get_pointers( &string_index,
   1480                                                &font->strings,
   1481                                                &font->string_pool ) ) )
   1482       goto Exit;
   1483 
   1484     font->num_strings = string_index.count;
   1485 
   1486     /* well, we don't really forget the `disabled' fonts... */
   1487     font->num_faces = font->name_index.count;
   1488     if ( face_index >= (FT_Int)font->num_faces )
   1489     {
   1490       FT_ERROR(( "cff_font_load: incorrect face index = %d\n",
   1491                  face_index ));
   1492       error = CFF_Err_Invalid_Argument;
   1493     }
   1494 
   1495     /* in case of a font format check, simply exit now */
   1496     if ( face_index < 0 )
   1497       goto Exit;
   1498 
   1499     /* now, parse the top-level font dictionary */
   1500     FT_TRACE4(( "parsing top-level\n" ));
   1501     error = cff_subfont_load( &font->top_font,
   1502                               &font->font_dict_index,
   1503                               face_index,
   1504                               stream,
   1505                               base_offset,
   1506                               library );
   1507     if ( error )
   1508       goto Exit;
   1509 
   1510     if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) )
   1511       goto Exit;
   1512 
   1513     error = cff_index_init( &font->charstrings_index, stream, 0 );
   1514     if ( error )
   1515       goto Exit;
   1516 
   1517     /* now, check for a CID font */
   1518     if ( dict->cid_registry != 0xFFFFU )
   1519     {
   1520       CFF_IndexRec  fd_index;
   1521       CFF_SubFont   sub = NULL;
   1522       FT_UInt       idx;
   1523 
   1524 
   1525       /* this is a CID-keyed font, we must now allocate a table of */
   1526       /* sub-fonts, then load each of them separately              */
   1527       if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) )
   1528         goto Exit;
   1529 
   1530       error = cff_index_init( &fd_index, stream, 0 );
   1531       if ( error )
   1532         goto Exit;
   1533 
   1534       if ( fd_index.count > CFF_MAX_CID_FONTS )
   1535       {
   1536         FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" ));
   1537         goto Fail_CID;
   1538       }
   1539 
   1540       /* allocate & read each font dict independently */
   1541       font->num_subfonts = fd_index.count;
   1542       if ( FT_NEW_ARRAY( sub, fd_index.count ) )
   1543         goto Fail_CID;
   1544 
   1545       /* set up pointer table */
   1546       for ( idx = 0; idx < fd_index.count; idx++ )
   1547         font->subfonts[idx] = sub + idx;
   1548 
   1549       /* now load each subfont independently */
   1550       for ( idx = 0; idx < fd_index.count; idx++ )
   1551       {
   1552         sub = font->subfonts[idx];
   1553         FT_TRACE4(( "parsing subfont %u\n", idx ));
   1554         error = cff_subfont_load( sub, &fd_index, idx,
   1555                                   stream, base_offset, library );
   1556         if ( error )
   1557           goto Fail_CID;
   1558       }
   1559 
   1560       /* now load the FD Select array */
   1561       error = CFF_Load_FD_Select( &font->fd_select,
   1562                                   font->charstrings_index.count,
   1563                                   stream,
   1564                                   base_offset + dict->cid_fd_select_offset );
   1565 
   1566     Fail_CID:
   1567       cff_index_done( &fd_index );
   1568 
   1569       if ( error )
   1570         goto Exit;
   1571     }
   1572     else
   1573       font->num_subfonts = 0;
   1574 
   1575     /* read the charstrings index now */
   1576     if ( dict->charstrings_offset == 0 )
   1577     {
   1578       FT_ERROR(( "cff_font_load: no charstrings offset\n" ));
   1579       error = CFF_Err_Invalid_File_Format;
   1580       goto Exit;
   1581     }
   1582 
   1583     font->num_glyphs = font->charstrings_index.count;
   1584 
   1585     error = cff_index_get_pointers( &font->global_subrs_index,
   1586                                     &font->global_subrs, NULL );
   1587 
   1588     if ( error )
   1589       goto Exit;
   1590 
   1591     /* read the Charset and Encoding tables if available */
   1592     if ( font->num_glyphs > 0 )
   1593     {
   1594       FT_Bool  invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff );
   1595 
   1596 
   1597       error = cff_charset_load( &font->charset, font->num_glyphs, stream,
   1598                                 base_offset, dict->charset_offset, invert );
   1599       if ( error )
   1600         goto Exit;
   1601 
   1602       /* CID-keyed CFFs don't have an encoding */
   1603       if ( dict->cid_registry == 0xFFFFU )
   1604       {
   1605         error = cff_encoding_load( &font->encoding,
   1606                                    &font->charset,
   1607                                    font->num_glyphs,
   1608                                    stream,
   1609                                    base_offset,
   1610                                    dict->encoding_offset );
   1611         if ( error )
   1612           goto Exit;
   1613       }
   1614     }
   1615 
   1616     /* get the font name (/CIDFontName for CID-keyed fonts, */
   1617     /* /FontName otherwise)                                 */
   1618     font->font_name = cff_index_get_name( font, face_index );
   1619 
   1620   Exit:
   1621     cff_index_done( &string_index );
   1622 
   1623     return error;
   1624   }
   1625 
   1626 
   1627   FT_LOCAL_DEF( void )
   1628   cff_font_done( CFF_Font  font )
   1629   {
   1630     FT_Memory  memory = font->memory;
   1631     FT_UInt    idx;
   1632 
   1633 
   1634     cff_index_done( &font->global_subrs_index );
   1635     cff_index_done( &font->font_dict_index );
   1636     cff_index_done( &font->name_index );
   1637     cff_index_done( &font->charstrings_index );
   1638 
   1639     /* release font dictionaries, but only if working with */
   1640     /* a CID keyed CFF font                                */
   1641     if ( font->num_subfonts > 0 )
   1642     {
   1643       for ( idx = 0; idx < font->num_subfonts; idx++ )
   1644         cff_subfont_done( memory, font->subfonts[idx] );
   1645 
   1646       /* the subfonts array has been allocated as a single block */
   1647       FT_FREE( font->subfonts[0] );
   1648     }
   1649 
   1650     cff_encoding_done( &font->encoding );
   1651     cff_charset_done( &font->charset, font->stream );
   1652 
   1653     cff_subfont_done( memory, &font->top_font );
   1654 
   1655     CFF_Done_FD_Select( &font->fd_select, font->stream );
   1656 
   1657     FT_FREE( font->font_info );
   1658 
   1659     FT_FREE( font->font_name );
   1660     FT_FREE( font->global_subrs );
   1661     FT_FREE( font->strings );
   1662     FT_FREE( font->string_pool );
   1663   }
   1664 
   1665 
   1666 /* END */
   1667