@ -2622,6 +2622,7 @@ void ImFont::BuildLookupTable()
for ( int i = 0 ; i ! = Glyphs . Size ; i + + )
max_codepoint = ImMax ( max_codepoint , ( int ) Glyphs [ i ] . Codepoint ) ;
// Build lookup table
IM_ASSERT ( Glyphs . Size < 0xFFFF ) ; // -1 is reserved
IndexAdvanceX . clear ( ) ;
IndexLookup . clear ( ) ;
@ -2638,7 +2639,7 @@ void ImFont::BuildLookupTable()
// FIXME: Needs proper TAB handling but it needs to be contextualized (or we could arbitrary say that each string starts at "column 0" ?)
if ( FindGlyph ( ( ImWchar ) ' ' ) )
{
if ( Glyphs . back ( ) . Codepoint ! = ' \t ' ) // So we can call this function multiple times
if ( Glyphs . back ( ) . Codepoint ! = ' \t ' ) // So we can call this function multiple times (FIXME: Flaky)
Glyphs . resize ( Glyphs . Size + 1 ) ;
ImFontGlyph & tab_glyph = Glyphs . back ( ) ;
tab_glyph = * FindGlyph ( ( ImWchar ) ' ' ) ;
@ -2648,6 +2649,11 @@ void ImFont::BuildLookupTable()
IndexLookup [ ( int ) tab_glyph . Codepoint ] = ( ImWchar ) ( Glyphs . Size - 1 ) ;
}
// Mark special glyphs as not visible (note that AddGlyph already mark as non-visible glyphs with zero-size polygons)
SetGlyphVisible ( ( ImWchar ) ' ' , false ) ;
SetGlyphVisible ( ( ImWchar ) ' \t ' , false ) ;
// Setup fall-backs
FallbackGlyph = FindGlyphNoFallback ( FallbackChar ) ;
FallbackAdvanceX = FallbackGlyph ? FallbackGlyph - > AdvanceX : 0.0f ;
for ( int i = 0 ; i < max_codepoint + 1 ; i + + )
@ -2655,6 +2661,12 @@ void ImFont::BuildLookupTable()
IndexAdvanceX [ i ] = FallbackAdvanceX ;
}
void ImFont : : SetGlyphVisible ( ImWchar c , bool visible )
{
if ( ImFontGlyph * glyph = ( ImFontGlyph * ) ( void * ) FindGlyph ( ( ImWchar ) c ) )
glyph - > Visible = visible ? 1 : 0 ;
}
void ImFont : : SetFallbackChar ( ImWchar c )
{
FallbackChar = c ;
@ -2676,7 +2688,8 @@ void ImFont::AddGlyph(ImWchar codepoint, float x0, float y0, float x1, float y1,
{
Glyphs . resize ( Glyphs . Size + 1 ) ;
ImFontGlyph & glyph = Glyphs . back ( ) ;
glyph . Codepoint = ( ImWchar ) codepoint ;
glyph . Codepoint = ( unsigned int ) codepoint ;
glyph . Visible = ( x0 ! = x1 ) & & ( y0 ! = y1 ) ;
glyph . X0 = x0 ;
glyph . Y0 = y0 ;
glyph . X1 = x1 ;
@ -2925,16 +2938,14 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons
void ImFont : : RenderChar ( ImDrawList * draw_list , float size , ImVec2 pos , ImU32 col , ImWchar c ) const
{
if ( c = = ' ' | | c = = ' \t ' | | c = = ' \n ' | | c = = ' \r ' ) // Match behavior of RenderText(), those 4 codepoints are hard-coded.
const ImFontGlyph * glyph = FindGlyph ( c ) ;
if ( ! glyph | | ! glyph - > Visible )
return ;
if ( const ImFontGlyph * glyph = FindGlyph ( c ) )
{
float scale = ( size > = 0.0f ) ? ( size / FontSize ) : 1.0f ;
pos . x = IM_FLOOR ( pos . x + DisplayOffset . x ) ;
pos . y = IM_FLOOR ( pos . y + DisplayOffset . y ) ;
draw_list - > PrimReserve ( 6 , 4 ) ;
draw_list - > PrimRectUV ( ImVec2 ( pos . x + glyph - > X0 * scale , pos . y + glyph - > Y0 * scale ) , ImVec2 ( pos . x + glyph - > X1 * scale , pos . y + glyph - > Y1 * scale ) , ImVec2 ( glyph - > U0 , glyph - > V0 ) , ImVec2 ( glyph - > U1 , glyph - > V1 ) , col ) ;
}
float scale = ( size > = 0.0f ) ? ( size / FontSize ) : 1.0f ;
pos . x = IM_FLOOR ( pos . x + DisplayOffset . x ) ;
pos . y = IM_FLOOR ( pos . y + DisplayOffset . y ) ;
draw_list - > PrimReserve ( 6 , 4 ) ;
draw_list - > PrimRectUV ( ImVec2 ( pos . x + glyph - > X0 * scale , pos . y + glyph - > Y0 * scale ) , ImVec2 ( pos . x + glyph - > X1 * scale , pos . y + glyph - > Y1 * scale ) , ImVec2 ( glyph - > U0 , glyph - > V0 ) , ImVec2 ( glyph - > U1 , glyph - > V1 ) , col ) ;
}
void ImFont : : RenderText ( ImDrawList * draw_list , float size , ImVec2 pos , ImU32 col , const ImVec4 & clip_rect , const char * text_begin , const char * text_end , float wrap_width , bool cpu_fine_clip ) const
@ -3047,73 +3058,70 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
continue ;
}
float char_width = 0.0f ;
if ( const ImFontGlyph * glyph = FindGlyph ( ( ImWchar ) c ) )
{
char_width = glyph - > AdvanceX * scale ;
const ImFontGlyph * glyph = FindGlyph ( ( ImWchar ) c ) ;
if ( glyph = = NULL )
continue ;
// Arbitrarily assume that both space and tabs are empty glyphs as an optimization
if ( c ! = ' ' & & c ! = ' \t ' )
float char_width = glyph - > AdvanceX * scale ;
if ( glyph - > Visible )
{
// We don't do a second finer clipping test on the Y axis as we've already skipped anything before clip_rect.y and exit once we pass clip_rect.w
float x1 = x + glyph - > X0 * scale ;
float x2 = x + glyph - > X1 * scale ;
float y1 = y + glyph - > Y0 * scale ;
float y2 = y + glyph - > Y1 * scale ;
if ( x1 < = clip_rect . z & & x2 > = clip_rect . x )
{
// We don't do a second finer clipping test on the Y axis as we've already skipped anything before clip_rect.y and exit once we pass clip_rect.w
float x1 = x + glyph - > X0 * scale ;
float x2 = x + glyph - > X1 * scale ;
float y1 = y + glyph - > Y0 * scale ;
float y2 = y + glyph - > Y1 * scale ;
if ( x1 < = clip_rect . z & & x2 > = clip_rect . x )
// Render a character
float u1 = glyph - > U0 ;
float v1 = glyph - > V0 ;
float u2 = glyph - > U1 ;
float v2 = glyph - > V1 ;
// CPU side clipping used to fit text in their frame when the frame is too small. Only does clipping for axis aligned quads.
if ( cpu_fine_clip )
{
// Render a character
float u1 = glyph - > U0 ;
float v1 = glyph - > V0 ;
float u2 = glyph - > U1 ;
float v2 = glyph - > V1 ;
// CPU side clipping used to fit text in their frame when the frame is too small. Only does clipping for axis aligned quads.
if ( cpu_fine_clip )
if ( x1 < clip_rect . x )
{
if ( x1 < clip_rect . x )
{
u1 = u1 + ( 1.0f - ( x2 - clip_rect . x ) / ( x2 - x1 ) ) * ( u2 - u1 ) ;
x1 = clip_rect . x ;
}
if ( y1 < clip_rect . y )
{
v1 = v1 + ( 1.0f - ( y2 - clip_rect . y ) / ( y2 - y1 ) ) * ( v2 - v1 ) ;
y1 = clip_rect . y ;
}
if ( x2 > clip_rect . z )
{
u2 = u1 + ( ( clip_rect . z - x1 ) / ( x2 - x1 ) ) * ( u2 - u1 ) ;
x2 = clip_rect . z ;
}
if ( y2 > clip_rect . w )
{
v2 = v1 + ( ( clip_rect . w - y1 ) / ( y2 - y1 ) ) * ( v2 - v1 ) ;
y2 = clip_rect . w ;
}
if ( y1 > = y2 )
{
x + = char_width ;
continue ;
}
u1 = u1 + ( 1.0f - ( x2 - clip_rect . x ) / ( x2 - x1 ) ) * ( u2 - u1 ) ;
x1 = clip_rect . x ;
}
// We are NOT calling PrimRectUV() here because non-inlined causes too much overhead in a debug builds. Inlined here:
if ( y1 < clip_rect . y )
{
v1 = v1 + ( 1.0f - ( y2 - clip_rect . y ) / ( y2 - y1 ) ) * ( v2 - v1 ) ;
y1 = clip_rect . y ;
}
if ( x2 > clip_rect . z )
{
idx_write [ 0 ] = ( ImDrawIdx ) ( vtx_current_idx ) ; idx_write [ 1 ] = ( ImDrawIdx ) ( vtx_current_idx + 1 ) ; idx_write [ 2 ] = ( ImDrawIdx ) ( vtx_current_idx + 2 ) ;
idx_write [ 3 ] = ( ImDrawIdx ) ( vtx_current_idx ) ; idx_write [ 4 ] = ( ImDrawIdx ) ( vtx_current_idx + 2 ) ; idx_write [ 5 ] = ( ImDrawIdx ) ( vtx_current_idx + 3 ) ;
vtx_write [ 0 ] . pos . x = x1 ; vtx_write [ 0 ] . pos . y = y1 ; vtx_write [ 0 ] . col = col ; vtx_write [ 0 ] . uv . x = u1 ; vtx_write [ 0 ] . uv . y = v1 ;
vtx_write [ 1 ] . pos . x = x2 ; vtx_write [ 1 ] . pos . y = y1 ; vtx_write [ 1 ] . col = col ; vtx_write [ 1 ] . uv . x = u2 ; vtx_write [ 1 ] . uv . y = v1 ;
vtx_write [ 2 ] . pos . x = x2 ; vtx_write [ 2 ] . pos . y = y2 ; vtx_write [ 2 ] . col = col ; vtx_write [ 2 ] . uv . x = u2 ; vtx_write [ 2 ] . uv . y = v2 ;
vtx_write [ 3 ] . pos . x = x1 ; vtx_write [ 3 ] . pos . y = y2 ; vtx_write [ 3 ] . col = col ; vtx_write [ 3 ] . uv . x = u1 ; vtx_write [ 3 ] . uv . y = v2 ;
vtx_write + = 4 ;
vtx_current_idx + = 4 ;
idx_write + = 6 ;
u2 = u1 + ( ( clip_rect . z - x1 ) / ( x2 - x1 ) ) * ( u2 - u1 ) ;
x2 = clip_rect . z ;
}
if ( y2 > clip_rect . w )
{
v2 = v1 + ( ( clip_rect . w - y1 ) / ( y2 - y1 ) ) * ( v2 - v1 ) ;
y2 = clip_rect . w ;
}
if ( y1 > = y2 )
{
x + = char_width ;
continue ;
}
}
// We are NOT calling PrimRectUV() here because non-inlined causes too much overhead in a debug builds. Inlined here:
{
idx_write [ 0 ] = ( ImDrawIdx ) ( vtx_current_idx ) ; idx_write [ 1 ] = ( ImDrawIdx ) ( vtx_current_idx + 1 ) ; idx_write [ 2 ] = ( ImDrawIdx ) ( vtx_current_idx + 2 ) ;
idx_write [ 3 ] = ( ImDrawIdx ) ( vtx_current_idx ) ; idx_write [ 4 ] = ( ImDrawIdx ) ( vtx_current_idx + 2 ) ; idx_write [ 5 ] = ( ImDrawIdx ) ( vtx_current_idx + 3 ) ;
vtx_write [ 0 ] . pos . x = x1 ; vtx_write [ 0 ] . pos . y = y1 ; vtx_write [ 0 ] . col = col ; vtx_write [ 0 ] . uv . x = u1 ; vtx_write [ 0 ] . uv . y = v1 ;
vtx_write [ 1 ] . pos . x = x2 ; vtx_write [ 1 ] . pos . y = y1 ; vtx_write [ 1 ] . col = col ; vtx_write [ 1 ] . uv . x = u2 ; vtx_write [ 1 ] . uv . y = v1 ;
vtx_write [ 2 ] . pos . x = x2 ; vtx_write [ 2 ] . pos . y = y2 ; vtx_write [ 2 ] . col = col ; vtx_write [ 2 ] . uv . x = u2 ; vtx_write [ 2 ] . uv . y = v2 ;
vtx_write [ 3 ] . pos . x = x1 ; vtx_write [ 3 ] . pos . y = y2 ; vtx_write [ 3 ] . col = col ; vtx_write [ 3 ] . uv . x = u1 ; vtx_write [ 3 ] . uv . y = v2 ;
vtx_write + = 4 ;
vtx_current_idx + = 4 ;
idx_write + = 6 ;
}
}
}
x + = char_width ;
}