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