blob: 80e7547b908bfbe518df50c0222746ff62e643bf [file] [log] [blame]
Werner Lemberg8c90c222002-06-08 06:47:18 +00001/***************************************************************************/
2/* */
3/* t42parse.c */
4/* */
5/* Type 42 font parser (body). */
6/* */
Werner Lemberg1d565fb2005-02-13 21:42:42 +00007/* Copyright 2002, 2003, 2004, 2005 by Roberto Alameda. */
Werner Lemberg8c90c222002-06-08 06:47:18 +00008/* */
9/* This file is part of the FreeType project, and may only be used, */
10/* modified, and distributed under the terms of the FreeType project */
11/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
12/* this file you indicate that you have read the license and */
13/* understand and accept it fully. */
14/* */
15/***************************************************************************/
16
17
David Turner9f95bab2002-06-07 07:23:06 +000018#include "t42parse.h"
Werner Lemberg8c90c222002-06-08 06:47:18 +000019#include "t42error.h"
David Turner9f95bab2002-06-07 07:23:06 +000020#include FT_INTERNAL_DEBUG_H
21#include FT_INTERNAL_STREAM_H
22#include FT_LIST_H
23#include FT_INTERNAL_POSTSCRIPT_AUX_H
24
Werner Lemberg8c90c222002-06-08 06:47:18 +000025
David Turner9f95bab2002-06-07 07:23:06 +000026 /*************************************************************************/
27 /* */
28 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
29 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
30 /* messages during execution. */
31 /* */
32#undef FT_COMPONENT
33#define FT_COMPONENT trace_t42
34
Werner Lemberg8c90c222002-06-08 06:47:18 +000035
David Turner9f95bab2002-06-07 07:23:06 +000036 static void
David Turner9f95bab2002-06-07 07:23:06 +000037 t42_parse_font_matrix( T42_Face face,
38 T42_Loader loader );
39 static void
40 t42_parse_encoding( T42_Face face,
41 T42_Loader loader );
David Turner3c40d732003-08-17 22:31:23 +000042
David Turner9f95bab2002-06-07 07:23:06 +000043 static void
44 t42_parse_charstrings( T42_Face face,
45 T42_Loader loader );
David Turner3c40d732003-08-17 22:31:23 +000046
David Turner9f95bab2002-06-07 07:23:06 +000047 static void
48 t42_parse_sfnts( T42_Face face,
49 T42_Loader loader );
50
51
52 static const
53 T1_FieldRec t42_keywords[] = {
54
55#undef FT_STRUCTURE
56#define FT_STRUCTURE T1_FontInfo
57#undef T1CODE
58#define T1CODE T1_FIELD_LOCATION_FONT_INFO
59
Werner Lemberg64f1ba92003-07-25 22:09:53 +000060 T1_FIELD_STRING( "version", version )
61 T1_FIELD_STRING( "Notice", notice )
62 T1_FIELD_STRING( "FullName", full_name )
63 T1_FIELD_STRING( "FamilyName", family_name )
64 T1_FIELD_STRING( "Weight", weight )
David Turner3c40d732003-08-17 22:31:23 +000065 T1_FIELD_NUM ( "ItalicAngle", italic_angle )
Werner Lemberg64f1ba92003-07-25 22:09:53 +000066 T1_FIELD_BOOL ( "isFixedPitch", is_fixed_pitch )
David Turner3c40d732003-08-17 22:31:23 +000067 T1_FIELD_NUM ( "UnderlinePosition", underline_position )
68 T1_FIELD_NUM ( "UnderlineThickness", underline_thickness )
David Turner9f95bab2002-06-07 07:23:06 +000069
70#undef FT_STRUCTURE
71#define FT_STRUCTURE T1_FontRec
72#undef T1CODE
73#define T1CODE T1_FIELD_LOCATION_FONT_DICT
74
Werner Lemberg64f1ba92003-07-25 22:09:53 +000075 T1_FIELD_KEY ( "FontName", font_name )
76 T1_FIELD_NUM ( "PaintType", paint_type )
77 T1_FIELD_NUM ( "FontType", font_type )
78 T1_FIELD_FIXED( "StrokeWidth", stroke_width )
David Turner9f95bab2002-06-07 07:23:06 +000079
Werner Lembergfdc042b2003-06-12 04:59:07 +000080#undef FT_STRUCTURE
81#define FT_STRUCTURE FT_BBox
82#undef T1CODE
83#define T1CODE T1_FIELD_LOCATION_BBOX
84
85 T1_FIELD_BBOX("FontBBox", xMin )
86
David Turner9f95bab2002-06-07 07:23:06 +000087 T1_FIELD_CALLBACK( "FontMatrix", t42_parse_font_matrix )
88 T1_FIELD_CALLBACK( "Encoding", t42_parse_encoding )
89 T1_FIELD_CALLBACK( "CharStrings", t42_parse_charstrings )
90 T1_FIELD_CALLBACK( "sfnts", t42_parse_sfnts )
91
92 { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 }
93 };
94
95
96#define T1_Add_Table( p, i, o, l ) (p)->funcs.add( (p), i, o, l )
97#define T1_Done_Table( p ) \
98 do \
99 { \
100 if ( (p)->funcs.done ) \
101 (p)->funcs.done( p ); \
102 } while ( 0 )
103#define T1_Release_Table( p ) \
104 do \
105 { \
106 if ( (p)->funcs.release ) \
107 (p)->funcs.release( p ); \
108 } while ( 0 )
109
Werner Lemberg52f911a2003-10-07 05:49:41 +0000110#define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root )
111#define T1_Skip_PS_Token( p ) (p)->root.funcs.skip_PS_token( &(p)->root )
David Turner9f95bab2002-06-07 07:23:06 +0000112
Werner Lemberge3f41982003-10-16 15:48:39 +0000113#define T1_ToInt( p ) \
114 (p)->root.funcs.to_int( &(p)->root )
115#define T1_ToBytes( p, b, m, n, d ) \
116 (p)->root.funcs.to_bytes( &(p)->root, b, m, n, d )
David Turner9f95bab2002-06-07 07:23:06 +0000117
David Turner9f95bab2002-06-07 07:23:06 +0000118#define T1_ToFixedArray( p, m, f, t ) \
119 (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
120#define T1_ToToken( p, t ) \
121 (p)->root.funcs.to_token( &(p)->root, t )
David Turner9f95bab2002-06-07 07:23:06 +0000122
123#define T1_Load_Field( p, f, o, m, pf ) \
124 (p)->root.funcs.load_field( &(p)->root, f, o, m, pf )
125#define T1_Load_Field_Table( p, f, o, m, pf ) \
126 (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )
127
128
129 /********************* Parsing Functions ******************/
130
131 FT_LOCAL_DEF( FT_Error )
132 t42_parser_init( T42_Parser parser,
133 FT_Stream stream,
134 FT_Memory memory,
135 PSAux_Service psaux )
136 {
Werner Lemberg8c90c222002-06-08 06:47:18 +0000137 FT_Error error = T42_Err_Ok;
David Turner9f95bab2002-06-07 07:23:06 +0000138 FT_Long size;
139
140
141 psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
142
143 parser->stream = stream;
144 parser->base_len = 0;
145 parser->base_dict = 0;
146 parser->in_memory = 0;
147
148 /*******************************************************************/
149 /* */
150 /* Here a short summary of what is going on: */
151 /* */
152 /* When creating a new Type 42 parser, we try to locate and load */
153 /* the base dictionary, loading the whole font into memory. */
154 /* */
Werner Lemberg3864f4e2003-09-30 06:43:54 +0000155 /* When `loading' the base dictionary, we only set up pointers */
156 /* in the case of a memory-based stream. Otherwise, we allocate */
David Turner9f95bab2002-06-07 07:23:06 +0000157 /* and load the base dictionary in it. */
158 /* */
159 /* parser->in_memory is set if we have a memory stream. */
160 /* */
161
David Turner58609c42005-03-15 23:31:48 +0000162 if ( FT_STREAM_SEEK( 0L ) ||
163 FT_FRAME_ENTER( 17 ) )
164 goto Exit;
165
166 if ( ft_memcmp( stream->cursor, "%!PS-TrueTypeFont", 17 ) != 0 )
167 {
168 FT_TRACE2(( "not a Type42 font\n" ));
169 error = T42_Err_Unknown_File_Format;
170 }
171
172 FT_FRAME_EXIT();
173
174 if ( error || FT_STREAM_SEEK( 0 ) )
David Turner9f95bab2002-06-07 07:23:06 +0000175 goto Exit;
176
177 size = stream->size;
178
179 /* now, try to load `size' bytes of the `base' dictionary we */
180 /* found previously */
181
182 /* if it is a memory-based resource, set up pointers */
183 if ( !stream->read )
184 {
185 parser->base_dict = (FT_Byte*)stream->base + stream->pos;
186 parser->base_len = size;
187 parser->in_memory = 1;
188
189 /* check that the `size' field is valid */
190 if ( FT_STREAM_SKIP( size ) )
191 goto Exit;
192 }
193 else
194 {
195 /* read segment in memory */
Werner Lemberg8c90c222002-06-08 06:47:18 +0000196 if ( FT_ALLOC( parser->base_dict, size ) ||
197 FT_STREAM_READ( parser->base_dict, size ) )
David Turner9f95bab2002-06-07 07:23:06 +0000198 goto Exit;
199
200 parser->base_len = size;
201 }
202
David Turner58609c42005-03-15 23:31:48 +0000203 parser->root.base = parser->base_dict;
204 parser->root.cursor = parser->base_dict;
205 parser->root.limit = parser->root.cursor + parser->base_len;
David Turner9f95bab2002-06-07 07:23:06 +0000206
207 Exit:
208 if ( error && !parser->in_memory )
209 FT_FREE( parser->base_dict );
210
211 return error;
212 }
213
214
215 FT_LOCAL_DEF( void )
216 t42_parser_done( T42_Parser parser )
217 {
218 FT_Memory memory = parser->root.memory;
219
220
221 /* free the base dictionary only when we have a disk stream */
222 if ( !parser->in_memory )
223 FT_FREE( parser->base_dict );
224
225 parser->root.funcs.done( &parser->root );
226 }
227
228
229 static int
David Turner9f95bab2002-06-07 07:23:06 +0000230 t42_is_space( FT_Byte c )
231 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000232 return ( c == ' ' || c == '\t' ||
233 c == '\r' || c == '\n' || c == '\f' ||
234 c == '\0' );
David Turner9f95bab2002-06-07 07:23:06 +0000235 }
236
237
238 static void
David Turner9f95bab2002-06-07 07:23:06 +0000239 t42_parse_font_matrix( T42_Face face,
240 T42_Loader loader )
241 {
242 T42_Parser parser = &loader->parser;
243 FT_Matrix* matrix = &face->type1.font_matrix;
244 FT_Vector* offset = &face->type1.font_offset;
245 FT_Face root = (FT_Face)&face->root;
246 FT_Fixed temp[6];
247 FT_Fixed temp_scale;
248
249
250 (void)T1_ToFixedArray( parser, 6, temp, 3 );
251
Werner Lembergdfa46192004-03-05 09:26:24 +0000252 temp_scale = FT_ABS( temp[3] );
David Turner9f95bab2002-06-07 07:23:06 +0000253
254 /* Set Units per EM based on FontMatrix values. We set the value to */
255 /* 1000 / temp_scale, because temp_scale was already multiplied by */
256 /* 1000 (in t1_tofixed, from psobjs.c). */
257
258 root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L,
259 temp_scale ) >> 16 );
260
261 /* we need to scale the values by 1.0/temp_scale */
262 if ( temp_scale != 0x10000L ) {
263 temp[0] = FT_DivFix( temp[0], temp_scale );
264 temp[1] = FT_DivFix( temp[1], temp_scale );
265 temp[2] = FT_DivFix( temp[2], temp_scale );
266 temp[4] = FT_DivFix( temp[4], temp_scale );
267 temp[5] = FT_DivFix( temp[5], temp_scale );
268 temp[3] = 0x10000L;
269 }
270
271 matrix->xx = temp[0];
272 matrix->yx = temp[1];
273 matrix->xy = temp[2];
274 matrix->yy = temp[3];
275
276 /* note that the offsets must be expressed in integer font units */
Werner Lemberge3f41982003-10-16 15:48:39 +0000277 offset->x = temp[4] >> 16;
278 offset->y = temp[5] >> 16;
David Turner9f95bab2002-06-07 07:23:06 +0000279 }
280
281
282 static void
283 t42_parse_encoding( T42_Face face,
284 T42_Loader loader )
285 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000286 T42_Parser parser = &loader->parser;
287 FT_Byte* cur;
288 FT_Byte* limit = parser->root.limit;
David Turner9f95bab2002-06-07 07:23:06 +0000289
290 PSAux_Service psaux = (PSAux_Service)face->psaux;
291
292
Werner Lemberge3f41982003-10-16 15:48:39 +0000293 T1_Skip_Spaces( parser );
294 cur = parser->root.cursor;
Werner Lemberge3f41982003-10-16 15:48:39 +0000295 if ( cur >= limit )
David Turner9f95bab2002-06-07 07:23:06 +0000296 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000297 FT_ERROR(( "t42_parse_encoding: out of bounds!\n" ));
298 parser->root.error = T42_Err_Invalid_File_Format;
299 return;
David Turner9f95bab2002-06-07 07:23:06 +0000300 }
301
Werner Lemberge3f41982003-10-16 15:48:39 +0000302 /* if we have a number or `[', the encoding is an array, */
303 /* and we must load it now */
304 if ( ft_isdigit( *cur ) || *cur == '[' )
David Turner9f95bab2002-06-07 07:23:06 +0000305 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000306 T1_Encoding encode = &face->type1.encoding;
307 FT_UInt count, n;
308 PS_Table char_table = &loader->encoding_table;
309 FT_Memory memory = parser->root.memory;
David Turner9f95bab2002-06-07 07:23:06 +0000310 FT_Error error;
Werner Lemberge3f41982003-10-16 15:48:39 +0000311 FT_Bool only_immediates = 0;
David Turner9f95bab2002-06-07 07:23:06 +0000312
313
Werner Lemberge3f41982003-10-16 15:48:39 +0000314 /* read the number of entries in the encoding; should be 256 */
315 if ( *cur == '[' )
316 {
317 count = 256;
318 only_immediates = 1;
319 parser->root.cursor++;
320 }
321 else
322 count = (FT_UInt)T1_ToInt( parser );
Werner Lemberg3864f4e2003-09-30 06:43:54 +0000323
Werner Lemberge3f41982003-10-16 15:48:39 +0000324 T1_Skip_Spaces( parser );
325 if ( parser->root.cursor >= limit )
David Turner9f95bab2002-06-07 07:23:06 +0000326 return;
327
328 /* we use a T1_Table to store our charnames */
329 loader->num_chars = encode->num_chars = count;
Werner Lemberge3f41982003-10-16 15:48:39 +0000330 if ( FT_NEW_ARRAY( encode->char_index, count ) ||
331 FT_NEW_ARRAY( encode->char_name, count ) ||
David Turner9f95bab2002-06-07 07:23:06 +0000332 FT_SET_ERROR( psaux->ps_table_funcs->init(
333 char_table, count, memory ) ) )
334 {
335 parser->root.error = error;
336 return;
337 }
338
339 /* We need to `zero' out encoding_table.elements */
340 for ( n = 0; n < count; n++ )
341 {
342 char* notdef = (char *)".notdef";
343
344
345 T1_Add_Table( char_table, n, notdef, 8 );
346 }
347
Werner Lemberge3f41982003-10-16 15:48:39 +0000348 /* Now we need to read records of the form */
349 /* */
350 /* ... charcode /charname ... */
351 /* */
352 /* for each entry in our table. */
David Turner9f95bab2002-06-07 07:23:06 +0000353 /* */
354 /* We simply look for a number followed by an immediate */
355 /* name. Note that this ignores correctly the sequence */
Werner Lemberge3f41982003-10-16 15:48:39 +0000356 /* that is often seen in type42 fonts: */
David Turner9f95bab2002-06-07 07:23:06 +0000357 /* */
358 /* 0 1 255 { 1 index exch /.notdef put } for dup */
359 /* */
360 /* used to clean the encoding array before anything else. */
361 /* */
Werner Lemberge3f41982003-10-16 15:48:39 +0000362 /* Alternatively, if the array is directly given as */
363 /* */
364 /* /Encoding [ ... ] */
365 /* */
366 /* we only read immediates. */
David Turner9f95bab2002-06-07 07:23:06 +0000367
Werner Lemberge3f41982003-10-16 15:48:39 +0000368 n = 0;
Werner Lemberg4795b362003-10-23 16:24:10 +0000369 T1_Skip_Spaces( parser );
David Turner9f95bab2002-06-07 07:23:06 +0000370
Werner Lemberge3f41982003-10-16 15:48:39 +0000371 while ( parser->root.cursor < limit )
David Turner9f95bab2002-06-07 07:23:06 +0000372 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000373 cur = parser->root.cursor;
David Turner9f95bab2002-06-07 07:23:06 +0000374
Werner Lemberge3f41982003-10-16 15:48:39 +0000375 /* we stop when we encounter `def' or `]' */
376 if ( *cur == 'd' && cur + 3 < limit )
David Turner9f95bab2002-06-07 07:23:06 +0000377 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000378 if ( cur[1] == 'e' &&
379 cur[2] == 'f' &&
380 t42_is_space( cur[3] ) )
David Turner9f95bab2002-06-07 07:23:06 +0000381 {
382 FT_TRACE6(( "encoding end\n" ));
Werner Lemberge3f41982003-10-16 15:48:39 +0000383 cur += 3;
David Turner9f95bab2002-06-07 07:23:06 +0000384 break;
385 }
386 }
Werner Lemberge3f41982003-10-16 15:48:39 +0000387 if ( *cur == ']' )
388 {
389 FT_TRACE6(( "encoding end\n" ));
390 cur++;
391 break;
392 }
David Turner9f95bab2002-06-07 07:23:06 +0000393
Werner Lemberge3f41982003-10-16 15:48:39 +0000394 /* check whether we've found an entry */
395 if ( ft_isdigit( *cur ) || only_immediates )
David Turner9f95bab2002-06-07 07:23:06 +0000396 {
397 FT_Int charcode;
398
399
Werner Lemberge3f41982003-10-16 15:48:39 +0000400 if ( only_immediates )
401 charcode = n;
402 else
David Turner9f95bab2002-06-07 07:23:06 +0000403 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000404 charcode = (FT_Int)T1_ToInt( parser );
405 T1_Skip_Spaces( parser );
406 }
407
408 cur = parser->root.cursor;
409
410 if ( *cur == '/' && cur + 2 < limit && n < count )
411 {
Werner Lemberg3864f4e2003-09-30 06:43:54 +0000412 FT_PtrDist len;
David Turner9f95bab2002-06-07 07:23:06 +0000413
414
Werner Lemberge3f41982003-10-16 15:48:39 +0000415 cur++;
David Turner9f95bab2002-06-07 07:23:06 +0000416
Werner Lemberge3f41982003-10-16 15:48:39 +0000417 parser->root.cursor = cur;
418 T1_Skip_PS_Token( parser );
Werner Lemberg1d565fb2005-02-13 21:42:42 +0000419 if ( parser->root.error )
420 return;
Werner Lemberge3f41982003-10-16 15:48:39 +0000421
422 len = parser->root.cursor - cur;
David Turner9f95bab2002-06-07 07:23:06 +0000423
424 parser->root.error = T1_Add_Table( char_table, charcode,
Werner Lemberge3f41982003-10-16 15:48:39 +0000425 cur, len + 1 );
David Turner9f95bab2002-06-07 07:23:06 +0000426 if ( parser->root.error )
427 return;
Werner Lemberg1d565fb2005-02-13 21:42:42 +0000428 char_table->elements[charcode][len] = '\0';
David Turner9f95bab2002-06-07 07:23:06 +0000429
Werner Lemberge3f41982003-10-16 15:48:39 +0000430 n++;
David Turner9f95bab2002-06-07 07:23:06 +0000431 }
432 }
433 else
Werner Lemberge3f41982003-10-16 15:48:39 +0000434 T1_Skip_PS_Token( parser );
Werner Lemberg4795b362003-10-23 16:24:10 +0000435
436 T1_Skip_Spaces( parser );
David Turner9f95bab2002-06-07 07:23:06 +0000437 }
438
439 face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY;
440 parser->root.cursor = cur;
441 }
Werner Lemberge3f41982003-10-16 15:48:39 +0000442
David Turner9f95bab2002-06-07 07:23:06 +0000443 /* Otherwise, we should have either `StandardEncoding', */
444 /* `ExpertEncoding', or `ISOLatin1Encoding' */
445 else
446 {
447 if ( cur + 17 < limit &&
448 ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
449 face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;
450
451 else if ( cur + 15 < limit &&
452 ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
453 face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;
454
455 else if ( cur + 18 < limit &&
456 ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
457 face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;
458
Werner Lemberge3f41982003-10-16 15:48:39 +0000459 else
460 {
David Turner9f95bab2002-06-07 07:23:06 +0000461 FT_ERROR(( "t42_parse_encoding: invalid token!\n" ));
Werner Lemberg8c90c222002-06-08 06:47:18 +0000462 parser->root.error = T42_Err_Invalid_File_Format;
David Turner9f95bab2002-06-07 07:23:06 +0000463 }
464 }
465 }
466
467
Werner Lemberge3f41982003-10-16 15:48:39 +0000468 typedef enum
David Turner9f95bab2002-06-07 07:23:06 +0000469 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000470 BEFORE_START,
471 BEFORE_TABLE_DIR,
472 OTHER_TABLES
David Turner3c40d732003-08-17 22:31:23 +0000473
Werner Lemberge3f41982003-10-16 15:48:39 +0000474 } T42_Load_Status;
David Turner9f95bab2002-06-07 07:23:06 +0000475
476
477 static void
478 t42_parse_sfnts( T42_Face face,
479 T42_Loader loader )
480 {
481 T42_Parser parser = &loader->parser;
482 FT_Memory memory = parser->root.memory;
Werner Lemberge3f41982003-10-16 15:48:39 +0000483 FT_Byte* cur;
David Turner9f95bab2002-06-07 07:23:06 +0000484 FT_Byte* limit = parser->root.limit;
485 FT_Error error;
Werner Lemberge3f41982003-10-16 15:48:39 +0000486 FT_Int num_tables = 0;
487 FT_ULong count, ttf_size = 0;
488
489 FT_Long n, string_size, old_string_size, real_size;
490 FT_Byte* string_buf = NULL;
491 FT_Bool alloc = 0;
492
493 T42_Load_Status status;
David Turner9f95bab2002-06-07 07:23:06 +0000494
495
Werner Lemberge3f41982003-10-16 15:48:39 +0000496 /* The format is */
497 /* */
498 /* /sfnts [ <hexstring> <hexstring> ... ] def */
499 /* */
500 /* or */
501 /* */
502 /* /sfnts [ */
503 /* <num_bin_bytes> RD <binary data> */
504 /* <num_bin_bytes> RD <binary data> */
505 /* ... */
506 /* ] def */
507 /* */
508 /* with exactly one space after the `RD' token. */
David Turner9f95bab2002-06-07 07:23:06 +0000509
Werner Lemberge3f41982003-10-16 15:48:39 +0000510 T1_Skip_Spaces( parser );
David Turner9f95bab2002-06-07 07:23:06 +0000511
Werner Lemberge3f41982003-10-16 15:48:39 +0000512 if ( parser->root.cursor >= limit || *parser->root.cursor++ != '[' )
David Turner9f95bab2002-06-07 07:23:06 +0000513 {
514 FT_ERROR(( "t42_parse_sfnts: can't find begin of sfnts vector!\n" ));
Werner Lemberg8c90c222002-06-08 06:47:18 +0000515 error = T42_Err_Invalid_File_Format;
David Turner9f95bab2002-06-07 07:23:06 +0000516 goto Fail;
517 }
518
Werner Lemberge3f41982003-10-16 15:48:39 +0000519 T1_Skip_Spaces( parser );
520 status = BEFORE_START;
Werner Lemberg17d75812003-10-20 08:29:46 +0000521 string_size = 0;
Werner Lemberge3f41982003-10-16 15:48:39 +0000522 old_string_size = 0;
523 count = 0;
524
525 while ( parser->root.cursor < limit )
David Turner9f95bab2002-06-07 07:23:06 +0000526 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000527 cur = parser->root.cursor;
David Turner9f95bab2002-06-07 07:23:06 +0000528
Werner Lemberge3f41982003-10-16 15:48:39 +0000529 if ( *cur == ']' )
David Turner9f95bab2002-06-07 07:23:06 +0000530 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000531 parser->root.cursor++;
532 goto Exit;
David Turner9f95bab2002-06-07 07:23:06 +0000533 }
534
Werner Lemberge3f41982003-10-16 15:48:39 +0000535 else if ( *cur == '<' )
David Turner9f95bab2002-06-07 07:23:06 +0000536 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000537 T1_Skip_PS_Token( parser );
538 if ( parser->root.error )
539 goto Exit;
540
541 /* don't include delimiters */
542 string_size = (FT_Long)( ( parser->root.cursor - cur - 2 + 1 ) / 2 );
543 if ( FT_REALLOC( string_buf, old_string_size, string_size ) )
544 goto Fail;
545
546 alloc = 1;
547
548 parser->root.cursor = cur;
549 (void)T1_ToBytes( parser, string_buf, string_size, &real_size, 1 );
550 old_string_size = string_size;
551 string_size = real_size;
552 }
553
554 else if ( ft_isdigit( *cur ) )
555 {
556 string_size = T1_ToInt( parser );
557
558 T1_Skip_PS_Token( parser ); /* `RD' */
Werner Lemberg1d565fb2005-02-13 21:42:42 +0000559 if ( parser->root.error )
560 return;
Werner Lemberge3f41982003-10-16 15:48:39 +0000561
562 string_buf = parser->root.cursor + 1; /* one space after `RD' */
563
564 parser->root.cursor += string_size + 1;
565 if ( parser->root.cursor >= limit )
David Turner9f95bab2002-06-07 07:23:06 +0000566 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000567 FT_ERROR(( "t42_parse_sfnts: too many binary data!\n" ));
568 error = T42_Err_Invalid_File_Format;
569 goto Fail;
David Turner9f95bab2002-06-07 07:23:06 +0000570 }
Werner Lemberge3f41982003-10-16 15:48:39 +0000571 }
572
573 /* A string can have a trailing zero byte for padding. Ignore it. */
574 if ( string_buf[string_size - 1] == 0 && ( string_size % 2 == 1 ) )
575 string_size--;
576
577 for ( n = 0; n < string_size; n++ )
578 {
579 switch ( status )
David Turner9f95bab2002-06-07 07:23:06 +0000580 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000581 case BEFORE_START:
582 /* load offset table, 12 bytes */
583 if ( count < 12 )
David Turner9f95bab2002-06-07 07:23:06 +0000584 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000585 face->ttf_data[count++] = string_buf[n];
586 continue;
David Turner9f95bab2002-06-07 07:23:06 +0000587 }
Werner Lemberge3f41982003-10-16 15:48:39 +0000588 else
589 {
590 num_tables = 16 * face->ttf_data[4] + face->ttf_data[5];
591 status = BEFORE_TABLE_DIR;
592 ttf_size = 12 + 16 * num_tables;
David Turner9f95bab2002-06-07 07:23:06 +0000593
Werner Lemberge3f41982003-10-16 15:48:39 +0000594 if ( FT_REALLOC( face->ttf_data, 12, ttf_size ) )
595 goto Fail;
596 }
597 /* fall through */
David Turner9f95bab2002-06-07 07:23:06 +0000598
Werner Lemberge3f41982003-10-16 15:48:39 +0000599 case BEFORE_TABLE_DIR:
600 /* the offset table is read; read the table directory */
601 if ( count < ttf_size )
602 {
603 face->ttf_data[count++] = string_buf[n];
604 continue;
605 }
606 else
607 {
608 int i;
609 FT_ULong len;
610
611
612 for ( i = 0; i < num_tables; i++ )
613 {
614 FT_Byte* p = face->ttf_data + 12 + 16 * i + 12;
615
616
617 len = FT_PEEK_ULONG( p );
618
619 /* Pad to a 4-byte boundary length */
620 ttf_size += ( len + 3 ) & ~3;
621 }
622
623 status = OTHER_TABLES;
624 face->ttf_size = ttf_size;
625
626 if ( FT_REALLOC( face->ttf_data, 12 + 16 * num_tables,
627 ttf_size + 1 ) )
628 goto Fail;
629 }
630 /* fall through */
631
632 case OTHER_TABLES:
633 /* all other tables are just copied */
634 if ( count >= ttf_size )
635 {
636 FT_ERROR(( "t42_parse_sfnts: too many binary data!\n" ));
637 error = T42_Err_Invalid_File_Format;
David Turner9f95bab2002-06-07 07:23:06 +0000638 goto Fail;
Werner Lemberge3f41982003-10-16 15:48:39 +0000639 }
640 face->ttf_data[count++] = string_buf[n];
David Turner9f95bab2002-06-07 07:23:06 +0000641 }
David Turner9f95bab2002-06-07 07:23:06 +0000642 }
Werner Lemberge3f41982003-10-16 15:48:39 +0000643
644 T1_Skip_Spaces( parser );
David Turner9f95bab2002-06-07 07:23:06 +0000645 }
646
Werner Lemberge3f41982003-10-16 15:48:39 +0000647 /* if control reaches this point, the format was not valid */
Werner Lemberg8c90c222002-06-08 06:47:18 +0000648 error = T42_Err_Invalid_File_Format;
David Turner9f95bab2002-06-07 07:23:06 +0000649
650 Fail:
651 parser->root.error = error;
Werner Lemberge3f41982003-10-16 15:48:39 +0000652
653 Exit:
654 if ( alloc )
655 FT_FREE( string_buf );
David Turner9f95bab2002-06-07 07:23:06 +0000656 }
657
658
659 static void
660 t42_parse_charstrings( T42_Face face,
661 T42_Loader loader )
662 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000663 T42_Parser parser = &loader->parser;
664 PS_Table code_table = &loader->charstrings;
665 PS_Table name_table = &loader->glyph_names;
666 PS_Table swap_table = &loader->swap_table;
667 FT_Memory memory = parser->root.memory;
David Turner9f95bab2002-06-07 07:23:06 +0000668 FT_Error error;
669
Werner Lemberge3f41982003-10-16 15:48:39 +0000670 PSAux_Service psaux = (PSAux_Service)face->psaux;
David Turner9f95bab2002-06-07 07:23:06 +0000671
672 FT_Byte* cur;
Werner Lemberge3f41982003-10-16 15:48:39 +0000673 FT_Byte* limit = parser->root.limit;
674 FT_UInt n;
675 FT_UInt notdef_index = 0;
676 FT_Byte notdef_found = 0;
David Turner9f95bab2002-06-07 07:23:06 +0000677
678
Werner Lemberge3f41982003-10-16 15:48:39 +0000679 T1_Skip_Spaces( parser );
680
681 if ( parser->root.cursor >= limit )
682 {
683 FT_ERROR(( "t42_parse_charstrings: out of bounds!\n" ));
684 error = T42_Err_Invalid_File_Format;
685 goto Fail;
686 }
687
688 if ( ft_isdigit( *parser->root.cursor ) )
689 {
690 loader->num_glyphs = (FT_UInt)T1_ToInt( parser );
691 if ( parser->root.error )
692 return;
693 }
694 else if ( *parser->root.cursor == '<' )
695 {
696 /* We have `<< ... >>'. Count the number of `/' in the dictionary */
697 /* to get its size. */
698 FT_UInt count = 0;
699
700
701 T1_Skip_PS_Token( parser );
Werner Lemberg1d565fb2005-02-13 21:42:42 +0000702 if ( parser->root.error )
703 return;
Werner Lemberge3f41982003-10-16 15:48:39 +0000704 T1_Skip_Spaces( parser );
705 cur = parser->root.cursor;
706
707 while ( parser->root.cursor < limit )
708 {
709 if ( *parser->root.cursor == '/' )
710 count++;
711 else if ( *parser->root.cursor == '>' )
712 {
713 loader->num_glyphs = count;
714 parser->root.cursor = cur; /* rewind */
715 break;
716 }
717 T1_Skip_PS_Token( parser );
Werner Lemberg1d565fb2005-02-13 21:42:42 +0000718 if ( parser->root.error )
719 return;
Werner Lemberge3f41982003-10-16 15:48:39 +0000720 T1_Skip_Spaces( parser );
721 }
722 }
723 else
724 {
725 FT_ERROR(( "t42_parse_charstrings: invalid token!\n" ));
726 error = T42_Err_Invalid_File_Format;
727 goto Fail;
728 }
729
730 if ( parser->root.cursor >= limit )
731 {
732 FT_ERROR(( "t42_parse_charstrings: out of bounds!\n" ));
733 error = T42_Err_Invalid_File_Format;
734 goto Fail;
735 }
David Turner9f95bab2002-06-07 07:23:06 +0000736
737 /* initialize tables */
738
739 error = psaux->ps_table_funcs->init( code_table,
740 loader->num_glyphs,
741 memory );
742 if ( error )
743 goto Fail;
744
745 error = psaux->ps_table_funcs->init( name_table,
746 loader->num_glyphs,
747 memory );
748 if ( error )
749 goto Fail;
750
Werner Lemberge3f41982003-10-16 15:48:39 +0000751 /* Initialize table for swapping index notdef_index and */
752 /* index 0 names and codes (if necessary). */
753
754 error = psaux->ps_table_funcs->init( swap_table, 4, memory );
755 if ( error )
756 goto Fail;
757
David Turner9f95bab2002-06-07 07:23:06 +0000758 n = 0;
759
760 for (;;)
761 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000762 /* The format is simple: */
763 /* `/glyphname' + index [+ def] */
764
David Turner9f95bab2002-06-07 07:23:06 +0000765 T1_Skip_Spaces( parser );
766
767 cur = parser->root.cursor;
768 if ( cur >= limit )
769 break;
770
Werner Lemberge3f41982003-10-16 15:48:39 +0000771 /* We stop when we find an `end' keyword or '>' */
772 if ( *cur == 'e' &&
773 cur + 3 < limit &&
774 cur[1] == 'n' &&
775 cur[2] == 'd' &&
776 t42_is_space( cur[3] ) )
777 break;
778 if ( *cur == '>' )
David Turner9f95bab2002-06-07 07:23:06 +0000779 break;
780
Werner Lemberge3f41982003-10-16 15:48:39 +0000781 T1_Skip_PS_Token( parser );
Werner Lemberg1d565fb2005-02-13 21:42:42 +0000782 if ( parser->root.error )
783 return;
Werner Lemberge3f41982003-10-16 15:48:39 +0000784
785 if ( *cur == '/' )
David Turner9f95bab2002-06-07 07:23:06 +0000786 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000787 FT_PtrDist len;
David Turner9f95bab2002-06-07 07:23:06 +0000788
789
Werner Lemberge3f41982003-10-16 15:48:39 +0000790 if ( cur + 1 >= limit )
791 {
792 FT_ERROR(( "t42_parse_charstrings: out of bounds!\n" ));
793 error = T42_Err_Invalid_File_Format;
794 goto Fail;
795 }
David Turner9f95bab2002-06-07 07:23:06 +0000796
Werner Lemberge3f41982003-10-16 15:48:39 +0000797 cur++; /* skip `/' */
798 len = parser->root.cursor - cur;
799
800 error = T1_Add_Table( name_table, n, cur, len + 1 );
David Turner9f95bab2002-06-07 07:23:06 +0000801 if ( error )
802 goto Fail;
803
804 /* add a trailing zero to the name table */
805 name_table->elements[n][len] = '\0';
806
Werner Lemberge3f41982003-10-16 15:48:39 +0000807 /* record index of /.notdef */
808 if ( *cur == '.' &&
809 ft_strcmp( ".notdef",
810 (const char*)(name_table->elements[n]) ) == 0 )
811 {
812 notdef_index = n;
813 notdef_found = 1;
814 }
815
David Turner9f95bab2002-06-07 07:23:06 +0000816 T1_Skip_Spaces( parser );
817
Werner Lemberge3f41982003-10-16 15:48:39 +0000818 cur = parser->root.cursor;
David Turner9f95bab2002-06-07 07:23:06 +0000819
Werner Lemberge3f41982003-10-16 15:48:39 +0000820 (void)T1_ToInt( parser );
821 if ( parser->root.cursor >= limit )
822 {
823 FT_ERROR(( "t42_parse_charstrings: out of bounds!\n" ));
824 error = T42_Err_Invalid_File_Format;
825 goto Fail;
826 }
827
828 len = parser->root.cursor - cur;
David Turner9f95bab2002-06-07 07:23:06 +0000829
830 error = T1_Add_Table( code_table, n, cur, len + 1 );
831 if ( error )
832 goto Fail;
833
834 code_table->elements[n][len] = '\0';
835
836 n++;
837 if ( n >= loader->num_glyphs )
838 break;
839 }
840 }
841
Werner Lemberge3f41982003-10-16 15:48:39 +0000842 loader->num_glyphs = n;
843
844 if ( !notdef_found )
David Turner9f95bab2002-06-07 07:23:06 +0000845 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000846 FT_ERROR(( "t42_parse_charstrings: no /.notdef glyph!\n" ));
Werner Lemberg8c90c222002-06-08 06:47:18 +0000847 error = T42_Err_Invalid_File_Format;
David Turner9f95bab2002-06-07 07:23:06 +0000848 goto Fail;
849 }
850
Werner Lemberge3f41982003-10-16 15:48:39 +0000851 /* if /.notdef does not occupy index 0, do our magic. */
852 if ( ft_strcmp( (const char*)".notdef",
853 (const char*)name_table->elements[0] ) )
854 {
855 /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */
856 /* name and code entries to swap_table. Then place notdef_index */
857 /* name and code entries into swap_table. Then swap name and code */
858 /* entries at indices notdef_index and 0 using values stored in */
859 /* swap_table. */
860
861 /* Index 0 name */
862 error = T1_Add_Table( swap_table, 0,
863 name_table->elements[0],
864 name_table->lengths [0] );
865 if ( error )
866 goto Fail;
867
868 /* Index 0 code */
869 error = T1_Add_Table( swap_table, 1,
870 code_table->elements[0],
871 code_table->lengths [0] );
872 if ( error )
873 goto Fail;
874
875 /* Index notdef_index name */
876 error = T1_Add_Table( swap_table, 2,
877 name_table->elements[notdef_index],
878 name_table->lengths [notdef_index] );
879 if ( error )
880 goto Fail;
881
882 /* Index notdef_index code */
883 error = T1_Add_Table( swap_table, 3,
884 code_table->elements[notdef_index],
885 code_table->lengths [notdef_index] );
886 if ( error )
887 goto Fail;
888
889 error = T1_Add_Table( name_table, notdef_index,
890 swap_table->elements[0],
891 swap_table->lengths [0] );
892 if ( error )
893 goto Fail;
894
895 error = T1_Add_Table( code_table, notdef_index,
896 swap_table->elements[1],
897 swap_table->lengths [1] );
898 if ( error )
899 goto Fail;
900
901 error = T1_Add_Table( name_table, 0,
902 swap_table->elements[2],
903 swap_table->lengths [2] );
904 if ( error )
905 goto Fail;
906
907 error = T1_Add_Table( code_table, 0,
908 swap_table->elements[3],
909 swap_table->lengths [3] );
910 if ( error )
911 goto Fail;
912
913 }
914
David Turner9f95bab2002-06-07 07:23:06 +0000915 return;
916
917 Fail:
918 parser->root.error = error;
919 }
920
921
922 static FT_Error
923 t42_load_keyword( T42_Face face,
924 T42_Loader loader,
925 T1_Field field )
926 {
927 FT_Error error;
928 void* dummy_object;
929 void** objects;
930 FT_UInt max_objects = 0;
931
932
933 /* if the keyword has a dedicated callback, call it */
Werner Lemberge3f41982003-10-16 15:48:39 +0000934 if ( field->type == T1_FIELD_TYPE_CALLBACK )
935 {
David Turner9f95bab2002-06-07 07:23:06 +0000936 field->reader( (FT_Face)face, loader );
937 error = loader->parser.root.error;
938 goto Exit;
939 }
940
Werner Lemberge3f41982003-10-16 15:48:39 +0000941 /* now the keyword is either a simple field or a table of fields; */
942 /* we are now going to take care of it */
943
David Turner9f95bab2002-06-07 07:23:06 +0000944 switch ( field->location )
945 {
946 case T1_FIELD_LOCATION_FONT_INFO:
947 dummy_object = &face->type1.font_info;
Werner Lembergfdc042b2003-06-12 04:59:07 +0000948 break;
949
950 case T1_FIELD_LOCATION_BBOX:
951 dummy_object = &face->type1.font_bbox;
David Turner9f95bab2002-06-07 07:23:06 +0000952 break;
953
954 default:
955 dummy_object = &face->type1;
David Turner9f95bab2002-06-07 07:23:06 +0000956 }
957
Werner Lembergfdc042b2003-06-12 04:59:07 +0000958 objects = &dummy_object;
959
David Turner9f95bab2002-06-07 07:23:06 +0000960 if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
961 field->type == T1_FIELD_TYPE_FIXED_ARRAY )
962 error = T1_Load_Field_Table( &loader->parser, field,
963 objects, max_objects, 0 );
964 else
965 error = T1_Load_Field( &loader->parser, field,
966 objects, max_objects, 0 );
967
968 Exit:
969 return error;
970 }
971
972
973 FT_LOCAL_DEF( FT_Error )
974 t42_parse_dict( T42_Face face,
975 T42_Loader loader,
976 FT_Byte* base,
977 FT_Long size )
978 {
Werner Lemberg73861972003-06-05 04:31:05 +0000979 T42_Parser parser = &loader->parser;
Werner Lemberge3f41982003-10-16 15:48:39 +0000980 FT_Byte* limit;
Werner Lembergdc8ad542003-12-09 02:12:14 +0000981 FT_Int n_keywords = (FT_Int)( sizeof ( t42_keywords ) /
982 sizeof ( t42_keywords[0] ) );
David Turner3c40d732003-08-17 22:31:23 +0000983
David Turner9f95bab2002-06-07 07:23:06 +0000984
985 parser->root.cursor = base;
986 parser->root.limit = base + size;
Werner Lemberge3f41982003-10-16 15:48:39 +0000987 parser->root.error = T42_Err_Ok;
David Turner9f95bab2002-06-07 07:23:06 +0000988
Werner Lemberge3f41982003-10-16 15:48:39 +0000989 limit = parser->root.limit;
990
991 T1_Skip_Spaces( parser );
992
993 while ( parser->root.cursor < limit )
David Turner9f95bab2002-06-07 07:23:06 +0000994 {
Werner Lemberge3f41982003-10-16 15:48:39 +0000995 FT_Byte* cur;
996
997
998 cur = parser->root.cursor;
999
1000 /* look for `FontDirectory' which causes problems for some fonts */
David Turner9f95bab2002-06-07 07:23:06 +00001001 if ( *cur == 'F' && cur + 25 < limit &&
1002 ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
1003 {
1004 FT_Byte* cur2;
1005
1006
1007 /* skip the `FontDirectory' keyword */
Werner Lemberge3f41982003-10-16 15:48:39 +00001008 T1_Skip_PS_Token( parser );
1009 T1_Skip_Spaces ( parser );
1010 cur = cur2 = parser->root.cursor;
David Turner9f95bab2002-06-07 07:23:06 +00001011
Werner Lemberge3f41982003-10-16 15:48:39 +00001012 /* look up the `known' keyword */
1013 while ( cur < limit )
1014 {
1015 if ( *cur == 'k' && cur + 5 < limit &&
1016 ft_strncmp( (char*)cur, "known", 5 ) == 0 )
1017 break;
1018
1019 T1_Skip_PS_Token( parser );
Werner Lemberg1d565fb2005-02-13 21:42:42 +00001020 if ( parser->root.error )
1021 goto Exit;
Werner Lemberge3f41982003-10-16 15:48:39 +00001022 T1_Skip_Spaces ( parser );
1023 cur = parser->root.cursor;
1024 }
David Turner9f95bab2002-06-07 07:23:06 +00001025
1026 if ( cur < limit )
1027 {
1028 T1_TokenRec token;
1029
1030
1031 /* skip the `known' keyword and the token following it */
Werner Lemberge3f41982003-10-16 15:48:39 +00001032 T1_Skip_PS_Token( parser );
1033 T1_ToToken( parser, &token );
David Turner9f95bab2002-06-07 07:23:06 +00001034
1035 /* if the last token was an array, skip it! */
1036 if ( token.type == T1_TOKEN_TYPE_ARRAY )
1037 cur2 = parser->root.cursor;
1038 }
Werner Lemberge3f41982003-10-16 15:48:39 +00001039 parser->root.cursor = cur2;
David Turner9f95bab2002-06-07 07:23:06 +00001040 }
Werner Lemberge3f41982003-10-16 15:48:39 +00001041
David Turner9f95bab2002-06-07 07:23:06 +00001042 /* look for immediates */
1043 else if ( *cur == '/' && cur + 2 < limit )
1044 {
Werner Lemberge3f41982003-10-16 15:48:39 +00001045 FT_PtrDist len;
David Turner9f95bab2002-06-07 07:23:06 +00001046
1047
1048 cur++;
David Turner9f95bab2002-06-07 07:23:06 +00001049
Werner Lemberge3f41982003-10-16 15:48:39 +00001050 parser->root.cursor = cur;
1051 T1_Skip_PS_Token( parser );
Werner Lemberg1d565fb2005-02-13 21:42:42 +00001052 if ( parser->root.error )
1053 goto Exit;
Werner Lemberge3f41982003-10-16 15:48:39 +00001054
1055 len = parser->root.cursor - cur;
1056
1057 if ( len > 0 && len < 22 && parser->root.cursor < limit )
David Turner9f95bab2002-06-07 07:23:06 +00001058 {
Werner Lemberge3f41982003-10-16 15:48:39 +00001059 int i;
David Turner9f95bab2002-06-07 07:23:06 +00001060
Werner Lemberge3f41982003-10-16 15:48:39 +00001061
1062 /* now compare the immediate name to the keyword table */
1063
1064 /* loop through all known keywords */
David Turner9f95bab2002-06-07 07:23:06 +00001065 for ( i = 0; i < n_keywords; i++ )
1066 {
1067 T1_Field keyword = (T1_Field)&t42_keywords[i];
1068 FT_Byte *name = (FT_Byte*)keyword->ident;
1069
1070
1071 if ( !name )
1072 continue;
1073
Werner Lemberg3605e472004-11-12 07:02:45 +00001074 if ( cur[0] == name[0] &&
1075 len == (FT_PtrDist)ft_strlen( (const char *)name ) &&
1076 ft_memcmp( cur, name, len ) == 0 )
David Turner9f95bab2002-06-07 07:23:06 +00001077 {
1078 /* we found it -- run the parsing callback! */
Werner Lemberge3f41982003-10-16 15:48:39 +00001079 parser->root.error = t42_load_keyword( face,
1080 loader,
1081 keyword );
1082 if ( parser->root.error )
1083 return parser->root.error;
David Turner9f95bab2002-06-07 07:23:06 +00001084 break;
1085 }
1086 }
1087 }
1088 }
Werner Lemberge3f41982003-10-16 15:48:39 +00001089 else
Werner Lemberg1d565fb2005-02-13 21:42:42 +00001090 {
Werner Lemberge3f41982003-10-16 15:48:39 +00001091 T1_Skip_PS_Token( parser );
Werner Lemberg1d565fb2005-02-13 21:42:42 +00001092 if ( parser->root.error )
1093 goto Exit;
1094 }
Werner Lemberge3f41982003-10-16 15:48:39 +00001095
1096 T1_Skip_Spaces( parser );
David Turner9f95bab2002-06-07 07:23:06 +00001097 }
Werner Lemberge3f41982003-10-16 15:48:39 +00001098
Werner Lemberg1d565fb2005-02-13 21:42:42 +00001099 Exit:
David Turner9f95bab2002-06-07 07:23:06 +00001100 return parser->root.error;
1101 }
1102
1103
1104 FT_LOCAL_DEF( void )
1105 t42_loader_init( T42_Loader loader,
1106 T42_Face face )
1107 {
1108 FT_UNUSED( face );
1109
Werner Lembergb3d5e9c2002-07-28 05:05:24 +00001110 FT_MEM_ZERO( loader, sizeof ( *loader ) );
David Turner9f95bab2002-06-07 07:23:06 +00001111 loader->num_glyphs = 0;
1112 loader->num_chars = 0;
1113
1114 /* initialize the tables -- simply set their `init' field to 0 */
1115 loader->encoding_table.init = 0;
1116 loader->charstrings.init = 0;
1117 loader->glyph_names.init = 0;
1118 }
1119
1120
1121 FT_LOCAL_DEF( void )
1122 t42_loader_done( T42_Loader loader )
1123 {
1124 T42_Parser parser = &loader->parser;
1125
1126
1127 /* finalize tables */
1128 T1_Release_Table( &loader->encoding_table );
1129 T1_Release_Table( &loader->charstrings );
1130 T1_Release_Table( &loader->glyph_names );
Werner Lemberge3f41982003-10-16 15:48:39 +00001131 T1_Release_Table( &loader->swap_table );
David Turner9f95bab2002-06-07 07:23:06 +00001132
1133 /* finalize parser */
1134 t42_parser_done( parser );
1135 }
1136
1137
Werner Lemberg8c90c222002-06-08 06:47:18 +00001138/* END */