@ -393,6 +393,361 @@
}
/* some macros we need */
# define FT_FIXED_ONE ( (FT_Fixed)0x10000 )
# define FT_fdot14ToFixed( x ) \
( ( ( FT_Fixed ) ( ( FT_Int16 ) ( x ) ) ) < < 2 )
# define FT_intToFixed( i ) \
( ( FT_Fixed ) ( ( FT_UInt32 ) ( i ) < < 16 ) )
# define FT_fixedToInt( x ) \
( ( FT_Short ) ( ( ( FT_UInt32 ) ( x ) + 0x8000U ) > > 16 ) )
/*************************************************************************/
/* */
/* <Function> */
/* ft_var_load_hvar */
/* */
/* <Description> */
/* Parse the `HVAR' table and set `blend->hvar_loaded' to TRUE. */
/* */
/* On success, `blend->hvar_checked' is set to TRUE. */
/* */
/* Some memory may remain allocated on error; it is always freed in */
/* `tt_done_blend', however. */
/* */
/* <InOut> */
/* face :: The font face. */
/* */
/* <Return> */
/* FreeType error code. 0 means success. */
/* */
static FT_Error
ft_var_load_hvar ( TT_Face face )
{
FT_Stream stream = FT_FACE_STREAM ( face ) ;
FT_Memory memory = stream - > memory ;
GX_Blend blend = face - > blend ;
FT_Error error ;
FT_UShort majorVersion ;
FT_UShort minorVersion ;
FT_ULong table_len ;
FT_ULong table_offset ;
FT_ULong store_offset ;
FT_ULong map_offset ;
FT_ULong * dataOffsetArray = NULL ;
blend - > hvar_loaded = TRUE ;
FT_TRACE2 ( ( " HVAR " ) ) ;
error = face - > goto_table ( face , TTAG_HVAR , stream , & table_len ) ;
if ( error )
{
FT_TRACE2 ( ( " is missing \n " ) ) ;
goto Exit ;
}
table_offset = FT_STREAM_POS ( ) ;
if ( FT_READ_USHORT ( majorVersion ) | |
FT_READ_USHORT ( minorVersion ) )
goto Exit ;
if ( majorVersion ! = 1 )
{
FT_TRACE2 ( ( " bad table version %d \n " , majorVersion ) ) ;
error = FT_THROW ( Invalid_Table ) ;
goto Exit ;
}
if ( FT_READ_ULONG ( store_offset ) | |
FT_READ_ULONG ( map_offset ) )
goto Exit ;
/* parse item variation store */
{
FT_UShort format ;
FT_ULong region_offset ;
FT_UInt i , j , k ;
FT_UInt shortDeltaCount ;
GX_HVStore itemStore ;
GX_HVarTable hvarTable ;
GX_HVarData hvarData ;
if ( FT_STREAM_SEEK ( table_offset + store_offset ) | |
FT_READ_USHORT ( format ) )
goto Exit ;
if ( format ! = 1 )
{
FT_TRACE2 ( ( " bad store format %d \n " , format ) ) ;
error = FT_THROW ( Invalid_Table ) ;
goto Exit ;
}
if ( FT_NEW ( blend - > hvar_table ) ) /* allocate table at top level */
goto Exit ;
hvarTable = blend - > hvar_table ;
itemStore = & hvarTable - > itemStore ;
/* read top level fields */
if ( FT_READ_ULONG ( region_offset ) | |
FT_READ_USHORT ( itemStore - > dataCount ) )
goto Exit ;
/* make temporary copy of item variation data offsets; */
/* we will parse region list first, then come back */
if ( FT_NEW_ARRAY ( dataOffsetArray , itemStore - > dataCount ) )
goto Exit ;
for ( i = 0 ; i < itemStore - > dataCount ; i + + )
{
if ( FT_READ_ULONG ( dataOffsetArray [ i ] ) )
goto Exit ;
}
/* parse array of region records (region list) */
if ( FT_STREAM_SEEK ( table_offset + store_offset + region_offset ) )
goto Exit ;
if ( FT_READ_USHORT ( itemStore - > axisCount ) | |
FT_READ_USHORT ( itemStore - > regionCount ) )
goto Exit ;
if ( FT_NEW_ARRAY ( itemStore - > varRegionList , itemStore - > regionCount ) )
goto Exit ;
for ( i = 0 ; i < itemStore - > regionCount ; i + + )
{
GX_AxisCoords axisCoords ;
if ( FT_NEW_ARRAY ( itemStore - > varRegionList [ i ] . axisList ,
itemStore - > axisCount ) )
goto Exit ;
axisCoords = itemStore - > varRegionList [ i ] . axisList ;
for ( j = 0 ; j < itemStore - > axisCount ; j + + )
{
FT_Short start , peak , end ;
if ( FT_READ_SHORT ( start ) | |
FT_READ_SHORT ( peak ) | |
FT_READ_SHORT ( end ) )
goto Exit ;
axisCoords [ j ] . startCoord = FT_fdot14ToFixed ( start ) ;
axisCoords [ j ] . peakCoord = FT_fdot14ToFixed ( peak ) ;
axisCoords [ j ] . endCoord = FT_fdot14ToFixed ( end ) ;
}
}
/* end of region list parse */
/* use dataOffsetArray now to parse varData items */
if ( FT_NEW_ARRAY ( itemStore - > varData , itemStore - > dataCount ) )
goto Exit ;
for ( i = 0 ; i < itemStore - > dataCount ; i + + )
{
hvarData = & itemStore - > varData [ i ] ;
if ( FT_STREAM_SEEK ( table_offset +
store_offset +
dataOffsetArray [ i ] ) )
goto Exit ;
if ( FT_READ_USHORT ( hvarData - > itemCount ) | |
FT_READ_USHORT ( shortDeltaCount ) | |
FT_READ_USHORT ( hvarData - > regionIdxCount ) )
goto Exit ;
/* check some data consistency */
if ( shortDeltaCount > hvarData - > regionIdxCount )
{
FT_TRACE2 ( ( " bad short count %d or region count %d \n " ,
shortDeltaCount ,
hvarData - > regionIdxCount ) ) ;
error = FT_THROW ( Invalid_Table ) ;
goto Exit ;
}
if ( hvarData - > regionIdxCount > itemStore - > regionCount )
{
FT_TRACE2 ( ( " inconsistent regionCount %d in varData[%d] \n " ,
hvarData - > regionIdxCount ,
i ) ) ;
error = FT_THROW ( Invalid_Table ) ;
goto Exit ;
}
/* parse region indices */
if ( FT_NEW_ARRAY ( hvarData - > regionIndices ,
hvarData - > regionIdxCount ) )
goto Exit ;
for ( j = 0 ; j < hvarData - > regionIdxCount ; j + + )
{
if ( FT_READ_USHORT ( hvarData - > regionIndices [ j ] ) )
goto Exit ;
if ( hvarData - > regionIndices [ j ] > = itemStore - > regionCount )
{
FT_TRACE2 ( ( " bad region index %d \n " ,
hvarData - > regionIndices [ j ] ) ) ;
error = FT_THROW ( Invalid_Table ) ;
goto Exit ;
}
}
/* Parse delta set. */
/* */
/* On input, deltas are ( shortDeltaCount + regionIdxCount ) bytes */
/* each; on output, deltas are expanded to `regionIdxCount' shorts */
/* each. */
if ( FT_NEW_ARRAY ( hvarData - > deltaSet ,
hvarData - > regionIdxCount * hvarData - > itemCount ) )
goto Exit ;
/* the delta set is stored as a 2-dimensional array of shorts; */
/* sign-extend signed bytes to signed shorts */
for ( j = 0 ; j < hvarData - > itemCount * hvarData - > regionIdxCount ; )
{
for ( k = 0 ; k < shortDeltaCount ; k + + , j + + )
{
/* read the short deltas */
FT_Short delta ;
if ( FT_READ_SHORT ( delta ) )
goto Exit ;
hvarData - > deltaSet [ j ] = delta ;
}
for ( ; k < hvarData - > regionIdxCount ; k + + , j + + )
{
/* read the (signed) byte deltas */
FT_Char delta ;
if ( FT_READ_CHAR ( delta ) )
goto Exit ;
hvarData - > deltaSet [ j ] = delta ;
}
}
}
}
/* end parse item variation store */
/* parse width map */
{
GX_WidthMap widthMap ;
FT_UShort format ;
FT_UInt entrySize ;
FT_UInt innerBitCount ;
FT_UInt innerIndexMask ;
FT_UInt i , j ;
widthMap = & blend - > hvar_table - > widthMap ;
if ( FT_READ_USHORT ( format ) | |
FT_READ_USHORT ( widthMap - > mapCount ) )
goto Exit ;
if ( format & 0xFFC0 )
{
FT_TRACE2 ( ( " bad map format %d \n " , format ) ) ;
error = FT_THROW ( Invalid_Table ) ;
goto Exit ;
}
/* bytes per entry: 1, 2, 3, or 4 */
entrySize = ( ( format & 0x0030 ) > > 4 ) + 1 ;
innerBitCount = ( format & 0x000F ) + 1 ;
innerIndexMask = ( 1 < < innerBitCount ) - 1 ;
if ( FT_NEW_ARRAY ( widthMap - > innerIndex , widthMap - > mapCount ) )
goto Exit ;
if ( FT_NEW_ARRAY ( widthMap - > outerIndex , widthMap - > mapCount ) )
goto Exit ;
for ( i = 0 ; i < widthMap - > mapCount ; i + + )
{
FT_UInt mapData = 0 ;
FT_UInt outerIndex , innerIndex ;
/* read map data one unsigned byte at a time, big endian */
for ( j = 0 ; j < entrySize ; j + + )
{
FT_Byte data ;
if ( FT_READ_BYTE ( data ) )
goto Exit ;
mapData = ( mapData < < 8 ) | data ;
}
outerIndex = mapData > > innerBitCount ;
if ( outerIndex > = blend - > hvar_table - > itemStore . dataCount )
{
FT_TRACE2 ( ( " outerIndex[%d] == %d out of range \n " ,
i ,
outerIndex ) ) ;
error = FT_THROW ( Invalid_Table ) ;
goto Exit ;
}
widthMap - > outerIndex [ i ] = outerIndex ;
innerIndex = mapData & innerIndexMask ;
if ( innerIndex > =
blend - > hvar_table - > itemStore . varData [ outerIndex ] . itemCount )
{
FT_TRACE2 ( ( " innerIndex[%d] == %d out of range \n " ,
i ,
innerIndex ) ) ;
error = FT_THROW ( Invalid_Table ) ;
goto Exit ;
}
widthMap - > innerIndex [ i ] = innerIndex ;
}
}
/* end parse width map */
FT_TRACE2 ( ( " loaded \n " ) ) ;
error = FT_Err_Ok ;
Exit :
FT_FREE ( dataOffsetArray ) ;
if ( ! error )
blend - > hvar_checked = TRUE ;
return error ;
}
typedef struct GX_GVar_Head_
{
FT_Long version ;
@ -778,6 +1133,7 @@
FT_Var_Axis * a ;
FT_Var_Named_Style * ns ;
GX_FVar_Head fvar_head ;
FT_Bool usePsName ;
static const FT_Frame_Field fvar_fields [ ] =
{
@ -851,8 +1207,6 @@
fvar_head . axisSize ! = 20 | |
/* axisCount limit implied by 16-bit instanceSize */
fvar_head . axisCount > 0x3FFE | |
fvar_head . instanceSize ! = 4 + 4 * fvar_head . axisCount | |
/* instanceCount limit implied by limited range of name IDs */
fvar_head . instanceCount > 0x7EFF | |
fvar_head . offsetToData + fvar_head . axisCount * 20U +
fvar_head . instanceCount * fvar_head . instanceSize > table_len )
@ -863,6 +1217,18 @@
goto Exit ;
}
if ( fvar_head . instanceSize = = 4 + 4 * fvar_head . axisCount )
usePsName = FALSE ;
else if ( fvar_head . instanceSize = = 6 + 4 * fvar_head . axisCount )
usePsName = TRUE ;
else
{
FT_TRACE1 ( ( " \n "
" TT_Get_MM_Var: invalid `fvar' header \n " ) ) ;
error = FT_THROW ( Invalid_Table ) ;
goto Exit ;
}
FT_TRACE2 ( ( " loaded \n " ) ) ;
FT_TRACE5 ( ( " number of GX style axes: %d \n " , fvar_head . axisCount ) ) ;
@ -952,7 +1318,9 @@
ns = mmvar - > namedstyle ;
for ( i = 0 ; i < fvar_head . instanceCount ; i + + , ns + + )
{
if ( FT_FRAME_ENTER ( 4L + 4L * fvar_head . axisCount ) )
/* PostScript names add 2 bytes to the instance record size */
if ( FT_FRAME_ENTER ( ( usePsName ? 6L : 4L ) +
4L * fvar_head . axisCount ) )
goto Exit ;
ns - > strid = FT_GET_USHORT ( ) ;
@ -961,6 +1329,9 @@
for ( j = 0 ; j < fvar_head . axisCount ; j + + )
ns - > coords [ j ] = FT_GET_LONG ( ) ;
if ( usePsName )
ns - > psid = FT_GET_USHORT ( ) ;
FT_FRAME_EXIT ( ) ;
}
}
@ -2296,6 +2667,30 @@
FT_FREE ( blend - > avar_segment ) ;
}
if ( blend - > hvar_table ! = NULL )
{
if ( blend - > hvar_table - > itemStore . varData )
{
for ( i = 0 ; i < blend - > hvar_table - > itemStore . dataCount ; i + + )
{
FT_FREE ( blend - > hvar_table - > itemStore . varData [ i ] . regionIndices ) ;
FT_FREE ( blend - > hvar_table - > itemStore . varData [ i ] . deltaSet ) ;
}
FT_FREE ( blend - > hvar_table - > itemStore . varData ) ;
}
if ( blend - > hvar_table - > itemStore . varRegionList )
{
for ( i = 0 ; i < blend - > hvar_table - > itemStore . regionCount ; i + + )
FT_FREE ( blend - > hvar_table - > itemStore . varRegionList [ i ] . axisList ) ;
FT_FREE ( blend - > hvar_table - > itemStore . varRegionList ) ;
}
FT_FREE ( blend - > hvar_table - > widthMap . innerIndex ) ;
FT_FREE ( blend - > hvar_table - > widthMap . outerIndex ) ;
FT_FREE ( blend - > hvar_table ) ;
}
FT_FREE ( blend - > tuplecoords ) ;
FT_FREE ( blend - > glyphoffsets ) ;
FT_FREE ( blend ) ;