@ -6,6 +6,7 @@
// CHANGELOG
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// (minor and older changes stripped away, please see git history for details)
// 2021/01/28: added support for color-layered glyphs via ImGuiFreeTypeBuilderFlags_LoadColor (require Freetype 2.10+).
// 2021/01/26: simplified integration by using '#define IMGUI_ENABLE_FREETYPE'.
// 2021/01/26: simplified integration by using '#define IMGUI_ENABLE_FREETYPE'.
// renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API. removed ImGuiFreeType::BuildFontAtlas().
// renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API. removed ImGuiFreeType::BuildFontAtlas().
// 2020/06/04: fix for rare case where FT_Get_Char_Index() succeed but FT_Load_Glyph() fails.
// 2020/06/04: fix for rare case where FT_Get_Char_Index() succeed but FT_Load_Glyph() fails.
@ -96,7 +97,7 @@ namespace
// | |
// | |
// |------------- advanceX ----------->|
// |------------- advanceX ----------->|
// / A structure that describe a glyph.
// A structure that describe a glyph.
struct GlyphInfo
struct GlyphInfo
{
{
int Width ; // Glyph's width in pixels.
int Width ; // Glyph's width in pixels.
@ -104,6 +105,7 @@ namespace
FT_Int OffsetX ; // The distance from the origin ("pen position") to the left of the glyph.
FT_Int OffsetX ; // The distance from the origin ("pen position") to the left of the glyph.
FT_Int OffsetY ; // The distance from the origin to the top of the glyph. This is usually a value < 0.
FT_Int OffsetY ; // The distance from the origin to the top of the glyph. This is usually a value < 0.
float AdvanceX ; // The distance from the origin to the origin of the next glyph. This is usually a value > 0.
float AdvanceX ; // The distance from the origin to the origin of the next glyph. This is usually a value > 0.
bool IsColored ;
} ;
} ;
// Font parameters and metrics.
// Font parameters and metrics.
@ -252,6 +254,7 @@ namespace
out_glyph_info - > OffsetX = Face - > glyph - > bitmap_left ;
out_glyph_info - > OffsetX = Face - > glyph - > bitmap_left ;
out_glyph_info - > OffsetY = - Face - > glyph - > bitmap_top ;
out_glyph_info - > OffsetY = - Face - > glyph - > bitmap_top ;
out_glyph_info - > AdvanceX = ( float ) FT_CEIL ( slot - > advance . x ) ;
out_glyph_info - > AdvanceX = ( float ) FT_CEIL ( slot - > advance . x ) ;
out_glyph_info - > IsColored = ( ft_bitmap - > pixel_mode = = FT_PIXEL_MODE_BGRA ) ;
return ft_bitmap ;
return ft_bitmap ;
}
}
@ -271,19 +274,15 @@ namespace
if ( multiply_table = = NULL )
if ( multiply_table = = NULL )
{
{
for ( uint32_t y = 0 ; y < h ; y + + , src + = src_pitch , dst + = dst_pitch )
for ( uint32_t y = 0 ; y < h ; y + + , src + = src_pitch , dst + = dst_pitch )
{
for ( uint32_t x = 0 ; x < w ; x + + )
for ( uint32_t x = 0 ; x < w ; x + + )
dst [ x ] = IM_COL32 ( 255 , 255 , 255 , src [ x ] ) ;
dst [ x ] = IM_COL32 ( 255 , 255 , 255 , src [ x ] ) ;
}
}
}
else
else
{
{
for ( uint32_t y = 0 ; y < h ; y + + , src + = src_pitch , dst + = dst_pitch )
for ( uint32_t y = 0 ; y < h ; y + + , src + = src_pitch , dst + = dst_pitch )
{
for ( uint32_t x = 0 ; x < w ; x + + )
for ( uint32_t x = 0 ; x < w ; x + + )
dst [ x ] = IM_COL32 ( 255 , 255 , 255 , multiply_table [ src [ x ] ] ) ;
dst [ x ] = IM_COL32 ( 255 , 255 , 255 , multiply_table [ src [ x ] ] ) ;
}
}
}
break ;
break ;
}
}
case FT_PIXEL_MODE_MONO : // Monochrome image, 1 bit per pixel. The bits in each byte are ordered from MSB to LSB.
case FT_PIXEL_MODE_MONO : // Monochrome image, 1 bit per pixel. The bits in each byte are ordered from MSB to LSB.
@ -305,18 +304,15 @@ namespace
}
}
case FT_PIXEL_MODE_BGRA :
case FT_PIXEL_MODE_BGRA :
{
{
// FIXME: Converting pre-multiplied alpha to straight. Doesn't smell good.
# define DE_MULTIPLY(color, alpha) (ImU32)(255.0f * (float)color / (float)alpha + 0.5f)
# define DE_MULTIPLY(color, alpha) (ImU32)(255.0f * (float)color / (float)alpha + 0.5f)
if ( multiply_table = = NULL )
if ( multiply_table = = NULL )
{
{
for ( uint32_t y = 0 ; y < h ; y + + , src + = src_pitch , dst + = dst_pitch )
for ( uint32_t y = 0 ; y < h ; y + + , src + = src_pitch , dst + = dst_pitch )
{
for ( uint32_t x = 0 ; x < w ; x + + )
for ( uint32_t x = 0 ; x < w ; x + + )
dst [ x ] = IM_COL32 (
{
DE_MULTIPLY ( src [ x * 4 + 2 ] , src [ x * 4 + 3 ] ) ,
uint8_t r = src [ x * 4 + 2 ] , g = src [ x * 4 + 1 ] , b = src [ x * 4 ] , a = src [ x * 4 + 3 ] ;
DE_MULTIPLY ( src [ x * 4 + 1 ] , src [ x * 4 + 3 ] ) ,
dst [ x ] = IM_COL32 ( DE_MULTIPLY ( r , a ) , DE_MULTIPLY ( g , a ) , DE_MULTIPLY ( b , a ) , a ) ;
DE_MULTIPLY ( src [ x * 4 ] , src [ x * 4 + 3 ] ) ,
src [ x * 4 + 3 ] ) ;
}
}
}
}
else
else
@ -324,14 +320,12 @@ namespace
for ( uint32_t y = 0 ; y < h ; y + + , src + = src_pitch , dst + = dst_pitch )
for ( uint32_t y = 0 ; y < h ; y + + , src + = src_pitch , dst + = dst_pitch )
{
{
for ( uint32_t x = 0 ; x < w ; x + + )
for ( uint32_t x = 0 ; x < w ; x + + )
dst [ x ] = IM_COL32 (
{
multiply_table [ DE_MULTIPLY ( src [ x * 4 + 2 ] , src [ x * 4 + 3 ] ) ] ,
uint8_t r = src [ x * 4 + 2 ] , g = src [ x * 4 + 1 ] , b = src [ x * 4 ] , a = src [ x * 4 + 3 ] ;
multiply_table [ DE_MULTIPLY ( src [ x * 4 + 1 ] , src [ x * 4 + 3 ] ) ] ,
dst [ x ] = IM_COL32 ( multiply_table [ DE_MULTIPLY ( r , a ) ] , multiply_table [ DE_MULTIPLY ( g , a ) ] , multiply_table [ DE_MULTIPLY ( b , a ) ] , multiply_table [ a ] ) ;
multiply_table [ DE_MULTIPLY ( src [ x * 4 ] , src [ x * 4 + 3 ] ) ] ,
}
multiply_table [ src [ x * 4 + 3 ] ] ) ;
}
}
}
}
# undef DE_MULTIPLY
# undef DE_MULTIPLY
break ;
break ;
}
}
@ -359,6 +353,8 @@ struct ImFontBuildSrcGlyphFT
GlyphInfo Info ;
GlyphInfo Info ;
uint32_t Codepoint ;
uint32_t Codepoint ;
unsigned int * BitmapData ; // Point within one of the dst_tmp_bitmap_buffers[] array
unsigned int * BitmapData ; // Point within one of the dst_tmp_bitmap_buffers[] array
ImFontBuildSrcGlyphFT ( ) { memset ( this , 0 , sizeof ( * this ) ) ; }
} ;
} ;
struct ImFontBuildSrcDataFT
struct ImFontBuildSrcDataFT
@ -396,6 +392,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
atlas - > ClearTexData ( ) ;
atlas - > ClearTexData ( ) ;
// Temporary storage for building
// Temporary storage for building
bool src_load_color = false ;
ImVector < ImFontBuildSrcDataFT > src_tmp_array ;
ImVector < ImFontBuildSrcDataFT > src_tmp_array ;
ImVector < ImFontBuildDstDataFT > dst_tmp_array ;
ImVector < ImFontBuildDstDataFT > dst_tmp_array ;
src_tmp_array . resize ( atlas - > ConfigData . Size ) ;
src_tmp_array . resize ( atlas - > ConfigData . Size ) ;
@ -425,6 +422,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
return false ;
return false ;
// Measure highest codepoints
// Measure highest codepoints
src_load_color | = ( cfg . FontBuilderFlags & ImGuiFreeTypeBuilderFlags_LoadColor ) ! = 0 ;
ImFontBuildDstDataFT & dst_tmp = dst_tmp_array [ src_tmp . DstIndex ] ;
ImFontBuildDstDataFT & dst_tmp = dst_tmp_array [ src_tmp . DstIndex ] ;
src_tmp . SrcRanges = cfg . GlyphRanges ? cfg . GlyphRanges : atlas - > GetGlyphRangesDefault ( ) ;
src_tmp . SrcRanges = cfg . GlyphRanges ? cfg . GlyphRanges : atlas - > GetGlyphRangesDefault ( ) ;
for ( const ImWchar * src_range = src_tmp . SrcRanges ; src_range [ 0 ] & & src_range [ 1 ] ; src_range + = 2 )
for ( const ImWchar * src_range = src_tmp . SrcRanges ; src_range [ 0 ] & & src_range [ 1 ] ; src_range + = 2 )
@ -476,7 +474,6 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
if ( entries_32 & ( ( ImU32 ) 1 < < bit_n ) )
if ( entries_32 & ( ( ImU32 ) 1 < < bit_n ) )
{
{
ImFontBuildSrcGlyphFT src_glyph ;
ImFontBuildSrcGlyphFT src_glyph ;
memset ( & src_glyph , 0 , sizeof ( src_glyph ) ) ;
src_glyph . Codepoint = ( ImWchar ) ( ( ( it - it_begin ) < < 5 ) + bit_n ) ;
src_glyph . Codepoint = ( ImWchar ) ( ( ( it - it_begin ) < < 5 ) + bit_n ) ;
//src_glyph.GlyphIndex = 0; // FIXME-OPT: We had this info in the previous step and lost it..
//src_glyph.GlyphIndex = 0; // FIXME-OPT: We had this info in the previous step and lost it..
src_tmp . GlyphsList . push_back ( src_glyph ) ;
src_tmp . GlyphsList . push_back ( src_glyph ) ;
@ -595,7 +592,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
// 7. Allocate texture
// 7. Allocate texture
atlas - > TexHeight = ( atlas - > Flags & ImFontAtlasFlags_NoPowerOfTwoHeight ) ? ( atlas - > TexHeight + 1 ) : ImUpperPowerOfTwo ( atlas - > TexHeight ) ;
atlas - > TexHeight = ( atlas - > Flags & ImFontAtlasFlags_NoPowerOfTwoHeight ) ? ( atlas - > TexHeight + 1 ) : ImUpperPowerOfTwo ( atlas - > TexHeight ) ;
atlas - > TexUvScale = ImVec2 ( 1.0f / atlas - > TexWidth , 1.0f / atlas - > TexHeight ) ;
atlas - > TexUvScale = ImVec2 ( 1.0f / atlas - > TexWidth , 1.0f / atlas - > TexHeight ) ;
if ( extra_flags & ImGuiFreeTypeBuilderFlags_LoadC olor)
if ( src_load_c olor)
{
{
atlas - > TexPixelsRGBA32 = ( unsigned int * ) IM_ALLOC ( atlas - > TexWidth * atlas - > TexHeight * 4 ) ;
atlas - > TexPixelsRGBA32 = ( unsigned int * ) IM_ALLOC ( atlas - > TexWidth * atlas - > TexHeight * 4 ) ;
memset ( atlas - > TexPixelsRGBA32 , 0 , atlas - > TexWidth * atlas - > TexHeight * 4 ) ;
memset ( atlas - > TexPixelsRGBA32 , 0 , atlas - > TexWidth * atlas - > TexHeight * 4 ) ;
@ -670,6 +667,10 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
float u1 = ( tx + info . Width ) / ( float ) atlas - > TexWidth ;
float u1 = ( tx + info . Width ) / ( float ) atlas - > TexWidth ;
float v1 = ( ty + info . Height ) / ( float ) atlas - > TexHeight ;
float v1 = ( ty + info . Height ) / ( float ) atlas - > TexHeight ;
dst_font - > AddGlyph ( & cfg , ( ImWchar ) src_glyph . Codepoint , x0 , y0 , x1 , y1 , u0 , v0 , u1 , v1 , info . AdvanceX ) ;
dst_font - > AddGlyph ( & cfg , ( ImWchar ) src_glyph . Codepoint , x0 , y0 , x1 , y1 , u0 , v0 , u1 , v1 , info . AdvanceX ) ;
IM_ASSERT ( dst_font - > Glyphs . back ( ) . Codepoint = = src_glyph . Codepoint ) ;
if ( src_glyph . Info . IsColored )
dst_font - > Glyphs . back ( ) . Colored = true ;
}
}
src_tmp . Rects = NULL ;
src_tmp . Rects = NULL ;