📄 gxvcommn.c
字号:
/***************************************************************************/
/* */
/* gxvcommn.c */
/* */
/* TrueTypeGX/AAT common tables validation (body). */
/* */
/* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
/* 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. */
/* */
/***************************************************************************/
/***************************************************************************/
/* */
/* gxvalid is derived from both gxlayout module and otvalid module. */
/* Development of gxlayout is supported by the Information-technology */
/* Promotion Agency(IPA), Japan. */
/* */
/***************************************************************************/
#include "gxvcommn.h"
/*************************************************************************/
/* */
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
/* messages during execution. */
/* */
#undef FT_COMPONENT
#define FT_COMPONENT trace_gxvcommon
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** 16bit offset sorter *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
static int
gxv_compare_ushort_offset( FT_UShort* a,
FT_UShort* b )
{
if ( *a < *b )
return ( -1 );
else if ( *a > *b )
return ( 1 );
else
return ( 0 );
}
FT_LOCAL_DEF( void )
gxv_set_length_by_ushort_offset( FT_UShort* offset,
FT_UShort** length,
FT_UShort* buff,
FT_UInt nmemb,
FT_UShort limit,
GXV_Validator valid )
{
FT_UInt i;
for ( i = 0; i < nmemb; i++ )
*(length[i]) = 0;
for ( i = 0; i < nmemb; i++ )
buff[i] = offset[i];
buff[nmemb] = limit;
ft_qsort( buff, ( nmemb + 1 ), sizeof ( FT_UShort ),
( int(*)(const void*, const void*) )gxv_compare_ushort_offset );
if ( buff[nmemb] > limit )
FT_INVALID_OFFSET;
for ( i = 0; i < nmemb; i++ )
{
FT_UInt j;
for ( j = 0; j < nmemb; j++ )
if ( buff[j] == offset[i] )
break;
if ( j == nmemb )
FT_INVALID_OFFSET;
*(length[i]) = (FT_UShort)( buff[j + 1] - buff[j] );
if ( 0 != offset[i] && 0 == *(length[i]) )
FT_INVALID_OFFSET;
}
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** 32bit offset sorter *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
static int
gxv_compare_ulong_offset( FT_ULong* a,
FT_ULong* b )
{
if ( *a < *b )
return ( -1 );
else if ( *a > *b )
return ( 1 );
else
return ( 0 );
}
FT_LOCAL_DEF( void )
gxv_set_length_by_ulong_offset( FT_ULong* offset,
FT_ULong** length,
FT_ULong* buff,
FT_UInt nmemb,
FT_ULong limit,
GXV_Validator valid)
{
FT_UInt i;
for ( i = 0; i < nmemb; i++ )
*(length[i]) = 0;
for ( i = 0; i < nmemb; i++ )
buff[i] = offset[i];
buff[nmemb] = limit;
ft_qsort( buff, ( nmemb + 1 ), sizeof ( FT_ULong ),
( int(*)(const void*, const void*) )gxv_compare_ulong_offset );
if ( buff[nmemb] > limit )
FT_INVALID_OFFSET;
for ( i = 0; i < nmemb; i++ )
{
FT_UInt j;
for ( j = 0; j < nmemb; j++ )
if ( buff[j] == offset[i] )
break;
if ( j == nmemb )
FT_INVALID_OFFSET;
*(length[i]) = buff[j + 1] - buff[j];
if ( 0 != offset[i] && 0 == *(length[i]) )
FT_INVALID_OFFSET;
}
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** scan value array and get min & max *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
FT_LOCAL_DEF( void )
gxv_array_getlimits_byte( FT_Bytes table,
FT_Bytes limit,
FT_Byte* min,
FT_Byte* max,
GXV_Validator valid )
{
FT_Bytes p = table;
*min = 0xFF;
*max = 0x00;
while ( p < limit )
{
FT_Byte val;
GXV_LIMIT_CHECK( 1 );
val = FT_NEXT_BYTE( p );
*min = (FT_Byte)FT_MIN( *min, val );
*max = (FT_Byte)FT_MAX( *max, val );
}
valid->subtable_length = p - table;
}
FT_LOCAL_DEF( void )
gxv_array_getlimits_ushort( FT_Bytes table,
FT_Bytes limit,
FT_UShort* min,
FT_UShort* max,
GXV_Validator valid )
{
FT_Bytes p = table;
*min = 0xFFFFU;
*max = 0x0000;
while ( p < limit )
{
FT_UShort val;
GXV_LIMIT_CHECK( 2 );
val = FT_NEXT_USHORT( p );
*min = (FT_Byte)FT_MIN( *min, val );
*max = (FT_Byte)FT_MAX( *max, val );
}
valid->subtable_length = p - table;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** BINSEARCHHEADER *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
typedef struct GXV_BinSrchHeader_
{
FT_UShort unitSize;
FT_UShort nUnits;
FT_UShort searchRange;
FT_UShort entrySelector;
FT_UShort rangeShift;
} GXV_BinSrchHeader;
static void
gxv_BinSrchHeader_check_consistency( GXV_BinSrchHeader* binSrchHeader,
GXV_Validator valid )
{
FT_UShort searchRange;
FT_UShort entrySelector;
FT_UShort rangeShift;
if ( binSrchHeader->unitSize == 0 )
FT_INVALID_DATA;
if ( binSrchHeader->nUnits == 0 )
{
if ( binSrchHeader->searchRange == 0 &&
binSrchHeader->entrySelector == 0 &&
binSrchHeader->rangeShift == 0 )
return;
else
FT_INVALID_DATA;
}
for ( searchRange = 1, entrySelector = 1;
( searchRange * 2 ) <= binSrchHeader->nUnits &&
searchRange < 0x8000U;
searchRange *= 2, entrySelector++ )
;
entrySelector--;
searchRange = (FT_UShort)( searchRange * binSrchHeader->unitSize );
rangeShift = (FT_UShort)( binSrchHeader->nUnits * binSrchHeader->unitSize
- searchRange );
if ( searchRange != binSrchHeader->searchRange ||
entrySelector != binSrchHeader->entrySelector ||
rangeShift != binSrchHeader->rangeShift )
{
GXV_TRACE(( "Inconsistency found in BinSrchHeader\n" ));
GXV_TRACE(( "originally: unitSize=%d, nUnits=%d, "
"searchRange=%d, entrySelector=%d, "
"rangeShift=%d\n",
binSrchHeader->unitSize, binSrchHeader->nUnits,
binSrchHeader->searchRange, binSrchHeader->entrySelector,
binSrchHeader->rangeShift ));
GXV_TRACE(( "calculated: unitSize=%d, nUnits=%d, "
"searchRange=%d, entrySelector=%d, "
"rangeShift=%d\n",
binSrchHeader->unitSize, binSrchHeader->nUnits,
searchRange, entrySelector, rangeShift ));
if ( valid->root->level >= FT_VALIDATE_PARANOID )
FT_INVALID_DATA;
}
}
/*
* parser & validator of BinSrchHeader
* which is used in LookupTable format 2, 4, 6.
*
* Essential parameters (unitSize, nUnits) are returned by
* given pointer, others (searchRange, entrySelector, rangeShift)
* can be calculated by essential parameters, so they are just
* validated and discarded.
*
* However, wrong values in searchRange, entrySelector, rangeShift
* won't cause fatal errors, because these parameters might be
* only used in old m68k font driver in MacOS.
* -- suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
*/
FT_LOCAL_DEF( void )
gxv_BinSrchHeader_validate( FT_Bytes table,
FT_Bytes limit,
FT_UShort* unitSize_p,
FT_UShort* nUnits_p,
GXV_Validator valid )
{
FT_Bytes p = table;
GXV_BinSrchHeader binSrchHeader;
GXV_NAME_ENTER( "BinSrchHeader validate" );
if ( *unitSize_p == 0 )
{
GXV_LIMIT_CHECK( 2 );
binSrchHeader.unitSize = FT_NEXT_USHORT( p );
}
else
binSrchHeader.unitSize = *unitSize_p;
if ( *nUnits_p == 0 )
{
GXV_LIMIT_CHECK( 2 );
binSrchHeader.nUnits = FT_NEXT_USHORT( p );
}
else
binSrchHeader.nUnits = *nUnits_p;
GXV_LIMIT_CHECK( 2 + 2 + 2 );
binSrchHeader.searchRange = FT_NEXT_USHORT( p );
binSrchHeader.entrySelector = FT_NEXT_USHORT( p );
binSrchHeader.rangeShift = FT_NEXT_USHORT( p );
GXV_TRACE(( "nUnits %d\n", binSrchHeader.nUnits ));
gxv_BinSrchHeader_check_consistency( &binSrchHeader, valid );
if ( *unitSize_p == 0 )
*unitSize_p = binSrchHeader.unitSize;
if ( *nUnits_p == 0 )
*nUnits_p = binSrchHeader.nUnits;
valid->subtable_length = p - table;
GXV_EXIT;
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** LOOKUP TABLE *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
#define GXV_LOOKUP_VALUE_LOAD( P, SIGNSPEC ) \
( P += 2, gxv_lookup_value_load( P - 2, SIGNSPEC ) )
static GXV_LookupValueDesc
gxv_lookup_value_load( FT_Bytes p,
int signspec )
{
GXV_LookupValueDesc v;
if ( signspec == GXV_LOOKUPVALUE_UNSIGNED )
v.u = FT_NEXT_USHORT( p );
else
v.s = FT_NEXT_SHORT( p );
return v;
}
#define GXV_UNITSIZE_VALIDATE( FORMAT, UNITSIZE, NUNITS, CORRECTSIZE ) \
FT_BEGIN_STMNT \
if ( UNITSIZE != CORRECTSIZE ) \
{ \
FT_ERROR(( "unitSize=%d differs from" \
"expected unitSize=%d" \
"in LookupTable %s", \
UNITSIZE, CORRECTSIZE, FORMAT )); \
if ( UNITSIZE != 0 && NUNITS != 0 ) \
{ \
FT_ERROR(( " cannot validate anymore\n" )); \
FT_INVALID_FORMAT; \
} \
else \
FT_ERROR(( " forcibly continues\n" )); \
} \
FT_END_STMNT
/* ================= Simple Array Format 0 Lookup Table ================ */
static void
gxv_LookupTable_fmt0_validate( FT_Bytes table,
FT_Bytes limit,
GXV_Validator valid )
{
FT_Bytes p = table;
FT_UShort i;
GXV_LookupValueDesc value;
GXV_NAME_ENTER( "LookupTable format 0" );
GXV_LIMIT_CHECK( 2 * valid->face->num_glyphs );
for ( i = 0; i < valid->face->num_glyphs; i++ )
{
GXV_LIMIT_CHECK( 2 );
if ( p + 2 >= limit ) /* some fonts have too-short fmt0 array */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -