diff --git a/ChangeLog b/ChangeLog index 47811d18c..d42f98685 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2017-09-24 Alexei Podtelezhnikov + + 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 [sfnt] Fix `premultiply_data' (#52092). @@ -32,7 +53,7 @@ VariationIndex subtable. (otv_Lookup_validate): Handle MarkFilteringSet. -2017-09-21 Alexei Podtelezhnikov +2017-09-23 Alexei Podtelezhnikov [build] Windows-style DLL versioning. diff --git a/include/freetype/ftlcdfil.h b/include/freetype/ftlcdfil.h index ea4a66e69..8c751418f 100644 --- a/include/freetype/ftlcdfil.h +++ b/include/freetype/ftlcdfil.h @@ -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 ); + /* */ diff --git a/include/freetype/internal/ftobjs.h b/include/freetype/internal/ftobjs.h index 4231be238..25c328f4f 100644 --- a/include/freetype/internal/ftobjs.h +++ b/include/freetype/internal/ftobjs.h @@ -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 ); - - /*************************************************************************/ /* */ /* */ @@ -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 diff --git a/src/base/ftlcdfil.c b/src/base/ftlcdfil.c index 60c813fd9..ca781f324 100644 --- a/src/base/ftlcdfil.c +++ b/src/base/ftlcdfil.c @@ -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; } diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index 6db8136cf..aedb1f33d 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -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 ); diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c index 963435de1..99a9883d2 100644 --- a/src/smooth/ftsmooth.c +++ b/src/smooth/ftsmooth.c @@ -115,56 +115,22 @@ FT_Bool have_buffer = FALSE; #ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING + FT_Byte* lcd_weights; + FT_Bitmap_LcdFilterFunc lcd_filter_func; - FT_LcdFiveTapFilter lcd_weights = { 0 }; - FT_Bool have_custom_weight = FALSE; - FT_Bitmap_LcdFilterFunc lcd_filter_func = NULL; - - 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 ) {