forked from minhngoc25a/freetype2
Bitmap metrics presetting [1/2].
This mainly just extracts the code for presetting the bitmap metrics from the monochrome, grayscale, and LCD renderers into a separate function. * src/base/ftobjs.c (ft_glyphslot_preset_bitmap): New function that calculates prespective bitmap metrics for the given rendering mode. * include/freetype/internal/ftobjs.h (ft_glyphslot_preset_bitmap): Declare it. * src/base/ftlcdfil.c (ft_lcd_padding): New helper function that adds padding to CBox taking into account pecularities of LCD rendering. * include/freetype/ftlcdfil.h (ft_lcd_padding): Declare it. * src/raster/ftrend1.c (ft_raster1_render): Reworked to use `ft_glyphslot_preset_bitmap'. * src/smooth/ftsmooth.c (ft_smooth_render_generic): Ditto. (ft_smooth_render_lcd, ft_smooth_render_lcd): The pixel_mode setting is moved to `ft_glyphslot_preset_bitmap'.
This commit is contained in:
parent
dd40d10e81
commit
61d1818b5e
23
ChangeLog
23
ChangeLog
|
@ -1,3 +1,26 @@
|
|||
2017-09-28 Alexei Podtelezhnikov <apodtele@gmail.com>
|
||||
|
||||
Bitmap metrics presetting [1/2].
|
||||
|
||||
This mainly just extracts the code for presetting the bitmap metrics
|
||||
from the monochrome, grayscale, and LCD renderers into a separate
|
||||
function.
|
||||
|
||||
* src/base/ftobjs.c (ft_glyphslot_preset_bitmap): New function that
|
||||
calculates prespective bitmap metrics for the given rendering mode.
|
||||
* include/freetype/internal/ftobjs.h (ft_glyphslot_preset_bitmap):
|
||||
Declare it.
|
||||
|
||||
* src/base/ftlcdfil.c (ft_lcd_padding): New helper function that adds
|
||||
padding to CBox taking into account pecularities of LCD rendering.
|
||||
* include/freetype/ftlcdfil.h (ft_lcd_padding): Declare it.
|
||||
|
||||
* src/raster/ftrend1.c (ft_raster1_render): Reworked to use
|
||||
`ft_glyphslot_preset_bitmap'.
|
||||
* src/smooth/ftsmooth.c (ft_smooth_render_generic): Ditto.
|
||||
(ft_smooth_render_lcd, ft_smooth_render_lcd): The pixel_mode setting
|
||||
is moved to `ft_glyphslot_preset_bitmap'.
|
||||
|
||||
2017-09-28 Ewald Hew <ewaldhew@gmail.com>
|
||||
|
||||
[psaux] Fix compiler warning.
|
||||
|
|
|
@ -316,6 +316,14 @@ FT_BEGIN_HEADER
|
|||
|
||||
typedef FT_Byte FT_LcdFiveTapFilter[FT_LCD_FILTER_FIVE_TAPS];
|
||||
|
||||
|
||||
FT_BASE( void )
|
||||
ft_lcd_padding( FT_Pos* Min,
|
||||
FT_Pos* Max,
|
||||
FT_GlyphSlot slot );
|
||||
|
||||
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
|
||||
|
||||
typedef void (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap* bitmap,
|
||||
FT_Render_Mode render_mode,
|
||||
FT_Byte* weights );
|
||||
|
@ -327,6 +335,8 @@ FT_BEGIN_HEADER
|
|||
FT_Render_Mode mode,
|
||||
FT_LcdFiveTapFilter weights );
|
||||
|
||||
#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
|
||||
|
||||
|
||||
/* */
|
||||
|
||||
|
|
|
@ -708,6 +708,12 @@ FT_BEGIN_HEADER
|
|||
ft_glyphslot_free_bitmap( FT_GlyphSlot slot );
|
||||
|
||||
|
||||
/* Preset bitmap metrics of an outline glyphslot prior to rendering. */
|
||||
FT_BASE( void )
|
||||
ft_glyphslot_preset_bitmap( FT_GlyphSlot slot,
|
||||
FT_Render_Mode mode,
|
||||
const FT_Vector* origin );
|
||||
|
||||
/* Allocate a new bitmap buffer in a glyph slot. */
|
||||
FT_BASE( FT_Error )
|
||||
ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot,
|
||||
|
|
|
@ -31,6 +31,39 @@
|
|||
|
||||
#define FT_SHIFTCLAMP( x ) ( x >>= 8, (FT_Byte)( x > 255 ? 255 : x ) )
|
||||
|
||||
|
||||
/* add padding according to filter weights */
|
||||
FT_BASE_DEF (void)
|
||||
ft_lcd_padding( FT_Pos* Min,
|
||||
FT_Pos* Max,
|
||||
FT_GlyphSlot slot )
|
||||
{
|
||||
FT_Byte* lcd_weights;
|
||||
FT_Bitmap_LcdFilterFunc lcd_filter_func;
|
||||
|
||||
|
||||
/* Per-face LCD filtering takes priority if set up. */
|
||||
if ( slot->face && slot->face->internal->lcd_filter_func )
|
||||
{
|
||||
lcd_weights = slot->face->internal->lcd_weights;
|
||||
lcd_filter_func = slot->face->internal->lcd_filter_func;
|
||||
}
|
||||
else
|
||||
{
|
||||
lcd_weights = slot->library->lcd_weights;
|
||||
lcd_filter_func = slot->library->lcd_filter_func;
|
||||
}
|
||||
|
||||
if ( lcd_filter_func == ft_lcd_filter_fir )
|
||||
{
|
||||
*Min -= lcd_weights[0] ? 43 :
|
||||
lcd_weights[1] ? 22 : 0;
|
||||
*Max += lcd_weights[4] ? 43 :
|
||||
lcd_weights[3] ? 22 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* FIR filter used by the default and light filters */
|
||||
FT_BASE_DEF( void )
|
||||
ft_lcd_filter_fir( FT_Bitmap* bitmap,
|
||||
|
@ -310,14 +343,16 @@
|
|||
|
||||
#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
|
||||
|
||||
FT_BASE( void )
|
||||
ft_lcd_filter_fir( FT_Bitmap* bitmap,
|
||||
FT_Render_Mode mode,
|
||||
FT_LcdFiveTapFilter weights )
|
||||
/* add padding according to accommodate outline shifts */
|
||||
FT_BASE_DEF (void)
|
||||
ft_lcd_padding( FT_Pos* Min,
|
||||
FT_Pos* Max,
|
||||
FT_GlyphSlot slot )
|
||||
{
|
||||
FT_UNUSED( bitmap );
|
||||
FT_UNUSED( mode );
|
||||
FT_UNUSED( weights );
|
||||
FT_UNUSED( slot );
|
||||
|
||||
*Min -= 21;
|
||||
*Max += 21;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -327,6 +327,135 @@
|
|||
}
|
||||
|
||||
|
||||
FT_BASE_DEF( void )
|
||||
ft_glyphslot_preset_bitmap( FT_GlyphSlot slot,
|
||||
FT_Render_Mode mode,
|
||||
const FT_Vector* origin )
|
||||
{
|
||||
FT_Outline* outline = &slot->outline;
|
||||
FT_Bitmap* bitmap = &slot->bitmap;
|
||||
|
||||
FT_Pixel_Mode pixel_mode;
|
||||
|
||||
FT_BBox cbox;
|
||||
FT_Pos x_shift = 0;
|
||||
FT_Pos y_shift = 0;
|
||||
FT_Pos x_left, y_top;
|
||||
FT_Pos width, height, pitch;
|
||||
|
||||
|
||||
if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
|
||||
return;
|
||||
|
||||
if ( origin )
|
||||
{
|
||||
x_shift = origin->x;
|
||||
y_shift = origin->y;
|
||||
}
|
||||
|
||||
/* compute the control box, and grid fit it */
|
||||
/* taking into account the origin shift */
|
||||
FT_Outline_Get_CBox( outline, &cbox );
|
||||
|
||||
cbox.xMin += x_shift;
|
||||
cbox.yMin += y_shift;
|
||||
cbox.xMax += x_shift;
|
||||
cbox.yMax += y_shift;
|
||||
|
||||
switch ( mode )
|
||||
{
|
||||
case FT_RENDER_MODE_MONO:
|
||||
pixel_mode = FT_PIXEL_MODE_MONO;
|
||||
#if 1
|
||||
/* undocumented but confirmed: bbox values get rounded */
|
||||
/* unless the rounded box can collapse for a narrow glyph */
|
||||
if ( cbox.xMax - cbox.xMin < 64 )
|
||||
{
|
||||
cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
|
||||
cbox.xMax = FT_PIX_CEIL( cbox.xMax );
|
||||
}
|
||||
else
|
||||
{
|
||||
cbox.xMin = FT_PIX_ROUND( cbox.xMin );
|
||||
cbox.xMax = FT_PIX_ROUND( cbox.xMax );
|
||||
}
|
||||
|
||||
if ( cbox.yMax - cbox.yMin < 64 )
|
||||
{
|
||||
cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
|
||||
cbox.yMax = FT_PIX_CEIL( cbox.yMax );
|
||||
}
|
||||
else
|
||||
{
|
||||
cbox.yMin = FT_PIX_ROUND( cbox.yMin );
|
||||
cbox.yMax = FT_PIX_ROUND( cbox.yMax );
|
||||
}
|
||||
#else
|
||||
cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
|
||||
cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
|
||||
cbox.xMax = FT_PIX_CEIL( cbox.xMax );
|
||||
cbox.yMax = FT_PIX_CEIL( cbox.yMax );
|
||||
#endif
|
||||
break;
|
||||
|
||||
case FT_RENDER_MODE_LCD:
|
||||
pixel_mode = FT_PIXEL_MODE_LCD;
|
||||
ft_lcd_padding( &cbox.xMin, &cbox.xMax, slot );
|
||||
goto Round;
|
||||
|
||||
case FT_RENDER_MODE_LCD_V:
|
||||
pixel_mode = FT_PIXEL_MODE_LCD_V;
|
||||
ft_lcd_padding( &cbox.yMin, &cbox.yMax, slot );
|
||||
goto Round;
|
||||
|
||||
case FT_RENDER_MODE_NORMAL:
|
||||
case FT_RENDER_MODE_LIGHT:
|
||||
default:
|
||||
pixel_mode = FT_PIXEL_MODE_GRAY;
|
||||
Round:
|
||||
cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
|
||||
cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
|
||||
cbox.xMax = FT_PIX_CEIL( cbox.xMax );
|
||||
cbox.yMax = FT_PIX_CEIL( cbox.yMax );
|
||||
}
|
||||
|
||||
x_shift -= cbox.xMin;
|
||||
y_shift -= cbox.yMin;
|
||||
|
||||
x_left = cbox.xMin >> 6;
|
||||
y_top = cbox.yMax >> 6;
|
||||
|
||||
width = (FT_ULong)( cbox.xMax - cbox.xMin ) >> 6;
|
||||
height = (FT_ULong)( cbox.yMax - cbox.yMin ) >> 6;
|
||||
|
||||
switch ( pixel_mode )
|
||||
{
|
||||
case FT_PIXEL_MODE_MONO:
|
||||
pitch = ( ( width + 15 ) >> 4 ) << 1;
|
||||
break;
|
||||
case FT_PIXEL_MODE_LCD:
|
||||
width *= 3;
|
||||
pitch = FT_PAD_CEIL( width, 4 );
|
||||
break;
|
||||
case FT_PIXEL_MODE_LCD_V:
|
||||
height *= 3;
|
||||
/* fall through */
|
||||
case FT_PIXEL_MODE_GRAY:
|
||||
default:
|
||||
pitch = width;
|
||||
}
|
||||
|
||||
slot->bitmap_left = (FT_Int)x_left;
|
||||
slot->bitmap_top = (FT_Int)y_top;
|
||||
|
||||
bitmap->pixel_mode = pixel_mode;
|
||||
bitmap->num_grays = 256;
|
||||
bitmap->width = (unsigned int)width;
|
||||
bitmap->rows = (unsigned int)height;
|
||||
bitmap->pitch = pitch;
|
||||
}
|
||||
|
||||
|
||||
FT_BASE_DEF( void )
|
||||
ft_glyphslot_set_bitmap( FT_GlyphSlot slot,
|
||||
FT_Byte* buffer )
|
||||
|
|
|
@ -98,11 +98,11 @@
|
|||
const FT_Vector* origin )
|
||||
{
|
||||
FT_Error error;
|
||||
FT_Outline* outline;
|
||||
FT_BBox cbox, cbox0;
|
||||
FT_UInt width, height, pitch;
|
||||
FT_Bitmap* bitmap;
|
||||
FT_Memory memory;
|
||||
FT_Outline* outline = &slot->outline;
|
||||
FT_Bitmap* bitmap = &slot->bitmap;
|
||||
FT_Memory memory = render->root.memory;
|
||||
FT_Pos x_shift = 0;
|
||||
FT_Pos y_shift = 0;
|
||||
|
||||
FT_Raster_Params params;
|
||||
|
||||
|
@ -121,60 +121,6 @@
|
|||
return FT_THROW( Cannot_Render_Glyph );
|
||||
}
|
||||
|
||||
outline = &slot->outline;
|
||||
|
||||
/* translate the outline to the new origin if needed */
|
||||
if ( origin )
|
||||
FT_Outline_Translate( outline, origin->x, origin->y );
|
||||
|
||||
/* compute the control box, and grid fit it */
|
||||
FT_Outline_Get_CBox( outline, &cbox0 );
|
||||
|
||||
/* undocumented but confirmed: bbox values get rounded */
|
||||
#if 1
|
||||
cbox.xMin = FT_PIX_ROUND( cbox0.xMin );
|
||||
cbox.yMin = FT_PIX_ROUND( cbox0.yMin );
|
||||
cbox.xMax = FT_PIX_ROUND( cbox0.xMax );
|
||||
cbox.yMax = FT_PIX_ROUND( cbox0.yMax );
|
||||
#else
|
||||
cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
|
||||
cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
|
||||
cbox.xMax = FT_PIX_CEIL( cbox.xMax );
|
||||
cbox.yMax = FT_PIX_CEIL( cbox.yMax );
|
||||
#endif
|
||||
|
||||
/* If either `width' or `height' round to 0, try */
|
||||
/* explicitly rounding up/down. In the case of */
|
||||
/* glyphs containing only one very narrow feature, */
|
||||
/* this gives the drop-out compensation in the scan */
|
||||
/* conversion code a chance to do its stuff. */
|
||||
width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
|
||||
if ( width == 0 )
|
||||
{
|
||||
cbox.xMin = FT_PIX_FLOOR( cbox0.xMin );
|
||||
cbox.xMax = FT_PIX_CEIL( cbox0.xMax );
|
||||
|
||||
width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
|
||||
}
|
||||
|
||||
height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
|
||||
if ( height == 0 )
|
||||
{
|
||||
cbox.yMin = FT_PIX_FLOOR( cbox0.yMin );
|
||||
cbox.yMax = FT_PIX_CEIL( cbox0.yMax );
|
||||
|
||||
height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
|
||||
}
|
||||
|
||||
if ( width > FT_USHORT_MAX || height > FT_USHORT_MAX )
|
||||
{
|
||||
error = FT_THROW( Invalid_Argument );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
bitmap = &slot->bitmap;
|
||||
memory = render->root.memory;
|
||||
|
||||
/* release old bitmap buffer */
|
||||
if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
|
||||
{
|
||||
|
@ -182,20 +128,26 @@
|
|||
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
|
||||
}
|
||||
|
||||
pitch = ( ( width + 15 ) >> 4 ) << 1;
|
||||
bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
|
||||
ft_glyphslot_preset_bitmap( slot, mode, origin );
|
||||
|
||||
bitmap->width = width;
|
||||
bitmap->rows = height;
|
||||
bitmap->pitch = (int)pitch;
|
||||
|
||||
if ( FT_ALLOC_MULT( bitmap->buffer, height, pitch ) )
|
||||
/* allocate new one */
|
||||
if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) )
|
||||
goto Exit;
|
||||
|
||||
slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
|
||||
|
||||
x_shift = -slot->bitmap_left * 64;
|
||||
y_shift = ( bitmap->rows - slot->bitmap_top ) * 64;
|
||||
|
||||
if ( origin )
|
||||
{
|
||||
x_shift += origin->x;
|
||||
y_shift += origin->y;
|
||||
}
|
||||
|
||||
/* translate outline to render it into the bitmap */
|
||||
FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin );
|
||||
if ( x_shift || y_shift )
|
||||
FT_Outline_Translate( outline, x_shift, y_shift );
|
||||
|
||||
/* set up parameters */
|
||||
params.target = bitmap;
|
||||
|
@ -204,17 +156,24 @@
|
|||
|
||||
/* render outline into the bitmap */
|
||||
error = render->raster_render( render->raster, ¶ms );
|
||||
|
||||
FT_Outline_Translate( outline, cbox.xMin, cbox.yMin );
|
||||
|
||||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
slot->format = FT_GLYPH_FORMAT_BITMAP;
|
||||
slot->bitmap_left = (FT_Int)( cbox.xMin >> 6 );
|
||||
slot->bitmap_top = (FT_Int)( cbox.yMax >> 6 );
|
||||
/* everything is fine; the glyph is now officially a bitmap */
|
||||
slot->format = FT_GLYPH_FORMAT_BITMAP;
|
||||
|
||||
error = FT_Err_Ok;
|
||||
|
||||
Exit:
|
||||
if ( x_shift || y_shift )
|
||||
FT_Outline_Translate( outline, -x_shift, -y_shift );
|
||||
if ( slot->format != FT_GLYPH_FORMAT_BITMAP &&
|
||||
slot->internal->flags & FT_GLYPH_OWN_BITMAP )
|
||||
{
|
||||
FT_FREE( bitmap->buffer );
|
||||
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
|
|
@ -101,36 +101,13 @@
|
|||
FT_Outline* outline = &slot->outline;
|
||||
FT_Bitmap* bitmap = &slot->bitmap;
|
||||
FT_Memory memory = render->root.memory;
|
||||
FT_BBox cbox;
|
||||
FT_Pos x_shift = 0;
|
||||
FT_Pos y_shift = 0;
|
||||
FT_Pos x_left, y_top;
|
||||
FT_Pos width, height, pitch;
|
||||
FT_Int hmul = ( mode == FT_RENDER_MODE_LCD );
|
||||
FT_Int vmul = ( mode == FT_RENDER_MODE_LCD_V );
|
||||
|
||||
FT_Raster_Params params;
|
||||
|
||||
FT_Bool have_outline_shifted = FALSE;
|
||||
FT_Bool have_buffer = FALSE;
|
||||
|
||||
#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
|
||||
FT_Byte* lcd_weights;
|
||||
FT_Bitmap_LcdFilterFunc lcd_filter_func;
|
||||
|
||||
|
||||
/* Per-face LCD filtering takes priority if set up. */
|
||||
if ( slot->face && slot->face->internal->lcd_filter_func )
|
||||
{
|
||||
lcd_weights = slot->face->internal->lcd_weights;
|
||||
lcd_filter_func = slot->face->internal->lcd_filter_func;
|
||||
}
|
||||
else
|
||||
{
|
||||
lcd_weights = slot->library->lcd_weights;
|
||||
lcd_filter_func = slot->library->lcd_filter_func;
|
||||
}
|
||||
#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
|
||||
|
||||
/* check glyph image format */
|
||||
if ( slot->format != render->glyph_format )
|
||||
|
@ -146,100 +123,6 @@
|
|||
goto Exit;
|
||||
}
|
||||
|
||||
if ( origin )
|
||||
{
|
||||
x_shift = origin->x;
|
||||
y_shift = origin->y;
|
||||
}
|
||||
|
||||
/* compute the control box, and grid fit it */
|
||||
/* taking into account the origin shift */
|
||||
FT_Outline_Get_CBox( outline, &cbox );
|
||||
|
||||
#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
|
||||
|
||||
/* add minimal padding for LCD rendering */
|
||||
if ( hmul )
|
||||
{
|
||||
cbox.xMax += 21;
|
||||
cbox.xMin -= 21;
|
||||
}
|
||||
|
||||
if ( vmul )
|
||||
{
|
||||
cbox.yMax += 21;
|
||||
cbox.yMin -= 21;
|
||||
}
|
||||
|
||||
#else /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
|
||||
|
||||
/* add minimal padding for LCD filter depending on specific weights */
|
||||
if ( lcd_filter_func == ft_lcd_filter_fir )
|
||||
{
|
||||
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[4] ? 43
|
||||
: lcd_weights[3] ? 22 : 0;
|
||||
cbox.yMin -= lcd_weights[0] ? 43
|
||||
: lcd_weights[1] ? 22 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
|
||||
|
||||
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 );
|
||||
cbox.yMax = FT_PIX_CEIL( cbox.yMax + y_shift );
|
||||
|
||||
x_shift -= cbox.xMin;
|
||||
y_shift -= cbox.yMin;
|
||||
|
||||
x_left = cbox.xMin >> 6;
|
||||
y_top = cbox.yMax >> 6;
|
||||
|
||||
width = (FT_ULong)( cbox.xMax - cbox.xMin ) >> 6;
|
||||
height = (FT_ULong)( cbox.yMax - cbox.yMin ) >> 6;
|
||||
|
||||
pitch = width;
|
||||
if ( hmul )
|
||||
{
|
||||
width *= 3;
|
||||
pitch = FT_PAD_CEIL( width, 4 );
|
||||
}
|
||||
|
||||
if ( vmul )
|
||||
height *= 3;
|
||||
|
||||
/*
|
||||
* XXX: on 16bit system, we return an error for huge bitmap
|
||||
* to prevent an overflow.
|
||||
*/
|
||||
if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX ||
|
||||
x_left < FT_INT_MIN || y_top < FT_INT_MIN )
|
||||
{
|
||||
error = FT_THROW( Invalid_Pixel_Size );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* Required check is (pitch * height < FT_ULONG_MAX), */
|
||||
/* but we care realistic cases only. Always pitch <= width. */
|
||||
if ( width > 0x7FFF || height > 0x7FFF )
|
||||
{
|
||||
FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n",
|
||||
width, height ));
|
||||
error = FT_THROW( Raster_Overflow );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
/* release old bitmap buffer */
|
||||
if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
|
||||
{
|
||||
|
@ -247,30 +130,30 @@
|
|||
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
|
||||
}
|
||||
|
||||
ft_glyphslot_preset_bitmap( slot, mode, origin );
|
||||
|
||||
/* allocate new one */
|
||||
if ( FT_ALLOC( bitmap->buffer, (FT_ULong)( pitch * height ) ) )
|
||||
if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) )
|
||||
goto Exit;
|
||||
else
|
||||
have_buffer = TRUE;
|
||||
|
||||
slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
|
||||
|
||||
slot->format = FT_GLYPH_FORMAT_BITMAP;
|
||||
slot->bitmap_left = (FT_Int)x_left;
|
||||
slot->bitmap_top = (FT_Int)y_top;
|
||||
x_shift = 64 * -slot->bitmap_left;
|
||||
y_shift = 64 * -slot->bitmap_top;
|
||||
if ( bitmap->pixel_mode == FT_PIXEL_MODE_LCD_V )
|
||||
y_shift += 64 * bitmap->rows / 3;
|
||||
else
|
||||
y_shift += 64 * bitmap->rows;
|
||||
|
||||
bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
|
||||
bitmap->num_grays = 256;
|
||||
bitmap->width = (unsigned int)width;
|
||||
bitmap->rows = (unsigned int)height;
|
||||
bitmap->pitch = pitch;
|
||||
if ( origin )
|
||||
{
|
||||
x_shift += origin->x;
|
||||
y_shift += origin->y;
|
||||
}
|
||||
|
||||
/* translate outline to render it into the bitmap */
|
||||
if ( x_shift || y_shift )
|
||||
{
|
||||
FT_Outline_Translate( outline, x_shift, y_shift );
|
||||
have_outline_shifted = TRUE;
|
||||
}
|
||||
|
||||
/* set up parameters */
|
||||
params.target = bitmap;
|
||||
|
@ -317,8 +200,28 @@
|
|||
if ( error )
|
||||
goto Exit;
|
||||
|
||||
if ( lcd_filter_func )
|
||||
lcd_filter_func( bitmap, mode, lcd_weights );
|
||||
/* finally apply filtering */
|
||||
if ( hmul || vmul )
|
||||
{
|
||||
FT_Byte* lcd_weights;
|
||||
FT_Bitmap_LcdFilterFunc lcd_filter_func;
|
||||
|
||||
|
||||
/* Per-face LCD filtering takes priority if set up. */
|
||||
if ( slot->face && slot->face->internal->lcd_filter_func )
|
||||
{
|
||||
lcd_weights = slot->face->internal->lcd_weights;
|
||||
lcd_filter_func = slot->face->internal->lcd_filter_func;
|
||||
}
|
||||
else
|
||||
{
|
||||
lcd_weights = slot->library->lcd_weights;
|
||||
lcd_filter_func = slot->library->lcd_filter_func;
|
||||
}
|
||||
|
||||
if ( lcd_filter_func )
|
||||
lcd_filter_func( bitmap, mode, lcd_weights );
|
||||
}
|
||||
|
||||
#else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
|
||||
|
||||
|
@ -328,6 +231,10 @@
|
|||
FT_Byte* temp;
|
||||
FT_Int i, j;
|
||||
|
||||
unsigned int height = bitmap->rows;
|
||||
unsigned int width = bitmap->width;
|
||||
int pitch = bitmap->pitch;
|
||||
|
||||
|
||||
/* Render 3 separate monochrome bitmaps, shifting the outline */
|
||||
/* by 1/3 pixel. */
|
||||
|
@ -378,6 +285,9 @@
|
|||
}
|
||||
else if ( vmul ) /* lcd_v */
|
||||
{
|
||||
int pitch = bitmap->pitch;
|
||||
|
||||
|
||||
/* Render 3 separate monochrome bitmaps, shifting the outline */
|
||||
/* by 1/3 pixel. Triple the pitch to render on each third row. */
|
||||
bitmap->pitch *= 3;
|
||||
|
@ -418,15 +328,16 @@
|
|||
|
||||
#endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
|
||||
|
||||
/* everything is fine; don't deallocate buffer */
|
||||
have_buffer = FALSE;
|
||||
/* everything is fine; the glyph is now officially a bitmap */
|
||||
slot->format = FT_GLYPH_FORMAT_BITMAP;
|
||||
|
||||
error = FT_Err_Ok;
|
||||
|
||||
Exit:
|
||||
if ( have_outline_shifted )
|
||||
if ( x_shift || y_shift )
|
||||
FT_Outline_Translate( outline, -x_shift, -y_shift );
|
||||
if ( have_buffer )
|
||||
if ( slot->format != FT_GLYPH_FORMAT_BITMAP &&
|
||||
slot->internal->flags & FT_GLYPH_OWN_BITMAP )
|
||||
{
|
||||
FT_FREE( bitmap->buffer );
|
||||
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
|
||||
|
@ -460,12 +371,8 @@
|
|||
{
|
||||
FT_Error error;
|
||||
|
||||
error = ft_smooth_render_generic( render, slot, mode, origin,
|
||||
FT_RENDER_MODE_LCD );
|
||||
if ( !error )
|
||||
slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;
|
||||
|
||||
return error;
|
||||
return ft_smooth_render_generic( render, slot, mode, origin,
|
||||
FT_RENDER_MODE_LCD );
|
||||
}
|
||||
|
||||
|
||||
|
@ -478,12 +385,8 @@
|
|||
{
|
||||
FT_Error error;
|
||||
|
||||
error = ft_smooth_render_generic( render, slot, mode, origin,
|
||||
FT_RENDER_MODE_LCD_V );
|
||||
if ( !error )
|
||||
slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;
|
||||
|
||||
return error;
|
||||
return ft_smooth_render_generic( render, slot, mode, origin,
|
||||
FT_RENDER_MODE_LCD_V );
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue