misc/libfreetype/src/cid/cidparse.c
changeset 5172 88f2e05288ba
equal deleted inserted replaced
5171:f9283dc4860d 5172:88f2e05288ba
       
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  cidparse.c                                                             */
       
     4 /*                                                                         */
       
     5 /*    CID-keyed Type1 parser (body).                                       */
       
     6 /*                                                                         */
       
     7 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 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 #include <ft2build.h>
       
    20 #include FT_INTERNAL_DEBUG_H
       
    21 #include FT_INTERNAL_OBJECTS_H
       
    22 #include FT_INTERNAL_STREAM_H
       
    23 
       
    24 #include "cidparse.h"
       
    25 
       
    26 #include "ciderrs.h"
       
    27 
       
    28 
       
    29   /*************************************************************************/
       
    30   /*                                                                       */
       
    31   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
       
    32   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
       
    33   /* messages during execution.                                            */
       
    34   /*                                                                       */
       
    35 #undef  FT_COMPONENT
       
    36 #define FT_COMPONENT  trace_cidparse
       
    37 
       
    38 
       
    39   /*************************************************************************/
       
    40   /*************************************************************************/
       
    41   /*************************************************************************/
       
    42   /*****                                                               *****/
       
    43   /*****                    INPUT STREAM PARSER                        *****/
       
    44   /*****                                                               *****/
       
    45   /*************************************************************************/
       
    46   /*************************************************************************/
       
    47   /*************************************************************************/
       
    48 
       
    49 
       
    50   FT_LOCAL_DEF( FT_Error )
       
    51   cid_parser_new( CID_Parser*    parser,
       
    52                   FT_Stream      stream,
       
    53                   FT_Memory      memory,
       
    54                   PSAux_Service  psaux )
       
    55   {
       
    56     FT_Error  error;
       
    57     FT_ULong  base_offset, offset, ps_len;
       
    58     FT_Byte   *cur, *limit;
       
    59     FT_Byte   *arg1, *arg2;
       
    60 
       
    61 
       
    62     FT_MEM_ZERO( parser, sizeof ( *parser ) );
       
    63     psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
       
    64 
       
    65     parser->stream = stream;
       
    66 
       
    67     base_offset = FT_STREAM_POS();
       
    68 
       
    69     /* first of all, check the font format in the header */
       
    70     if ( FT_FRAME_ENTER( 31 ) )
       
    71       goto Exit;
       
    72 
       
    73     if ( ft_strncmp( (char *)stream->cursor,
       
    74                      "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) )
       
    75     {
       
    76       FT_TRACE2(( "[not a valid CID-keyed font]\n" ));
       
    77       error = CID_Err_Unknown_File_Format;
       
    78     }
       
    79 
       
    80     FT_FRAME_EXIT();
       
    81     if ( error )
       
    82       goto Exit;
       
    83 
       
    84   Again:
       
    85     /* now, read the rest of the file until we find */
       
    86     /* `StartData' or `/sfnts'                      */
       
    87     {
       
    88       FT_Byte   buffer[256 + 10];
       
    89       FT_Long   read_len = 256 + 10; /* same as signed FT_Stream->size */
       
    90       FT_Byte*  p        = buffer;
       
    91 
       
    92 
       
    93       for ( offset = FT_STREAM_POS(); ; offset += 256 )
       
    94       {
       
    95         FT_Long  stream_len; /* same as signed FT_Stream->size */
       
    96 
       
    97 
       
    98         stream_len = stream->size - FT_STREAM_POS();
       
    99         if ( stream_len == 0 )
       
   100         {
       
   101           FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" ));
       
   102           error = CID_Err_Unknown_File_Format;
       
   103           goto Exit;
       
   104         }
       
   105 
       
   106         read_len = FT_MIN( read_len, stream_len );
       
   107         if ( FT_STREAM_READ( p, read_len ) )
       
   108           goto Exit;
       
   109 
       
   110         if ( read_len < 256 )
       
   111           p[read_len]  = '\0';
       
   112 
       
   113         limit = p + read_len - 10;
       
   114 
       
   115         for ( p = buffer; p < limit; p++ )
       
   116         {
       
   117           if ( p[0] == 'S' && ft_strncmp( (char*)p, "StartData", 9 ) == 0 )
       
   118           {
       
   119             /* save offset of binary data after `StartData' */
       
   120             offset += p - buffer + 10;
       
   121             goto Found;
       
   122           }
       
   123           else if ( p[1] == 's' && ft_strncmp( (char*)p, "/sfnts", 6 ) == 0 )
       
   124           {
       
   125             offset += p - buffer + 7;
       
   126             goto Found;
       
   127           }
       
   128         }
       
   129 
       
   130         FT_MEM_MOVE( buffer, p, 10 );
       
   131         read_len = 256;
       
   132         p = buffer + 10;
       
   133       }
       
   134     }
       
   135 
       
   136   Found:
       
   137     /* We have found the start of the binary data or the `/sfnts' token. */
       
   138     /* Now rewind and extract the frame corresponding to this PostScript */
       
   139     /* section.                                                          */
       
   140 
       
   141     ps_len = offset - base_offset;
       
   142     if ( FT_STREAM_SEEK( base_offset )                  ||
       
   143          FT_FRAME_EXTRACT( ps_len, parser->postscript ) )
       
   144       goto Exit;
       
   145 
       
   146     parser->data_offset    = offset;
       
   147     parser->postscript_len = ps_len;
       
   148     parser->root.base      = parser->postscript;
       
   149     parser->root.cursor    = parser->postscript;
       
   150     parser->root.limit     = parser->root.cursor + ps_len;
       
   151     parser->num_dict       = -1;
       
   152 
       
   153     /* Finally, we check whether `StartData' or `/sfnts' was real --  */
       
   154     /* it could be in a comment or string.  We also get the arguments */
       
   155     /* of `StartData' to find out whether the data is represented in  */
       
   156     /* binary or hex format.                                          */
       
   157 
       
   158     arg1 = parser->root.cursor;
       
   159     cid_parser_skip_PS_token( parser );
       
   160     cid_parser_skip_spaces  ( parser );
       
   161     arg2 = parser->root.cursor;
       
   162     cid_parser_skip_PS_token( parser );
       
   163     cid_parser_skip_spaces  ( parser );
       
   164 
       
   165     limit = parser->root.limit;
       
   166     cur   = parser->root.cursor;
       
   167 
       
   168     while ( cur < limit )
       
   169     {
       
   170       if ( parser->root.error )
       
   171       {
       
   172         error = parser->root.error;
       
   173         goto Exit;
       
   174       }
       
   175 
       
   176       if ( cur[0] == 'S' && ft_strncmp( (char*)cur, "StartData", 9 ) == 0 )
       
   177       {
       
   178         if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 )
       
   179           parser->binary_length = ft_atol( (const char *)arg2 );
       
   180 
       
   181         limit = parser->root.limit;
       
   182         cur   = parser->root.cursor;
       
   183         goto Exit;
       
   184       }
       
   185       else if ( cur[1] == 's' && ft_strncmp( (char*)cur, "/sfnts", 6 ) == 0 )
       
   186       {
       
   187         FT_TRACE2(( "cid_parser_new: cannot handle Type 11 fonts\n" ));
       
   188         error = CID_Err_Unknown_File_Format;
       
   189         goto Exit;
       
   190       }
       
   191 
       
   192       cid_parser_skip_PS_token( parser );
       
   193       cid_parser_skip_spaces  ( parser );
       
   194       arg1 = arg2;
       
   195       arg2 = cur;
       
   196       cur  = parser->root.cursor;
       
   197     }
       
   198 
       
   199     /* we haven't found the correct `StartData'; go back and continue */
       
   200     /* searching                                                      */
       
   201     FT_FRAME_RELEASE( parser->postscript );
       
   202     if ( !FT_STREAM_SEEK( offset ) )
       
   203       goto Again;
       
   204 
       
   205   Exit:
       
   206     return error;
       
   207   }
       
   208 
       
   209 
       
   210   FT_LOCAL_DEF( void )
       
   211   cid_parser_done( CID_Parser*  parser )
       
   212   {
       
   213     /* always free the private dictionary */
       
   214     if ( parser->postscript )
       
   215     {
       
   216       FT_Stream  stream = parser->stream;
       
   217 
       
   218 
       
   219       FT_FRAME_RELEASE( parser->postscript );
       
   220     }
       
   221     parser->root.funcs.done( &parser->root );
       
   222   }
       
   223 
       
   224 
       
   225 /* END */