PageRenderTime 121ms CodeModel.GetById 39ms app.highlight 71ms RepoModel.GetById 1ms app.codeStats 0ms

/src/freetype/src/cff/cffload.c

https://bitbucket.org/cabalistic/ogredeps/
C | 1666 lines | 1172 code | 324 blank | 170 comment | 186 complexity | 3067822364c7ec1059a025c734a3810e MD5 | raw file
   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 */