PageRenderTime 127ms CodeModel.GetById 16ms app.highlight 100ms RepoModel.GetById 1ms app.codeStats 1ms

/modules/freetype2/src/cff/cffload.c

http://github.com/zpao/v8monkey
C | 1661 lines | 1166 code | 324 blank | 171 comment | 186 complexity | d294f10e900094b816c41f02086bd488 MD5 | raw file
   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      /* XXX: should check off2 does not exceed the end of this entry; */
 523      /*      at present, only truncate off2 at the end of this stream */
 524      if ( off2 > stream->size + 1                    ||
 525           idx->data_offset > stream->size - off2 + 1 )
 526      {
 527        FT_ERROR(( "cff_index_access_element:"
 528                   " offset to next entry (%d)"
 529                   " exceeds the end of stream (%d)\n",
 530                   off2, stream->size - idx->data_offset + 1 ));
 531        off2 = stream->size - idx->data_offset + 1;
 532      }
 533
 534      /* access element */
 535      if ( off1 && off2 > off1 )
 536      {
 537        *pbyte_len = off2 - off1;
 538
 539        if ( idx->bytes )
 540        {
 541          /* this index was completely loaded in memory, that's easy */
 542          *pbytes = idx->bytes + off1 - 1;
 543        }
 544        else
 545        {
 546          /* this index is still on disk/file, access it through a frame */
 547          if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) ||
 548               FT_FRAME_EXTRACT( off2 - off1, *pbytes )      )
 549            goto Exit;
 550        }
 551      }
 552      else
 553      {
 554        /* empty index element */
 555        *pbytes    = 0;
 556        *pbyte_len = 0;
 557      }
 558    }
 559    else
 560      error = CFF_Err_Invalid_Argument;
 561
 562  Exit:
 563    return error;
 564  }
 565
 566
 567  FT_LOCAL_DEF( void )
 568  cff_index_forget_element( CFF_Index  idx,
 569                            FT_Byte**  pbytes )
 570  {
 571    if ( idx->bytes == 0 )
 572    {
 573      FT_Stream  stream = idx->stream;
 574
 575
 576      FT_FRAME_RELEASE( *pbytes );
 577    }
 578  }
 579
 580
 581  /* get an entry from Name INDEX */
 582  FT_LOCAL_DEF( FT_String* )
 583  cff_index_get_name( CFF_Font  font,
 584                      FT_UInt   element )
 585  {
 586    CFF_Index   idx = &font->name_index;
 587    FT_Memory   memory = idx->stream->memory;
 588    FT_Byte*    bytes;
 589    FT_ULong    byte_len;
 590    FT_Error    error;
 591    FT_String*  name = 0;
 592
 593
 594    error = cff_index_access_element( idx, element, &bytes, &byte_len );
 595    if ( error )
 596      goto Exit;
 597
 598    if ( !FT_ALLOC( name, byte_len + 1 ) )
 599    {
 600      FT_MEM_COPY( name, bytes, byte_len );
 601      name[byte_len] = 0;
 602    }
 603    cff_index_forget_element( idx, &bytes );
 604
 605  Exit:
 606    return name;
 607  }
 608
 609
 610  /* get an entry from String INDEX */
 611  FT_LOCAL_DEF( FT_String* )
 612  cff_index_get_string( CFF_Font  font,
 613                        FT_UInt   element )
 614  {
 615    return ( element < font->num_strings )
 616             ? (FT_String*)font->strings[element]
 617             : NULL;
 618  }
 619
 620
 621  FT_LOCAL_DEF( FT_String* )
 622  cff_index_get_sid_string( CFF_Font  font,
 623                            FT_UInt   sid )
 624  {
 625    /* value 0xFFFFU indicates a missing dictionary entry */
 626    if ( sid == 0xFFFFU )
 627      return NULL;
 628
 629    /* if it is not a standard string, return it */
 630    if ( sid > 390 )
 631      return cff_index_get_string( font, sid - 391 );
 632
 633    /* CID-keyed CFF fonts don't have glyph names */
 634    if ( !font->psnames )
 635      return NULL;
 636
 637    /* this is a standard string */
 638    return (FT_String *)font->psnames->adobe_std_strings( sid );
 639  }
 640
 641
 642  /*************************************************************************/
 643  /*************************************************************************/
 644  /***                                                                   ***/
 645  /***   FD Select table support                                         ***/
 646  /***                                                                   ***/
 647  /*************************************************************************/
 648  /*************************************************************************/
 649
 650
 651  static void
 652  CFF_Done_FD_Select( CFF_FDSelect  fdselect,
 653                      FT_Stream     stream )
 654  {
 655    if ( fdselect->data )
 656      FT_FRAME_RELEASE( fdselect->data );
 657
 658    fdselect->data_size   = 0;
 659    fdselect->format      = 0;
 660    fdselect->range_count = 0;
 661  }
 662
 663
 664  static FT_Error
 665  CFF_Load_FD_Select( CFF_FDSelect  fdselect,
 666                      FT_UInt       num_glyphs,
 667                      FT_Stream     stream,
 668                      FT_ULong      offset )
 669  {
 670    FT_Error  error;
 671    FT_Byte   format;
 672    FT_UInt   num_ranges;
 673
 674
 675    /* read format */
 676    if ( FT_STREAM_SEEK( offset ) || FT_READ_BYTE( format ) )
 677      goto Exit;
 678
 679    fdselect->format      = format;
 680    fdselect->cache_count = 0;   /* clear cache */
 681
 682    switch ( format )
 683    {
 684    case 0:     /* format 0, that's simple */
 685      fdselect->data_size = num_glyphs;
 686      goto Load_Data;
 687
 688    case 3:     /* format 3, a tad more complex */
 689      if ( FT_READ_USHORT( num_ranges ) )
 690        goto Exit;
 691
 692      fdselect->data_size = num_ranges * 3 + 2;
 693
 694    Load_Data:
 695      if ( FT_FRAME_EXTRACT( fdselect->data_size, fdselect->data ) )
 696        goto Exit;
 697      break;
 698
 699    default:    /* hmm... that's wrong */
 700      error = CFF_Err_Invalid_File_Format;
 701    }
 702
 703  Exit:
 704    return error;
 705  }
 706
 707
 708  FT_LOCAL_DEF( FT_Byte )
 709  cff_fd_select_get( CFF_FDSelect  fdselect,
 710                     FT_UInt       glyph_index )
 711  {
 712    FT_Byte  fd = 0;
 713
 714
 715    switch ( fdselect->format )
 716    {
 717    case 0:
 718      fd = fdselect->data[glyph_index];
 719      break;
 720
 721    case 3:
 722      /* first, compare to cache */
 723      if ( (FT_UInt)( glyph_index - fdselect->cache_first ) <
 724                        fdselect->cache_count )
 725      {
 726        fd = fdselect->cache_fd;
 727        break;
 728      }
 729
 730      /* then, lookup the ranges array */
 731      {
 732        FT_Byte*  p       = fdselect->data;
 733        FT_Byte*  p_limit = p + fdselect->data_size;
 734        FT_Byte   fd2;
 735        FT_UInt   first, limit;
 736
 737
 738        first = FT_NEXT_USHORT( p );
 739        do
 740        {
 741          if ( glyph_index < first )
 742            break;
 743
 744          fd2   = *p++;
 745          limit = FT_NEXT_USHORT( p );
 746
 747          if ( glyph_index < limit )
 748          {
 749            fd = fd2;
 750
 751            /* update cache */
 752            fdselect->cache_first = first;
 753            fdselect->cache_count = limit-first;
 754            fdselect->cache_fd    = fd2;
 755            break;
 756          }
 757          first = limit;
 758
 759        } while ( p < p_limit );
 760      }
 761      break;
 762
 763    default:
 764      ;
 765    }
 766
 767    return fd;
 768  }
 769
 770
 771  /*************************************************************************/
 772  /*************************************************************************/
 773  /***                                                                   ***/
 774  /***   CFF font support                                                ***/
 775  /***                                                                   ***/
 776  /*************************************************************************/
 777  /*************************************************************************/
 778
 779  static FT_Error
 780  cff_charset_compute_cids( CFF_Charset  charset,
 781                            FT_UInt      num_glyphs,
 782                            FT_Memory    memory )
 783  {
 784    FT_Error   error   = CFF_Err_Ok;
 785    FT_UInt    i;
 786    FT_Long    j;
 787    FT_UShort  max_cid = 0;
 788
 789
 790    if ( charset->max_cid > 0 )
 791      goto Exit;
 792
 793    for ( i = 0; i < num_glyphs; i++ )
 794    {
 795      if ( charset->sids[i] > max_cid )
 796        max_cid = charset->sids[i];
 797    }
 798
 799    if ( FT_NEW_ARRAY( charset->cids, (FT_ULong)max_cid + 1 ) )
 800      goto Exit;
 801
 802    /* When multiple GIDs map to the same CID, we choose the lowest */
 803    /* GID.  This is not described in any spec, but it matches the  */
 804    /* behaviour of recent Acroread versions.                       */
 805    for ( j = num_glyphs - 1; j >= 0 ; j-- )
 806      charset->cids[charset->sids[j]] = (FT_UShort)j;
 807
 808    charset->max_cid    = max_cid;
 809    charset->num_glyphs = num_glyphs;
 810
 811  Exit:
 812    return error;
 813  }
 814
 815
 816  FT_LOCAL_DEF( FT_UInt )
 817  cff_charset_cid_to_gindex( CFF_Charset  charset,
 818                             FT_UInt      cid )
 819  {
 820    FT_UInt  result = 0;
 821
 822
 823    if ( cid <= charset->max_cid )
 824      result = charset->cids[cid];
 825
 826    return result;
 827  }
 828
 829
 830  static void
 831  cff_charset_free_cids( CFF_Charset  charset,
 832                         FT_Memory    memory )
 833  {
 834    FT_FREE( charset->cids );
 835    charset->max_cid = 0;
 836  }
 837
 838
 839  static void
 840  cff_charset_done( CFF_Charset  charset,
 841                    FT_Stream    stream )
 842  {
 843    FT_Memory  memory = stream->memory;
 844
 845
 846    cff_charset_free_cids( charset, memory );
 847
 848    FT_FREE( charset->sids );
 849    charset->format = 0;
 850    charset->offset = 0;
 851  }
 852
 853
 854  static FT_Error
 855  cff_charset_load( CFF_Charset  charset,
 856                    FT_UInt      num_glyphs,
 857                    FT_Stream    stream,
 858                    FT_ULong     base_offset,
 859                    FT_ULong     offset,
 860                    FT_Bool      invert )
 861  {
 862    FT_Memory  memory = stream->memory;
 863    FT_Error   error  = CFF_Err_Ok;
 864    FT_UShort  glyph_sid;
 865
 866
 867    /* If the the offset is greater than 2, we have to parse the */
 868    /* charset table.                                            */
 869    if ( offset > 2 )
 870    {
 871      FT_UInt  j;
 872
 873
 874      charset->offset = base_offset + offset;
 875
 876      /* Get the format of the table. */
 877      if ( FT_STREAM_SEEK( charset->offset ) ||
 878           FT_READ_BYTE( charset->format )   )
 879        goto Exit;
 880
 881      /* Allocate memory for sids. */
 882      if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
 883        goto Exit;
 884
 885      /* assign the .notdef glyph */
 886      charset->sids[0] = 0;
 887
 888      switch ( charset->format )
 889      {
 890      case 0:
 891        if ( num_glyphs > 0 )
 892        {
 893          if ( FT_FRAME_ENTER( ( num_glyphs - 1 ) * 2 ) )
 894            goto Exit;
 895
 896          for ( j = 1; j < num_glyphs; j++ )
 897            charset->sids[j] = FT_GET_USHORT();
 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            /* try to rescue some of the SIDs if `nleft' is too large */
 931            if ( glyph_sid > 0xFFFFL - nleft )
 932            {
 933              FT_ERROR(( "cff_charset_load: invalid SID range trimmed"
 934                         " nleft=%d -> %d\n", nleft, 0xFFFFL - glyph_sid ));
 935              nleft = ( FT_UInt )( 0xFFFFL - glyph_sid );
 936            }
 937
 938            /* Fill in the range of sids -- `nleft + 1' glyphs. */
 939            for ( i = 0; j < num_glyphs && i <= nleft; i++, j++, glyph_sid++ )
 940              charset->sids[j] = glyph_sid;
 941          }
 942        }
 943        break;
 944
 945      default:
 946        FT_ERROR(( "cff_charset_load: invalid table format\n" ));
 947        error = CFF_Err_Invalid_File_Format;
 948        goto Exit;
 949      }
 950    }
 951    else
 952    {
 953      /* Parse default tables corresponding to offset == 0, 1, or 2.  */
 954      /* CFF specification intimates the following:                   */
 955      /*                                                              */
 956      /* In order to use a predefined charset, the following must be  */
 957      /* true: The charset constructed for the glyphs in the font's   */
 958      /* charstrings dictionary must match the predefined charset in  */
 959      /* the first num_glyphs.                                        */
 960
 961      charset->offset = offset;  /* record charset type */
 962
 963      switch ( (FT_UInt)offset )
 964      {
 965      case 0:
 966        if ( num_glyphs > 229 )
 967        {
 968          FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
 969                     "predefined charset (Adobe ISO-Latin)\n" ));
 970          error = CFF_Err_Invalid_File_Format;
 971          goto Exit;
 972        }
 973
 974        /* Allocate memory for sids. */
 975        if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
 976          goto Exit;
 977
 978        /* Copy the predefined charset into the allocated memory. */
 979        FT_ARRAY_COPY( charset->sids, cff_isoadobe_charset, num_glyphs );
 980
 981        break;
 982
 983      case 1:
 984        if ( num_glyphs > 166 )
 985        {
 986          FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
 987                     "predefined charset (Adobe Expert)\n" ));
 988          error = CFF_Err_Invalid_File_Format;
 989          goto Exit;
 990        }
 991
 992        /* Allocate memory for sids. */
 993        if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
 994          goto Exit;
 995
 996        /* Copy the predefined charset into the allocated memory.     */
 997        FT_ARRAY_COPY( charset->sids, cff_expert_charset, num_glyphs );
 998
 999        break;
1000
1001      case 2:
1002        if ( num_glyphs > 87 )
1003        {
1004          FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
1005                     "predefined charset (Adobe Expert Subset)\n" ));
1006          error = CFF_Err_Invalid_File_Format;
1007          goto Exit;
1008        }
1009
1010        /* Allocate memory for sids. */
1011        if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
1012          goto Exit;
1013
1014        /* Copy the predefined charset into the allocated memory.     */
1015        FT_ARRAY_COPY( charset->sids, cff_expertsubset_charset, num_glyphs );
1016
1017        break;
1018
1019      default:
1020        error = CFF_Err_Invalid_File_Format;
1021        goto Exit;
1022      }
1023    }
1024
1025    /* we have to invert the `sids' array for subsetted CID-keyed fonts */
1026    if ( invert )
1027      error = cff_charset_compute_cids( charset, num_glyphs, memory );
1028
1029  Exit:
1030    /* Clean up if there was an error. */
1031    if ( error )
1032    {
1033      FT_FREE( charset->sids );
1034      FT_FREE( charset->cids );
1035      charset->format = 0;
1036      charset->offset = 0;
1037      charset->sids   = 0;
1038    }
1039
1040    return error;
1041  }
1042
1043
1044  static void
1045  cff_encoding_done( CFF_Encoding  encoding )
1046  {
1047    encoding->format = 0;
1048    encoding->offset = 0;
1049    encoding->count  = 0;
1050  }
1051
1052
1053  static FT_Error
1054  cff_encoding_load( CFF_Encoding  encoding,
1055                     CFF_Charset   charset,
1056                     FT_UInt       num_glyphs,
1057                     FT_Stream     stream,
1058                     FT_ULong      base_offset,
1059                     FT_ULong      offset )
1060  {
1061    FT_Error   error = CFF_Err_Ok;
1062    FT_UInt    count;
1063    FT_UInt    j;
1064    FT_UShort  glyph_sid;
1065    FT_UInt    glyph_code;
1066
1067
1068    /* Check for charset->sids.  If we do not have this, we fail. */
1069    if ( !charset->sids )
1070    {
1071      error = CFF_Err_Invalid_File_Format;
1072      goto Exit;
1073    }
1074
1075    /* Zero out the code to gid/sid mappings. */
1076    for ( j = 0; j < 256; j++ )
1077    {
1078      encoding->sids [j] = 0;
1079      encoding->codes[j] = 0;
1080    }
1081
1082    /* Note: The encoding table in a CFF font is indexed by glyph index;  */
1083    /* the first encoded glyph index is 1.  Hence, we read the character  */
1084    /* code (`glyph_code') at index j and make the assignment:            */
1085    /*                                                                    */
1086    /*    encoding->codes[glyph_code] = j + 1                             */
1087    /*                                                                    */
1088    /* We also make the assignment:                                       */
1089    /*                                                                    */
1090    /*    encoding->sids[glyph_code] = charset->sids[j + 1]               */
1091    /*                                                                    */
1092    /* This gives us both a code to GID and a code to SID mapping.        */
1093
1094    if ( offset > 1 )
1095    {
1096      encoding->offset = base_offset + offset;
1097
1098      /* we need to parse the table to determine its size */
1099      if ( FT_STREAM_SEEK( encoding->offset ) ||
1100           FT_READ_BYTE( encoding->format )   ||
1101           FT_READ_BYTE( count )              )
1102        goto Exit;
1103
1104      switch ( encoding->format & 0x7F )
1105      {
1106      case 0:
1107        {
1108          FT_Byte*  p;
1109
1110
1111          /* By convention, GID 0 is always ".notdef" and is never */
1112          /* coded in the font.  Hence, the number of codes found  */
1113          /* in the table is `count+1'.                            */
1114          /*                                                       */
1115          encoding->count = count + 1;
1116
1117          if ( FT_FRAME_ENTER( count ) )
1118            goto Exit;
1119
1120          p = (FT_Byte*)stream->cursor;
1121
1122          for ( j = 1; j <= count; j++ )
1123          {
1124            glyph_code = *p++;
1125
1126            /* Make sure j is not too big. */
1127            if ( j < num_glyphs )
1128            {
1129              /* Assign code to GID mapping. */
1130              encoding->codes[glyph_code] = (FT_UShort)j;
1131
1132              /* Assign code to SID mapping. */
1133              encoding->sids[glyph_code] = charset->sids[j];
1134            }
1135          }
1136
1137          FT_FRAME_EXIT();
1138        }
1139        break;
1140
1141      case 1:
1142        {
1143          FT_UInt  nleft;
1144          FT_UInt  i = 1;
1145          FT_UInt  k;
1146
1147
1148          encoding->count = 0;
1149
1150          /* Parse the Format1 ranges. */
1151          for ( j = 0;  j < count; j++, i += nleft )
1152          {
1153            /* Read the first glyph code of the range. */
1154            if ( FT_READ_BYTE( glyph_code ) )
1155              goto Exit;
1156
1157            /* Read the number of codes in the range. */
1158            if ( FT_READ_BYTE( nleft ) )
1159              goto Exit;
1160
1161            /* Increment nleft, so we read `nleft + 1' codes/sids. */
1162            nleft++;
1163
1164            /* compute max number of character codes */
1165            if ( (FT_UInt)nleft > encoding->count )
1166              encoding->count = nleft;
1167
1168            /* Fill in the range of codes/sids. */
1169            for ( k = i; k < nleft + i; k++, glyph_code++ )
1170            {
1171              /* Make sure k is not too big. */
1172              if ( k < num_glyphs && glyph_code < 256 )
1173              {
1174                /* Assign code to GID mapping. */
1175                encoding->codes[glyph_code] = (FT_UShort)k;
1176
1177                /* Assign code to SID mapping. */
1178                encoding->sids[glyph_code] = charset->sids[k];
1179              }
1180            }
1181          }
1182
1183          /* simple check; one never knows what can be found in a font */
1184          if ( encoding->count > 256 )
1185            encoding->count = 256;
1186        }
1187        break;
1188
1189      default:
1190        FT_ERROR(( "cff_encoding_load: invalid table format\n" ));
1191        error = CFF_Err_Invalid_File_Format;
1192        goto Exit;
1193      }
1194
1195      /* Parse supplemental encodings, if any. */
1196      if ( encoding->format & 0x80 )
1197      {
1198        FT_UInt  gindex;
1199
1200
1201        /* count supplements */
1202        if ( FT_READ_BYTE( count ) )
1203          goto Exit;
1204
1205        for ( j = 0; j < count; j++ )
1206        {
1207          /* Read supplemental glyph code. */
1208          if ( FT_READ_BYTE( glyph_code ) )
1209            goto Exit;
1210
1211          /* Read the SID associated with this glyph code. */
1212          if ( FT_READ_USHORT( glyph_sid ) )
1213            goto Exit;
1214
1215          /* Assign code to SID mapping. */
1216          encoding->sids[glyph_code] = glyph_sid;
1217
1218          /* First, look up GID which has been assigned to */
1219          /* SID glyph_sid.                                */
1220          for ( gindex = 0; gindex < num_glyphs; gindex++ )
1221          {
1222            if ( charset->sids[gindex] == glyph_sid )
1223            {
1224              encoding->codes[glyph_code] = (FT_UShort)gindex;
1225              break;
1226            }
1227          }
1228        }
1229      }
1230    }
1231    else
1232    {
1233      /* We take into account the fact a CFF font can use a predefined */
1234      /* encoding without containing all of the glyphs encoded by this */
1235      /* encoding (see the note at the end of section 12 in the CFF    */
1236      /* specification).                                               */
1237
1238      switch ( (FT_UInt)offset )
1239      {
1240      case 0:
1241        /* First, copy the code to SID mapping. */
1242        FT_ARRAY_COPY( encoding->sids, cff_standard_encoding, 256 );
1243        goto Populate;
1244
1245      case 1:
1246        /* First, copy the code to SID mapping. */
1247        FT_ARRAY_COPY( encoding->sids, cff_expert_encoding, 256 );
1248
1249      Populate:
1250        /* Construct code to GID mapping from code to SID mapping */
1251        /* and charset.                                           */
1252
1253        encoding->count = 0;
1254
1255        error = cff_charset_compute_cids( charset, num_glyphs,
1256                                          stream->memory );
1257        if ( error )
1258          goto Exit;
1259
1260        for ( j = 0; j < 256; j++ )
1261        {
1262          FT_UInt  sid = encoding->sids[j];
1263          FT_UInt  gid = 0;
1264
1265
1266          if ( sid )
1267            gid = cff_charset_cid_to_gindex( charset, sid );
1268
1269          if ( gid != 0 )
1270          {
1271            encoding->codes[j] = (FT_UShort)gid;
1272            encoding->count    = j + 1;
1273          }
1274          else
1275          {
1276            encoding->codes[j] = 0;
1277            encoding->sids [j] = 0;
1278          }
1279        }
1280        break;
1281
1282      default:
1283        FT_ERROR(( "cff_encoding_load: invalid table format\n" ));
1284        error = CFF_Err_Invalid_File_Format;
1285        goto Exit;
1286      }
1287    }
1288
1289  Exit:
1290
1291    /* Clean up if there was an error. */
1292    return error;
1293  }
1294
1295
1296  static FT_Error
1297  cff_subfont_load( CFF_SubFont  font,
1298                    CFF_Index    idx,
1299                    FT_UInt      font_index,
1300                    FT_Stream    stream,
1301                    FT_ULong     base_offset,
1302                    FT_Library   library )
1303  {
1304    FT_Error         error;
1305    CFF_ParserRec    parser;
1306    FT_Byte*         dict = NULL;
1307    FT_ULong         dict_len;
1308    CFF_FontRecDict  top  = &font->font_dict;
1309    CFF_Private      priv = &font->private_dict;
1310
1311
1312    cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict, library );
1313
1314    /* set defaults */
1315    FT_MEM_ZERO( top, sizeof ( *top ) );
1316
1317    top->underline_position  = -100L << 16;
1318    top->underline_thickness = 50L << 16;
1319    top->charstring_type     = 2;
1320    top->font_matrix.xx      = 0x10000L;
1321    top->font_matrix.yy      = 0x10000L;
1322    top->cid_count           = 8720;
1323
1324    /* we use the implementation specific SID value 0xFFFF to indicate */
1325    /* missing entries                                                 */
1326    top->version             = 0xFFFFU;
1327    top->notice              = 0xFFFFU;
1328    top->copyright           = 0xFFFFU;
1329    top->full_name           = 0xFFFFU;
1330    top->family_name         = 0xFFFFU;
1331    top->weight              = 0xFFFFU;
1332    top->embedded_postscript = 0xFFFFU;
1333
1334    top->cid_registry        = 0xFFFFU;
1335    top->cid_ordering        = 0xFFFFU;
1336    top->cid_font_name       = 0xFFFFU;
1337
1338    error = cff_index_access_element( idx, font_index, &dict, &dict_len );
1339    if ( !error )
1340      error = cff_parser_run( &parser, dict, dict + dict_len );
1341
1342    cff_index_forget_element( idx, &dict );
1343
1344    if ( error )
1345      goto Exit;
1346
1347    /* if it is a CID font, we stop there */
1348    if ( top->cid_registry != 0xFFFFU )
1349      goto Exit;
1350
1351    /* parse the private dictionary, if any */
1352    if ( top->private_offset && top->private_size )
1353    {
1354      /* set defaults */
1355      FT_MEM_ZERO( priv, sizeof ( *priv ) );
1356
1357      priv->blue_shift       = 7;
1358      priv->blue_fuzz        = 1;
1359      priv->lenIV            = -1;
1360      priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
1361      priv->blue_scale       = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
1362
1363      cff_parser_init( &parser, CFF_CODE_PRIVATE, priv, library );
1364
1365      if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) ||
1366           FT_FRAME_ENTER( font->font_dict.private_size )                 )
1367        goto Exit;
1368
1369      error = cff_parser_run( &parser,
1370                              (FT_Byte*)stream->cursor,
1371                              (FT_Byte*)stream->limit );
1372      FT_FRAME_EXIT();
1373      if ( error )
1374        goto Exit;
1375
1376      /* ensure that `num_blue_values' is even */
1377      priv->num_blue_values &= ~1;
1378    }
1379
1380    /* read the local subrs, if any */
1381    if ( priv->local_subrs_offset )
1382    {
1383      if ( FT_STREAM_SEEK( base_offset + top->private_offset +
1384                           priv->local_subrs_offset ) )
1385        goto Exit;
1386
1387      error = cff_index_init( &font->local_subrs_index, stream, 1 );
1388      if ( error )
1389        goto Exit;
1390
1391      error = cff_index_get_pointers( &font->local_subrs_index,
1392                                      &font->local_subrs, NULL );
1393      if ( error )
1394        goto Exit;
1395    }
1396
1397  Exit:
1398    return error;
1399  }
1400
1401
1402  static void
1403  cff_subfont_done( FT_Memory    memory,
1404                    CFF_SubFont  subfont )
1405  {
1406    if ( subfont )
1407    {
1408      cff_index_done( &subfont->local_subrs_index );
1409      FT_FREE( subfont->local_subrs );
1410    }
1411  }
1412
1413
1414  FT_LOCAL_DEF( FT_Error )
1415  cff_font_load( FT_Library library,
1416                 FT_Stream  stream,
1417                 FT_Int     face_index,
1418                 CFF_Font   font,
1419                 FT_Bool    pure_cff )
1420  {
1421    static const FT_Frame_Field  cff_header_fields[] =
1422    {
1423#undef  FT_STRUCTURE
1424#define FT_STRUCTURE  CFF_FontRec
1425
1426      FT_FRAME_START( 4 ),
1427        FT_FRAME_BYTE( version_major ),
1428        FT_FRAME_BYTE( version_minor ),
1429        FT_FRAME_BYTE( header_size ),
1430        FT_FRAME_BYTE( absolute_offsize ),
1431      FT_FRAME_END
1432    };
1433
1434    FT_Error         error;
1435    FT_Memory        memory = stream->memory;
1436    FT_ULong         base_offset;
1437    CFF_FontRecDict  dict;
1438    CFF_IndexRec     string_index;
1439
1440
1441    FT_ZERO( font );
1442    FT_ZERO( &string_index );
1443
1444    font->stream = stream;
1445    font->memory = memory;
1446    dict         = &font->top_font.font_dict;
1447    base_offset  = FT_STREAM_POS();
1448
1449    /* read CFF font header */
1450    if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) )
1451      goto Exit;
1452
1453    /* check format */
1454    if ( font->version_major   != 1 ||
1455         font->header_size      < 4 ||
1456         font->absolute_offsize > 4 )
1457    {
1458      FT_TRACE2(( "[not a CFF font header]\n" ));
1459      error = CFF_Err_Unknown_File_Format;
1460      goto Exit;
1461    }
1462
1463    /* skip the rest of the header */
1464    if ( FT_STREAM_SKIP( font->header_size - 4 ) )
1465      goto Exit;
1466
1467    /* read the name, top dict, string and global subrs index */
1468    if ( FT_SET_ERROR( cff_index_init( &font->name_index,
1469                                       stream, 0 ) )                  ||
1470         FT_SET_ERROR( cff_index_init( &font->font_dict_index,
1471                                       stream, 0 ) )                  ||
1472         FT_SET_ERROR( cff_index_init( &string_index,
1473                                       stream, 1 ) )                  ||
1474         FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
1475                                       stream, 1 ) )                  ||
1476         FT_SET_ERROR( cff_index_get_pointers( &string_index,
1477                                               &font->strings,
1478                                               &font->string_pool ) ) )
1479      goto Exit;
1480
1481    font->num_strings = string_index.count;
1482
1483    /* well, we don't really forget the `disabled' fonts... */
1484    font->num_faces = font->name_index.count;
1485    if ( face_index >= (FT_Int)font->num_faces )
1486    {
1487      FT_ERROR(( "cff_font_load: incorrect face index = %d\n",
1488                 face_index ));
1489      error = CFF_Err_Invalid_Argument;
1490    }
1491
1492    /* in case of a font format check, simply exit now */
1493    if ( face_index < 0 )
1494      goto Exit;
1495
1496    /* now, parse the top-level font dictionary */
1497    error = cff_subfont_load( &font->top_font,
1498                              &font->font_dict_index,
1499                              face_index,
1500                              stream,
1501                              base_offset,
1502                              library );
1503    if ( error )
1504      goto Exit;
1505
1506    if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) )
1507      goto Exit;
1508
1509    error = cff_index_init( &font->charstrings_index, stream, 0 );
1510    if ( error )
1511      goto Exit;
1512
1513    /* now, check for a CID font */
1514    if ( dict->cid_registry != 0xFFFFU )
1515    {
1516      CFF_IndexRec  fd_index;
1517      CFF_SubFont   sub;
1518      FT_UInt       idx;
1519
1520
1521      /* this is a CID-keyed font, we must now allocate a table of */
1522      /* sub-fonts, then load each of them separately              */
1523      if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) )
1524        goto Exit;
1525
1526      error = cff_index_init( &fd_index, stream, 0 );
1527      if ( error )
1528        goto Exit;
1529
1530      if ( fd_index.count > CFF_MAX_CID_FONTS )
1531      {
1532        FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" ));
1533        goto Fail_CID;
1534      }
1535
1536      /* allocate & read each font dict independently */
1537      font->num_subfonts = fd_index.count;
1538      if ( FT_NEW_ARRAY( sub, fd_index.count ) )
1539        goto Fail_CID;
1540
1541      /* set up pointer table */
1542      for ( idx = 0; idx < fd_index.count; idx++ )
1543        font->subfonts[idx] = sub + idx;
1544
1545      /* now load each subfont independently */
1546      for ( idx = 0; idx < fd_index.count; idx++ )
1547      {
1548        sub = font->subfonts[idx];
1549        error = cff_subfont_load( sub, &fd_index, idx,
1550                                  stream, base_offset, library );
1551        if ( error )
1552          goto Fail_CID;
1553      }
1554
1555      /* now load the FD Select array */
1556      error = CFF_Load_FD_Select( &font->fd_select,
1557                                  font->charstrings_index.count,
1558                                  stream,
1559                                  base_offset + dict->cid_fd_select_offset );
1560
1561    Fail_CID:
1562      cff_index_done( &fd_index );
1563
1564      if ( error )
1565        goto Exit;
1566    }
1567    else
1568      font->num_subfonts = 0;
1569
1570    /* read the charstrings index now */
1571    if ( dict->charstrings_offset == 0 )
1572    {
1573      FT_ERROR(( "cff_font_load: no charstrings offset\n" ));
1574      error = CFF_Err_Unknown_File_Format;
1575      goto Exit;
1576    }
1577
1578    font->num_glyphs = font->charstrings_index.count;
1579
1580    error = cff_index_get_pointers( &font->global_subrs_index,
1581                                    &font->global_subrs, NULL );
1582
1583    if ( error )
1584      goto Exit;
1585
1586    /* read the Charset and Encoding tables if available */
1587    if ( font->num_glyphs > 0 )
1588    {
1589      FT_Bool  invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff );
1590
1591
1592      error = cff_charset_load( &font->charset, font->num_glyphs, stream,
1593                                base_offset, dict->charset_offset, invert );
1594      if ( error )
1595        goto Exit;
1596
1597      /* CID-keyed CFFs don't have an encoding */
1598      if ( dict->cid_registry == 0xFFFFU )
1599      {
1600        error = cff_encoding_load( &font->encoding,
1601                                   &font->charset,
1602                                   font->num_glyphs,
1603                                   stream,
1604                                   base_offset,
1605                                   dict->encoding_offset );
1606        if ( error )
1607          goto Exit;
1608      }
1609    }
1610
1611    /* get the font name (/CIDFontName for CID-keyed fonts, */
1612    /* /FontName otherwise)                                 */
1613    font->font_name = cff_index_get_name( font, face_index );
1614
1615  Exit:
1616    cff_index_done( &string_index );
1617
1618    return error;
1619  }
1620
1621
1622  FT_LOCAL_DEF( void )
1623  cff_font_done( CFF_Font  font )
1624  {
1625    FT_Memory  memory = font->memory;
1626    FT_UInt    idx;
1627
1628
1629    cff_index_done( &font->global_subrs_index );
1630    cff_index_done( &font->font_dict_index );
1631    cff_index_done( &font->name_index );
1632    cff_index_done( &font->charstrings_index );
1633
1634    /* release font dictionaries, but only if working with */
1635    /* a CID keyed CFF font                                */
1636    if ( font->num_subfonts > 0 )
1637    {
1638      for ( idx = 0; idx < font->num_subfonts; idx++ )
1639        cff_subfont_done( memory, font->subfonts[idx] );
1640
1641      /* the subfonts array has been allocated as a single block */
1642      FT_FREE( font->subfonts[0] );
1643    }
1644
1645    cff_encoding_done( &font->encoding );
1646    cff_charset_done( &font->charset, font->stream );
1647
1648    cff_subfont_done( memory, &font->top_font );
1649
1650    CFF_Done_FD_Select( &font->fd_select, font->stream );
1651
1652    FT_FREE( font->font_info );
1653
1654    FT_FREE( font->font_name );
1655    FT_FREE( font->global_subrs );
1656    FT_FREE( font->strings );
1657    FT_FREE( font->string_pool );
1658  }
1659
1660
1661/* END */