[sfnt, truetype] Add `size_reset` to `MetricsVariations`.

This is a generalization of commit

```
commit e6699596af
Author: Werner Lemberg <wl@gnu.org>
Date:   Thu Feb 2 11:38:04 2017 +0100

    [truetype] Fix MVAR post-action handling.
```

It is also possible for plain `CFF ` style fonts to contain an `fvar` and
`MVAR` table and use `cff_metrics_adjust`.  `tt_size_reset` should only be
called with `TT_Size` and never with `CFF_Size`.

Allow the "metrics-variations" service to specify the correct function (if
any) to reset `FT_Size`s after adjusting metrics.

* src/truetype/ttobjs.c (tt_size_reset): Split off some functionality
into...
(tt_size_reset_height): ... this new function.

* src/truetype/ttdriver.c (tt_service_metrics_variations): Add
`size_reset`.
(tt_size_select, tt_size_request): Updated.

* src/truetype/ttobjs.h: Updated.

* include/freetype/internal/services/svmetric.h (MetricsVariations): Add
`size_reset`.
(FT_DEFINE_SERVICE_METRICSVARIATIONSREC): Updated.

* include/freetype/internal/tttypes.h (TT_FaceRec_): Rename `var` to
`tt_var` and add `face_var`.

* src/cff/cffdrivr.c (cff_service_metrics_variations): Add `size_reset`.
(cff_hadvance_adjust, cff_metrics_adjust): Updated.

* src/cff/cffobjs.c (cff_face_init): Use `face_var`.

* src/sfnt/sfobjs.c (sfnt_init_face): Initialize `face_var`.

* src/sfnt/ttmtx.c (tt_face_get_metrics): Use `tt_var`.

* src/truetype/ttgxvar.c (tt_size_reset_iterator): Renamed to...
(ft_size_reset_iterator): ... this new function.
Call `size_reset`.
(tt_apply_mvar): Pass `size_reset` to `ft_size_reset_iterator`.

Fixes #1211
This commit is contained in:
Ben Wagner 2023-04-06 11:16:29 -04:00 committed by Werner Lemberg
parent e77d8ba87c
commit e78e2d29a9
10 changed files with 93 additions and 56 deletions

View File

@ -77,6 +77,9 @@ FT_BEGIN_HEADER
typedef void typedef void
(*FT_Metrics_Adjust_Func)( FT_Face face ); (*FT_Metrics_Adjust_Func)( FT_Face face );
typedef void
(*FT_Size_Reset_Func)( FT_Size size );
FT_DEFINE_SERVICE( MetricsVariations ) FT_DEFINE_SERVICE( MetricsVariations )
{ {
@ -90,6 +93,7 @@ FT_BEGIN_HEADER
FT_VOrg_Adjust_Func vorg_adjust; FT_VOrg_Adjust_Func vorg_adjust;
FT_Metrics_Adjust_Func metrics_adjust; FT_Metrics_Adjust_Func metrics_adjust;
FT_Size_Reset_Func size_reset;
}; };
@ -101,7 +105,8 @@ FT_BEGIN_HEADER
tsb_adjust_, \ tsb_adjust_, \
bsb_adjust_, \ bsb_adjust_, \
vorg_adjust_, \ vorg_adjust_, \
metrics_adjust_ ) \ metrics_adjust_, \
size_reset_ ) \
static const FT_Service_MetricsVariationsRec class_ = \ static const FT_Service_MetricsVariationsRec class_ = \
{ \ { \
hadvance_adjust_, \ hadvance_adjust_, \
@ -111,7 +116,8 @@ FT_BEGIN_HEADER
tsb_adjust_, \ tsb_adjust_, \
bsb_adjust_, \ bsb_adjust_, \
vorg_adjust_, \ vorg_adjust_, \
metrics_adjust_ \ metrics_adjust_, \
size_reset_ \
}; };
/* */ /* */

View File

@ -1455,8 +1455,14 @@ FT_BEGIN_HEADER
void* mm; void* mm;
/* a typeless pointer to the FT_Service_MetricsVariationsRec table */ /* a typeless pointer to the FT_Service_MetricsVariationsRec table */
/* used to handle the HVAR, VVAR, and MVAR OpenType tables */ /* used to handle the HVAR, VVAR, and MVAR OpenType tables by the */
void* var; /* "truetype" driver */
void* tt_var;
/* a typeless pointer to the FT_Service_MetricsVariationsRec table */
/* used to handle the HVAR, VVAR, and MVAR OpenType tables by this */
/* TT_Face's driver */
void* face_var;
#endif #endif
/* a typeless pointer to the PostScript Aux service */ /* a typeless pointer to the PostScript Aux service */

View File

@ -1046,7 +1046,8 @@
FT_UInt gindex, FT_UInt gindex,
FT_Int *avalue ) FT_Int *avalue )
{ {
FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; FT_Service_MetricsVariations
var = (FT_Service_MetricsVariations)face->tt_var;
return var->hadvance_adjust( FT_FACE( face ), gindex, avalue ); return var->hadvance_adjust( FT_FACE( face ), gindex, avalue );
@ -1056,7 +1057,8 @@
static void static void
cff_metrics_adjust( CFF_Face face ) cff_metrics_adjust( CFF_Face face )
{ {
FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; FT_Service_MetricsVariations
var = (FT_Service_MetricsVariations)face->tt_var;
var->metrics_adjust( FT_FACE( face ) ); var->metrics_adjust( FT_FACE( face ) );
@ -1075,7 +1077,8 @@
(FT_BSB_Adjust_Func) NULL, /* bsb_adjust */ (FT_BSB_Adjust_Func) NULL, /* bsb_adjust */
(FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */ (FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */
(FT_Metrics_Adjust_Func) cff_metrics_adjust /* metrics_adjust */ (FT_Metrics_Adjust_Func) cff_metrics_adjust, /* metrics_adjust */
(FT_Size_Reset_Func) NULL /* size_reset */
) )
#endif #endif

View File

@ -719,8 +719,10 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
{ {
FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; FT_Service_MultiMasters
FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; mm = (FT_Service_MultiMasters)face->mm;
FT_Service_MetricsVariations
var = (FT_Service_MetricsVariations)face->face_var;
FT_UInt instance_index = (FT_UInt)face_index >> 16; FT_UInt instance_index = (FT_UInt)face_index >> 16;

View File

@ -534,17 +534,23 @@
0 ); 0 );
} }
if ( !face->var ) if ( !face->tt_var )
{ {
/* we want the metrics variations interface */ /* we want the metrics variations interface */
/* from the `truetype' module only */ /* from the `truetype' module only */
FT_Module tt_module = FT_Get_Module( library, "truetype" ); FT_Module tt_module = FT_Get_Module( library, "truetype" );
face->var = ft_module_get_service( tt_module, face->tt_var = ft_module_get_service( tt_module,
FT_SERVICE_ID_METRICS_VARIATIONS, FT_SERVICE_ID_METRICS_VARIATIONS,
0 ); 0 );
} }
if ( !face->face_var )
face->face_var = ft_module_get_service(
&face->root.driver->root,
FT_SERVICE_ID_METRICS_VARIATIONS,
0 );
#endif #endif
FT_TRACE2(( "SFNT driver\n" )); FT_TRACE2(( "SFNT driver\n" ));

View File

@ -239,7 +239,7 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
FT_Service_MetricsVariations var = FT_Service_MetricsVariations var =
(FT_Service_MetricsVariations)face->var; (FT_Service_MetricsVariations)face->tt_var;
#endif #endif

View File

@ -316,7 +316,7 @@
/* use the scaled metrics, even when tt_size_reset fails */ /* use the scaled metrics, even when tt_size_reset fails */
FT_Select_Metrics( size->face, strike_index ); FT_Select_Metrics( size->face, strike_index );
tt_size_reset( ttsize, 0 ); /* ignore return value */ tt_size_reset( ttsize ); /* ignore return value */
} }
else else
{ {
@ -377,7 +377,7 @@
if ( FT_IS_SCALABLE( size->face ) ) if ( FT_IS_SCALABLE( size->face ) )
{ {
error = tt_size_reset( ttsize, 0 ); error = tt_size_reset( ttsize );
#ifdef TT_USE_BYTECODE_INTERPRETER #ifdef TT_USE_BYTECODE_INTERPRETER
/* for the `MPS' bytecode instruction we need the point size */ /* for the `MPS' bytecode instruction we need the point size */
@ -559,7 +559,8 @@
(FT_BSB_Adjust_Func) NULL, /* bsb_adjust */ (FT_BSB_Adjust_Func) NULL, /* bsb_adjust */
(FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */ (FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */
(FT_Metrics_Adjust_Func) tt_apply_mvar /* metrics_adjust */ (FT_Metrics_Adjust_Func) tt_apply_mvar, /* metrics_adjust */
(FT_Size_Reset_Func) tt_size_reset_height /* size_reset */
) )
#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */

View File

@ -1462,15 +1462,14 @@
static FT_Error static FT_Error
tt_size_reset_iterator( FT_ListNode node, ft_size_reset_iterator( FT_ListNode node,
void* user ) void* user )
{ {
TT_Size size = (TT_Size)node->data; FT_Size size = (FT_Size)node->data;
FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)user;
FT_UNUSED( user );
tt_size_reset( size, 1 ); var->size_reset( size );
return FT_Err_Ok; return FT_Err_Ok;
} }
@ -1543,6 +1542,9 @@
/* adjust all derived values */ /* adjust all derived values */
{ {
FT_Service_MetricsVariations var =
(FT_Service_MetricsVariations)face->face_var;
FT_Face root = &face->root; FT_Face root = &face->root;
/* /*
@ -1584,11 +1586,12 @@
face->postscript.underlineThickness / 2; face->postscript.underlineThickness / 2;
root->underline_thickness = face->postscript.underlineThickness; root->underline_thickness = face->postscript.underlineThickness;
/* iterate over all FT_Size objects and call `tt_size_reset' */ /* iterate over all FT_Size objects and call `var->size_reset' */
/* to propagate the metrics changes */ /* to propagate the metrics changes */
FT_List_Iterate( &root->sizes_list, if ( var && var->size_reset )
tt_size_reset_iterator, FT_List_Iterate( &root->sizes_list,
NULL ); ft_size_reset_iterator,
(void*)var );
} }
} }

View File

@ -1338,39 +1338,25 @@
/************************************************************************** /**************************************************************************
* *
* @Function: * @Function:
* tt_size_reset * tt_size_reset_height
* *
* @Description: * @Description:
* Reset a TrueType size when resolutions and character dimensions * Recompute a TrueType size's ascender, descender, and height
* have been changed. * when resolutions and character dimensions have been changed.
* Used for variation fonts as an iterator function.
* *
* @Input: * @Input:
* size :: * size ::
* A handle to the target size object. * A handle to the target size object.
*
* only_height ::
* Only recompute ascender, descender, and height;
* this flag is used for variation fonts where
* `tt_size_reset' is used as an iterator function.
*/ */
FT_LOCAL_DEF( FT_Error ) FT_LOCAL_DEF( FT_Error )
tt_size_reset( TT_Size size, tt_size_reset_height( TT_Size size )
FT_Bool only_height )
{ {
TT_Face face; TT_Face face = (TT_Face)size->root.face;
FT_Size_Metrics* size_metrics; FT_Size_Metrics* size_metrics = &size->hinted_metrics;
face = (TT_Face)size->root.face;
/* nothing to do for CFF2 */
if ( face->is_cff2 )
return FT_Err_Ok;
size->ttmetrics.valid = FALSE; size->ttmetrics.valid = FALSE;
size_metrics = &size->hinted_metrics;
/* copy the result from base layer */ /* copy the result from base layer */
*size_metrics = size->root.metrics; *size_metrics = size->root.metrics;
@ -1397,12 +1383,34 @@
size->ttmetrics.valid = TRUE; size->ttmetrics.valid = TRUE;
if ( only_height ) return FT_Err_Ok;
{ }
/* we must not recompute the scaling values here since */
/* `tt_size_reset' was already called (with only_height = 0) */
return FT_Err_Ok; /**************************************************************************
} *
* @Function:
* tt_size_reset
*
* @Description:
* Reset a TrueType size when resolutions and character dimensions
* have been changed.
*
* @Input:
* size ::
* A handle to the target size object.
*/
FT_LOCAL_DEF( FT_Error )
tt_size_reset( TT_Size size )
{
FT_Error error;
TT_Face face = (TT_Face)size->root.face;
FT_Size_Metrics* size_metrics = &size->hinted_metrics;
error = tt_size_reset_height( size );
if ( error )
return error;
if ( face->header.Flags & 8 ) if ( face->header.Flags & 8 )
{ {

View File

@ -391,8 +391,10 @@ FT_BEGIN_HEADER
#endif /* TT_USE_BYTECODE_INTERPRETER */ #endif /* TT_USE_BYTECODE_INTERPRETER */
FT_LOCAL( FT_Error ) FT_LOCAL( FT_Error )
tt_size_reset( TT_Size size, tt_size_reset_height( TT_Size size );
FT_Bool only_height );
FT_LOCAL( FT_Error )
tt_size_reset( TT_Size size );
/************************************************************************** /**************************************************************************