[truetype] Parse `MVAR' table.
* src/truetype/ttgxvar.h (MVAR_TAG_XXX): New macros for MVAR tags. (GX_Value, GX_MVarTable): New structures. (GX_Blend): Add it. * src/truetype/ttgxvar.c (GX_VALUE_SIZE, GX_VALUE_CASE, GX_GASP_CASE): New macros. (ft_var_get_value_pointer): New auxiliary function to get a pointer to a value from various SFNT tables already stored in `TT_Face'. (ft_var_load_mvar): New function. (TT_Get_MM_Var): Call it. (tt_done_blend): Updated.
This commit is contained in:
parent
8ab08cff63
commit
07ee1d250c
16
ChangeLog
16
ChangeLog
@ -1,3 +1,19 @@
|
||||
2017-01-11 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
[truetype] Parse `MVAR' table.
|
||||
|
||||
* src/truetype/ttgxvar.h (MVAR_TAG_XXX): New macros for MVAR tags.
|
||||
(GX_Value, GX_MVarTable): New structures.
|
||||
(GX_Blend): Add it.
|
||||
|
||||
* src/truetype/ttgxvar.c (GX_VALUE_SIZE, GX_VALUE_CASE,
|
||||
GX_GASP_CASE): New macros.
|
||||
(ft_var_get_value_pointer): New auxiliary function to get a pointer
|
||||
to a value from various SFNT tables already stored in `TT_Face'.
|
||||
(ft_var_load_mvar): New function.
|
||||
(TT_Get_MM_Var): Call it.
|
||||
(tt_done_blend): Updated.
|
||||
|
||||
2017-01-11 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
[truetype] More preparations for MVAR support.
|
||||
|
@ -744,6 +744,7 @@
|
||||
if ( FT_READ_USHORT( majorVersion ) ||
|
||||
FT_STREAM_SKIP( 2 ) )
|
||||
goto Exit;
|
||||
|
||||
if ( majorVersion != 1 )
|
||||
{
|
||||
FT_TRACE2(( "bad table version %d\n", majorVersion ));
|
||||
@ -964,7 +965,6 @@
|
||||
outerIndex,
|
||||
innerIndex );
|
||||
|
||||
/* apply the accumulated adjustment to derive the interpolated value */
|
||||
FT_TRACE5(( "horizontal width %d adjusted by %d units (HVAR)\n",
|
||||
*avalue,
|
||||
delta ));
|
||||
@ -976,6 +976,205 @@
|
||||
}
|
||||
|
||||
|
||||
#define GX_VALUE_SIZE 8
|
||||
|
||||
/* all values are FT_Short or FT_UShort entities; */
|
||||
/* we treat them consistently as FT_Short */
|
||||
#define GX_VALUE_CASE( tag, dflt ) \
|
||||
case MVAR_TAG_ ## tag : \
|
||||
p = (FT_Short*)&face->dflt; \
|
||||
break
|
||||
|
||||
#define GX_GASP_CASE( idx ) \
|
||||
case MVAR_TAG_GASP_ ## idx : \
|
||||
if ( idx < face->gasp.numRanges - 1 ) \
|
||||
p = (FT_Short*)&face->gasp.gaspRanges[idx].maxPPEM; \
|
||||
else \
|
||||
p = NULL; \
|
||||
break
|
||||
|
||||
|
||||
static FT_Short*
|
||||
ft_var_get_value_pointer( TT_Face face,
|
||||
FT_ULong mvar_tag )
|
||||
{
|
||||
FT_Short* p;
|
||||
|
||||
|
||||
switch ( mvar_tag )
|
||||
{
|
||||
GX_GASP_CASE( 0 );
|
||||
GX_GASP_CASE( 1 );
|
||||
GX_GASP_CASE( 2 );
|
||||
GX_GASP_CASE( 3 );
|
||||
GX_GASP_CASE( 4 );
|
||||
GX_GASP_CASE( 5 );
|
||||
GX_GASP_CASE( 6 );
|
||||
GX_GASP_CASE( 7 );
|
||||
GX_GASP_CASE( 8 );
|
||||
GX_GASP_CASE( 9 );
|
||||
|
||||
GX_VALUE_CASE( CPHT, os2.sCapHeight );
|
||||
GX_VALUE_CASE( HASC, os2.sTypoAscender );
|
||||
GX_VALUE_CASE( HCLA, os2.usWinAscent );
|
||||
GX_VALUE_CASE( HCLD, os2.usWinDescent );
|
||||
GX_VALUE_CASE( HCOF, horizontal.caret_Offset );
|
||||
GX_VALUE_CASE( HCRN, horizontal.caret_Slope_Run );
|
||||
GX_VALUE_CASE( HCRS, horizontal.caret_Slope_Rise );
|
||||
GX_VALUE_CASE( HDSC, os2.sTypoDescender );
|
||||
GX_VALUE_CASE( HLGP, os2.sTypoLineGap );
|
||||
GX_VALUE_CASE( SBXO, os2.ySubscriptXOffset);
|
||||
GX_VALUE_CASE( SBXS, os2.ySubscriptXSize );
|
||||
GX_VALUE_CASE( SBYO, os2.ySubscriptYOffset );
|
||||
GX_VALUE_CASE( SBYS, os2.ySubscriptYSize );
|
||||
GX_VALUE_CASE( SPXO, os2.ySuperscriptXOffset );
|
||||
GX_VALUE_CASE( SPXS, os2.ySuperscriptXSize );
|
||||
GX_VALUE_CASE( SPYO, os2.ySuperscriptYOffset );
|
||||
GX_VALUE_CASE( SPYS, os2.ySuperscriptYSize );
|
||||
GX_VALUE_CASE( STRO, os2.yStrikeoutPosition );
|
||||
GX_VALUE_CASE( STRS, os2.yStrikeoutSize );
|
||||
GX_VALUE_CASE( UNDO, postscript.underlinePosition );
|
||||
GX_VALUE_CASE( UNDS, postscript.underlineThickness );
|
||||
GX_VALUE_CASE( VASC, vertical.Ascender );
|
||||
GX_VALUE_CASE( VCOF, vertical.caret_Offset );
|
||||
GX_VALUE_CASE( VCRN, vertical.caret_Slope_Run );
|
||||
GX_VALUE_CASE( VCRS, vertical.caret_Slope_Rise );
|
||||
GX_VALUE_CASE( VDSC, vertical.Descender );
|
||||
GX_VALUE_CASE( VLGP, vertical.Line_Gap );
|
||||
GX_VALUE_CASE( XHGT, os2.sxHeight );
|
||||
|
||||
default:
|
||||
/* ignore unknown tag */
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Function> */
|
||||
/* ft_var_load_mvar */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* Parse the `MVAR' table. */
|
||||
/* */
|
||||
/* Some memory may remain allocated on error; it is always freed in */
|
||||
/* `tt_done_blend', however. */
|
||||
/* */
|
||||
/* <InOut> */
|
||||
/* face :: The font face. */
|
||||
/* */
|
||||
static void
|
||||
ft_var_load_mvar( TT_Face face )
|
||||
{
|
||||
FT_Stream stream = FT_FACE_STREAM( face );
|
||||
FT_Memory memory = stream->memory;
|
||||
|
||||
GX_Blend blend = face->blend;
|
||||
GX_ItemVarStore itemStore;
|
||||
GX_Value value, limit;
|
||||
|
||||
FT_Error error;
|
||||
FT_UShort majorVersion;
|
||||
FT_ULong table_len;
|
||||
FT_ULong table_offset;
|
||||
FT_UShort store_offset;
|
||||
FT_ULong records_offset;
|
||||
|
||||
|
||||
FT_TRACE2(( "MVAR " ));
|
||||
|
||||
error = face->goto_table( face, TTAG_MVAR, stream, &table_len );
|
||||
if ( error )
|
||||
{
|
||||
FT_TRACE2(( "is missing\n" ));
|
||||
return;
|
||||
}
|
||||
|
||||
table_offset = FT_STREAM_POS();
|
||||
|
||||
/* skip minor version */
|
||||
if ( FT_READ_USHORT( majorVersion ) ||
|
||||
FT_STREAM_SKIP( 2 ) )
|
||||
return;
|
||||
|
||||
if ( majorVersion != 1 )
|
||||
{
|
||||
FT_TRACE2(( "bad table version %d\n", majorVersion ));
|
||||
return;
|
||||
}
|
||||
|
||||
if ( FT_NEW( blend->mvar_table ) )
|
||||
return;
|
||||
|
||||
/* skip value record size */
|
||||
if ( FT_READ_USHORT( blend->mvar_table->axisCount ) ||
|
||||
FT_STREAM_SKIP( 2 ) ||
|
||||
FT_READ_USHORT( blend->mvar_table->valueCount ) ||
|
||||
FT_READ_USHORT( store_offset ) )
|
||||
return;
|
||||
|
||||
records_offset = FT_STREAM_POS();
|
||||
|
||||
error = ft_var_load_item_variation_store(
|
||||
face,
|
||||
table_offset + store_offset,
|
||||
&blend->mvar_table->itemStore );
|
||||
if ( error )
|
||||
return;
|
||||
|
||||
if ( FT_NEW_ARRAY( blend->mvar_table->values,
|
||||
blend->mvar_table->valueCount ) )
|
||||
return;
|
||||
|
||||
if ( FT_STREAM_SEEK( records_offset ) ||
|
||||
FT_FRAME_ENTER( blend->mvar_table->valueCount * GX_VALUE_SIZE ) )
|
||||
return;
|
||||
|
||||
value = blend->mvar_table->values;
|
||||
limit = value + blend->mvar_table->valueCount;
|
||||
itemStore = &blend->mvar_table->itemStore;
|
||||
|
||||
for ( ; value < limit; value++ )
|
||||
{
|
||||
value->tag = FT_GET_ULONG();
|
||||
value->outerIndex = FT_GET_USHORT();
|
||||
value->innerIndex = FT_GET_USHORT();
|
||||
|
||||
if ( value->outerIndex >= itemStore->dataCount ||
|
||||
value->innerIndex >= itemStore->varData[value->outerIndex]
|
||||
.itemCount )
|
||||
{
|
||||
error = FT_THROW( Invalid_Table );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FT_FRAME_EXIT();
|
||||
|
||||
if ( error )
|
||||
return;
|
||||
|
||||
FT_TRACE2(( "loaded\n" ));
|
||||
|
||||
value = blend->mvar_table->values;
|
||||
limit = value + blend->mvar_table->valueCount;
|
||||
|
||||
/* save original values of the data MVAR is going to modify */
|
||||
for ( ; value < limit; value++ )
|
||||
{
|
||||
FT_Short* p = ft_var_get_value_pointer( face, value->tag );
|
||||
|
||||
|
||||
value->unmodified = *p;
|
||||
}
|
||||
|
||||
face->variation_support |= TT_FACE_FLAG_VAR_MVAR;
|
||||
}
|
||||
|
||||
|
||||
typedef struct GX_GVar_Head_
|
||||
{
|
||||
FT_Long version;
|
||||
@ -1332,7 +1531,8 @@
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* Check that the font's `fvar' table is valid, parse it, and return */
|
||||
/* those data. */
|
||||
/* those data. It also loads (and parses) the `MVAR' table, if */
|
||||
/* possible. */
|
||||
/* */
|
||||
/* <InOut> */
|
||||
/* face :: The font face. */
|
||||
@ -1551,6 +1751,8 @@
|
||||
|
||||
FT_FRAME_EXIT();
|
||||
}
|
||||
|
||||
ft_var_load_mvar( face );
|
||||
}
|
||||
|
||||
/* fill the output array if requested */
|
||||
@ -3074,6 +3276,15 @@
|
||||
FT_FREE( blend->hvar_table );
|
||||
}
|
||||
|
||||
if ( blend->mvar_table )
|
||||
{
|
||||
ft_var_done_item_variation_store( face,
|
||||
&blend->mvar_table->itemStore );
|
||||
|
||||
FT_FREE( blend->mvar_table->values );
|
||||
FT_FREE( blend->mvar_table );
|
||||
}
|
||||
|
||||
FT_FREE( blend->tuplecoords );
|
||||
FT_FREE( blend->glyphoffsets );
|
||||
FT_FREE( blend );
|
||||
|
@ -132,6 +132,77 @@ FT_BEGIN_HEADER
|
||||
} GX_HVarTableRec, *GX_HVarTable;
|
||||
|
||||
|
||||
#define MVAR_TAG_GASP_0 FT_MAKE_TAG( 'g', 's', 'p', '0' )
|
||||
#define MVAR_TAG_GASP_1 FT_MAKE_TAG( 'g', 's', 'p', '1' )
|
||||
#define MVAR_TAG_GASP_2 FT_MAKE_TAG( 'g', 's', 'p', '2' )
|
||||
#define MVAR_TAG_GASP_3 FT_MAKE_TAG( 'g', 's', 'p', '3' )
|
||||
#define MVAR_TAG_GASP_4 FT_MAKE_TAG( 'g', 's', 'p', '4' )
|
||||
#define MVAR_TAG_GASP_5 FT_MAKE_TAG( 'g', 's', 'p', '5' )
|
||||
#define MVAR_TAG_GASP_6 FT_MAKE_TAG( 'g', 's', 'p', '6' )
|
||||
#define MVAR_TAG_GASP_7 FT_MAKE_TAG( 'g', 's', 'p', '7' )
|
||||
#define MVAR_TAG_GASP_8 FT_MAKE_TAG( 'g', 's', 'p', '8' )
|
||||
#define MVAR_TAG_GASP_9 FT_MAKE_TAG( 'g', 's', 'p', '9' )
|
||||
|
||||
#define MVAR_TAG_CPHT FT_MAKE_TAG( 'c', 'p', 'h', 't' )
|
||||
#define MVAR_TAG_HASC FT_MAKE_TAG( 'h', 'a', 's', 'c' )
|
||||
#define MVAR_TAG_HCLA FT_MAKE_TAG( 'h', 'c', 'l', 'a' )
|
||||
#define MVAR_TAG_HCLD FT_MAKE_TAG( 'h', 'c', 'l', 'd' )
|
||||
#define MVAR_TAG_HCOF FT_MAKE_TAG( 'h', 'c', 'o', 'f' )
|
||||
#define MVAR_TAG_HCRN FT_MAKE_TAG( 'h', 'c', 'r', 'n' )
|
||||
#define MVAR_TAG_HCRS FT_MAKE_TAG( 'h', 'c', 'r', 's' )
|
||||
#define MVAR_TAG_HDSC FT_MAKE_TAG( 'h', 'd', 's', 'c' )
|
||||
#define MVAR_TAG_HLGP FT_MAKE_TAG( 'h', 'l', 'g', 'p' )
|
||||
#define MVAR_TAG_SBXO FT_MAKE_TAG( 's', 'b', 'x', 'o' )
|
||||
#define MVAR_TAG_SBXS FT_MAKE_TAG( 's', 'b', 'x', 's' )
|
||||
#define MVAR_TAG_SBYO FT_MAKE_TAG( 's', 'b', 'y', 'o' )
|
||||
#define MVAR_TAG_SBYS FT_MAKE_TAG( 's', 'b', 'y', 's' )
|
||||
#define MVAR_TAG_SPXO FT_MAKE_TAG( 's', 'p', 'x', 'o' )
|
||||
#define MVAR_TAG_SPXS FT_MAKE_TAG( 's', 'p', 'x', 's' )
|
||||
#define MVAR_TAG_SPYO FT_MAKE_TAG( 's', 'p', 'y', 'o' )
|
||||
#define MVAR_TAG_SPYS FT_MAKE_TAG( 's', 'p', 'y', 's' )
|
||||
#define MVAR_TAG_STRO FT_MAKE_TAG( 's', 't', 'r', 'o' )
|
||||
#define MVAR_TAG_STRS FT_MAKE_TAG( 's', 't', 'r', 's' )
|
||||
#define MVAR_TAG_UNDO FT_MAKE_TAG( 'u', 'n', 'd', 'o' )
|
||||
#define MVAR_TAG_UNDS FT_MAKE_TAG( 'u', 'n', 'd', 's' )
|
||||
#define MVAR_TAG_VASC FT_MAKE_TAG( 'v', 'a', 's', 'c' )
|
||||
#define MVAR_TAG_VCOF FT_MAKE_TAG( 'v', 'c', 'o', 'f' )
|
||||
#define MVAR_TAG_VCRN FT_MAKE_TAG( 'v', 'c', 'r', 'n' )
|
||||
#define MVAR_TAG_VCRS FT_MAKE_TAG( 'v', 'c', 'r', 's' )
|
||||
#define MVAR_TAG_VDSC FT_MAKE_TAG( 'v', 'd', 's', 'c' )
|
||||
#define MVAR_TAG_VLGP FT_MAKE_TAG( 'v', 'l', 'g', 'p' )
|
||||
#define MVAR_TAG_XHGT FT_MAKE_TAG( 'x', 'h', 'g', 't' )
|
||||
|
||||
|
||||
typedef struct GX_ValueRec_
|
||||
{
|
||||
FT_ULong tag;
|
||||
FT_UShort outerIndex;
|
||||
FT_UShort innerIndex;
|
||||
|
||||
FT_Short unmodified; /* values are either FT_Short or FT_UShort */
|
||||
|
||||
} GX_ValueRec, *GX_Value;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Struct> */
|
||||
/* GX_MVarTableRec */
|
||||
/* */
|
||||
/* <Description> */
|
||||
/* Data from the `MVAR' table. */
|
||||
/* */
|
||||
typedef struct GX_MVarTableRec_
|
||||
{
|
||||
FT_UShort axisCount;
|
||||
FT_UShort valueCount;
|
||||
|
||||
GX_ItemVarStoreRec itemStore; /* Item Variation Store */
|
||||
GX_Value values; /* Value Records */
|
||||
|
||||
} GX_MVarTableRec, *GX_MVarTable;
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* */
|
||||
/* <Struct> */
|
||||
@ -165,6 +236,8 @@ FT_BEGIN_HEADER
|
||||
FT_Error hvar_error;
|
||||
GX_HVarTable hvar_table;
|
||||
|
||||
GX_MVarTable mvar_table;
|
||||
|
||||
FT_UInt tuplecount; /* shared tuples in `gvar' */
|
||||
FT_Fixed* tuplecoords; /* tuplecoords[tuplecount][num_axis] */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user