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