[base, smooth] LCD filtering cleanups.
* src/base/ftlcdlil.c (ft_lcd_filter_fir, _ft_lcd_filter_legacy): Clean up, start filtering from the bottom-left origin. * src/smooth/ftsmooth.c (ft_smooth_render_generic): Updated.
This commit is contained in:
parent
4dc00cf5c0
commit
7b7278334c
|
@ -1,3 +1,12 @@
|
||||||
|
2017-06-17 Alexei Podtelezhnikov <apodtele@gmail.com>
|
||||||
|
|
||||||
|
[base, smooth] LCD filtering cleanups.
|
||||||
|
|
||||||
|
* src/base/ftlcdlil.c (ft_lcd_filter_fir, _ft_lcd_filter_legacy):
|
||||||
|
Clean up, start filtering from the bottom-left origin.
|
||||||
|
|
||||||
|
* src/smooth/ftsmooth.c (ft_smooth_render_generic): Updated.
|
||||||
|
|
||||||
2017-06-16 Werner Lemberg <wl@gnu.org>
|
2017-06-16 Werner Lemberg <wl@gnu.org>
|
||||||
|
|
||||||
[truetype] Integer overflows.
|
[truetype] Integer overflows.
|
||||||
|
|
|
@ -35,135 +35,113 @@
|
||||||
FT_Render_Mode mode,
|
FT_Render_Mode mode,
|
||||||
FT_LcdFiveTapFilter weights )
|
FT_LcdFiveTapFilter weights )
|
||||||
{
|
{
|
||||||
FT_UInt width = (FT_UInt)bitmap->width;
|
FT_UInt width = (FT_UInt)bitmap->width;
|
||||||
FT_UInt height = (FT_UInt)bitmap->rows;
|
FT_UInt height = (FT_UInt)bitmap->rows;
|
||||||
|
FT_Int pitch = bitmap->pitch;
|
||||||
|
FT_Byte* origin = bitmap->buffer;
|
||||||
|
|
||||||
|
|
||||||
|
/* take care of bitmap flow */
|
||||||
|
if ( pitch > 0 )
|
||||||
|
origin += pitch * (FT_Int)( height - 1 );
|
||||||
|
|
||||||
/* horizontal in-place FIR filter */
|
/* horizontal in-place FIR filter */
|
||||||
if ( mode == FT_RENDER_MODE_LCD && width >= 4 )
|
if ( mode == FT_RENDER_MODE_LCD && width >= 2 )
|
||||||
{
|
{
|
||||||
FT_Byte* line = bitmap->buffer;
|
FT_Byte* line = origin;
|
||||||
|
|
||||||
|
|
||||||
/* take care of bitmap flow */
|
/* `fir' must be at least 32 bit wide, since the sum of */
|
||||||
if ( bitmap->pitch < 0 )
|
/* the values in `weights' can exceed 0xFF */
|
||||||
line -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
|
|
||||||
|
|
||||||
/* `fir' and `pix' must be at least 32 bit wide, since the sum of */
|
for ( ; height > 0; height--, line -= pitch )
|
||||||
/* the values in `weights' can exceed 0xFF */
|
|
||||||
|
|
||||||
for ( ; height > 0; height--, line += bitmap->pitch )
|
|
||||||
{
|
{
|
||||||
FT_UInt fir[4]; /* below, `pix' is used as the 5th element */
|
FT_UInt fir[5];
|
||||||
FT_UInt val1, xx;
|
FT_UInt val, xx;
|
||||||
|
|
||||||
|
|
||||||
val1 = line[0];
|
val = line[0];
|
||||||
fir[0] = weights[2] * val1;
|
fir[2] = weights[2] * val;
|
||||||
fir[1] = weights[3] * val1;
|
fir[3] = weights[3] * val;
|
||||||
fir[2] = weights[4] * val1;
|
fir[4] = weights[4] * val;
|
||||||
fir[3] = 0;
|
|
||||||
|
|
||||||
val1 = line[1];
|
val = line[1];
|
||||||
fir[0] += weights[1] * val1;
|
fir[1] = fir[2] + weights[1] * val;
|
||||||
fir[1] += weights[2] * val1;
|
fir[2] = fir[3] + weights[2] * val;
|
||||||
fir[2] += weights[3] * val1;
|
fir[3] = fir[4] + weights[3] * val;
|
||||||
fir[3] += weights[4] * val1;
|
fir[4] = weights[4] * val;
|
||||||
|
|
||||||
for ( xx = 2; xx < width; xx++ )
|
for ( xx = 2; xx < width; xx++ )
|
||||||
{
|
{
|
||||||
FT_UInt val, pix;
|
|
||||||
|
|
||||||
|
|
||||||
val = line[xx];
|
val = line[xx];
|
||||||
pix = fir[0] + weights[0] * val;
|
fir[0] = fir[1] + weights[0] * val;
|
||||||
fir[0] = fir[1] + weights[1] * val;
|
fir[1] = fir[2] + weights[1] * val;
|
||||||
fir[1] = fir[2] + weights[2] * val;
|
fir[2] = fir[3] + weights[2] * val;
|
||||||
fir[2] = fir[3] + weights[3] * val;
|
fir[3] = fir[4] + weights[3] * val;
|
||||||
fir[3] = weights[4] * val;
|
fir[4] = weights[4] * val;
|
||||||
|
|
||||||
pix >>= 8;
|
fir[0] >>= 8;
|
||||||
pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
|
fir[0] |= (FT_UInt)-(FT_Int)( fir[0] >> 8 );
|
||||||
line[xx - 2] = (FT_Byte)pix;
|
line[xx - 2] = (FT_Byte)fir[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
fir[1] >>= 8;
|
||||||
FT_UInt pix;
|
fir[1] |= (FT_UInt)-(FT_Int)( fir[1] >> 8 );
|
||||||
|
line[xx - 2] = (FT_Byte)fir[1];
|
||||||
|
|
||||||
|
fir[2] >>= 8;
|
||||||
pix = fir[0] >> 8;
|
fir[2] |= (FT_UInt)-(FT_Int)( fir[2] >> 8 );
|
||||||
pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
|
line[xx - 1] = (FT_Byte)fir[2];
|
||||||
line[xx - 2] = (FT_Byte)pix;
|
|
||||||
|
|
||||||
pix = fir[1] >> 8;
|
|
||||||
pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
|
|
||||||
line[xx - 1] = (FT_Byte)pix;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vertical in-place FIR filter */
|
/* vertical in-place FIR filter */
|
||||||
else if ( mode == FT_RENDER_MODE_LCD_V && height >= 4 )
|
else if ( mode == FT_RENDER_MODE_LCD_V && height >= 2 )
|
||||||
{
|
{
|
||||||
FT_Byte* column = bitmap->buffer;
|
FT_Byte* column = origin;
|
||||||
FT_Int pitch = bitmap->pitch;
|
|
||||||
|
|
||||||
|
|
||||||
/* take care of bitmap flow */
|
|
||||||
if ( bitmap->pitch < 0 )
|
|
||||||
column -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
|
|
||||||
|
|
||||||
for ( ; width > 0; width--, column++ )
|
for ( ; width > 0; width--, column++ )
|
||||||
{
|
{
|
||||||
FT_Byte* col = column;
|
FT_Byte* col = column;
|
||||||
FT_UInt fir[4]; /* below, `pix' is used as the 5th element */
|
FT_UInt fir[5];
|
||||||
FT_UInt val1, yy;
|
FT_UInt val, yy;
|
||||||
|
|
||||||
|
|
||||||
val1 = col[0];
|
val = col[0];
|
||||||
fir[0] = weights[2] * val1;
|
fir[2] = weights[2] * val;
|
||||||
fir[1] = weights[3] * val1;
|
fir[3] = weights[3] * val;
|
||||||
fir[2] = weights[4] * val1;
|
fir[4] = weights[4] * val;
|
||||||
fir[3] = 0;
|
col -= pitch;
|
||||||
col += pitch;
|
|
||||||
|
|
||||||
val1 = col[0];
|
val = col[0];
|
||||||
fir[0] += weights[1] * val1;
|
fir[1] = fir[2] + weights[1] * val;
|
||||||
fir[1] += weights[2] * val1;
|
fir[2] = fir[3] + weights[2] * val;
|
||||||
fir[2] += weights[3] * val1;
|
fir[3] = fir[4] + weights[3] * val;
|
||||||
fir[3] += weights[4] * val1;
|
fir[4] = weights[4] * val;
|
||||||
col += pitch;
|
col -= pitch;
|
||||||
|
|
||||||
for ( yy = 2; yy < height; yy++ )
|
for ( yy = 2; yy < height; yy++, col -= pitch )
|
||||||
{
|
{
|
||||||
FT_UInt val, pix;
|
|
||||||
|
|
||||||
|
|
||||||
val = col[0];
|
val = col[0];
|
||||||
pix = fir[0] + weights[0] * val;
|
fir[0] = fir[1] + weights[0] * val;
|
||||||
fir[0] = fir[1] + weights[1] * val;
|
fir[1] = fir[2] + weights[1] * val;
|
||||||
fir[1] = fir[2] + weights[2] * val;
|
fir[2] = fir[3] + weights[2] * val;
|
||||||
fir[2] = fir[3] + weights[3] * val;
|
fir[3] = fir[4] + weights[3] * val;
|
||||||
fir[3] = weights[4] * val;
|
fir[4] = weights[4] * val;
|
||||||
|
|
||||||
pix >>= 8;
|
fir[0] >>= 8;
|
||||||
pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
|
fir[0] |= (FT_UInt)-(FT_Int)( fir[0] >> 8 );
|
||||||
col[-2 * pitch] = (FT_Byte)pix;
|
col[pitch * 2] = (FT_Byte)fir[0];
|
||||||
col += pitch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
fir[1] >>= 8;
|
||||||
FT_UInt pix;
|
fir[1] |= (FT_UInt)-(FT_Int)( fir[1] >> 8 );
|
||||||
|
col[pitch * 2] = (FT_Byte)fir[1];
|
||||||
|
|
||||||
|
fir[2] >>= 8;
|
||||||
pix = fir[0] >> 8;
|
fir[2] |= (FT_UInt)-(FT_Int)( fir[2] >> 8 );
|
||||||
pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
|
col[pitch] = (FT_Byte)fir[2];
|
||||||
col[-2 * pitch] = (FT_Byte)pix;
|
|
||||||
|
|
||||||
pix = fir[1] >> 8;
|
|
||||||
pix |= (FT_UInt)-(FT_Int)( pix >> 8 );
|
|
||||||
col[-pitch] = (FT_Byte)pix;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,9 +155,10 @@
|
||||||
FT_Render_Mode mode,
|
FT_Render_Mode mode,
|
||||||
FT_Byte* weights )
|
FT_Byte* weights )
|
||||||
{
|
{
|
||||||
FT_UInt width = (FT_UInt)bitmap->width;
|
FT_UInt width = (FT_UInt)bitmap->width;
|
||||||
FT_UInt height = (FT_UInt)bitmap->rows;
|
FT_UInt height = (FT_UInt)bitmap->rows;
|
||||||
FT_Int pitch = bitmap->pitch;
|
FT_Int pitch = bitmap->pitch;
|
||||||
|
FT_Byte* origin = bitmap->buffer;
|
||||||
|
|
||||||
static const unsigned int filters[3][3] =
|
static const unsigned int filters[3][3] =
|
||||||
{
|
{
|
||||||
|
@ -191,33 +170,31 @@
|
||||||
FT_UNUSED( weights );
|
FT_UNUSED( weights );
|
||||||
|
|
||||||
|
|
||||||
|
/* take care of bitmap flow */
|
||||||
|
if ( pitch > 0 )
|
||||||
|
origin += pitch * (FT_Int)( height - 1 );
|
||||||
|
|
||||||
/* horizontal in-place intra-pixel filter */
|
/* horizontal in-place intra-pixel filter */
|
||||||
if ( mode == FT_RENDER_MODE_LCD && width >= 3 )
|
if ( mode == FT_RENDER_MODE_LCD && width >= 3 )
|
||||||
{
|
{
|
||||||
FT_Byte* line = bitmap->buffer;
|
FT_Byte* line = origin;
|
||||||
|
|
||||||
|
|
||||||
/* take care of bitmap flow */
|
for ( ; height > 0; height--, line -= pitch )
|
||||||
if ( bitmap->pitch < 0 )
|
|
||||||
line -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
|
|
||||||
|
|
||||||
for ( ; height > 0; height--, line += pitch )
|
|
||||||
{
|
{
|
||||||
FT_UInt xx;
|
FT_UInt xx;
|
||||||
|
|
||||||
|
|
||||||
for ( xx = 0; xx < width; xx += 3 )
|
for ( xx = 0; xx < width; xx += 3 )
|
||||||
{
|
{
|
||||||
FT_UInt r = 0;
|
FT_UInt r, g, b;
|
||||||
FT_UInt g = 0;
|
|
||||||
FT_UInt b = 0;
|
|
||||||
FT_UInt p;
|
FT_UInt p;
|
||||||
|
|
||||||
|
|
||||||
p = line[xx];
|
p = line[xx];
|
||||||
r += filters[0][0] * p;
|
r = filters[0][0] * p;
|
||||||
g += filters[0][1] * p;
|
g = filters[0][1] * p;
|
||||||
b += filters[0][2] * p;
|
b = filters[0][2] * p;
|
||||||
|
|
||||||
p = line[xx + 1];
|
p = line[xx + 1];
|
||||||
r += filters[1][0] * p;
|
r += filters[1][0] * p;
|
||||||
|
@ -237,31 +214,24 @@
|
||||||
}
|
}
|
||||||
else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 )
|
else if ( mode == FT_RENDER_MODE_LCD_V && height >= 3 )
|
||||||
{
|
{
|
||||||
FT_Byte* column = bitmap->buffer;
|
FT_Byte* column = origin;
|
||||||
|
|
||||||
|
|
||||||
/* take care of bitmap flow */
|
|
||||||
if ( bitmap->pitch < 0 )
|
|
||||||
column -= bitmap->pitch * (FT_Int)( bitmap->rows - 1 );
|
|
||||||
|
|
||||||
for ( ; width > 0; width--, column++ )
|
for ( ; width > 0; width--, column++ )
|
||||||
{
|
{
|
||||||
FT_Byte* col = column;
|
FT_Byte* col = column - 2 * pitch;
|
||||||
FT_Byte* col_end = col + (FT_Int)height * pitch;
|
|
||||||
|
|
||||||
|
|
||||||
for ( ; col < col_end; col += 3 * pitch )
|
for ( ; height > 0; height -= 3, col -= 3 * pitch )
|
||||||
{
|
{
|
||||||
FT_UInt r = 0;
|
FT_UInt r, g, b;
|
||||||
FT_UInt g = 0;
|
|
||||||
FT_UInt b = 0;
|
|
||||||
FT_UInt p;
|
FT_UInt p;
|
||||||
|
|
||||||
|
|
||||||
p = col[0];
|
p = col[0];
|
||||||
r += filters[0][0] * p;
|
r = filters[0][0] * p;
|
||||||
g += filters[0][1] * p;
|
g = filters[0][1] * p;
|
||||||
b += filters[0][2] * p;
|
b = filters[0][2] * p;
|
||||||
|
|
||||||
p = col[pitch];
|
p = col[pitch];
|
||||||
r += filters[1][0] * p;
|
r += filters[1][0] * p;
|
||||||
|
@ -275,7 +245,7 @@
|
||||||
|
|
||||||
col[0] = (FT_Byte)( r / 65536 );
|
col[0] = (FT_Byte)( r / 65536 );
|
||||||
col[pitch] = (FT_Byte)( g / 65536 );
|
col[pitch] = (FT_Byte)( g / 65536 );
|
||||||
col[2 * pitch] = (FT_Byte)( b / 65536 );
|
col[pitch * 2] = (FT_Byte)( b / 65536 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,10 +207,10 @@
|
||||||
|
|
||||||
if ( vmul )
|
if ( vmul )
|
||||||
{
|
{
|
||||||
cbox.yMax += lcd_weights[0] ? 43
|
cbox.yMax += lcd_weights[4] ? 43
|
||||||
: lcd_weights[1] ? 22 : 0;
|
|
||||||
cbox.yMin -= lcd_weights[4] ? 43
|
|
||||||
: lcd_weights[3] ? 22 : 0;
|
: lcd_weights[3] ? 22 : 0;
|
||||||
|
cbox.yMin -= lcd_weights[0] ? 43
|
||||||
|
: lcd_weights[1] ? 22 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue