Tweak per-face LCD filtering controls.

Thing are simpler with a NULL-function pointer.

* include/freetype/internal/ftobjs.h (FT_Face_InternalRec): New
pointer to the filter function.
(FT_LibraryRec): Remove unused `lcd_filter'.
(FT_Bitmap_LcdFilterFunc, ft_lcd_filter_fir):  Move from here...
* include/freetype/ftlcdfil.h (FT_Bitmap_LcdFilterFunc,
ft_lcd_filter_fir): ... to here.

* src/base/ftobjs.c (ft_open_face_internal): NULL-initialize the
per-face filter.
(FT_Face_Properties): Set it.
* src/smooth/ftsmooth.c (ft_smooth_render_generic): Simplify.

* src/base/ftlcdfil.c (ft_lcd_filter_fir, FT_Libary_SetLcdFilter):
Minor.
This commit is contained in:
Alexei Podtelezhnikov 2017-09-24 22:18:34 -04:00
parent 6f2b6f8f72
commit 02e80da609
6 changed files with 54 additions and 75 deletions

View File

@ -1,3 +1,24 @@
2017-09-24 Alexei Podtelezhnikov <apodtele@gmail.com>
Tweak per-face LCD filtering controls.
Thing are simpler with a NULL-function pointer.
* include/freetype/internal/ftobjs.h (FT_Face_InternalRec): New
pointer to the filter function.
(FT_LibraryRec): Remove unused `lcd_filter'.
(FT_Bitmap_LcdFilterFunc, ft_lcd_filter_fir): Move from here...
* include/freetype/ftlcdfil.h (FT_Bitmap_LcdFilterFunc,
ft_lcd_filter_fir): ... to here.
* src/base/ftobjs.c (ft_open_face_internal): NULL-initialize the
per-face filter.
(FT_Face_Properties): Set it.
* src/smooth/ftsmooth.c (ft_smooth_render_generic): Simplify.
* src/base/ftlcdfil.c (ft_lcd_filter_fir, FT_Libary_SetLcdFilter):
Minor.
2017-09-24 Jonathan Kew <jfkthame@gmail.com>
[sfnt] Fix `premultiply_data' (#52092).
@ -32,7 +53,7 @@
VariationIndex subtable.
(otv_Lookup_validate): Handle MarkFilteringSet.
2017-09-21 Alexei Podtelezhnikov <apodtele@gmail.com>
2017-09-23 Alexei Podtelezhnikov <apodtele@gmail.com>
[build] Windows-style DLL versioning.

View File

@ -316,6 +316,17 @@ FT_BEGIN_HEADER
typedef FT_Byte FT_LcdFiveTapFilter[FT_LCD_FILTER_FIVE_TAPS];
typedef void (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap* bitmap,
FT_Render_Mode render_mode,
FT_Byte* weights );
/* This is the default LCD filter, an in-place, 5-tap FIR filter. */
FT_BASE( void )
ft_lcd_filter_fir( FT_Bitmap* bitmap,
FT_Render_Mode mode,
FT_LcdFiveTapFilter weights );
/* */

View File

@ -369,9 +369,10 @@ FT_BEGIN_HEADER
/* operator. Value~0 means to use the font's value. Value~-1 */
/* means to use the CFF driver's default. */
/* */
/* lcd_weights :: */
/* Overrides the library default with custom weights for the 5-tap */
/* FIR filter. `{0, 0, 0, 0, 0}' means to use the library default. */
/* lcd_weights :: */
/* lcd_filter_func :: */
/* If subpixel rendering is activated, the LCD filtering weights */
/* and callback function. */
/* */
/* refcount :: */
/* A counter initialized to~1 at the time an @FT_Face structure is */
@ -393,8 +394,10 @@ FT_BEGIN_HEADER
FT_Char no_stem_darkening;
FT_Int32 random_seed;
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
FT_LcdFiveTapFilter lcd_weights; /* preset or custom filter weights */
FT_LcdFiveTapFilter lcd_weights; /* filter weights, if any */
FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */
#endif
FT_Int refcount;
@ -821,18 +824,6 @@ FT_BEGIN_HEADER
#define FT_DEBUG_HOOK_TRUETYPE 0
typedef void (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap* bitmap,
FT_Render_Mode render_mode,
FT_Byte* weights );
/* This is the default LCD filter, an in-place, 5-tap FIR filter. */
FT_BASE( void )
ft_lcd_filter_fir( FT_Bitmap* bitmap,
FT_Render_Mode mode,
FT_LcdFiveTapFilter weights );
/*************************************************************************/
/* */
/* <Struct> */
@ -878,9 +869,6 @@ FT_BEGIN_HEADER
/* interpreter. Currently, only the TrueType */
/* bytecode debugger uses this. */
/* */
/* lcd_filter :: If subpixel rendering is activated, the */
/* selected LCD filter mode. */
/* */
/* lcd_weights :: If subpixel rendering is activated, the LCD */
/* filter weights, if any. */
/* */
@ -915,7 +903,6 @@ FT_BEGIN_HEADER
FT_DebugHook_Func debug_hooks[4];
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
FT_LcdFilter lcd_filter;
FT_LcdFiveTapFilter lcd_weights; /* filter weights, if any */
FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */
#endif

View File

@ -32,7 +32,7 @@
#define FT_SHIFTCLAMP( x ) ( x >>= 8, (FT_Byte)( x > 255 ? 255 : x ) )
/* FIR filter used by the default and light filters */
FT_BASE( void )
FT_BASE_DEF( void )
ft_lcd_filter_fir( FT_Bitmap* bitmap,
FT_Render_Mode mode,
FT_LcdFiveTapFilter weights )
@ -305,8 +305,6 @@
return FT_THROW( Invalid_Argument );
}
library->lcd_filter = filter;
return FT_Err_Ok;
}

View File

@ -2441,7 +2441,8 @@
internal->no_stem_darkening = -1;
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
ft_memset( internal->lcd_weights, 0, FT_LCD_FILTER_FIVE_TAPS );
/* Per-face filtering can only be set up by FT_Face_Properties */
internal->lcd_filter_func = NULL;
#endif
}
@ -3653,16 +3654,11 @@
{
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
if ( properties->data )
{
ft_memcpy( face->internal->lcd_weights,
properties->data,
FT_LCD_FILTER_FIVE_TAPS );
else
{
/* Value NULL indicates `no custom weights, use library */
/* defaults', signaled by filling the weight field with zeros. */
ft_memset( face->internal->lcd_weights,
0,
FT_LCD_FILTER_FIVE_TAPS );
face->internal->lcd_filter_func = ft_lcd_filter_fir;
}
#else
error = FT_THROW( Unimplemented_Feature );

View File

@ -115,56 +115,22 @@
FT_Bool have_buffer = FALSE;
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
FT_LcdFiveTapFilter lcd_weights = { 0 };
FT_Bool have_custom_weight = FALSE;
FT_Bitmap_LcdFilterFunc lcd_filter_func = NULL;
FT_Byte* lcd_weights;
FT_Bitmap_LcdFilterFunc lcd_filter_func;
if ( slot->face )
/* Per-face LCD filtering takes priority if set up. */
if ( slot->face && slot->face->internal->lcd_filter_func )
{
FT_Char i;
for ( i = 0; i < FT_LCD_FILTER_FIVE_TAPS; i++ )
if ( slot->face->internal->lcd_weights[i] != 0 )
{
have_custom_weight = TRUE;
break;
}
}
/*
* The LCD filter can be set library-wide and per-face. Face overrides
* library. If the face filter weights are all zero (the default), it
* means that the library default should be used.
*/
if ( have_custom_weight )
{
/*
* A per-font filter is set. It always uses the default 5-tap
* in-place FIR filter.
*/
ft_memcpy( lcd_weights,
slot->face->internal->lcd_weights,
FT_LCD_FILTER_FIVE_TAPS );
lcd_filter_func = ft_lcd_filter_fir;
lcd_weights = slot->face->internal->lcd_weights;
lcd_filter_func = slot->face->internal->lcd_filter_func;
}
else
{
/*
* The face's lcd_weights is {0, 0, 0, 0, 0}, meaning `use library
* default'. If the library is set to use no LCD filtering
* (lcd_filter_func == NULL), `lcd_filter_func' here is also set to
* NULL and the tests further below pass over the filtering process.
*/
ft_memcpy( lcd_weights,
slot->library->lcd_weights,
FT_LCD_FILTER_FIVE_TAPS );
lcd_weights = slot->library->lcd_weights;
lcd_filter_func = slot->library->lcd_filter_func;
}
#endif /*FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
/* check glyph image format */
if ( slot->format != render->glyph_format )
@ -208,7 +174,7 @@
#else /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
/* add minimal padding for LCD filter depending on specific weights */
if ( lcd_filter_func )
if ( lcd_filter_func == ft_lcd_filter_fir )
{
if ( hmul )
{