[truetype] Increase precision of font variation (#54371).
This patch make FreeType use font units in 26.6 format internally instead of integers. * src/truetype/ttgxvar.c (FT_fixedToFdot6): New macro. (TT_Vary_Apply_Glyph_Deltas): Add argument to output unrounded font coordinates. * src/truetype/ttgxvar.h: Updated. * src/truetype/ttgload.c (TT_Process_Simple_Glyph): Use `extra_points2' array to temporarily hold unrounded point coordinates; use them to compute scaled coordinates and linear advance width and height. (load_truetype_code): Adjust similarly.
This commit is contained in:
parent
a113e5df0c
commit
1178227b39
18
ChangeLog
18
ChangeLog
@ -1,3 +1,21 @@
|
||||
2019-05-09 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
[truetype] Increase precision of font variation (#54371).
|
||||
|
||||
This patch make FreeType use font units in 26.6 format internally
|
||||
instead of integers.
|
||||
|
||||
* src/truetype/ttgxvar.c (FT_fixedToFdot6): New macro.
|
||||
(TT_Vary_Apply_Glyph_Deltas): Add argument to output unrounded font
|
||||
coordinates.
|
||||
* src/truetype/ttgxvar.h: Updated.
|
||||
|
||||
* src/truetype/ttgload.c (TT_Process_Simple_Glyph): Use
|
||||
`extra_points2' array to temporarily hold unrounded point
|
||||
coordinates; use them to compute scaled coordinates and linear
|
||||
advance width and height.
|
||||
(load_truetype_code): Adjust similarly.
|
||||
|
||||
2019-05-09 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
* src/truetype/ttgload.c (TT_Process_Simple_Glyph): Minor.
|
||||
|
@ -1766,6 +1766,13 @@ FT_BEGIN_HEADER
|
||||
* transformed, distorted, emboldened, etc. However, it must not be
|
||||
* freed.
|
||||
*
|
||||
* [Since 2.10.1] If @FT_LOAD_NO_SCALE is set, outline coordinates of
|
||||
* OpenType variation fonts for a selected instance are internally
|
||||
* handled as 26.6 fractional font units but returned as (rounded)
|
||||
* integers, as expected. To get unrounded font units, don't use
|
||||
* @FT_LOAD_NO_SCALE but load the glyph with @FT_LOAD_NO_HINTING and
|
||||
* scale it, using the font's `units_per_EM` value as the ppem.
|
||||
*
|
||||
* num_subglyphs ::
|
||||
* The number of subglyphs in a composite glyph. This field is only
|
||||
* valid for the composite glyph format that should normally only be
|
||||
|
@ -925,6 +925,7 @@
|
||||
FT_GlyphLoader gloader = loader->gloader;
|
||||
FT_Error error = FT_Err_Ok;
|
||||
FT_Outline* outline;
|
||||
FT_Vector* unrounded;
|
||||
FT_Int n_points;
|
||||
|
||||
|
||||
@ -950,20 +951,26 @@
|
||||
if ( FT_IS_NAMED_INSTANCE( FT_FACE( loader->face ) ) ||
|
||||
FT_IS_VARIATION( FT_FACE( loader->face ) ) )
|
||||
{
|
||||
/* Deltas apply to the unscaled data. */
|
||||
/* Deltas apply to the unscaled data. */
|
||||
/* We temporarily use `extra_points2' to hold unrounded values. */
|
||||
unrounded = gloader->current.extra_points2;
|
||||
error = TT_Vary_Apply_Glyph_Deltas( loader->face,
|
||||
loader->glyph_index,
|
||||
outline,
|
||||
unrounded,
|
||||
(FT_UInt)n_points );
|
||||
|
||||
/* recalculate linear horizontal and vertical advances */
|
||||
/* if we don't have HVAR and VVAR, respectively */
|
||||
|
||||
/* XXX: change all FreeType modules to store `linear' and `vadvance' */
|
||||
/* in 26.6 format before the `base' module scales them to 16.16 */
|
||||
if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
|
||||
loader->linear = outline->points[n_points - 3].x -
|
||||
outline->points[n_points - 4].x;
|
||||
loader->linear = FT_PIX_ROUND( unrounded[n_points - 3].x -
|
||||
unrounded[n_points - 4].x ) / 64;
|
||||
if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
|
||||
loader->vadvance = outline->points[n_points - 1].x -
|
||||
outline->points[n_points - 2].x;
|
||||
loader->vadvance = FT_PIX_ROUND( unrounded[n_points - 1].x -
|
||||
unrounded[n_points - 2].x ) / 64;
|
||||
|
||||
if ( error )
|
||||
return error;
|
||||
@ -1013,10 +1020,17 @@
|
||||
/* compensate for any scaling by de/emboldening; */
|
||||
/* the amount was determined via experimentation */
|
||||
if ( x_scale_factor != 1000 && ppem > 11 )
|
||||
{
|
||||
FT_Vector* orig_points = outline->points;
|
||||
|
||||
|
||||
outline->points = unrounded;
|
||||
FT_Outline_EmboldenXY( outline,
|
||||
FT_MulFix( 1280 * ppem,
|
||||
1000 - x_scale_factor ),
|
||||
0 );
|
||||
outline->points = orig_points;
|
||||
}
|
||||
do_scale = TRUE;
|
||||
}
|
||||
}
|
||||
@ -1037,10 +1051,10 @@
|
||||
|
||||
if ( do_scale )
|
||||
{
|
||||
for ( ; vec < limit; vec++ )
|
||||
for ( ; vec < limit; vec++, unrounded++ )
|
||||
{
|
||||
vec->x = FT_MulFix( vec->x, x_scale );
|
||||
vec->y = FT_MulFix( vec->y, y_scale );
|
||||
vec->x = FT_MulDiv( unrounded->x, x_scale, 0x10000L * 64 );
|
||||
vec->y = FT_MulDiv( unrounded->y, y_scale, 0x10000L * 64 );
|
||||
}
|
||||
}
|
||||
|
||||
@ -1678,6 +1692,9 @@
|
||||
short contours[4] = { 0, 1, 2, 3 };
|
||||
FT_Outline outline;
|
||||
|
||||
/* unrounded values */
|
||||
FT_Vector unrounded[4];
|
||||
|
||||
|
||||
points[0].x = loader->pp1.x;
|
||||
points[0].y = loader->pp1.y;
|
||||
@ -1699,6 +1716,7 @@
|
||||
error = TT_Vary_Apply_Glyph_Deltas( loader->face,
|
||||
glyph_index,
|
||||
&outline,
|
||||
unrounded,
|
||||
(FT_UInt)outline.n_points );
|
||||
if ( error )
|
||||
goto Exit;
|
||||
@ -1716,9 +1734,11 @@
|
||||
/* recalculate linear horizontal and vertical advances */
|
||||
/* if we don't have HVAR and VVAR, respectively */
|
||||
if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
|
||||
loader->linear = loader->pp2.x - loader->pp1.x;
|
||||
loader->linear = FT_PIX_ROUND( unrounded[1].x -
|
||||
unrounded[0].x ) / 64;
|
||||
if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
|
||||
loader->vadvance = loader->pp4.x - loader->pp3.x;
|
||||
loader->vadvance = FT_PIX_ROUND( unrounded[3].x -
|
||||
unrounded[2].x ) / 64;
|
||||
}
|
||||
|
||||
#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
|
||||
@ -1858,9 +1878,10 @@
|
||||
FT_SubGlyph subglyph;
|
||||
|
||||
FT_Outline outline;
|
||||
FT_Vector* points = NULL;
|
||||
char* tags = NULL;
|
||||
short* contours = NULL;
|
||||
FT_Vector* points = NULL;
|
||||
char* tags = NULL;
|
||||
short* contours = NULL;
|
||||
FT_Vector* unrounded = NULL;
|
||||
|
||||
|
||||
limit = (short)gloader->current.num_subglyphs;
|
||||
@ -1874,9 +1895,10 @@
|
||||
outline.tags = NULL;
|
||||
outline.contours = NULL;
|
||||
|
||||
if ( FT_NEW_ARRAY( points, outline.n_points ) ||
|
||||
FT_NEW_ARRAY( tags, outline.n_points ) ||
|
||||
FT_NEW_ARRAY( contours, outline.n_points ) )
|
||||
if ( FT_NEW_ARRAY( points, outline.n_points ) ||
|
||||
FT_NEW_ARRAY( tags, outline.n_points ) ||
|
||||
FT_NEW_ARRAY( contours, outline.n_points ) ||
|
||||
FT_NEW_ARRAY( unrounded, outline.n_points ) )
|
||||
goto Exit1;
|
||||
|
||||
subglyph = gloader->current.subglyphs;
|
||||
@ -1925,6 +1947,7 @@
|
||||
face,
|
||||
glyph_index,
|
||||
&outline,
|
||||
unrounded,
|
||||
(FT_UInt)outline.n_points ) ) )
|
||||
goto Exit1;
|
||||
|
||||
@ -1952,14 +1975,17 @@
|
||||
/* recalculate linear horizontal and vertical advances */
|
||||
/* if we don't have HVAR and VVAR, respectively */
|
||||
if ( !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
|
||||
loader->linear = loader->pp2.x - loader->pp1.x;
|
||||
loader->linear = FT_PIX_ROUND( unrounded[1].x -
|
||||
unrounded[0].x ) / 64;
|
||||
if ( !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
|
||||
loader->vadvance = loader->pp4.x - loader->pp3.x;
|
||||
loader->vadvance = FT_PIX_ROUND( unrounded[3].x -
|
||||
unrounded[2].x ) / 64;
|
||||
|
||||
Exit1:
|
||||
FT_FREE( outline.points );
|
||||
FT_FREE( outline.tags );
|
||||
FT_FREE( outline.contours );
|
||||
FT_FREE( unrounded );
|
||||
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
@ -68,12 +68,14 @@
|
||||
|
||||
|
||||
/* some macros we need */
|
||||
#define FT_fdot14ToFixed( x ) \
|
||||
( (FT_Fixed)( (FT_ULong)(x) << 2 ) )
|
||||
#define FT_intToFixed( i ) \
|
||||
( (FT_Fixed)( (FT_ULong)(i) << 16 ) )
|
||||
#define FT_fixedToInt( x ) \
|
||||
( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
|
||||
#define FT_fdot14ToFixed( x ) \
|
||||
( (FT_Fixed)( (FT_ULong)(x) << 2 ) )
|
||||
#define FT_intToFixed( i ) \
|
||||
( (FT_Fixed)( (FT_ULong)(i) << 16 ) )
|
||||
#define FT_fixedToInt( x ) \
|
||||
( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
|
||||
#define FT_fixedToFdot6( x ) \
|
||||
( (FT_Pos)( ( (FT_UInt32)(x) + 0x20 ) >> 10 ) )
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
@ -3674,6 +3676,11 @@
|
||||
* outline ::
|
||||
* The outline to change.
|
||||
*
|
||||
* @Output:
|
||||
* unrounded ::
|
||||
* An array with `n_points' elements that is filled with unrounded
|
||||
* point coordinates (in 26.6 format).
|
||||
*
|
||||
* @Return:
|
||||
* FreeType error code. 0 means success.
|
||||
*/
|
||||
@ -3681,6 +3688,7 @@
|
||||
TT_Vary_Apply_Glyph_Deltas( TT_Face face,
|
||||
FT_UInt glyph_index,
|
||||
FT_Outline* outline,
|
||||
FT_Vector* unrounded,
|
||||
FT_UInt n_points )
|
||||
{
|
||||
FT_Error error;
|
||||
@ -4068,6 +4076,11 @@
|
||||
|
||||
for ( i = 0; i < n_points; i++ )
|
||||
{
|
||||
unrounded[i].x = INT_TO_F26DOT6( outline->points[i].x ) +
|
||||
FT_fixedToFdot6( point_deltas_x[i] );
|
||||
unrounded[i].y = INT_TO_F26DOT6( outline->points[i].y ) +
|
||||
FT_fixedToFdot6( point_deltas_y[i] );
|
||||
|
||||
outline->points[i].x += FT_fixedToInt( point_deltas_x[i] );
|
||||
outline->points[i].y += FT_fixedToInt( point_deltas_y[i] );
|
||||
}
|
||||
|
@ -416,6 +416,7 @@ FT_BEGIN_HEADER
|
||||
TT_Vary_Apply_Glyph_Deltas( TT_Face face,
|
||||
FT_UInt glyph_index,
|
||||
FT_Outline* outline,
|
||||
FT_Vector* unrounded,
|
||||
FT_UInt n_points );
|
||||
|
||||
FT_LOCAL( FT_Error )
|
||||
|
Loading…
Reference in New Issue
Block a user