[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:
Alexei Podtelezhnikov 2017-06-17 23:28:14 -04:00
parent 4dc00cf5c0
commit 7b7278334c
3 changed files with 102 additions and 123 deletions

View File

@ -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.

View File

@ -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 );
} }
} }
} }

View File

@ -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