From e78e2d29a95baf6053e30cc9422aa20319259803 Mon Sep 17 00:00:00 2001 From: Ben Wagner Date: Thu, 6 Apr 2023 11:16:29 -0400 Subject: [sfnt, truetype] Add `size_reset` to `MetricsVariations`. This is a generalization of commit ``` commit e6699596af5c5d6f0ae0ea06e19df87dce088df8 Author: Werner Lemberg 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 --- include/freetype/internal/services/svmetric.h | 10 ++++- include/freetype/internal/tttypes.h | 10 ++++- src/cff/cffdrivr.c | 9 ++-- src/cff/cffobjs.c | 6 ++- src/sfnt/sfobjs.c | 14 ++++-- src/sfnt/ttmtx.c | 2 +- src/truetype/ttdriver.c | 7 +-- src/truetype/ttgxvar.c | 23 +++++----- src/truetype/ttobjs.c | 62 +++++++++++++++------------ src/truetype/ttobjs.h | 6 ++- 10 files changed, 93 insertions(+), 56 deletions(-) diff --git a/include/freetype/internal/services/svmetric.h b/include/freetype/internal/services/svmetric.h index e588ea487..d067dc977 100644 --- a/include/freetype/internal/services/svmetric.h +++ b/include/freetype/internal/services/svmetric.h @@ -77,6 +77,9 @@ FT_BEGIN_HEADER typedef void (*FT_Metrics_Adjust_Func)( FT_Face face ); + typedef void + (*FT_Size_Reset_Func)( FT_Size size ); + FT_DEFINE_SERVICE( MetricsVariations ) { @@ -90,6 +93,7 @@ FT_BEGIN_HEADER FT_VOrg_Adjust_Func vorg_adjust; FT_Metrics_Adjust_Func metrics_adjust; + FT_Size_Reset_Func size_reset; }; @@ -101,7 +105,8 @@ FT_BEGIN_HEADER tsb_adjust_, \ bsb_adjust_, \ vorg_adjust_, \ - metrics_adjust_ ) \ + metrics_adjust_, \ + size_reset_ ) \ static const FT_Service_MetricsVariationsRec class_ = \ { \ hadvance_adjust_, \ @@ -111,7 +116,8 @@ FT_BEGIN_HEADER tsb_adjust_, \ bsb_adjust_, \ vorg_adjust_, \ - metrics_adjust_ \ + metrics_adjust_, \ + size_reset_ \ }; /* */ diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h index dc790f932..d257d05bd 100644 --- a/include/freetype/internal/tttypes.h +++ b/include/freetype/internal/tttypes.h @@ -1455,8 +1455,14 @@ FT_BEGIN_HEADER void* mm; /* a typeless pointer to the FT_Service_MetricsVariationsRec table */ - /* used to handle the HVAR, VVAR, and MVAR OpenType tables */ - void* var; + /* used to handle the HVAR, VVAR, and MVAR OpenType tables by the */ + /* "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 /* a typeless pointer to the PostScript Aux service */ diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c index 4e2e0e00d..688c4c0b3 100644 --- a/src/cff/cffdrivr.c +++ b/src/cff/cffdrivr.c @@ -1046,7 +1046,8 @@ FT_UInt gindex, 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 ); @@ -1056,7 +1057,8 @@ static void 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 ) ); @@ -1075,7 +1077,8 @@ (FT_BSB_Adjust_Func) NULL, /* bsb_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 diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c index 3e94a283e..9608a4178 100644 --- a/src/cff/cffobjs.c +++ b/src/cff/cffobjs.c @@ -719,8 +719,10 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT { - FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; - FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; + FT_Service_MultiMasters + 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; diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c index 6469da9ab..13f2f45f4 100644 --- a/src/sfnt/sfobjs.c +++ b/src/sfnt/sfobjs.c @@ -534,17 +534,23 @@ 0 ); } - if ( !face->var ) + if ( !face->tt_var ) { /* we want the metrics variations interface */ /* from the `truetype' module only */ FT_Module tt_module = FT_Get_Module( library, "truetype" ); - face->var = ft_module_get_service( tt_module, - FT_SERVICE_ID_METRICS_VARIATIONS, - 0 ); + face->tt_var = ft_module_get_service( tt_module, + FT_SERVICE_ID_METRICS_VARIATIONS, + 0 ); } + + if ( !face->face_var ) + face->face_var = ft_module_get_service( + &face->root.driver->root, + FT_SERVICE_ID_METRICS_VARIATIONS, + 0 ); #endif FT_TRACE2(( "SFNT driver\n" )); diff --git a/src/sfnt/ttmtx.c b/src/sfnt/ttmtx.c index 5e53e6dd4..38ee9ae72 100644 --- a/src/sfnt/ttmtx.c +++ b/src/sfnt/ttmtx.c @@ -239,7 +239,7 @@ #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT FT_Service_MetricsVariations var = - (FT_Service_MetricsVariations)face->var; + (FT_Service_MetricsVariations)face->tt_var; #endif diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c index 4e689e99a..c2e041cd3 100644 --- a/src/truetype/ttdriver.c +++ b/src/truetype/ttdriver.c @@ -316,7 +316,7 @@ /* use the scaled metrics, even when tt_size_reset fails */ FT_Select_Metrics( size->face, strike_index ); - tt_size_reset( ttsize, 0 ); /* ignore return value */ + tt_size_reset( ttsize ); /* ignore return value */ } else { @@ -377,7 +377,7 @@ if ( FT_IS_SCALABLE( size->face ) ) { - error = tt_size_reset( ttsize, 0 ); + error = tt_size_reset( ttsize ); #ifdef TT_USE_BYTECODE_INTERPRETER /* for the `MPS' bytecode instruction we need the point size */ @@ -559,7 +559,8 @@ (FT_BSB_Adjust_Func) NULL, /* bsb_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 */ diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c index 20d27ee42..3af028aac 100644 --- a/src/truetype/ttgxvar.c +++ b/src/truetype/ttgxvar.c @@ -1462,15 +1462,14 @@ static FT_Error - tt_size_reset_iterator( FT_ListNode node, + ft_size_reset_iterator( FT_ListNode node, void* user ) { - TT_Size size = (TT_Size)node->data; - - FT_UNUSED( user ); + FT_Size size = (FT_Size)node->data; + FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)user; - tt_size_reset( size, 1 ); + var->size_reset( size ); return FT_Err_Ok; } @@ -1543,6 +1542,9 @@ /* adjust all derived values */ { + FT_Service_MetricsVariations var = + (FT_Service_MetricsVariations)face->face_var; + FT_Face root = &face->root; /* @@ -1584,11 +1586,12 @@ face->postscript.underlineThickness / 2; root->underline_thickness = face->postscript.underlineThickness; - /* iterate over all FT_Size objects and call `tt_size_reset' */ - /* to propagate the metrics changes */ - FT_List_Iterate( &root->sizes_list, - tt_size_reset_iterator, - NULL ); + /* iterate over all FT_Size objects and call `var->size_reset' */ + /* to propagate the metrics changes */ + if ( var && var->size_reset ) + FT_List_Iterate( &root->sizes_list, + ft_size_reset_iterator, + (void*)var ); } } diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c index 4a8873fd8..ee4f3de1b 100644 --- a/src/truetype/ttobjs.c +++ b/src/truetype/ttobjs.c @@ -1338,39 +1338,25 @@ /************************************************************************** * * @Function: - * tt_size_reset + * tt_size_reset_height * * @Description: - * Reset a TrueType size when resolutions and character dimensions - * have been changed. + * Recompute a TrueType size's ascender, descender, and height + * when resolutions and character dimensions have been changed. + * Used for variation fonts as an iterator function. * * @Input: * size :: * 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 ) - tt_size_reset( TT_Size size, - FT_Bool only_height ) + tt_size_reset_height( TT_Size size ) { - TT_Face face; - FT_Size_Metrics* size_metrics; - - - face = (TT_Face)size->root.face; - - /* nothing to do for CFF2 */ - if ( face->is_cff2 ) - return FT_Err_Ok; + TT_Face face = (TT_Face)size->root.face; + FT_Size_Metrics* size_metrics = &size->hinted_metrics; size->ttmetrics.valid = FALSE; - size_metrics = &size->hinted_metrics; - /* copy the result from base layer */ *size_metrics = size->root.metrics; @@ -1397,12 +1383,34 @@ size->ttmetrics.valid = TRUE; - if ( only_height ) - { - /* we must not recompute the scaling values here since */ - /* `tt_size_reset' was already called (with only_height = 0) */ - return FT_Err_Ok; - } + 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 ) { diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h index bc6fbe7f1..d74264e57 100644 --- a/src/truetype/ttobjs.h +++ b/src/truetype/ttobjs.h @@ -391,8 +391,10 @@ FT_BEGIN_HEADER #endif /* TT_USE_BYTECODE_INTERPRETER */ FT_LOCAL( FT_Error ) - tt_size_reset( TT_Size size, - FT_Bool only_height ); + tt_size_reset_height( TT_Size size ); + + FT_LOCAL( FT_Error ) + tt_size_reset( TT_Size size ); /************************************************************************** -- cgit v1.2.1