cidparse.c revision 059bc335ce42220b222763379e89d0cbf2b949eb
1/***************************************************************************/ 2/* */ 3/* cidparse.c */ 4/* */ 5/* CID-keyed Type1 parser (body). */ 6/* */ 7/* Copyright 1996-2007, 2009, 2013 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 CID-keyed font\n" )); 77 error = FT_THROW( 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 = FT_THROW( Invalid_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 = FT_THROW( 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 */ 226