📄 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 + -