📄 psobjs.c
字号:
break;
if ( !IS_PS_XDIGIT( *cur ) )
break;
}
if ( cur < limit && *cur != '>' )
{
FT_ERROR(( "skip_string: missing closing delimiter `>'\n" ));
err = PSaux_Err_Invalid_File_Format;
}
else
cur++;
*acur = cur;
return err;
}
/* first character must be the opening brace that */
/* starts the procedure */
/* NB: [ and ] need not match: */
/* `/foo {[} def' is a valid PostScript fragment, */
/* even within a Type1 font */
static FT_Error
skip_procedure( FT_Byte* *acur,
FT_Byte* limit )
{
FT_Byte* cur;
FT_Int embed = 0;
FT_Error error = PSaux_Err_Ok;
FT_ASSERT( **acur == '{' );
for ( cur = *acur; cur < limit && error == PSaux_Err_Ok; ++cur )
{
switch ( *cur )
{
case '{':
++embed;
break;
case '}':
--embed;
if ( embed == 0 )
{
++cur;
goto end;
}
break;
case '(':
error = skip_literal_string( &cur, limit );
break;
case '<':
error = skip_string( &cur, limit );
break;
case '%':
skip_comment( &cur, limit );
break;
}
}
end:
if ( embed != 0 )
error = PSaux_Err_Invalid_File_Format;
*acur = cur;
return error;
}
/***********************************************************************/
/* */
/* All exported parsing routines handle leading whitespace and stop at */
/* the first character which isn't part of the just handled token. */
/* */
/***********************************************************************/
FT_LOCAL_DEF( void )
ps_parser_skip_PS_token( PS_Parser parser )
{
/* Note: PostScript allows any non-delimiting, non-whitespace */
/* character in a name (PS Ref Manual, 3rd ed, p31). */
/* PostScript delimiters are (, ), <, >, [, ], {, }, /, and %. */
FT_Byte* cur = parser->cursor;
FT_Byte* limit = parser->limit;
FT_Error error = PSaux_Err_Ok;
skip_spaces( &cur, limit ); /* this also skips comments */
if ( cur >= limit )
goto Exit;
/* self-delimiting, single-character tokens */
if ( *cur == '[' || *cur == ']' )
{
cur++;
goto Exit;
}
/* skip balanced expressions (procedures and strings) */
if ( *cur == '{' ) /* {...} */
{
error = skip_procedure( &cur, limit );
goto Exit;
}
if ( *cur == '(' ) /* (...) */
{
error = skip_literal_string( &cur, limit );
goto Exit;
}
if ( *cur == '<' ) /* <...> */
{
if ( cur + 1 < limit && *(cur + 1) == '<' ) /* << */
{
cur++;
cur++;
}
else
error = skip_string( &cur, limit );
goto Exit;
}
if ( *cur == '>' )
{
cur++;
if ( cur >= limit || *cur != '>' ) /* >> */
{
FT_ERROR(( "ps_parser_skip_PS_token: "
"unexpected closing delimiter `>'\n" ));
error = PSaux_Err_Invalid_File_Format;
goto Exit;
}
cur++;
goto Exit;
}
if ( *cur == '/' )
cur++;
/* anything else */
while ( cur < limit )
{
/* *cur might be invalid (e.g., ')' or '}'), but this */
/* is handled by the test `cur == parser->cursor' below */
if ( IS_PS_DELIM( *cur ) )
break;
cur++;
}
Exit:
if ( cur == parser->cursor )
{
FT_ERROR(( "ps_parser_skip_PS_token: "
"current token is `%c', which is self-delimiting "
"but invalid at this point\n",
*cur ));
error = PSaux_Err_Invalid_File_Format;
}
FT_ASSERT( parser->error == PSaux_Err_Ok );
parser->error = error;
parser->cursor = cur;
}
FT_LOCAL_DEF( void )
ps_parser_skip_spaces( PS_Parser parser )
{
skip_spaces( &parser->cursor, parser->limit );
}
/* `token' here means either something between balanced delimiters */
/* or the next token; the delimiters are not removed. */
FT_LOCAL_DEF( void )
ps_parser_to_token( PS_Parser parser,
T1_Token token )
{
FT_Byte* cur;
FT_Byte* limit;
FT_Int embed;
token->type = T1_TOKEN_TYPE_NONE;
token->start = 0;
token->limit = 0;
/* first of all, skip leading whitespace */
ps_parser_skip_spaces( parser );
cur = parser->cursor;
limit = parser->limit;
if ( cur >= limit )
return;
switch ( *cur )
{
/************* check for literal string *****************/
case '(':
token->type = T1_TOKEN_TYPE_STRING;
token->start = cur;
if ( skip_literal_string( &cur, limit ) == PSaux_Err_Ok )
token->limit = cur;
break;
/************* check for programs/array *****************/
case '{':
token->type = T1_TOKEN_TYPE_ARRAY;
token->start = cur;
if ( skip_procedure( &cur, limit ) == PSaux_Err_Ok )
token->limit = cur;
break;
/************* check for table/array ********************/
/* XXX: in theory we should also look for "<<" */
/* since this is semantically equivalent to "["; */
/* in practice it doesn't matter (?) */
case '[':
token->type = T1_TOKEN_TYPE_ARRAY;
embed = 1;
token->start = cur++;
/* we need this to catch `[ ]' */
parser->cursor = cur;
ps_parser_skip_spaces( parser );
cur = parser->cursor;
while ( cur < limit && !parser->error )
{
/* XXX: this is wrong because it does not */
/* skip comments, procedures, and strings */
if ( *cur == '[' )
embed++;
else if ( *cur == ']' )
{
embed--;
if ( embed <= 0 )
{
token->limit = ++cur;
break;
}
}
parser->cursor = cur;
ps_parser_skip_PS_token( parser );
/* we need this to catch `[XXX ]' */
ps_parser_skip_spaces ( parser );
cur = parser->cursor;
}
break;
/* ************ otherwise, it is any token **************/
default:
token->start = cur;
token->type = ( *cur == '/' ? T1_TOKEN_TYPE_KEY : T1_TOKEN_TYPE_ANY );
ps_parser_skip_PS_token( parser );
cur = parser->cursor;
if ( !parser->error )
token->limit = cur;
}
if ( !token->limit )
{
token->start = 0;
token->type = T1_TOKEN_TYPE_NONE;
}
parser->cursor = cur;
}
/* NB: `tokens' can be NULL if we only want to count */
/* the number of array elements */
FT_LOCAL_DEF( void )
ps_parser_to_token_array( PS_Parser parser,
T1_Token tokens,
FT_UInt max_tokens,
FT_Int* pnum_tokens )
{
T1_TokenRec master;
*pnum_tokens = -1;
/* this also handles leading whitespace */
ps_parser_to_token( parser, &master );
if ( master.type == T1_TOKEN_TYPE_ARRAY )
{
FT_Byte* old_cursor = parser->cursor;
FT_Byte* old_limit = parser->limit;
T1_Token cur = tokens;
T1_Token limit = cur + max_tokens;
/* don't include outermost delimiters */
parser->cursor = master.start + 1;
parser->limit = master.limit - 1;
while ( parser->cursor < parser->limit )
{
T1_TokenRec token;
ps_parser_to_token( parser, &token );
if ( !token.type )
break;
if ( tokens != NULL && cur < limit )
*cur = token;
cur++;
}
*pnum_tokens = (FT_Int)( cur - tokens );
parser->cursor = old_cursor;
parser->limit = old_limit;
}
}
/* first character must be a delimiter or a part of a number */
/* NB: `coords' can be NULL if we just want to skip the */
/* array; in this case we ignore `max_coords' */
static FT_Int
ps_tocoordarray( FT_Byte* *acur,
FT_Byte* limit,
FT_Int max_coords,
FT_Short* coords )
{
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 coordinates */
while ( cur < limit )
{
FT_Short dummy;
/* skip whitespace in front of data */
skip_spaces( &cur, limit );
if ( cur >= limit )
goto Exit;
if ( coords != NULL && count >= max_coords )
break;
if ( *cur == ender )
{
cur++;
break;
}
/* call PS_Conv_ToFixed() even if coords == NULL */
/* to properly parse number at `cur' */
*( coords != NULL ? &coords[count] : &dummy ) =
(FT_Short)( PS_Conv_ToFixed( &cur, limit, 0 ) >> 16 );
count++;
if ( !ender )
break;
}
Exit:
*acur = cur;
return count;
}
/* first character must be a delimiter or a part of a number */
/* NB: `values' can be NULL if we just want to skip the */
/* array in this case we ignore `max_values' */
static FT_Int
ps_tofixedarray( FT_Byte* *acur,
FT_Byte* limit,
FT_Int max_values,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -