t1parse.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  t1parse.c                                                              */
00004 /*                                                                         */
00005 /*    Type 1 parser (body).                                                */
00006 /*                                                                         */
00007 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2008, 2009 by             */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
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   /*************************************************************************/
00020   /*                                                                       */
00021   /* The Type 1 parser is in charge of the following:                      */
00022   /*                                                                       */
00023   /*  - provide an implementation of a growing sequence of objects called  */
00024   /*    a `T1_Table' (used to build various tables needed by the loader).  */
00025   /*                                                                       */
00026   /*  - opening .pfb and .pfa files to extract their top-level and private */
00027   /*    dictionaries.                                                      */
00028   /*                                                                       */
00029   /*  - read numbers, arrays & strings from any dictionary.                */
00030   /*                                                                       */
00031   /* See `t1load.c' to see how data is loaded from the font file.          */
00032   /*                                                                       */
00033   /*************************************************************************/
00034 
00035 
00036 #include <ft2build.h>
00037 #include FT_INTERNAL_DEBUG_H
00038 #include FT_INTERNAL_STREAM_H
00039 #include FT_INTERNAL_POSTSCRIPT_AUX_H
00040 
00041 #include "t1parse.h"
00042 
00043 #include "t1errors.h"
00044 
00045 
00046   /*************************************************************************/
00047   /*                                                                       */
00048   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00049   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00050   /* messages during execution.                                            */
00051   /*                                                                       */
00052 #undef  FT_COMPONENT
00053 #define FT_COMPONENT  trace_t1parse
00054 
00055 
00056   /*************************************************************************/
00057   /*************************************************************************/
00058   /*************************************************************************/
00059   /*****                                                               *****/
00060   /*****                   INPUT STREAM PARSER                         *****/
00061   /*****                                                               *****/
00062   /*************************************************************************/
00063   /*************************************************************************/
00064   /*************************************************************************/
00065 
00066 
00067   /* see Adobe Technical Note 5040.Download_Fonts.pdf */
00068 
00069   static FT_Error
00070   read_pfb_tag( FT_Stream   stream,
00071                 FT_UShort  *atag,
00072                 FT_ULong   *asize )
00073   {
00074     FT_Error   error;
00075     FT_UShort  tag;
00076     FT_ULong   size;
00077 
00078 
00079     *atag  = 0;
00080     *asize = 0;
00081 
00082     if ( !FT_READ_USHORT( tag ) )
00083     {
00084       if ( tag == 0x8001U || tag == 0x8002U )
00085       {
00086         if ( !FT_READ_ULONG_LE( size ) )
00087           *asize = size;
00088       }
00089 
00090       *atag = tag;
00091     }
00092 
00093     return error;
00094   }
00095 
00096 
00097   static FT_Error
00098   check_type1_format( FT_Stream    stream,
00099                       const char*  header_string,
00100                       size_t       header_length )
00101   {
00102     FT_Error   error;
00103     FT_UShort  tag;
00104     FT_ULong   dummy;
00105 
00106 
00107     if ( FT_STREAM_SEEK( 0 ) )
00108       goto Exit;
00109 
00110     error = read_pfb_tag( stream, &tag, &dummy );
00111     if ( error )
00112       goto Exit;
00113 
00114     /* We assume that the first segment in a PFB is always encoded as   */
00115     /* text.  This might be wrong (and the specification doesn't insist */
00116     /* on that), but we have never seen a counterexample.               */
00117     if ( tag != 0x8001U && FT_STREAM_SEEK( 0 ) )
00118       goto Exit;
00119 
00120     if ( !FT_FRAME_ENTER( header_length ) )
00121     {
00122       error = T1_Err_Ok;
00123 
00124       if ( ft_memcmp( stream->cursor, header_string, header_length ) != 0 )
00125         error = T1_Err_Unknown_File_Format;
00126 
00127       FT_FRAME_EXIT();
00128     }
00129 
00130   Exit:
00131     return error;
00132   }
00133 
00134 
00135   FT_LOCAL_DEF( FT_Error )
00136   T1_New_Parser( T1_Parser      parser,
00137                  FT_Stream      stream,
00138                  FT_Memory      memory,
00139                  PSAux_Service  psaux )
00140   {
00141     FT_Error   error;
00142     FT_UShort  tag;
00143     FT_ULong   size;
00144 
00145 
00146     psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
00147 
00148     parser->stream       = stream;
00149     parser->base_len     = 0;
00150     parser->base_dict    = 0;
00151     parser->private_len  = 0;
00152     parser->private_dict = 0;
00153     parser->in_pfb       = 0;
00154     parser->in_memory    = 0;
00155     parser->single_block = 0;
00156 
00157     /* check the header format */
00158     error = check_type1_format( stream, "%!PS-AdobeFont", 14 );
00159     if ( error )
00160     {
00161       if ( error != T1_Err_Unknown_File_Format )
00162         goto Exit;
00163 
00164       error = check_type1_format( stream, "%!FontType", 10 );
00165       if ( error )
00166       {
00167         FT_TRACE2(( "[not a Type1 font]\n" ));
00168         goto Exit;
00169       }
00170     }
00171 
00172     /******************************************************************/
00173     /*                                                                */
00174     /* Here a short summary of what is going on:                      */
00175     /*                                                                */
00176     /*   When creating a new Type 1 parser, we try to locate and load */
00177     /*   the base dictionary if this is possible (i.e., for PFB       */
00178     /*   files).  Otherwise, we load the whole font into memory.      */
00179     /*                                                                */
00180     /*   When `loading' the base dictionary, we only setup pointers   */
00181     /*   in the case of a memory-based stream.  Otherwise, we         */
00182     /*   allocate and load the base dictionary in it.                 */
00183     /*                                                                */
00184     /*   parser->in_pfb is set if we are in a binary (`.pfb') font.   */
00185     /*   parser->in_memory is set if we have a memory stream.         */
00186     /*                                                                */
00187 
00188     /* try to compute the size of the base dictionary;     */
00189     /* look for a Postscript binary file tag, i.e., 0x8001 */
00190     if ( FT_STREAM_SEEK( 0L ) )
00191       goto Exit;
00192 
00193     error = read_pfb_tag( stream, &tag, &size );
00194     if ( error )
00195       goto Exit;
00196 
00197     if ( tag != 0x8001U )
00198     {
00199       /* assume that this is a PFA file for now; an error will */
00200       /* be produced later when more things are checked        */
00201       if ( FT_STREAM_SEEK( 0L ) )
00202         goto Exit;
00203       size = stream->size;
00204     }
00205     else
00206       parser->in_pfb = 1;
00207 
00208     /* now, try to load `size' bytes of the `base' dictionary we */
00209     /* found previously                                          */
00210 
00211     /* if it is a memory-based resource, set up pointers */
00212     if ( !stream->read )
00213     {
00214       parser->base_dict = (FT_Byte*)stream->base + stream->pos;
00215       parser->base_len  = size;
00216       parser->in_memory = 1;
00217 
00218       /* check that the `size' field is valid */
00219       if ( FT_STREAM_SKIP( size ) )
00220         goto Exit;
00221     }
00222     else
00223     {
00224       /* read segment in memory -- this is clumsy, but so does the format */
00225       if ( FT_ALLOC( parser->base_dict, size )       ||
00226            FT_STREAM_READ( parser->base_dict, size ) )
00227         goto Exit;
00228       parser->base_len = size;
00229     }
00230 
00231     parser->root.base   = parser->base_dict;
00232     parser->root.cursor = parser->base_dict;
00233     parser->root.limit  = parser->root.cursor + parser->base_len;
00234 
00235   Exit:
00236     if ( error && !parser->in_memory )
00237       FT_FREE( parser->base_dict );
00238 
00239     return error;
00240   }
00241 
00242 
00243   FT_LOCAL_DEF( void )
00244   T1_Finalize_Parser( T1_Parser  parser )
00245   {
00246     FT_Memory  memory = parser->root.memory;
00247 
00248 
00249     /* always free the private dictionary */
00250     FT_FREE( parser->private_dict );
00251 
00252     /* free the base dictionary only when we have a disk stream */
00253     if ( !parser->in_memory )
00254       FT_FREE( parser->base_dict );
00255 
00256     parser->root.funcs.done( &parser->root );
00257   }
00258 
00259 
00260   FT_LOCAL_DEF( FT_Error )
00261   T1_Get_Private_Dict( T1_Parser      parser,
00262                        PSAux_Service  psaux )
00263   {
00264     FT_Stream  stream = parser->stream;
00265     FT_Memory  memory = parser->root.memory;
00266     FT_Error   error  = T1_Err_Ok;
00267     FT_ULong   size;
00268 
00269 
00270     if ( parser->in_pfb )
00271     {
00272       /* in the case of the PFB format, the private dictionary can be  */
00273       /* made of several segments.  We thus first read the number of   */
00274       /* segments to compute the total size of the private dictionary  */
00275       /* then re-read them into memory.                                */
00276       FT_Long    start_pos = FT_STREAM_POS();
00277       FT_UShort  tag;
00278 
00279 
00280       parser->private_len = 0;
00281       for (;;)
00282       {
00283         error = read_pfb_tag( stream, &tag, &size );
00284         if ( error )
00285           goto Fail;
00286 
00287         if ( tag != 0x8002U )
00288           break;
00289 
00290         parser->private_len += size;
00291 
00292         if ( FT_STREAM_SKIP( size ) )
00293           goto Fail;
00294       }
00295 
00296       /* Check that we have a private dictionary there */
00297       /* and allocate private dictionary buffer        */
00298       if ( parser->private_len == 0 )
00299       {
00300         FT_ERROR(( "T1_Get_Private_Dict:"
00301                    " invalid private dictionary section\n" ));
00302         error = T1_Err_Invalid_File_Format;
00303         goto Fail;
00304       }
00305 
00306       if ( FT_STREAM_SEEK( start_pos )                           ||
00307            FT_ALLOC( parser->private_dict, parser->private_len ) )
00308         goto Fail;
00309 
00310       parser->private_len = 0;
00311       for (;;)
00312       {
00313         error = read_pfb_tag( stream, &tag, &size );
00314         if ( error || tag != 0x8002U )
00315         {
00316           error = T1_Err_Ok;
00317           break;
00318         }
00319 
00320         if ( FT_STREAM_READ( parser->private_dict + parser->private_len,
00321                              size ) )
00322           goto Fail;
00323 
00324         parser->private_len += size;
00325       }
00326     }
00327     else
00328     {
00329       /* We have already `loaded' the whole PFA font file into memory; */
00330       /* if this is a memory resource, allocate a new block to hold    */
00331       /* the private dict.  Otherwise, simply overwrite into the base  */
00332       /* dictionary block in the heap.                                 */
00333 
00334       /* first of all, look at the `eexec' keyword */
00335       FT_Byte*  cur   = parser->base_dict;
00336       FT_Byte*  limit = cur + parser->base_len;
00337       FT_Byte   c;
00338 
00339 
00340     Again:
00341       for (;;)
00342       {
00343         c = cur[0];
00344         if ( c == 'e' && cur + 9 < limit )  /* 9 = 5 letters for `eexec' + */
00345                                             /* newline + 4 chars           */
00346         {
00347           if ( cur[1] == 'e' &&
00348                cur[2] == 'x' &&
00349                cur[3] == 'e' &&
00350                cur[4] == 'c' )
00351             break;
00352         }
00353         cur++;
00354         if ( cur >= limit )
00355         {
00356           FT_ERROR(( "T1_Get_Private_Dict:"
00357                      " could not find `eexec' keyword\n" ));
00358           error = T1_Err_Invalid_File_Format;
00359           goto Exit;
00360         }
00361       }
00362 
00363       /* check whether `eexec' was real -- it could be in a comment */
00364       /* or string (as e.g. in u003043t.gsf from ghostscript)       */
00365 
00366       parser->root.cursor = parser->base_dict;
00367       parser->root.limit  = cur + 9;
00368 
00369       cur   = parser->root.cursor;
00370       limit = parser->root.limit;
00371 
00372       while ( cur < limit )
00373       {
00374         if ( *cur == 'e' && ft_strncmp( (char*)cur, "eexec", 5 ) == 0 )
00375           goto Found;
00376 
00377         T1_Skip_PS_Token( parser );
00378         if ( parser->root.error )
00379           break;
00380         T1_Skip_Spaces  ( parser );
00381         cur = parser->root.cursor;
00382       }
00383 
00384       /* we haven't found the correct `eexec'; go back and continue */
00385       /* searching                                                  */
00386 
00387       cur   = limit;
00388       limit = parser->base_dict + parser->base_len;
00389       goto Again;
00390 
00391       /* now determine where to write the _encrypted_ binary private  */
00392       /* dictionary.  We overwrite the base dictionary for disk-based */
00393       /* resources and allocate a new block otherwise                 */
00394 
00395     Found:
00396       parser->root.limit = parser->base_dict + parser->base_len;
00397 
00398       T1_Skip_PS_Token( parser );
00399       cur = parser->root.cursor;
00400 
00401       /* according to the Type1 spec, the first cipher byte must not be  */
00402       /* an ASCII whitespace character code (blank, tab, carriage return */
00403       /* or line feed).  We have seen Type 1 fonts with two line feed    */
00404       /* characters...  So skip now all whitespace character codes.      */
00405       while ( cur < limit       &&
00406               ( *cur == ' '  ||
00407                 *cur == '\t' || 
00408                 *cur == '\r' ||
00409                 *cur == '\n' ) )
00410         ++cur;
00411       if ( cur >= limit )
00412       {
00413         FT_ERROR(( "T1_Get_Private_Dict:"
00414                    " `eexec' not properly terminated\n" ));
00415         error = T1_Err_Invalid_File_Format;
00416         goto Exit;
00417       }
00418 
00419       size = parser->base_len - ( cur - parser->base_dict );
00420 
00421       if ( parser->in_memory )
00422       {
00423         /* note that we allocate one more byte to put a terminating `0' */
00424         if ( FT_ALLOC( parser->private_dict, size + 1 ) )
00425           goto Fail;
00426         parser->private_len = size;
00427       }
00428       else
00429       {
00430         parser->single_block = 1;
00431         parser->private_dict = parser->base_dict;
00432         parser->private_len  = size;
00433         parser->base_dict    = 0;
00434         parser->base_len     = 0;
00435       }
00436 
00437       /* now determine whether the private dictionary is encoded in binary */
00438       /* or hexadecimal ASCII format -- decode it accordingly              */
00439 
00440       /* we need to access the next 4 bytes (after the final \r following */
00441       /* the `eexec' keyword); if they all are hexadecimal digits, then   */
00442       /* we have a case of ASCII storage                                  */
00443 
00444       if ( ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) &&
00445            ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) )
00446       {
00447         /* ASCII hexadecimal encoding */
00448         FT_Long  len;
00449 
00450 
00451         parser->root.cursor = cur;
00452         (void)psaux->ps_parser_funcs->to_bytes( &parser->root,
00453                                                 parser->private_dict,
00454                                                 parser->private_len,
00455                                                 &len,
00456                                                 0 );
00457         parser->private_len = len;
00458 
00459         /* put a safeguard */
00460         parser->private_dict[len] = '\0';
00461       }
00462       else
00463         /* binary encoding -- copy the private dict */
00464         FT_MEM_MOVE( parser->private_dict, cur, size );
00465     }
00466 
00467     /* we now decrypt the encoded binary private dictionary */
00468     psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U );
00469 
00470     /* replace the four random bytes at the beginning with whitespace */
00471     parser->private_dict[0] = ' ';
00472     parser->private_dict[1] = ' ';
00473     parser->private_dict[2] = ' ';
00474     parser->private_dict[3] = ' ';
00475 
00476     parser->root.base   = parser->private_dict;
00477     parser->root.cursor = parser->private_dict;
00478     parser->root.limit  = parser->root.cursor + parser->private_len;
00479 
00480   Fail:
00481   Exit:
00482     return error;
00483   }
00484 
00485 
00486 /* END */

Generated on Tue Jul 5 14:13:54 2011 for ROOT_528-00b_version by  doxygen 1.5.1