ReactOS Fundraising Campaign 2012
 
€ 3,303 / € 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

t42parse.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  t42parse.c                                                             */
00004 /*                                                                         */
00005 /*    Type 42 font parser (body).                                          */
00006 /*                                                                         */
00007 /*  Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by      */
00008 /*  Roberto Alameda.                                                       */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 
00019 #include "t42parse.h"
00020 #include "t42error.h"
00021 #include FT_INTERNAL_DEBUG_H
00022 #include FT_INTERNAL_STREAM_H
00023 #include FT_INTERNAL_POSTSCRIPT_AUX_H
00024 
00025 
00026   /*************************************************************************/
00027   /*                                                                       */
00028   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00029   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00030   /* messages during execution.                                            */
00031   /*                                                                       */
00032 #undef  FT_COMPONENT
00033 #define FT_COMPONENT  trace_t42
00034 
00035 
00036   static void
00037   t42_parse_font_matrix( T42_Face    face,
00038                          T42_Loader  loader );
00039   static void
00040   t42_parse_encoding( T42_Face    face,
00041                       T42_Loader  loader );
00042 
00043   static void
00044   t42_parse_charstrings( T42_Face    face,
00045                          T42_Loader  loader );
00046 
00047   static void
00048   t42_parse_sfnts( T42_Face    face,
00049                    T42_Loader  loader );
00050 
00051 
00052   /* as Type42 fonts have no Private dict,         */
00053   /* we set the last argument of T1_FIELD_XXX to 0 */
00054   static const
00055   T1_FieldRec  t42_keywords[] =
00056   {
00057 
00058 #undef  FT_STRUCTURE
00059 #define FT_STRUCTURE  T1_FontInfo
00060 #undef  T1CODE
00061 #define T1CODE        T1_FIELD_LOCATION_FONT_INFO
00062 
00063     T1_FIELD_STRING( "version",            version,             0 )
00064     T1_FIELD_STRING( "Notice",             notice,              0 )
00065     T1_FIELD_STRING( "FullName",           full_name,           0 )
00066     T1_FIELD_STRING( "FamilyName",         family_name,         0 )
00067     T1_FIELD_STRING( "Weight",             weight,              0 )
00068     T1_FIELD_NUM   ( "ItalicAngle",        italic_angle,        0 )
00069     T1_FIELD_BOOL  ( "isFixedPitch",       is_fixed_pitch,      0 )
00070     T1_FIELD_NUM   ( "UnderlinePosition",  underline_position,  0 )
00071     T1_FIELD_NUM   ( "UnderlineThickness", underline_thickness, 0 )
00072 
00073 #undef  FT_STRUCTURE
00074 #define FT_STRUCTURE  PS_FontExtraRec
00075 #undef  T1CODE
00076 #define T1CODE        T1_FIELD_LOCATION_FONT_EXTRA
00077 
00078     T1_FIELD_NUM   ( "FSType",             fs_type,             0 )
00079 
00080 #undef  FT_STRUCTURE
00081 #define FT_STRUCTURE  T1_FontRec
00082 #undef  T1CODE
00083 #define T1CODE        T1_FIELD_LOCATION_FONT_DICT
00084 
00085     T1_FIELD_KEY  ( "FontName",    font_name,    0 )
00086     T1_FIELD_NUM  ( "PaintType",   paint_type,   0 )
00087     T1_FIELD_NUM  ( "FontType",    font_type,    0 )
00088     T1_FIELD_FIXED( "StrokeWidth", stroke_width, 0 )
00089 
00090 #undef  FT_STRUCTURE
00091 #define FT_STRUCTURE  FT_BBox
00092 #undef  T1CODE
00093 #define T1CODE        T1_FIELD_LOCATION_BBOX
00094 
00095     T1_FIELD_BBOX("FontBBox", xMin, 0 )
00096 
00097     T1_FIELD_CALLBACK( "FontMatrix",  t42_parse_font_matrix, 0 )
00098     T1_FIELD_CALLBACK( "Encoding",    t42_parse_encoding,    0 )
00099     T1_FIELD_CALLBACK( "CharStrings", t42_parse_charstrings, 0 )
00100     T1_FIELD_CALLBACK( "sfnts",       t42_parse_sfnts,       0 )
00101 
00102     { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
00103   };
00104 
00105 
00106 #define T1_Add_Table( p, i, o, l )  (p)->funcs.add( (p), i, o, l )
00107 #define T1_Done_Table( p )          \
00108           do                        \
00109           {                         \
00110             if ( (p)->funcs.done )  \
00111               (p)->funcs.done( p ); \
00112           } while ( 0 )
00113 #define T1_Release_Table( p )          \
00114           do                           \
00115           {                            \
00116             if ( (p)->funcs.release )  \
00117               (p)->funcs.release( p ); \
00118           } while ( 0 )
00119 
00120 #define T1_Skip_Spaces( p )    (p)->root.funcs.skip_spaces( &(p)->root )
00121 #define T1_Skip_PS_Token( p )  (p)->root.funcs.skip_PS_token( &(p)->root )
00122 
00123 #define T1_ToInt( p )                          \
00124           (p)->root.funcs.to_int( &(p)->root )
00125 #define T1_ToBytes( p, b, m, n, d )                          \
00126           (p)->root.funcs.to_bytes( &(p)->root, b, m, n, d )
00127 
00128 #define T1_ToFixedArray( p, m, f, t )                           \
00129           (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
00130 #define T1_ToToken( p, t )                          \
00131           (p)->root.funcs.to_token( &(p)->root, t )
00132 
00133 #define T1_Load_Field( p, f, o, m, pf )                         \
00134           (p)->root.funcs.load_field( &(p)->root, f, o, m, pf )
00135 #define T1_Load_Field_Table( p, f, o, m, pf )                         \
00136           (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )
00137 
00138 
00139   /********************* Parsing Functions ******************/
00140 
00141   FT_LOCAL_DEF( FT_Error )
00142   t42_parser_init( T42_Parser     parser,
00143                    FT_Stream      stream,
00144                    FT_Memory      memory,
00145                    PSAux_Service  psaux )
00146   {
00147     FT_Error  error = T42_Err_Ok;
00148     FT_Long   size;
00149 
00150 
00151     psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
00152 
00153     parser->stream    = stream;
00154     parser->base_len  = 0;
00155     parser->base_dict = 0;
00156     parser->in_memory = 0;
00157 
00158     /*******************************************************************/
00159     /*                                                                 */
00160     /* Here a short summary of what is going on:                       */
00161     /*                                                                 */
00162     /*   When creating a new Type 42 parser, we try to locate and load */
00163     /*   the base dictionary, loading the whole font into memory.      */
00164     /*                                                                 */
00165     /*   When `loading' the base dictionary, we only set up pointers   */
00166     /*   in the case of a memory-based stream.  Otherwise, we allocate */
00167     /*   and load the base dictionary in it.                           */
00168     /*                                                                 */
00169     /*   parser->in_memory is set if we have a memory stream.          */
00170     /*                                                                 */
00171 
00172     if ( FT_STREAM_SEEK( 0L ) ||
00173          FT_FRAME_ENTER( 17 ) )
00174       goto Exit;
00175 
00176     if ( ft_memcmp( stream->cursor, "%!PS-TrueTypeFont", 17 ) != 0 )
00177     {
00178       FT_TRACE2(( "not a Type42 font\n" ));
00179       error = T42_Err_Unknown_File_Format;
00180     }
00181 
00182     FT_FRAME_EXIT();
00183 
00184     if ( error || FT_STREAM_SEEK( 0 ) )
00185       goto Exit;
00186 
00187     size = stream->size;
00188 
00189     /* now, try to load `size' bytes of the `base' dictionary we */
00190     /* found previously                                          */
00191 
00192     /* if it is a memory-based resource, set up pointers */
00193     if ( !stream->read )
00194     {
00195       parser->base_dict = (FT_Byte*)stream->base + stream->pos;
00196       parser->base_len  = size;
00197       parser->in_memory = 1;
00198 
00199       /* check that the `size' field is valid */
00200       if ( FT_STREAM_SKIP( size ) )
00201         goto Exit;
00202     }
00203     else
00204     {
00205       /* read segment in memory */
00206       if ( FT_ALLOC( parser->base_dict, size )       ||
00207            FT_STREAM_READ( parser->base_dict, size ) )
00208         goto Exit;
00209 
00210       parser->base_len = size;
00211     }
00212 
00213     parser->root.base   = parser->base_dict;
00214     parser->root.cursor = parser->base_dict;
00215     parser->root.limit  = parser->root.cursor + parser->base_len;
00216 
00217   Exit:
00218     if ( error && !parser->in_memory )
00219       FT_FREE( parser->base_dict );
00220 
00221     return error;
00222   }
00223 
00224 
00225   FT_LOCAL_DEF( void )
00226   t42_parser_done( T42_Parser  parser )
00227   {
00228     FT_Memory  memory = parser->root.memory;
00229 
00230 
00231     /* free the base dictionary only when we have a disk stream */
00232     if ( !parser->in_memory )
00233       FT_FREE( parser->base_dict );
00234 
00235     parser->root.funcs.done( &parser->root );
00236   }
00237 
00238 
00239   static int
00240   t42_is_space( FT_Byte  c )
00241   {
00242     return ( c == ' '  || c == '\t'              ||
00243              c == '\r' || c == '\n' || c == '\f' ||
00244              c == '\0'                           );
00245   }
00246 
00247 
00248   static void
00249   t42_parse_font_matrix( T42_Face    face,
00250                          T42_Loader  loader )
00251   {
00252     T42_Parser  parser = &loader->parser;
00253     FT_Matrix*  matrix = &face->type1.font_matrix;
00254     FT_Vector*  offset = &face->type1.font_offset;
00255     FT_Face     root   = (FT_Face)&face->root;
00256     FT_Fixed    temp[6];
00257     FT_Fixed    temp_scale;
00258 
00259 
00260     (void)T1_ToFixedArray( parser, 6, temp, 3 );
00261 
00262     temp_scale = FT_ABS( temp[3] );
00263 
00264     /* Set Units per EM based on FontMatrix values.  We set the value to */
00265     /* 1000 / temp_scale, because temp_scale was already multiplied by   */
00266     /* 1000 (in t1_tofixed, from psobjs.c).                              */
00267 
00268     root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L,
00269                                                  temp_scale ) >> 16 );
00270 
00271     /* we need to scale the values by 1.0/temp_scale */
00272     if ( temp_scale != 0x10000L )
00273     {
00274       temp[0] = FT_DivFix( temp[0], temp_scale );
00275       temp[1] = FT_DivFix( temp[1], temp_scale );
00276       temp[2] = FT_DivFix( temp[2], temp_scale );
00277       temp[4] = FT_DivFix( temp[4], temp_scale );
00278       temp[5] = FT_DivFix( temp[5], temp_scale );
00279       temp[3] = 0x10000L;
00280     }
00281 
00282     matrix->xx = temp[0];
00283     matrix->yx = temp[1];
00284     matrix->xy = temp[2];
00285     matrix->yy = temp[3];
00286 
00287     /* note that the offsets must be expressed in integer font units */
00288     offset->x = temp[4] >> 16;
00289     offset->y = temp[5] >> 16;
00290   }
00291 
00292 
00293   static void
00294   t42_parse_encoding( T42_Face    face,
00295                       T42_Loader  loader )
00296   {
00297     T42_Parser  parser = &loader->parser;
00298     FT_Byte*    cur;
00299     FT_Byte*    limit  = parser->root.limit;
00300 
00301     PSAux_Service  psaux  = (PSAux_Service)face->psaux;
00302 
00303 
00304     T1_Skip_Spaces( parser );
00305     cur = parser->root.cursor;
00306     if ( cur >= limit )
00307     {
00308       FT_ERROR(( "t42_parse_encoding: out of bounds\n" ));
00309       parser->root.error = T42_Err_Invalid_File_Format;
00310       return;
00311     }
00312 
00313     /* if we have a number or `[', the encoding is an array, */
00314     /* and we must load it now                               */
00315     if ( ft_isdigit( *cur ) || *cur == '[' )
00316     {
00317       T1_Encoding  encode          = &face->type1.encoding;
00318       FT_UInt      count, n;
00319       PS_Table     char_table      = &loader->encoding_table;
00320       FT_Memory    memory          = parser->root.memory;
00321       FT_Error     error;
00322       FT_Bool      only_immediates = 0;
00323 
00324 
00325       /* read the number of entries in the encoding; should be 256 */
00326       if ( *cur == '[' )
00327       {
00328         count           = 256;
00329         only_immediates = 1;
00330         parser->root.cursor++;
00331       }
00332       else
00333         count = (FT_UInt)T1_ToInt( parser );
00334 
00335       T1_Skip_Spaces( parser );
00336       if ( parser->root.cursor >= limit )
00337         return;
00338 
00339       /* we use a T1_Table to store our charnames */
00340       loader->num_chars = encode->num_chars = count;
00341       if ( FT_NEW_ARRAY( encode->char_index, count )     ||
00342            FT_NEW_ARRAY( encode->char_name,  count )     ||
00343            FT_SET_ERROR( psaux->ps_table_funcs->init(
00344                            char_table, count, memory ) ) )
00345       {
00346         parser->root.error = error;
00347         return;
00348       }
00349 
00350       /* We need to `zero' out encoding_table.elements */
00351       for ( n = 0; n < count; n++ )
00352       {
00353         char*  notdef = (char *)".notdef";
00354 
00355 
00356         T1_Add_Table( char_table, n, notdef, 8 );
00357       }
00358 
00359       /* Now we need to read records of the form                */
00360       /*                                                        */
00361       /*   ... charcode /charname ...                           */
00362       /*                                                        */
00363       /* for each entry in our table.                           */
00364       /*                                                        */
00365       /* We simply look for a number followed by an immediate   */
00366       /* name.  Note that this ignores correctly the sequence   */
00367       /* that is often seen in type42 fonts:                    */
00368       /*                                                        */
00369       /*   0 1 255 { 1 index exch /.notdef put } for dup        */
00370       /*                                                        */
00371       /* used to clean the encoding array before anything else. */
00372       /*                                                        */
00373       /* Alternatively, if the array is directly given as       */
00374       /*                                                        */
00375       /*   /Encoding [ ... ]                                    */
00376       /*                                                        */
00377       /* we only read immediates.                               */
00378 
00379       n = 0;
00380       T1_Skip_Spaces( parser );
00381 
00382       while ( parser->root.cursor < limit )
00383       {
00384         cur = parser->root.cursor;
00385 
00386         /* we stop when we encounter `def' or `]' */
00387         if ( *cur == 'd' && cur + 3 < limit )
00388         {
00389           if ( cur[1] == 'e'          &&
00390                cur[2] == 'f'          &&
00391                t42_is_space( cur[3] ) )
00392           {
00393             FT_TRACE6(( "encoding end\n" ));
00394             cur += 3;
00395             break;
00396           }
00397         }
00398         if ( *cur == ']' )
00399         {
00400           FT_TRACE6(( "encoding end\n" ));
00401           cur++;
00402           break;
00403         }
00404 
00405         /* check whether we have found an entry */
00406         if ( ft_isdigit( *cur ) || only_immediates )
00407         {
00408           FT_Int  charcode;
00409 
00410 
00411           if ( only_immediates )
00412             charcode = n;
00413           else
00414           {
00415             charcode = (FT_Int)T1_ToInt( parser );
00416             T1_Skip_Spaces( parser );
00417           }
00418 
00419           cur = parser->root.cursor;
00420 
00421           if ( *cur == '/' && cur + 2 < limit && n < count )
00422           {
00423             FT_PtrDist  len;
00424 
00425 
00426             cur++;
00427 
00428             parser->root.cursor = cur;
00429             T1_Skip_PS_Token( parser );
00430             if ( parser->root.error )
00431               return;
00432 
00433             len = parser->root.cursor - cur;
00434 
00435             parser->root.error = T1_Add_Table( char_table, charcode,
00436                                                cur, len + 1 );
00437             if ( parser->root.error )
00438               return;
00439             char_table->elements[charcode][len] = '\0';
00440 
00441             n++;
00442           }
00443         }
00444         else
00445         {
00446           T1_Skip_PS_Token( parser );
00447           if ( parser->root.error )
00448             return;
00449         }
00450 
00451         T1_Skip_Spaces( parser );
00452       }
00453 
00454       face->type1.encoding_type  = T1_ENCODING_TYPE_ARRAY;
00455       parser->root.cursor        = cur;
00456     }
00457 
00458     /* Otherwise, we should have either `StandardEncoding', */
00459     /* `ExpertEncoding', or `ISOLatin1Encoding'             */
00460     else
00461     {
00462       if ( cur + 17 < limit                                            &&
00463            ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
00464         face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;
00465 
00466       else if ( cur + 15 < limit                                          &&
00467                 ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
00468         face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;
00469 
00470       else if ( cur + 18 < limit                                             &&
00471                 ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
00472         face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;
00473 
00474       else
00475       {
00476         FT_ERROR(( "t42_parse_encoding: invalid token\n" ));
00477         parser->root.error = T42_Err_Invalid_File_Format;
00478       }
00479     }
00480   }
00481 
00482 
00483   typedef enum  T42_Load_Status_
00484   {
00485     BEFORE_START,
00486     BEFORE_TABLE_DIR,
00487     OTHER_TABLES
00488 
00489   } T42_Load_Status;
00490 
00491 
00492   static void
00493   t42_parse_sfnts( T42_Face    face,
00494                    T42_Loader  loader )
00495   {
00496     T42_Parser  parser = &loader->parser;
00497     FT_Memory   memory = parser->root.memory;
00498     FT_Byte*    cur;
00499     FT_Byte*    limit  = parser->root.limit;
00500     FT_Error    error;
00501     FT_Int      num_tables = 0;
00502     FT_ULong    count, ttf_size = 0;
00503 
00504     FT_Long     n, string_size, old_string_size, real_size;
00505     FT_Byte*    string_buf = NULL;
00506     FT_Bool     allocated  = 0;
00507 
00508     T42_Load_Status  status;
00509 
00510 
00511     /* The format is                                */
00512     /*                                              */
00513     /*   /sfnts [ <hexstring> <hexstring> ... ] def */
00514     /*                                              */
00515     /* or                                           */
00516     /*                                              */
00517     /*   /sfnts [                                   */
00518     /*      <num_bin_bytes> RD <binary data>        */
00519     /*      <num_bin_bytes> RD <binary data>        */
00520     /*      ...                                     */
00521     /*   ] def                                      */
00522     /*                                              */
00523     /* with exactly one space after the `RD' token. */
00524 
00525     T1_Skip_Spaces( parser );
00526 
00527     if ( parser->root.cursor >= limit || *parser->root.cursor++ != '[' )
00528     {
00529       FT_ERROR(( "t42_parse_sfnts: can't find begin of sfnts vector\n" ));
00530       error = T42_Err_Invalid_File_Format;
00531       goto Fail;
00532     }
00533 
00534     T1_Skip_Spaces( parser );
00535     status          = BEFORE_START;
00536     string_size     = 0;
00537     old_string_size = 0;
00538     count           = 0;
00539 
00540     while ( parser->root.cursor < limit )
00541     {
00542       cur = parser->root.cursor;
00543 
00544       if ( *cur == ']' )
00545       {
00546         parser->root.cursor++;
00547         goto Exit;
00548       }
00549 
00550       else if ( *cur == '<' )
00551       {
00552         T1_Skip_PS_Token( parser );
00553         if ( parser->root.error )
00554           goto Exit;
00555 
00556         /* don't include delimiters */
00557         string_size = (FT_Long)( ( parser->root.cursor - cur - 2 + 1 ) / 2 );
00558         if ( FT_REALLOC( string_buf, old_string_size, string_size ) )
00559           goto Fail;
00560 
00561         allocated = 1;
00562 
00563         parser->root.cursor = cur;
00564         (void)T1_ToBytes( parser, string_buf, string_size, &real_size, 1 );
00565         old_string_size = string_size;
00566         string_size = real_size;
00567       }
00568 
00569       else if ( ft_isdigit( *cur ) )
00570       {
00571         if ( allocated )
00572         {
00573           FT_ERROR(( "t42_parse_sfnts: "
00574                      "can't handle mixed binary and hex strings\n" ));
00575           error = T42_Err_Invalid_File_Format;
00576           goto Fail;
00577         }
00578 
00579         string_size = T1_ToInt( parser );
00580         if ( string_size < 0 )
00581         {
00582           FT_ERROR(( "t42_parse_sfnts: invalid string size\n" ));
00583           error = T42_Err_Invalid_File_Format;
00584           goto Fail;
00585         }
00586 
00587         T1_Skip_PS_Token( parser );             /* `RD' */
00588         if ( parser->root.error )
00589           return;
00590 
00591         string_buf = parser->root.cursor + 1;   /* one space after `RD' */
00592 
00593         if ( limit - parser->root.cursor < string_size )
00594         {
00595           FT_ERROR(( "t42_parse_sfnts: too many binary data\n" ));
00596           error = T42_Err_Invalid_File_Format;
00597           goto Fail;
00598         }
00599         else
00600           parser->root.cursor += string_size + 1;
00601       }
00602 
00603       if ( !string_buf )
00604       {
00605         FT_ERROR(( "t42_parse_sfnts: invalid data in sfnts array\n" ));
00606         error = T42_Err_Invalid_File_Format;
00607         goto Fail;
00608       }
00609 
00610       /* A string can have a trailing zero byte for padding.  Ignore it. */
00611       if ( string_buf[string_size - 1] == 0 && ( string_size % 2 == 1 ) )
00612         string_size--;
00613 
00614       if ( !string_size )
00615       {
00616         FT_ERROR(( "t42_parse_sfnts: invalid string\n" ));
00617         error = T42_Err_Invalid_File_Format;
00618         goto Fail;
00619       }
00620 
00621       for ( n = 0; n < string_size; n++ )
00622       {
00623         switch ( status )
00624         {
00625         case BEFORE_START:
00626           /* load offset table, 12 bytes */
00627           if ( count < 12 )
00628           {
00629             face->ttf_data[count++] = string_buf[n];
00630             continue;
00631           }
00632           else
00633           {
00634             num_tables = 16 * face->ttf_data[4] + face->ttf_data[5];
00635             status     = BEFORE_TABLE_DIR;
00636             ttf_size   = 12 + 16 * num_tables;
00637 
00638             if ( FT_REALLOC( face->ttf_data, 12, ttf_size ) )
00639               goto Fail;
00640           }
00641           /* fall through */
00642 
00643         case BEFORE_TABLE_DIR:
00644           /* the offset table is read; read the table directory */
00645           if ( count < ttf_size )
00646           {
00647             face->ttf_data[count++] = string_buf[n];
00648             continue;
00649           }
00650           else
00651           {
00652             int       i;
00653             FT_ULong  len;
00654 
00655 
00656             for ( i = 0; i < num_tables; i++ )
00657             {
00658               FT_Byte*  p = face->ttf_data + 12 + 16 * i + 12;
00659 
00660 
00661               len = FT_PEEK_ULONG( p );
00662 
00663               /* Pad to a 4-byte boundary length */
00664               ttf_size += ( len + 3 ) & ~3;
00665             }
00666 
00667             status         = OTHER_TABLES;
00668             face->ttf_size = ttf_size;
00669 
00670             /* there are no more than 256 tables, so no size check here */
00671             if ( FT_REALLOC( face->ttf_data, 12 + 16 * num_tables,
00672                              ttf_size + 1 ) )
00673               goto Fail;
00674           }
00675           /* fall through */
00676 
00677         case OTHER_TABLES:
00678           /* all other tables are just copied */
00679           if ( count >= ttf_size )
00680           {
00681             FT_ERROR(( "t42_parse_sfnts: too many binary data\n" ));
00682             error = T42_Err_Invalid_File_Format;
00683             goto Fail;
00684           }
00685           face->ttf_data[count++] = string_buf[n];
00686         }
00687       }
00688 
00689       T1_Skip_Spaces( parser );
00690     }
00691 
00692     /* if control reaches this point, the format was not valid */
00693     error = T42_Err_Invalid_File_Format;
00694 
00695   Fail:
00696     parser->root.error = error;
00697 
00698   Exit:
00699     if ( allocated )
00700       FT_FREE( string_buf );
00701   }
00702 
00703 
00704   static void
00705   t42_parse_charstrings( T42_Face    face,
00706                          T42_Loader  loader )
00707   {
00708     T42_Parser     parser       = &loader->parser;
00709     PS_Table       code_table   = &loader->charstrings;
00710     PS_Table       name_table   = &loader->glyph_names;
00711     PS_Table       swap_table   = &loader->swap_table;
00712     FT_Memory      memory       = parser->root.memory;
00713     FT_Error       error;
00714 
00715     PSAux_Service  psaux        = (PSAux_Service)face->psaux;
00716 
00717     FT_Byte*       cur;
00718     FT_Byte*       limit        = parser->root.limit;
00719     FT_UInt        n;
00720     FT_UInt        notdef_index = 0;
00721     FT_Byte        notdef_found = 0;
00722 
00723 
00724     T1_Skip_Spaces( parser );
00725 
00726     if ( parser->root.cursor >= limit )
00727     {
00728       FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
00729       error = T42_Err_Invalid_File_Format;
00730       goto Fail;
00731     }
00732 
00733     if ( ft_isdigit( *parser->root.cursor ) )
00734     {
00735       loader->num_glyphs = (FT_UInt)T1_ToInt( parser );
00736       if ( parser->root.error )
00737         return;
00738     }
00739     else if ( *parser->root.cursor == '<' )
00740     {
00741       /* We have `<< ... >>'.  Count the number of `/' in the dictionary */
00742       /* to get its size.                                                */
00743       FT_UInt  count = 0;
00744 
00745 
00746       T1_Skip_PS_Token( parser );
00747       if ( parser->root.error )
00748         return;
00749       T1_Skip_Spaces( parser );
00750       cur = parser->root.cursor;
00751 
00752       while ( parser->root.cursor < limit )
00753       {
00754         if ( *parser->root.cursor == '/' )
00755           count++;
00756         else if ( *parser->root.cursor == '>' )
00757         {
00758           loader->num_glyphs  = count;
00759           parser->root.cursor = cur;        /* rewind */
00760           break;
00761         }
00762         T1_Skip_PS_Token( parser );
00763         if ( parser->root.error )
00764           return;
00765         T1_Skip_Spaces( parser );
00766       }
00767     }
00768     else
00769     {
00770       FT_ERROR(( "t42_parse_charstrings: invalid token\n" ));
00771       error = T42_Err_Invalid_File_Format;
00772       goto Fail;
00773     }
00774 
00775     if ( parser->root.cursor >= limit )
00776     {
00777       FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
00778       error = T42_Err_Invalid_File_Format;
00779       goto Fail;
00780     }
00781 
00782     /* initialize tables */
00783 
00784     error = psaux->ps_table_funcs->init( code_table,
00785                                          loader->num_glyphs,
00786                                          memory );
00787     if ( error )
00788       goto Fail;
00789 
00790     error = psaux->ps_table_funcs->init( name_table,
00791                                          loader->num_glyphs,
00792                                          memory );
00793     if ( error )
00794       goto Fail;
00795 
00796     /* Initialize table for swapping index notdef_index and */
00797     /* index 0 names and codes (if necessary).              */
00798 
00799     error = psaux->ps_table_funcs->init( swap_table, 4, memory );
00800     if ( error )
00801       goto Fail;
00802 
00803     n = 0;
00804 
00805     for (;;)
00806     {
00807       /* The format is simple:                   */
00808       /*   `/glyphname' + index [+ def]          */
00809 
00810       T1_Skip_Spaces( parser );
00811 
00812       cur = parser->root.cursor;
00813       if ( cur >= limit )
00814         break;
00815 
00816       /* We stop when we find an `end' keyword or '>' */
00817       if ( *cur   == 'e'          &&
00818            cur + 3 < limit        &&
00819            cur[1] == 'n'          &&
00820            cur[2] == 'd'          &&
00821            t42_is_space( cur[3] ) )
00822         break;
00823       if ( *cur == '>' )
00824         break;
00825 
00826       T1_Skip_PS_Token( parser );
00827       if ( parser->root.error )
00828         return;
00829 
00830       if ( *cur == '/' )
00831       {
00832         FT_PtrDist  len;
00833 
00834 
00835         if ( cur + 1 >= limit )
00836         {
00837           FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
00838           error = T42_Err_Invalid_File_Format;
00839           goto Fail;
00840         }
00841 
00842         cur++;                              /* skip `/' */
00843         len = parser->root.cursor - cur;
00844 
00845         error = T1_Add_Table( name_table, n, cur, len + 1 );
00846         if ( error )
00847           goto Fail;
00848 
00849         /* add a trailing zero to the name table */
00850         name_table->elements[n][len] = '\0';
00851 
00852         /* record index of /.notdef */
00853         if ( *cur == '.'                                              &&
00854              ft_strcmp( ".notdef",
00855                         (const char*)(name_table->elements[n]) ) == 0 )
00856         {
00857           notdef_index = n;
00858           notdef_found = 1;
00859         }
00860 
00861         T1_Skip_Spaces( parser );
00862 
00863         cur = parser->root.cursor;
00864 
00865         (void)T1_ToInt( parser );
00866         if ( parser->root.cursor >= limit )
00867         {
00868           FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
00869           error = T42_Err_Invalid_File_Format;
00870           goto Fail;
00871         }
00872 
00873         len = parser->root.cursor - cur;
00874 
00875         error = T1_Add_Table( code_table, n, cur, len + 1 );
00876         if ( error )
00877           goto Fail;
00878 
00879         code_table->elements[n][len] = '\0';
00880 
00881         n++;
00882         if ( n >= loader->num_glyphs )
00883           break;
00884       }
00885     }
00886 
00887     loader->num_glyphs = n;
00888 
00889     if ( !notdef_found )
00890     {
00891       FT_ERROR(( "t42_parse_charstrings: no /.notdef glyph\n" ));
00892       error = T42_Err_Invalid_File_Format;
00893       goto Fail;
00894     }
00895 
00896     /* if /.notdef does not occupy index 0, do our magic. */
00897     if ( ft_strcmp( (const char*)".notdef",
00898                     (const char*)name_table->elements[0] ) )
00899     {
00900       /* Swap glyph in index 0 with /.notdef glyph.  First, add index 0  */
00901       /* name and code entries to swap_table.  Then place notdef_index   */
00902       /* name and code entries into swap_table.  Then swap name and code */
00903       /* entries at indices notdef_index and 0 using values stored in    */
00904       /* swap_table.                                                     */
00905 
00906       /* Index 0 name */
00907       error = T1_Add_Table( swap_table, 0,
00908                             name_table->elements[0],
00909                             name_table->lengths [0] );
00910       if ( error )
00911         goto Fail;
00912 
00913       /* Index 0 code */
00914       error = T1_Add_Table( swap_table, 1,
00915                             code_table->elements[0],
00916                             code_table->lengths [0] );
00917       if ( error )
00918         goto Fail;
00919 
00920       /* Index notdef_index name */
00921       error = T1_Add_Table( swap_table, 2,
00922                             name_table->elements[notdef_index],
00923                             name_table->lengths [notdef_index] );
00924       if ( error )
00925         goto Fail;
00926 
00927       /* Index notdef_index code */
00928       error = T1_Add_Table( swap_table, 3,
00929                             code_table->elements[notdef_index],
00930                             code_table->lengths [notdef_index] );
00931       if ( error )
00932         goto Fail;
00933 
00934       error = T1_Add_Table( name_table, notdef_index,
00935                             swap_table->elements[0],
00936                             swap_table->lengths [0] );
00937       if ( error )
00938         goto Fail;
00939 
00940       error = T1_Add_Table( code_table, notdef_index,
00941                             swap_table->elements[1],
00942                             swap_table->lengths [1] );
00943       if ( error )
00944         goto Fail;
00945 
00946       error = T1_Add_Table( name_table, 0,
00947                             swap_table->elements[2],
00948                             swap_table->lengths [2] );
00949       if ( error )
00950         goto Fail;
00951 
00952       error = T1_Add_Table( code_table, 0,
00953                             swap_table->elements[3],
00954                             swap_table->lengths [3] );
00955       if ( error )
00956         goto Fail;
00957 
00958     }
00959 
00960     return;
00961 
00962   Fail:
00963     parser->root.error = error;
00964   }
00965 
00966 
00967   static FT_Error
00968   t42_load_keyword( T42_Face    face,
00969                     T42_Loader  loader,
00970                     T1_Field    field )
00971   {
00972     FT_Error  error;
00973     void*     dummy_object;
00974     void**    objects;
00975     FT_UInt   max_objects = 0;
00976 
00977 
00978     /* if the keyword has a dedicated callback, call it */
00979     if ( field->type == T1_FIELD_TYPE_CALLBACK )
00980     {
00981       field->reader( (FT_Face)face, loader );
00982       error = loader->parser.root.error;
00983       goto Exit;
00984     }
00985 
00986     /* now the keyword is either a simple field or a table of fields; */
00987     /* we are now going to take care of it                            */
00988 
00989     switch ( field->location )
00990     {
00991     case T1_FIELD_LOCATION_FONT_INFO:
00992       dummy_object = &face->type1.font_info;
00993       break;
00994 
00995     case T1_FIELD_LOCATION_FONT_EXTRA:
00996       dummy_object = &face->type1.font_extra;
00997       break;
00998 
00999     case T1_FIELD_LOCATION_BBOX:
01000       dummy_object = &face->type1.font_bbox;
01001       break;
01002 
01003     default:
01004       dummy_object = &face->type1;
01005     }
01006 
01007     objects = &dummy_object;
01008 
01009     if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
01010          field->type == T1_FIELD_TYPE_FIXED_ARRAY   )
01011       error = T1_Load_Field_Table( &loader->parser, field,
01012                                    objects, max_objects, 0 );
01013     else
01014       error = T1_Load_Field( &loader->parser, field,
01015                              objects, max_objects, 0 );
01016 
01017    Exit:
01018     return error;
01019   }
01020 
01021 
01022   FT_LOCAL_DEF( FT_Error )
01023   t42_parse_dict( T42_Face    face,
01024                   T42_Loader  loader,
01025                   FT_Byte*    base,
01026                   FT_Long     size )
01027   {
01028     T42_Parser  parser     = &loader->parser;
01029     FT_Byte*    limit;
01030     FT_Int      n_keywords = (FT_Int)( sizeof ( t42_keywords ) /
01031                                          sizeof ( t42_keywords[0] ) );
01032 
01033 
01034     parser->root.cursor = base;
01035     parser->root.limit  = base + size;
01036     parser->root.error  = T42_Err_Ok;
01037 
01038     limit = parser->root.limit;
01039 
01040     T1_Skip_Spaces( parser );
01041 
01042     while ( parser->root.cursor < limit )
01043     {
01044       FT_Byte*  cur;
01045 
01046 
01047       cur = parser->root.cursor;
01048 
01049       /* look for `FontDirectory' which causes problems for some fonts */
01050       if ( *cur == 'F' && cur + 25 < limit                    &&
01051            ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
01052       {
01053         FT_Byte*  cur2;
01054 
01055 
01056         /* skip the `FontDirectory' keyword */
01057         T1_Skip_PS_Token( parser );
01058         T1_Skip_Spaces  ( parser );
01059         cur = cur2 = parser->root.cursor;
01060 
01061         /* look up the `known' keyword */
01062         while ( cur < limit )
01063         {
01064           if ( *cur == 'k' && cur + 5 < limit             &&
01065                 ft_strncmp( (char*)cur, "known", 5 ) == 0 )
01066             break;
01067 
01068           T1_Skip_PS_Token( parser );
01069           if ( parser->root.error )
01070             goto Exit;
01071           T1_Skip_Spaces  ( parser );
01072           cur = parser->root.cursor;
01073         }
01074 
01075         if ( cur < limit )
01076         {
01077           T1_TokenRec  token;
01078 
01079 
01080           /* skip the `known' keyword and the token following it */
01081           T1_Skip_PS_Token( parser );
01082           T1_ToToken( parser, &token );
01083 
01084           /* if the last token was an array, skip it! */
01085           if ( token.type == T1_TOKEN_TYPE_ARRAY )
01086             cur2 = parser->root.cursor;
01087         }
01088         parser->root.cursor = cur2;
01089       }
01090 
01091       /* look for immediates */
01092       else if ( *cur == '/' && cur + 2 < limit )
01093       {
01094         FT_PtrDist  len;
01095 
01096 
01097         cur++;
01098 
01099         parser->root.cursor = cur;
01100         T1_Skip_PS_Token( parser );
01101         if ( parser->root.error )
01102           goto Exit;
01103 
01104         len = parser->root.cursor - cur;
01105 
01106         if ( len > 0 && len < 22 && parser->root.cursor < limit )
01107         {
01108           int  i;
01109 
01110 
01111           /* now compare the immediate name to the keyword table */
01112 
01113           /* loop through all known keywords */
01114           for ( i = 0; i < n_keywords; i++ )
01115           {
01116             T1_Field  keyword = (T1_Field)&t42_keywords[i];
01117             FT_Byte   *name   = (FT_Byte*)keyword->ident;
01118 
01119 
01120             if ( !name )
01121               continue;
01122 
01123             if ( cur[0] == name[0]                                  &&
01124                  len == (FT_PtrDist)ft_strlen( (const char *)name ) &&
01125                  ft_memcmp( cur, name, len ) == 0                   )
01126             {
01127               /* we found it -- run the parsing callback! */
01128               parser->root.error = t42_load_keyword( face,
01129                                                      loader,
01130                                                      keyword );
01131               if ( parser->root.error )
01132                 return parser->root.error;
01133               break;
01134             }
01135           }
01136         }
01137       }
01138       else
01139       {
01140         T1_Skip_PS_Token( parser );
01141         if ( parser->root.error )
01142           goto Exit;
01143       }
01144 
01145       T1_Skip_Spaces( parser );
01146     }
01147 
01148   Exit:
01149     return parser->root.error;
01150   }
01151 
01152 
01153   FT_LOCAL_DEF( void )
01154   t42_loader_init( T42_Loader  loader,
01155                    T42_Face    face )
01156   {
01157     FT_UNUSED( face );
01158 
01159     FT_MEM_ZERO( loader, sizeof ( *loader ) );
01160     loader->num_glyphs = 0;
01161     loader->num_chars  = 0;
01162 
01163     /* initialize the tables -- simply set their `init' field to 0 */
01164     loader->encoding_table.init = 0;
01165     loader->charstrings.init    = 0;
01166     loader->glyph_names.init    = 0;
01167   }
01168 
01169 
01170   FT_LOCAL_DEF( void )
01171   t42_loader_done( T42_Loader  loader )
01172   {
01173     T42_Parser  parser = &loader->parser;
01174 
01175 
01176     /* finalize tables */
01177     T1_Release_Table( &loader->encoding_table );
01178     T1_Release_Table( &loader->charstrings );
01179     T1_Release_Table( &loader->glyph_names );
01180     T1_Release_Table( &loader->swap_table );
01181 
01182     /* finalize parser */
01183     t42_parser_done( parser );
01184   }
01185 
01186 
01187 /* END */

Generated on Tue May 15 04:58:29 2012 for ReactOS by doxygen 1.6.3

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