ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

cffload.c
Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  cffload.c                                                              */
00004 /*                                                                         */
00005 /*    OpenType and CFF data/program tables loader (body).                  */
00006 /*                                                                         */
00007 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
00008 /*            2010 by                                                      */
00009 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00010 /*                                                                         */
00011 /*  This file is part of the FreeType project, and may only be used,       */
00012 /*  modified, and distributed under the terms of the FreeType project      */
00013 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00014 /*  this file you indicate that you have read the license and              */
00015 /*  understand and accept it fully.                                        */
00016 /*                                                                         */
00017 /***************************************************************************/
00018 
00019 
00020 #include <ft2build.h>
00021 #include FT_INTERNAL_DEBUG_H
00022 #include FT_INTERNAL_OBJECTS_H
00023 #include FT_INTERNAL_STREAM_H
00024 #include FT_TRUETYPE_TAGS_H
00025 #include FT_TYPE1_TABLES_H
00026 
00027 #include "cffload.h"
00028 #include "cffparse.h"
00029 
00030 #include "cfferrs.h"
00031 
00032 
00033 #if 1
00034 
00035   static const FT_UShort  cff_isoadobe_charset[229] =
00036   {
00037       0,   1,   2,   3,   4,   5,   6,   7,
00038       8,   9,  10,  11,  12,  13,  14,  15,
00039      16,  17,  18,  19,  20,  21,  22,  23,
00040      24,  25,  26,  27,  28,  29,  30,  31,
00041      32,  33,  34,  35,  36,  37,  38,  39,
00042      40,  41,  42,  43,  44,  45,  46,  47,
00043      48,  49,  50,  51,  52,  53,  54,  55,
00044      56,  57,  58,  59,  60,  61,  62,  63,
00045      64,  65,  66,  67,  68,  69,  70,  71,
00046      72,  73,  74,  75,  76,  77,  78,  79,
00047      80,  81,  82,  83,  84,  85,  86,  87,
00048      88,  89,  90,  91,  92,  93,  94,  95,
00049      96,  97,  98,  99, 100, 101, 102, 103,
00050     104, 105, 106, 107, 108, 109, 110, 111,
00051     112, 113, 114, 115, 116, 117, 118, 119,
00052     120, 121, 122, 123, 124, 125, 126, 127,
00053     128, 129, 130, 131, 132, 133, 134, 135,
00054     136, 137, 138, 139, 140, 141, 142, 143,
00055     144, 145, 146, 147, 148, 149, 150, 151,
00056     152, 153, 154, 155, 156, 157, 158, 159,
00057     160, 161, 162, 163, 164, 165, 166, 167,
00058     168, 169, 170, 171, 172, 173, 174, 175,
00059     176, 177, 178, 179, 180, 181, 182, 183,
00060     184, 185, 186, 187, 188, 189, 190, 191,
00061     192, 193, 194, 195, 196, 197, 198, 199,
00062     200, 201, 202, 203, 204, 205, 206, 207,
00063     208, 209, 210, 211, 212, 213, 214, 215,
00064     216, 217, 218, 219, 220, 221, 222, 223,
00065     224, 225, 226, 227, 228
00066   };
00067 
00068   static const FT_UShort  cff_expert_charset[166] =
00069   {
00070       0,   1, 229, 230, 231, 232, 233, 234,
00071     235, 236, 237, 238,  13,  14,  15,  99,
00072     239, 240, 241, 242, 243, 244, 245, 246,
00073     247, 248,  27,  28, 249, 250, 251, 252,
00074     253, 254, 255, 256, 257, 258, 259, 260,
00075     261, 262, 263, 264, 265, 266, 109, 110,
00076     267, 268, 269, 270, 271, 272, 273, 274,
00077     275, 276, 277, 278, 279, 280, 281, 282,
00078     283, 284, 285, 286, 287, 288, 289, 290,
00079     291, 292, 293, 294, 295, 296, 297, 298,
00080     299, 300, 301, 302, 303, 304, 305, 306,
00081     307, 308, 309, 310, 311, 312, 313, 314,
00082     315, 316, 317, 318, 158, 155, 163, 319,
00083     320, 321, 322, 323, 324, 325, 326, 150,
00084     164, 169, 327, 328, 329, 330, 331, 332,
00085     333, 334, 335, 336, 337, 338, 339, 340,
00086     341, 342, 343, 344, 345, 346, 347, 348,
00087     349, 350, 351, 352, 353, 354, 355, 356,
00088     357, 358, 359, 360, 361, 362, 363, 364,
00089     365, 366, 367, 368, 369, 370, 371, 372,
00090     373, 374, 375, 376, 377, 378
00091   };
00092 
00093   static const FT_UShort  cff_expertsubset_charset[87] =
00094   {
00095       0,   1, 231, 232, 235, 236, 237, 238,
00096      13,  14,  15,  99, 239, 240, 241, 242,
00097     243, 244, 245, 246, 247, 248,  27,  28,
00098     249, 250, 251, 253, 254, 255, 256, 257,
00099     258, 259, 260, 261, 262, 263, 264, 265,
00100     266, 109, 110, 267, 268, 269, 270, 272,
00101     300, 301, 302, 305, 314, 315, 158, 155,
00102     163, 320, 321, 322, 323, 324, 325, 326,
00103     150, 164, 169, 327, 328, 329, 330, 331,
00104     332, 333, 334, 335, 336, 337, 338, 339,
00105     340, 341, 342, 343, 344, 345, 346
00106   };
00107 
00108   static const FT_UShort  cff_standard_encoding[256] =
00109   {
00110       0,   0,   0,   0,   0,   0,   0,   0,
00111       0,   0,   0,   0,   0,   0,   0,   0,
00112       0,   0,   0,   0,   0,   0,   0,   0,
00113       0,   0,   0,   0,   0,   0,   0,   0,
00114       1,   2,   3,   4,   5,   6,   7,   8,
00115       9,  10,  11,  12,  13,  14,  15,  16,
00116      17,  18,  19,  20,  21,  22,  23,  24,
00117      25,  26,  27,  28,  29,  30,  31,  32,
00118      33,  34,  35,  36,  37,  38,  39,  40,
00119      41,  42,  43,  44,  45,  46,  47,  48,
00120      49,  50,  51,  52,  53,  54,  55,  56,
00121      57,  58,  59,  60,  61,  62,  63,  64,
00122      65,  66,  67,  68,  69,  70,  71,  72,
00123      73,  74,  75,  76,  77,  78,  79,  80,
00124      81,  82,  83,  84,  85,  86,  87,  88,
00125      89,  90,  91,  92,  93,  94,  95,   0,
00126       0,   0,   0,   0,   0,   0,   0,   0,
00127       0,   0,   0,   0,   0,   0,   0,   0,
00128       0,   0,   0,   0,   0,   0,   0,   0,
00129       0,   0,   0,   0,   0,   0,   0,   0,
00130       0,  96,  97,  98,  99, 100, 101, 102,
00131     103, 104, 105, 106, 107, 108, 109, 110,
00132       0, 111, 112, 113, 114,   0, 115, 116,
00133     117, 118, 119, 120, 121, 122,   0, 123,
00134       0, 124, 125, 126, 127, 128, 129, 130,
00135     131,   0, 132, 133,   0, 134, 135, 136,
00136     137,   0,   0,   0,   0,   0,   0,   0,
00137       0,   0,   0,   0,   0,   0,   0,   0,
00138       0, 138,   0, 139,   0,   0,   0,   0,
00139     140, 141, 142, 143,   0,   0,   0,   0,
00140       0, 144,   0,   0,   0, 145,   0,   0,
00141     146, 147, 148, 149,   0,   0,   0,   0
00142   };
00143 
00144   static const FT_UShort  cff_expert_encoding[256] =
00145   {
00146       0,   0,   0,   0,   0,   0,   0,   0,
00147       0,   0,   0,   0,   0,   0,   0,   0,
00148       0,   0,   0,   0,   0,   0,   0,   0,
00149       0,   0,   0,   0,   0,   0,   0,   0,
00150       1, 229, 230,   0, 231, 232, 233, 234,
00151     235, 236, 237, 238,  13,  14,  15,  99,
00152     239, 240, 241, 242, 243, 244, 245, 246,
00153     247, 248,  27,  28, 249, 250, 251, 252,
00154       0, 253, 254, 255, 256, 257,   0,   0,
00155       0, 258,   0,   0, 259, 260, 261, 262,
00156       0,   0, 263, 264, 265,   0, 266, 109,
00157     110, 267, 268, 269,   0, 270, 271, 272,
00158     273, 274, 275, 276, 277, 278, 279, 280,
00159     281, 282, 283, 284, 285, 286, 287, 288,
00160     289, 290, 291, 292, 293, 294, 295, 296,
00161     297, 298, 299, 300, 301, 302, 303,   0,
00162       0,   0,   0,   0,   0,   0,   0,   0,
00163       0,   0,   0,   0,   0,   0,   0,   0,
00164       0,   0,   0,   0,   0,   0,   0,   0,
00165       0,   0,   0,   0,   0,   0,   0,   0,
00166       0, 304, 305, 306,   0,   0, 307, 308,
00167     309, 310, 311,   0, 312,   0,   0, 312,
00168       0,   0, 314, 315,   0,   0, 316, 317,
00169     318,   0,   0,   0, 158, 155, 163, 319,
00170     320, 321, 322, 323, 324, 325,   0,   0,
00171     326, 150, 164, 169, 327, 328, 329, 330,
00172     331, 332, 333, 334, 335, 336, 337, 338,
00173     339, 340, 341, 342, 343, 344, 345, 346,
00174     347, 348, 349, 350, 351, 352, 353, 354,
00175     355, 356, 357, 358, 359, 360, 361, 362,
00176     363, 364, 365, 366, 367, 368, 369, 370,
00177     371, 372, 373, 374, 375, 376, 377, 378
00178   };
00179 
00180 #endif /* 1 */
00181 
00182 
00183   FT_LOCAL_DEF( FT_UShort )
00184   cff_get_standard_encoding( FT_UInt  charcode )
00185   {
00186     return (FT_UShort)( charcode < 256 ? cff_standard_encoding[charcode]
00187                                        : 0 );
00188   }
00189 
00190 
00191   /*************************************************************************/
00192   /*                                                                       */
00193   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00194   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00195   /* messages during execution.                                            */
00196   /*                                                                       */
00197 #undef  FT_COMPONENT
00198 #define FT_COMPONENT  trace_cffload
00199 
00200 
00201   /* read an offset from the index's stream current position */
00202   static FT_ULong
00203   cff_index_read_offset( CFF_Index  idx,
00204                          FT_Error  *errorp )
00205   {
00206     FT_Error   error;
00207     FT_Stream  stream = idx->stream;
00208     FT_Byte    tmp[4];
00209     FT_ULong   result = 0;
00210 
00211 
00212     if ( !FT_STREAM_READ( tmp, idx->off_size ) )
00213     {
00214       FT_Int  nn;
00215 
00216 
00217       for ( nn = 0; nn < idx->off_size; nn++ )
00218         result = ( result << 8 ) | tmp[nn];
00219     }
00220 
00221     *errorp = error;
00222     return result;
00223   }
00224 
00225 
00226   static FT_Error
00227   cff_index_init( CFF_Index  idx,
00228                   FT_Stream  stream,
00229                   FT_Bool    load )
00230   {
00231     FT_Error   error;
00232     FT_Memory  memory = stream->memory;
00233     FT_UShort  count;
00234 
00235 
00236     FT_MEM_ZERO( idx, sizeof ( *idx ) );
00237 
00238     idx->stream = stream;
00239     idx->start  = FT_STREAM_POS();
00240     if ( !FT_READ_USHORT( count ) &&
00241          count > 0                )
00242     {
00243       FT_Byte   offsize;
00244       FT_ULong  size;
00245 
00246 
00247       /* there is at least one element; read the offset size,           */
00248       /* then access the offset table to compute the index's total size */
00249       if ( FT_READ_BYTE( offsize ) )
00250         goto Exit;
00251 
00252       if ( offsize < 1 || offsize > 4 )
00253       {
00254         error = CFF_Err_Invalid_Table;
00255         goto Exit;
00256       }
00257 
00258       idx->count    = count;
00259       idx->off_size = offsize;
00260       size          = (FT_ULong)( count + 1 ) * offsize;
00261 
00262       idx->data_offset = idx->start + 3 + size;
00263 
00264       if ( FT_STREAM_SKIP( size - offsize ) )
00265         goto Exit;
00266 
00267       size = cff_index_read_offset( idx, &error );
00268       if ( error )
00269         goto Exit;
00270 
00271       if ( size == 0 )
00272       {
00273         error = CFF_Err_Invalid_Table;
00274         goto Exit;
00275       }
00276 
00277       idx->data_size = --size;
00278 
00279       if ( load )
00280       {
00281         /* load the data */
00282         if ( FT_FRAME_EXTRACT( size, idx->bytes ) )
00283           goto Exit;
00284       }
00285       else
00286       {
00287         /* skip the data */
00288         if ( FT_STREAM_SKIP( size ) )
00289           goto Exit;
00290       }
00291     }
00292 
00293   Exit:
00294     if ( error )
00295       FT_FREE( idx->offsets );
00296 
00297     return error;
00298   }
00299 
00300 
00301   static void
00302   cff_index_done( CFF_Index  idx )
00303   {
00304     if ( idx->stream )
00305     {
00306       FT_Stream  stream = idx->stream;
00307       FT_Memory  memory = stream->memory;
00308 
00309 
00310       if ( idx->bytes )
00311         FT_FRAME_RELEASE( idx->bytes );
00312 
00313       FT_FREE( idx->offsets );
00314       FT_MEM_ZERO( idx, sizeof ( *idx ) );
00315     }
00316   }
00317 
00318 
00319   static FT_Error
00320   cff_index_load_offsets( CFF_Index  idx )
00321   {
00322     FT_Error   error  = CFF_Err_Ok;
00323     FT_Stream  stream = idx->stream;
00324     FT_Memory  memory = stream->memory;
00325 
00326 
00327     if ( idx->count > 0 && idx->offsets == NULL )
00328     {
00329       FT_Byte    offsize = idx->off_size;
00330       FT_ULong   data_size;
00331       FT_Byte*   p;
00332       FT_Byte*   p_end;
00333       FT_ULong*  poff;
00334 
00335 
00336       data_size = (FT_ULong)( idx->count + 1 ) * offsize;
00337 
00338       if ( FT_NEW_ARRAY( idx->offsets, idx->count + 1 ) ||
00339            FT_STREAM_SEEK( idx->start + 3 )             ||
00340            FT_FRAME_ENTER( data_size )                  )
00341         goto Exit;
00342 
00343       poff   = idx->offsets;
00344       p      = (FT_Byte*)stream->cursor;
00345       p_end  = p + data_size;
00346 
00347       switch ( offsize )
00348       {
00349       case 1:
00350         for ( ; p < p_end; p++, poff++ )
00351           poff[0] = p[0];
00352         break;
00353 
00354       case 2:
00355         for ( ; p < p_end; p += 2, poff++ )
00356           poff[0] = FT_PEEK_USHORT( p );
00357         break;
00358 
00359       case 3:
00360         for ( ; p < p_end; p += 3, poff++ )
00361           poff[0] = FT_PEEK_OFF3( p );
00362         break;
00363 
00364       default:
00365         for ( ; p < p_end; p += 4, poff++ )
00366           poff[0] = FT_PEEK_ULONG( p );
00367       }
00368 
00369       FT_FRAME_EXIT();
00370     }
00371 
00372   Exit:
00373     if ( error )
00374       FT_FREE( idx->offsets );
00375 
00376     return error;
00377   }
00378 
00379 
00380   /* Allocate a table containing pointers to an index's elements. */
00381   /* The `pool' argument makes this function convert the index    */
00382   /* entries to C-style strings (this is, NULL-terminated).       */
00383   static FT_Error
00384   cff_index_get_pointers( CFF_Index   idx,
00385                           FT_Byte***  table,
00386                           FT_Byte**   pool )
00387   {
00388     FT_Error   error     = CFF_Err_Ok;
00389     FT_Memory  memory    = idx->stream->memory;
00390     FT_Byte**  t;
00391     FT_Byte*   new_bytes = NULL;
00392 
00393 
00394     *table = NULL;
00395 
00396     if ( idx->offsets == NULL )
00397     {
00398       error = cff_index_load_offsets( idx );
00399       if ( error )
00400         goto Exit;
00401     }
00402 
00403     if ( idx->count > 0                                        &&
00404          !FT_NEW_ARRAY( t, idx->count + 1 )                    &&
00405          ( !pool || !FT_ALLOC( new_bytes,
00406                                idx->data_size + idx->count ) ) )
00407     {
00408       FT_ULong  n, cur_offset;
00409       FT_ULong  extra = 0;
00410       FT_Byte*  org_bytes = idx->bytes;
00411 
00412 
00413       /* at this point, `idx->offsets' can't be NULL */
00414       cur_offset = idx->offsets[0] - 1;
00415 
00416       /* sanity check */
00417       if ( cur_offset >= idx->data_size )
00418       {
00419         FT_TRACE0(( "cff_index_get_pointers:"
00420                     " invalid first offset value %d set to zero\n",
00421                     cur_offset ));
00422         cur_offset = 0;
00423       }
00424 
00425       if ( !pool )
00426         t[0] = org_bytes + cur_offset;
00427       else
00428         t[0] = new_bytes + cur_offset;
00429 
00430       for ( n = 1; n <= idx->count; n++ )
00431       {
00432         FT_ULong  next_offset = idx->offsets[n] - 1;
00433 
00434 
00435         /* empty slot + two sanity checks for invalid offset tables */
00436         if ( next_offset == 0                                    ||
00437              next_offset < cur_offset                            ||
00438              ( next_offset >= idx->data_size && n < idx->count ) )
00439           next_offset = cur_offset;
00440 
00441         if ( !pool )
00442           t[n] = org_bytes + next_offset;
00443         else
00444         {
00445           t[n] = new_bytes + next_offset + extra;
00446 
00447           if ( next_offset != cur_offset )
00448           {
00449             FT_MEM_COPY( t[n - 1], org_bytes + cur_offset, t[n] - t[n - 1] );
00450             t[n][0] = '\0';
00451             t[n]   += 1;
00452             extra++;
00453           }
00454         }
00455 
00456         cur_offset = next_offset;
00457       }
00458       *table = t;
00459 
00460       if ( pool )
00461         *pool = new_bytes;
00462     }
00463 
00464   Exit:
00465     return error;
00466   }
00467 
00468 
00469   FT_LOCAL_DEF( FT_Error )
00470   cff_index_access_element( CFF_Index  idx,
00471                             FT_UInt    element,
00472                             FT_Byte**  pbytes,
00473                             FT_ULong*  pbyte_len )
00474   {
00475     FT_Error  error = CFF_Err_Ok;
00476 
00477 
00478     if ( idx && idx->count > element )
00479     {
00480       /* compute start and end offsets */
00481       FT_Stream  stream = idx->stream;
00482       FT_ULong   off1, off2 = 0;
00483 
00484 
00485       /* load offsets from file or the offset table */
00486       if ( !idx->offsets )
00487       {
00488         FT_ULong  pos = element * idx->off_size;
00489 
00490 
00491         if ( FT_STREAM_SEEK( idx->start + 3 + pos ) )
00492           goto Exit;
00493 
00494         off1 = cff_index_read_offset( idx, &error );
00495         if ( error )
00496           goto Exit;
00497 
00498         if ( off1 != 0 )
00499         {
00500           do
00501           {
00502             element++;
00503             off2 = cff_index_read_offset( idx, &error );
00504           }
00505           while ( off2 == 0 && element < idx->count );
00506         }
00507       }
00508       else   /* use offsets table */
00509       {
00510         off1 = idx->offsets[element];
00511         if ( off1 )
00512         {
00513           do
00514           {
00515             element++;
00516             off2 = idx->offsets[element];
00517 
00518           } while ( off2 == 0 && element < idx->count );
00519         }
00520       }
00521 
00522       /* XXX: should check off2 does not exceed the end of this entry; */
00523       /*      at present, only truncate off2 at the end of this stream */
00524       if ( off2 > stream->size + 1                    ||
00525            idx->data_offset > stream->size - off2 + 1 )
00526       {
00527         FT_ERROR(( "cff_index_access_element:"
00528                    " offset to next entry (%d)"
00529                    " exceeds the end of stream (%d)\n",
00530                    off2, stream->size - idx->data_offset + 1 ));
00531         off2 = stream->size - idx->data_offset + 1;
00532       }
00533 
00534       /* access element */
00535       if ( off1 && off2 > off1 )
00536       {
00537         *pbyte_len = off2 - off1;
00538 
00539         if ( idx->bytes )
00540         {
00541           /* this index was completely loaded in memory, that's easy */
00542           *pbytes = idx->bytes + off1 - 1;
00543         }
00544         else
00545         {
00546           /* this index is still on disk/file, access it through a frame */
00547           if ( FT_STREAM_SEEK( idx->data_offset + off1 - 1 ) ||
00548                FT_FRAME_EXTRACT( off2 - off1, *pbytes )      )
00549             goto Exit;
00550         }
00551       }
00552       else
00553       {
00554         /* empty index element */
00555         *pbytes    = 0;
00556         *pbyte_len = 0;
00557       }
00558     }
00559     else
00560       error = CFF_Err_Invalid_Argument;
00561 
00562   Exit:
00563     return error;
00564   }
00565 
00566 
00567   FT_LOCAL_DEF( void )
00568   cff_index_forget_element( CFF_Index  idx,
00569                             FT_Byte**  pbytes )
00570   {
00571     if ( idx->bytes == 0 )
00572     {
00573       FT_Stream  stream = idx->stream;
00574 
00575 
00576       FT_FRAME_RELEASE( *pbytes );
00577     }
00578   }
00579 
00580 
00581   /* get an entry from Name INDEX */
00582   FT_LOCAL_DEF( FT_String* )
00583   cff_index_get_name( CFF_Font  font,
00584                       FT_UInt   element )
00585   {
00586     CFF_Index   idx = &font->name_index;
00587     FT_Memory   memory = idx->stream->memory;
00588     FT_Byte*    bytes;
00589     FT_ULong    byte_len;
00590     FT_Error    error;
00591     FT_String*  name = 0;
00592 
00593 
00594     error = cff_index_access_element( idx, element, &bytes, &byte_len );
00595     if ( error )
00596       goto Exit;
00597 
00598     if ( !FT_ALLOC( name, byte_len + 1 ) )
00599     {
00600       FT_MEM_COPY( name, bytes, byte_len );
00601       name[byte_len] = 0;
00602     }
00603     cff_index_forget_element( idx, &bytes );
00604 
00605   Exit:
00606     return name;
00607   }
00608 
00609 
00610   /* get an entry from String INDEX */
00611   FT_LOCAL_DEF( FT_String* )
00612   cff_index_get_string( CFF_Font  font,
00613                         FT_UInt   element )
00614   {
00615     return ( element < font->num_strings )
00616              ? (FT_String*)font->strings[element]
00617              : NULL;
00618   }
00619 
00620 
00621   FT_LOCAL_DEF( FT_String* )
00622   cff_index_get_sid_string( CFF_Font  font,
00623                             FT_UInt   sid )
00624   {
00625     /* value 0xFFFFU indicates a missing dictionary entry */
00626     if ( sid == 0xFFFFU )
00627       return NULL;
00628 
00629     /* if it is not a standard string, return it */
00630     if ( sid > 390 )
00631       return cff_index_get_string( font, sid - 391 );
00632 
00633     /* CID-keyed CFF fonts don't have glyph names */
00634     if ( !font->psnames )
00635       return NULL;
00636 
00637     /* this is a standard string */
00638     return (FT_String *)font->psnames->adobe_std_strings( sid );
00639   }
00640 
00641 
00642   /*************************************************************************/
00643   /*************************************************************************/
00644   /***                                                                   ***/
00645   /***   FD Select table support                                         ***/
00646   /***                                                                   ***/
00647   /*************************************************************************/
00648   /*************************************************************************/
00649 
00650 
00651   static void
00652   CFF_Done_FD_Select( CFF_FDSelect  fdselect,
00653                       FT_Stream     stream )
00654   {
00655     if ( fdselect->data )
00656       FT_FRAME_RELEASE( fdselect->data );
00657 
00658     fdselect->data_size   = 0;
00659     fdselect->format      = 0;
00660     fdselect->range_count = 0;
00661   }
00662 
00663 
00664   static FT_Error
00665   CFF_Load_FD_Select( CFF_FDSelect  fdselect,
00666                       FT_UInt       num_glyphs,
00667                       FT_Stream     stream,
00668                       FT_ULong      offset )
00669   {
00670     FT_Error  error;
00671     FT_Byte   format;
00672     FT_UInt   num_ranges;
00673 
00674 
00675     /* read format */
00676     if ( FT_STREAM_SEEK( offset ) || FT_READ_BYTE( format ) )
00677       goto Exit;
00678 
00679     fdselect->format      = format;
00680     fdselect->cache_count = 0;   /* clear cache */
00681 
00682     switch ( format )
00683     {
00684     case 0:     /* format 0, that's simple */
00685       fdselect->data_size = num_glyphs;
00686       goto Load_Data;
00687 
00688     case 3:     /* format 3, a tad more complex */
00689       if ( FT_READ_USHORT( num_ranges ) )
00690         goto Exit;
00691 
00692       fdselect->data_size = num_ranges * 3 + 2;
00693 
00694     Load_Data:
00695       if ( FT_FRAME_EXTRACT( fdselect->data_size, fdselect->data ) )
00696         goto Exit;
00697       break;
00698 
00699     default:    /* hmm... that's wrong */
00700       error = CFF_Err_Invalid_File_Format;
00701     }
00702 
00703   Exit:
00704     return error;
00705   }
00706 
00707 
00708   FT_LOCAL_DEF( FT_Byte )
00709   cff_fd_select_get( CFF_FDSelect  fdselect,
00710                      FT_UInt       glyph_index )
00711   {
00712     FT_Byte  fd = 0;
00713 
00714 
00715     switch ( fdselect->format )
00716     {
00717     case 0:
00718       fd = fdselect->data[glyph_index];
00719       break;
00720 
00721     case 3:
00722       /* first, compare to cache */
00723       if ( (FT_UInt)( glyph_index - fdselect->cache_first ) <
00724                         fdselect->cache_count )
00725       {
00726         fd = fdselect->cache_fd;
00727         break;
00728       }
00729 
00730       /* then, lookup the ranges array */
00731       {
00732         FT_Byte*  p       = fdselect->data;
00733         FT_Byte*  p_limit = p + fdselect->data_size;
00734         FT_Byte   fd2;
00735         FT_UInt   first, limit;
00736 
00737 
00738         first = FT_NEXT_USHORT( p );
00739         do
00740         {
00741           if ( glyph_index < first )
00742             break;
00743 
00744           fd2   = *p++;
00745           limit = FT_NEXT_USHORT( p );
00746 
00747           if ( glyph_index < limit )
00748           {
00749             fd = fd2;
00750 
00751             /* update cache */
00752             fdselect->cache_first = first;
00753             fdselect->cache_count = limit-first;
00754             fdselect->cache_fd    = fd2;
00755             break;
00756           }
00757           first = limit;
00758 
00759         } while ( p < p_limit );
00760       }
00761       break;
00762 
00763     default:
00764       ;
00765     }
00766 
00767     return fd;
00768   }
00769 
00770 
00771   /*************************************************************************/
00772   /*************************************************************************/
00773   /***                                                                   ***/
00774   /***   CFF font support                                                ***/
00775   /***                                                                   ***/
00776   /*************************************************************************/
00777   /*************************************************************************/
00778 
00779   static FT_Error
00780   cff_charset_compute_cids( CFF_Charset  charset,
00781                             FT_UInt      num_glyphs,
00782                             FT_Memory    memory )
00783   {
00784     FT_Error   error   = CFF_Err_Ok;
00785     FT_UInt    i;
00786     FT_Long    j;
00787     FT_UShort  max_cid = 0;
00788 
00789 
00790     if ( charset->max_cid > 0 )
00791       goto Exit;
00792 
00793     for ( i = 0; i < num_glyphs; i++ )
00794     {
00795       if ( charset->sids[i] > max_cid )
00796         max_cid = charset->sids[i];
00797     }
00798 
00799     if ( FT_NEW_ARRAY( charset->cids, (FT_ULong)max_cid + 1 ) )
00800       goto Exit;
00801 
00802     /* When multiple GIDs map to the same CID, we choose the lowest */
00803     /* GID.  This is not described in any spec, but it matches the  */
00804     /* behaviour of recent Acroread versions.                       */
00805     for ( j = num_glyphs - 1; j >= 0 ; j-- )
00806       charset->cids[charset->sids[j]] = (FT_UShort)j;
00807 
00808     charset->max_cid    = max_cid;
00809     charset->num_glyphs = num_glyphs;
00810 
00811   Exit:
00812     return error;
00813   }
00814 
00815 
00816   FT_LOCAL_DEF( FT_UInt )
00817   cff_charset_cid_to_gindex( CFF_Charset  charset,
00818                              FT_UInt      cid )
00819   {
00820     FT_UInt  result = 0;
00821 
00822 
00823     if ( cid <= charset->max_cid )
00824       result = charset->cids[cid];
00825 
00826     return result;
00827   }
00828 
00829 
00830   static void
00831   cff_charset_free_cids( CFF_Charset  charset,
00832                          FT_Memory    memory )
00833   {
00834     FT_FREE( charset->cids );
00835     charset->max_cid = 0;
00836   }
00837 
00838 
00839   static void
00840   cff_charset_done( CFF_Charset  charset,
00841                     FT_Stream    stream )
00842   {
00843     FT_Memory  memory = stream->memory;
00844 
00845 
00846     cff_charset_free_cids( charset, memory );
00847 
00848     FT_FREE( charset->sids );
00849     charset->format = 0;
00850     charset->offset = 0;
00851   }
00852 
00853 
00854   static FT_Error
00855   cff_charset_load( CFF_Charset  charset,
00856                     FT_UInt      num_glyphs,
00857                     FT_Stream    stream,
00858                     FT_ULong     base_offset,
00859                     FT_ULong     offset,
00860                     FT_Bool      invert )
00861   {
00862     FT_Memory  memory = stream->memory;
00863     FT_Error   error  = CFF_Err_Ok;
00864     FT_UShort  glyph_sid;
00865 
00866 
00867     /* If the the offset is greater than 2, we have to parse the */
00868     /* charset table.                                            */
00869     if ( offset > 2 )
00870     {
00871       FT_UInt  j;
00872 
00873 
00874       charset->offset = base_offset + offset;
00875 
00876       /* Get the format of the table. */
00877       if ( FT_STREAM_SEEK( charset->offset ) ||
00878            FT_READ_BYTE( charset->format )   )
00879         goto Exit;
00880 
00881       /* Allocate memory for sids. */
00882       if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
00883         goto Exit;
00884 
00885       /* assign the .notdef glyph */
00886       charset->sids[0] = 0;
00887 
00888       switch ( charset->format )
00889       {
00890       case 0:
00891         if ( num_glyphs > 0 )
00892         {
00893           if ( FT_FRAME_ENTER( ( num_glyphs - 1 ) * 2 ) )
00894             goto Exit;
00895 
00896           for ( j = 1; j < num_glyphs; j++ )
00897             charset->sids[j] = FT_GET_USHORT();
00898 
00899           FT_FRAME_EXIT();
00900         }
00901         break;
00902 
00903       case 1:
00904       case 2:
00905         {
00906           FT_UInt  nleft;
00907           FT_UInt  i;
00908 
00909 
00910           j = 1;
00911 
00912           while ( j < num_glyphs )
00913           {
00914             /* Read the first glyph sid of the range. */
00915             if ( FT_READ_USHORT( glyph_sid ) )
00916               goto Exit;
00917 
00918             /* Read the number of glyphs in the range.  */
00919             if ( charset->format == 2 )
00920             {
00921               if ( FT_READ_USHORT( nleft ) )
00922                 goto Exit;
00923             }
00924             else
00925             {
00926               if ( FT_READ_BYTE( nleft ) )
00927                 goto Exit;
00928             }
00929 
00930             /* try to rescue some of the SIDs if `nleft' is too large */
00931             if ( glyph_sid > 0xFFFFL - nleft )
00932             {
00933               FT_ERROR(( "cff_charset_load: invalid SID range trimmed"
00934                          " nleft=%d -> %d\n", nleft, 0xFFFFL - glyph_sid ));
00935               nleft = ( FT_UInt )( 0xFFFFL - glyph_sid );
00936             }
00937 
00938             /* Fill in the range of sids -- `nleft + 1' glyphs. */
00939             for ( i = 0; j < num_glyphs && i <= nleft; i++, j++, glyph_sid++ )
00940               charset->sids[j] = glyph_sid;
00941           }
00942         }
00943         break;
00944 
00945       default:
00946         FT_ERROR(( "cff_charset_load: invalid table format\n" ));
00947         error = CFF_Err_Invalid_File_Format;
00948         goto Exit;
00949       }
00950     }
00951     else
00952     {
00953       /* Parse default tables corresponding to offset == 0, 1, or 2.  */
00954       /* CFF specification intimates the following:                   */
00955       /*                                                              */
00956       /* In order to use a predefined charset, the following must be  */
00957       /* true: The charset constructed for the glyphs in the font's   */
00958       /* charstrings dictionary must match the predefined charset in  */
00959       /* the first num_glyphs.                                        */
00960 
00961       charset->offset = offset;  /* record charset type */
00962 
00963       switch ( (FT_UInt)offset )
00964       {
00965       case 0:
00966         if ( num_glyphs > 229 )
00967         {
00968           FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
00969                      "predefined charset (Adobe ISO-Latin)\n" ));
00970           error = CFF_Err_Invalid_File_Format;
00971           goto Exit;
00972         }
00973 
00974         /* Allocate memory for sids. */
00975         if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
00976           goto Exit;
00977 
00978         /* Copy the predefined charset into the allocated memory. */
00979         FT_ARRAY_COPY( charset->sids, cff_isoadobe_charset, num_glyphs );
00980 
00981         break;
00982 
00983       case 1:
00984         if ( num_glyphs > 166 )
00985         {
00986           FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
00987                      "predefined charset (Adobe Expert)\n" ));
00988           error = CFF_Err_Invalid_File_Format;
00989           goto Exit;
00990         }
00991 
00992         /* Allocate memory for sids. */
00993         if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
00994           goto Exit;
00995 
00996         /* Copy the predefined charset into the allocated memory.     */
00997         FT_ARRAY_COPY( charset->sids, cff_expert_charset, num_glyphs );
00998 
00999         break;
01000 
01001       case 2:
01002         if ( num_glyphs > 87 )
01003         {
01004           FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
01005                      "predefined charset (Adobe Expert Subset)\n" ));
01006           error = CFF_Err_Invalid_File_Format;
01007           goto Exit;
01008         }
01009 
01010         /* Allocate memory for sids. */
01011         if ( FT_NEW_ARRAY( charset->sids, num_glyphs ) )
01012           goto Exit;
01013 
01014         /* Copy the predefined charset into the allocated memory.     */
01015         FT_ARRAY_COPY( charset->sids, cff_expertsubset_charset, num_glyphs );
01016 
01017         break;
01018 
01019       default:
01020         error = CFF_Err_Invalid_File_Format;
01021         goto Exit;
01022       }
01023     }
01024 
01025     /* we have to invert the `sids' array for subsetted CID-keyed fonts */
01026     if ( invert )
01027       error = cff_charset_compute_cids( charset, num_glyphs, memory );
01028 
01029   Exit:
01030     /* Clean up if there was an error. */
01031     if ( error )
01032     {
01033       FT_FREE( charset->sids );
01034       FT_FREE( charset->cids );
01035       charset->format = 0;
01036       charset->offset = 0;
01037       charset->sids   = 0;
01038     }
01039 
01040     return error;
01041   }
01042 
01043 
01044   static void
01045   cff_encoding_done( CFF_Encoding  encoding )
01046   {
01047     encoding->format = 0;
01048     encoding->offset = 0;
01049     encoding->count  = 0;
01050   }
01051 
01052 
01053   static FT_Error
01054   cff_encoding_load( CFF_Encoding  encoding,
01055                      CFF_Charset   charset,
01056                      FT_UInt       num_glyphs,
01057                      FT_Stream     stream,
01058                      FT_ULong      base_offset,
01059                      FT_ULong      offset )
01060   {
01061     FT_Error   error = CFF_Err_Ok;
01062     FT_UInt    count;
01063     FT_UInt    j;
01064     FT_UShort  glyph_sid;
01065     FT_UInt    glyph_code;
01066 
01067 
01068     /* Check for charset->sids.  If we do not have this, we fail. */
01069     if ( !charset->sids )
01070     {
01071       error = CFF_Err_Invalid_File_Format;
01072       goto Exit;
01073     }
01074 
01075     /* Zero out the code to gid/sid mappings. */
01076     for ( j = 0; j < 256; j++ )
01077     {
01078       encoding->sids [j] = 0;
01079       encoding->codes[j] = 0;
01080     }
01081 
01082     /* Note: The encoding table in a CFF font is indexed by glyph index;  */
01083     /* the first encoded glyph index is 1.  Hence, we read the character  */
01084     /* code (`glyph_code') at index j and make the assignment:            */
01085     /*                                                                    */
01086     /*    encoding->codes[glyph_code] = j + 1                             */
01087     /*                                                                    */
01088     /* We also make the assignment:                                       */
01089     /*                                                                    */
01090     /*    encoding->sids[glyph_code] = charset->sids[j + 1]               */
01091     /*                                                                    */
01092     /* This gives us both a code to GID and a code to SID mapping.        */
01093 
01094     if ( offset > 1 )
01095     {
01096       encoding->offset = base_offset + offset;
01097 
01098       /* we need to parse the table to determine its size */
01099       if ( FT_STREAM_SEEK( encoding->offset ) ||
01100            FT_READ_BYTE( encoding->format )   ||
01101            FT_READ_BYTE( count )              )
01102         goto Exit;
01103 
01104       switch ( encoding->format & 0x7F )
01105       {
01106       case 0:
01107         {
01108           FT_Byte*  p;
01109 
01110 
01111           /* By convention, GID 0 is always ".notdef" and is never */
01112           /* coded in the font.  Hence, the number of codes found  */
01113           /* in the table is `count+1'.                            */
01114           /*                                                       */
01115           encoding->count = count + 1;
01116 
01117           if ( FT_FRAME_ENTER( count ) )
01118             goto Exit;
01119 
01120           p = (FT_Byte*)stream->cursor;
01121 
01122           for ( j = 1; j <= count; j++ )
01123           {
01124             glyph_code = *p++;
01125 
01126             /* Make sure j is not too big. */
01127             if ( j < num_glyphs )
01128             {
01129               /* Assign code to GID mapping. */
01130               encoding->codes[glyph_code] = (FT_UShort)j;
01131 
01132               /* Assign code to SID mapping. */
01133               encoding->sids[glyph_code] = charset->sids[j];
01134             }
01135           }
01136 
01137           FT_FRAME_EXIT();
01138         }
01139         break;
01140 
01141       case 1:
01142         {
01143           FT_UInt  nleft;
01144           FT_UInt  i = 1;
01145           FT_UInt  k;
01146 
01147 
01148           encoding->count = 0;
01149 
01150           /* Parse the Format1 ranges. */
01151           for ( j = 0;  j < count; j++, i += nleft )
01152           {
01153             /* Read the first glyph code of the range. */
01154             if ( FT_READ_BYTE( glyph_code ) )
01155               goto Exit;
01156 
01157             /* Read the number of codes in the range. */
01158             if ( FT_READ_BYTE( nleft ) )
01159               goto Exit;
01160 
01161             /* Increment nleft, so we read `nleft + 1' codes/sids. */
01162             nleft++;
01163 
01164             /* compute max number of character codes */
01165             if ( (FT_UInt)nleft > encoding->count )
01166               encoding->count = nleft;
01167 
01168             /* Fill in the range of codes/sids. */
01169             for ( k = i; k < nleft + i; k++, glyph_code++ )
01170             {
01171               /* Make sure k is not too big. */
01172               if ( k < num_glyphs && glyph_code < 256 )
01173               {
01174                 /* Assign code to GID mapping. */
01175                 encoding->codes[glyph_code] = (FT_UShort)k;
01176 
01177                 /* Assign code to SID mapping. */
01178                 encoding->sids[glyph_code] = charset->sids[k];
01179               }
01180             }
01181           }
01182 
01183           /* simple check; one never knows what can be found in a font */
01184           if ( encoding->count > 256 )
01185             encoding->count = 256;
01186         }
01187         break;
01188 
01189       default:
01190         FT_ERROR(( "cff_encoding_load: invalid table format\n" ));
01191         error = CFF_Err_Invalid_File_Format;
01192         goto Exit;
01193       }
01194 
01195       /* Parse supplemental encodings, if any. */
01196       if ( encoding->format & 0x80 )
01197       {
01198         FT_UInt  gindex;
01199 
01200 
01201         /* count supplements */
01202         if ( FT_READ_BYTE( count ) )
01203           goto Exit;
01204 
01205         for ( j = 0; j < count; j++ )
01206         {
01207           /* Read supplemental glyph code. */
01208           if ( FT_READ_BYTE( glyph_code ) )
01209             goto Exit;
01210 
01211           /* Read the SID associated with this glyph code. */
01212           if ( FT_READ_USHORT( glyph_sid ) )
01213             goto Exit;
01214 
01215           /* Assign code to SID mapping. */
01216           encoding->sids[glyph_code] = glyph_sid;
01217 
01218           /* First, look up GID which has been assigned to */
01219           /* SID glyph_sid.                                */
01220           for ( gindex = 0; gindex < num_glyphs; gindex++ )
01221           {
01222             if ( charset->sids[gindex] == glyph_sid )
01223             {
01224               encoding->codes[glyph_code] = (FT_UShort)gindex;
01225               break;
01226             }
01227           }
01228         }
01229       }
01230     }
01231     else
01232     {
01233       /* We take into account the fact a CFF font can use a predefined */
01234       /* encoding without containing all of the glyphs encoded by this */
01235       /* encoding (see the note at the end of section 12 in the CFF    */
01236       /* specification).                                               */
01237 
01238       switch ( (FT_UInt)offset )
01239       {
01240       case 0:
01241         /* First, copy the code to SID mapping. */
01242         FT_ARRAY_COPY( encoding->sids, cff_standard_encoding, 256 );
01243         goto Populate;
01244 
01245       case 1:
01246         /* First, copy the code to SID mapping. */
01247         FT_ARRAY_COPY( encoding->sids, cff_expert_encoding, 256 );
01248 
01249       Populate:
01250         /* Construct code to GID mapping from code to SID mapping */
01251         /* and charset.                                           */
01252 
01253         encoding->count = 0;
01254 
01255         error = cff_charset_compute_cids( charset, num_glyphs,
01256                                           stream->memory );
01257         if ( error )
01258           goto Exit;
01259 
01260         for ( j = 0; j < 256; j++ )
01261         {
01262           FT_UInt  sid = encoding->sids[j];
01263           FT_UInt  gid = 0;
01264 
01265 
01266           if ( sid )
01267             gid = cff_charset_cid_to_gindex( charset, sid );
01268 
01269           if ( gid != 0 )
01270           {
01271             encoding->codes[j] = (FT_UShort)gid;
01272             encoding->count    = j + 1;
01273           }
01274           else
01275           {
01276             encoding->codes[j] = 0;
01277             encoding->sids [j] = 0;
01278           }
01279         }
01280         break;
01281 
01282       default:
01283         FT_ERROR(( "cff_encoding_load: invalid table format\n" ));
01284         error = CFF_Err_Invalid_File_Format;
01285         goto Exit;
01286       }
01287     }
01288 
01289   Exit:
01290 
01291     /* Clean up if there was an error. */
01292     return error;
01293   }
01294 
01295 
01296   static FT_Error
01297   cff_subfont_load( CFF_SubFont  font,
01298                     CFF_Index    idx,
01299                     FT_UInt      font_index,
01300                     FT_Stream    stream,
01301                     FT_ULong     base_offset,
01302                     FT_Library   library )
01303   {
01304     FT_Error         error;
01305     CFF_ParserRec    parser;
01306     FT_Byte*         dict = NULL;
01307     FT_ULong         dict_len;
01308     CFF_FontRecDict  top  = &font->font_dict;
01309     CFF_Private      priv = &font->private_dict;
01310 
01311 
01312     cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict, library );
01313 
01314     /* set defaults */
01315     FT_MEM_ZERO( top, sizeof ( *top ) );
01316 
01317     top->underline_position  = -100L << 16;
01318     top->underline_thickness = 50L << 16;
01319     top->charstring_type     = 2;
01320     top->font_matrix.xx      = 0x10000L;
01321     top->font_matrix.yy      = 0x10000L;
01322     top->cid_count           = 8720;
01323 
01324     /* we use the implementation specific SID value 0xFFFF to indicate */
01325     /* missing entries                                                 */
01326     top->version             = 0xFFFFU;
01327     top->notice              = 0xFFFFU;
01328     top->copyright           = 0xFFFFU;
01329     top->full_name           = 0xFFFFU;
01330     top->family_name         = 0xFFFFU;
01331     top->weight              = 0xFFFFU;
01332     top->embedded_postscript = 0xFFFFU;
01333 
01334     top->cid_registry        = 0xFFFFU;
01335     top->cid_ordering        = 0xFFFFU;
01336     top->cid_font_name       = 0xFFFFU;
01337 
01338     error = cff_index_access_element( idx, font_index, &dict, &dict_len );
01339     if ( !error )
01340       error = cff_parser_run( &parser, dict, dict + dict_len );
01341 
01342     cff_index_forget_element( idx, &dict );
01343 
01344     if ( error )
01345       goto Exit;
01346 
01347     /* if it is a CID font, we stop there */
01348     if ( top->cid_registry != 0xFFFFU )
01349       goto Exit;
01350 
01351     /* parse the private dictionary, if any */
01352     if ( top->private_offset && top->private_size )
01353     {
01354       /* set defaults */
01355       FT_MEM_ZERO( priv, sizeof ( *priv ) );
01356 
01357       priv->blue_shift       = 7;
01358       priv->blue_fuzz        = 1;
01359       priv->lenIV            = -1;
01360       priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
01361       priv->blue_scale       = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
01362 
01363       cff_parser_init( &parser, CFF_CODE_PRIVATE, priv, library );
01364 
01365       if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) ||
01366            FT_FRAME_ENTER( font->font_dict.private_size )                 )
01367         goto Exit;
01368 
01369       error = cff_parser_run( &parser,
01370                               (FT_Byte*)stream->cursor,
01371                               (FT_Byte*)stream->limit );
01372       FT_FRAME_EXIT();
01373       if ( error )
01374         goto Exit;
01375 
01376       /* ensure that `num_blue_values' is even */
01377       priv->num_blue_values &= ~1;
01378     }
01379 
01380     /* read the local subrs, if any */
01381     if ( priv->local_subrs_offset )
01382     {
01383       if ( FT_STREAM_SEEK( base_offset + top->private_offset +
01384                            priv->local_subrs_offset ) )
01385         goto Exit;
01386 
01387       error = cff_index_init( &font->local_subrs_index, stream, 1 );
01388       if ( error )
01389         goto Exit;
01390 
01391       error = cff_index_get_pointers( &font->local_subrs_index,
01392                                       &font->local_subrs, NULL );
01393       if ( error )
01394         goto Exit;
01395     }
01396 
01397   Exit:
01398     return error;
01399   }
01400 
01401 
01402   static void
01403   cff_subfont_done( FT_Memory    memory,
01404                     CFF_SubFont  subfont )
01405   {
01406     if ( subfont )
01407     {
01408       cff_index_done( &subfont->local_subrs_index );
01409       FT_FREE( subfont->local_subrs );
01410     }
01411   }
01412 
01413 
01414   FT_LOCAL_DEF( FT_Error )
01415   cff_font_load( FT_Library library,
01416                  FT_Stream  stream,
01417                  FT_Int     face_index,
01418                  CFF_Font   font,
01419                  FT_Bool    pure_cff )
01420   {
01421     static const FT_Frame_Field  cff_header_fields[] =
01422     {
01423 #undef  FT_STRUCTURE
01424 #define FT_STRUCTURE  CFF_FontRec
01425 
01426       FT_FRAME_START( 4 ),
01427         FT_FRAME_BYTE( version_major ),
01428         FT_FRAME_BYTE( version_minor ),
01429         FT_FRAME_BYTE( header_size ),
01430         FT_FRAME_BYTE( absolute_offsize ),
01431       FT_FRAME_END
01432     };
01433 
01434     FT_Error         error;
01435     FT_Memory        memory = stream->memory;
01436     FT_ULong         base_offset;
01437     CFF_FontRecDict  dict;
01438     CFF_IndexRec     string_index;
01439 
01440 
01441     FT_ZERO( font );
01442     FT_ZERO( &string_index );
01443 
01444     font->stream = stream;
01445     font->memory = memory;
01446     dict         = &font->top_font.font_dict;
01447     base_offset  = FT_STREAM_POS();
01448 
01449     /* read CFF font header */
01450     if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) )
01451       goto Exit;
01452 
01453     /* check format */
01454     if ( font->version_major   != 1 ||
01455          font->header_size      < 4 ||
01456          font->absolute_offsize > 4 )
01457     {
01458       FT_TRACE2(( "[not a CFF font header]\n" ));
01459       error = CFF_Err_Unknown_File_Format;
01460       goto Exit;
01461     }
01462 
01463     /* skip the rest of the header */
01464     if ( FT_STREAM_SKIP( font->header_size - 4 ) )
01465       goto Exit;
01466 
01467     /* read the name, top dict, string and global subrs index */
01468     if ( FT_SET_ERROR( cff_index_init( &font->name_index,
01469                                        stream, 0 ) )                  ||
01470          FT_SET_ERROR( cff_index_init( &font->font_dict_index,
01471                                        stream, 0 ) )                  ||
01472          FT_SET_ERROR( cff_index_init( &string_index,
01473                                        stream, 1 ) )                  ||
01474          FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
01475                                        stream, 1 ) )                  ||
01476          FT_SET_ERROR( cff_index_get_pointers( &string_index,
01477                                                &font->strings,
01478                                                &font->string_pool ) ) )
01479       goto Exit;
01480 
01481     font->num_strings = string_index.count;
01482 
01483     /* well, we don't really forget the `disabled' fonts... */
01484     font->num_faces = font->name_index.count;
01485     if ( face_index >= (FT_Int)font->num_faces )
01486     {
01487       FT_ERROR(( "cff_font_load: incorrect face index = %d\n",
01488                  face_index ));
01489       error = CFF_Err_Invalid_Argument;
01490     }
01491 
01492     /* in case of a font format check, simply exit now */
01493     if ( face_index < 0 )
01494       goto Exit;
01495 
01496     /* now, parse the top-level font dictionary */
01497     error = cff_subfont_load( &font->top_font,
01498                               &font->font_dict_index,
01499                               face_index,
01500                               stream,
01501                               base_offset,
01502                               library );
01503     if ( error )
01504       goto Exit;
01505 
01506     if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) )
01507       goto Exit;
01508 
01509     error = cff_index_init( &font->charstrings_index, stream, 0 );
01510     if ( error )
01511       goto Exit;
01512 
01513     /* now, check for a CID font */
01514     if ( dict->cid_registry != 0xFFFFU )
01515     {
01516       CFF_IndexRec  fd_index;
01517       CFF_SubFont   sub;
01518       FT_UInt       idx;
01519 
01520 
01521       /* this is a CID-keyed font, we must now allocate a table of */
01522       /* sub-fonts, then load each of them separately              */
01523       if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) )
01524         goto Exit;
01525 
01526       error = cff_index_init( &fd_index, stream, 0 );
01527       if ( error )
01528         goto Exit;
01529 
01530       if ( fd_index.count > CFF_MAX_CID_FONTS )
01531       {
01532         FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" ));
01533         goto Fail_CID;
01534       }
01535 
01536       /* allocate & read each font dict independently */
01537       font->num_subfonts = fd_index.count;
01538       if ( FT_NEW_ARRAY( sub, fd_index.count ) )
01539         goto Fail_CID;
01540 
01541       /* set up pointer table */
01542       for ( idx = 0; idx < fd_index.count; idx++ )
01543         font->subfonts[idx] = sub + idx;
01544 
01545       /* now load each subfont independently */
01546       for ( idx = 0; idx < fd_index.count; idx++ )
01547       {
01548         sub = font->subfonts[idx];
01549         error = cff_subfont_load( sub, &fd_index, idx,
01550                                   stream, base_offset, library );
01551         if ( error )
01552           goto Fail_CID;
01553       }
01554 
01555       /* now load the FD Select array */
01556       error = CFF_Load_FD_Select( &font->fd_select,
01557                                   font->charstrings_index.count,
01558                                   stream,
01559                                   base_offset + dict->cid_fd_select_offset );
01560 
01561     Fail_CID:
01562       cff_index_done( &fd_index );
01563 
01564       if ( error )
01565         goto Exit;
01566     }
01567     else
01568       font->num_subfonts = 0;
01569 
01570     /* read the charstrings index now */
01571     if ( dict->charstrings_offset == 0 )
01572     {
01573       FT_ERROR(( "cff_font_load: no charstrings offset\n" ));
01574       error = CFF_Err_Unknown_File_Format;
01575       goto Exit;
01576     }
01577 
01578     font->num_glyphs = font->charstrings_index.count;
01579 
01580     error = cff_index_get_pointers( &font->global_subrs_index,
01581                                     &font->global_subrs, NULL );
01582 
01583     if ( error )
01584       goto Exit;
01585 
01586     /* read the Charset and Encoding tables if available */
01587     if ( font->num_glyphs > 0 )
01588     {
01589       FT_Bool  invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff );
01590 
01591 
01592       error = cff_charset_load( &font->charset, font->num_glyphs, stream,
01593                                 base_offset, dict->charset_offset, invert );
01594       if ( error )
01595         goto Exit;
01596 
01597       /* CID-keyed CFFs don't have an encoding */
01598       if ( dict->cid_registry == 0xFFFFU )
01599       {
01600         error = cff_encoding_load( &font->encoding,
01601                                    &font->charset,
01602                                    font->num_glyphs,
01603                                    stream,
01604                                    base_offset,
01605                                    dict->encoding_offset );
01606         if ( error )
01607           goto Exit;
01608       }
01609     }
01610 
01611     /* get the font name (/CIDFontName for CID-keyed fonts, */
01612     /* /FontName otherwise)                                 */
01613     font->font_name = cff_index_get_name( font, face_index );
01614 
01615   Exit:
01616     cff_index_done( &string_index );
01617 
01618     return error;
01619   }
01620 
01621 
01622   FT_LOCAL_DEF( void )
01623   cff_font_done( CFF_Font  font )
01624   {
01625     FT_Memory  memory = font->memory;
01626     FT_UInt    idx;
01627 
01628 
01629     cff_index_done( &font->global_subrs_index );
01630     cff_index_done( &font->font_dict_index );
01631     cff_index_done( &font->name_index );
01632     cff_index_done( &font->charstrings_index );
01633 
01634     /* release font dictionaries, but only if working with */
01635     /* a CID keyed CFF font                                */
01636     if ( font->num_subfonts > 0 )
01637     {
01638       for ( idx = 0; idx < font->num_subfonts; idx++ )
01639         cff_subfont_done( memory, font->subfonts[idx] );
01640 
01641       /* the subfonts array has been allocated as a single block */
01642       FT_FREE( font->subfonts[0] );
01643     }
01644 
01645     cff_encoding_done( &font->encoding );
01646     cff_charset_done( &font->charset, font->stream );
01647 
01648     cff_subfont_done( memory, &font->top_font );
01649 
01650     CFF_Done_FD_Select( &font->fd_select, font->stream );
01651 
01652     FT_FREE( font->font_info );
01653 
01654     FT_FREE( font->font_name );
01655     FT_FREE( font->global_subrs );
01656     FT_FREE( font->strings );
01657     FT_FREE( font->string_pool );
01658   }
01659 
01660 
01661 /* END */

Generated on Sat May 26 2012 04:32:40 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.