[hvf] Fix macro usage and metrics calculations.

* src/hvf/hvfload.c (hvf_render_callback): Fix glyph loader macro calls
and metrics calculations.
* src/hvf/hvfobjs.c (hvf_refresh_axis_coordinates,
hvf_init_axis_coordinates): Tweak macro usage.
* src/hvf/hvfobjs.h (HVF_RenderContext): Remove `face`.

* include/freetype/ftmoderr.h: Add HVF error base.
This commit is contained in:
Deborah Goldsmith 2026-05-12 23:48:38 +00:00 committed by Alexei Podtelezhnikov
parent 3c364321ad
commit c39ca391b3
4 changed files with 88 additions and 57 deletions

View file

@ -172,6 +172,7 @@
FT_MODERRDEF( Winfonts, 0x1500, "Windows FON/FNT module" )
FT_MODERRDEF( GXvalid, 0x1600, "GX validation module" )
FT_MODERRDEF( Sdf, 0x1700, "Signed distance field raster module" )
FT_MODERRDEF( HVF, 0x1800, "HVF module" )
#ifdef FT_MODERR_END_LIST

View file

@ -184,9 +184,7 @@
/* Move-to or line-to point with pre-calculated scaling factors. */
error = FT_GLYPHLOADER_CHECK_POINTS( ctx->loader,
ctx->outline->n_points + 1,
ctx->outline->n_contours );
error = FT_GLYPHLOADER_CHECK_POINTS( ctx->loader, 1, 0 );
if ( error )
return HVFPartRenderActionStop;
@ -211,9 +209,7 @@
/* Quadratic curve with pre-calculated scaling factors. */
error = FT_GLYPHLOADER_CHECK_POINTS( ctx->loader,
ctx->outline->n_points + 2,
ctx->outline->n_contours );
error = FT_GLYPHLOADER_CHECK_POINTS( ctx->loader, 2, 0 );
if ( error )
return HVFPartRenderActionStop;
@ -249,9 +245,7 @@
/* Cubic curve with pre-calculated scaling factors. */
error = FT_GLYPHLOADER_CHECK_POINTS( ctx->loader,
ctx->outline->n_points + 3,
ctx->outline->n_contours );
error = FT_GLYPHLOADER_CHECK_POINTS( ctx->loader, 3, 0 );
if ( error )
return HVFPartRenderActionStop;
@ -295,9 +289,7 @@
if ( ctx->path_begun && ctx->outline->n_points > 0 )
{
/* Check space for contour. */
error = FT_GLYPHLOADER_CHECK_POINTS( ctx->loader,
ctx->outline->n_points,
ctx->outline->n_contours + 1 );
error = FT_GLYPHLOADER_CHECK_POINTS( ctx->loader, 0, 1 );
if ( error )
return HVFPartRenderActionStop;
@ -380,7 +372,6 @@
return FT_THROW( Invalid_Glyph_Index );
/* Initialize render context. */
context.face = face;
context.loader = loader;
context.path_begun = 0;
@ -431,6 +422,7 @@
" hvf_set_variation_axes failed (error %d)\n", error ));
}
#endif
error = FT_Err_Ok; /* axis failure is non-fatal */
/* Render the glyph using HVF. */
hvf_result = HVF_render_current_part( (HVFPartRenderer*)face->renderer,
@ -453,9 +445,7 @@
if ( context.path_begun && context.outline->n_points > 0 )
{
/* Check space for contour. */
error = FT_GLYPHLOADER_CHECK_POINTS( loader,
context.outline->n_points,
context.outline->n_contours + 1 );
error = FT_GLYPHLOADER_CHECK_POINTS( loader, 0, 1 );
if ( !error )
{
context.outline->contours[context.outline->n_contours++] =
@ -476,14 +466,19 @@
/* Set glyph metrics - get from TrueType infrastructure when possible. */
{
FT_UShort advance_width = 0;
FT_Short left_bearing = 0;
FT_BBox bbox;
FT_UShort advance_width = 0;
FT_Short left_bearing = 0;
TT_Face tt_face = (TT_Face)face;
SFNT_Service sfnt = (SFNT_Service)tt_face->sfnt;
FT_Bool has_vertical_info;
FT_Pos top; /* vertical top side bearing */
FT_Pos advance; /* vertical advance height */
/* Get metrics from TrueType tables if available. */
/* Get horizontal metrics from TrueType tables if available. */
if ( sfnt && glyph_index < (FT_UInt)face->root.root.num_glyphs )
sfnt->get_metrics( tt_face, 0, glyph_index,
&left_bearing, &advance_width );
@ -494,42 +489,79 @@
left_bearing = 0;
}
/* Set up unscaled metrics. */
glyph->metrics.width = advance_width;
glyph->metrics.height = size->metrics.y_ppem;
glyph->metrics.horiBearingX = left_bearing;
glyph->metrics.horiBearingY = glyph->metrics.height;
glyph->metrics.horiAdvance = advance_width;
glyph->metrics.vertBearingX = glyph->metrics.width / 2;
glyph->metrics.vertBearingY = 0;
glyph->metrics.vertAdvance = glyph->metrics.height;
}
glyph->linearHoriAdvance = advance_width;
/* Scale metrics if scaling was applied */
/* (coordinates already scaled in callback). */
if ( apply_scaling )
{
FT_Size_Metrics* metrics = &size->metrics;
/* Get vertical metrics from vmtx table or synthesize them, */
/* consistent with TrueType and CFF drivers for SFNT-based fonts. */
has_vertical_info =
FT_BOOL( tt_face->vertical_info &&
tt_face->vertical.number_Of_VMetrics > 0 );
/* Scale metrics using size metrics - */
/* coordinates already scaled in callback. */
glyph->metrics.width = FT_MulFix( glyph->metrics.width,
metrics->x_scale );
glyph->metrics.height = FT_MulFix( glyph->metrics.height,
metrics->y_scale );
glyph->metrics.horiBearingX = FT_MulFix( glyph->metrics.horiBearingX,
metrics->x_scale );
glyph->metrics.horiBearingY = FT_MulFix( glyph->metrics.horiBearingY,
metrics->y_scale );
glyph->metrics.horiAdvance = FT_MulFix( glyph->metrics.horiAdvance,
metrics->x_scale );
glyph->metrics.vertBearingX = FT_MulFix( glyph->metrics.vertBearingX,
metrics->x_scale );
glyph->metrics.vertBearingY = FT_MulFix( glyph->metrics.vertBearingY,
metrics->y_scale );
glyph->metrics.vertAdvance = FT_MulFix( glyph->metrics.vertAdvance,
metrics->y_scale );
if ( has_vertical_info )
{
FT_Short tsb = 0;
FT_UShort ah = 0;
sfnt->get_metrics( tt_face, 1, glyph_index, &tsb, &ah );
top = tsb;
advance = ah;
}
else
{
/* Use OS/2 or horizontal header for vertical advance. */
if ( tt_face->os2.version != 0xFFFFU )
advance = (FT_Pos)( tt_face->os2.sTypoAscender -
tt_face->os2.sTypoDescender );
else
advance = (FT_Pos)( tt_face->horizontal.Ascender -
tt_face->horizontal.Descender );
top = 0; /* computed after bbox is known */
}
glyph->linearVertAdvance = advance;
/* Scale table-derived metrics if needed. */
/* Outline coordinates are already in the target coordinate */
/* space (scaled in callback, or 26.6 font units for NO_SCALE) */
/* so bbox-derived metrics need no additional scaling. */
if ( apply_scaling )
{
FT_Fixed x_scale = size->metrics.x_scale;
FT_Fixed y_scale = size->metrics.y_scale;
glyph->metrics.horiAdvance = FT_MulFix( glyph->metrics.horiAdvance,
x_scale );
top = FT_MulFix( top, y_scale );
advance = FT_MulFix( advance, y_scale );
}
/* Compute width, height, and bearing metrics from the glyph */
/* outline bounding box, consistent with TrueType and CFF */
/* drivers. */
FT_Outline_Get_CBox( &glyph->outline, &bbox );
glyph->metrics.width = bbox.xMax - bbox.xMin;
glyph->metrics.height = bbox.yMax - bbox.yMin;
glyph->metrics.horiBearingX = bbox.xMin;
glyph->metrics.horiBearingY = bbox.yMax;
/* Finalize vertical metrics. */
/* vertBearingX centers the glyph horizontally for vertical */
/* layout, matching both TrueType and CFF drivers. */
/* When no vmtx data is available, vertBearingY centers the */
/* glyph vertically within the advance height. */
if ( !has_vertical_info )
top = ( advance - glyph->metrics.height ) / 2;
glyph->metrics.vertBearingX = glyph->metrics.horiBearingX -
glyph->metrics.horiAdvance / 2;
glyph->metrics.vertBearingY = top;
glyph->metrics.vertAdvance = advance;
}
/* Cache management - clear cache every */

View file

@ -202,8 +202,8 @@
face->num_axes = mm_var->num_axis;
/* Allocate storage for HVF axis coordinates. */
if ( !( FT_MEM_QNEW_ARRAY( *(HVFAxisValue**)&face->axis_coords,
face->num_axes ) ) )
if ( FT_QNEW_ARRAY( *(HVFAxisValue**)&face->axis_coords,
face->num_axes ) )
{
face->num_axes = 0;
goto Cleanup;
@ -242,7 +242,7 @@
return FT_Err_Ok;
/* Allocate temporary storage for current FreeType coordinates. */
if ( !( FT_MEM_QNEW_ARRAY( ft_coords, face->num_axes ) ) )
if ( FT_QNEW_ARRAY( ft_coords, face->num_axes ) )
return error;
/* Get current variation coordinates. */

View file

@ -115,8 +115,6 @@ FT_BEGIN_HEADER
FT_GlyphLoader loader; /* Standard FreeType loader. */
FT_Outline* outline; /* Points to `loader->current.outline`. */
FT_Bool path_begun; /* Path state tracking. */
HVF_Face face; /* Reference to face. */
/* Pre-calculated scaling factors for efficient coordinate conversion. */
HVFXYCoord x_scale_fixed; /* x_scale * 65536.0 (or just 65536.0) */