forked from minhngoc25a/freetype2
Add face property for LCD filter weights.
* include/freetype/ftlcdfil.h (FT_PARAM_TAG_LCD_FILTER_WEIGHTS, FT_LCD_FILTER_FIVE_TAPS): New macros. (FT_LcdFiveTapFilter): New typedef. * include/freetype/ftobjs.h (FT_Face_InternalRec) [FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Add `lcd_weights' field. (FT_Bitmap_LcdFilterFunc): Change third argument to weights array. (ft_lcd_filter_fir): New prototype. (FT_LibraryRec): Updated. * src/base/ftlcdfil.c (_ft_lcd_filter_fir): Renamed to... (ft_lcd_filter_dir): ... this base function. Updated. (_ft_lcd_filter_legacy): Updated. (FT_Library_SetLcdFilterWeights, FT_Library_SetLcdFilter): Updated. * src/base/ftobjs.c (ft_open_face_internal): Updated. (FT_Face_Properties): Handle FT_PARAM_TAG_LCD_FILTER_WEIGHTS. * src/smooth/ftsmooth.c (ft_smooth_render_generic) [FT_CONFIG_OPTION_SUBPIXEL_RENDERING: Handle LCD weights from `FT_Face_Internal'.
This commit is contained in:
parent
64cdee7348
commit
2e9519885b
28
ChangeLog
28
ChangeLog
|
@ -1,3 +1,31 @@
|
|||
2017-02-16 Nikolaus Waxweiler <madigens@gmail.com>
|
||||
Werner Lemberg <wl@gnu.org>
|
||||
|
||||
Add face property for LCD filter weights.
|
||||
|
||||
* include/freetype/ftlcdfil.h (FT_PARAM_TAG_LCD_FILTER_WEIGHTS,
|
||||
FT_LCD_FILTER_FIVE_TAPS): New macros.
|
||||
(FT_LcdFiveTapFilter): New typedef.
|
||||
|
||||
* include/freetype/ftobjs.h (FT_Face_InternalRec)
|
||||
[FT_CONFIG_OPTION_SUBPIXEL_RENDERING]: Add `lcd_weights' field.
|
||||
(FT_Bitmap_LcdFilterFunc): Change third argument to weights array.
|
||||
(ft_lcd_filter_fir): New prototype.
|
||||
(FT_LibraryRec): Updated.
|
||||
|
||||
* src/base/ftlcdfil.c (_ft_lcd_filter_fir): Renamed to...
|
||||
(ft_lcd_filter_dir): ... this base function.
|
||||
Updated.
|
||||
(_ft_lcd_filter_legacy): Updated.
|
||||
(FT_Library_SetLcdFilterWeights, FT_Library_SetLcdFilter): Updated.
|
||||
|
||||
* src/base/ftobjs.c (ft_open_face_internal): Updated.
|
||||
(FT_Face_Properties): Handle FT_PARAM_TAG_LCD_FILTER_WEIGHTS.
|
||||
|
||||
* src/smooth/ftsmooth.c (ft_smooth_render_generic)
|
||||
[FT_CONFIG_OPTION_SUBPIXEL_RENDERING: Handle LCD weights from
|
||||
`FT_Face_Internal'.
|
||||
|
||||
2017-02-14 Nikolaus Waxweiler <madigens@gmail.com>
|
||||
Werner Lemberg <wl@gnu.org>
|
||||
|
||||
|
|
|
@ -3629,6 +3629,12 @@ FT_BEGIN_HEADER
|
|||
* Note that only a subset of the available properties can be
|
||||
* controlled.
|
||||
*
|
||||
* * LCD filter weights (@FT_PARAM_TAG_LCD_FILTER_WEIGHTS, corresponding
|
||||
* to function @FT_Library_SetLcdFilterWeights).
|
||||
*
|
||||
* Pass NULL as `data' in @FT_Parameter for a given tag to reset the
|
||||
* option and use the library or module default again.
|
||||
*
|
||||
* @input:
|
||||
* face ::
|
||||
* A handle to the source face object.
|
||||
|
|
|
@ -275,6 +275,37 @@ FT_BEGIN_HEADER
|
|||
FT_Library_SetLcdFilterWeights( FT_Library library,
|
||||
unsigned char *weights );
|
||||
|
||||
|
||||
/*
|
||||
* @constant:
|
||||
* FT_PARAM_TAG_LCD_FILTER_WEIGHTS
|
||||
*
|
||||
* @description:
|
||||
* An @FT_Parameter tag to be used with @FT_Face_Properties. The
|
||||
* corresponding argument specifies the five LCD filter weights for a
|
||||
* given face (if using @FT_LOAD_TARGET_LCD, for example), overriding
|
||||
* the global default values or the values set up with
|
||||
* @FT_Library_Set_LcdFilterWeights.
|
||||
*
|
||||
*/
|
||||
#define FT_PARAM_TAG_LCD_FILTER_WEIGHTS \
|
||||
FT_MAKE_TAG( 'l', 'c', 'd', 'f' )
|
||||
|
||||
|
||||
/*
|
||||
* @type:
|
||||
* FT_LcdFiveTapFilter
|
||||
*
|
||||
* @description:
|
||||
* A typedef for passing the five LCD filter weights to
|
||||
* @FT_Face_Properties within an @FT_Parameter structure.
|
||||
*
|
||||
*/
|
||||
#define FT_LCD_FILTER_FIVE_TAPS 5
|
||||
|
||||
typedef FT_Byte FT_LcdFiveTapFilter[FT_LCD_FILTER_FIVE_TAPS];
|
||||
|
||||
|
||||
/* */
|
||||
|
||||
|
||||
|
|
|
@ -348,6 +348,10 @@ FT_BEGIN_HEADER
|
|||
/* @FT_Done_Face only destroys a face if the counter is~1, */
|
||||
/* otherwise it simply decrements it. */
|
||||
/* */
|
||||
/* 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. */
|
||||
/* */
|
||||
typedef struct FT_Face_InternalRec_
|
||||
{
|
||||
FT_Matrix transform_matrix;
|
||||
|
@ -362,6 +366,10 @@ FT_BEGIN_HEADER
|
|||
|
||||
FT_Int refcount;
|
||||
|
||||
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
|
||||
FT_LcdFiveTapFilter lcd_weights; /* preset or custom filter weights */
|
||||
#endif
|
||||
|
||||
} FT_Face_InternalRec;
|
||||
|
||||
|
||||
|
@ -775,12 +783,19 @@ FT_BEGIN_HEADER
|
|||
|
||||
/* This hook is used by the TrueType debugger. It must be set to an */
|
||||
/* alternate truetype bytecode interpreter function. */
|
||||
#define FT_DEBUG_HOOK_TRUETYPE 0
|
||||
#define FT_DEBUG_HOOK_TRUETYPE 0
|
||||
|
||||
|
||||
typedef void (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap* bitmap,
|
||||
FT_Render_Mode render_mode,
|
||||
FT_Library library );
|
||||
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 );
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
|
@ -876,7 +891,7 @@ FT_BEGIN_HEADER
|
|||
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
|
||||
FT_LcdFilter lcd_filter;
|
||||
FT_Int lcd_extra; /* number of extra pixels */
|
||||
FT_Byte lcd_weights[5]; /* filter weights, if any */
|
||||
FT_LcdFiveTapFilter lcd_weights; /* filter weights, if any */
|
||||
FT_Bitmap_LcdFilterFunc lcd_filter_func; /* filtering callback */
|
||||
#endif
|
||||
|
||||
|
|
|
@ -30,14 +30,13 @@
|
|||
#define USE_LEGACY
|
||||
|
||||
/* FIR filter used by the default and light filters */
|
||||
static void
|
||||
_ft_lcd_filter_fir( FT_Bitmap* bitmap,
|
||||
FT_Render_Mode mode,
|
||||
FT_Library library )
|
||||
FT_BASE( void )
|
||||
ft_lcd_filter_fir( FT_Bitmap* bitmap,
|
||||
FT_Render_Mode mode,
|
||||
FT_LcdFiveTapFilter weights )
|
||||
{
|
||||
FT_Byte* weights = library->lcd_weights;
|
||||
FT_UInt width = (FT_UInt)bitmap->width;
|
||||
FT_UInt height = (FT_UInt)bitmap->rows;
|
||||
FT_UInt width = (FT_UInt)bitmap->width;
|
||||
FT_UInt height = (FT_UInt)bitmap->rows;
|
||||
|
||||
|
||||
/* horizontal in-place FIR filter */
|
||||
|
@ -176,7 +175,7 @@
|
|||
static void
|
||||
_ft_lcd_filter_legacy( FT_Bitmap* bitmap,
|
||||
FT_Render_Mode mode,
|
||||
FT_Library library )
|
||||
FT_Byte* weights )
|
||||
{
|
||||
FT_UInt width = (FT_UInt)bitmap->width;
|
||||
FT_UInt height = (FT_UInt)bitmap->rows;
|
||||
|
@ -189,7 +188,7 @@
|
|||
{ 65538 * 1/13, 65538 * 1/6, 65538 * 9/13 }
|
||||
};
|
||||
|
||||
FT_UNUSED( library );
|
||||
FT_UNUSED( weights );
|
||||
|
||||
|
||||
/* horizontal in-place intra-pixel filter */
|
||||
|
@ -295,8 +294,8 @@
|
|||
if ( !weights )
|
||||
return FT_THROW( Invalid_Argument );
|
||||
|
||||
ft_memcpy( library->lcd_weights, weights, 5 );
|
||||
library->lcd_filter_func = _ft_lcd_filter_fir;
|
||||
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;
|
||||
|
@ -307,10 +306,10 @@
|
|||
FT_Library_SetLcdFilter( FT_Library library,
|
||||
FT_LcdFilter filter )
|
||||
{
|
||||
static const FT_Byte default_filter[5] =
|
||||
{ 0x08, 0x4d, 0x56, 0x4d, 0x08 };
|
||||
static const FT_Byte light_filter[5] =
|
||||
{ 0x00, 0x55, 0x56, 0x55, 0x00 };
|
||||
static const FT_LcdFiveTapFilter default_weights =
|
||||
{ 0x08, 0x4d, 0x56, 0x4d, 0x08 };
|
||||
static const FT_LcdFiveTapFilter light_weights =
|
||||
{ 0x00, 0x55, 0x56, 0x55, 0x00 };
|
||||
|
||||
|
||||
if ( !library )
|
||||
|
@ -324,14 +323,18 @@
|
|||
break;
|
||||
|
||||
case FT_LCD_FILTER_DEFAULT:
|
||||
ft_memcpy( library->lcd_weights, default_filter, 5 );
|
||||
library->lcd_filter_func = _ft_lcd_filter_fir;
|
||||
ft_memcpy( library->lcd_weights,
|
||||
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:
|
||||
ft_memcpy( library->lcd_weights, light_filter, 5 );
|
||||
library->lcd_filter_func = _ft_lcd_filter_fir;
|
||||
ft_memcpy( library->lcd_weights,
|
||||
light_weights,
|
||||
FT_LCD_FILTER_FIVE_TAPS );
|
||||
library->lcd_filter_func = ft_lcd_filter_fir;
|
||||
library->lcd_extra = 2;
|
||||
break;
|
||||
|
||||
|
@ -356,6 +359,17 @@
|
|||
|
||||
#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
|
||||
|
||||
FT_BASE( void )
|
||||
ft_lcd_filter_fir( FT_Bitmap* bitmap,
|
||||
FT_Render_Mode mode,
|
||||
FT_LcdFiveTapFilter weights )
|
||||
{
|
||||
FT_UNUSED( bitmap );
|
||||
FT_UNUSED( mode );
|
||||
FT_UNUSED( weights );
|
||||
}
|
||||
|
||||
|
||||
FT_EXPORT_DEF( FT_Error )
|
||||
FT_Library_SetLcdFilterWeights( FT_Library library,
|
||||
unsigned char *weights )
|
||||
|
|
|
@ -2424,6 +2424,10 @@
|
|||
internal->transform_delta.y = 0;
|
||||
|
||||
internal->refcount = 1;
|
||||
|
||||
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
|
||||
ft_memset( internal->lcd_weights, 0, FT_LCD_FILTER_FIVE_TAPS );
|
||||
#endif
|
||||
}
|
||||
|
||||
if ( aface )
|
||||
|
@ -3607,8 +3611,31 @@
|
|||
|
||||
for ( ; num_properties > 0; num_properties-- )
|
||||
{
|
||||
error = FT_THROW( Invalid_Argument );
|
||||
goto Exit;
|
||||
if ( properties->tag == FT_PARAM_TAG_LCD_FILTER_WEIGHTS )
|
||||
{
|
||||
#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 );
|
||||
}
|
||||
#else
|
||||
error = FT_THROW( Unimplemented_Feature );
|
||||
goto Exit;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
error = FT_THROW( Invalid_Argument );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if ( error )
|
||||
break;
|
||||
|
|
|
@ -122,6 +122,60 @@
|
|||
FT_Bool have_outline_shifted = FALSE;
|
||||
FT_Bool have_buffer = FALSE;
|
||||
|
||||
#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;
|
||||
|
||||
|
||||
if ( slot->face )
|
||||
{
|
||||
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 that needs 2 extra pixels.
|
||||
*/
|
||||
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
|
||||
{
|
||||
/*
|
||||
* 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_filter_func = slot->library->lcd_filter_func;
|
||||
lcd_extra = slot->library->lcd_extra;
|
||||
}
|
||||
|
||||
#endif /*FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
|
||||
|
||||
/* check glyph image format */
|
||||
if ( slot->format != render->glyph_format )
|
||||
|
@ -177,28 +231,23 @@
|
|||
height *= 3;
|
||||
|
||||
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
|
||||
|
||||
if ( slot->library->lcd_filter_func )
|
||||
if ( lcd_filter_func )
|
||||
{
|
||||
FT_Int extra = slot->library->lcd_extra;
|
||||
|
||||
|
||||
if ( hmul )
|
||||
{
|
||||
x_shift += 64 * ( extra >> 1 );
|
||||
x_left -= extra >> 1;
|
||||
width += 3 * extra;
|
||||
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 * ( extra >> 1 );
|
||||
y_top += extra >> 1;
|
||||
height += 3 * extra;
|
||||
y_shift += 64 * ( lcd_extra >> 1 );
|
||||
y_top += lcd_extra >> 1;
|
||||
height += 3 * lcd_extra;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -299,8 +348,8 @@
|
|||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
if ( slot->library->lcd_filter_func )
|
||||
slot->library->lcd_filter_func( bitmap, mode, slot->library );
|
||||
if ( lcd_filter_func )
|
||||
lcd_filter_func( bitmap, mode, lcd_weights );
|
||||
|
||||
#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
|
||||
|
||||
|
|
Loading…
Reference in New Issue