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

Information | Donate

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

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

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

ReactOS Development > Doxygen

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 Fri May 25 2012 04:32:35 for ReactOS by doxygen 1.7.6.1

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