📄 ftcommon.i
字号:
{
max_fonts *= 2;
fonts = (PFont*)realloc( fonts, max_fonts * sizeof ( PFont ) );
memset( &fonts[num_fonts], 0,
( max_fonts - num_fonts ) * sizeof ( PFont ) );
}
fonts[num_fonts++] = font;
}
return 0;
}
/*************************************************************************/
/* */
/* The face requester is a function provided by the client application */
/* to the cache manager, whose role is to translate an `abstract' face */
/* ID into a real FT_Face object. */
/* */
/* In this program, the face IDs are simply pointers to TFont objects. */
/* */
FT_CALLBACK_DEF( FT_Error )
my_face_requester( FTC_FaceID face_id,
FT_Library lib,
FT_Pointer request_data,
FT_Face* aface )
{
PFont font = (PFont)face_id;
FT_UNUSED( request_data );
error = FT_New_Face( lib,
font->filepathname,
font->face_index,
aface );
if ( encoding == FT_ENCODING_NONE || error )
goto Fail;
error = FT_Select_Charmap( *aface, encoding );
Fail:
return error;
}
static void
init_freetype( void )
{
error = FT_Init_FreeType( &library );
if ( error )
PanicZ( "could not initialize FreeType" );
error = FTC_Manager_New( library, 0, 0, 0,
my_face_requester, 0, &cache_manager );
if ( error )
PanicZ( "could not initialize cache manager" );
error = FTC_SBitCache_New( cache_manager, &sbits_cache );
if ( error )
PanicZ( "could not initialize small bitmaps cache" );
error = FTC_ImageCache_New( cache_manager, &image_cache );
if ( error )
PanicZ( "could not initialize glyph image cache" );
error = FTC_CMapCache_New( cache_manager, &cmap_cache );
if ( error )
PanicZ( "could not initialize charmap cache" );
FT_Bitmap_New( &ft_bitmap );
}
static void
done_freetype( void )
{
int i;
for ( i = 0; i < max_fonts; i++ )
{
if ( fonts[i] )
{
if ( fonts[i]->filepathname )
free( (void*)fonts[i]->filepathname );
free( fonts[i] );
}
}
free( fonts );
FTC_Manager_Done( cache_manager );
FT_Bitmap_Done( library, &ft_bitmap );
FT_Done_FreeType( library );
}
static void
set_current_face( PFont font )
{
current_font.face_id = (FTC_FaceID)font;
}
static void
set_current_size( int pixel_size )
{
if ( pixel_size > 0xFFFF )
pixel_size = 0xFFFF;
current_font.width = (FT_UShort)pixel_size;
current_font.height = (FT_UShort)pixel_size;
}
static void
set_current_pointsize( int point_size )
{
set_current_size( ( point_size * res + 36 ) / 72 );
}
static void
set_current_image_type( void )
{
current_font.flags = antialias ? FT_LOAD_DEFAULT : FT_LOAD_TARGET_MONO;
current_font.flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
if ( !hinted )
current_font.flags |= FT_LOAD_NO_HINTING;
if ( autohint )
current_font.flags |= FT_LOAD_FORCE_AUTOHINT;
if ( !use_sbits )
current_font.flags |= FT_LOAD_NO_BITMAP;
if ( antialias && lcd_mode > 0 )
{
if ( lcd_mode <= 1 )
current_font.flags |= FT_LOAD_TARGET_LIGHT;
else if ( lcd_mode <= 3 )
current_font.flags |= FT_LOAD_TARGET_LCD;
else
current_font.flags |= FT_LOAD_TARGET_LCD_V;
}
}
static void
done_glyph_bitmap( FT_Pointer _glyf )
{
if ( _glyf )
{
FT_Glyph glyf = (FT_Glyph)_glyf;
FT_Done_Glyph( glyf );
}
}
static FT_UInt
get_glyph_index( FT_UInt32 charcode )
{
FTC_FaceID face_id = current_font.face_id;
PFont font = (PFont)face_id;
return FTC_CMapCache_Lookup( cmap_cache, face_id,
font->cmap_index, charcode );
}
static FT_Error
glyph_to_bitmap( FT_Glyph glyf,
grBitmap* target,
int *left,
int *top,
int *x_advance,
int *y_advance,
FT_Pointer *aref )
{
FT_BitmapGlyph bitmap;
FT_Bitmap* source;
*aref = NULL;
error = FT_Err_Ok;
if ( glyf->format == FT_GLYPH_FORMAT_OUTLINE )
{
/* render the glyph to a bitmap, don't destroy original */
error = FT_Glyph_To_Bitmap( &glyf,
antialias ? FT_RENDER_MODE_NORMAL
: FT_RENDER_MODE_MONO,
NULL, 0 );
if ( error )
goto Exit;
*aref = glyf;
}
if ( glyf->format != FT_GLYPH_FORMAT_BITMAP )
PanicZ( "invalid glyph format returned!" );
bitmap = (FT_BitmapGlyph)glyf;
source = &bitmap->bitmap;
target->rows = source->rows;
target->width = source->width;
target->pitch = source->pitch;
target->buffer = source->buffer;
switch ( source->pixel_mode )
{
case FT_PIXEL_MODE_MONO:
target->mode = gr_pixel_mode_mono;
target->grays = 2;
break;
case FT_PIXEL_MODE_GRAY:
target->mode = gr_pixel_mode_gray;
target->grays = source->num_grays;
break;
case FT_PIXEL_MODE_GRAY2:
case FT_PIXEL_MODE_GRAY4:
(void)FT_Bitmap_Convert( library, source, &ft_bitmap, 1 );
target->pitch = ft_bitmap.pitch;
target->buffer = ft_bitmap.buffer;
target->mode = gr_pixel_mode_gray;
target->grays = ft_bitmap.num_grays;
break;
case FT_PIXEL_MODE_LCD:
target->mode = lcd_mode == 2 ? gr_pixel_mode_lcd
: gr_pixel_mode_lcd2;
target->grays = source->num_grays;
break;
case FT_PIXEL_MODE_LCD_V:
target->mode = lcd_mode == 4 ? gr_pixel_mode_lcdv
: gr_pixel_mode_lcdv2;
target->grays = source->num_grays;
break;
default:
return FT_Err_Invalid_Glyph_Format;
}
*left = bitmap->left;
*top = bitmap->top;
*x_advance = ( glyf->advance.x + 0x8000 ) >> 16;
*y_advance = ( glyf->advance.y + 0x8000 ) >> 16;
Exit:
return error;
}
static FT_Error
get_glyph_bitmap( FT_ULong Index,
grBitmap* target,
int *left,
int *top,
int *x_advance,
int *y_advance,
FT_Pointer *aglyf )
{
*aglyf = NULL;
if ( encoding != FT_ENCODING_NONE )
Index = get_glyph_index( Index );
/* use the SBits cache to store small glyph bitmaps; this is a lot */
/* more memory-efficient */
/* */
if ( use_sbits_cache &&
current_font.width < 48 &&
current_font.height < 48 )
{
FTC_SBit sbit;
FT_Bitmap source;
error = FTC_SBitCache_Lookup( sbits_cache,
¤t_font,
Index,
&sbit,
NULL );
if ( error )
goto Exit;
if ( sbit->buffer )
{
target->rows = sbit->height;
target->width = sbit->width;
target->pitch = sbit->pitch;
target->buffer = sbit->buffer;
switch ( sbit->format )
{
case FT_PIXEL_MODE_MONO:
target->mode = gr_pixel_mode_mono;
target->grays = 2;
break;
case FT_PIXEL_MODE_GRAY:
target->mode = gr_pixel_mode_gray;
target->grays = sbit->max_grays + 1;
break;
case FT_PIXEL_MODE_GRAY2:
case FT_PIXEL_MODE_GRAY4:
source.rows = sbit->height;
source.width = sbit->width;
source.pitch = sbit->pitch;
source.buffer = sbit->buffer;
source.pixel_mode = sbit->format;
(void)FT_Bitmap_Convert( library, &source, &ft_bitmap, 1 );
target->pitch = ft_bitmap.pitch;
target->buffer = ft_bitmap.buffer;
target->mode = gr_pixel_mode_gray;
target->grays = ft_bitmap.num_grays;
break;
case FT_PIXEL_MODE_LCD:
target->mode = lcd_mode == 2 ? gr_pixel_mode_lcd
: gr_pixel_mode_lcd2;
target->grays = sbit->max_grays + 1;
break;
case FT_PIXEL_MODE_LCD_V:
target->mode = lcd_mode == 4 ? gr_pixel_mode_lcdv
: gr_pixel_mode_lcdv2;
target->grays = sbit->max_grays + 1;
break;
default:
return FT_Err_Invalid_Glyph_Format;
}
*left = sbit->left;
*top = sbit->top;
*x_advance = sbit->xadvance;
*y_advance = sbit->yadvance;
goto Exit;
}
}
/* otherwise, use an image cache to store glyph outlines, and render */
/* them on demand. we can thus support very large sizes easily.. */
{
FT_Glyph glyf;
error = FTC_ImageCache_Lookup( image_cache,
¤t_font,
Index,
&glyf,
NULL );
if ( !error )
error = glyph_to_bitmap( glyf, target, left, top, x_advance, y_advance, aglyf );
}
Exit:
/* don't accept a `missing' character with zero or negative width */
if ( Index == 0 && *x_advance <= 0 )
*x_advance = 1;
return error;
}
/* End */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -