1 /***************************************************************************/
5 /* Auxiliary functions for PostScript fonts (body). */
7 /* Copyright 1996-2018 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 /***************************************************************************/
20 #include FT_INTERNAL_POSTSCRIPT_AUX_H
21 #include FT_INTERNAL_DEBUG_H
22 #include FT_INTERNAL_CALC_H
32 /*************************************************************************/
34 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
35 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
36 /* messages during execution. */
39 #define FT_COMPONENT trace_psobjs
42 /*************************************************************************/
43 /*************************************************************************/
45 /***** PS_TABLE *****/
47 /*************************************************************************/
48 /*************************************************************************/
50 /*************************************************************************/
56 /* Initializes a PS_Table. */
59 /* table :: The address of the target table. */
62 /* count :: The table size = the maximum number of elements. */
64 /* memory :: The memory object to use for all subsequent */
68 /* FreeType error code. 0 means success. */
70 FT_LOCAL_DEF( FT_Error
)
71 ps_table_new( PS_Table table
,
78 table
->memory
= memory
;
79 if ( FT_NEW_ARRAY( table
->elements
, count
) ||
80 FT_NEW_ARRAY( table
->lengths
, count
) )
83 table
->max_elems
= count
;
84 table
->init
= 0xDEADBEEFUL
;
90 *(PS_Table_FuncsRec
*)&table
->funcs
= ps_table_funcs
;
94 FT_FREE( table
->elements
);
101 shift_elements( PS_Table table
,
104 FT_PtrDist delta
= table
->block
- old_base
;
105 FT_Byte
** offset
= table
->elements
;
106 FT_Byte
** limit
= offset
+ table
->max_elems
;
109 for ( ; offset
< limit
; offset
++ )
118 reallocate_t1_table( PS_Table table
,
121 FT_Memory memory
= table
->memory
;
122 FT_Byte
* old_base
= table
->block
;
126 /* allocate new base block */
127 if ( FT_ALLOC( table
->block
, new_size
) )
129 table
->block
= old_base
;
133 /* copy elements and shift offsets */
136 FT_MEM_COPY( table
->block
, old_base
, table
->capacity
);
137 shift_elements( table
, old_base
);
141 table
->capacity
= new_size
;
147 /*************************************************************************/
153 /* Adds an object to a PS_Table, possibly growing its memory block. */
156 /* table :: The target table. */
159 /* idx :: The index of the object in the table. */
161 /* object :: The address of the object to copy in memory. */
163 /* length :: The length in bytes of the source object. */
166 /* FreeType error code. 0 means success. An error is returned if a */
167 /* reallocation fails. */
169 FT_LOCAL_DEF( FT_Error
)
170 ps_table_add( PS_Table table
,
175 if ( idx
< 0 || idx
>= table
->max_elems
)
177 FT_ERROR(( "ps_table_add: invalid index\n" ));
178 return FT_THROW( Invalid_Argument
);
181 /* grow the base block if needed */
182 if ( table
->cursor
+ length
> table
->capacity
)
185 FT_Offset new_size
= table
->capacity
;
186 FT_PtrDist in_offset
;
189 in_offset
= (FT_Byte
*)object
- table
->block
;
190 if ( in_offset
< 0 || (FT_Offset
)in_offset
>= table
->capacity
)
193 while ( new_size
< table
->cursor
+ length
)
195 /* increase size by 25% and round up to the nearest multiple
197 new_size
+= ( new_size
>> 2 ) + 1;
198 new_size
= FT_PAD_CEIL( new_size
, 1024 );
201 error
= reallocate_t1_table( table
, new_size
);
205 if ( in_offset
>= 0 )
206 object
= table
->block
+ in_offset
;
209 /* add the object to the base block and adjust offset */
210 table
->elements
[idx
] = table
->block
+ table
->cursor
;
211 table
->lengths
[idx
] = length
;
212 FT_MEM_COPY( table
->block
+ table
->cursor
, object
, length
);
214 table
->cursor
+= length
;
219 /*************************************************************************/
225 /* Finalizes a PS_TableRec (i.e., reallocate it to its current */
229 /* table :: The target table. */
232 /* This function does NOT release the heap's memory block. It is up */
233 /* to the caller to clean it, or reference it in its own structures. */
236 ps_table_done( PS_Table table
)
238 FT_Memory memory
= table
->memory
;
240 FT_Byte
* old_base
= table
->block
;
243 /* should never fail, because rec.cursor <= rec.size */
247 if ( FT_ALLOC( table
->block
, table
->cursor
) )
249 FT_MEM_COPY( table
->block
, old_base
, table
->cursor
);
250 shift_elements( table
, old_base
);
252 table
->capacity
= table
->cursor
;
260 ps_table_release( PS_Table table
)
262 FT_Memory memory
= table
->memory
;
265 if ( (FT_ULong
)table
->init
== 0xDEADBEEFUL
)
267 FT_FREE( table
->block
);
268 FT_FREE( table
->elements
);
269 FT_FREE( table
->lengths
);
275 /*************************************************************************/
276 /*************************************************************************/
278 /***** T1 PARSER *****/
280 /*************************************************************************/
281 /*************************************************************************/
284 /* first character must be already part of the comment */
287 skip_comment( FT_Byte
* *acur
,
290 FT_Byte
* cur
= *acur
;
293 while ( cur
< limit
)
295 if ( IS_PS_NEWLINE( *cur
) )
305 skip_spaces( FT_Byte
* *acur
,
308 FT_Byte
* cur
= *acur
;
311 while ( cur
< limit
)
313 if ( !IS_PS_SPACE( *cur
) )
316 /* According to the PLRM, a comment is equal to a space. */
317 skip_comment( &cur
, limit
);
328 #define IS_OCTAL_DIGIT( c ) ( '0' <= (c) && (c) <= '7' )
331 /* first character must be `('; */
332 /* *acur is positioned at the character after the closing `)' */
335 skip_literal_string( FT_Byte
* *acur
,
338 FT_Byte
* cur
= *acur
;
340 FT_Error error
= FT_ERR( Invalid_File_Format
);
344 while ( cur
< limit
)
353 /* Red Book 3rd ed., section `Literal Text Strings', p. 29: */
354 /* A backslash can introduce three different types */
355 /* of escape sequences: */
356 /* - a special escaped char like \r, \n, etc. */
357 /* - a one-, two-, or three-digit octal number */
358 /* - none of the above in which case the backslash is ignored */
361 /* error (or to be ignored?) */
366 /* skip `special' escape */
379 /* skip octal escape or ignore backslash */
380 for ( i
= 0; i
< 3 && cur
< limit
; i
++ )
382 if ( !IS_OCTAL_DIGIT( *cur
) )
408 /* first character must be `<' */
411 skip_string( FT_Byte
* *acur
,
414 FT_Byte
* cur
= *acur
;
415 FT_Error err
= FT_Err_Ok
;
418 while ( ++cur
< limit
)
420 /* All whitespace characters are ignored. */
421 skip_spaces( &cur
, limit
);
425 if ( !IS_PS_XDIGIT( *cur
) )
429 if ( cur
< limit
&& *cur
!= '>' )
431 FT_ERROR(( "skip_string: missing closing delimiter `>'\n" ));
432 err
= FT_THROW( Invalid_File_Format
);
442 /* first character must be the opening brace that */
443 /* starts the procedure */
445 /* NB: [ and ] need not match: */
446 /* `/foo {[} def' is a valid PostScript fragment, */
447 /* even within a Type1 font */
450 skip_procedure( FT_Byte
* *acur
,
455 FT_Error error
= FT_Err_Ok
;
458 FT_ASSERT( **acur
== '{' );
460 for ( cur
= *acur
; cur
< limit
&& error
== FT_Err_Ok
; cur
++ )
478 error
= skip_literal_string( &cur
, limit
);
482 error
= skip_string( &cur
, limit
);
486 skip_comment( &cur
, limit
);
493 error
= FT_THROW( Invalid_File_Format
);
501 /***********************************************************************/
503 /* All exported parsing routines handle leading whitespace and stop at */
504 /* the first character which isn't part of the just handled token. */
506 /***********************************************************************/
510 ps_parser_skip_PS_token( PS_Parser parser
)
512 /* Note: PostScript allows any non-delimiting, non-whitespace */
513 /* character in a name (PS Ref Manual, 3rd ed, p31). */
514 /* PostScript delimiters are (, ), <, >, [, ], {, }, /, and %. */
516 FT_Byte
* cur
= parser
->cursor
;
517 FT_Byte
* limit
= parser
->limit
;
518 FT_Error error
= FT_Err_Ok
;
521 skip_spaces( &cur
, limit
); /* this also skips comments */
525 /* self-delimiting, single-character tokens */
526 if ( *cur
== '[' || *cur
== ']' )
532 /* skip balanced expressions (procedures and strings) */
534 if ( *cur
== '{' ) /* {...} */
536 error
= skip_procedure( &cur
, limit
);
540 if ( *cur
== '(' ) /* (...) */
542 error
= skip_literal_string( &cur
, limit
);
546 if ( *cur
== '<' ) /* <...> */
548 if ( cur
+ 1 < limit
&& *(cur
+ 1) == '<' ) /* << */
554 error
= skip_string( &cur
, limit
);
562 if ( cur
>= limit
|| *cur
!= '>' ) /* >> */
564 FT_ERROR(( "ps_parser_skip_PS_token:"
565 " unexpected closing delimiter `>'\n" ));
566 error
= FT_THROW( Invalid_File_Format
);
577 while ( cur
< limit
)
579 /* *cur might be invalid (e.g., ')' or '}'), but this */
580 /* is handled by the test `cur == parser->cursor' below */
581 if ( IS_PS_DELIM( *cur
) )
588 if ( cur
< limit
&& cur
== parser
->cursor
)
590 FT_ERROR(( "ps_parser_skip_PS_token:"
591 " current token is `%c' which is self-delimiting\n"
593 " but invalid at this point\n",
596 error
= FT_THROW( Invalid_File_Format
);
602 parser
->error
= error
;
603 parser
->cursor
= cur
;
608 ps_parser_skip_spaces( PS_Parser parser
)
610 skip_spaces( &parser
->cursor
, parser
->limit
);
614 /* `token' here means either something between balanced delimiters */
615 /* or the next token; the delimiters are not removed. */
618 ps_parser_to_token( PS_Parser parser
,
626 token
->type
= T1_TOKEN_TYPE_NONE
;
630 /* first of all, skip leading whitespace */
631 ps_parser_skip_spaces( parser
);
633 cur
= parser
->cursor
;
634 limit
= parser
->limit
;
641 /************* check for literal string *****************/
643 token
->type
= T1_TOKEN_TYPE_STRING
;
646 if ( skip_literal_string( &cur
, limit
) == FT_Err_Ok
)
650 /************* check for programs/array *****************/
652 token
->type
= T1_TOKEN_TYPE_ARRAY
;
655 if ( skip_procedure( &cur
, limit
) == FT_Err_Ok
)
659 /************* check for table/array ********************/
660 /* XXX: in theory we should also look for "<<" */
661 /* since this is semantically equivalent to "["; */
662 /* in practice it doesn't matter (?) */
664 token
->type
= T1_TOKEN_TYPE_ARRAY
;
666 token
->start
= cur
++;
668 /* we need this to catch `[ ]' */
669 parser
->cursor
= cur
;
670 ps_parser_skip_spaces( parser
);
671 cur
= parser
->cursor
;
673 while ( cur
< limit
&& !parser
->error
)
675 /* XXX: this is wrong because it does not */
676 /* skip comments, procedures, and strings */
679 else if ( *cur
== ']' )
684 token
->limit
= ++cur
;
689 parser
->cursor
= cur
;
690 ps_parser_skip_PS_token( parser
);
691 /* we need this to catch `[XXX ]' */
692 ps_parser_skip_spaces ( parser
);
693 cur
= parser
->cursor
;
697 /* ************ otherwise, it is any token **************/
700 token
->type
= ( *cur
== '/' ) ? T1_TOKEN_TYPE_KEY
: T1_TOKEN_TYPE_ANY
;
701 ps_parser_skip_PS_token( parser
);
702 cur
= parser
->cursor
;
703 if ( !parser
->error
)
710 token
->type
= T1_TOKEN_TYPE_NONE
;
713 parser
->cursor
= cur
;
717 /* NB: `tokens' can be NULL if we only want to count */
718 /* the number of array elements */
721 ps_parser_to_token_array( PS_Parser parser
,
724 FT_Int
* pnum_tokens
)
731 /* this also handles leading whitespace */
732 ps_parser_to_token( parser
, &master
);
734 if ( master
.type
== T1_TOKEN_TYPE_ARRAY
)
736 FT_Byte
* old_cursor
= parser
->cursor
;
737 FT_Byte
* old_limit
= parser
->limit
;
738 T1_Token cur
= tokens
;
739 T1_Token limit
= cur
+ max_tokens
;
742 /* don't include outermost delimiters */
743 parser
->cursor
= master
.start
+ 1;
744 parser
->limit
= master
.limit
- 1;
746 while ( parser
->cursor
< parser
->limit
)
751 ps_parser_to_token( parser
, &token
);
755 if ( tokens
&& cur
< limit
)
761 *pnum_tokens
= (FT_Int
)( cur
- tokens
);
763 parser
->cursor
= old_cursor
;
764 parser
->limit
= old_limit
;
769 /* first character must be a delimiter or a part of a number */
770 /* NB: `coords' can be NULL if we just want to skip the */
771 /* array; in this case we ignore `max_coords' */
774 ps_tocoordarray( FT_Byte
* *acur
,
779 FT_Byte
* cur
= *acur
;
787 /* check for the beginning of an array; otherwise, only one number */
800 /* now, read the coordinates */
801 while ( cur
< limit
)
807 /* skip whitespace in front of data */
808 skip_spaces( &cur
, limit
);
820 if ( coords
&& count
>= max_coords
)
823 /* call PS_Conv_ToFixed() even if coords == NULL */
824 /* to properly parse number at `cur' */
825 *( coords
? &coords
[count
] : &dummy
) =
826 (FT_Short
)( PS_Conv_ToFixed( &cur
, limit
, 0 ) >> 16 );
828 if ( old_cur
== cur
)
846 /* first character must be a delimiter or a part of a number */
847 /* NB: `values' can be NULL if we just want to skip the */
848 /* array; in this case we ignore `max_values' */
850 /* return number of successfully parsed values */
853 ps_tofixedarray( FT_Byte
* *acur
,
859 FT_Byte
* cur
= *acur
;
867 /* Check for the beginning of an array. Otherwise, only one number */
880 /* now, read the values */
881 while ( cur
< limit
)
887 /* skip whitespace in front of data */
888 skip_spaces( &cur
, limit
);
900 if ( values
&& count
>= max_values
)
903 /* call PS_Conv_ToFixed() even if coords == NULL */
904 /* to properly parse number at `cur' */
905 *( values
? &values
[count
] : &dummy
) =
906 PS_Conv_ToFixed( &cur
, limit
, power_ten
);
908 if ( old_cur
== cur
)
929 ps_tostring( FT_Byte
** cursor
,
933 FT_Byte
* cur
= *cursor
;
940 /* XXX: some stupid fonts have a `Notice' or `Copyright' string */
941 /* that simply doesn't begin with an opening parenthesis, even */
942 /* though they have a closing one! E.g. "amuncial.pfb" */
944 /* We must deal with these ill-fated cases there. Note that */
945 /* these fonts didn't work with the old Type 1 driver as the */
946 /* notice/copyright was not recognized as a valid string token */
947 /* and made the old token parser commit errors. */
949 while ( cur
< limit
&& ( *cur
== ' ' || *cur
== '\t' ) )
951 if ( cur
+ 1 >= limit
)
955 cur
++; /* skip the opening parenthesis, if there is one */
960 /* then, count its length */
961 for ( ; cur
< limit
; cur
++ )
966 else if ( *cur
== ')' )
974 len
= (FT_UInt
)( cur
- *cursor
);
975 if ( cur
>= limit
|| FT_ALLOC( result
, len
+ 1 ) )
978 /* now copy the string */
979 FT_MEM_COPY( result
, *cursor
, len
);
989 ps_tobool( FT_Byte
* *acur
,
992 FT_Byte
* cur
= *acur
;
996 /* return 1 if we find `true', 0 otherwise */
997 if ( cur
+ 3 < limit
&&
1006 else if ( cur
+ 4 < limit
&&
1022 /* load a simple field (i.e. non-table) into the current list of objects */
1024 FT_LOCAL_DEF( FT_Error
)
1025 ps_parser_load_field( PS_Parser parser
,
1026 const T1_Field field
,
1028 FT_UInt max_objects
,
1040 /* this also skips leading whitespace */
1041 ps_parser_to_token( parser
, &token
);
1048 limit
= token
.limit
;
1052 /* we must detect arrays in /FontBBox */
1053 if ( type
== T1_FIELD_TYPE_BBOX
)
1056 FT_Byte
* old_cur
= parser
->cursor
;
1057 FT_Byte
* old_limit
= parser
->limit
;
1060 /* don't include delimiters */
1061 parser
->cursor
= token
.start
+ 1;
1062 parser
->limit
= token
.limit
- 1;
1064 ps_parser_to_token( parser
, &token2
);
1065 parser
->cursor
= old_cur
;
1066 parser
->limit
= old_limit
;
1068 if ( token2
.type
== T1_TOKEN_TYPE_ARRAY
)
1070 type
= T1_FIELD_TYPE_MM_BBOX
;
1074 else if ( token
.type
== T1_TOKEN_TYPE_ARRAY
)
1076 count
= max_objects
;
1079 /* if this is an array and we have no blend, an error occurs */
1080 if ( max_objects
== 0 )
1085 /* don't include delimiters */
1090 for ( ; count
> 0; count
--, idx
++ )
1092 FT_Byte
* q
= (FT_Byte
*)objects
[idx
] + field
->offset
;
1094 FT_String
* string
= NULL
;
1097 skip_spaces( &cur
, limit
);
1101 case T1_FIELD_TYPE_BOOL
:
1102 val
= ps_tobool( &cur
, limit
);
1105 case T1_FIELD_TYPE_FIXED
:
1106 val
= PS_Conv_ToFixed( &cur
, limit
, 0 );
1109 case T1_FIELD_TYPE_FIXED_1000
:
1110 val
= PS_Conv_ToFixed( &cur
, limit
, 3 );
1113 case T1_FIELD_TYPE_INTEGER
:
1114 val
= PS_Conv_ToInt( &cur
, limit
);
1118 switch ( field
->size
)
1120 case (8 / FT_CHAR_BIT
):
1121 *(FT_Byte
*)q
= (FT_Byte
)val
;
1124 case (16 / FT_CHAR_BIT
):
1125 *(FT_UShort
*)q
= (FT_UShort
)val
;
1128 case (32 / FT_CHAR_BIT
):
1129 *(FT_UInt32
*)q
= (FT_UInt32
)val
;
1132 default: /* for 64-bit systems */
1137 case T1_FIELD_TYPE_STRING
:
1138 case T1_FIELD_TYPE_KEY
:
1140 FT_Memory memory
= parser
->memory
;
1141 FT_UInt len
= (FT_UInt
)( limit
- cur
);
1147 /* we allow both a string or a name */
1148 /* for cases like /FontName (foo) def */
1149 if ( token
.type
== T1_TOKEN_TYPE_KEY
)
1151 /* don't include leading `/' */
1155 else if ( token
.type
== T1_TOKEN_TYPE_STRING
)
1157 /* don't include delimiting parentheses */
1158 /* XXX we don't handle <<...>> here */
1159 /* XXX should we convert octal escapes? */
1160 /* if so, what encoding should we use? */
1166 FT_ERROR(( "ps_parser_load_field:"
1167 " expected a name or string\n"
1169 " but found token of type %d instead\n",
1171 error
= FT_THROW( Invalid_File_Format
);
1175 /* for this to work (FT_String**)q must have been */
1176 /* initialized to NULL */
1177 if ( *(FT_String
**)q
)
1179 FT_TRACE0(( "ps_parser_load_field: overwriting field %s\n",
1181 FT_FREE( *(FT_String
**)q
);
1182 *(FT_String
**)q
= NULL
;
1185 if ( FT_ALLOC( string
, len
+ 1 ) )
1188 FT_MEM_COPY( string
, cur
, len
);
1191 *(FT_String
**)q
= string
;
1195 case T1_FIELD_TYPE_BBOX
:
1198 FT_BBox
* bbox
= (FT_BBox
*)q
;
1202 result
= ps_tofixedarray( &cur
, limit
, 4, temp
, 0 );
1206 FT_ERROR(( "ps_parser_load_field:"
1207 " expected four integers in bounding box\n" ));
1208 error
= FT_THROW( Invalid_File_Format
);
1212 bbox
->xMin
= FT_RoundFix( temp
[0] );
1213 bbox
->yMin
= FT_RoundFix( temp
[1] );
1214 bbox
->xMax
= FT_RoundFix( temp
[2] );
1215 bbox
->yMax
= FT_RoundFix( temp
[3] );
1219 case T1_FIELD_TYPE_MM_BBOX
:
1221 FT_Memory memory
= parser
->memory
;
1222 FT_Fixed
* temp
= NULL
;
1227 if ( FT_NEW_ARRAY( temp
, max_objects
* 4 ) )
1230 for ( i
= 0; i
< 4; i
++ )
1232 result
= ps_tofixedarray( &cur
, limit
, (FT_Int
)max_objects
,
1233 temp
+ i
* max_objects
, 0 );
1234 if ( result
< 0 || (FT_UInt
)result
< max_objects
)
1236 FT_ERROR(( "ps_parser_load_field:"
1237 " expected %d integer%s in the %s subarray\n"
1239 " of /FontBBox in the /Blend dictionary\n",
1240 max_objects
, max_objects
> 1 ? "s" : "",
1242 : ( i
== 1 ? "second"
1243 : ( i
== 2 ? "third"
1245 error
= FT_THROW( Invalid_File_Format
);
1251 skip_spaces( &cur
, limit
);
1254 for ( i
= 0; i
< max_objects
; i
++ )
1256 FT_BBox
* bbox
= (FT_BBox
*)objects
[i
];
1259 bbox
->xMin
= FT_RoundFix( temp
[i
] );
1260 bbox
->yMin
= FT_RoundFix( temp
[i
+ max_objects
] );
1261 bbox
->xMax
= FT_RoundFix( temp
[i
+ 2 * max_objects
] );
1262 bbox
->yMax
= FT_RoundFix( temp
[i
+ 3 * max_objects
] );
1270 /* an error occurred */
1275 #if 0 /* obsolete -- keep for reference */
1277 *pflags
|= 1L << field
->flag_bit
;
1279 FT_UNUSED( pflags
);
1288 error
= FT_THROW( Invalid_File_Format
);
1293 #define T1_MAX_TABLE_ELEMENTS 32
1296 FT_LOCAL_DEF( FT_Error
)
1297 ps_parser_load_field_table( PS_Parser parser
,
1298 const T1_Field field
,
1300 FT_UInt max_objects
,
1303 T1_TokenRec elements
[T1_MAX_TABLE_ELEMENTS
];
1305 FT_Int num_elements
;
1306 FT_Error error
= FT_Err_Ok
;
1307 FT_Byte
* old_cursor
;
1309 T1_FieldRec fieldrec
= *(T1_Field
)field
;
1312 fieldrec
.type
= T1_FIELD_TYPE_INTEGER
;
1313 if ( field
->type
== T1_FIELD_TYPE_FIXED_ARRAY
||
1314 field
->type
== T1_FIELD_TYPE_BBOX
)
1315 fieldrec
.type
= T1_FIELD_TYPE_FIXED
;
1317 ps_parser_to_token_array( parser
, elements
,
1318 T1_MAX_TABLE_ELEMENTS
, &num_elements
);
1319 if ( num_elements
< 0 )
1321 error
= FT_ERR( Ignore
);
1324 if ( (FT_UInt
)num_elements
> field
->array_max
)
1325 num_elements
= (FT_Int
)field
->array_max
;
1327 old_cursor
= parser
->cursor
;
1328 old_limit
= parser
->limit
;
1330 /* we store the elements count if necessary; */
1331 /* we further assume that `count_offset' can't be zero */
1332 if ( field
->type
!= T1_FIELD_TYPE_BBOX
&& field
->count_offset
!= 0 )
1333 *(FT_Byte
*)( (FT_Byte
*)objects
[0] + field
->count_offset
) =
1334 (FT_Byte
)num_elements
;
1336 /* we now load each element, adjusting the field.offset on each one */
1338 for ( ; num_elements
> 0; num_elements
--, token
++ )
1340 parser
->cursor
= token
->start
;
1341 parser
->limit
= token
->limit
;
1343 error
= ps_parser_load_field( parser
,
1351 fieldrec
.offset
+= fieldrec
.size
;
1354 #if 0 /* obsolete -- keep for reference */
1356 *pflags
|= 1L << field
->flag_bit
;
1358 FT_UNUSED( pflags
);
1361 parser
->cursor
= old_cursor
;
1362 parser
->limit
= old_limit
;
1369 FT_LOCAL_DEF( FT_Long
)
1370 ps_parser_to_int( PS_Parser parser
)
1372 ps_parser_skip_spaces( parser
);
1373 return PS_Conv_ToInt( &parser
->cursor
, parser
->limit
);
1377 /* first character must be `<' if `delimiters' is non-zero */
1379 FT_LOCAL_DEF( FT_Error
)
1380 ps_parser_to_bytes( PS_Parser parser
,
1382 FT_Offset max_bytes
,
1383 FT_ULong
* pnum_bytes
,
1384 FT_Bool delimiters
)
1386 FT_Error error
= FT_Err_Ok
;
1390 ps_parser_skip_spaces( parser
);
1391 cur
= parser
->cursor
;
1393 if ( cur
>= parser
->limit
)
1400 FT_ERROR(( "ps_parser_to_bytes: Missing starting delimiter `<'\n" ));
1401 error
= FT_THROW( Invalid_File_Format
);
1408 *pnum_bytes
= PS_Conv_ASCIIHexDecode( &cur
,
1415 if ( cur
< parser
->limit
&& *cur
!= '>' )
1417 FT_ERROR(( "ps_parser_to_bytes: Missing closing delimiter `>'\n" ));
1418 error
= FT_THROW( Invalid_File_Format
);
1425 parser
->cursor
= cur
;
1432 FT_LOCAL_DEF( FT_Fixed
)
1433 ps_parser_to_fixed( PS_Parser parser
,
1436 ps_parser_skip_spaces( parser
);
1437 return PS_Conv_ToFixed( &parser
->cursor
, parser
->limit
, power_ten
);
1441 FT_LOCAL_DEF( FT_Int
)
1442 ps_parser_to_coord_array( PS_Parser parser
,
1446 ps_parser_skip_spaces( parser
);
1447 return ps_tocoordarray( &parser
->cursor
, parser
->limit
,
1448 max_coords
, coords
);
1452 FT_LOCAL_DEF( FT_Int
)
1453 ps_parser_to_fixed_array( PS_Parser parser
,
1458 ps_parser_skip_spaces( parser
);
1459 return ps_tofixedarray( &parser
->cursor
, parser
->limit
,
1460 max_values
, values
, power_ten
);
1466 FT_LOCAL_DEF( FT_String
* )
1467 T1_ToString( PS_Parser parser
)
1469 return ps_tostring( &parser
->cursor
, parser
->limit
, parser
->memory
);
1473 FT_LOCAL_DEF( FT_Bool
)
1474 T1_ToBool( PS_Parser parser
)
1476 return ps_tobool( &parser
->cursor
, parser
->limit
);
1482 FT_LOCAL_DEF( void )
1483 ps_parser_init( PS_Parser parser
,
1488 parser
->error
= FT_Err_Ok
;
1489 parser
->base
= base
;
1490 parser
->limit
= limit
;
1491 parser
->cursor
= base
;
1492 parser
->memory
= memory
;
1493 parser
->funcs
= ps_parser_funcs
;
1497 FT_LOCAL_DEF( void )
1498 ps_parser_done( PS_Parser parser
)
1500 FT_UNUSED( parser
);
1504 /*************************************************************************/
1505 /*************************************************************************/
1507 /***** T1 BUILDER *****/
1509 /*************************************************************************/
1510 /*************************************************************************/
1512 /*************************************************************************/
1515 /* t1_builder_init */
1518 /* Initializes a given glyph builder. */
1521 /* builder :: A pointer to the glyph builder to initialize. */
1524 /* face :: The current face object. */
1526 /* size :: The current size object. */
1528 /* glyph :: The current glyph object. */
1530 /* hinting :: Whether hinting should be applied. */
1532 FT_LOCAL_DEF( void )
1533 t1_builder_init( T1_Builder builder
,
1539 builder
->parse_state
= T1_Parse_Start
;
1540 builder
->load_points
= 1;
1542 builder
->face
= face
;
1543 builder
->glyph
= glyph
;
1544 builder
->memory
= face
->memory
;
1548 FT_GlyphLoader loader
= glyph
->internal
->loader
;
1551 builder
->loader
= loader
;
1552 builder
->base
= &loader
->base
.outline
;
1553 builder
->current
= &loader
->current
.outline
;
1554 FT_GlyphLoader_Rewind( loader
);
1556 builder
->hints_globals
= size
->internal
->module_data
;
1557 builder
->hints_funcs
= NULL
;
1560 builder
->hints_funcs
= glyph
->internal
->glyph_hints
;
1566 builder
->left_bearing
.x
= 0;
1567 builder
->left_bearing
.y
= 0;
1568 builder
->advance
.x
= 0;
1569 builder
->advance
.y
= 0;
1571 builder
->funcs
= t1_builder_funcs
;
1575 /*************************************************************************/
1578 /* t1_builder_done */
1581 /* Finalizes a given glyph builder. Its contents can still be used */
1582 /* after the call, but the function saves important information */
1583 /* within the corresponding glyph slot. */
1586 /* builder :: A pointer to the glyph builder to finalize. */
1588 FT_LOCAL_DEF( void )
1589 t1_builder_done( T1_Builder builder
)
1591 FT_GlyphSlot glyph
= builder
->glyph
;
1595 glyph
->outline
= *builder
->base
;
1599 /* check that there is enough space for `count' more points */
1600 FT_LOCAL_DEF( FT_Error
)
1601 t1_builder_check_points( T1_Builder builder
,
1604 return FT_GLYPHLOADER_CHECK_POINTS( builder
->loader
, count
, 0 );
1608 /* add a new point, do not check space */
1609 FT_LOCAL_DEF( void )
1610 t1_builder_add_point( T1_Builder builder
,
1615 FT_Outline
* outline
= builder
->current
;
1618 if ( builder
->load_points
)
1620 FT_Vector
* point
= outline
->points
+ outline
->n_points
;
1621 FT_Byte
* control
= (FT_Byte
*)outline
->tags
+ outline
->n_points
;
1624 point
->x
= FIXED_TO_INT( x
);
1625 point
->y
= FIXED_TO_INT( y
);
1626 *control
= (FT_Byte
)( flag
? FT_CURVE_TAG_ON
: FT_CURVE_TAG_CUBIC
);
1628 outline
->n_points
++;
1632 /* check space for a new on-curve point, then add it */
1633 FT_LOCAL_DEF( FT_Error
)
1634 t1_builder_add_point1( T1_Builder builder
,
1641 error
= t1_builder_check_points( builder
, 1 );
1643 t1_builder_add_point( builder
, x
, y
, 1 );
1649 /* check space for a new contour, then add it */
1650 FT_LOCAL_DEF( FT_Error
)
1651 t1_builder_add_contour( T1_Builder builder
)
1653 FT_Outline
* outline
= builder
->current
;
1657 /* this might happen in invalid fonts */
1660 FT_ERROR(( "t1_builder_add_contour: no outline to add points to\n" ));
1661 return FT_THROW( Invalid_File_Format
);
1664 if ( !builder
->load_points
)
1666 outline
->n_contours
++;
1670 error
= FT_GLYPHLOADER_CHECK_POINTS( builder
->loader
, 0, 1 );
1673 if ( outline
->n_contours
> 0 )
1674 outline
->contours
[outline
->n_contours
- 1] =
1675 (short)( outline
->n_points
- 1 );
1677 outline
->n_contours
++;
1684 /* if a path was begun, add its first on-curve point */
1685 FT_LOCAL_DEF( FT_Error
)
1686 t1_builder_start_point( T1_Builder builder
,
1690 FT_Error error
= FT_ERR( Invalid_File_Format
);
1693 /* test whether we are building a new contour */
1695 if ( builder
->parse_state
== T1_Parse_Have_Path
)
1699 builder
->parse_state
= T1_Parse_Have_Path
;
1700 error
= t1_builder_add_contour( builder
);
1702 error
= t1_builder_add_point1( builder
, x
, y
);
1709 /* close the current contour */
1710 FT_LOCAL_DEF( void )
1711 t1_builder_close_contour( T1_Builder builder
)
1713 FT_Outline
* outline
= builder
->current
;
1720 first
= outline
->n_contours
<= 1
1721 ? 0 : outline
->contours
[outline
->n_contours
- 2] + 1;
1723 /* in malformed fonts it can happen that a contour was started */
1724 /* but no points were added */
1725 if ( outline
->n_contours
&& first
== outline
->n_points
)
1727 outline
->n_contours
--;
1731 /* We must not include the last point in the path if it */
1732 /* is located on the first point. */
1733 if ( outline
->n_points
> 1 )
1735 FT_Vector
* p1
= outline
->points
+ first
;
1736 FT_Vector
* p2
= outline
->points
+ outline
->n_points
- 1;
1737 FT_Byte
* control
= (FT_Byte
*)outline
->tags
+ outline
->n_points
- 1;
1740 /* `delete' last point only if it coincides with the first */
1741 /* point and it is not a control point (which can happen). */
1742 if ( p1
->x
== p2
->x
&& p1
->y
== p2
->y
)
1743 if ( *control
== FT_CURVE_TAG_ON
)
1744 outline
->n_points
--;
1747 if ( outline
->n_contours
> 0 )
1749 /* Don't add contours only consisting of one point, i.e., */
1750 /* check whether the first and the last point is the same. */
1751 if ( first
== outline
->n_points
- 1 )
1753 outline
->n_contours
--;
1754 outline
->n_points
--;
1757 outline
->contours
[outline
->n_contours
- 1] =
1758 (short)( outline
->n_points
- 1 );
1763 /*************************************************************************/
1764 /*************************************************************************/
1766 /***** CFF BUILDER *****/
1768 /*************************************************************************/
1769 /*************************************************************************/
1772 /*************************************************************************/
1775 /* cff_builder_init */
1778 /* Initializes a given glyph builder. */
1781 /* builder :: A pointer to the glyph builder to initialize. */
1784 /* face :: The current face object. */
1786 /* size :: The current size object. */
1788 /* glyph :: The current glyph object. */
1790 /* hinting :: Whether hinting is active. */
1792 FT_LOCAL_DEF( void )
1793 cff_builder_init( CFF_Builder
* builder
,
1796 CFF_GlyphSlot glyph
,
1799 builder
->path_begun
= 0;
1800 builder
->load_points
= 1;
1802 builder
->face
= face
;
1803 builder
->glyph
= glyph
;
1804 builder
->memory
= face
->root
.memory
;
1808 FT_GlyphLoader loader
= glyph
->root
.internal
->loader
;
1811 builder
->loader
= loader
;
1812 builder
->base
= &loader
->base
.outline
;
1813 builder
->current
= &loader
->current
.outline
;
1814 FT_GlyphLoader_Rewind( loader
);
1816 builder
->hints_globals
= NULL
;
1817 builder
->hints_funcs
= NULL
;
1819 if ( hinting
&& size
)
1821 FT_Size ftsize
= FT_SIZE( size
);
1822 CFF_Internal internal
= (CFF_Internal
)ftsize
->internal
->module_data
;
1826 builder
->hints_globals
= (void *)internal
->topfont
;
1827 builder
->hints_funcs
= glyph
->root
.internal
->glyph_hints
;
1835 builder
->left_bearing
.x
= 0;
1836 builder
->left_bearing
.y
= 0;
1837 builder
->advance
.x
= 0;
1838 builder
->advance
.y
= 0;
1840 builder
->funcs
= cff_builder_funcs
;
1844 /*************************************************************************/
1847 /* cff_builder_done */
1850 /* Finalizes a given glyph builder. Its contents can still be used */
1851 /* after the call, but the function saves important information */
1852 /* within the corresponding glyph slot. */
1855 /* builder :: A pointer to the glyph builder to finalize. */
1857 FT_LOCAL_DEF( void )
1858 cff_builder_done( CFF_Builder
* builder
)
1860 CFF_GlyphSlot glyph
= builder
->glyph
;
1864 glyph
->root
.outline
= *builder
->base
;
1868 /* check that there is enough space for `count' more points */
1869 FT_LOCAL_DEF( FT_Error
)
1870 cff_check_points( CFF_Builder
* builder
,
1873 return FT_GLYPHLOADER_CHECK_POINTS( builder
->loader
, count
, 0 );
1877 /* add a new point, do not check space */
1878 FT_LOCAL_DEF( void )
1879 cff_builder_add_point( CFF_Builder
* builder
,
1884 FT_Outline
* outline
= builder
->current
;
1887 if ( builder
->load_points
)
1889 FT_Vector
* point
= outline
->points
+ outline
->n_points
;
1890 FT_Byte
* control
= (FT_Byte
*)outline
->tags
+ outline
->n_points
;
1892 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
1893 PS_Driver driver
= (PS_Driver
)FT_FACE_DRIVER( builder
->face
);
1896 if ( driver
->hinting_engine
== FT_HINTING_FREETYPE
)
1904 /* cf2_decoder_parse_charstrings uses 16.16 coordinates */
1908 *control
= (FT_Byte
)( flag
? FT_CURVE_TAG_ON
: FT_CURVE_TAG_CUBIC
);
1911 outline
->n_points
++;
1915 /* check space for a new on-curve point, then add it */
1916 FT_LOCAL_DEF( FT_Error
)
1917 cff_builder_add_point1( CFF_Builder
* builder
,
1924 error
= cff_check_points( builder
, 1 );
1926 cff_builder_add_point( builder
, x
, y
, 1 );
1932 /* check space for a new contour, then add it */
1933 FT_LOCAL_DEF( FT_Error
)
1934 cff_builder_add_contour( CFF_Builder
* builder
)
1936 FT_Outline
* outline
= builder
->current
;
1940 if ( !builder
->load_points
)
1942 outline
->n_contours
++;
1946 error
= FT_GLYPHLOADER_CHECK_POINTS( builder
->loader
, 0, 1 );
1949 if ( outline
->n_contours
> 0 )
1950 outline
->contours
[outline
->n_contours
- 1] =
1951 (short)( outline
->n_points
- 1 );
1953 outline
->n_contours
++;
1960 /* if a path was begun, add its first on-curve point */
1961 FT_LOCAL_DEF( FT_Error
)
1962 cff_builder_start_point( CFF_Builder
* builder
,
1966 FT_Error error
= FT_Err_Ok
;
1969 /* test whether we are building a new contour */
1970 if ( !builder
->path_begun
)
1972 builder
->path_begun
= 1;
1973 error
= cff_builder_add_contour( builder
);
1975 error
= cff_builder_add_point1( builder
, x
, y
);
1982 /* close the current contour */
1983 FT_LOCAL_DEF( void )
1984 cff_builder_close_contour( CFF_Builder
* builder
)
1986 FT_Outline
* outline
= builder
->current
;
1993 first
= outline
->n_contours
<= 1
1994 ? 0 : outline
->contours
[outline
->n_contours
- 2] + 1;
1996 /* We must not include the last point in the path if it */
1997 /* is located on the first point. */
1998 if ( outline
->n_points
> 1 )
2000 FT_Vector
* p1
= outline
->points
+ first
;
2001 FT_Vector
* p2
= outline
->points
+ outline
->n_points
- 1;
2002 FT_Byte
* control
= (FT_Byte
*)outline
->tags
+ outline
->n_points
- 1;
2005 /* `delete' last point only if it coincides with the first */
2006 /* point and if it is not a control point (which can happen). */
2007 if ( p1
->x
== p2
->x
&& p1
->y
== p2
->y
)
2008 if ( *control
== FT_CURVE_TAG_ON
)
2009 outline
->n_points
--;
2012 if ( outline
->n_contours
> 0 )
2014 /* Don't add contours only consisting of one point, i.e., */
2015 /* check whether begin point and last point are the same. */
2016 if ( first
== outline
->n_points
- 1 )
2018 outline
->n_contours
--;
2019 outline
->n_points
--;
2022 outline
->contours
[outline
->n_contours
- 1] =
2023 (short)( outline
->n_points
- 1 );
2028 /*************************************************************************/
2029 /*************************************************************************/
2031 /***** PS BUILDER *****/
2033 /*************************************************************************/
2034 /*************************************************************************/
2036 /*************************************************************************/
2039 /* ps_builder_init */
2042 /* Initializes a given glyph builder. */
2045 /* builder :: A pointer to the glyph builder to initialize. */
2048 /* face :: The current face object. */
2050 /* size :: The current size object. */
2052 /* glyph :: The current glyph object. */
2054 /* hinting :: Whether hinting should be applied. */
2056 FT_LOCAL_DEF( void )
2057 ps_builder_init( PS_Builder
* ps_builder
,
2061 FT_ZERO( ps_builder
);
2065 T1_Builder t1builder
= (T1_Builder
)builder
;
2068 ps_builder
->memory
= t1builder
->memory
;
2069 ps_builder
->face
= (FT_Face
)t1builder
->face
;
2070 ps_builder
->glyph
= (CFF_GlyphSlot
)t1builder
->glyph
;
2071 ps_builder
->loader
= t1builder
->loader
;
2072 ps_builder
->base
= t1builder
->base
;
2073 ps_builder
->current
= t1builder
->current
;
2075 ps_builder
->pos_x
= &t1builder
->pos_x
;
2076 ps_builder
->pos_y
= &t1builder
->pos_y
;
2078 ps_builder
->left_bearing
= &t1builder
->left_bearing
;
2079 ps_builder
->advance
= &t1builder
->advance
;
2081 ps_builder
->bbox
= &t1builder
->bbox
;
2082 ps_builder
->path_begun
= 0;
2083 ps_builder
->load_points
= t1builder
->load_points
;
2084 ps_builder
->no_recurse
= t1builder
->no_recurse
;
2086 ps_builder
->metrics_only
= t1builder
->metrics_only
;
2090 CFF_Builder
* cffbuilder
= (CFF_Builder
*)builder
;
2093 ps_builder
->memory
= cffbuilder
->memory
;
2094 ps_builder
->face
= (FT_Face
)cffbuilder
->face
;
2095 ps_builder
->glyph
= cffbuilder
->glyph
;
2096 ps_builder
->loader
= cffbuilder
->loader
;
2097 ps_builder
->base
= cffbuilder
->base
;
2098 ps_builder
->current
= cffbuilder
->current
;
2100 ps_builder
->pos_x
= &cffbuilder
->pos_x
;
2101 ps_builder
->pos_y
= &cffbuilder
->pos_y
;
2103 ps_builder
->left_bearing
= &cffbuilder
->left_bearing
;
2104 ps_builder
->advance
= &cffbuilder
->advance
;
2106 ps_builder
->bbox
= &cffbuilder
->bbox
;
2107 ps_builder
->path_begun
= cffbuilder
->path_begun
;
2108 ps_builder
->load_points
= cffbuilder
->load_points
;
2109 ps_builder
->no_recurse
= cffbuilder
->no_recurse
;
2111 ps_builder
->metrics_only
= cffbuilder
->metrics_only
;
2114 ps_builder
->is_t1
= is_t1
;
2115 ps_builder
->funcs
= ps_builder_funcs
;
2119 /*************************************************************************/
2122 /* ps_builder_done */
2125 /* Finalizes a given glyph builder. Its contents can still be used */
2126 /* after the call, but the function saves important information */
2127 /* within the corresponding glyph slot. */
2130 /* builder :: A pointer to the glyph builder to finalize. */
2132 FT_LOCAL_DEF( void )
2133 ps_builder_done( PS_Builder
* builder
)
2135 CFF_GlyphSlot glyph
= builder
->glyph
;
2139 glyph
->root
.outline
= *builder
->base
;
2143 /* check that there is enough space for `count' more points */
2144 FT_LOCAL_DEF( FT_Error
)
2145 ps_builder_check_points( PS_Builder
* builder
,
2148 return FT_GLYPHLOADER_CHECK_POINTS( builder
->loader
, count
, 0 );
2152 /* add a new point, do not check space */
2153 FT_LOCAL_DEF( void )
2154 ps_builder_add_point( PS_Builder
* builder
,
2159 FT_Outline
* outline
= builder
->current
;
2162 if ( builder
->load_points
)
2164 FT_Vector
* point
= outline
->points
+ outline
->n_points
;
2165 FT_Byte
* control
= (FT_Byte
*)outline
->tags
+ outline
->n_points
;
2167 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
2168 PS_Driver driver
= (PS_Driver
)FT_FACE_DRIVER( builder
->face
);
2171 if ( !builder
->is_t1
&&
2172 driver
->hinting_engine
== FT_HINTING_FREETYPE
)
2179 #ifdef T1_CONFIG_OPTION_OLD_ENGINE
2180 #ifndef CFF_CONFIG_OPTION_OLD_ENGINE
2181 PS_Driver driver
= (PS_Driver
)FT_FACE_DRIVER( builder
->face
);
2183 if ( builder
->is_t1
&&
2184 driver
->hinting_engine
== FT_HINTING_FREETYPE
)
2186 point
->x
= FIXED_TO_INT( x
);
2187 point
->y
= FIXED_TO_INT( y
);
2192 /* cf2_decoder_parse_charstrings uses 16.16 coordinates */
2196 *control
= (FT_Byte
)( flag
? FT_CURVE_TAG_ON
: FT_CURVE_TAG_CUBIC
);
2198 outline
->n_points
++;
2202 /* check space for a new on-curve point, then add it */
2203 FT_LOCAL_DEF( FT_Error
)
2204 ps_builder_add_point1( PS_Builder
* builder
,
2211 error
= ps_builder_check_points( builder
, 1 );
2213 ps_builder_add_point( builder
, x
, y
, 1 );
2219 /* check space for a new contour, then add it */
2220 FT_LOCAL_DEF( FT_Error
)
2221 ps_builder_add_contour( PS_Builder
* builder
)
2223 FT_Outline
* outline
= builder
->current
;
2227 /* this might happen in invalid fonts */
2230 FT_ERROR(( "ps_builder_add_contour: no outline to add points to\n" ));
2231 return FT_THROW( Invalid_File_Format
);
2234 if ( !builder
->load_points
)
2236 outline
->n_contours
++;
2240 error
= FT_GLYPHLOADER_CHECK_POINTS( builder
->loader
, 0, 1 );
2243 if ( outline
->n_contours
> 0 )
2244 outline
->contours
[outline
->n_contours
- 1] =
2245 (short)( outline
->n_points
- 1 );
2247 outline
->n_contours
++;
2254 /* if a path was begun, add its first on-curve point */
2255 FT_LOCAL_DEF( FT_Error
)
2256 ps_builder_start_point( PS_Builder
* builder
,
2260 FT_Error error
= FT_Err_Ok
;
2263 /* test whether we are building a new contour */
2264 if ( !builder
->path_begun
)
2266 builder
->path_begun
= 1;
2267 error
= ps_builder_add_contour( builder
);
2269 error
= ps_builder_add_point1( builder
, x
, y
);
2276 /* close the current contour */
2277 FT_LOCAL_DEF( void )
2278 ps_builder_close_contour( PS_Builder
* builder
)
2280 FT_Outline
* outline
= builder
->current
;
2287 first
= outline
->n_contours
<= 1
2288 ? 0 : outline
->contours
[outline
->n_contours
- 2] + 1;
2290 /* in malformed fonts it can happen that a contour was started */
2291 /* but no points were added */
2292 if ( outline
->n_contours
&& first
== outline
->n_points
)
2294 outline
->n_contours
--;
2298 /* We must not include the last point in the path if it */
2299 /* is located on the first point. */
2300 if ( outline
->n_points
> 1 )
2302 FT_Vector
* p1
= outline
->points
+ first
;
2303 FT_Vector
* p2
= outline
->points
+ outline
->n_points
- 1;
2304 FT_Byte
* control
= (FT_Byte
*)outline
->tags
+ outline
->n_points
- 1;
2307 /* `delete' last point only if it coincides with the first */
2308 /* point and it is not a control point (which can happen). */
2309 if ( p1
->x
== p2
->x
&& p1
->y
== p2
->y
)
2310 if ( *control
== FT_CURVE_TAG_ON
)
2311 outline
->n_points
--;
2314 if ( outline
->n_contours
> 0 )
2316 /* Don't add contours only consisting of one point, i.e., */
2317 /* check whether the first and the last point is the same. */
2318 if ( first
== outline
->n_points
- 1 )
2320 outline
->n_contours
--;
2321 outline
->n_points
--;
2324 outline
->contours
[outline
->n_contours
- 1] =
2325 (short)( outline
->n_points
- 1 );
2330 /*************************************************************************/
2331 /*************************************************************************/
2335 /*************************************************************************/
2336 /*************************************************************************/
2339 /*************************************************************************/
2342 /* ps_decoder_init */
2345 /* Creates a wrapper decoder for use in the combined */
2346 /* Type 1 / CFF interpreter. */
2349 /* ps_decoder :: A pointer to the decoder to initialize. */
2352 /* decoder :: A pointer to the original decoder. */
2354 /* is_t1 :: Flag indicating Type 1 or CFF */
2356 FT_LOCAL_DEF( void )
2357 ps_decoder_init( PS_Decoder
* ps_decoder
,
2361 FT_ZERO( ps_decoder
);
2365 T1_Decoder t1_decoder
= (T1_Decoder
)decoder
;
2368 ps_builder_init( &ps_decoder
->builder
,
2369 &t1_decoder
->builder
,
2372 ps_decoder
->cf2_instance
= &t1_decoder
->cf2_instance
;
2373 ps_decoder
->psnames
= t1_decoder
->psnames
;
2375 ps_decoder
->num_glyphs
= t1_decoder
->num_glyphs
;
2376 ps_decoder
->glyph_names
= t1_decoder
->glyph_names
;
2377 ps_decoder
->hint_mode
= t1_decoder
->hint_mode
;
2378 ps_decoder
->blend
= t1_decoder
->blend
;
2380 ps_decoder
->num_locals
= (FT_UInt
)t1_decoder
->num_subrs
;
2381 ps_decoder
->locals
= t1_decoder
->subrs
;
2382 ps_decoder
->locals_len
= t1_decoder
->subrs_len
;
2383 ps_decoder
->locals_hash
= t1_decoder
->subrs_hash
;
2385 ps_decoder
->buildchar
= t1_decoder
->buildchar
;
2386 ps_decoder
->len_buildchar
= t1_decoder
->len_buildchar
;
2388 ps_decoder
->lenIV
= t1_decoder
->lenIV
;
2392 CFF_Decoder
* cff_decoder
= (CFF_Decoder
*)decoder
;
2395 ps_builder_init( &ps_decoder
->builder
,
2396 &cff_decoder
->builder
,
2399 ps_decoder
->cff
= cff_decoder
->cff
;
2400 ps_decoder
->cf2_instance
= &cff_decoder
->cff
->cf2_instance
;
2401 ps_decoder
->current_subfont
= cff_decoder
->current_subfont
;
2403 ps_decoder
->num_globals
= cff_decoder
->num_globals
;
2404 ps_decoder
->globals
= cff_decoder
->globals
;
2405 ps_decoder
->globals_bias
= cff_decoder
->globals_bias
;
2406 ps_decoder
->num_locals
= cff_decoder
->num_locals
;
2407 ps_decoder
->locals
= cff_decoder
->locals
;
2408 ps_decoder
->locals_bias
= cff_decoder
->locals_bias
;
2410 ps_decoder
->glyph_width
= &cff_decoder
->glyph_width
;
2411 ps_decoder
->width_only
= cff_decoder
->width_only
;
2413 ps_decoder
->hint_mode
= cff_decoder
->hint_mode
;
2415 ps_decoder
->get_glyph_callback
= cff_decoder
->get_glyph_callback
;
2416 ps_decoder
->free_glyph_callback
= cff_decoder
->free_glyph_callback
;
2421 /* Synthesize a SubFont object for Type 1 fonts, for use in the */
2422 /* new interpreter to access Private dict data. */
2423 FT_LOCAL_DEF( void )
2424 t1_make_subfont( FT_Face face
,
2426 CFF_SubFont subfont
)
2428 CFF_Private cpriv
= &subfont
->private_dict
;
2435 count
= cpriv
->num_blue_values
= priv
->num_blue_values
;
2436 for ( n
= 0; n
< count
; n
++ )
2437 cpriv
->blue_values
[n
] = (FT_Pos
)priv
->blue_values
[n
];
2439 count
= cpriv
->num_other_blues
= priv
->num_other_blues
;
2440 for ( n
= 0; n
< count
; n
++ )
2441 cpriv
->other_blues
[n
] = (FT_Pos
)priv
->other_blues
[n
];
2443 count
= cpriv
->num_family_blues
= priv
->num_family_blues
;
2444 for ( n
= 0; n
< count
; n
++ )
2445 cpriv
->family_blues
[n
] = (FT_Pos
)priv
->family_blues
[n
];
2447 count
= cpriv
->num_family_other_blues
= priv
->num_family_other_blues
;
2448 for ( n
= 0; n
< count
; n
++ )
2449 cpriv
->family_other_blues
[n
] = (FT_Pos
)priv
->family_other_blues
[n
];
2451 cpriv
->blue_scale
= priv
->blue_scale
;
2452 cpriv
->blue_shift
= (FT_Pos
)priv
->blue_shift
;
2453 cpriv
->blue_fuzz
= (FT_Pos
)priv
->blue_fuzz
;
2455 cpriv
->standard_width
= (FT_Pos
)priv
->standard_width
[0];
2456 cpriv
->standard_height
= (FT_Pos
)priv
->standard_height
[0];
2458 count
= cpriv
->num_snap_widths
= priv
->num_snap_widths
;
2459 for ( n
= 0; n
< count
; n
++ )
2460 cpriv
->snap_widths
[n
] = (FT_Pos
)priv
->snap_widths
[n
];
2462 count
= cpriv
->num_snap_heights
= priv
->num_snap_heights
;
2463 for ( n
= 0; n
< count
; n
++ )
2464 cpriv
->snap_heights
[n
] = (FT_Pos
)priv
->snap_heights
[n
];
2466 cpriv
->force_bold
= priv
->force_bold
;
2467 cpriv
->lenIV
= priv
->lenIV
;
2468 cpriv
->language_group
= priv
->language_group
;
2469 cpriv
->expansion_factor
= priv
->expansion_factor
;
2471 cpriv
->subfont
= subfont
;
2474 /* Initialize the random number generator. */
2475 if ( face
->internal
->random_seed
!= -1 )
2477 /* If we have a face-specific seed, use it. */
2478 /* If non-zero, update it to a positive value. */
2479 subfont
->random
= (FT_UInt32
)face
->internal
->random_seed
;
2480 if ( face
->internal
->random_seed
)
2484 face
->internal
->random_seed
= (FT_Int32
)cff_random(
2485 (FT_UInt32
)face
->internal
->random_seed
);
2487 } while ( face
->internal
->random_seed
< 0 );
2490 if ( !subfont
->random
)
2495 /* compute random seed from some memory addresses */
2496 seed
= (FT_UInt32
)( (FT_Offset
)(char*)&seed
^
2497 (FT_Offset
)(char*)&face
^
2498 (FT_Offset
)(char*)&subfont
);
2499 seed
= seed
^ ( seed
>> 10 ) ^ ( seed
>> 20 );
2503 subfont
->random
= seed
;
2508 FT_LOCAL_DEF( void )
2509 t1_decrypt( FT_Byte
* buffer
,
2513 PS_Conv_EexecDecode( &buffer
,
2521 FT_LOCAL_DEF( FT_UInt32
)
2522 cff_random( FT_UInt32 r
)
2524 /* a 32bit version of the `xorshift' algorithm */