📄 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 + -