1 /****************************************************************************
5 * Auxiliary functions for PostScript fonts (body).
7 * Copyright (C) 1996-2023 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.
19 #include <freetype/internal/psaux.h>
20 #include <freetype/internal/ftdebug.h>
21 #include <freetype/internal/ftcalc.h>
22 #include <freetype/ftdriver.h>
31 /**************************************************************************
33 * The macro FT_COMPONENT is used in trace mode. It is an implicit
34 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
35 * messages during execution.
38 #define FT_COMPONENT psobjs
41 /*************************************************************************/
42 /*************************************************************************/
44 /***** PS_TABLE *****/
46 /*************************************************************************/
47 /*************************************************************************/
49 /**************************************************************************
55 * Initializes a PS_Table.
59 * The address of the target table.
63 * The table size = the maximum number of elements.
66 * The memory object to use for all subsequent
70 * FreeType error code. 0 means success.
72 FT_LOCAL_DEF( FT_Error )
73 ps_table_new( PS_Table table,
80 table->memory = memory;
81 if ( FT_NEW_ARRAY( table->elements, count ) ||
82 FT_NEW_ARRAY( table->lengths, count ) )
85 table->max_elems = count;
86 table->init = 0xDEADBEEFUL;
91 *(PS_Table_FuncsRec*)&table->funcs = ps_table_funcs;
95 FT_FREE( table->elements );
102 ps_table_realloc( PS_Table table,
105 FT_Memory memory = table->memory;
106 FT_Byte* old_base = table->block;
110 /* (re)allocate the base block */
111 if ( FT_REALLOC( table->block, table->capacity, new_size ) )
114 /* rebase offsets if necessary */
115 if ( old_base && table->block != old_base )
117 FT_Byte** offset = table->elements;
118 FT_Byte** limit = offset + table->max_elems;
121 for ( ; offset < limit; offset++ )
124 *offset = table->block + ( *offset - old_base );
128 table->capacity = new_size;
134 /**************************************************************************
140 * Adds an object to a PS_Table, possibly growing its memory block.
148 * The index of the object in the table.
151 * The address of the object to copy in memory.
154 * The length in bytes of the source object.
157 * FreeType error code. 0 means success. An error is returned if a
158 * reallocation fails.
160 FT_LOCAL_DEF( FT_Error )
161 ps_table_add( PS_Table table,
166 if ( idx < 0 || idx >= table->max_elems )
168 FT_ERROR(( "ps_table_add: invalid index\n" ));
169 return FT_THROW( Invalid_Argument );
172 /* grow the base block if needed */
173 if ( table->cursor + length > table->capacity )
176 FT_Offset new_size = table->capacity;
177 FT_PtrDist in_offset;
180 in_offset = (FT_Byte*)object - table->block;
181 if ( in_offset < 0 || (FT_Offset)in_offset >= table->capacity )
184 while ( new_size < table->cursor + length )
186 /* increase size by 25% and round up to the nearest multiple
188 new_size += ( new_size >> 2 ) + 1;
189 new_size = FT_PAD_CEIL( new_size, 1024 );
192 error = ps_table_realloc( table, new_size );
196 if ( in_offset >= 0 )
197 object = table->block + in_offset;
200 /* add the object to the base block and adjust offset */
201 table->elements[idx] = FT_OFFSET( table->block, table->cursor );
202 table->lengths [idx] = length;
203 FT_MEM_COPY( table->block + table->cursor, object, length );
205 table->cursor += length;
210 /**************************************************************************
216 * Finalizes a PS_TableRec (i.e., reallocate it to its current
224 ps_table_done( PS_Table table )
226 /* no problem if shrinking fails */
227 ps_table_realloc( table, table->cursor );
232 ps_table_release( PS_Table table )
234 FT_Memory memory = table->memory;
237 if ( table->init == 0xDEADBEEFUL )
239 FT_FREE( table->block );
240 FT_FREE( table->elements );
241 FT_FREE( table->lengths );
247 /*************************************************************************/
248 /*************************************************************************/
250 /***** T1 PARSER *****/
252 /*************************************************************************/
253 /*************************************************************************/
256 /* first character must be already part of the comment */
259 skip_comment( FT_Byte* *acur,
262 FT_Byte* cur = *acur;
265 while ( cur < limit )
267 if ( IS_PS_NEWLINE( *cur ) )
277 skip_spaces( FT_Byte* *acur,
280 FT_Byte* cur = *acur;
283 while ( cur < limit )
285 if ( !IS_PS_SPACE( *cur ) )
288 /* According to the PLRM, a comment is equal to a space. */
289 skip_comment( &cur, limit );
300 #define IS_OCTAL_DIGIT( c ) ( '0' <= (c) && (c) <= '7' )
303 /* first character must be `('; */
304 /* *acur is positioned at the character after the closing `)' */
307 skip_literal_string( FT_Byte* *acur,
310 FT_Byte* cur = *acur;
312 FT_Error error = FT_ERR( Invalid_File_Format );
316 while ( cur < limit )
325 /* Red Book 3rd ed., section `Literal Text Strings', p. 29: */
326 /* A backslash can introduce three different types */
327 /* of escape sequences: */
328 /* - a special escaped char like \r, \n, etc. */
329 /* - a one-, two-, or three-digit octal number */
330 /* - none of the above in which case the backslash is ignored */
333 /* error (or to be ignored?) */
338 /* skip `special' escape */
351 /* skip octal escape or ignore backslash */
352 for ( i = 0; i < 3 && cur < limit; i++ )
354 if ( !IS_OCTAL_DIGIT( *cur ) )
380 /* first character must be `<' */
383 skip_string( FT_Byte* *acur,
386 FT_Byte* cur = *acur;
387 FT_Error err = FT_Err_Ok;
390 while ( ++cur < limit )
392 /* All whitespace characters are ignored. */
393 skip_spaces( &cur, limit );
397 if ( !IS_PS_XDIGIT( *cur ) )
401 if ( cur < limit && *cur != '>' )
403 FT_ERROR(( "skip_string: missing closing delimiter `>'\n" ));
404 err = FT_THROW( Invalid_File_Format );
414 /* first character must be the opening brace that */
415 /* starts the procedure */
417 /* NB: [ and ] need not match: */
418 /* `/foo {[} def' is a valid PostScript fragment, */
419 /* even within a Type1 font */
422 skip_procedure( FT_Byte* *acur,
427 FT_Error error = FT_Err_Ok;
430 FT_ASSERT( **acur == '{' );
432 for ( cur = *acur; cur < limit && error == FT_Err_Ok; cur++ )
450 error = skip_literal_string( &cur, limit );
454 error = skip_string( &cur, limit );
458 skip_comment( &cur, limit );
465 error = FT_THROW( Invalid_File_Format );
473 /************************************************************************
475 * All exported parsing routines handle leading whitespace and stop at
476 * the first character which isn't part of the just handled token.
482 ps_parser_skip_PS_token( PS_Parser parser )
484 /* Note: PostScript allows any non-delimiting, non-whitespace */
485 /* character in a name (PS Ref Manual, 3rd ed, p31). */
486 /* PostScript delimiters are (, ), <, >, [, ], {, }, /, and %. */
488 FT_Byte* cur = parser->cursor;
489 FT_Byte* limit = parser->limit;
490 FT_Error error = FT_Err_Ok;
493 skip_spaces( &cur, limit ); /* this also skips comments */
497 /* self-delimiting, single-character tokens */
498 if ( *cur == '[' || *cur == ']' )
504 /* skip balanced expressions (procedures and strings) */
506 if ( *cur == '{' ) /* {...} */
508 error = skip_procedure( &cur, limit );
512 if ( *cur == '(' ) /* (...) */
514 error = skip_literal_string( &cur, limit );
518 if ( *cur == '<' ) /* <...> */
520 if ( cur + 1 < limit && *( cur + 1 ) == '<' ) /* << */
526 error = skip_string( &cur, limit );
534 if ( cur >= limit || *cur != '>' ) /* >> */
536 FT_ERROR(( "ps_parser_skip_PS_token:"
537 " unexpected closing delimiter `>'\n" ));
538 error = FT_THROW( Invalid_File_Format );
549 while ( cur < limit )
551 /* *cur might be invalid (e.g., ')' or '}'), but this */
552 /* is handled by the test `cur == parser->cursor' below */
553 if ( IS_PS_DELIM( *cur ) )
560 if ( cur < limit && cur == parser->cursor )
562 FT_ERROR(( "ps_parser_skip_PS_token:"
563 " current token is `%c' which is self-delimiting\n",
566 " but invalid at this point\n" ));
568 error = FT_THROW( Invalid_File_Format );
574 parser->error = error;
575 parser->cursor = cur;
580 ps_parser_skip_spaces( PS_Parser parser )
582 skip_spaces( &parser->cursor, parser->limit );
586 /* `token' here means either something between balanced delimiters */
587 /* or the next token; the delimiters are not removed. */
590 ps_parser_to_token( PS_Parser parser,
598 token->type = T1_TOKEN_TYPE_NONE;
602 /* first of all, skip leading whitespace */
603 ps_parser_skip_spaces( parser );
605 cur = parser->cursor;
606 limit = parser->limit;
613 /************* check for literal string *****************/
615 token->type = T1_TOKEN_TYPE_STRING;
618 if ( skip_literal_string( &cur, limit ) == FT_Err_Ok )
622 /************* check for programs/array *****************/
624 token->type = T1_TOKEN_TYPE_ARRAY;
627 if ( skip_procedure( &cur, limit ) == FT_Err_Ok )
631 /************* check for table/array ********************/
632 /* XXX: in theory we should also look for "<<" */
633 /* since this is semantically equivalent to "["; */
634 /* in practice it doesn't matter (?) */
636 token->type = T1_TOKEN_TYPE_ARRAY;
638 token->start = cur++;
640 /* we need this to catch `[ ]' */
641 parser->cursor = cur;
642 ps_parser_skip_spaces( parser );
643 cur = parser->cursor;
645 while ( cur < limit && !parser->error )
647 /* XXX: this is wrong because it does not */
648 /* skip comments, procedures, and strings */
651 else if ( *cur == ']' )
656 token->limit = ++cur;
661 parser->cursor = cur;
662 ps_parser_skip_PS_token( parser );
663 /* we need this to catch `[XXX ]' */
664 ps_parser_skip_spaces ( parser );
665 cur = parser->cursor;
669 /* ************ otherwise, it is any token **************/
672 token->type = ( *cur == '/' ) ? T1_TOKEN_TYPE_KEY : T1_TOKEN_TYPE_ANY;
673 ps_parser_skip_PS_token( parser );
674 cur = parser->cursor;
675 if ( !parser->error )
682 token->type = T1_TOKEN_TYPE_NONE;
685 parser->cursor = cur;
689 /* NB: `tokens' can be NULL if we only want to count */
690 /* the number of array elements */
693 ps_parser_to_token_array( PS_Parser parser,
696 FT_Int* pnum_tokens )
703 /* this also handles leading whitespace */
704 ps_parser_to_token( parser, &master );
706 if ( master.type == T1_TOKEN_TYPE_ARRAY )
708 FT_Byte* old_cursor = parser->cursor;
709 FT_Byte* old_limit = parser->limit;
710 T1_Token cur = tokens;
711 T1_Token limit = cur + max_tokens;
714 /* don't include outermost delimiters */
715 parser->cursor = master.start + 1;
716 parser->limit = master.limit - 1;
718 while ( parser->cursor < parser->limit )
723 ps_parser_to_token( parser, &token );
727 if ( tokens && cur < limit )
733 *pnum_tokens = (FT_Int)( cur - tokens );
735 parser->cursor = old_cursor;
736 parser->limit = old_limit;
741 /* first character must be a delimiter or a part of a number */
742 /* NB: `coords' can be NULL if we just want to skip the */
743 /* array; in this case we ignore `max_coords' */
746 ps_tocoordarray( FT_Byte* *acur,
751 FT_Byte* cur = *acur;
759 /* check for the beginning of an array; otherwise, only one number */
772 /* now, read the coordinates */
773 while ( cur < limit )
779 /* skip whitespace in front of data */
780 skip_spaces( &cur, limit );
792 if ( coords && count >= max_coords )
795 /* call PS_Conv_ToFixed() even if coords == NULL */
796 /* to properly parse number at `cur' */
797 *( coords ? &coords[count] : &dummy ) =
798 (FT_Short)( PS_Conv_ToFixed( &cur, limit, 0 ) >> 16 );
800 if ( old_cur == cur )
818 /* first character must be a delimiter or a part of a number */
819 /* NB: `values' can be NULL if we just want to skip the */
820 /* array; in this case we ignore `max_values' */
822 /* return number of successfully parsed values */
825 ps_tofixedarray( FT_Byte* *acur,
831 FT_Byte* cur = *acur;
839 /* Check for the beginning of an array. Otherwise, only one number */
852 /* now, read the values */
853 while ( cur < limit )
859 /* skip whitespace in front of data */
860 skip_spaces( &cur, limit );
872 if ( values && count >= max_values )
875 /* call PS_Conv_ToFixed() even if coords == NULL */
876 /* to properly parse number at `cur' */
877 *( values ? &values[count] : &dummy ) =
878 PS_Conv_ToFixed( &cur, limit, power_ten );
880 if ( old_cur == cur )
901 ps_tostring( FT_Byte** cursor,
905 FT_Byte* cur = *cursor;
912 /* XXX: some stupid fonts have a `Notice' or `Copyright' string */
913 /* that simply doesn't begin with an opening parenthesis, even */
914 /* though they have a closing one! E.g. "amuncial.pfb" */
916 /* We must deal with these ill-fated cases there. Note that */
917 /* these fonts didn't work with the old Type 1 driver as the */
918 /* notice/copyright was not recognized as a valid string token */
919 /* and made the old token parser commit errors. */
921 while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) )
923 if ( cur + 1 >= limit )
927 cur++; /* skip the opening parenthesis, if there is one */
932 /* then, count its length */
933 for ( ; cur < limit; cur++ )
938 else if ( *cur == ')' )
946 len = (FT_UInt)( cur - *cursor );
947 if ( cur >= limit || FT_QALLOC( result, len + 1 ) )
950 /* now copy the string */
951 FT_MEM_COPY( result, *cursor, len );
961 ps_tobool( FT_Byte* *acur,
964 FT_Byte* cur = *acur;
968 /* return 1 if we find `true', 0 otherwise */
969 if ( cur + 3 < limit &&
978 else if ( cur + 4 < limit &&
994 /* load a simple field (i.e. non-table) into the current list of objects */
996 FT_LOCAL_DEF( FT_Error )
997 ps_parser_load_field( PS_Parser parser,
998 const T1_Field field,
1000 FT_UInt max_objects,
1012 /* this also skips leading whitespace */
1013 ps_parser_to_token( parser, &token );
1020 limit = token.limit;
1024 /* we must detect arrays in /FontBBox */
1025 if ( type == T1_FIELD_TYPE_BBOX )
1028 FT_Byte* old_cur = parser->cursor;
1029 FT_Byte* old_limit = parser->limit;
1032 /* don't include delimiters */
1033 parser->cursor = token.start + 1;
1034 parser->limit = token.limit - 1;
1036 ps_parser_to_token( parser, &token2 );
1037 parser->cursor = old_cur;
1038 parser->limit = old_limit;
1040 if ( token2.type == T1_TOKEN_TYPE_ARRAY )
1042 type = T1_FIELD_TYPE_MM_BBOX;
1046 else if ( token.type == T1_TOKEN_TYPE_ARRAY )
1048 count = max_objects;
1051 /* if this is an array and we have no blend, an error occurs */
1052 if ( max_objects == 0 )
1057 /* don't include delimiters */
1062 for ( ; count > 0; count--, idx++ )
1064 FT_Byte* q = (FT_Byte*)objects[idx] + field->offset;
1068 skip_spaces( &cur, limit );
1072 case T1_FIELD_TYPE_BOOL:
1073 val = ps_tobool( &cur, limit );
1074 FT_TRACE4(( " %s", val ? "true" : "false" ));
1077 case T1_FIELD_TYPE_FIXED:
1078 val = PS_Conv_ToFixed( &cur, limit, 0 );
1079 FT_TRACE4(( " %f", (double)val / 65536 ));
1082 case T1_FIELD_TYPE_FIXED_1000:
1083 val = PS_Conv_ToFixed( &cur, limit, 3 );
1084 FT_TRACE4(( " %f", (double)val / 65536 / 1000 ));
1087 case T1_FIELD_TYPE_INTEGER:
1088 val = PS_Conv_ToInt( &cur, limit );
1089 FT_TRACE4(( " %ld", val ));
1093 switch ( field->size )
1095 case (8 / FT_CHAR_BIT):
1096 *(FT_Byte*)q = (FT_Byte)val;
1099 case (16 / FT_CHAR_BIT):
1100 *(FT_UShort*)q = (FT_UShort)val;
1103 case (32 / FT_CHAR_BIT):
1104 *(FT_UInt32*)q = (FT_UInt32)val;
1107 default: /* for 64-bit systems */
1112 case T1_FIELD_TYPE_STRING:
1113 case T1_FIELD_TYPE_KEY:
1115 FT_Memory memory = parser->memory;
1116 FT_UInt len = (FT_UInt)( limit - cur );
1117 FT_String* string = NULL;
1123 /* we allow both a string or a name */
1124 /* for cases like /FontName (foo) def */
1125 if ( token.type == T1_TOKEN_TYPE_KEY )
1127 /* don't include leading `/' */
1131 else if ( token.type == T1_TOKEN_TYPE_STRING )
1133 /* don't include delimiting parentheses */
1134 /* XXX we don't handle <<...>> here */
1135 /* XXX should we convert octal escapes? */
1136 /* if so, what encoding should we use? */
1142 FT_ERROR(( "ps_parser_load_field:"
1143 " expected a name or string\n" ));
1145 " but found token of type %d instead\n",
1147 error = FT_THROW( Invalid_File_Format );
1151 /* for this to work (FT_String**)q must have been */
1152 /* initialized to NULL */
1153 if ( *(FT_String**)q )
1155 FT_TRACE0(( "ps_parser_load_field: overwriting field %s\n",
1157 FT_FREE( *(FT_String**)q );
1160 if ( FT_QALLOC( string, len + 1 ) )
1163 FT_MEM_COPY( string, cur, len );
1166 #ifdef FT_DEBUG_LEVEL_TRACE
1167 if ( token.type == T1_TOKEN_TYPE_STRING )
1168 FT_TRACE4(( " (%s)", string ));
1170 FT_TRACE4(( " /%s", string ));
1173 *(FT_String**)q = string;
1177 case T1_FIELD_TYPE_BBOX:
1180 FT_BBox* bbox = (FT_BBox*)q;
1184 result = ps_tofixedarray( &cur, limit, 4, temp, 0 );
1188 FT_ERROR(( "ps_parser_load_field:"
1189 " expected four integers in bounding box\n" ));
1190 error = FT_THROW( Invalid_File_Format );
1194 bbox->xMin = FT_RoundFix( temp[0] );
1195 bbox->yMin = FT_RoundFix( temp[1] );
1196 bbox->xMax = FT_RoundFix( temp[2] );
1197 bbox->yMax = FT_RoundFix( temp[3] );
1199 FT_TRACE4(( " [%ld %ld %ld %ld]",
1203 bbox->yMax / 65536 ));
1207 case T1_FIELD_TYPE_MM_BBOX:
1209 FT_Memory memory = parser->memory;
1210 FT_Fixed* temp = NULL;
1215 if ( FT_QNEW_ARRAY( temp, max_objects * 4 ) )
1218 for ( i = 0; i < 4; i++ )
1220 result = ps_tofixedarray( &cur, limit, (FT_Int)max_objects,
1221 temp + i * max_objects, 0 );
1222 if ( result < 0 || (FT_UInt)result < max_objects )
1224 FT_ERROR(( "ps_parser_load_field:"
1225 " expected %d integer%s in the %s subarray\n",
1226 max_objects, max_objects > 1 ? "s" : "",
1228 : ( i == 1 ? "second"
1229 : ( i == 2 ? "third"
1232 " of /FontBBox in the /Blend dictionary\n" ));
1233 error = FT_THROW( Invalid_File_Format );
1239 skip_spaces( &cur, limit );
1242 FT_TRACE4(( " [" ));
1243 for ( i = 0; i < max_objects; i++ )
1245 FT_BBox* bbox = (FT_BBox*)objects[i];
1248 bbox->xMin = FT_RoundFix( temp[i ] );
1249 bbox->yMin = FT_RoundFix( temp[i + max_objects] );
1250 bbox->xMax = FT_RoundFix( temp[i + 2 * max_objects] );
1251 bbox->yMax = FT_RoundFix( temp[i + 3 * max_objects] );
1253 FT_TRACE4(( " [%ld %ld %ld %ld]",
1257 bbox->yMax / 65536 ));
1266 /* an error occurred */
1271 #if 0 /* obsolete -- keep for reference */
1273 *pflags |= 1L << field->flag_bit;
1275 FT_UNUSED( pflags );
1284 error = FT_THROW( Invalid_File_Format );
1289 #define T1_MAX_TABLE_ELEMENTS 32
1292 FT_LOCAL_DEF( FT_Error )
1293 ps_parser_load_field_table( PS_Parser parser,
1294 const T1_Field field,
1296 FT_UInt max_objects,
1299 T1_TokenRec elements[T1_MAX_TABLE_ELEMENTS];
1301 FT_Int num_elements;
1302 FT_Error error = FT_Err_Ok;
1303 FT_Byte* old_cursor;
1305 T1_FieldRec fieldrec = *(T1_Field)field;
1308 fieldrec.type = T1_FIELD_TYPE_INTEGER;
1309 if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY ||
1310 field->type == T1_FIELD_TYPE_BBOX )
1311 fieldrec.type = T1_FIELD_TYPE_FIXED;
1313 ps_parser_to_token_array( parser, elements,
1314 T1_MAX_TABLE_ELEMENTS, &num_elements );
1315 if ( num_elements < 0 )
1317 error = FT_ERR( Ignore );
1320 if ( (FT_UInt)num_elements > field->array_max )
1321 num_elements = (FT_Int)field->array_max;
1323 old_cursor = parser->cursor;
1324 old_limit = parser->limit;
1326 /* we store the elements count if necessary; */
1327 /* we further assume that `count_offset' can't be zero */
1328 if ( field->type != T1_FIELD_TYPE_BBOX && field->count_offset != 0 )
1329 *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =
1330 (FT_Byte)num_elements;
1332 FT_TRACE4(( " [" ));
1334 /* we now load each element, adjusting the field.offset on each one */
1336 for ( ; num_elements > 0; num_elements--, token++ )
1338 parser->cursor = token->start;
1339 parser->limit = token->limit;
1341 error = ps_parser_load_field( parser,
1349 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,
1413 parser->cursor = cur;
1417 if ( cur < parser->limit && *cur != '>' )
1419 FT_ERROR(( "ps_parser_to_bytes: Missing closing delimiter `>'\n" ));
1420 error = FT_THROW( Invalid_File_Format );
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 /**************************************************************************
1518 * Initializes a given glyph builder.
1522 * A pointer to the glyph builder to initialize.
1526 * The current face object.
1529 * The current size object.
1532 * The current glyph object.
1535 * Whether hinting should be applied.
1537 FT_LOCAL_DEF( void )
1538 t1_builder_init( T1_Builder builder,
1544 builder->parse_state = T1_Parse_Start;
1545 builder->load_points = 1;
1547 builder->face = face;
1548 builder->glyph = glyph;
1549 builder->memory = face->memory;
1553 FT_GlyphLoader loader = glyph->internal->loader;
1556 builder->loader = loader;
1557 builder->base = &loader->base.outline;
1558 builder->current = &loader->current.outline;
1559 FT_GlyphLoader_Rewind( loader );
1561 builder->hints_globals = size->internal->module_data;
1562 builder->hints_funcs = NULL;
1565 builder->hints_funcs = glyph->internal->glyph_hints;
1571 builder->left_bearing.x = 0;
1572 builder->left_bearing.y = 0;
1573 builder->advance.x = 0;
1574 builder->advance.y = 0;
1576 builder->funcs = t1_builder_funcs;
1580 /**************************************************************************
1586 * Finalizes a given glyph builder. Its contents can still be used
1587 * after the call, but the function saves important information
1588 * within the corresponding glyph slot.
1592 * A pointer to the glyph builder to finalize.
1594 FT_LOCAL_DEF( void )
1595 t1_builder_done( T1_Builder builder )
1597 FT_GlyphSlot glyph = builder->glyph;
1601 glyph->outline = *builder->base;
1605 /* check that there is enough space for `count' more points */
1606 FT_LOCAL_DEF( FT_Error )
1607 t1_builder_check_points( T1_Builder builder,
1610 return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
1614 /* add a new point, do not check space */
1615 FT_LOCAL_DEF( void )
1616 t1_builder_add_point( T1_Builder builder,
1621 FT_Outline* outline = builder->current;
1624 if ( builder->load_points )
1626 FT_Vector* point = outline->points + outline->n_points;
1627 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
1630 point->x = FIXED_TO_INT( x );
1631 point->y = FIXED_TO_INT( y );
1632 *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
1634 outline->n_points++;
1638 /* check space for a new on-curve point, then add it */
1639 FT_LOCAL_DEF( FT_Error )
1640 t1_builder_add_point1( T1_Builder builder,
1647 error = t1_builder_check_points( builder, 1 );
1649 t1_builder_add_point( builder, x, y, 1 );
1655 /* check space for a new contour, then add it */
1656 FT_LOCAL_DEF( FT_Error )
1657 t1_builder_add_contour( T1_Builder builder )
1659 FT_Outline* outline = builder->current;
1663 /* this might happen in invalid fonts */
1666 FT_ERROR(( "t1_builder_add_contour: no outline to add points to\n" ));
1667 return FT_THROW( Invalid_File_Format );
1670 if ( !builder->load_points )
1672 outline->n_contours++;
1676 error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
1679 if ( outline->n_contours > 0 )
1680 outline->contours[outline->n_contours - 1] =
1681 (short)( outline->n_points - 1 );
1683 outline->n_contours++;
1690 /* if a path was begun, add its first on-curve point */
1691 FT_LOCAL_DEF( FT_Error )
1692 t1_builder_start_point( T1_Builder builder,
1696 FT_Error error = FT_ERR( Invalid_File_Format );
1699 /* test whether we are building a new contour */
1701 if ( builder->parse_state == T1_Parse_Have_Path )
1705 builder->parse_state = T1_Parse_Have_Path;
1706 error = t1_builder_add_contour( builder );
1708 error = t1_builder_add_point1( builder, x, y );
1715 /* close the current contour */
1716 FT_LOCAL_DEF( void )
1717 t1_builder_close_contour( T1_Builder builder )
1719 FT_Outline* outline = builder->current;
1726 first = outline->n_contours <= 1
1727 ? 0 : outline->contours[outline->n_contours - 2] + 1;
1729 /* in malformed fonts it can happen that a contour was started */
1730 /* but no points were added */
1731 if ( outline->n_contours && first == outline->n_points )
1733 outline->n_contours--;
1737 /* We must not include the last point in the path if it */
1738 /* is located on the first point. */
1739 if ( outline->n_points > 1 )
1741 FT_Vector* p1 = outline->points + first;
1742 FT_Vector* p2 = outline->points + outline->n_points - 1;
1743 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;
1746 /* `delete' last point only if it coincides with the first */
1747 /* point and it is not a control point (which can happen). */
1748 if ( p1->x == p2->x && p1->y == p2->y )
1749 if ( *control == FT_CURVE_TAG_ON )
1750 outline->n_points--;
1753 if ( outline->n_contours > 0 )
1755 /* Don't add contours only consisting of one point, i.e., */
1756 /* check whether the first and the last point is the same. */
1757 if ( first == outline->n_points - 1 )
1759 outline->n_contours--;
1760 outline->n_points--;
1763 outline->contours[outline->n_contours - 1] =
1764 (short)( outline->n_points - 1 );
1769 /*************************************************************************/
1770 /*************************************************************************/
1772 /***** CFF BUILDER *****/
1774 /*************************************************************************/
1775 /*************************************************************************/
1778 /**************************************************************************
1784 * Initializes a given glyph builder.
1788 * A pointer to the glyph builder to initialize.
1792 * The current face object.
1795 * The current size object.
1798 * The current glyph object.
1801 * Whether hinting is active.
1803 FT_LOCAL_DEF( void )
1804 cff_builder_init( CFF_Builder* builder,
1807 CFF_GlyphSlot glyph,
1810 builder->path_begun = 0;
1811 builder->load_points = 1;
1813 builder->face = face;
1814 builder->glyph = glyph;
1815 builder->memory = face->root.memory;
1819 FT_GlyphLoader loader = glyph->root.internal->loader;
1822 builder->loader = loader;
1823 builder->base = &loader->base.outline;
1824 builder->current = &loader->current.outline;
1825 FT_GlyphLoader_Rewind( loader );
1827 builder->hints_globals = NULL;
1828 builder->hints_funcs = NULL;
1830 if ( hinting && size )
1832 FT_Size ftsize = FT_SIZE( size );
1833 CFF_Internal internal = (CFF_Internal)ftsize->internal->module_data;
1837 builder->hints_globals = (void *)internal->topfont;
1838 builder->hints_funcs = glyph->root.internal->glyph_hints;
1846 builder->left_bearing.x = 0;
1847 builder->left_bearing.y = 0;
1848 builder->advance.x = 0;
1849 builder->advance.y = 0;
1851 builder->funcs = cff_builder_funcs;
1855 /**************************************************************************
1861 * Finalizes a given glyph builder. Its contents can still be used
1862 * after the call, but the function saves important information
1863 * within the corresponding glyph slot.
1867 * A pointer to the glyph builder to finalize.
1869 FT_LOCAL_DEF( void )
1870 cff_builder_done( CFF_Builder* builder )
1872 CFF_GlyphSlot glyph = builder->glyph;
1876 glyph->root.outline = *builder->base;
1880 /* check that there is enough space for `count' more points */
1881 FT_LOCAL_DEF( FT_Error )
1882 cff_check_points( CFF_Builder* builder,
1885 return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
1889 /* add a new point, do not check space */
1890 FT_LOCAL_DEF( void )
1891 cff_builder_add_point( CFF_Builder* builder,
1896 FT_Outline* outline = builder->current;
1899 if ( builder->load_points )
1901 FT_Vector* point = outline->points + outline->n_points;
1902 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
1904 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
1905 PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face );
1908 if ( driver->hinting_engine == FT_HINTING_FREETYPE )
1916 /* cf2_decoder_parse_charstrings uses 16.16 coordinates */
1920 *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
1923 outline->n_points++;
1927 /* check space for a new on-curve point, then add it */
1928 FT_LOCAL_DEF( FT_Error )
1929 cff_builder_add_point1( CFF_Builder* builder,
1936 error = cff_check_points( builder, 1 );
1938 cff_builder_add_point( builder, x, y, 1 );
1944 /* check space for a new contour, then add it */
1945 FT_LOCAL_DEF( FT_Error )
1946 cff_builder_add_contour( CFF_Builder* builder )
1948 FT_Outline* outline = builder->current;
1952 if ( !builder->load_points )
1954 outline->n_contours++;
1958 error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
1961 if ( outline->n_contours > 0 )
1962 outline->contours[outline->n_contours - 1] =
1963 (short)( outline->n_points - 1 );
1965 outline->n_contours++;
1972 /* if a path was begun, add its first on-curve point */
1973 FT_LOCAL_DEF( FT_Error )
1974 cff_builder_start_point( CFF_Builder* builder,
1978 FT_Error error = FT_Err_Ok;
1981 /* test whether we are building a new contour */
1982 if ( !builder->path_begun )
1984 builder->path_begun = 1;
1985 error = cff_builder_add_contour( builder );
1987 error = cff_builder_add_point1( builder, x, y );
1994 /* close the current contour */
1995 FT_LOCAL_DEF( void )
1996 cff_builder_close_contour( CFF_Builder* builder )
1998 FT_Outline* outline = builder->current;
2005 first = outline->n_contours <= 1
2006 ? 0 : outline->contours[outline->n_contours - 2] + 1;
2008 /* in malformed fonts it can happen that a contour was started */
2009 /* but no points were added */
2010 if ( outline->n_contours && first == outline->n_points )
2012 outline->n_contours--;
2016 /* We must not include the last point in the path if it */
2017 /* is located on the first point. */
2018 if ( outline->n_points > 1 )
2020 FT_Vector* p1 = outline->points + first;
2021 FT_Vector* p2 = outline->points + outline->n_points - 1;
2022 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;
2025 /* `delete' last point only if it coincides with the first */
2026 /* point and if it is not a control point (which can happen). */
2027 if ( p1->x == p2->x && p1->y == p2->y )
2028 if ( *control == FT_CURVE_TAG_ON )
2029 outline->n_points--;
2032 if ( outline->n_contours > 0 )
2034 /* Don't add contours only consisting of one point, i.e., */
2035 /* check whether begin point and last point are the same. */
2036 if ( first == outline->n_points - 1 )
2038 outline->n_contours--;
2039 outline->n_points--;
2042 outline->contours[outline->n_contours - 1] =
2043 (short)( outline->n_points - 1 );
2048 /*************************************************************************/
2049 /*************************************************************************/
2051 /***** PS BUILDER *****/
2053 /*************************************************************************/
2054 /*************************************************************************/
2056 /**************************************************************************
2062 * Initializes a given glyph builder.
2066 * A pointer to the glyph builder to initialize.
2070 * The current face object.
2073 * The current size object.
2076 * The current glyph object.
2079 * Whether hinting should be applied.
2081 FT_LOCAL_DEF( void )
2082 ps_builder_init( PS_Builder* ps_builder,
2086 FT_ZERO( ps_builder );
2090 T1_Builder t1builder = (T1_Builder)builder;
2093 ps_builder->memory = t1builder->memory;
2094 ps_builder->face = (FT_Face)t1builder->face;
2095 ps_builder->glyph = (CFF_GlyphSlot)t1builder->glyph;
2096 ps_builder->loader = t1builder->loader;
2097 ps_builder->base = t1builder->base;
2098 ps_builder->current = t1builder->current;
2100 ps_builder->pos_x = &t1builder->pos_x;
2101 ps_builder->pos_y = &t1builder->pos_y;
2103 ps_builder->left_bearing = &t1builder->left_bearing;
2104 ps_builder->advance = &t1builder->advance;
2106 ps_builder->bbox = &t1builder->bbox;
2107 ps_builder->path_begun = 0;
2108 ps_builder->load_points = t1builder->load_points;
2109 ps_builder->no_recurse = t1builder->no_recurse;
2111 ps_builder->metrics_only = t1builder->metrics_only;
2115 CFF_Builder* cffbuilder = (CFF_Builder*)builder;
2118 ps_builder->memory = cffbuilder->memory;
2119 ps_builder->face = (FT_Face)cffbuilder->face;
2120 ps_builder->glyph = cffbuilder->glyph;
2121 ps_builder->loader = cffbuilder->loader;
2122 ps_builder->base = cffbuilder->base;
2123 ps_builder->current = cffbuilder->current;
2125 ps_builder->pos_x = &cffbuilder->pos_x;
2126 ps_builder->pos_y = &cffbuilder->pos_y;
2128 ps_builder->left_bearing = &cffbuilder->left_bearing;
2129 ps_builder->advance = &cffbuilder->advance;
2131 ps_builder->bbox = &cffbuilder->bbox;
2132 ps_builder->path_begun = cffbuilder->path_begun;
2133 ps_builder->load_points = cffbuilder->load_points;
2134 ps_builder->no_recurse = cffbuilder->no_recurse;
2136 ps_builder->metrics_only = cffbuilder->metrics_only;
2139 ps_builder->is_t1 = is_t1;
2140 ps_builder->funcs = ps_builder_funcs;
2144 /**************************************************************************
2150 * Finalizes a given glyph builder. Its contents can still be used
2151 * after the call, but the function saves important information
2152 * within the corresponding glyph slot.
2156 * A pointer to the glyph builder to finalize.
2158 FT_LOCAL_DEF( void )
2159 ps_builder_done( PS_Builder* builder )
2161 CFF_GlyphSlot glyph = builder->glyph;
2165 glyph->root.outline = *builder->base;
2169 /* check that there is enough space for `count' more points */
2170 FT_LOCAL_DEF( FT_Error )
2171 ps_builder_check_points( PS_Builder* builder,
2174 return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
2178 /* add a new point, do not check space */
2179 FT_LOCAL_DEF( void )
2180 ps_builder_add_point( PS_Builder* builder,
2185 FT_Outline* outline = builder->current;
2188 if ( builder->load_points )
2190 FT_Vector* point = outline->points + outline->n_points;
2191 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
2193 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
2194 PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face );
2197 if ( !builder->is_t1 &&
2198 driver->hinting_engine == FT_HINTING_FREETYPE )
2205 #ifdef T1_CONFIG_OPTION_OLD_ENGINE
2206 #ifndef CFF_CONFIG_OPTION_OLD_ENGINE
2207 PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face );
2209 if ( builder->is_t1 &&
2210 driver->hinting_engine == FT_HINTING_FREETYPE )
2212 point->x = FIXED_TO_INT( x );
2213 point->y = FIXED_TO_INT( y );
2218 /* cf2_decoder_parse_charstrings uses 16.16 coordinates */
2222 *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
2224 outline->n_points++;
2228 /* check space for a new on-curve point, then add it */
2229 FT_LOCAL_DEF( FT_Error )
2230 ps_builder_add_point1( PS_Builder* builder,
2237 error = ps_builder_check_points( builder, 1 );
2239 ps_builder_add_point( builder, x, y, 1 );
2245 /* check space for a new contour, then add it */
2246 FT_LOCAL_DEF( FT_Error )
2247 ps_builder_add_contour( PS_Builder* builder )
2249 FT_Outline* outline = builder->current;
2253 /* this might happen in invalid fonts */
2256 FT_ERROR(( "ps_builder_add_contour: no outline to add points to\n" ));
2257 return FT_THROW( Invalid_File_Format );
2260 if ( !builder->load_points )
2262 outline->n_contours++;
2266 error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
2269 if ( outline->n_contours > 0 )
2270 outline->contours[outline->n_contours - 1] =
2271 (short)( outline->n_points - 1 );
2273 outline->n_contours++;
2280 /* if a path was begun, add its first on-curve point */
2281 FT_LOCAL_DEF( FT_Error )
2282 ps_builder_start_point( PS_Builder* builder,
2286 FT_Error error = FT_Err_Ok;
2289 /* test whether we are building a new contour */
2290 if ( !builder->path_begun )
2292 builder->path_begun = 1;
2293 error = ps_builder_add_contour( builder );
2295 error = ps_builder_add_point1( builder, x, y );
2302 /* close the current contour */
2303 FT_LOCAL_DEF( void )
2304 ps_builder_close_contour( PS_Builder* builder )
2306 FT_Outline* outline = builder->current;
2313 first = outline->n_contours <= 1
2314 ? 0 : outline->contours[outline->n_contours - 2] + 1;
2316 /* in malformed fonts it can happen that a contour was started */
2317 /* but no points were added */
2318 if ( outline->n_contours && first == outline->n_points )
2320 outline->n_contours--;
2324 /* We must not include the last point in the path if it */
2325 /* is located on the first point. */
2326 if ( outline->n_points > 1 )
2328 FT_Vector* p1 = outline->points + first;
2329 FT_Vector* p2 = outline->points + outline->n_points - 1;
2330 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;
2333 /* `delete' last point only if it coincides with the first */
2334 /* point and it is not a control point (which can happen). */
2335 if ( p1->x == p2->x && p1->y == p2->y )
2336 if ( *control == FT_CURVE_TAG_ON )
2337 outline->n_points--;
2340 if ( outline->n_contours > 0 )
2342 /* Don't add contours only consisting of one point, i.e., */
2343 /* check whether the first and the last point is the same. */
2344 if ( first == outline->n_points - 1 )
2346 outline->n_contours--;
2347 outline->n_points--;
2350 outline->contours[outline->n_contours - 1] =
2351 (short)( outline->n_points - 1 );
2356 /*************************************************************************/
2357 /*************************************************************************/
2361 /*************************************************************************/
2362 /*************************************************************************/
2365 /**************************************************************************
2371 * Creates a wrapper decoder for use in the combined
2372 * Type 1 / CFF interpreter.
2376 * A pointer to the decoder to initialize.
2380 * A pointer to the original decoder.
2383 * Flag indicating Type 1 or CFF
2385 FT_LOCAL_DEF( void )
2386 ps_decoder_init( PS_Decoder* ps_decoder,
2390 FT_ZERO( ps_decoder );
2394 T1_Decoder t1_decoder = (T1_Decoder)decoder;
2397 ps_builder_init( &ps_decoder->builder,
2398 &t1_decoder->builder,
2401 ps_decoder->cf2_instance = &t1_decoder->cf2_instance;
2402 ps_decoder->psnames = t1_decoder->psnames;
2404 ps_decoder->num_glyphs = t1_decoder->num_glyphs;
2405 ps_decoder->glyph_names = t1_decoder->glyph_names;
2406 ps_decoder->hint_mode = t1_decoder->hint_mode;
2407 ps_decoder->blend = t1_decoder->blend;
2409 ps_decoder->num_locals = (FT_UInt)t1_decoder->num_subrs;
2410 ps_decoder->locals = t1_decoder->subrs;
2411 ps_decoder->locals_len = t1_decoder->subrs_len;
2412 ps_decoder->locals_hash = t1_decoder->subrs_hash;
2414 ps_decoder->buildchar = t1_decoder->buildchar;
2415 ps_decoder->len_buildchar = t1_decoder->len_buildchar;
2417 ps_decoder->lenIV = t1_decoder->lenIV;
2421 CFF_Decoder* cff_decoder = (CFF_Decoder*)decoder;
2424 ps_builder_init( &ps_decoder->builder,
2425 &cff_decoder->builder,
2428 ps_decoder->cff = cff_decoder->cff;
2429 ps_decoder->cf2_instance = &cff_decoder->cff->cf2_instance;
2430 ps_decoder->current_subfont = cff_decoder->current_subfont;
2432 ps_decoder->num_globals = cff_decoder->num_globals;
2433 ps_decoder->globals = cff_decoder->globals;
2434 ps_decoder->globals_bias = cff_decoder->globals_bias;
2435 ps_decoder->num_locals = cff_decoder->num_locals;
2436 ps_decoder->locals = cff_decoder->locals;
2437 ps_decoder->locals_bias = cff_decoder->locals_bias;
2439 ps_decoder->glyph_width = &cff_decoder->glyph_width;
2440 ps_decoder->width_only = cff_decoder->width_only;
2442 ps_decoder->hint_mode = cff_decoder->hint_mode;
2444 ps_decoder->get_glyph_callback = cff_decoder->get_glyph_callback;
2445 ps_decoder->free_glyph_callback = cff_decoder->free_glyph_callback;
2450 /* Synthesize a SubFont object for Type 1 fonts, for use in the */
2451 /* new interpreter to access Private dict data. */
2452 FT_LOCAL_DEF( void )
2453 t1_make_subfont( FT_Face face,
2455 CFF_SubFont subfont )
2457 CFF_Private cpriv = &subfont->private_dict;
2464 count = cpriv->num_blue_values = priv->num_blue_values;
2465 for ( n = 0; n < count; n++ )
2466 cpriv->blue_values[n] = (FT_Pos)priv->blue_values[n];
2468 count = cpriv->num_other_blues = priv->num_other_blues;
2469 for ( n = 0; n < count; n++ )
2470 cpriv->other_blues[n] = (FT_Pos)priv->other_blues[n];
2472 count = cpriv->num_family_blues = priv->num_family_blues;
2473 for ( n = 0; n < count; n++ )
2474 cpriv->family_blues[n] = (FT_Pos)priv->family_blues[n];
2476 count = cpriv->num_family_other_blues = priv->num_family_other_blues;
2477 for ( n = 0; n < count; n++ )
2478 cpriv->family_other_blues[n] = (FT_Pos)priv->family_other_blues[n];
2480 cpriv->blue_scale = priv->blue_scale;
2481 cpriv->blue_shift = (FT_Pos)priv->blue_shift;
2482 cpriv->blue_fuzz = (FT_Pos)priv->blue_fuzz;
2484 cpriv->standard_width = (FT_Pos)priv->standard_width[0];
2485 cpriv->standard_height = (FT_Pos)priv->standard_height[0];
2487 count = cpriv->num_snap_widths = priv->num_snap_widths;
2488 for ( n = 0; n < count; n++ )
2489 cpriv->snap_widths[n] = (FT_Pos)priv->snap_widths[n];
2491 count = cpriv->num_snap_heights = priv->num_snap_heights;
2492 for ( n = 0; n < count; n++ )
2493 cpriv->snap_heights[n] = (FT_Pos)priv->snap_heights[n];
2495 cpriv->force_bold = priv->force_bold;
2496 cpriv->lenIV = priv->lenIV;
2497 cpriv->language_group = priv->language_group;
2498 cpriv->expansion_factor = priv->expansion_factor;
2500 cpriv->subfont = subfont;
2503 /* Initialize the random number generator. */
2504 if ( face->internal->random_seed != -1 )
2506 /* If we have a face-specific seed, use it. */
2507 /* If non-zero, update it to a positive value. */
2508 subfont->random = (FT_UInt32)face->internal->random_seed;
2509 if ( face->internal->random_seed )
2513 face->internal->random_seed = (FT_Int32)cff_random(
2514 (FT_UInt32)face->internal->random_seed );
2516 } while ( face->internal->random_seed < 0 );
2519 if ( !subfont->random )
2524 /* compute random seed from some memory addresses */
2525 seed = (FT_UInt32)( (FT_Offset)(char*)&seed ^
2526 (FT_Offset)(char*)&face ^
2527 (FT_Offset)(char*)&subfont );
2528 seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 );
2532 subfont->random = seed;
2537 FT_LOCAL_DEF( void )
2538 t1_decrypt( FT_Byte* buffer,
2542 PS_Conv_EexecDecode( &buffer,
2543 FT_OFFSET( buffer, length ),
2550 FT_LOCAL_DEF( FT_UInt32 )
2551 cff_random( FT_UInt32 r )
2553 /* a 32bit version of the `xorshift' algorithm */