From d7b6e947a32b0ed46f1d86ae030f59061c023d15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Behdad=20Esfahbod=20=28=D8=A8=D9=87=D8=AF=D8=A7=D8=AF=20?= =?UTF-8?q?=D8=A7=D8=B3=D9=81=D9=87=D8=A8=D8=AF=29?= Date: Wed, 21 May 2025 01:34:08 -0600 Subject: [PATCH] [gxvar] Cache shared-tuple scalar values. GoogleSansFlex HB benchmark-font draw results: Before: 2.13ms After: 1.65ms Speedup: 22% * src/truetype/ttgxvar.h (GX_BlendRec): Add `tuplescalars` field. * src/truetype/ttgxvar.c (ft_var_load_gvar): Allocate `tuplescalars` array. (tt_set_mm_blend): Set its values. (TT_Vary_Apply_Glyph_Deltas): Use it. (tt_done_blend): Deallocate it. --- src/truetype/ttgxvar.c | 37 ++++++++++++++++++++++++++++++++++--- src/truetype/ttgxvar.h | 5 +++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index d0626c7b0..681c0cad2 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -1831,6 +1831,10 @@ FT_TRACE5(( "]\n" )); } + if ( FT_NEW_ARRAY( blend->tuplescalars, + gvar_head.globalCoordCount ) ) + goto Fail2; + blend->tuplecount = gvar_head.globalCoordCount; FT_TRACE5(( "\n" )); @@ -2951,6 +2955,9 @@ } } + for ( i = 0 ; i < blend->tuplecount ; i++ ) + blend->tuplescalars[i] = (FT_Fixed)-0x20000L; + Exit: return error; } @@ -4192,13 +4199,16 @@ tupleCount &= GX_TC_TUPLE_COUNT_MASK; for ( i = 0; i < tupleCount; i++ ) { - FT_UInt tupleDataSize; - FT_UInt tupleIndex; - FT_Fixed apply; + FT_UInt tupleDataSize; + FT_UInt tupleIndex; + FT_Fixed apply; + FT_Fixed* tupleScalars; FT_TRACE6(( " tuple %d:\n", i )); + tupleScalars = blend->tuplescalars; + /* Enter frame for four bytes. */ if ( stream->limit - stream->cursor < 4 ) { @@ -4214,11 +4224,24 @@ { for ( j = 0; j < blend->num_axis; j++ ) peak_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() ); + tuple_coords = peak_coords; + tupleScalars = NULL; } else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) < blend->tuplecount ) + { + FT_Fixed scalar = tupleScalars[tupleIndex & GX_TI_TUPLE_INDEX_MASK]; + + + if ( scalar != (FT_Fixed)-0x20000 ) + { + apply = scalar; + goto apply_found; + } + tuple_coords = blend->tuplecoords + ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis; + } else { FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:" @@ -4234,6 +4257,8 @@ im_start_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() ); for ( j = 0; j < blend->num_axis; j++ ) im_end_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() ); + + tupleScalars = NULL; } apply = ft_var_apply_tuple( blend, @@ -4242,6 +4267,11 @@ im_start_coords, im_end_coords ); + if ( tupleScalars ) + tupleScalars[tupleIndex & GX_TI_TUPLE_INDEX_MASK] = apply; + + apply_found: + if ( apply == 0 ) /* tuple isn't active for our blend */ { offsetToData += tupleDataSize; @@ -4624,6 +4654,7 @@ FT_FREE( blend->mvar_table ); } + FT_FREE( blend->tuplescalars ); FT_FREE( blend->tuplecoords ); FT_FREE( blend->glyphoffsets ); FT_FREE( blend ); diff --git a/src/truetype/ttgxvar.h b/src/truetype/ttgxvar.h index 9326011e3..fe8f1f6b6 100644 --- a/src/truetype/ttgxvar.h +++ b/src/truetype/ttgxvar.h @@ -255,6 +255,10 @@ FT_BEGIN_HEADER * A two-dimensional array that holds the shared tuple coordinates * in the `gvar' table. * + * tuplescalars :: + * A one-dimensional array that holds the shared tuple + * scalars in the `gvar' table for current face coordinates. + * * gv_glyphcnt :: * The number of glyphs handled in the `gvar' table. * @@ -293,6 +297,7 @@ FT_BEGIN_HEADER FT_UInt tuplecount; FT_Fixed* tuplecoords; /* tuplecoords[tuplecount][num_axis] */ + FT_Fixed* tuplescalars; /* tuplescalars[tuplecount] */ FT_UInt gv_glyphcnt; FT_ULong* glyphoffsets; /* glyphoffsets[gv_glyphcnt + 1] */