[smooth] Implement minimal dynamic padding for LCD filtering.

Extra bitmap padding for LCD filtering depends on the filter.  The
default 5-tap filter needs 2 extra subpixels.  The light 3-tap filter
needs only 1 extra subpixel.  This space could be already available
due to rounding.  In order to optimize the padding, we now expand
CBox for the given filter weights before rounding.

This change breakes current Skia (and Firefox).

* include/freetype/internal/ftobjs.h (FT_LibraryRec)
[FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Remove `lcd_extra' field.

* src/base/ftlcdfil.c (FT_Library_SetLcdFilterWeights,
FT_Library_SetLcdFilter): Remove `lcd_extra' initializations.

* src/smooth/ftsmooth.c (ft_smooth_render_generic): Implement dymanic
LCD padding.
This commit is contained in:
Alexei Podtelezhnikov 2017-05-20 00:35:21 -04:00
parent 881f64475f
commit ab2599ea3f
4 changed files with 44 additions and 33 deletions

View File

@ -1,3 +1,24 @@
2017-05-20 Alexei Podtelezhnikov <apodtele@gmail.com>
[smooth] Implement minimal dynamic padding for LCD filtering.
Extra bitmap padding for LCD filtering depends on the filter. The
default 5-tap filter needs 2 extra subpixels. The light 3-tap filter
needs only 1 extra subpixel. This space could be already available
due to rounding. In order to optimize the padding, we now expand
CBox for the given filter weights before rounding.
This change breakes current Skia (and Firefox).
* include/freetype/internal/ftobjs.h (FT_LibraryRec)
[FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Remove `lcd_extra' field.
* src/base/ftlcdfil.c (FT_Library_SetLcdFilterWeights,
FT_Library_SetLcdFilter): Remove `lcd_extra' initializations.
* src/smooth/ftsmooth.c (ft_smooth_render_generic): Implement dymanic
LCD padding.
2017-05-15 Werner Lemberg <wl@gnu.org>
[sfnt] Return proper scaling values for SBIX bitmaps.

View File

@ -864,9 +864,6 @@ FT_BEGIN_HEADER
/* lcd_filter :: If subpixel rendering is activated, the */
/* selected LCD filter mode. */
/* */
/* lcd_extra :: If subpixel rendering is activated, the number */
/* of extra pixels needed for the LCD filter. */
/* */
/* lcd_weights :: If subpixel rendering is activated, the LCD */
/* filter weights, if any. */
/* */
@ -902,7 +899,6 @@ FT_BEGIN_HEADER
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
FT_LcdFilter lcd_filter;
FT_Int lcd_extra; /* number of extra pixels */
FT_LcdFiveTapFilter lcd_weights; /* filter weights, if any */
FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */
#endif

View File

@ -296,7 +296,6 @@
ft_memcpy( library->lcd_weights, weights, FT_LCD_FILTER_FIVE_TAPS );
library->lcd_filter_func = ft_lcd_filter_fir;
library->lcd_extra = 2;
return FT_Err_Ok;
}
@ -319,7 +318,6 @@
{
case FT_LCD_FILTER_NONE:
library->lcd_filter_func = NULL;
library->lcd_extra = 0;
break;
case FT_LCD_FILTER_DEFAULT:
@ -327,7 +325,6 @@
default_weights,
FT_LCD_FILTER_FIVE_TAPS );
library->lcd_filter_func = ft_lcd_filter_fir;
library->lcd_extra = 2;
break;
case FT_LCD_FILTER_LIGHT:
@ -335,7 +332,6 @@
light_weights,
FT_LCD_FILTER_FIVE_TAPS );
library->lcd_filter_func = ft_lcd_filter_fir;
library->lcd_extra = 2;
break;
#ifdef USE_LEGACY
@ -343,7 +339,6 @@
case FT_LCD_FILTER_LEGACY:
case FT_LCD_FILTER_LEGACY1:
library->lcd_filter_func = _ft_lcd_filter_legacy;
library->lcd_extra = 0;
break;
#endif

View File

@ -119,7 +119,6 @@
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
FT_Int lcd_extra = 0;
FT_LcdFiveTapFilter lcd_weights = { 0 };
FT_Bool have_custom_weight = FALSE;
FT_Bitmap_LcdFilterFunc lcd_filter_func = NULL;
@ -147,13 +146,12 @@
{
/*
* A per-font filter is set. It always uses the default 5-tap
* in-place FIR filter that needs 2 extra pixels.
* 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_extra = 2;
}
else
{
@ -167,7 +165,6 @@
slot->library->lcd_weights,
FT_LCD_FILTER_FIVE_TAPS );
lcd_filter_func = slot->library->lcd_filter_func;
lcd_extra = slot->library->lcd_extra;
}
#endif /*FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
@ -196,6 +193,28 @@
/* taking into account the origin shift */
FT_Outline_Get_CBox( outline, &cbox );
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
/* add minimal padding for LCD filter depending on specific weights */
if ( lcd_filter_func)
{
if ( hmul )
{
cbox.xMax += lcd_weights[4] ? 43
: lcd_weights[3] ? 22 : 0;
cbox.xMin -= lcd_weights[0] ? 43
: lcd_weights[1] ? 22 : 0;
}
if ( vmul )
{
cbox.yMax += lcd_weights[0] ? 43
: lcd_weights[1] ? 22 : 0;
cbox.yMin -= lcd_weights[4] ? 43
: lcd_weights[3] ? 22 : 0;
}
}
#endif
cbox.xMin = FT_PIX_FLOOR( cbox.xMin + x_shift );
cbox.yMin = FT_PIX_FLOOR( cbox.yMin + y_shift );
cbox.xMax = FT_PIX_CEIL( cbox.xMax + x_shift );
@ -225,26 +244,6 @@
if ( vmul )
height *= 3;
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
if ( lcd_filter_func )
{
if ( hmul )
{
x_shift += 64 * ( lcd_extra >> 1 );
x_left -= lcd_extra >> 1;
width += 3 * lcd_extra;
pitch = FT_PAD_CEIL( width, 4 );
}
if ( vmul )
{
y_shift += 64 * ( lcd_extra >> 1 );
y_top += lcd_extra >> 1;
height += 3 * lcd_extra;
}
}
#endif
/*
* XXX: on 16bit system, we return an error for huge bitmap
* to prevent an overflow.