[psaux] Performance improvements (#43248).

Implement proper disabling of hinting procedures when not hinting. This
results in a ~30% speedup.

* src/psaux/pshints.h (CF2_HintData): Gather hintmaps into hinting context.
* src/psaux/pshints.c: Do not allocate structs unless needed.
Skip hintmap funcs calls.
Update references.

* src/psaux/psintrp.c (cf2_interpT2CharString): Initialization for hinting
context.
<cntrmask, hintmask>: Ignore if not hinting.
Update references.
This commit is contained in:
Ewald Hew 2017-08-21 14:20:47 +08:00
parent 423d7cf165
commit c48e55b738
3 changed files with 89 additions and 54 deletions

View File

@ -814,6 +814,9 @@
FT_Byte maskByte; FT_Byte maskByte;
if ( !hintmap )
return;
/* check whether initial map is constructed */ /* check whether initial map is constructed */
if ( !initialMap && !cf2_hintmap_isValid( hintmap->initialHintMap ) ) if ( !initialMap && !cf2_hintmap_isValid( hintmap->initialHintMap ) )
{ {
@ -1072,6 +1075,7 @@
/* CF2_Fixed hShift, */ /* CF2_Fixed hShift, */
CF2_ArrStack hStemHintArray, CF2_ArrStack hStemHintArray,
CF2_ArrStack vStemHintArray, CF2_ArrStack vStemHintArray,
CF2_HintData hintData,
CF2_HintMask hintMask, CF2_HintMask hintMask,
CF2_Fixed hintOriginY, CF2_Fixed hintOriginY,
const CF2_Blues blues, const CF2_Blues blues,
@ -1082,26 +1086,34 @@
glyphpath->font = font; glyphpath->font = font;
glyphpath->callbacks = callbacks; glyphpath->callbacks = callbacks;
cf2_arrstack_init( &glyphpath->hintMoves, if ( font->hinted )
font->memory, {
&font->error, cf2_arrstack_init( &hintData->hintMoves,
sizeof ( CF2_HintMoveRec ) ); font->memory,
&font->error,
sizeof ( CF2_HintMoveRec ) );
cf2_hintmap_init( &glyphpath->initialHintMap, cf2_hintmap_init( &hintData->initialHintMap,
font, font,
&glyphpath->initialHintMap, &hintData->initialHintMap,
&glyphpath->hintMoves, &hintData->hintMoves,
scaleY ); scaleY );
cf2_hintmap_init( &glyphpath->firstHintMap, cf2_hintmap_init( &hintData->firstHintMap,
font, font,
&glyphpath->initialHintMap, &hintData->initialHintMap,
&glyphpath->hintMoves, &hintData->hintMoves,
scaleY ); scaleY );
cf2_hintmap_init( &glyphpath->hintMap, cf2_hintmap_init( &hintData->hintMap,
font, font,
&glyphpath->initialHintMap, &hintData->initialHintMap,
&glyphpath->hintMoves, &hintData->hintMoves,
scaleY ); scaleY );
glyphpath->hintMap = &hintData->hintMap;
glyphpath->firstHintMap = &hintData->firstHintMap;
glyphpath->initialHintMap = &hintData->initialHintMap;
glyphpath->hintMoves = &hintData->hintMoves;
}
glyphpath->scaleX = font->innerTransform.a; glyphpath->scaleX = font->innerTransform.a;
glyphpath->scaleC = font->innerTransform.c; glyphpath->scaleC = font->innerTransform.c;
@ -1138,7 +1150,8 @@
FT_LOCAL_DEF( void ) FT_LOCAL_DEF( void )
cf2_glyphpath_finalize( CF2_GlyphPath glyphpath ) cf2_glyphpath_finalize( CF2_GlyphPath glyphpath )
{ {
cf2_arrstack_finalize( &glyphpath->hintMoves ); if ( glyphpath->font->hinted )
cf2_arrstack_finalize( glyphpath->hintMoves );
} }
@ -1160,7 +1173,9 @@
pt.x = ADD_INT32( FT_MulFix( glyphpath->scaleX, x ), pt.x = ADD_INT32( FT_MulFix( glyphpath->scaleX, x ),
FT_MulFix( glyphpath->scaleC, y ) ); FT_MulFix( glyphpath->scaleC, y ) );
pt.y = cf2_hintmap_map( hintmap, y ); pt.y = hintmap ? cf2_hintmap_map( hintmap, y )
: FT_MulFix( glyphpath->scaleY, y );
ppt->x = ADD_INT32( ppt->x = ADD_INT32(
FT_MulFix( glyphpath->font->outerTransform.a, pt.x ), FT_MulFix( glyphpath->font->outerTransform.a, pt.x ),
@ -1366,7 +1381,7 @@
{ {
/* use first hint map if closing */ /* use first hint map if closing */
cf2_glyphpath_hintPoint( glyphpath, cf2_glyphpath_hintPoint( glyphpath,
&glyphpath->firstHintMap, glyphpath->firstHintMap,
&params.pt1, &params.pt1,
glyphpath->prevElemP1.x, glyphpath->prevElemP1.x,
glyphpath->prevElemP1.y ); glyphpath->prevElemP1.y );
@ -1428,7 +1443,7 @@
/* if we are closing the subpath, then nextP0 is in the first */ /* if we are closing the subpath, then nextP0 is in the first */
/* hint zone */ /* hint zone */
cf2_glyphpath_hintPoint( glyphpath, cf2_glyphpath_hintPoint( glyphpath,
&glyphpath->firstHintMap, glyphpath->firstHintMap,
&params.pt1, &params.pt1,
nextP0->x, nextP0->x,
nextP0->y ); nextP0->y );
@ -1478,7 +1493,8 @@
/* Test if move has really happened yet; it would have called */ /* Test if move has really happened yet; it would have called */
/* `cf2_hintmap_build' to set `isValid'. */ /* `cf2_hintmap_build' to set `isValid'. */
if ( !cf2_hintmap_isValid( &glyphpath->hintMap ) ) if ( glyphpath->font->hinted &&
!cf2_hintmap_isValid( glyphpath->hintMap ) )
{ {
/* we are here iff first subpath is missing a moveto operator: */ /* we are here iff first subpath is missing a moveto operator: */
/* synthesize first moveTo to finish initialization of hintMap */ /* synthesize first moveTo to finish initialization of hintMap */
@ -1488,7 +1504,7 @@
} }
cf2_glyphpath_hintPoint( glyphpath, cf2_glyphpath_hintPoint( glyphpath,
&glyphpath->hintMap, glyphpath->hintMap,
&params.pt1, &params.pt1,
start.x, start.x,
start.y ); start.y );
@ -1677,18 +1693,21 @@
glyphpath->moveIsPending = TRUE; glyphpath->moveIsPending = TRUE;
/* ensure we have a valid map with current mask */ /* ensure we have a valid map with current mask, if hinting is on */
if ( !cf2_hintmap_isValid( &glyphpath->hintMap ) || if ( glyphpath->font->hinted )
cf2_hintmask_isNew( glyphpath->hintMask ) ) {
cf2_hintmap_build( &glyphpath->hintMap, if ( !cf2_hintmap_isValid( glyphpath->hintMap ) ||
glyphpath->hStemHintArray, cf2_hintmask_isNew( glyphpath->hintMask ) )
glyphpath->vStemHintArray, cf2_hintmap_build( glyphpath->hintMap,
glyphpath->hintMask, glyphpath->hStemHintArray,
glyphpath->hintOriginY, glyphpath->vStemHintArray,
FALSE ); glyphpath->hintMask,
glyphpath->hintOriginY,
FALSE );
/* save a copy of current HintMap to use when drawing initial point */ /* save a copy of current HintMap to use when drawing initial point */
glyphpath->firstHintMap = glyphpath->hintMap; /* structure copy */ *glyphpath->firstHintMap = *glyphpath->hintMap; /* structure copy */
}
} }
@ -1768,11 +1787,12 @@
if ( glyphpath->elemIsQueued ) if ( glyphpath->elemIsQueued )
{ {
FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) || FT_ASSERT( !glyphpath->font->hinted ||
glyphpath->hintMap.count == 0 ); cf2_hintmap_isValid( glyphpath->hintMap ) ||
glyphpath->hintMap->count == 0 );
cf2_glyphpath_pushPrevElem( glyphpath, cf2_glyphpath_pushPrevElem( glyphpath,
&glyphpath->hintMap, glyphpath->hintMap,
&P0, &P0,
P1, P1,
FALSE ); FALSE );
@ -1786,7 +1806,7 @@
/* update current map */ /* update current map */
if ( newHintMap ) if ( newHintMap )
cf2_hintmap_build( &glyphpath->hintMap, cf2_hintmap_build( glyphpath->hintMap,
glyphpath->hStemHintArray, glyphpath->hStemHintArray,
glyphpath->vStemHintArray, glyphpath->vStemHintArray,
glyphpath->hintMask, glyphpath->hintMask,
@ -1856,11 +1876,12 @@
if ( glyphpath->elemIsQueued ) if ( glyphpath->elemIsQueued )
{ {
FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) || FT_ASSERT( !glyphpath->font->hinted ||
glyphpath->hintMap.count == 0 ); cf2_hintmap_isValid( glyphpath->hintMap ) ||
glyphpath->hintMap->count == 0 );
cf2_glyphpath_pushPrevElem( glyphpath, cf2_glyphpath_pushPrevElem( glyphpath,
&glyphpath->hintMap, glyphpath->hintMap,
&P0, &P0,
P1, P1,
FALSE ); FALSE );
@ -1876,7 +1897,7 @@
/* update current map */ /* update current map */
if ( cf2_hintmask_isNew( glyphpath->hintMask ) ) if ( cf2_hintmask_isNew( glyphpath->hintMask ) )
cf2_hintmap_build( &glyphpath->hintMap, cf2_hintmap_build( glyphpath->hintMap,
glyphpath->hStemHintArray, glyphpath->hStemHintArray,
glyphpath->vStemHintArray, glyphpath->vStemHintArray,
glyphpath->hintMask, glyphpath->hintMask,
@ -1907,7 +1928,7 @@
/* empty the final element from the queue and close the path */ /* empty the final element from the queue and close the path */
if ( glyphpath->elemIsQueued ) if ( glyphpath->elemIsQueued )
cf2_glyphpath_pushPrevElem( glyphpath, cf2_glyphpath_pushPrevElem( glyphpath,
&glyphpath->hintMap, glyphpath->hintMap,
&glyphpath->offsetStart0, &glyphpath->offsetStart0,
glyphpath->offsetStart1, glyphpath->offsetStart1,
TRUE ); TRUE );

View File

@ -173,6 +173,16 @@ FT_BEGIN_HEADER
FT_Bool initialMap ); FT_Bool initialMap );
typedef struct CF2_HintDataRec_
{
CF2_HintMapRec hintMap; /* current hint map */
CF2_HintMapRec firstHintMap; /* saved copy */
CF2_HintMapRec initialHintMap; /* based on all captured hints */
CF2_ArrStackRec hintMoves; /* list of hint moves for 2nd pass */
} CF2_HintDataRec, *CF2_HintData;
/* /*
* GlyphPath is a wrapper for drawing operations that scales the * GlyphPath is a wrapper for drawing operations that scales the
* coordinates according to the render matrix and HintMap. It also tracks * coordinates according to the render matrix and HintMap. It also tracks
@ -181,17 +191,15 @@ FT_BEGIN_HEADER
*/ */
typedef struct CF2_GlyphPathRec_ typedef struct CF2_GlyphPathRec_
{ {
/* TODO: gather some of these into a hinting context */
CF2_Font font; /* font instance */ CF2_Font font; /* font instance */
CF2_OutlineCallbacks callbacks; /* outline consumer */ CF2_OutlineCallbacks callbacks; /* outline consumer */
CF2_HintMapRec hintMap; /* current hint map */ CF2_HintMap hintMap; /* ptr to current hint map */
CF2_HintMapRec firstHintMap; /* saved copy */ CF2_HintMap firstHintMap; /* ptr to saved copy */
CF2_HintMapRec initialHintMap; /* based on all captured hints */ CF2_HintMap initialHintMap; /* based on all captured hints */
CF2_ArrStackRec hintMoves; /* list of hint moves for 2nd pass */ CF2_ArrStack hintMoves; /* list of hint moves for 2nd pass */
CF2_Fixed scaleX; /* matrix a */ CF2_Fixed scaleX; /* matrix a */
CF2_Fixed scaleC; /* matrix c */ CF2_Fixed scaleC; /* matrix c */
@ -253,6 +261,7 @@ FT_BEGIN_HEADER
/* CF2_Fixed hShift, */ /* CF2_Fixed hShift, */
CF2_ArrStack hStemHintArray, CF2_ArrStack hStemHintArray,
CF2_ArrStack vStemHintArray, CF2_ArrStack vStemHintArray,
CF2_HintData hintData,
CF2_HintMask hintMask, CF2_HintMask hintMask,
CF2_Fixed hintOrigin, CF2_Fixed hintOrigin,
const CF2_Blues blues, const CF2_Blues blues,

View File

@ -524,9 +524,9 @@
CF2_ArrStackRec vStemHintArray; CF2_ArrStackRec vStemHintArray;
CF2_HintMaskRec hintMask; CF2_HintMaskRec hintMask;
CF2_HintDataRec hintData;
CF2_GlyphPathRec glyphPath; CF2_GlyphPathRec glyphPath;
FT_ZERO( &storage ); FT_ZERO( &storage );
FT_ZERO( &results ); FT_ZERO( &results );
FT_ZERO( &flexStore ); FT_ZERO( &flexStore );
@ -560,6 +560,7 @@
/* hShift, */ /* hShift, */
&hStemHintArray, &hStemHintArray,
&vStemHintArray, &vStemHintArray,
&hintData,
&hintMask, &hintMask,
hintOriginY, hintOriginY,
&font->blues, &font->blues,
@ -2504,6 +2505,10 @@
/* `cf2_hintmask_read' (which also traces the mask bytes) */ /* `cf2_hintmask_read' (which also traces the mask bytes) */
FT_TRACE4(( op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" )); FT_TRACE4(( op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" ));
/* disregard if not hinting */
if ( !font->hinted )
break;
/* never add hints after the mask is computed */ /* never add hints after the mask is computed */
if ( cf2_stack_count( opStack ) > 1 && if ( cf2_stack_count( opStack ) > 1 &&
cf2_hintmask_isValid( &hintMask ) ) cf2_hintmask_isValid( &hintMask ) )
@ -2553,8 +2558,8 @@
cf2_hintmap_init( &counterHintMap, cf2_hintmap_init( &counterHintMap,
font, font,
&glyphPath.initialHintMap, glyphPath.initialHintMap,
&glyphPath.hintMoves, glyphPath.hintMoves,
scaleY ); scaleY );
cf2_hintmask_init( &counterMask, error ); cf2_hintmask_init( &counterMask, error );