1 /***************************************************************************/
5 /* CID-keyed Type1 parser (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/internal/ftcalc.h>
21 #include <freetype/internal/ftobjs.h>
22 #include <freetype/internal/ftstream.h>
23 #include <freetype/internal/t1errors.h>
26 #ifdef FT_FLAT_COMPILE
32 #include <freetype/src/cid/cidparse.h>
37 #include <string.h> /* for strncmp() */
40 /*************************************************************************/
42 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
43 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
44 /* messages during execution. */
47 #define FT_COMPONENT trace_cidparse
52 /*************************************************************************/
53 /*************************************************************************/
54 /*************************************************************************/
56 /***** IMPLEMENTATION OF CID_TABLE OBJECT *****/
58 /*************************************************************************/
59 /*************************************************************************/
60 /*************************************************************************/
63 /*************************************************************************/
69 /* Initializes a CID_Table. */
72 /* table :: The address of the target table. */
75 /* count :: The table size, i.e., the maximal number of elements. */
77 /* memory :: The memory object to be used for all subsequent */
81 /* FreeType error code. 0 means success. */
84 FT_Error CID_New_Table( CID_Table* table,
91 table->memory = memory;
92 if ( ALLOC_ARRAY( table->elements, count, FT_Byte* ) ||
93 ALLOC_ARRAY( table->lengths, count, FT_Byte* ) )
96 table->max_elems = count;
97 table->init = 0xDEADBEEFL;
105 FREE( table->elements );
112 void shift_elements( CID_Table* table,
115 FT_Long delta = table->block - old_base;
116 FT_Byte** offset = table->elements;
117 FT_Byte** limit = offset + table->max_elems;
121 for ( ; offset < limit; offset++ )
130 FT_Error reallocate_t1_table( CID_Table* table,
133 FT_Memory memory = table->memory;
134 FT_Byte* old_base = table->block;
138 /* realloc the base block */
139 if ( REALLOC( table->block, table->capacity, new_size ) )
142 table->capacity = new_size;
144 /* shift all offsets when needed */
146 shift_elements( table, old_base );
152 /*************************************************************************/
158 /* Adds an object to a CID_Table, possibly growing its memory block. */
161 /* table :: The target table. */
164 /* index :: The index of the object in the table. */
166 /* object :: The address of the object to copy in the memory. */
168 /* length :: The length in bytes of the source object. */
171 /* FreeType error code. 0 means success. An error is returned if */
172 /* reallocation fails. */
175 FT_Error CID_Add_Table( CID_Table* table,
180 if ( index < 0 || index > table->max_elems )
182 FT_ERROR(( "CID_Add_Table: invalid index\n" ));
183 return T1_Err_Syntax_Error;
186 /* grow the base block if needed */
187 if ( table->cursor + length > table->capacity )
190 FT_Int new_size = table->capacity;
193 while ( new_size < table->cursor + length )
196 error = reallocate_t1_table( table, new_size );
201 /* add the object to the base block and adjust offset */
202 table->elements[index] = table->block + table->cursor;
203 table->lengths [index] = length;
205 MEM_Copy( table->block + table->cursor, object, length );
207 table->cursor += length;
213 /*************************************************************************/
219 /* Finalizes a CID_Table (reallocate it to its current cursor). */
222 /* table :: The target table. */
225 /* This function does NOT release the heap's memory block. It is up */
226 /* to the caller to clean it, or reference it in its own structures. */
229 void CID_Done_Table( CID_Table* table )
231 FT_Memory memory = table->memory;
236 /* should never fail, as rec.cursor <= rec.size */
237 old_base = table->block;
241 (void)REALLOC( table->block, table->capacity, table->cursor );
242 table->capacity = table->cursor;
244 if ( old_base != table->block )
245 shift_elements( table, old_base );
250 void CID_Release_Table( CID_Table* table )
252 FT_Memory memory = table->memory;
255 if ( table->init == 0xDEADBEEFL )
257 FREE( table->block );
258 FREE( table->elements );
259 FREE( table->lengths );
267 /*************************************************************************/
268 /*************************************************************************/
269 /*************************************************************************/
271 /***** INPUT STREAM PARSER *****/
273 /*************************************************************************/
274 /*************************************************************************/
275 /*************************************************************************/
278 #define IS_CID_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' )
279 #define IS_CID_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' )
281 #define IS_CID_SPACE( c ) ( IS_CID_WHITESPACE( c ) || IS_CID_LINESPACE( c ) )
285 void CID_Skip_Spaces( CID_Parser* parser )
287 FT_Byte* cur = parser->cursor;
288 FT_Byte* limit = parser->limit;
291 while ( cur < limit )
296 if ( !IS_CID_SPACE( c ) )
301 parser->cursor = cur;
306 void CID_ToToken( CID_Parser* parser,
307 CID_Token_Rec* token )
311 FT_Byte starter, ender;
315 token->type = t1_token_none;
319 /* first of all, skip space */
320 CID_Skip_Spaces( parser );
322 cur = parser->cursor;
323 limit = parser->limit;
329 /************* check for strings ***********************/
331 token->type = t1_token_string;
335 /************* check for programs/array ****************/
337 token->type = t1_token_array;
341 /************* check for table/array ******************/
343 token->type = t1_token_array;
351 while ( cur < limit )
353 if ( *cur == starter )
355 else if ( *cur == ender )
360 token->limit = cur++;
368 /* **************** otherwise, it is any token **********/
370 token->start = cur++;
371 token->type = t1_token_any;
372 while ( cur < limit && !IS_CID_SPACE( *cur ) )
381 token->type = t1_token_none;
384 parser->cursor = cur;
390 void CID_ToTokenArray( CID_Parser* parser,
391 CID_Token_Rec* tokens,
393 FT_Int* pnum_tokens )
395 CID_Token_Rec master;
400 CID_ToToken( parser, &master );
402 if ( master.type == t1_token_array )
404 FT_Byte* old_cursor = parser->cursor;
405 FT_Byte* old_limit = parser->limit;
406 CID_Token_Rec* cur = tokens;
407 CID_Token_Rec* limit = cur + max_tokens;
410 parser->cursor = master.start;
411 parser->limit = master.limit;
413 while ( parser->cursor < parser->limit )
418 CID_ToToken( parser, &token );
428 *pnum_tokens = cur - tokens;
430 parser->cursor = old_cursor;
431 parser->limit = old_limit;
437 FT_Long t1_toint( FT_Byte** cursor,
441 FT_Byte* cur = *cursor;
445 for ( ; cur < limit; cur++ )
448 d = (FT_Byte)( c - '0' );
463 d = (FT_Byte)( cur[0] - '0' );
467 result = result * 10 + d;
470 } while ( cur < limit );
483 FT_Long t1_tofixed( FT_Byte** cursor,
487 FT_Byte* cur = *cursor;
488 FT_Long num, divider, result;
496 /* first of all, read the integer part */
497 result = t1_toint( &cur, limit ) << 16;
510 /* read decimal part, if any */
511 if ( *cur == '.' && cur + 1 < limit )
517 d = (FT_Byte)( *cur - '0' );
521 if ( divider < 10000000L )
533 /* read exponent, if any */
534 if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) )
537 power_ten += t1_toint( &cur, limit );
541 /* raise to power of ten if needed */
542 while ( power_ten > 0 )
544 result = result * 10;
549 while ( power_ten < 0 )
551 result = result / 10;
552 divider = divider * 10;
557 result += FT_DivFix( num, divider );
569 int t1_tobool( FT_Byte** cursor,
572 FT_Byte* cur = *cursor;
576 /* return 1 if we find a "true", 0 otherwise */
577 if ( cur + 3 < limit &&
586 else if ( cur + 4 < limit &&
602 FT_Int t1_tocoordarray( FT_Byte** cursor,
607 FT_Byte* cur = *cursor;
615 /* check for the beginning of an array. */
616 /* If not, only one number will be read */
629 /* now, read the coordinates */
630 for ( ; cur < limit; )
632 /* skip whitespace in front of data */
636 if ( c != ' ' && c != '\t' )
644 if ( count >= max_coords || c == ender )
647 coords[count] = (FT_Short)( t1_tofixed( &cur, limit, 0 ) >> 16 );
661 FT_Int t1_tofixedarray( FT_Byte** cursor,
667 FT_Byte* cur = *cursor;
675 /* check for the beginning of an array. */
676 /* If not, only one number will be read */
689 /* now, read the values */
690 for ( ; cur < limit; )
692 /* skip whitespace in front of data */
696 if ( c != ' ' && c != '\t' )
704 if ( count >= max_values || c == ender )
707 values[count] = t1_tofixed( &cur, limit, power_ten );
721 /* Loads a simple field (i.e. non-table) into the current */
722 /* list of objects */
724 FT_Error CID_Load_Field( CID_Parser* parser,
725 const CID_Field_Rec* field,
736 CID_ToToken( parser, &token );
746 FT_Byte* q = (FT_Byte*)object + field->offset;
751 switch ( field->type )
754 val = t1_tobool( &cur, limit );
758 val = t1_tofixed( &cur, limit, 0 );
761 case t1_field_integer:
762 val = t1_toint( &cur, limit );
765 switch ( field->size )
768 *(FT_Byte*)q = (FT_Byte)val;
772 *(FT_UShort*)q = (FT_UShort)val;
776 *(FT_Int32*)q = (FT_Int)val;
779 default: /* for 64-bit systems */
784 case t1_field_string:
786 FT_Memory memory = parser->memory;
787 FT_UInt len = limit-cur;
790 if ( ALLOC( string, len + 1 ) )
793 MEM_Copy( string, cur, len );
796 *(FT_String**)q = string;
801 /* an error occurred */
812 error = T1_Err_Invalid_File_Format;
817 #define T1_MAX_TABLE_ELEMENTS 32
821 FT_Error CID_Load_Field_Table( CID_Parser* parser,
822 const CID_Field_Rec* field,
825 CID_Token_Rec elements[T1_MAX_TABLE_ELEMENTS];
826 CID_Token_Rec* token;
831 CID_Field_Rec fieldrec = *(CID_Field_Rec*)field;
834 fieldrec.type = t1_field_integer;
835 if ( field->type == t1_field_fixed_array )
836 fieldrec.type = t1_field_fixed;
838 CID_ToTokenArray( parser, elements, 32, &num_elements );
839 if ( num_elements < 0 )
842 if ( num_elements > T1_MAX_TABLE_ELEMENTS )
843 num_elements = T1_MAX_TABLE_ELEMENTS;
845 old_cursor = parser->cursor;
846 old_limit = parser->limit;
848 /* we store the elements count */
849 if ( field->count_offset )
850 *(FT_Byte*)( (FT_Byte*)object + field->count_offset ) = num_elements;
852 /* we now load each element, adjusting the field.offset on each one */
854 for ( ; num_elements > 0; num_elements--, token++ )
856 parser->cursor = token->start;
857 parser->limit = token->limit;
858 CID_Load_Field( parser, &fieldrec, object );
859 fieldrec.offset += fieldrec.size;
862 parser->cursor = old_cursor;
863 parser->limit = old_limit;
869 error = T1_Err_Invalid_File_Format;
875 FT_Long CID_ToInt( CID_Parser* parser )
877 return t1_toint( &parser->cursor, parser->limit );
882 FT_Int CID_ToCoordArray( CID_Parser* parser,
886 return t1_tocoordarray( &parser->cursor, parser->limit,
887 max_coords, coords );
892 FT_Int CID_ToFixedArray( CID_Parser* parser,
897 return t1_tofixedarray( &parser->cursor, parser->limit,
898 max_values, values, power_ten );
904 /* return the value of an hexadecimal digit */
906 int hexa_value( char c )
911 d = (unsigned int)( c - '0' );
915 d = (unsigned int)( c - 'a' );
917 return (int)( d + 10 );
919 d = (unsigned int)( c - 'A' );
921 return (int)( d + 10 );
930 FT_Error CID_New_Parser( CID_Parser* parser,
935 FT_ULong base_offset, offset, ps_len;
936 FT_Byte buffer[256 + 10];
940 MEM_Set( parser, 0, sizeof ( *parser ) );
941 parser->stream = stream;
942 parser->memory = memory;
944 base_offset = FILE_Pos();
946 /* first of all, check the font format in the header */
947 if ( ACCESS_Frame( 31 ) )
950 if ( strncmp( (char *)stream->cursor,
951 "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) )
953 FT_TRACE2(( "[not a valid CID-keyed font]\n" ));
954 error = FT_Err_Unknown_File_Format;
961 /* now, read the rest of the file, until we find a `StartData' */
965 FT_Byte *p, *limit = buffer + 256;
967 /* fill input buffer */
970 MEM_Move( buffer, limit, buff_len );
972 if ( FILE_Read( buffer, 256 + 10 - buff_len ) )
977 /* look for `StartData' */
978 for ( p = buffer; p < limit; p++ )
980 if ( p[0] == 'S' && strncmp( (char*)p, "StartData", 9 ) == 0 )
982 /* save offset of binary data after `StartData' */
983 offset = FILE_Pos() - ( limit - p ) + 10;
990 /* we have found the start of the binary data. We will now */
991 /* rewind and extract the frame of corresponding to the Postscript */
994 ps_len = offset - base_offset;
995 if ( FILE_Seek( base_offset ) ||
996 EXTRACT_Frame( ps_len, parser->postscript ) )
999 parser->data_offset = offset;
1000 parser->postscript_len = ps_len;
1001 parser->cursor = parser->postscript;
1002 parser->limit = parser->cursor + ps_len;
1003 parser->num_dict = -1;
1011 void CID_Done_Parser( CID_Parser* parser )
1013 /* always free the private dictionary */
1014 if ( parser->postscript )
1016 FT_Stream stream = parser->stream;
1019 RELEASE_Frame( parser->postscript );