misc/libfreetype/src/type1/t1parse.c
changeset 9372 915436ff64ab
parent 9371 f3840de881bd
child 9373 b769a8e38cbd
equal deleted inserted replaced
9371:f3840de881bd 9372:915436ff64ab
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  t1parse.c                                                              */
       
     4 /*                                                                         */
       
     5 /*    Type 1 parser (body).                                                */
       
     6 /*                                                                         */
       
     7 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2008, 2009 by             */
       
     8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
       
     9 /*                                                                         */
       
    10 /*  This file is part of the FreeType project, and may only be used,       */
       
    11 /*  modified, and distributed under the terms of the FreeType project      */
       
    12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
       
    13 /*  this file you indicate that you have read the license and              */
       
    14 /*  understand and accept it fully.                                        */
       
    15 /*                                                                         */
       
    16 /***************************************************************************/
       
    17 
       
    18 
       
    19   /*************************************************************************/
       
    20   /*                                                                       */
       
    21   /* The Type 1 parser is in charge of the following:                      */
       
    22   /*                                                                       */
       
    23   /*  - provide an implementation of a growing sequence of objects called  */
       
    24   /*    a `T1_Table' (used to build various tables needed by the loader).  */
       
    25   /*                                                                       */
       
    26   /*  - opening .pfb and .pfa files to extract their top-level and private */
       
    27   /*    dictionaries.                                                      */
       
    28   /*                                                                       */
       
    29   /*  - read numbers, arrays & strings from any dictionary.                */
       
    30   /*                                                                       */
       
    31   /* See `t1load.c' to see how data is loaded from the font file.          */
       
    32   /*                                                                       */
       
    33   /*************************************************************************/
       
    34 
       
    35 
       
    36 #include <ft2build.h>
       
    37 #include FT_INTERNAL_DEBUG_H
       
    38 #include FT_INTERNAL_STREAM_H
       
    39 #include FT_INTERNAL_POSTSCRIPT_AUX_H
       
    40 
       
    41 #include "t1parse.h"
       
    42 
       
    43 #include "t1errors.h"
       
    44 
       
    45 
       
    46   /*************************************************************************/
       
    47   /*                                                                       */
       
    48   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
       
    49   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
       
    50   /* messages during execution.                                            */
       
    51   /*                                                                       */
       
    52 #undef  FT_COMPONENT
       
    53 #define FT_COMPONENT  trace_t1parse
       
    54 
       
    55 
       
    56   /*************************************************************************/
       
    57   /*************************************************************************/
       
    58   /*************************************************************************/
       
    59   /*****                                                               *****/
       
    60   /*****                   INPUT STREAM PARSER                         *****/
       
    61   /*****                                                               *****/
       
    62   /*************************************************************************/
       
    63   /*************************************************************************/
       
    64   /*************************************************************************/
       
    65 
       
    66 
       
    67   /* see Adobe Technical Note 5040.Download_Fonts.pdf */
       
    68 
       
    69   static FT_Error
       
    70   read_pfb_tag( FT_Stream   stream,
       
    71                 FT_UShort  *atag,
       
    72                 FT_ULong   *asize )
       
    73   {
       
    74     FT_Error   error;
       
    75     FT_UShort  tag;
       
    76     FT_ULong   size;
       
    77 
       
    78 
       
    79     *atag  = 0;
       
    80     *asize = 0;
       
    81 
       
    82     if ( !FT_READ_USHORT( tag ) )
       
    83     {
       
    84       if ( tag == 0x8001U || tag == 0x8002U )
       
    85       {
       
    86         if ( !FT_READ_ULONG_LE( size ) )
       
    87           *asize = size;
       
    88       }
       
    89 
       
    90       *atag = tag;
       
    91     }
       
    92 
       
    93     return error;
       
    94   }
       
    95 
       
    96 
       
    97   static FT_Error
       
    98   check_type1_format( FT_Stream    stream,
       
    99                       const char*  header_string,
       
   100                       size_t       header_length )
       
   101   {
       
   102     FT_Error   error;
       
   103     FT_UShort  tag;
       
   104     FT_ULong   dummy;
       
   105 
       
   106 
       
   107     if ( FT_STREAM_SEEK( 0 ) )
       
   108       goto Exit;
       
   109 
       
   110     error = read_pfb_tag( stream, &tag, &dummy );
       
   111     if ( error )
       
   112       goto Exit;
       
   113 
       
   114     /* We assume that the first segment in a PFB is always encoded as   */
       
   115     /* text.  This might be wrong (and the specification doesn't insist */
       
   116     /* on that), but we have never seen a counterexample.               */
       
   117     if ( tag != 0x8001U && FT_STREAM_SEEK( 0 ) )
       
   118       goto Exit;
       
   119 
       
   120     if ( !FT_FRAME_ENTER( header_length ) )
       
   121     {
       
   122       error = T1_Err_Ok;
       
   123 
       
   124       if ( ft_memcmp( stream->cursor, header_string, header_length ) != 0 )
       
   125         error = T1_Err_Unknown_File_Format;
       
   126 
       
   127       FT_FRAME_EXIT();
       
   128     }
       
   129 
       
   130   Exit:
       
   131     return error;
       
   132   }
       
   133 
       
   134 
       
   135   FT_LOCAL_DEF( FT_Error )
       
   136   T1_New_Parser( T1_Parser      parser,
       
   137                  FT_Stream      stream,
       
   138                  FT_Memory      memory,
       
   139                  PSAux_Service  psaux )
       
   140   {
       
   141     FT_Error   error;
       
   142     FT_UShort  tag;
       
   143     FT_ULong   size;
       
   144 
       
   145 
       
   146     psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
       
   147 
       
   148     parser->stream       = stream;
       
   149     parser->base_len     = 0;
       
   150     parser->base_dict    = 0;
       
   151     parser->private_len  = 0;
       
   152     parser->private_dict = 0;
       
   153     parser->in_pfb       = 0;
       
   154     parser->in_memory    = 0;
       
   155     parser->single_block = 0;
       
   156 
       
   157     /* check the header format */
       
   158     error = check_type1_format( stream, "%!PS-AdobeFont", 14 );
       
   159     if ( error )
       
   160     {
       
   161       if ( error != T1_Err_Unknown_File_Format )
       
   162         goto Exit;
       
   163 
       
   164       error = check_type1_format( stream, "%!FontType", 10 );
       
   165       if ( error )
       
   166       {
       
   167         FT_TRACE2(( "[not a Type1 font]\n" ));
       
   168         goto Exit;
       
   169       }
       
   170     }
       
   171 
       
   172     /******************************************************************/
       
   173     /*                                                                */
       
   174     /* Here a short summary of what is going on:                      */
       
   175     /*                                                                */
       
   176     /*   When creating a new Type 1 parser, we try to locate and load */
       
   177     /*   the base dictionary if this is possible (i.e., for PFB       */
       
   178     /*   files).  Otherwise, we load the whole font into memory.      */
       
   179     /*                                                                */
       
   180     /*   When `loading' the base dictionary, we only setup pointers   */
       
   181     /*   in the case of a memory-based stream.  Otherwise, we         */
       
   182     /*   allocate and load the base dictionary in it.                 */
       
   183     /*                                                                */
       
   184     /*   parser->in_pfb is set if we are in a binary (`.pfb') font.   */
       
   185     /*   parser->in_memory is set if we have a memory stream.         */
       
   186     /*                                                                */
       
   187 
       
   188     /* try to compute the size of the base dictionary;     */
       
   189     /* look for a Postscript binary file tag, i.e., 0x8001 */
       
   190     if ( FT_STREAM_SEEK( 0L ) )
       
   191       goto Exit;
       
   192 
       
   193     error = read_pfb_tag( stream, &tag, &size );
       
   194     if ( error )
       
   195       goto Exit;
       
   196 
       
   197     if ( tag != 0x8001U )
       
   198     {
       
   199       /* assume that this is a PFA file for now; an error will */
       
   200       /* be produced later when more things are checked        */
       
   201       if ( FT_STREAM_SEEK( 0L ) )
       
   202         goto Exit;
       
   203       size = stream->size;
       
   204     }
       
   205     else
       
   206       parser->in_pfb = 1;
       
   207 
       
   208     /* now, try to load `size' bytes of the `base' dictionary we */
       
   209     /* found previously                                          */
       
   210 
       
   211     /* if it is a memory-based resource, set up pointers */
       
   212     if ( !stream->read )
       
   213     {
       
   214       parser->base_dict = (FT_Byte*)stream->base + stream->pos;
       
   215       parser->base_len  = size;
       
   216       parser->in_memory = 1;
       
   217 
       
   218       /* check that the `size' field is valid */
       
   219       if ( FT_STREAM_SKIP( size ) )
       
   220         goto Exit;
       
   221     }
       
   222     else
       
   223     {
       
   224       /* read segment in memory -- this is clumsy, but so does the format */
       
   225       if ( FT_ALLOC( parser->base_dict, size )       ||
       
   226            FT_STREAM_READ( parser->base_dict, size ) )
       
   227         goto Exit;
       
   228       parser->base_len = size;
       
   229     }
       
   230 
       
   231     parser->root.base   = parser->base_dict;
       
   232     parser->root.cursor = parser->base_dict;
       
   233     parser->root.limit  = parser->root.cursor + parser->base_len;
       
   234 
       
   235   Exit:
       
   236     if ( error && !parser->in_memory )
       
   237       FT_FREE( parser->base_dict );
       
   238 
       
   239     return error;
       
   240   }
       
   241 
       
   242 
       
   243   FT_LOCAL_DEF( void )
       
   244   T1_Finalize_Parser( T1_Parser  parser )
       
   245   {
       
   246     FT_Memory  memory = parser->root.memory;
       
   247 
       
   248 
       
   249     /* always free the private dictionary */
       
   250     FT_FREE( parser->private_dict );
       
   251 
       
   252     /* free the base dictionary only when we have a disk stream */
       
   253     if ( !parser->in_memory )
       
   254       FT_FREE( parser->base_dict );
       
   255 
       
   256     parser->root.funcs.done( &parser->root );
       
   257   }
       
   258 
       
   259 
       
   260   FT_LOCAL_DEF( FT_Error )
       
   261   T1_Get_Private_Dict( T1_Parser      parser,
       
   262                        PSAux_Service  psaux )
       
   263   {
       
   264     FT_Stream  stream = parser->stream;
       
   265     FT_Memory  memory = parser->root.memory;
       
   266     FT_Error   error  = T1_Err_Ok;
       
   267     FT_ULong   size;
       
   268 
       
   269 
       
   270     if ( parser->in_pfb )
       
   271     {
       
   272       /* in the case of the PFB format, the private dictionary can be  */
       
   273       /* made of several segments.  We thus first read the number of   */
       
   274       /* segments to compute the total size of the private dictionary  */
       
   275       /* then re-read them into memory.                                */
       
   276       FT_Long    start_pos = FT_STREAM_POS();
       
   277       FT_UShort  tag;
       
   278 
       
   279 
       
   280       parser->private_len = 0;
       
   281       for (;;)
       
   282       {
       
   283         error = read_pfb_tag( stream, &tag, &size );
       
   284         if ( error )
       
   285           goto Fail;
       
   286 
       
   287         if ( tag != 0x8002U )
       
   288           break;
       
   289 
       
   290         parser->private_len += size;
       
   291 
       
   292         if ( FT_STREAM_SKIP( size ) )
       
   293           goto Fail;
       
   294       }
       
   295 
       
   296       /* Check that we have a private dictionary there */
       
   297       /* and allocate private dictionary buffer        */
       
   298       if ( parser->private_len == 0 )
       
   299       {
       
   300         FT_ERROR(( "T1_Get_Private_Dict:"
       
   301                    " invalid private dictionary section\n" ));
       
   302         error = T1_Err_Invalid_File_Format;
       
   303         goto Fail;
       
   304       }
       
   305 
       
   306       if ( FT_STREAM_SEEK( start_pos )                           ||
       
   307            FT_ALLOC( parser->private_dict, parser->private_len ) )
       
   308         goto Fail;
       
   309 
       
   310       parser->private_len = 0;
       
   311       for (;;)
       
   312       {
       
   313         error = read_pfb_tag( stream, &tag, &size );
       
   314         if ( error || tag != 0x8002U )
       
   315         {
       
   316           error = T1_Err_Ok;
       
   317           break;
       
   318         }
       
   319 
       
   320         if ( FT_STREAM_READ( parser->private_dict + parser->private_len,
       
   321                              size ) )
       
   322           goto Fail;
       
   323 
       
   324         parser->private_len += size;
       
   325       }
       
   326     }
       
   327     else
       
   328     {
       
   329       /* We have already `loaded' the whole PFA font file into memory; */
       
   330       /* if this is a memory resource, allocate a new block to hold    */
       
   331       /* the private dict.  Otherwise, simply overwrite into the base  */
       
   332       /* dictionary block in the heap.                                 */
       
   333 
       
   334       /* first of all, look at the `eexec' keyword */
       
   335       FT_Byte*  cur   = parser->base_dict;
       
   336       FT_Byte*  limit = cur + parser->base_len;
       
   337       FT_Byte   c;
       
   338 
       
   339 
       
   340     Again:
       
   341       for (;;)
       
   342       {
       
   343         c = cur[0];
       
   344         if ( c == 'e' && cur + 9 < limit )  /* 9 = 5 letters for `eexec' + */
       
   345                                             /* newline + 4 chars           */
       
   346         {
       
   347           if ( cur[1] == 'e' &&
       
   348                cur[2] == 'x' &&
       
   349                cur[3] == 'e' &&
       
   350                cur[4] == 'c' )
       
   351             break;
       
   352         }
       
   353         cur++;
       
   354         if ( cur >= limit )
       
   355         {
       
   356           FT_ERROR(( "T1_Get_Private_Dict:"
       
   357                      " could not find `eexec' keyword\n" ));
       
   358           error = T1_Err_Invalid_File_Format;
       
   359           goto Exit;
       
   360         }
       
   361       }
       
   362 
       
   363       /* check whether `eexec' was real -- it could be in a comment */
       
   364       /* or string (as e.g. in u003043t.gsf from ghostscript)       */
       
   365 
       
   366       parser->root.cursor = parser->base_dict;
       
   367       parser->root.limit  = cur + 9;
       
   368 
       
   369       cur   = parser->root.cursor;
       
   370       limit = parser->root.limit;
       
   371 
       
   372       while ( cur < limit )
       
   373       {
       
   374         if ( *cur == 'e' && ft_strncmp( (char*)cur, "eexec", 5 ) == 0 )
       
   375           goto Found;
       
   376 
       
   377         T1_Skip_PS_Token( parser );
       
   378         if ( parser->root.error )
       
   379           break;
       
   380         T1_Skip_Spaces  ( parser );
       
   381         cur = parser->root.cursor;
       
   382       }
       
   383 
       
   384       /* we haven't found the correct `eexec'; go back and continue */
       
   385       /* searching                                                  */
       
   386 
       
   387       cur   = limit;
       
   388       limit = parser->base_dict + parser->base_len;
       
   389       goto Again;
       
   390 
       
   391       /* now determine where to write the _encrypted_ binary private  */
       
   392       /* dictionary.  We overwrite the base dictionary for disk-based */
       
   393       /* resources and allocate a new block otherwise                 */
       
   394 
       
   395     Found:
       
   396       parser->root.limit = parser->base_dict + parser->base_len;
       
   397 
       
   398       T1_Skip_PS_Token( parser );
       
   399       cur = parser->root.cursor;
       
   400 
       
   401       /* according to the Type1 spec, the first cipher byte must not be  */
       
   402       /* an ASCII whitespace character code (blank, tab, carriage return */
       
   403       /* or line feed).  We have seen Type 1 fonts with two line feed    */
       
   404       /* characters...  So skip now all whitespace character codes.      */
       
   405       while ( cur < limit       &&
       
   406               ( *cur == ' '  ||
       
   407                 *cur == '\t' || 
       
   408                 *cur == '\r' ||
       
   409                 *cur == '\n' ) )
       
   410         ++cur;
       
   411       if ( cur >= limit )
       
   412       {
       
   413         FT_ERROR(( "T1_Get_Private_Dict:"
       
   414                    " `eexec' not properly terminated\n" ));
       
   415         error = T1_Err_Invalid_File_Format;
       
   416         goto Exit;
       
   417       }
       
   418 
       
   419       size = parser->base_len - ( cur - parser->base_dict );
       
   420 
       
   421       if ( parser->in_memory )
       
   422       {
       
   423         /* note that we allocate one more byte to put a terminating `0' */
       
   424         if ( FT_ALLOC( parser->private_dict, size + 1 ) )
       
   425           goto Fail;
       
   426         parser->private_len = size;
       
   427       }
       
   428       else
       
   429       {
       
   430         parser->single_block = 1;
       
   431         parser->private_dict = parser->base_dict;
       
   432         parser->private_len  = size;
       
   433         parser->base_dict    = 0;
       
   434         parser->base_len     = 0;
       
   435       }
       
   436 
       
   437       /* now determine whether the private dictionary is encoded in binary */
       
   438       /* or hexadecimal ASCII format -- decode it accordingly              */
       
   439 
       
   440       /* we need to access the next 4 bytes (after the final \r following */
       
   441       /* the `eexec' keyword); if they all are hexadecimal digits, then   */
       
   442       /* we have a case of ASCII storage                                  */
       
   443 
       
   444       if ( ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) &&
       
   445            ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) )
       
   446       {
       
   447         /* ASCII hexadecimal encoding */
       
   448         FT_Long  len;
       
   449 
       
   450 
       
   451         parser->root.cursor = cur;
       
   452         (void)psaux->ps_parser_funcs->to_bytes( &parser->root,
       
   453                                                 parser->private_dict,
       
   454                                                 parser->private_len,
       
   455                                                 &len,
       
   456                                                 0 );
       
   457         parser->private_len = len;
       
   458 
       
   459         /* put a safeguard */
       
   460         parser->private_dict[len] = '\0';
       
   461       }
       
   462       else
       
   463         /* binary encoding -- copy the private dict */
       
   464         FT_MEM_MOVE( parser->private_dict, cur, size );
       
   465     }
       
   466 
       
   467     /* we now decrypt the encoded binary private dictionary */
       
   468     psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U );
       
   469 
       
   470     /* replace the four random bytes at the beginning with whitespace */
       
   471     parser->private_dict[0] = ' ';
       
   472     parser->private_dict[1] = ' ';
       
   473     parser->private_dict[2] = ' ';
       
   474     parser->private_dict[3] = ' ';
       
   475 
       
   476     parser->root.base   = parser->private_dict;
       
   477     parser->root.cursor = parser->private_dict;
       
   478     parser->root.limit  = parser->root.cursor + parser->private_len;
       
   479 
       
   480   Fail:
       
   481   Exit:
       
   482     return error;
       
   483   }
       
   484 
       
   485 
       
   486 /* END */