1 /***************************************************************************/
5 /* CID-keyed Type1 font loader (body). */
7 /* Copyright 1996-2000 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16 /***************************************************************************/
19 #include <freetype/internal/ftdebug.h>
20 #include <freetype/config/ftconfig.h>
21 #include <freetype/ftmm.h>
23 #include <freetype/internal/t1types.h>
24 #include <freetype/internal/t1errors.h>
27 #ifdef FT_FLAT_COMPILE
33 #include <freetype/src/cid/cidload.h>
39 #include <ctype.h> /* for isspace(), isalnum() */
42 /*************************************************************************/
44 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
45 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
46 /* messages during execution. */
49 #define FT_COMPONENT trace_cidload
52 /* read a single offset */
54 FT_Long cid_get_offset( FT_Byte** start,
61 for ( result = 0; offsize > 0; offsize-- )
73 void cid_decrypt( FT_Byte* buffer,
82 plain = ( *buffer ^ ( seed >> 8 ) );
83 seed = ( *buffer + seed ) * 52845 + 22719;
90 /*************************************************************************/
91 /*************************************************************************/
93 /***** TYPE 1 SYMBOL PARSING *****/
95 /*************************************************************************/
96 /*************************************************************************/
100 FT_Error cid_load_keyword( CID_Face face,
102 const CID_Field_Rec* keyword )
105 CID_Parser* parser = &loader->parser;
107 CID_Info* cid = &face->cid;
110 /* if the keyword has a dedicated callback, call it */
111 if ( keyword->type == t1_field_callback )
113 error = keyword->reader( face, parser );
117 /* we must now compute the address of our target object */
118 switch ( keyword->location )
120 case t1_field_cid_info:
121 object = (FT_Byte*)cid;
124 case t1_field_font_info:
125 object = (FT_Byte*)&cid->font_info;
133 if ( parser->num_dict < 0 )
135 FT_ERROR(( "cid_load_keyword: invalid use of `%s'!\n",
137 error = T1_Err_Syntax_Error;
141 dict = cid->font_dicts + parser->num_dict;
142 switch ( keyword->location )
144 case t1_field_private:
145 object = (FT_Byte*)&dict->private_dict;
149 object = (FT_Byte*)dict;
154 /* now, load the keyword data in the object's field(s) */
155 if ( keyword->type == t1_field_integer_array ||
156 keyword->type == t1_field_fixed_array )
157 error = CID_Load_Field_Table( parser, keyword, object );
159 error = CID_Load_Field( parser, keyword, object );
167 FT_Error parse_font_bbox( CID_Face face,
171 FT_BBox* bbox = &face->cid.font_bbox;
174 (void)CID_ToCoordArray( parser, 4, temp );
175 bbox->xMin = temp[0];
176 bbox->yMin = temp[1];
177 bbox->xMax = temp[2];
178 bbox->yMax = temp[3];
180 return T1_Err_Ok; /* this is a callback function; */
181 /* we must return an error code */
186 FT_Error parse_font_matrix( CID_Face face,
194 if ( parser->num_dict >= 0 )
196 dict = face->cid.font_dicts + parser->num_dict;
197 matrix = &dict->font_matrix;
199 (void)CID_ToFixedArray( parser, 4, temp, 3 );
200 matrix->xx = temp[0];
201 matrix->yx = temp[1];
202 matrix->xy = temp[2];
203 matrix->yy = temp[3];
206 return T1_Err_Ok; /* this is a callback function; */
207 /* we must return an error code */
212 FT_Error parse_fd_array( CID_Face face,
215 CID_Info* cid = &face->cid;
216 FT_Memory memory = face->root.memory;
217 FT_Error error = T1_Err_Ok;
221 num_dicts = CID_ToInt( parser );
223 if ( !cid->font_dicts )
228 if ( ALLOC_ARRAY( cid->font_dicts, num_dicts, CID_FontDict ) )
231 cid->num_dicts = (FT_UInt)num_dicts;
233 /* don't forget to set a few defaults */
234 for ( n = 0; n < cid->num_dicts; n++ )
236 CID_FontDict* dict = cid->font_dicts + n;
239 /* default value for lenIV */
240 dict->private_dict.lenIV = 4;
250 const CID_Field_Rec t1_field_records[] =
253 #ifdef FT_FLAT_COMPILE
255 #include "cidtokens.h"
259 #include <freetype/src/cid/cidtokens.h>
263 { 0, t1_field_cid_info, t1_field_none, 0, 0, 0, 0, 0 }
268 int is_alpha( char c )
270 return ( isalnum( c ) ||
277 void skip_whitespace( CID_Parser* parser )
279 FT_Byte* cur = parser->cursor;
282 while ( cur < parser->limit && isspace( *cur ) )
285 parser->cursor = cur;
290 FT_Error parse_dict( CID_Face face,
295 CID_Parser* parser = &loader->parser;
298 parser->cursor = base;
299 parser->limit = base + size;
304 FT_Byte* limit = cur + size;
307 for ( ;cur < limit; cur++ )
309 /* look for `%ADOBeginFontDict' */
310 if ( *cur == '%' && cur + 20 < limit &&
311 strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
315 /* if /FDArray was found, then cid->num_dicts is > 0, and */
316 /* we can start increasing parser->num_dict */
317 if ( face->cid.num_dicts > 0 )
320 /* look for immediates */
321 else if ( *cur == '/' && cur + 2 < limit )
330 while ( cur2 < limit && is_alpha( *cur2 ) )
334 if ( len > 0 && len < 22 )
336 /* now compare the immediate name to the keyword table */
337 const CID_Field_Rec* keyword = t1_field_records;
345 name = (FT_Byte*)keyword->ident;
349 if ( cur[0] == name[0] &&
350 len == (FT_Int)strlen( (const char*)name ) )
355 for ( n = 1; n < len; n++ )
356 if ( cur[n] != name[n] )
361 /* we found it - run the parsing callback */
362 parser->cursor = cur2;
363 skip_whitespace( parser );
364 parser->error = cid_load_keyword( face, loader, keyword );
366 return parser->error;
368 cur = parser->cursor;
378 return parser->error;
382 /* read the subrmap and the subrs of each font dict */
384 FT_Error cid_read_subrs( CID_Face face )
386 CID_Info* cid = &face->cid;
387 FT_Memory memory = face->root.memory;
388 FT_Stream stream = face->root.stream;
392 FT_UInt max_offsets = 0;
393 FT_ULong* offsets = 0;
396 if ( ALLOC_ARRAY( face->subrs, cid->num_dicts, CID_Subrs ) )
400 for ( n = 0; n < cid->num_dicts; n++, subr++ )
402 CID_FontDict* dict = cid->font_dicts + n;
403 FT_UInt count, num_subrs = dict->num_subrs;
408 /* reallocate offsets array if needed */
409 if ( num_subrs + 1 > max_offsets )
411 FT_UInt new_max = ( num_subrs + 1 + 3 ) & -4;
414 if ( REALLOC_ARRAY( offsets, max_offsets, new_max, FT_ULong ) )
417 max_offsets = new_max;
420 /* read the subrmap's offsets */
421 if ( FILE_Seek( cid->data_offset + dict->subrmap_offset ) ||
422 ACCESS_Frame( ( num_subrs + 1 ) * dict->sd_bytes ) )
425 p = (FT_Byte*)stream->cursor;
426 for ( count = 0; count <= num_subrs; count++ )
427 offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes );
431 /* now, compute the size of subrs charstrings, */
432 /* allocate, and read them */
433 data_len = offsets[num_subrs] - offsets[0];
435 if ( ALLOC_ARRAY( subr->code, num_subrs + 1, FT_Byte* ) ||
436 ALLOC( subr->code[0], data_len ) )
439 if ( FILE_Seek( cid->data_offset + offsets[0] ) ||
440 FILE_Read( subr->code[0], data_len ) )
443 /* set up pointers */
444 for ( count = 1; count <= num_subrs; count++ )
449 len = offsets[count] - offsets[count - 1];
450 subr->code[count] = subr->code[count - 1] + len;
453 /* decrypt subroutines */
454 for ( count = 0; count < num_subrs; count++ )
459 len = offsets[count + 1] - offsets[count];
460 cid_decrypt( subr->code[count], len, 4330 );
463 subr->num_subrs = num_subrs;
473 for ( n = 0; n < cid->num_dicts; n++ )
475 if ( face->subrs[n].code )
476 FREE( face->subrs[n].code[0] );
478 FREE( face->subrs[n].code );
487 void t1_init_loader( CID_Loader* loader,
492 MEM_Set( loader, 0, sizeof ( *loader ) );
497 void t1_done_loader( CID_Loader* loader )
499 CID_Parser* parser = &loader->parser;
502 /* finalize parser */
503 CID_Done_Parser( parser );
508 FT_Error CID_Open_Face( CID_Face face )
515 t1_init_loader( &loader, face );
517 parser = &loader.parser;
518 error = CID_New_Parser( parser, face->root.stream, face->root.memory );
522 error = parse_dict( face, &loader,
524 parser->postscript_len );
528 face->cid.data_offset = loader.parser.data_offset;
529 error = cid_read_subrs( face );
532 t1_done_loader( &loader );