📄 psaux.c
字号:
/***************************************************************************/
/* */
/* psaux.c */
/* */
/* FreeType auxiliary PostScript driver component (body only). */
/* */
/* Copyright 1996-2001, 2002, 2006 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include "ft2build.h"
/***************************************************************************/
/* */
/* psobjs.c */
/* */
/* Auxiliary functions for PostScript fonts (body). */
/* */
/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#include "ft2build.h"
#include FT_INTERNAL_POSTSCRIPT_AUX_H
#include FT_INTERNAL_DEBUG_H
#include "psobjs.h"
#include "psconv.h"
#include "psauxerr.h"
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** PS_TABLE *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/* */
/* <Function> */
/* ps_table_new */
/* */
/* <Description> */
/* Initializes a PS_Table. */
/* */
/* <InOut> */
/* table :: The address of the target table. */
/* */
/* <Input> */
/* count :: The table size = the maximum number of elements. */
/* */
/* memory :: The memory object to use for all subsequent */
/* reallocations. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
FT_LOCAL_DEF( FT_Error )
ps_table_new( PS_Table table,
FT_Int count,
FT_Memory memory )
{
FT_Error error;
table->memory = memory;
if ( FT_NEW_ARRAY( table->elements, count ) ||
FT_NEW_ARRAY( table->lengths, count ) )
goto Exit;
table->max_elems = count;
table->init = 0xDEADBEEFUL;
table->num_elems = 0;
table->block = 0;
table->capacity = 0;
table->cursor = 0;
*(PS_Table_FuncsRec*)&table->funcs = ps_table_funcs;
Exit:
if ( error )
FT_FREE( table->elements );
return error;
}
static void
shift_elements( PS_Table table,
FT_Byte* old_base )
{
FT_PtrDist delta = table->block - old_base;
FT_Byte** offset = table->elements;
FT_Byte** limit = offset + table->max_elems;
for ( ; offset < limit; offset++ )
{
if ( offset[0] )
offset[0] += delta;
}
}
static FT_Error
reallocate_t1_table( PS_Table table,
FT_Long new_size )
{
FT_Memory memory = table->memory;
FT_Byte* old_base = table->block;
FT_Error error;
/* allocate new base block */
if ( FT_ALLOC( table->block, new_size ) )
{
table->block = old_base;
return error;
}
/* copy elements and shift offsets */
if (old_base )
{
FT_MEM_COPY( table->block, old_base, table->capacity );
shift_elements( table, old_base );
FT_FREE( old_base );
}
table->capacity = new_size;
return PSaux_Err_Ok;
}
/*************************************************************************/
/* */
/* <Function> */
/* ps_table_add */
/* */
/* <Description> */
/* Adds an object to a PS_Table, possibly growing its memory block. */
/* */
/* <InOut> */
/* table :: The target table. */
/* */
/* <Input> */
/* idx :: The index of the object in the table. */
/* */
/* object :: The address of the object to copy in memory. */
/* */
/* length :: The length in bytes of the source object. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. An error is returned if a */
/* reallocation fails. */
/* */
FT_LOCAL_DEF( FT_Error )
ps_table_add( PS_Table table,
FT_Int idx,
void* object,
FT_PtrDist length )
{
if ( idx < 0 || idx > table->max_elems )
{
FT_ERROR(( "ps_table_add: invalid index\n" ));
return PSaux_Err_Invalid_Argument;
}
/* grow the base block if needed */
if ( table->cursor + length > table->capacity )
{
FT_Error error;
FT_Offset new_size = table->capacity;
FT_Long in_offset;
in_offset = (FT_Long)((FT_Byte*)object - table->block);
if ( (FT_ULong)in_offset >= table->capacity )
in_offset = -1;
while ( new_size < table->cursor + length )
{
/* increase size by 25% and round up to the nearest multiple
of 1024 */
new_size += ( new_size >> 2 ) + 1;
new_size = FT_PAD_CEIL( new_size, 1024 );
}
error = reallocate_t1_table( table, new_size );
if ( error )
return error;
if ( in_offset >= 0 )
object = table->block + in_offset;
}
/* add the object to the base block and adjust offset */
table->elements[idx] = table->block + table->cursor;
table->lengths [idx] = length;
FT_MEM_COPY( table->block + table->cursor, object, length );
table->cursor += length;
return PSaux_Err_Ok;
}
/*************************************************************************/
/* */
/* <Function> */
/* ps_table_done */
/* */
/* <Description> */
/* Finalizes a PS_TableRec (i.e., reallocate it to its current */
/* cursor). */
/* */
/* <InOut> */
/* table :: The target table. */
/* */
/* <Note> */
/* This function does NOT release the heap's memory block. It is up */
/* to the caller to clean it, or reference it in its own structures. */
/* */
FT_LOCAL_DEF( void )
ps_table_done( PS_Table table )
{
FT_Memory memory = table->memory;
FT_Error error;
FT_Byte* old_base = table->block;
/* should never fail, because rec.cursor <= rec.size */
if ( !old_base )
return;
if ( FT_ALLOC( table->block, table->cursor ) )
return;
FT_MEM_COPY( table->block, old_base, table->cursor );
shift_elements( table, old_base );
table->capacity = table->cursor;
FT_FREE( old_base );
FT_UNUSED( error );
}
FT_LOCAL_DEF( void )
ps_table_release( PS_Table table )
{
FT_Memory memory = table->memory;
if ( (FT_ULong)table->init == 0xDEADBEEFUL )
{
FT_FREE( table->block );
FT_FREE( table->elements );
FT_FREE( table->lengths );
table->init = 0;
}
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** T1 PARSER *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/* first character must be already part of the comment */
static void
skip_comment( FT_Byte* *acur,
FT_Byte* limit )
{
FT_Byte* cur = *acur;
while ( cur < limit )
{
if ( IS_PS_NEWLINE( *cur ) )
break;
cur++;
}
*acur = cur;
}
static void
skip_spaces( FT_Byte* *acur,
FT_Byte* limit )
{
FT_Byte* cur = *acur;
while ( cur < limit )
{
if ( !IS_PS_SPACE( *cur ) )
{
if ( *cur == '%' )
/* According to the PLRM, a comment is equal to a space. */
skip_comment( &cur, limit );
else
break;
}
cur++;
}
*acur = cur;
}
/* first character must be `(' */
static void
skip_literal_string( FT_Byte* *acur,
FT_Byte* limit )
{
FT_Byte* cur = *acur;
FT_Int embed = 0;
while ( cur < limit )
{
if ( *cur == '\\' )
cur++;
else if ( *cur == '(' )
embed++;
else if ( *cur == ')' )
{
embed--;
if ( embed == 0 )
{
cur++;
break;
}
}
cur++;
}
*acur = cur;
}
/* first character must be `<' */
static void
skip_string( PS_Parser parser )
{
FT_Byte* cur = parser->cursor;
FT_Byte* limit = parser->limit;
while ( ++cur < limit )
{
/* All whitespace characters are ignored. */
skip_spaces( &cur, limit );
if ( cur >= limit )
break;
if ( !IS_PS_XDIGIT( *cur ) )
break;
}
if ( cur < limit && *cur != '>' )
{
FT_ERROR(( "skip_string: missing closing delimiter `>'\n" ));
parser->error = PSaux_Err_Invalid_File_Format;
}
else
cur++;
parser->cursor = cur;
}
/***********************************************************************/
/* */
/* 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;
skip_spaces( &cur, limit ); /* this also skips comments */
if ( cur >= limit )
goto Exit;
/* self-delimiting, single-character tokens */
if ( *cur == '[' || *cur == ']' ||
*cur == '{' || *cur == '}' )
{
cur++;
goto Exit;
}
if ( *cur == '(' ) /* (...) */
{
skip_literal_string( &cur, limit );
goto Exit;
}
if ( *cur == '<' ) /* <...> */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -