@ -1,4 +1,4 @@
// dear imgui, v1. 7 8 WIP
// dear imgui, v1. 80 WIP
// (drawing and font code)
/*
@ -60,6 +60,9 @@ Index of this file:
# if __has_warning("-Wunknown-warning-option")
# pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx' // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great!
# endif
# if __has_warning("-Walloca")
# pragma clang diagnostic ignored "-Walloca" // warning: use of function '__builtin_alloca' is discouraged
# endif
# pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx'
# pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
# pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants ok.
@ -354,26 +357,17 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
}
//-----------------------------------------------------------------------------
// ImDrawList
// [SECTION] ImDrawList
//-----------------------------------------------------------------------------
ImDrawListSharedData : : ImDrawListSharedData ( )
{
Font = NULL ;
FontSize = 0.0f ;
CurveTessellationTol = 0.0f ;
CircleSegmentMaxError = 0.0f ;
ClipRectFullscreen = ImVec4 ( - 8192.0f , - 8192.0f , + 8192.0f , + 8192.0f ) ;
InitialFlags = ImDrawListFlags_None ;
// Lookup tables
memset ( this , 0 , sizeof ( * this ) ) ;
for ( int i = 0 ; i < IM_ARRAYSIZE ( ArcFastVtx ) ; i + + )
{
const float a = ( ( float ) i * 2 * IM_PI ) / ( float ) IM_ARRAYSIZE ( ArcFastVtx ) ;
ArcFastVtx [ i ] = ImVec2 ( ImCos ( a ) , ImSin ( a ) ) ;
}
memset ( CircleSegmentCounts , 0 , sizeof ( CircleSegmentCounts ) ) ; // This will be set by SetCircleSegmentMaxError()
TexUvLines = NULL ;
}
void ImDrawListSharedData : : SetCircleSegmentMaxError ( float max_error )
@ -532,7 +526,7 @@ void ImDrawList::_OnChangedVtxOffset()
// We don't need to compare curr_cmd->VtxOffset != _CmdHeader.VtxOffset because we know it'll be different at the time we call this.
_VtxCurrentIdx = 0 ;
ImDrawCmd * curr_cmd = & CmdBuffer . Data [ CmdBuffer . Size - 1 ] ;
IM_ASSERT ( curr_cmd - > VtxOffset ! = _CmdHeader . VtxOffset ) ;
//IM_ASSERT(curr_cmd->VtxOffset != _CmdHeader.VtxOffset); // See #3349
if ( curr_cmd - > ElemCount ! = 0 )
{
AddDrawCmd ( ) ;
@ -597,6 +591,9 @@ void ImDrawList::PrimReserve(int idx_count, int vtx_count)
IM_ASSERT_PARANOID ( idx_count > = 0 & & vtx_count > = 0 ) ;
if ( sizeof ( ImDrawIdx ) = = 2 & & ( _VtxCurrentIdx + vtx_count > = ( 1 < < 16 ) ) & & ( Flags & ImDrawListFlags_AllowVtxOffset ) )
{
// FIXME: In theory we should be testing that vtx_count <64k here.
// In practice, RenderText() relies on reserving ahead for a worst case scenario so it is currently useful for us
// to not make that check until we rework the text functions to handle clipping and large horizontal lines better.
_CmdHeader . VtxOffset = VtxBuffer . Size ;
_OnChangedVtxOffset ( ) ;
}
@ -732,8 +729,11 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
// [PATH 1] Texture-based lines (thick or non-thick)
// [PATH 2] Non texture-based lines (non-thick)
// The width of the geometry we need to draw - this is essentially <thickness> pixels for the line itself, plus one pixel for AA
// We don't use AA_SIZE here because the +1 is tied to the generated texture and so alternate values won't work without changes to that code
// The width of the geometry we need to draw - this is essentially <thickness> pixels for the line itself, plus "one pixel" for AA.
// - In the texture-based path, we don't use AA_SIZE here because the +1 is tied to the generated texture
// (see ImFontAtlasBuildRenderLinesTexData() function), and so alternate values won't work without changes to that code.
// - In the non texture-based paths, we would allow AA_SIZE to potentially be != 1.0f with a patch (e.g. fringe_scale patch to
// allow scaling geometry while preserving one-screen-pixel AA fringe).
const float half_draw_size = use_texture ? ( ( thickness * 0.5f ) + 1 ) : AA_SIZE ;
// If line is not closed, the first and last points need to be generated differently as there are no normals to blend
@ -1250,7 +1250,7 @@ void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int nu
// Because we are filling a closed shape we remove 1 from the count of segments/points
const float a_max = ( IM_PI * 2.0f ) * ( ( float ) num_segments - 1.0f ) / ( float ) num_segments ;
if ( num_segments = = 12 )
PathArcToFast ( center , radius - 0.5f , 0 , 12 ) ;
PathArcToFast ( center , radius - 0.5f , 0 , 12 - 1 ) ;
else
PathArcTo ( center , radius - 0.5f , 0.0f , a_max , num_segments - 1 ) ;
PathStroke ( col , true , thickness ) ;
@ -1280,7 +1280,7 @@ void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col,
// Because we are filling a closed shape we remove 1 from the count of segments/points
const float a_max = ( IM_PI * 2.0f ) * ( ( float ) num_segments - 1.0f ) / ( float ) num_segments ;
if ( num_segments = = 12 )
PathArcToFast ( center , radius , 0 , 12 ) ;
PathArcToFast ( center , radius , 0 , 12 - 1 ) ;
else
PathArcTo ( center , radius , 0.0f , a_max , num_segments - 1 ) ;
PathFillConvex ( col ) ;
@ -1414,7 +1414,7 @@ void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& p_mi
//-----------------------------------------------------------------------------
// ImDrawListSplitter
// [SECTION] ImDrawListSplitter
//-----------------------------------------------------------------------------
// FIXME: This may be a little confusing, trying to be a little too low-level/optimal instead of just doing vector swap..
//-----------------------------------------------------------------------------
@ -1435,10 +1435,14 @@ void ImDrawListSplitter::ClearFreeMemory()
void ImDrawListSplitter : : Split ( ImDrawList * draw_list , int channels_count )
{
IM_UNUSED ( draw_list ) ;
IM_ASSERT ( _Current = = 0 & & _Count < = 1 & & " Nested channel splitting is not supported. Please use separate instances of ImDrawListSplitter. " ) ;
int old_channels_count = _Channels . Size ;
if ( old_channels_count < channels_count )
{
_Channels . reserve ( channels_count ) ; // Avoid over reserving since this is likely to stay stable
_Channels . resize ( channels_count ) ;
}
_Count = channels_count ;
// Channels[] (24/32 bytes each) hold storage that we'll swap with draw_list->_CmdBuffer/_IdxBuffer
@ -1456,12 +1460,6 @@ void ImDrawListSplitter::Split(ImDrawList* draw_list, int channels_count)
_Channels [ i ] . _CmdBuffer . resize ( 0 ) ;
_Channels [ i ] . _IdxBuffer . resize ( 0 ) ;
}
if ( _Channels [ i ] . _CmdBuffer . Size = = 0 )
{
ImDrawCmd draw_cmd ;
ImDrawCmd_HeaderCopy ( & draw_cmd , & draw_list - > _CmdHeader ) ; // Copy ClipRect, TextureId, VtxOffset
_Channels [ i ] . _CmdBuffer . push_back ( draw_cmd ) ;
}
}
}
@ -1551,8 +1549,10 @@ void ImDrawListSplitter::SetCurrentChannel(ImDrawList* draw_list, int idx)
draw_list - > _IdxWritePtr = draw_list - > IdxBuffer . Data + draw_list - > IdxBuffer . Size ;
// If current command is used with different settings we need to add a new command
ImDrawCmd * curr_cmd = & draw_list - > CmdBuffer . Data [ draw_list - > CmdBuffer . Size - 1 ] ;
if ( curr_cmd - > ElemCount = = 0 )
ImDrawCmd * curr_cmd = ( draw_list - > CmdBuffer . Size = = 0 ) ? NULL : & draw_list - > CmdBuffer . Data [ draw_list - > CmdBuffer . Size - 1 ] ;
if ( curr_cmd = = NULL )
draw_list - > AddDrawCmd ( ) ;
else if ( curr_cmd - > ElemCount = = 0 )
ImDrawCmd_HeaderCopy ( curr_cmd , & draw_list - > _CmdHeader ) ; // Copy ClipRect, TextureId, VtxOffset
else if ( ImDrawCmd_HeaderCompare ( curr_cmd , & draw_list - > _CmdHeader ) ! = 0 )
draw_list - > AddDrawCmd ( ) ;
@ -1608,13 +1608,19 @@ void ImGui::ShadeVertsLinearColorGradientKeepAlpha(ImDrawList* draw_list, int ve
float gradient_inv_length2 = 1.0f / ImLengthSqr ( gradient_extent ) ;
ImDrawVert * vert_start = draw_list - > VtxBuffer . Data + vert_start_idx ;
ImDrawVert * vert_end = draw_list - > VtxBuffer . Data + vert_end_idx ;
const int col0_r = ( int ) ( col0 > > IM_COL32_R_SHIFT ) & 0xFF ;
const int col0_g = ( int ) ( col0 > > IM_COL32_G_SHIFT ) & 0xFF ;
const int col0_b = ( int ) ( col0 > > IM_COL32_B_SHIFT ) & 0xFF ;
const int col_delta_r = ( ( int ) ( col1 > > IM_COL32_R_SHIFT ) & 0xFF ) - col0_r ;
const int col_delta_g = ( ( int ) ( col1 > > IM_COL32_G_SHIFT ) & 0xFF ) - col0_g ;
const int col_delta_b = ( ( int ) ( col1 > > IM_COL32_B_SHIFT ) & 0xFF ) - col0_b ;
for ( ImDrawVert * vert = vert_start ; vert < vert_end ; vert + + )
{
float d = ImDot ( vert - > pos - gradient_p0 , gradient_extent ) ;
float t = ImClamp ( d * gradient_inv_length2 , 0.0f , 1.0f ) ;
int r = ImLerp ( ( int ) ( col0 > > IM_COL32_R_SHIFT ) & 0xFF , ( int ) ( col1 > > IM_COL32_R_SHIFT ) & 0xFF , t ) ;
int g = ImLerp ( ( int ) ( col0 > > IM_COL32_G_SHIFT ) & 0xFF , ( int ) ( col1 > > IM_COL32_G_SHIFT ) & 0xFF , t ) ;
int b = ImLerp ( ( int ) ( col0 > > IM_COL32_B_SHIFT ) & 0xFF , ( int ) ( col1 > > IM_COL32_B_SHIFT ) & 0xFF , t ) ;
int r = ( int ) ( col0_r + col_delta_r * t ) ;
int g = ( int ) ( col0_g + col_delta_g * t ) ;
int b = ( int ) ( col0_b + col_delta_b * t ) ;
vert - > col = ( r < < IM_COL32_R_SHIFT ) | ( g < < IM_COL32_G_SHIFT ) | ( b < < IM_COL32_B_SHIFT ) | ( vert - > col & IM_COL32_A_MASK ) ;
}
}
@ -1676,10 +1682,10 @@ ImFontConfig::ImFontConfig()
//-----------------------------------------------------------------------------
// A work of art lies ahead! (. = white layer, X = black layer, others are blank)
// The white texels on the top left are the ones we'll use everywhere in Dear ImGui to render filled shapes.
const int FONT_ATLAS_DEFAULT_TEX_DATA_W _HALF = 108 ;
const int FONT_ATLAS_DEFAULT_TEX_DATA_H = 27 ;
static const char FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS [ FONT_ATLAS_DEFAULT_TEX_DATA_W _HALF * FONT_ATLAS_DEFAULT_TEX_DATA_H + 1 ] =
// The 2x2 white texels on the top left are the ones we'll use everywhere in Dear ImGui to render filled shapes.
const int FONT_ATLAS_DEFAULT_TEX_DATA_W = 108 ; // Actual texture will be 2 times that + 1 spacing.
const int FONT_ATLAS_DEFAULT_TEX_DATA_H = 27 ;
static const char FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS [ FONT_ATLAS_DEFAULT_TEX_DATA_W * FONT_ATLAS_DEFAULT_TEX_DATA_H + 1 ] =
{
" ..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX- XX "
" ..- -X.....X- X.X - X.X -X.....X - X.....X- X..X "
@ -1894,11 +1900,11 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template)
if ( font_cfg . Name [ 0 ] = = ' \0 ' )
ImFormatString ( font_cfg . Name , IM_ARRAYSIZE ( font_cfg . Name ) , " ProggyClean.ttf, %dpx " , ( int ) font_cfg . SizePixels ) ;
font_cfg . EllipsisChar = ( ImWchar ) 0x0085 ;
font_cfg . GlyphOffset . y = 1.0f * IM_FLOOR ( font_cfg . SizePixels / 13.0f ) ; // Add +1 offset per 13 units
const char * ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85 ( ) ;
const ImWchar * glyph_ranges = font_cfg . GlyphRanges ! = NULL ? font_cfg . GlyphRanges : GetGlyphRangesDefault ( ) ;
ImFont * font = AddFontFromMemoryCompressedBase85TTF ( ttf_compressed_base85 , font_cfg . SizePixels , & font_cfg , glyph_ranges ) ;
font - > DisplayOffset . y = 1.0f ;
return font ;
}
@ -2012,7 +2018,7 @@ bool ImFontAtlas::GetMouseCursorTexData(ImGuiMouseCursor cursor_type, ImVec2* ou
* out_offset = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA [ cursor_type ] [ 2 ] ;
out_uv_border [ 0 ] = ( pos ) * TexUvScale ;
out_uv_border [ 1 ] = ( pos + size ) * TexUvScale ;
pos . x + = FONT_ATLAS_DEFAULT_TEX_DATA_W _HALF + 1 ;
pos . x + = FONT_ATLAS_DEFAULT_TEX_DATA_W + 1 ;
out_uv_fill [ 0 ] = ( pos ) * TexUvScale ;
out_uv_fill [ 1 ] = ( pos + size ) * TexUvScale ;
return true ;
@ -2294,8 +2300,11 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
if ( src_tmp . GlyphsCount = = 0 )
continue ;
// When merging fonts with MergeMode=true:
// - We can have multiple input fonts writing into a same destination font.
// - dst_font->ConfigData is != from cfg which is our source configuration.
ImFontConfig & cfg = atlas - > ConfigData [ src_i ] ;
ImFont * dst_font = cfg . DstFont ; // We can have multiple input fonts writing into a same destination font (when using MergeMode=true)
ImFont * dst_font = cfg . DstFont ;
const float font_scale = stbtt_ScaleForPixelHeight ( & src_tmp . FontInfo , cfg . SizePixels ) ;
int unscaled_ascent , unscaled_descent , unscaled_line_gap ;
@ -2309,20 +2318,13 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
for ( int glyph_i = 0 ; glyph_i < src_tmp . GlyphsCount ; glyph_i + + )
{
// Register glyph
const int codepoint = src_tmp . GlyphsList [ glyph_i ] ;
const stbtt_packedchar & pc = src_tmp . PackedChars [ glyph_i ] ;
const float char_advance_x_org = pc . xadvance ;
const float char_advance_x_mod = ImClamp ( char_advance_x_org , cfg . GlyphMinAdvanceX , cfg . GlyphMaxAdvanceX ) ;
float char_off_x = font_off_x ;
if ( char_advance_x_org ! = char_advance_x_mod )
char_off_x + = cfg . PixelSnapH ? ImFloor ( ( char_advance_x_mod - char_advance_x_org ) * 0.5f ) : ( char_advance_x_mod - char_advance_x_org ) * 0.5f ;
// Register glyph
stbtt_aligned_quad q ;
float dummy _x = 0.0f , dummy _y = 0.0f ;
stbtt_GetPackedQuad ( src_tmp . PackedChars , atlas - > TexWidth , atlas - > TexHeight , glyph_i , & dummy _x, & dummy _y, & q , 0 ) ;
dst_font - > AddGlyph ( ( ImWchar ) codepoint , q . x0 + char _off_x, q . y0 + font_off_y , q . x1 + char _off_x, q . y1 + font_off_y , q . s0 , q . t0 , q . s1 , q . t1 , char_advance_x_mod ) ;
float unused_x = 0.0f , unused_y = 0.0f ;
stbtt_GetPackedQuad ( src_tmp . PackedChars , atlas - > TexWidth , atlas - > TexHeight , glyph_i , & unused_x , & unused_y , & q , 0 ) ;
dst_font - > AddGlyph ( & cfg , ( ImWchar ) codepoint , q . x0 + font_off_x , q . y0 + font_off_y , q . x1 + font_off_x , q . y1 + font_off_y , q . s0 , q . t0 , q . s1 , q . t1 , pc . xadvance ) ;
}
}
@ -2341,6 +2343,7 @@ void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* f
font - > ClearOutputData ( ) ;
font - > FontSize = font_config - > SizePixels ;
font - > ConfigData = font_config ;
font - > ConfigDataCount = 0 ;
font - > ContainerAtlas = atlas ;
font - > Ascent = ascent ;
font - > Descent = descent ;
@ -2375,6 +2378,16 @@ void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opa
}
}
void ImFontAtlasBuildRender1bppRectFromString ( ImFontAtlas * atlas , int x , int y , int w , int h , const char * in_str , char in_marker_char , unsigned char in_marker_pixel_value )
{
IM_ASSERT ( x > = 0 & & x + w < = atlas - > TexWidth ) ;
IM_ASSERT ( y > = 0 & & y + h < = atlas - > TexHeight ) ;
unsigned char * out_pixel = atlas - > TexPixelsAlpha8 + x + ( y * atlas - > TexWidth ) ;
for ( int off_y = 0 ; off_y < h ; off_y + + , out_pixel + = atlas - > TexWidth , in_str + = w )
for ( int off_x = 0 ; off_x < w ; off_x + + )
out_pixel [ off_x ] = ( in_str [ off_x ] = = in_marker_char ) ? in_marker_pixel_value : 0x00 ;
}
static void ImFontAtlasBuildRenderDefaultTexData ( ImFontAtlas * atlas )
{
ImFontAtlasCustomRect * r = atlas - > GetCustomRectByIndex ( atlas - > PackIdMouseCursors ) ;
@ -2384,15 +2397,11 @@ static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas)
if ( ! ( atlas - > Flags & ImFontAtlasFlags_NoMouseCursors ) )
{
// Render/copy pixels
IM_ASSERT ( r - > Width = = FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * 2 + 1 & & r - > Height = = FONT_ATLAS_DEFAULT_TEX_DATA_H ) ;
for ( int y = 0 , n = 0 ; y < FONT_ATLAS_DEFAULT_TEX_DATA_H ; y + + )
for ( int x = 0 ; x < FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF ; x + + , n + + )
{
const int offset0 = ( int ) ( r - > X + x ) + ( int ) ( r - > Y + y ) * w ;
const int offset1 = offset0 + FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF + 1 ;
atlas - > TexPixelsAlpha8 [ offset0 ] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS [ n ] = = ' . ' ? 0xFF : 0x00 ;
atlas - > TexPixelsAlpha8 [ offset1 ] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS [ n ] = = ' X ' ? 0xFF : 0x00 ;
}
IM_ASSERT ( r - > Width = = FONT_ATLAS_DEFAULT_TEX_DATA_W * 2 + 1 & & r - > Height = = FONT_ATLAS_DEFAULT_TEX_DATA_H ) ;
const int x_for_white = r - > X ;
const int x_for_black = r - > X + FONT_ATLAS_DEFAULT_TEX_DATA_W + 1 ;
ImFontAtlasBuildRender1bppRectFromString ( atlas , x_for_white , r - > Y , FONT_ATLAS_DEFAULT_TEX_DATA_W , FONT_ATLAS_DEFAULT_TEX_DATA_H , FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS , ' . ' , 0xFF ) ;
ImFontAtlasBuildRender1bppRectFromString ( atlas , x_for_black , r - > Y , FONT_ATLAS_DEFAULT_TEX_DATA_W , FONT_ATLAS_DEFAULT_TEX_DATA_H , FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS , ' X ' , 0xFF ) ;
}
else
{
@ -2442,7 +2451,7 @@ void ImFontAtlasBuildInit(ImFontAtlas* atlas)
if ( atlas - > PackIdMouseCursors < 0 )
{
if ( ! ( atlas - > Flags & ImFontAtlasFlags_NoMouseCursors ) )
atlas - > PackIdMouseCursors = atlas - > AddCustomRectRegular ( FONT_ATLAS_DEFAULT_TEX_DATA_W _HALF * 2 + 1 , FONT_ATLAS_DEFAULT_TEX_DATA_H ) ;
atlas - > PackIdMouseCursors = atlas - > AddCustomRectRegular ( FONT_ATLAS_DEFAULT_TEX_DATA_W * 2 + 1 , FONT_ATLAS_DEFAULT_TEX_DATA_H ) ;
else
atlas - > PackIdMouseCursors = atlas - > AddCustomRectRegular ( 2 , 2 ) ;
}
@ -2471,10 +2480,11 @@ void ImFontAtlasBuildFinish(ImFontAtlas* atlas)
if ( r - > Font = = NULL | | r - > GlyphID = = 0 )
continue ;
// Will ignore ImFontConfig settings: GlyphMinAdvanceX, GlyphMinAdvanceY, GlyphExtraSpacing, PixelSnapH
IM_ASSERT ( r - > Font - > ContainerAtlas = = atlas ) ;
ImVec2 uv0 , uv1 ;
atlas - > CalcCustomRectUV ( r , & uv0 , & uv1 ) ;
r - > Font - > AddGlyph ( ( ImWchar ) r - > GlyphID , r - > GlyphOffset . x , r - > GlyphOffset . y , r - > GlyphOffset . x + r - > Width , r - > GlyphOffset . y + r - > Height , uv0 . x , uv0 . y , uv1 . x , uv1 . y , r - > GlyphAdvanceX ) ;
r - > Font - > AddGlyph ( NULL , ( ImWchar ) r - > GlyphID , r - > GlyphOffset . x , r - > GlyphOffset . y , r - > GlyphOffset . x + r - > Width , r - > GlyphOffset . y + r - > Height , uv0 . x , uv0 . y , uv1 . x , uv1 . y , r - > GlyphAdvanceX ) ;
}
// Build all fonts lookup tables
@ -2767,7 +2777,6 @@ ImFont::ImFont()
FallbackAdvanceX = 0.0f ;
FallbackChar = ( ImWchar ) ' ? ' ;
EllipsisChar = ( ImWchar ) - 1 ;
DisplayOffset = ImVec2 ( 0.0f , 0.0f ) ;
FallbackGlyph = NULL ;
ContainerAtlas = NULL ;
ConfigData = NULL ;
@ -2884,8 +2893,29 @@ void ImFont::GrowIndex(int new_size)
// x0/y0/x1/y1 are offset from the character upper-left layout position, in pixels. Therefore x0/y0 are often fairly close to zero.
// Not to be mistaken with texture coordinates, which are held by u0/v0/u1/v1 in normalized format (0.0..1.0 on each texture axis).
void ImFont : : AddGlyph ( ImWchar codepoint , float x0 , float y0 , float x1 , float y1 , float u0 , float v0 , float u1 , float v1 , float advance_x )
// 'cfg' is not necessarily == 'this->ConfigData' because multiple source fonts+configs can be used to build one target font.
void ImFont : : AddGlyph ( const ImFontConfig * cfg , ImWchar codepoint , float x0 , float y0 , float x1 , float y1 , float u0 , float v0 , float u1 , float v1 , float advance_x )
{
if ( cfg ! = NULL )
{
// Clamp & recenter if needed
const float advance_x_original = advance_x ;
advance_x = ImClamp ( advance_x , cfg - > GlyphMinAdvanceX , cfg - > GlyphMaxAdvanceX ) ;
if ( advance_x ! = advance_x_original )
{
float char_off_x = cfg - > PixelSnapH ? ImFloor ( ( advance_x - advance_x_original ) * 0.5f ) : ( advance_x - advance_x_original ) * 0.5f ;
x0 + = char_off_x ;
x1 + = char_off_x ;
}
// Snap to pixel
if ( cfg - > PixelSnapH )
advance_x = IM_ROUND ( advance_x ) ;
// Bake spacing
advance_x + = cfg - > GlyphExtraSpacing . x ;
}
Glyphs . resize ( Glyphs . Size + 1 ) ;
ImFontGlyph & glyph = Glyphs . back ( ) ;
glyph . Codepoint = ( unsigned int ) codepoint ;
@ -2898,14 +2928,13 @@ void ImFont::AddGlyph(ImWchar codepoint, float x0, float y0, float x1, float y1,
glyph . V0 = v0 ;
glyph . U1 = u1 ;
glyph . V1 = v1 ;
glyph . AdvanceX = advance_x + ConfigData - > GlyphExtraSpacing . x ; // Bake spacing into AdvanceX
if ( ConfigData - > PixelSnapH )
glyph . AdvanceX = IM_ROUND ( glyph . AdvanceX ) ;
glyph . AdvanceX = advance_x ;
// Compute rough surface usage metrics (+1 to account for average padding, +0.99 to round)
// We use (U1-U0)*TexWidth instead of X1-X0 to account for oversampling.
float pad = ContainerAtlas - > TexGlyphPadding + 0.99f ;
DirtyLookupTables = true ;
MetricsTotalSurface + = ( int ) ( ( glyph . U1 - glyph . U0 ) * ContainerAtlas - > TexWidth + 1.99f ) * ( int ) ( ( glyph . V1 - glyph . V0 ) * ContainerAtlas - > TexHeight + 1.99f ) ;
MetricsTotalSurface + = ( int ) ( ( glyph . U1 - glyph . U0 ) * ContainerAtlas - > TexWidth + pad ) * ( int ) ( ( glyph . V1 - glyph . V0 ) * ContainerAtlas - > TexHeight + pad ) ;
}
void ImFont : : AddRemapChar ( ImWchar dst , ImWchar src , bool overwrite_dst )
@ -3142,8 +3171,8 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
if ( ! glyph | | ! glyph - > Visible )
return ;
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 ) ;
pos . x = IM_FLOOR ( pos . x ) ;
pos . y = IM_FLOOR ( pos . 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 ) ;
}
@ -3154,8 +3183,8 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
text_end = text_begin + strlen ( text_begin ) ; // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls.
// Align to be pixel perfect
pos . x = IM_FLOOR ( pos . x + DisplayOffset . x ) ;
pos . y = IM_FLOOR ( pos . y + DisplayOffset . y ) ;
pos . x = IM_FLOOR ( pos . x ) ;
pos . y = IM_FLOOR ( pos . y ) ;
float x = pos . x ;
float y = pos . y ;
if ( y > clip_rect . w )
@ -3504,6 +3533,22 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im
draw_list - > PathFillConvex ( col ) ;
}
void ImGui : : RenderRectFilledWithHole ( ImDrawList * draw_list , ImRect outer , ImRect inner , ImU32 col , float rounding )
{
const bool fill_L = ( inner . Min . x > outer . Min . x ) ;
const bool fill_R = ( inner . Max . x < outer . Max . x ) ;
const bool fill_U = ( inner . Min . y > outer . Min . y ) ;
const bool fill_D = ( inner . Max . y < outer . Max . y ) ;
if ( fill_L ) draw_list - > AddRectFilled ( ImVec2 ( outer . Min . x , inner . Min . y ) , ImVec2 ( inner . Min . x , inner . Max . y ) , col , rounding , ( fill_U ? 0 : ImDrawCornerFlags_TopLeft ) | ( fill_D ? 0 : ImDrawCornerFlags_BotLeft ) ) ;
if ( fill_R ) draw_list - > AddRectFilled ( ImVec2 ( inner . Max . x , inner . Min . y ) , ImVec2 ( outer . Max . x , inner . Max . y ) , col , rounding , ( fill_U ? 0 : ImDrawCornerFlags_TopRight ) | ( fill_D ? 0 : ImDrawCornerFlags_BotRight ) ) ;
if ( fill_U ) draw_list - > AddRectFilled ( ImVec2 ( inner . Min . x , outer . Min . y ) , ImVec2 ( inner . Max . x , inner . Min . y ) , col , rounding , ( fill_L ? 0 : ImDrawCornerFlags_TopLeft ) | ( fill_R ? 0 : ImDrawCornerFlags_TopRight ) ) ;
if ( fill_D ) draw_list - > AddRectFilled ( ImVec2 ( inner . Min . x , inner . Max . y ) , ImVec2 ( inner . Max . x , outer . Max . y ) , col , rounding , ( fill_L ? 0 : ImDrawCornerFlags_BotLeft ) | ( fill_R ? 0 : ImDrawCornerFlags_BotRight ) ) ;
if ( fill_L & & fill_U ) draw_list - > AddRectFilled ( ImVec2 ( outer . Min . x , outer . Min . y ) , ImVec2 ( inner . Min . x , inner . Min . y ) , col , rounding , ImDrawCornerFlags_TopLeft ) ;
if ( fill_R & & fill_U ) draw_list - > AddRectFilled ( ImVec2 ( inner . Max . x , outer . Min . y ) , ImVec2 ( outer . Max . x , inner . Min . y ) , col , rounding , ImDrawCornerFlags_TopRight ) ;
if ( fill_L & & fill_D ) draw_list - > AddRectFilled ( ImVec2 ( outer . Min . x , inner . Max . y ) , ImVec2 ( inner . Min . x , outer . Max . y ) , col , rounding , ImDrawCornerFlags_BotLeft ) ;
if ( fill_R & & fill_D ) draw_list - > AddRectFilled ( ImVec2 ( inner . Max . x , inner . Max . y ) , ImVec2 ( outer . Max . x , outer . Max . y ) , col , rounding , ImDrawCornerFlags_BotRight ) ;
}
// Helper for ColorPicker4()
// NB: This is rather brittle and will show artifact when rounding this enabled if rounded corners overlap multiple cells. Caller currently responsible for avoiding that.
// Spent a non reasonable amount of time trying to getting this right for ColorButton with rounding+anti-aliasing+ImGuiColorEditFlags_HalfAlphaPreview flag + various grid sizes and offsets, and eventually gave up... probably more reasonable to disable rounding altogether.