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 <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
);