📄 psobjs.c
字号:
FT_Fixed* values,
FT_Int power_ten )
{
FT_Byte* cur = *acur;
FT_Int count = 0;
FT_Byte c, ender;
if ( cur >= limit )
goto Exit;
/* Check for the beginning of an array. Otherwise, only one number */
/* will be read. */
c = *cur;
ender = 0;
if ( c == '[' )
ender = ']';
if ( c == '{' )
ender = '}';
if ( ender )
cur++;
/* now, read the values */
while ( cur < limit )
{
FT_Fixed dummy;
/* skip whitespace in front of data */
skip_spaces( &cur, limit );
if ( cur >= limit )
goto Exit;
if ( values != NULL && count >= max_values )
break;
if ( *cur == ender )
{
cur++;
break;
}
/* call PS_Conv_ToFixed() even if coords == NULL */
/* to properly parse number at `cur' */
*( values != NULL ? &values[count] : &dummy ) =
PS_Conv_ToFixed( &cur, limit, power_ten );
count++;
if ( !ender )
break;
}
Exit:
*acur = cur;
return count;
}
#if 0
static FT_String*
ps_tostring( FT_Byte** cursor,
FT_Byte* limit,
FT_Memory memory )
{
FT_Byte* cur = *cursor;
FT_PtrDist len = 0;
FT_Int count;
FT_String* result;
FT_Error error;
/* XXX: some stupid fonts have a `Notice' or `Copyright' string */
/* that simply doesn't begin with an opening parenthesis, even */
/* though they have a closing one! E.g. "amuncial.pfb" */
/* */
/* We must deal with these ill-fated cases there. Note that */
/* these fonts didn't work with the old Type 1 driver as the */
/* notice/copyright was not recognized as a valid string token */
/* and made the old token parser commit errors. */
while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) )
cur++;
if ( cur + 1 >= limit )
return 0;
if ( *cur == '(' )
cur++; /* skip the opening parenthesis, if there is one */
*cursor = cur;
count = 0;
/* then, count its length */
for ( ; cur < limit; cur++ )
{
if ( *cur == '(' )
count++;
else if ( *cur == ')' )
{
count--;
if ( count < 0 )
break;
}
}
len = cur - *cursor;
if ( cur >= limit || FT_ALLOC( result, len + 1 ) )
return 0;
/* now copy the string */
FT_MEM_COPY( result, *cursor, len );
result[len] = '\0';
*cursor = cur;
return result;
}
#endif /* 0 */
static int
ps_tobool( FT_Byte* *acur,
FT_Byte* limit )
{
FT_Byte* cur = *acur;
FT_Bool result = 0;
/* return 1 if we find `true', 0 otherwise */
if ( cur + 3 < limit &&
cur[0] == 't' &&
cur[1] == 'r' &&
cur[2] == 'u' &&
cur[3] == 'e' )
{
result = 1;
cur += 5;
}
else if ( cur + 4 < limit &&
cur[0] == 'f' &&
cur[1] == 'a' &&
cur[2] == 'l' &&
cur[3] == 's' &&
cur[4] == 'e' )
{
result = 0;
cur += 6;
}
*acur = cur;
return result;
}
/* load a simple field (i.e. non-table) into the current list of objects */
FT_LOCAL_DEF( FT_Error )
ps_parser_load_field( PS_Parser parser,
const T1_Field field,
void** objects,
FT_UInt max_objects,
FT_ULong* pflags )
{
T1_TokenRec token;
FT_Byte* cur;
FT_Byte* limit;
FT_UInt count;
FT_UInt idx;
FT_Error error;
/* this also skips leading whitespace */
ps_parser_to_token( parser, &token );
if ( !token.type )
goto Fail;
count = 1;
idx = 0;
cur = token.start;
limit = token.limit;
/* we must detect arrays in /FontBBox */
if ( field->type == T1_FIELD_TYPE_BBOX )
{
T1_TokenRec token2;
FT_Byte* old_cur = parser->cursor;
FT_Byte* old_limit = parser->limit;
/* don't include delimiters */
parser->cursor = token.start + 1;
parser->limit = token.limit - 1;
ps_parser_to_token( parser, &token2 );
parser->cursor = old_cur;
parser->limit = old_limit;
if ( token2.type == T1_TOKEN_TYPE_ARRAY )
goto FieldArray;
}
else if ( token.type == T1_TOKEN_TYPE_ARRAY )
{
FieldArray:
/* if this is an array and we have no blend, an error occurs */
if ( max_objects == 0 )
goto Fail;
count = max_objects;
idx = 1;
/* don't include delimiters */
cur++;
limit--;
}
for ( ; count > 0; count--, idx++ )
{
FT_Byte* q = (FT_Byte*)objects[idx] + field->offset;
FT_Long val;
FT_String* string;
skip_spaces( &cur, limit );
switch ( field->type )
{
case T1_FIELD_TYPE_BOOL:
val = ps_tobool( &cur, limit );
goto Store_Integer;
case T1_FIELD_TYPE_FIXED:
val = PS_Conv_ToFixed( &cur, limit, 0 );
goto Store_Integer;
case T1_FIELD_TYPE_FIXED_1000:
val = PS_Conv_ToFixed( &cur, limit, 3 );
goto Store_Integer;
case T1_FIELD_TYPE_INTEGER:
val = PS_Conv_ToInt( &cur, limit );
/* fall through */
Store_Integer:
switch ( field->size )
{
case (8 / FT_CHAR_BIT):
*(FT_Byte*)q = (FT_Byte)val;
break;
case (16 / FT_CHAR_BIT):
*(FT_UShort*)q = (FT_UShort)val;
break;
case (32 / FT_CHAR_BIT):
*(FT_UInt32*)q = (FT_UInt32)val;
break;
default: /* for 64-bit systems */
*(FT_Long*)q = val;
}
break;
case T1_FIELD_TYPE_STRING:
case T1_FIELD_TYPE_KEY:
{
FT_Memory memory = parser->memory;
FT_UInt len = (FT_UInt)( limit - cur );
if ( cur >= limit )
break;
/* we allow both a string or a name */
/* for cases like /FontName (foo) def */
if ( token.type == T1_TOKEN_TYPE_KEY )
{
/* don't include leading `/' */
len--;
cur++;
}
else if ( token.type == T1_TOKEN_TYPE_STRING )
{
/* don't include delimiting parentheses */
/* XXX we don't handle <<...>> here */
/* XXX should we convert octal escapes? */
/* if so, what encoding should we use? */
cur++;
len -= 2;
}
else
{
FT_ERROR(( "ps_parser_load_field: expected a name or string "
"but found token of type %d instead\n",
token.type ));
error = PSaux_Err_Invalid_File_Format;
goto Exit;
}
/* for this to work (FT_String**)q must have been */
/* initialized to NULL */
if ( *(FT_String**)q != NULL )
{
FT_TRACE0(( "ps_parser_load_field: overwriting field %s\n",
field->ident ));
FT_FREE( *(FT_String**)q );
*(FT_String**)q = NULL;
}
if ( FT_ALLOC( string, len + 1 ) )
goto Exit;
FT_MEM_COPY( string, cur, len );
string[len] = 0;
*(FT_String**)q = string;
}
break;
case T1_FIELD_TYPE_BBOX:
{
FT_Fixed temp[4];
FT_BBox* bbox = (FT_BBox*)q;
(void)ps_tofixedarray( &token.start, token.limit, 4, temp, 0 );
bbox->xMin = FT_RoundFix( temp[0] );
bbox->yMin = FT_RoundFix( temp[1] );
bbox->xMax = FT_RoundFix( temp[2] );
bbox->yMax = FT_RoundFix( temp[3] );
}
break;
default:
/* an error occurred */
goto Fail;
}
}
#if 0 /* obsolete -- keep for reference */
if ( pflags )
*pflags |= 1L << field->flag_bit;
#else
FT_UNUSED( pflags );
#endif
error = PSaux_Err_Ok;
Exit:
return error;
Fail:
error = PSaux_Err_Invalid_File_Format;
goto Exit;
}
#define T1_MAX_TABLE_ELEMENTS 32
FT_LOCAL_DEF( FT_Error )
ps_parser_load_field_table( PS_Parser parser,
const T1_Field field,
void** objects,
FT_UInt max_objects,
FT_ULong* pflags )
{
T1_TokenRec elements[T1_MAX_TABLE_ELEMENTS];
T1_Token token;
FT_Int num_elements;
FT_Error error = PSaux_Err_Ok;
FT_Byte* old_cursor;
FT_Byte* old_limit;
T1_FieldRec fieldrec = *(T1_Field)field;
fieldrec.type = T1_FIELD_TYPE_INTEGER;
if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY ||
field->type == T1_FIELD_TYPE_BBOX )
fieldrec.type = T1_FIELD_TYPE_FIXED;
ps_parser_to_token_array( parser, elements,
T1_MAX_TABLE_ELEMENTS, &num_elements );
if ( num_elements < 0 )
{
error = PSaux_Err_Ignore;
goto Exit;
}
if ( num_elements > T1_MAX_TABLE_ELEMENTS )
num_elements = T1_MAX_TABLE_ELEMENTS;
old_cursor = parser->cursor;
old_limit = parser->limit;
/* we store the elements count if necessary */
if ( field->type != T1_FIELD_TYPE_BBOX )
*(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =
(FT_Byte)num_elements;
/* we now load each element, adjusting the field.offset on each one */
token = elements;
for ( ; num_elements > 0; num_elements--, token++ )
{
parser->cursor = token->start;
parser->limit = token->limit;
ps_parser_load_field( parser, &fieldrec, objects, max_objects, 0 );
fieldrec.offset += fieldrec.size;
}
#if 0 /* obsolete -- keep for reference */
if ( pflags )
*pflags |= 1L << field->flag_bit;
#else
FT_UNUSED( pflags );
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -