[truetype] Rework handling of rendering mode in bytecode.

This replaces a large number of confusing boolean constructs that
describe the target rendering mode in the execution context with
the straight mode variable.  It might fix some hidden bugs when
FT_LOAD_TARGET_XXX were used as flags, which they are not.

The condition that triggers the CV program re-execution is simplified.
These events due the rendering mode change are rather rare and unexpected
and, therefore, should not be over-analyzed. In v40, all mode changes
now trigger the CV program. In v35, only switches to/from mono do.

* src/truetype/ttinterp.h (TT_ExecContext): Replace 'grayscale',
'grayscale_cleartype', 'subpixel_hinting_lean', and 'vertical_lcd_lean'
with the rendering 'mode'.
* src/truetype/ttinterp.c (Ins_GETINFO): Updated.
* src/truetype/ttgload.c (tt_loader_init): Replace 'prep' re-execution
trigger and update 'backward_compatibility' condition.
(tt_loader_set_pp): Updated.
This commit is contained in:
Alexei Podtelezhnikov 2025-06-21 22:59:29 -04:00
parent 0e38fa753f
commit 4c2437efa7
3 changed files with 22 additions and 65 deletions

View file

@ -1370,8 +1370,9 @@
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
loader->exec &&
loader->exec->subpixel_hinting_lean &&
loader->exec->grayscale_cleartype )
loader->exec->mode != FT_RENDER_MODE_MONO &&
loader->exec->mode != FT_RENDER_MODE_LCD &&
loader->exec->mode != FT_RENDER_MODE_LCD_V )
{
loader->pp3.x = loader->advance / 2;
loader->pp4.x = loader->advance / 2;
@ -2205,15 +2206,13 @@
{
FT_Error error;
TT_ExecContext exec;
FT_Bool grayscale = TRUE;
FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
FT_Bool grayscale = FT_BOOL( mode != FT_RENDER_MODE_MONO );
FT_Bool reexecute = FALSE;
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
FT_Bool subpixel_hinting_lean;
FT_Bool grayscale_cleartype;
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( glyph->face );
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( glyph->face );
#endif
FT_Bool reexecute = FALSE;
if ( size->bytecode_ready > 0 )
return size->bytecode_ready;
@ -2229,53 +2228,20 @@
exec = size->context;
grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
FT_RENDER_MODE_MONO );
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
{
subpixel_hinting_lean =
FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
FT_RENDER_MODE_MONO );
grayscale_cleartype =
FT_BOOL( subpixel_hinting_lean &&
!( ( load_flags &
FT_LOAD_TARGET_LCD ) ||
( load_flags &
FT_LOAD_TARGET_LCD_V ) ) );
exec->vertical_lcd_lean =
FT_BOOL( subpixel_hinting_lean &&
( load_flags &
FT_LOAD_TARGET_LCD_V ) );
grayscale = FT_BOOL( grayscale && !subpixel_hinting_lean );
grayscale = FALSE;
/* a change from mono to subpixel rendering (and vice versa) */
/* requires a re-execution of the CVT program */
if ( subpixel_hinting_lean != exec->subpixel_hinting_lean )
/* any mode change requires a re-execution of the CVT program */
if ( mode != exec->mode )
{
FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
FT_TRACE4(( "tt_loader_init: render mode change,"
" re-executing `prep' table\n" ));
exec->subpixel_hinting_lean = subpixel_hinting_lean;
reexecute = TRUE;
exec->mode = mode;
reexecute = TRUE;
}
/* a change from colored to grayscale subpixel rendering (and */
/* vice versa) requires a re-execution of the CVT program */
if ( grayscale_cleartype != exec->grayscale_cleartype )
{
FT_TRACE4(( "tt_loader_init: grayscale subpixel hinting change,"
" re-executing `prep' table\n" ));
exec->grayscale_cleartype = grayscale_cleartype;
reexecute = TRUE;
}
}
else
{
subpixel_hinting_lean = FALSE;
exec->vertical_lcd_lean = FALSE;
}
#endif
@ -2326,7 +2292,7 @@
*
*/
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
subpixel_hinting_lean &&
mode != FT_RENDER_MODE_MONO &&
!FT_IS_TRICKY( glyph->face ) )
exec->backward_compatibility = ( size->GS.instruct_control & 4 ) ^ 4;
else

View file

@ -6550,7 +6550,7 @@
/* Otherwise, instructions may behave weirdly and rendering results */
/* may differ between v35 and v40 mode, e.g., in `Times New Roman */
/* Bold Italic'. */
if ( SUBPIXEL_HINTING_MINIMAL && exc->subpixel_hinting_lean )
if ( SUBPIXEL_HINTING_MINIMAL && exc->mode != FT_RENDER_MODE_MONO )
{
/*********************************
* HINTING FOR SUBPIXEL
@ -6567,7 +6567,7 @@
* Selector Bit: 8
* Return Bit(s): 15
*/
if ( ( args[0] & 256 ) != 0 && exc->vertical_lcd_lean )
if ( ( args[0] & 256 ) != 0 && exc->mode == FT_RENDER_MODE_LCD_V )
K |= 1 << 15;
/*********************************
@ -6588,7 +6588,7 @@
* The only smoothing method FreeType supports unless someone sets
* FT_LOAD_TARGET_MONO.
*/
if ( ( args[0] & 2048 ) != 0 && exc->subpixel_hinting_lean )
if ( ( args[0] & 2048 ) != 0 && exc->mode != FT_RENDER_MODE_MONO )
K |= 1 << 18;
/*********************************
@ -6600,7 +6600,10 @@
* Grayscale rendering is what FreeType does anyway unless someone
* sets FT_LOAD_TARGET_MONO or FT_LOAD_TARGET_LCD(_V)
*/
if ( ( args[0] & 4096 ) != 0 && exc->grayscale_cleartype )
if ( ( args[0] & 4096 ) != 0 &&
exc->mode != FT_RENDER_MODE_MONO &&
exc->mode != FT_RENDER_MODE_LCD &&
exc->mode != FT_RENDER_MODE_LCD_V )
K |= 1 << 19;
}
#endif

View file

@ -329,20 +329,8 @@ FT_BEGIN_HEADER
/* or in native ClearType mode. */
FT_Int backward_compatibility;
/* Using v40 implies subpixel hinting, unless FT_RENDER_MODE_MONO */
/* has been requested. Used to detect interpreter version switches. */
FT_Bool subpixel_hinting_lean;
FT_Render_Mode mode; /* target render mode */
/* Long side of a LCD subpixel is vertical (e.g., screen is rotated). */
FT_Bool vertical_lcd_lean;
/* ClearType hinting and grayscale rendering, as used by Universal */
/* Windows Platform apps (Windows 8 and above). Like the standard */
/* colorful ClearType mode, it utilizes a vastly increased virtual */
/* resolution on the x axis. Different from bi-level hinting and */
/* grayscale rendering, the old mode from Win9x days that roughly */
/* adheres to the physical pixel grid on both axes. */
FT_Bool grayscale_cleartype;
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */
/* We maintain two counters (in addition to the instruction counter) */