1
/***************************************************************************/
5
/* Auxiliary functions for PostScript fonts (body). */
7
/* Copyright 1996-2001, 2002, 2003, 2004 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
28
/*************************************************************************/
29
/*************************************************************************/
31
/***** PS_TABLE *****/
33
/*************************************************************************/
34
/*************************************************************************/
36
/*************************************************************************/
42
/* Initializes a PS_Table. */
45
/* table :: The address of the target table. */
48
/* count :: The table size = the maximum number of elements. */
50
/* memory :: The memory object to use for all subsequent */
54
/* FreeType error code. 0 means success. */
56
FT_LOCAL_DEF( FT_Error )
57
ps_table_new( PS_Table table,
64
table->memory = memory;
65
if ( FT_NEW_ARRAY( table->elements, count ) ||
66
FT_NEW_ARRAY( table->lengths, count ) )
69
table->max_elems = count;
70
table->init = 0xDEADBEEFUL;
76
*(PS_Table_FuncsRec*)&table->funcs = ps_table_funcs;
80
FT_FREE( table->elements );
87
shift_elements( PS_Table table,
90
FT_Long delta = (FT_Long)( table->block - old_base );
91
FT_Byte** offset = table->elements;
92
FT_Byte** limit = offset + table->max_elems;
95
for ( ; offset < limit; offset++ )
104
reallocate_t1_table( PS_Table table,
107
FT_Memory memory = table->memory;
108
FT_Byte* old_base = table->block;
112
/* allocate new base block */
113
if ( FT_ALLOC( table->block, new_size ) )
115
table->block = old_base;
119
/* copy elements and shift offsets */
122
FT_MEM_COPY( table->block, old_base, table->capacity );
123
shift_elements( table, old_base );
127
table->capacity = new_size;
133
/*************************************************************************/
139
/* Adds an object to a PS_Table, possibly growing its memory block. */
142
/* table :: The target table. */
145
/* idx :: The index of the object in the table. */
147
/* object :: The address of the object to copy in memory. */
149
/* length :: The length in bytes of the source object. */
152
/* FreeType error code. 0 means success. An error is returned if a */
153
/* reallocation fails. */
155
FT_LOCAL_DEF( FT_Error )
156
ps_table_add( PS_Table table,
161
if ( idx < 0 || idx > table->max_elems )
163
FT_ERROR(( "ps_table_add: invalid index\n" ));
164
return PSaux_Err_Invalid_Argument;
167
/* grow the base block if needed */
168
if ( table->cursor + length > table->capacity )
171
FT_Offset new_size = table->capacity;
175
in_offset = (FT_Long)((FT_Byte*)object - table->block);
176
if ( (FT_ULong)in_offset >= table->capacity )
179
while ( new_size < table->cursor + length )
181
/* increase size by 25% and round up to the nearest multiple
183
new_size += ( new_size >> 2 ) + 1;
184
new_size = FT_PAD_CEIL( new_size, 1024 );
187
error = reallocate_t1_table( table, new_size );
191
if ( in_offset >= 0 )
192
object = table->block + in_offset;
195
/* add the object to the base block and adjust offset */
196
table->elements[idx] = table->block + table->cursor;
197
table->lengths [idx] = length;
198
FT_MEM_COPY( table->block + table->cursor, object, length );
200
table->cursor += length;
205
/*************************************************************************/
211
/* Finalizes a PS_TableRec (i.e., reallocate it to its current */
215
/* table :: The target table. */
218
/* This function does NOT release the heap's memory block. It is up */
219
/* to the caller to clean it, or reference it in its own structures. */
222
ps_table_done( PS_Table table )
224
FT_Memory memory = table->memory;
226
FT_Byte* old_base = table->block;
229
/* should never fail, because rec.cursor <= rec.size */
233
if ( FT_ALLOC( table->block, table->cursor ) )
235
FT_MEM_COPY( table->block, old_base, table->cursor );
236
shift_elements( table, old_base );
238
table->capacity = table->cursor;
246
ps_table_release( PS_Table table )
248
FT_Memory memory = table->memory;
251
if ( (FT_ULong)table->init == 0xDEADBEEFUL )
253
FT_FREE( table->block );
254
FT_FREE( table->elements );
255
FT_FREE( table->lengths );
261
/*************************************************************************/
262
/*************************************************************************/
264
/***** T1 PARSER *****/
266
/*************************************************************************/
267
/*************************************************************************/
269
/* In the PostScript Language Reference Manual (PLRM) the following */
270
/* characters are called `whitespace characters'. */
271
#define IS_T1_WHITESPACE( c ) ( (c) == ' ' || (c) == '\t' )
272
#define IS_T1_LINESPACE( c ) ( (c) == '\r' || (c) == '\n' || (c) == '\f' )
273
#define IS_T1_NULLSPACE( c ) ( (c) == '\0' )
275
/* According to the PLRM all whitespace characters are equivalent, */
276
/* except in comments and strings. */
277
#define IS_T1_SPACE( c ) ( IS_T1_WHITESPACE( c ) || \
278
IS_T1_LINESPACE( c ) || \
279
IS_T1_NULLSPACE( c ) )
282
/* The following array is used by various functions to quickly convert */
283
/* digits (both decimal and non-decimal) into numbers. */
288
static const char ft_char_table[128] =
291
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
292
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
293
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
294
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
295
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
296
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
297
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
298
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
301
/* no character >= 0x80 can represent a valid number */
304
#endif /* 'A' == 65 */
309
static const char ft_char_table[128] =
312
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,
313
-1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
314
-1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
315
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
316
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, -1, -1, -1, -1, -1, -1,
317
-1, 19, 20, 21, 22, 23, 24, 25, 26, 27, -1, -1, -1, -1, -1, -1,
318
-1, -1, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, -1,
319
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
322
/* no character < 0x80 can represent a valid number */
325
#endif /* 'A' == 193 */
328
/* first character must be already part of the comment */
331
skip_comment( FT_Byte* *acur,
334
FT_Byte* cur = *acur;
337
while ( cur < limit )
339
if ( IS_T1_LINESPACE( *cur ) )
349
skip_spaces( FT_Byte* *acur,
352
FT_Byte* cur = *acur;
355
while ( cur < limit )
357
if ( !IS_T1_SPACE( *cur ) )
360
/* According to the PLRM, a comment is equal to a space. */
361
skip_comment( &cur, limit );
372
/* first character must be `(' */
375
skip_literal_string( FT_Byte* *acur,
378
FT_Byte* cur = *acur;
382
while ( cur < limit )
386
else if ( *cur == '(' )
388
else if ( *cur == ')' )
404
/* first character must be `<' */
407
skip_string( PS_Parser parser )
409
FT_Byte* cur = parser->cursor;
410
FT_Byte* limit = parser->limit;
413
while ( ++cur < limit )
418
/* All whitespace characters are ignored. */
419
skip_spaces( &cur, limit );
426
d = ft_char_table[*cur & 0x7F];
427
if ( d < 0 || d >= 16 )
431
if ( cur < limit && *cur != '>' )
432
parser->error = PSaux_Err_Invalid_File_Format;
436
parser->cursor = cur;
440
/***********************************************************************/
442
/* All exported parsing routines handle leading whitespace and stop at */
443
/* the first character which isn't part of the just handled token. */
445
/***********************************************************************/
449
ps_parser_skip_PS_token( PS_Parser parser )
451
/* Note: PostScript allows any non-delimiting, non-whitespace */
452
/* character in a name (PS Ref Manual, 3rd ed, p31). */
453
/* PostScript delimiters are (, ), <, >, [, ], {, }, /, and %. */
455
FT_Byte* cur = parser->cursor;
456
FT_Byte* limit = parser->limit;
459
skip_spaces( &cur, limit ); /* this also skips comments */
463
/* self-delimiting, single-character tokens */
464
if ( *cur == '[' || *cur == ']' ||
465
*cur == '{' || *cur == '}' )
471
if ( *cur == '(' ) /* (...) */
473
skip_literal_string( &cur, limit );
477
if ( *cur == '<' ) /* <...> */
479
if ( cur + 1 < limit && *(cur + 1) == '<' ) /* << */
485
parser->cursor = cur;
486
skip_string( parser );
493
if ( cur >= limit || *cur != '>' ) /* >> */
495
parser->error = PSaux_Err_Invalid_File_Format;
506
while ( cur < limit )
508
if ( IS_T1_SPACE( *cur ) ||
512
*cur == '[' || *cur == ']' ||
513
*cur == '{' || *cur == '}' ||
514
*cur == '<' || *cur == '>' )
519
parser->error = PSaux_Err_Invalid_File_Format;
527
parser->cursor = cur;
532
ps_parser_skip_spaces( PS_Parser parser )
534
skip_spaces( &parser->cursor, parser->limit );
538
/* `token' here means either something between balanced delimiters */
539
/* or the next token; the delimiters are not removed. */
542
ps_parser_to_token( PS_Parser parser,
547
FT_Byte starter, ender;
551
token->type = T1_TOKEN_TYPE_NONE;
555
/* first of all, skip leading whitespace */
556
ps_parser_skip_spaces( parser );
558
cur = parser->cursor;
559
limit = parser->limit;
566
/************* check for literal string *****************/
568
token->type = T1_TOKEN_TYPE_STRING;
570
skip_literal_string( &cur, limit );
575
/************* check for programs/array *****************/
577
token->type = T1_TOKEN_TYPE_ARRAY;
581
/************* check for table/array ********************/
583
token->type = T1_TOKEN_TYPE_ARRAY;
590
token->start = cur++;
592
/* we need this to catch `[ ]' */
593
parser->cursor = cur;
594
ps_parser_skip_spaces( parser );
595
cur = parser->cursor;
597
while ( cur < limit && !parser->error )
599
if ( *cur == starter )
601
else if ( *cur == ender )
606
token->limit = ++cur;
611
parser->cursor = cur;
612
ps_parser_skip_PS_token( parser );
613
/* we need this to catch `[XXX ]' */
614
ps_parser_skip_spaces ( parser );
615
cur = parser->cursor;
619
/* ************ otherwise, it is any token **************/
622
token->type = T1_TOKEN_TYPE_ANY;
623
ps_parser_skip_PS_token( parser );
624
cur = parser->cursor;
625
if ( !parser->error )
632
token->type = T1_TOKEN_TYPE_NONE;
635
parser->cursor = cur;
640
ps_parser_to_token_array( PS_Parser parser,
643
FT_Int* pnum_tokens )
650
/* this also handles leading whitespace */
651
ps_parser_to_token( parser, &master );
653
if ( master.type == T1_TOKEN_TYPE_ARRAY )
655
FT_Byte* old_cursor = parser->cursor;
656
FT_Byte* old_limit = parser->limit;
657
T1_Token cur = tokens;
658
T1_Token limit = cur + max_tokens;
661
/* don't include outermost delimiters */
662
parser->cursor = master.start + 1;
663
parser->limit = master.limit - 1;
665
while ( parser->cursor < parser->limit )
670
ps_parser_to_token( parser, &token );
680
*pnum_tokens = (FT_Int)( cur - tokens );
682
parser->cursor = old_cursor;
683
parser->limit = old_limit;
688
/* first character must be already part of the number */
691
ps_radix( FT_Long radixBase,
696
FT_Byte* cur = *acur;
699
if ( radixBase < 2 || radixBase > 36 )
702
while ( cur < limit )
710
d = ft_char_table[*cur & 0x7F];
711
if ( d < 0 || d >= radixBase )
714
result = result * radixBase + d;
725
/* first character must be already part of the number */
728
ps_toint( FT_Byte* *acur,
732
FT_Byte* cur = *acur;
743
while ( cur < limit )
751
result = ps_radix( result, &cur, limit );
758
d = ft_char_table[*cur & 0x7F];
759
if ( d < 0 || d >= 10 )
761
result = result * 10 + d;
775
/* first character must be `<' if `delimiters' is non-zero */
778
ps_tobytes( FT_Byte* *acur,
785
FT_Error error = PSaux_Err_Ok;
787
FT_Byte* cur = *acur;
798
error = PSaux_Err_Invalid_File_Format;
805
max_bytes = max_bytes * 2;
807
for ( n = 0; cur < limit; n++, cur++ )
812
if ( n >= max_bytes )
816
/* All whitespace characters are ignored. */
817
skip_spaces( &cur, limit );
824
d = ft_char_table[*cur & 0x7F];
825
if ( d < 0 || d >= 16 )
828
/* <f> == <f0> != <0f> */
829
bytes[n / 2] = (FT_Byte)( ( n % 2 ) ? bytes[n / 2] + d
835
if ( cur < limit && *cur != '>' )
837
error = PSaux_Err_Invalid_File_Format;
847
*pnum_bytes = ( n + 1 ) / 2;
853
/* first character must be already part of the number */
856
ps_tofixed( FT_Byte* *acur,
860
FT_Byte* cur = *acur;
861
FT_Long num, divider, result;
868
/* first of all, check the sign */
869
if ( *cur == '-' && cur + 1 < limit )
875
/* then, read the integer part, if any */
877
result = ps_toint( &cur, limit ) << 16;
887
/* read decimal part, if any */
888
if ( *cur == '.' && cur + 1 < limit )
900
d = ft_char_table[*cur & 0x7F];
901
if ( d < 0 || d >= 10 )
904
if ( divider < 10000000L )
916
/* read exponent, if any */
917
if ( cur + 1 < limit && ( *cur == 'e' || *cur == 'E' ) )
920
power_ten += ps_toint( &cur, limit );
924
/* raise to power of ten if needed */
925
while ( power_ten > 0 )
927
result = result * 10;
932
while ( power_ten < 0 )
934
result = result / 10;
935
divider = divider * 10;
940
result += FT_DivFix( num, divider );
950
/* first character must be a delimiter or a part of a number */
953
ps_tocoordarray( FT_Byte* *acur,
958
FT_Byte* cur = *acur;
966
/* check for the beginning of an array; otherwise, only one number */
980
/* now, read the coordinates */
981
while ( cur < limit )
983
/* skip whitespace in front of data */
984
skip_spaces( &cur, limit );
988
if ( count >= max_coords )
997
coords[count] = (FT_Short)( ps_tofixed( &cur, limit, 0 ) >> 16 );
1010
/* first character must be a delimiter or a part of a number */
1013
ps_tofixedarray( FT_Byte* *acur,
1019
FT_Byte* cur = *acur;
1027
/* Check for the beginning of an array. Otherwise, only one number */
1041
/* now, read the values */
1042
while ( cur < limit )
1044
/* skip whitespace in front of data */
1045
skip_spaces( &cur, limit );
1049
if ( count >= max_values )
1058
values[count] = ps_tofixed( &cur, limit, power_ten );
1074
ps_tostring( FT_Byte** cursor,
1078
FT_Byte* cur = *cursor;
1085
/* XXX: some stupid fonts have a `Notice' or `Copyright' string */
1086
/* that simply doesn't begin with an opening parenthesis, even */
1087
/* though they have a closing one! E.g. "amuncial.pfb" */
1089
/* We must deal with these ill-fated cases there. Note that */
1090
/* these fonts didn't work with the old Type 1 driver as the */
1091
/* notice/copyright was not recognized as a valid string token */
1092
/* and made the old token parser commit errors. */
1094
while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) )
1096
if ( cur + 1 >= limit )
1100
cur++; /* skip the opening parenthesis, if there is one */
1105
/* then, count its length */
1106
for ( ; cur < limit; cur++ )
1111
else if ( *cur == ')' )
1119
len = cur - *cursor;
1120
if ( cur >= limit || FT_ALLOC( result, len + 1 ) )
1123
/* now copy the string */
1124
FT_MEM_COPY( result, *cursor, len );
1134
ps_tobool( FT_Byte* *acur,
1137
FT_Byte* cur = *acur;
1141
/* return 1 if we find `true', 0 otherwise */
1142
if ( cur + 3 < limit &&
1151
else if ( cur + 4 < limit &&
1167
/* load a simple field (i.e. non-table) into the current list of objects */
1169
FT_LOCAL_DEF( FT_Error )
1170
ps_parser_load_field( PS_Parser parser,
1171
const T1_Field field,
1173
FT_UInt max_objects,
1184
/* this also skips leading whitespace */
1185
ps_parser_to_token( parser, &token );
1192
limit = token.limit;
1194
/* we must detect arrays in /FontBBox */
1195
if ( field->type == T1_FIELD_TYPE_BBOX )
1198
FT_Byte* old_cur = parser->cursor;
1199
FT_Byte* old_limit = parser->limit;
1202
/* don't include delimiters */
1203
parser->cursor = token.start + 1;
1204
parser->limit = token.limit - 1;
1206
ps_parser_to_token( parser, &token2 );
1207
parser->cursor = old_cur;
1208
parser->limit = old_limit;
1210
if ( token2.type == T1_TOKEN_TYPE_ARRAY )
1213
else if ( token.type == T1_TOKEN_TYPE_ARRAY )
1216
/* if this is an array and we have no blend, an error occurs */
1217
if ( max_objects == 0 )
1220
count = max_objects;
1223
/* don't include delimiters */
1228
for ( ; count > 0; count--, idx++ )
1230
FT_Byte* q = (FT_Byte*)objects[idx] + field->offset;
1235
skip_spaces( &cur, limit );
1237
switch ( field->type )
1239
case T1_FIELD_TYPE_BOOL:
1240
val = ps_tobool( &cur, limit );
1243
case T1_FIELD_TYPE_FIXED:
1244
val = ps_tofixed( &cur, limit, 0 );
1247
case T1_FIELD_TYPE_FIXED_1000:
1248
val = ps_tofixed( &cur, limit, 3 );
1251
case T1_FIELD_TYPE_INTEGER:
1252
val = ps_toint( &cur, limit );
1256
switch ( field->size )
1258
case (8 / FT_CHAR_BIT):
1259
*(FT_Byte*)q = (FT_Byte)val;
1262
case (16 / FT_CHAR_BIT):
1263
*(FT_UShort*)q = (FT_UShort)val;
1266
case (32 / FT_CHAR_BIT):
1267
*(FT_UInt32*)q = (FT_UInt32)val;
1270
default: /* for 64-bit systems */
1275
case T1_FIELD_TYPE_STRING:
1276
case T1_FIELD_TYPE_KEY:
1278
FT_Memory memory = parser->memory;
1279
FT_UInt len = (FT_UInt)( limit - cur );
1285
if ( field->type == T1_FIELD_TYPE_KEY )
1287
/* don't include leading `/' */
1293
/* don't include delimiting parentheses */
1298
if ( FT_ALLOC( string, len + 1 ) )
1301
FT_MEM_COPY( string, cur, len );
1304
*(FT_String**)q = string;
1308
case T1_FIELD_TYPE_BBOX:
1311
FT_BBox* bbox = (FT_BBox*)q;
1314
(void)ps_tofixedarray( &token.start, token.limit, 4, temp, 0 );
1316
bbox->xMin = FT_RoundFix( temp[0] );
1317
bbox->yMin = FT_RoundFix( temp[1] );
1318
bbox->xMax = FT_RoundFix( temp[2] );
1319
bbox->yMax = FT_RoundFix( temp[3] );
1324
/* an error occured */
1329
#if 0 /* obsolete -- keep for reference */
1331
*pflags |= 1L << field->flag_bit;
1333
FT_UNUSED( pflags );
1336
error = PSaux_Err_Ok;
1342
error = PSaux_Err_Invalid_File_Format;
1347
#define T1_MAX_TABLE_ELEMENTS 32
1350
FT_LOCAL_DEF( FT_Error )
1351
ps_parser_load_field_table( PS_Parser parser,
1352
const T1_Field field,
1354
FT_UInt max_objects,
1357
T1_TokenRec elements[T1_MAX_TABLE_ELEMENTS];
1359
FT_Int num_elements;
1360
FT_Error error = PSaux_Err_Ok;
1361
FT_Byte* old_cursor;
1363
T1_FieldRec fieldrec = *(T1_Field)field;
1367
fieldrec.type = T1_FIELD_TYPE_INTEGER;
1368
if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY )
1369
fieldrec.type = T1_FIELD_TYPE_FIXED;
1372
ps_parser_to_token_array( parser, elements,
1373
T1_MAX_TABLE_ELEMENTS, &num_elements );
1374
if ( num_elements < 0 )
1376
error = PSaux_Err_Ignore;
1379
if ( num_elements > T1_MAX_TABLE_ELEMENTS )
1380
num_elements = T1_MAX_TABLE_ELEMENTS;
1382
old_cursor = parser->cursor;
1383
old_limit = parser->limit;
1385
/* we store the elements count */
1386
*(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =
1387
(FT_Byte)num_elements;
1389
/* we now load each element, adjusting the field.offset on each one */
1391
for ( ; num_elements > 0; num_elements--, token++ )
1393
parser->cursor = token->start;
1394
parser->limit = token->limit;
1395
ps_parser_load_field( parser, &fieldrec, objects, max_objects, 0 );
1396
fieldrec.offset += fieldrec.size;
1399
#if 0 /* obsolete -- keep for reference */
1401
*pflags |= 1L << field->flag_bit;
1403
FT_UNUSED( pflags );
1406
parser->cursor = old_cursor;
1407
parser->limit = old_limit;
1414
FT_LOCAL_DEF( FT_Long )
1415
ps_parser_to_int( PS_Parser parser )
1417
ps_parser_skip_spaces( parser );
1418
return ps_toint( &parser->cursor, parser->limit );
1422
FT_LOCAL_DEF( FT_Error )
1423
ps_parser_to_bytes( PS_Parser parser,
1426
FT_Long* pnum_bytes,
1427
FT_Bool delimiters )
1429
ps_parser_skip_spaces( parser );
1430
return ps_tobytes( &parser->cursor,
1439
FT_LOCAL_DEF( FT_Fixed )
1440
ps_parser_to_fixed( PS_Parser parser,
1443
ps_parser_skip_spaces( parser );
1444
return ps_tofixed( &parser->cursor, parser->limit, power_ten );
1448
FT_LOCAL_DEF( FT_Int )
1449
ps_parser_to_coord_array( PS_Parser parser,
1453
ps_parser_skip_spaces( parser );
1454
return ps_tocoordarray( &parser->cursor, parser->limit,
1455
max_coords, coords );
1459
FT_LOCAL_DEF( FT_Int )
1460
ps_parser_to_fixed_array( PS_Parser parser,
1465
ps_parser_skip_spaces( parser );
1466
return ps_tofixedarray( &parser->cursor, parser->limit,
1467
max_values, values, power_ten );
1473
FT_LOCAL_DEF( FT_String* )
1474
T1_ToString( PS_Parser parser )
1476
return ps_tostring( &parser->cursor, parser->limit, parser->memory );
1480
FT_LOCAL_DEF( FT_Bool )
1481
T1_ToBool( PS_Parser parser )
1483
return ps_tobool( &parser->cursor, parser->limit );
1489
FT_LOCAL_DEF( void )
1490
ps_parser_init( PS_Parser parser,
1495
parser->error = PSaux_Err_Ok;
1496
parser->base = base;
1497
parser->limit = limit;
1498
parser->cursor = base;
1499
parser->memory = memory;
1500
parser->funcs = ps_parser_funcs;
1504
FT_LOCAL_DEF( void )
1505
ps_parser_done( PS_Parser parser )
1507
FT_UNUSED( parser );
1511
/*************************************************************************/
1512
/*************************************************************************/
1514
/***** T1 BUILDER *****/
1516
/*************************************************************************/
1517
/*************************************************************************/
1519
/*************************************************************************/
1522
/* t1_builder_init */
1525
/* Initializes a given glyph builder. */
1528
/* builder :: A pointer to the glyph builder to initialize. */
1531
/* face :: The current face object. */
1533
/* size :: The current size object. */
1535
/* glyph :: The current glyph object. */
1537
/* hinting :: Whether hinting should be applied. */
1539
FT_LOCAL_DEF( void )
1540
t1_builder_init( T1_Builder builder,
1546
builder->parse_state = T1_Parse_Start;
1547
builder->load_points = 1;
1549
builder->face = face;
1550
builder->glyph = glyph;
1551
builder->memory = face->memory;
1555
FT_GlyphLoader loader = glyph->internal->loader;
1558
builder->loader = loader;
1559
builder->base = &loader->base.outline;
1560
builder->current = &loader->current.outline;
1561
FT_GlyphLoader_Rewind( loader );
1563
builder->hints_globals = size->internal;
1564
builder->hints_funcs = 0;
1567
builder->hints_funcs = glyph->internal->glyph_hints;
1572
builder->scale_x = size->metrics.x_scale;
1573
builder->scale_y = size->metrics.y_scale;
1579
builder->left_bearing.x = 0;
1580
builder->left_bearing.y = 0;
1581
builder->advance.x = 0;
1582
builder->advance.y = 0;
1584
builder->funcs = t1_builder_funcs;
1588
/*************************************************************************/
1591
/* t1_builder_done */
1594
/* Finalizes a given glyph builder. Its contents can still be used */
1595
/* after the call, but the function saves important information */
1596
/* within the corresponding glyph slot. */
1599
/* builder :: A pointer to the glyph builder to finalize. */
1601
FT_LOCAL_DEF( void )
1602
t1_builder_done( T1_Builder builder )
1604
FT_GlyphSlot glyph = builder->glyph;
1608
glyph->outline = *builder->base;
1612
/* check that there is enough space for `count' more points */
1613
FT_LOCAL_DEF( FT_Error )
1614
t1_builder_check_points( T1_Builder builder,
1617
return FT_GlyphLoader_CheckPoints( builder->loader, count, 0 );
1621
/* add a new point, do not check space */
1622
FT_LOCAL_DEF( void )
1623
t1_builder_add_point( T1_Builder builder,
1628
FT_Outline* outline = builder->current;
1631
if ( builder->load_points )
1633
FT_Vector* point = outline->points + outline->n_points;
1634
FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
1637
if ( builder->shift )
1644
*control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
1646
builder->last = *point;
1648
outline->n_points++;
1652
/* check space for a new on-curve point, then add it */
1653
FT_LOCAL_DEF( FT_Error )
1654
t1_builder_add_point1( T1_Builder builder,
1661
error = t1_builder_check_points( builder, 1 );
1663
t1_builder_add_point( builder, x, y, 1 );
1669
/* check space for a new contour, then add it */
1670
FT_LOCAL_DEF( FT_Error )
1671
t1_builder_add_contour( T1_Builder builder )
1673
FT_Outline* outline = builder->current;
1677
if ( !builder->load_points )
1679
outline->n_contours++;
1680
return PSaux_Err_Ok;
1683
error = FT_GlyphLoader_CheckPoints( builder->loader, 0, 1 );
1686
if ( outline->n_contours > 0 )
1687
outline->contours[outline->n_contours - 1] =
1688
(short)( outline->n_points - 1 );
1690
outline->n_contours++;
1697
/* if a path was begun, add its first on-curve point */
1698
FT_LOCAL_DEF( FT_Error )
1699
t1_builder_start_point( T1_Builder builder,
1703
FT_Error error = PSaux_Err_Invalid_File_Format;
1706
/* test whether we are building a new contour */
1708
if ( builder->parse_state == T1_Parse_Have_Path )
1709
error = PSaux_Err_Ok;
1710
else if ( builder->parse_state == T1_Parse_Have_Moveto )
1712
builder->parse_state = T1_Parse_Have_Path;
1713
error = t1_builder_add_contour( builder );
1715
error = t1_builder_add_point1( builder, x, y );
1722
/* close the current contour */
1723
FT_LOCAL_DEF( void )
1724
t1_builder_close_contour( T1_Builder builder )
1726
FT_Outline* outline = builder->current;
1729
/* XXXX: We must not include the last point in the path if it */
1730
/* is located on the first point. */
1731
if ( outline->n_points > 1 )
1734
FT_Vector* p1 = outline->points + first;
1735
FT_Vector* p2 = outline->points + outline->n_points - 1;
1736
FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;
1739
if ( outline->n_contours > 1 )
1741
first = outline->contours[outline->n_contours - 2] + 1;
1742
p1 = outline->points + first;
1745
/* `delete' last point only if it coincides with the first */
1746
/* point and it is not a control point (which can happen). */
1747
if ( p1->x == p2->x && p1->y == p2->y )
1748
if ( *control == FT_CURVE_TAG_ON )
1749
outline->n_points--;
1752
if ( outline->n_contours > 0 )
1753
outline->contours[outline->n_contours - 1] =
1754
(short)( outline->n_points - 1 );
1758
/*************************************************************************/
1759
/*************************************************************************/
1763
/*************************************************************************/
1764
/*************************************************************************/
1766
FT_LOCAL_DEF( void )
1767
t1_decrypt( FT_Byte* buffer,
1771
while ( length > 0 )
1776
plain = (FT_Byte)( *buffer ^ ( seed >> 8 ) );
1777
seed = (FT_UShort)( ( *buffer + seed ) * 52845U + 22719 );