Merge thedmd/feature/font-line-spacing into ImGui.

This commit is contained in:
Bartosz Taudul 2021-12-23 14:17:01 +01:00
parent b83cda575a
commit e822dde7e1
No known key found for this signature in database
GPG Key ID: B7FE2008B7575DF3
6 changed files with 155 additions and 99 deletions

View File

@ -2860,7 +2860,7 @@ void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool
if (text != text_display_end) if (text != text_display_end)
{ {
window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end); window->DrawList->AddText(g.Font, g.FontSize, g.FontLineHeight, g.FontBaselineOffset, pos, GetColorU32(ImGuiCol_Text), text, text_display_end);
if (g.LogEnabled) if (g.LogEnabled)
LogRenderedText(&pos, text, text_display_end); LogRenderedText(&pos, text, text_display_end);
} }
@ -2876,7 +2876,7 @@ void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end
if (text != text_end) if (text != text_end)
{ {
window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width); window->DrawList->AddText(g.Font, g.FontSize, g.FontLineHeight, g.FontBaselineOffset, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width);
if (g.LogEnabled) if (g.LogEnabled)
LogRenderedText(&pos, text, text_end); LogRenderedText(&pos, text, text_end);
} }
@ -2951,6 +2951,7 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con
const ImFont* font = draw_list->_Data->Font; const ImFont* font = draw_list->_Data->Font;
const float font_size = draw_list->_Data->FontSize; const float font_size = draw_list->_Data->FontSize;
const float font_line_height = draw_list->_Data->FontLineHeight;
const char* text_end_ellipsis = NULL; const char* text_end_ellipsis = NULL;
ImWchar ellipsis_char = font->EllipsisChar; ImWchar ellipsis_char = font->EllipsisChar;
@ -2975,18 +2976,18 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con
// We can now claim the space between pos_max.x and ellipsis_max.x // We can now claim the space between pos_max.x and ellipsis_max.x
const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_total_width) - pos_min.x, 1.0f); const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_total_width) - pos_min.x, 1.0f);
float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; float text_size_clipped_x = font->CalcTextSizeA(font_size, font_line_height, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x;
if (text == text_end_ellipsis && text_end_ellipsis < text_end_full) if (text == text_end_ellipsis && text_end_ellipsis < text_end_full)
{ {
// Always display at least 1 character if there's no room for character + ellipsis // Always display at least 1 character if there's no room for character + ellipsis
text_end_ellipsis = text + ImTextCountUtf8BytesFromChar(text, text_end_full); text_end_ellipsis = text + ImTextCountUtf8BytesFromChar(text, text_end_full);
text_size_clipped_x = font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text, text_end_ellipsis).x; text_size_clipped_x = font->CalcTextSizeA(font_size, font_line_height, FLT_MAX, 0.0f, text, text_end_ellipsis).x;
} }
while (text_end_ellipsis > text && ImCharIsBlankA(text_end_ellipsis[-1])) while (text_end_ellipsis > text && ImCharIsBlankA(text_end_ellipsis[-1]))
{ {
// Trim trailing space before ellipsis (FIXME: Supporting non-ascii blanks would be nice, for this we need a function to backtrack in UTF-8 text) // Trim trailing space before ellipsis (FIXME: Supporting non-ascii blanks would be nice, for this we need a function to backtrack in UTF-8 text)
text_end_ellipsis--; text_end_ellipsis--;
text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x; // Ascii blanks are always 1 byte text_size_clipped_x -= font->CalcTextSizeA(font_size, font_line_height, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x; // Ascii blanks are always 1 byte
} }
// Render text, render ellipsis // Render text, render ellipsis
@ -2995,7 +2996,7 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con
if (ellipsis_x + ellipsis_total_width <= ellipsis_max_x) if (ellipsis_x + ellipsis_total_width <= ellipsis_max_x)
for (int i = 0; i < ellipsis_char_count; i++) for (int i = 0; i < ellipsis_char_count; i++)
{ {
font->RenderChar(draw_list, font_size, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_char); font->RenderChar(draw_list, font_size, font_line_height, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_char);
ellipsis_x += ellipsis_glyph_width; ellipsis_x += ellipsis_glyph_width;
} }
} }
@ -3185,7 +3186,7 @@ static void SetCurrentWindow(ImGuiWindow* window)
g.CurrentWindow = window; g.CurrentWindow = window;
g.CurrentTable = window && window->DC.CurrentTableIdx != -1 ? g.Tables.GetByIndex(window->DC.CurrentTableIdx) : NULL; g.CurrentTable = window && window->DC.CurrentTableIdx != -1 ? g.Tables.GetByIndex(window->DC.CurrentTableIdx) : NULL;
if (window) if (window)
g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize(); ImGui::SetCurrentFont(g.Font);
} }
void ImGui::GcCompactTransientMiscBuffers() void ImGui::GcCompactTransientMiscBuffers()
@ -4008,7 +4009,7 @@ void ImGui::UpdateMouseWheel()
if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)) if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))
{ {
float max_step = window->InnerRect.GetHeight() * 0.67f; float max_step = window->InnerRect.GetHeight() * 0.67f;
float scroll_step = ImFloor(ImMin(5 * window->CalcFontSize(), max_step)); float scroll_step = ImFloor(ImMin(5 * window->CalcFontHeight(), max_step));
SetScrollY(window, window->Scroll.y - wheel_y * scroll_step); SetScrollY(window, window->Scroll.y - wheel_y * scroll_step);
} }
} }
@ -4022,7 +4023,7 @@ void ImGui::UpdateMouseWheel()
if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs)) if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(window->Flags & ImGuiWindowFlags_NoMouseInputs))
{ {
float max_step = window->InnerRect.GetWidth() * 0.67f; float max_step = window->InnerRect.GetWidth() * 0.67f;
float scroll_step = ImFloor(ImMin(2 * window->CalcFontSize(), max_step)); float scroll_step = ImFloor(ImMin(2 * window->CalcFontWidth(), max_step));
SetScrollX(window, window->Scroll.x - wheel_x * scroll_step); SetScrollX(window, window->Scroll.x - wheel_x * scroll_step);
} }
} }
@ -4919,9 +4920,10 @@ ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_tex
ImFont* font = g.Font; ImFont* font = g.Font;
const float font_size = g.FontSize; const float font_size = g.FontSize;
const float font_line_height = g.FontLineHeight;
if (text == text_display_end) if (text == text_display_end)
return ImVec2(0.0f, font_size); return ImVec2(0.0f, font_line_height);
ImVec2 text_size = font->CalcTextSizeA(font_size, FLT_MAX, wrap_width, text, text_display_end, NULL); ImVec2 text_size = font->CalcTextSizeA(font_size, font_line_height, FLT_MAX, wrap_width, text, text_display_end, NULL);
// Round // Round
// FIXME: This has been here since Dec 2015 (7b0bf230) but down the line we want this out. // FIXME: This has been here since Dec 2015 (7b0bf230) but down the line we want this out.
@ -6159,7 +6161,7 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
// FIXME: Would be nice to generalize the subtleties expressed here into reusable code. // FIXME: Would be nice to generalize the subtleties expressed here into reusable code.
float pad_l = style.FramePadding.x; float pad_l = style.FramePadding.x;
float pad_r = style.FramePadding.x; float pad_r = style.FramePadding.x;
float button_sz = g.FontSize; float button_sz = g.FontLineHeight;
ImVec2 close_button_pos; ImVec2 close_button_pos;
ImVec2 collapse_button_pos; ImVec2 collapse_button_pos;
if (has_close_button) if (has_close_button)
@ -7315,14 +7317,19 @@ void ImGui::SetCurrentFont(ImFont* font)
IM_ASSERT(font && font->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ? IM_ASSERT(font && font->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?
IM_ASSERT(font->Scale > 0.0f); IM_ASSERT(font->Scale > 0.0f);
g.Font = font; g.Font = font;
g.FontBaseSize = ImMax(1.0f, g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale); g.FontBaseScale = ImMax(0.01f, g.IO.FontGlobalScale * g.Font->Scale);
g.FontSize = g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f; const float font_scale = g.FontBaseScale * (g.CurrentWindow ? g.CurrentWindow->CalcFontScale() : 1.0f);
g.FontSize = IM_ROUND(g.Font->FontSize * font_scale);
g.FontLineHeight = IM_ROUND((g.Font->FontSize + g.Font->ExtraLineHeight) * font_scale);
g.FontBaselineOffset = g.Font->BaselineOffset * font_scale;
ImFontAtlas* atlas = g.Font->ContainerAtlas; ImFontAtlas* atlas = g.Font->ContainerAtlas;
g.DrawListSharedData.TexUvWhitePixel = atlas->TexUvWhitePixel; g.DrawListSharedData.TexUvWhitePixel = atlas->TexUvWhitePixel;
g.DrawListSharedData.TexUvLines = atlas->TexUvLines; g.DrawListSharedData.TexUvLines = atlas->TexUvLines;
g.DrawListSharedData.Font = g.Font; g.DrawListSharedData.Font = g.Font;
g.DrawListSharedData.FontSize = g.FontSize; g.DrawListSharedData.FontSize = g.FontSize;
g.DrawListSharedData.FontLineHeight = g.FontLineHeight;
g.DrawListSharedData.FontBaselineOffset = g.FontBaselineOffset;
} }
void ImGui::PushFont(ImFont* font) void ImGui::PushFont(ImFont* font)
@ -7852,6 +7859,16 @@ float ImGui::GetFontSize()
return GImGui->FontSize; return GImGui->FontSize;
} }
float ImGui::GetFontLineHeight()
{
return GImGui->FontLineHeight;
}
float ImGui::GetFontBaselineOffset()
{
return GImGui->FontBaselineOffset;
}
ImVec2 ImGui::GetFontTexUvWhitePixel() ImVec2 ImGui::GetFontTexUvWhitePixel()
{ {
return GImGui->DrawListSharedData.TexUvWhitePixel; return GImGui->DrawListSharedData.TexUvWhitePixel;
@ -7863,7 +7880,7 @@ void ImGui::SetWindowFontScale(float scale)
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
window->FontWindowScale = scale; window->FontWindowScale = scale;
g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize(); SetCurrentFont(g.Font);
} }
void ImGui::ActivateItem(ImGuiID id) void ImGui::ActivateItem(ImGuiID id)
@ -8631,25 +8648,25 @@ ImVec2 ImGui::CalcItemSize(ImVec2 size, float default_w, float default_h)
float ImGui::GetTextLineHeight() float ImGui::GetTextLineHeight()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
return g.FontSize; return g.FontLineHeight;
} }
float ImGui::GetTextLineHeightWithSpacing() float ImGui::GetTextLineHeightWithSpacing()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
return g.FontSize + g.Style.ItemSpacing.y; return g.FontLineHeight + g.Style.ItemSpacing.y;
} }
float ImGui::GetFrameHeight() float ImGui::GetFrameHeight()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
return g.FontSize + g.Style.FramePadding.y * 2.0f; return g.FontLineHeight + g.Style.FramePadding.y * 2.0f;
} }
float ImGui::GetFrameHeightWithSpacing() float ImGui::GetFrameHeightWithSpacing()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y; return g.FontLineHeight + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y;
} }
// FIXME: All the Contents Region function are messy or misleading. WE WILL AIM TO OBSOLETE ALL OF THEM WITH A NEW "WORK RECT" API. Thanks for your patience! // FIXME: All the Contents Region function are messy or misleading. WE WILL AIM TO OBSOLETE ALL OF THEM WITH A NEW "WORK RECT" API. Thanks for your patience!
@ -10333,23 +10350,24 @@ static void ImGui::NavUpdate()
{ {
// *Fallback* manual-scroll with Nav directional keys when window has no navigable item // *Fallback* manual-scroll with Nav directional keys when window has no navigable item
ImGuiWindow* window = g.NavWindow; ImGuiWindow* window = g.NavWindow;
const float scroll_speed = IM_ROUND(window->CalcFontSize() * 100 * io.DeltaTime); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. const float scroll_speed_x = IM_ROUND(window->CalcFontWidth() * 100 * io.DeltaTime); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported.
const float scroll_speed_y = IM_ROUND(window->CalcFontHeight() * 100 * io.DeltaTime); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported.
const ImGuiDir move_dir = g.NavMoveDir; const ImGuiDir move_dir = g.NavMoveDir;
if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavHasScroll && move_dir != ImGuiDir_None) if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavHasScroll && move_dir != ImGuiDir_None)
{ {
if (move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right) if (move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right)
SetScrollX(window, ImFloor(window->Scroll.x + ((move_dir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed)); SetScrollX(window, ImFloor(window->Scroll.x + ((move_dir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed_x));
if (move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down) if (move_dir == ImGuiDir_Up || move_dir == ImGuiDir_Down)
SetScrollY(window, ImFloor(window->Scroll.y + ((move_dir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed)); SetScrollY(window, ImFloor(window->Scroll.y + ((move_dir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed_y));
} }
// *Normal* Manual scroll with NavScrollXXX keys // *Normal* Manual scroll with NavScrollXXX keys
// Next movement request will clamp the NavId reference rectangle to the visible area, so navigation will resume within those bounds. // Next movement request will clamp the NavId reference rectangle to the visible area, so navigation will resume within those bounds.
ImVec2 scroll_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down, 1.0f / 10.0f, 10.0f); ImVec2 scroll_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down, 1.0f / 10.0f, 10.0f);
if (scroll_dir.x != 0.0f && window->ScrollbarX) if (scroll_dir.x != 0.0f && window->ScrollbarX)
SetScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed)); SetScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed_x));
if (scroll_dir.y != 0.0f) if (scroll_dir.y != 0.0f)
SetScrollY(window, ImFloor(window->Scroll.y + scroll_dir.y * scroll_speed)); SetScrollY(window, ImFloor(window->Scroll.y + scroll_dir.y * scroll_speed_y));
} }
// Always prioritize mouse highlight if navigation is disabled // Always prioritize mouse highlight if navigation is disabled
@ -10474,7 +10492,7 @@ void ImGui::NavUpdateCreateMoveRequest()
if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer])) if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer]))
{ {
IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: clamp NavRectRel\n"); IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: clamp NavRectRel\n");
float pad = window->CalcFontSize() * 0.5f; float pad = window->CalcFontWidth() * 0.5f;
window_rect_rel.Expand(ImVec2(-ImMin(window_rect_rel.GetWidth(), pad), -ImMin(window_rect_rel.GetHeight(), pad))); // Terrible approximation for the intent of starting navigation from first fully visible item window_rect_rel.Expand(ImVec2(-ImMin(window_rect_rel.GetWidth(), pad), -ImMin(window_rect_rel.GetHeight(), pad))); // Terrible approximation for the intent of starting navigation from first fully visible item
window->NavRectRel[g.NavLayer].ClipWithFull(window_rect_rel); window->NavRectRel[g.NavLayer].ClipWithFull(window_rect_rel);
g.NavId = g.NavFocusScopeId = 0; g.NavId = g.NavFocusScopeId = 0;
@ -10698,7 +10716,7 @@ static float ImGui::NavUpdatePageUpPageDown()
else else
{ {
ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer]; ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer];
const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight()); const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontHeight() * 1.0f + nav_rect_rel.GetHeight());
float nav_scoring_rect_offset_y = 0.0f; float nav_scoring_rect_offset_y = 0.0f;
if (IsKeyPressed(io.KeyMap[ImGuiKey_PageUp], true)) if (IsKeyPressed(io.KeyMap[ImGuiKey_PageUp], true))
{ {
@ -16943,7 +16961,7 @@ void ImGui::DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP*
window->DrawList->AddRectFilled(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_WindowBg, alpha_mul)); window->DrawList->AddRectFilled(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_WindowBg, alpha_mul));
window->DrawList->AddRectFilled(title_r.Min, title_r.Max, GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg, alpha_mul)); window->DrawList->AddRectFilled(title_r.Min, title_r.Max, GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg, alpha_mul));
window->DrawList->AddRect(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_Border, alpha_mul)); window->DrawList->AddRect(thumb_r.Min, thumb_r.Max, GetColorU32(ImGuiCol_Border, alpha_mul));
window->DrawList->AddText(g.Font, g.FontSize * 1.0f, title_r.Min, GetColorU32(ImGuiCol_Text, alpha_mul), thumb_window->Name, FindRenderedTextEnd(thumb_window->Name)); window->DrawList->AddText(g.Font, g.FontSize, g.FontLineHeight, g.FontBaselineOffset, title_r.Min, GetColorU32(ImGuiCol_Text, alpha_mul), thumb_window->Name, FindRenderedTextEnd(thumb_window->Name));
} }
draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul)); draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border, alpha_mul));
} }
@ -17740,7 +17758,12 @@ void ImGui::DebugNodeFont(ImFont* font)
"You may oversample them to get some flexibility with scaling. " "You may oversample them to get some flexibility with scaling. "
"You can also render at multiple sizes and select which one to use at runtime.\n\n" "You can also render at multiple sizes and select which one to use at runtime.\n\n"
"(Glimmer of hope: the atlas system will be rewritten in the future to make scaling more flexible.)"); "(Glimmer of hope: the atlas system will be rewritten in the future to make scaling more flexible.)");
SetNextItemWidth(GetFontSize() * 8);
DragFloat("Extra line height", &font->ExtraLineHeight, 1.0f, -font->FontSize, FLT_MAX, "%g");
SetNextItemWidth(GetFontSize() * 8);
DragFloat("Baseline offset", &font->BaselineOffset, 0.1f, -FLT_MAX, FLT_MAX, "%g");
Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent); Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
Text("Line Height: %f", font->FontSize + font->ExtraLineHeight);
char c_str[5]; char c_str[5];
Text("Fallback character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->FallbackChar), font->FallbackChar); Text("Fallback character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->FallbackChar), font->FallbackChar);
Text("Ellipsis character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->EllipsisChar), font->EllipsisChar); Text("Ellipsis character: '%s' (U+%04X)", ImTextCharToUtf8(c_str, font->EllipsisChar), font->EllipsisChar);
@ -17790,7 +17813,7 @@ void ImGui::DebugNodeFont(ImFont* font)
const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n)); const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n));
draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50)); draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50));
if (glyph) if (glyph)
font->RenderChar(draw_list, cell_size, cell_p1, glyph_col, (ImWchar)(base + n)); font->RenderChar(draw_list, cell_size, cell_size, cell_p1, glyph_col, (ImWchar)(base + n));
if (glyph && IsMouseHoveringRect(cell_p1, cell_p2)) if (glyph && IsMouseHoveringRect(cell_p1, cell_p2))
{ {
BeginTooltip(); BeginTooltip();

View File

@ -433,7 +433,9 @@ namespace ImGui
// Style read access // Style read access
// - Use the style editor (ShowStyleEditor() function) to interactively see what the colors are) // - Use the style editor (ShowStyleEditor() function) to interactively see what the colors are)
IMGUI_API ImFont* GetFont(); // get current font IMGUI_API ImFont* GetFont(); // get current font
IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied IMGUI_API float GetFontSize(); // get current font size, mostly used in context where width should be determined (= size in pixels) of current font with current scale applied
IMGUI_API float GetFontLineHeight(); // get current font line height (in pixels) of current font with current scale applied
IMGUI_API float GetFontBaselineOffset(); // get current font baseline offset (in pixels) of current font with current scale applied
IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API
IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul = 1.0f); // retrieve given style color with style alpha applied and optional extra alpha multiplier, packed as a 32-bit value suitable for ImDrawList IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul = 1.0f); // retrieve given style color with style alpha applied and optional extra alpha multiplier, packed as a 32-bit value suitable for ImDrawList
IMGUI_API ImU32 GetColorU32(const ImVec4& col); // retrieve given color with style alpha applied, packed as a 32-bit value suitable for ImDrawList IMGUI_API ImU32 GetColorU32(const ImVec4& col); // retrieve given color with style alpha applied, packed as a 32-bit value suitable for ImDrawList
@ -2551,6 +2553,7 @@ struct ImDrawList
IMGUI_API void AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments); IMGUI_API void AddNgonFilled(const ImVec2& center, float radius, ImU32 col, int num_segments);
IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL); IMGUI_API void AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL);
IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL); IMGUI_API void AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL);
IMGUI_API void AddText(const ImFont* font, float font_size, float font_line_height, float font_baseline_offset, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end = NULL, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = NULL);
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness); IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness);
IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col); // Note: Anti-aliased filling requires points to be in clockwise order. IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col); // Note: Anti-aliased filling requires points to be in clockwise order.
IMGUI_API void AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0); // Cubic Bezier (4 control points) IMGUI_API void AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness, int num_segments = 0); // Cubic Bezier (4 control points)
@ -2864,6 +2867,8 @@ struct ImFont
ImWchar DotChar; // 2 // out // = '.' // Character used for ellipsis rendering (if a single '...' character isn't found) ImWchar DotChar; // 2 // out // = '.' // Character used for ellipsis rendering (if a single '...' character isn't found)
bool DirtyLookupTables; // 1 // out // bool DirtyLookupTables; // 1 // out //
float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale() float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale()
float ExtraLineHeight; // 4 // in // // Amount of space to be added to line height. Using negative values are allowed. (You need to call ImGui::SetCurrentFont() to populate these values when you're expecting immediate response.)
float BaselineOffset; // 4 // in // // Font baseline will be modified by this value while drawing. (You need to call ImGui::SetCurrentFont() to populate these values when you're expecting immediate response.)
float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize]
int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) int MetricsTotalSurface;// 4 // out // // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs)
ImU8 Used4kPagesMap[(IM_UNICODE_CODEPOINT_MAX+1)/4096/8]; // 2 bytes if ImWchar=ImWchar16, 34 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 4K codepoints that has one active glyph. This is mainly used to facilitate iterations across all used codepoints. ImU8 Used4kPagesMap[(IM_UNICODE_CODEPOINT_MAX+1)/4096/8]; // 2 bytes if ImWchar=ImWchar16, 34 bytes if ImWchar==ImWchar32. Store 1-bit for each block of 4K codepoints that has one active glyph. This is mainly used to facilitate iterations across all used codepoints.
@ -2879,10 +2884,11 @@ struct ImFont
// 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable. // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable.
// 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable. // 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable.
IMGUI_API ImVec2 CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end = NULL, const char** remaining = NULL) const; // utf8 IMGUI_API ImVec2 CalcTextSizeA(float size, float line_height, float max_width, float wrap_width, const char* text_begin, const char* text_end = NULL, const char** remaining = NULL) const; // utf8
IMGUI_API const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const; IMGUI_API const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const;
IMGUI_API void RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, ImWchar c) const; IMGUI_API void RenderChar(ImDrawList* draw_list, float size, float line_height, ImVec2 pos, ImU32 col, ImWchar c) const;
IMGUI_API void 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 = 0.0f, bool cpu_fine_clip = false) const; IMGUI_API void 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 = 0.0f, bool cpu_fine_clip = false) const;
IMGUI_API void RenderText(ImDrawList* draw_list, float size, float line_height, float baseline_offset, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, bool cpu_fine_clip = false) const;
// [Internal] Don't use! // [Internal] Don't use!
IMGUI_API void BuildLookupTable(); IMGUI_API void BuildLookupTable();

View File

@ -1582,6 +1582,21 @@ void ImDrawList::AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const Im
} }
void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect) void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect)
{
// Pull default font/size from the shared ImDrawListSharedData instance
if (font == NULL)
font = _Data->Font;
if (font_size == 0.0f)
font_size = _Data->FontSize;
const float scale = font_size / font->FontSize;
const float line_height = (font->FontSize + font->ExtraLineHeight) * scale;
const float baseline_offset = font->BaselineOffset * scale;
AddText(font, font_size, line_height, baseline_offset, pos, col, text_begin, text_end, wrap_width, cpu_fine_clip_rect);
}
void ImDrawList::AddText(const ImFont* font, float font_size, float font_line_height, float font_baseline_offset, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect)
{ {
if ((col & IM_COL32_A_MASK) == 0) if ((col & IM_COL32_A_MASK) == 0)
return; return;
@ -1607,7 +1622,7 @@ void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos,
clip_rect.z = ImMin(clip_rect.z, cpu_fine_clip_rect->z); clip_rect.z = ImMin(clip_rect.z, cpu_fine_clip_rect->z);
clip_rect.w = ImMin(clip_rect.w, cpu_fine_clip_rect->w); clip_rect.w = ImMin(clip_rect.w, cpu_fine_clip_rect->w);
} }
font->RenderText(this, font_size, pos, col, clip_rect, text_begin, text_end, wrap_width, cpu_fine_clip_rect != NULL); font->RenderText(this, font_size, font_line_height, font_baseline_offset, pos, col, clip_rect, text_begin, text_end, wrap_width, cpu_fine_clip_rect != NULL);
} }
void ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end) void ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end)
@ -3113,6 +3128,8 @@ void ImFontGlyphRangesBuilder::BuildRanges(ImVector<ImWchar>* out_ranges)
ImFont::ImFont() ImFont::ImFont()
{ {
FontSize = 0.0f; FontSize = 0.0f;
ExtraLineHeight = 0.0f;
BaselineOffset = 0.0f;
FallbackAdvanceX = 0.0f; FallbackAdvanceX = 0.0f;
FallbackChar = (ImWchar)-1; FallbackChar = (ImWchar)-1;
EllipsisChar = (ImWchar)-1; EllipsisChar = (ImWchar)-1;
@ -3436,12 +3453,11 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c
return s; return s;
} }
ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** remaining) const ImVec2 ImFont::CalcTextSizeA(float size, float line_height, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** remaining) const
{ {
if (!text_end) if (!text_end)
text_end = text_begin + strlen(text_begin); // FIXME-OPT: Need to avoid this. text_end = text_begin + strlen(text_begin); // FIXME-OPT: Need to avoid this.
const float line_height = size;
const float scale = size / FontSize; const float scale = size / FontSize;
ImVec2 text_size = ImVec2(0, 0); ImVec2 text_size = ImVec2(0, 0);
@ -3531,7 +3547,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons
} }
// Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound. // Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound.
void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, ImWchar c) const void ImFont::RenderChar(ImDrawList* draw_list, float size, float line_height, ImVec2 pos, ImU32 col, ImWchar c) const
{ {
const ImFontGlyph* glyph = FindGlyph(c); const ImFontGlyph* glyph = FindGlyph(c);
if (!glyph || !glyph->Visible) if (!glyph || !glyph->Visible)
@ -3540,27 +3556,35 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
col |= ~IM_COL32_A_MASK; col |= ~IM_COL32_A_MASK;
float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f; float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f;
pos.x = IM_FLOOR(pos.x); pos.x = IM_FLOOR(pos.x);
pos.y = IM_FLOOR(pos.y); pos.y = IM_FLOOR(pos.y + (line_height - size) * 0.5f);
draw_list->PrimReserve(6, 4); 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); 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);
} }
// Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound. // Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound.
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 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
{
const float scale = size / FontSize;
const float line_height = (FontSize + ExtraLineHeight) * scale;
const float baseline_offset = BaselineOffset * scale;
RenderText(draw_list, size, line_height, baseline_offset, pos, col, clip_rect, text_begin, text_end, wrap_width, cpu_fine_clip);
}
void ImFont::RenderText(ImDrawList* draw_list, float size, float line_height, float baseline_offset, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const
{ {
if (!text_end) if (!text_end)
text_end = text_begin + strlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls. 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 // Align to be pixel perfect
pos.x = IM_FLOOR(pos.x); pos.x = IM_FLOOR(pos.x);
pos.y = IM_FLOOR(pos.y); pos.y = IM_FLOOR(pos.y + (line_height - size) * 0.5f + baseline_offset);
float x = pos.x; float x = pos.x;
float y = pos.y; float y = pos.y;
if (y > clip_rect.w) if (y > clip_rect.w)
return; return;
const float scale = size / FontSize; const float scale = size / FontSize;
const float line_height = FontSize * scale;
const bool word_wrap_enabled = (wrap_width > 0.0f); const bool word_wrap_enabled = (wrap_width > 0.0f);
const char* word_wrap_eol = NULL; const char* word_wrap_eol = NULL;
@ -3757,7 +3781,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
// Render an arrow aimed to be aligned with text (p_min is a position in the same space text would be positioned). To e.g. denote expanded/collapsed state // Render an arrow aimed to be aligned with text (p_min is a position in the same space text would be positioned). To e.g. denote expanded/collapsed state
void ImGui::RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float scale) void ImGui::RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImU32 col, ImGuiDir dir, float scale)
{ {
const float h = draw_list->_Data->FontSize * 1.00f; const float h = draw_list->_Data->FontLineHeight * 1.00f;
float r = h * 0.40f * scale; float r = h * 0.40f * scale;
ImVec2 center = pos + ImVec2(h * 0.50f, h * 0.50f * scale); ImVec2 center = pos + ImVec2(h * 0.50f, h * 0.50f * scale);

View File

@ -725,6 +725,8 @@ struct IMGUI_API ImDrawListSharedData
ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas
ImFont* Font; // Current/default font (optional, for simplified AddText overload) ImFont* Font; // Current/default font (optional, for simplified AddText overload)
float FontSize; // Current/default font size (optional, for simplified AddText overload) float FontSize; // Current/default font size (optional, for simplified AddText overload)
float FontLineHeight; // Current/default font line height (optional, for simplified AddText overload)
float FontBaselineOffset; // Current/default font baseline offset (optional, for simplified AddText overload)
float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo()
float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc
ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen() ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen()
@ -1677,8 +1679,10 @@ struct ImGuiContext
ImGuiConfigFlags ConfigFlagsCurrFrame; // = g.IO.ConfigFlags at the time of NewFrame() ImGuiConfigFlags ConfigFlagsCurrFrame; // = g.IO.ConfigFlags at the time of NewFrame()
ImGuiConfigFlags ConfigFlagsLastFrame; ImGuiConfigFlags ConfigFlagsLastFrame;
ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back()
float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window. float FontSize; // (Shortcut) == FontBaseScale * g.CurrentWindow->FontWindowScale * Font->FontSize == window->FontSize(). Text height for current window.
float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height. float FontLineHeight; // (Shortcut) == FontBaseScale * g.CurrentWindow->FontWindowScale * (Font->FontSize + Font->ExtraLineHeight) (optional, for simplified AddText overload)
float FontBaselineOffset; // (Shortcut) == FontBaseScale * g.CurrentWindow->FontWindowScale * Font->BaselineOffset (optional, for simplified AddText overload)
float FontBaseScale; // (Shortcut) == IO.FontGlobalScale * Font->Scale. Base text scale.
ImDrawListSharedData DrawListSharedData; ImDrawListSharedData DrawListSharedData;
double Time; double Time;
int FrameCount; int FrameCount;
@ -1944,7 +1948,7 @@ struct ImGuiContext
ConfigFlagsCurrFrame = ConfigFlagsLastFrame = ImGuiConfigFlags_None; ConfigFlagsCurrFrame = ConfigFlagsLastFrame = ImGuiConfigFlags_None;
FontAtlasOwnedByContext = shared_font_atlas ? false : true; FontAtlasOwnedByContext = shared_font_atlas ? false : true;
Font = NULL; Font = NULL;
FontSize = FontBaseSize = 0.0f; FontSize = FontBaseScale = FontLineHeight = FontBaselineOffset = 0.0f;
IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)(); IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
Time = 0.0f; Time = 0.0f;
FrameCount = 0; FrameCount = 0;
@ -2282,10 +2286,12 @@ public:
// We don't use g.FontSize because the window may be != g.CurrentWidow. // We don't use g.FontSize because the window may be != g.CurrentWidow.
ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); } ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
float CalcFontSize() const { ImGuiContext& g = *GImGui; float scale = g.FontBaseSize * FontWindowScale * FontDpiScale; if (ParentWindow) scale *= ParentWindow->FontWindowScale; return scale; } float CalcFontScale() const { float scale = FontWindowScale; if (ParentWindow) scale *= ParentWindow->FontWindowScale; return scale; }
float TitleBarHeight() const { ImGuiContext& g = *GImGui; return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + g.Style.FramePadding.y * 2.0f; } float CalcFontWidth() const { ImGuiContext& g = *GImGui; return CalcFontScale() * g.FontSize; }
float CalcFontHeight() const { ImGuiContext& g = *GImGui; return CalcFontScale() * g.FontLineHeight; }
float TitleBarHeight() const { ImGuiContext& g = *GImGui; return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontHeight() + g.Style.FramePadding.y * 2.0f; }
ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); } ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); }
float MenuBarHeight() const { ImGuiContext& g = *GImGui; return (Flags & ImGuiWindowFlags_MenuBar) ? DC.MenuBarOffset.y + CalcFontSize() + g.Style.FramePadding.y * 2.0f : 0.0f; } float MenuBarHeight() const { ImGuiContext& g = *GImGui; return (Flags & ImGuiWindowFlags_MenuBar) ? DC.MenuBarOffset.y + CalcFontHeight() + g.Style.FramePadding.y * 2.0f : 0.0f; }
ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); } ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); }
}; };

View File

@ -533,7 +533,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
// It will also react to changing fonts with mixed results. It doesn't need to be perfect but merely provide a decent transition. // It will also react to changing fonts with mixed results. It doesn't need to be perfect but merely provide a decent transition.
// FIXME-DPI: Provide consistent standards for reference size. Perhaps using g.CurrentDpiScale would be more self explanatory. // FIXME-DPI: Provide consistent standards for reference size. Perhaps using g.CurrentDpiScale would be more self explanatory.
// This is will lead us to non-rounded WidthRequest in columns, which should work but is a poorly tested path. // This is will lead us to non-rounded WidthRequest in columns, which should work but is a poorly tested path.
const float new_ref_scale_unit = g.FontSize; // g.Font->GetCharAdvance('A') ? const float new_ref_scale_unit = g.FontLineHeight; // g.Font->GetCharAdvance('A') ?
if (table->RefScale != 0.0f && table->RefScale != new_ref_scale_unit) if (table->RefScale != 0.0f && table->RefScale != new_ref_scale_unit)
{ {
const float scale_factor = new_ref_scale_unit / table->RefScale; const float scale_factor = new_ref_scale_unit / table->RefScale;

View File

@ -396,7 +396,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args)
const char* text_begin = g.TempBuffer; const char* text_begin = g.TempBuffer;
const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
const ImVec2 label_size = CalcTextSize(text_begin, text_end, false); const ImVec2 label_size = CalcTextSize(text_begin, text_end, false);
const ImVec2 total_size = ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x * 2) : 0.0f), label_size.y); // Empty text doesn't add padding const ImVec2 total_size = ImVec2(g.FontLineHeight + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x * 2) : 0.0f), label_size.y); // Empty text doesn't add padding
ImVec2 pos = window->DC.CursorPos; ImVec2 pos = window->DC.CursorPos;
pos.y += window->DC.CurrLineTextBaseOffset; pos.y += window->DC.CurrLineTextBaseOffset;
ItemSize(total_size, 0.0f); ItemSize(total_size, 0.0f);
@ -406,7 +406,7 @@ void ImGui::BulletTextV(const char* fmt, va_list args)
// Render // Render
ImU32 text_col = GetColorU32(ImGuiCol_Text); ImU32 text_col = GetColorU32(ImGuiCol_Text);
RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize * 0.5f, g.FontSize * 0.5f), text_col); RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize * 0.5f, g.FontLineHeight * 0.5f), text_col);
RenderText(bb.Min + ImVec2(g.FontSize + style.FramePadding.x * 2, 0.0f), text_begin, text_end, false); RenderText(bb.Min + ImVec2(g.FontSize + style.FramePadding.x * 2, 0.0f), text_begin, text_end, false);
} }
@ -776,7 +776,7 @@ bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiBu
const ImU32 text_col = GetColorU32(ImGuiCol_Text); const ImU32 text_col = GetColorU32(ImGuiCol_Text);
RenderNavHighlight(bb, id); RenderNavHighlight(bb, id);
RenderFrame(bb.Min, bb.Max, bg_col, true, g.Style.FrameRounding); RenderFrame(bb.Min, bb.Max, bg_col, true, g.Style.FrameRounding);
RenderArrow(window->DrawList, bb.Min + ImVec2(ImMax(0.0f, (size.x - g.FontSize) * 0.5f), ImMax(0.0f, (size.y - g.FontSize) * 0.5f)), text_col, dir); RenderArrow(window->DrawList, bb.Min + ImVec2(ImMax(0.0f, (size.x - g.FontLineHeight) * 0.5f), ImMax(0.0f, (size.y - g.FontLineHeight) * 0.5f)), text_col, dir);
return pressed; return pressed;
} }
@ -795,7 +795,7 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)
// Tweak 1: Shrink hit-testing area if button covers an abnormally large proportion of the visible region. That's in order to facilitate moving the window away. (#3825) // Tweak 1: Shrink hit-testing area if button covers an abnormally large proportion of the visible region. That's in order to facilitate moving the window away. (#3825)
// This may better be applied as a general hit-rect reduction mechanism for all widgets to ensure the area to move window is always accessible? // This may better be applied as a general hit-rect reduction mechanism for all widgets to ensure the area to move window is always accessible?
const ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f); const ImRect bb(pos, pos + ImVec2(g.FontLineHeight, g.FontLineHeight) + g.Style.FramePadding * 2.0f);
ImRect bb_interact = bb; ImRect bb_interact = bb;
const float area_to_visible_ratio = window->OuterRectClipped.GetArea() / bb.GetArea(); const float area_to_visible_ratio = window->OuterRectClipped.GetArea() / bb.GetArea();
if (area_to_visible_ratio < 1.5f) if (area_to_visible_ratio < 1.5f)
@ -832,7 +832,7 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos, ImGuiDockNode* dock_no
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f); ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontLineHeight) + g.Style.FramePadding * 2.0f);
ItemAdd(bb, id); ItemAdd(bb, id);
bool hovered, held; bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_None); bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_None);
@ -927,8 +927,8 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
// When we are too small, start hiding and disabling the grab (this reduce visual noise on very small window and facilitate using the window resize grab) // When we are too small, start hiding and disabling the grab (this reduce visual noise on very small window and facilitate using the window resize grab)
float alpha = 1.0f; float alpha = 1.0f;
if ((axis == ImGuiAxis_Y) && bb_frame_height < g.FontSize + g.Style.FramePadding.y * 2.0f) if ((axis == ImGuiAxis_Y) && bb_frame_height < g.FontLineHeight + g.Style.FramePadding.y * 2.0f)
alpha = ImSaturate((bb_frame_height - g.FontSize) / (g.Style.FramePadding.y * 2.0f)); alpha = ImSaturate((bb_frame_height - g.FontLineHeight) / (g.Style.FramePadding.y * 2.0f));
if (alpha <= 0.0f) if (alpha <= 0.0f)
return false; return false;
@ -1254,7 +1254,7 @@ void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* over
const ImGuiStyle& style = g.Style; const ImGuiStyle& style = g.Style;
ImVec2 pos = window->DC.CursorPos; ImVec2 pos = window->DC.CursorPos;
ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y * 2.0f); ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), g.FontLineHeight + style.FramePadding.y * 2.0f);
ImRect bb(pos, pos + size); ImRect bb(pos, pos + size);
ItemSize(size, style.FramePadding.y); ItemSize(size, style.FramePadding.y);
if (!ItemAdd(bb, 0)) if (!ItemAdd(bb, 0))
@ -1288,7 +1288,7 @@ void ImGui::Bullet()
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style; const ImGuiStyle& style = g.Style;
const float line_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y * 2), g.FontSize); const float line_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontLineHeight + g.Style.FramePadding.y * 2), g.FontLineHeight);
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize, line_height)); const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize, line_height));
ItemSize(bb); ItemSize(bb);
if (!ItemAdd(bb, 0)) if (!ItemAdd(bb, 0))
@ -1347,7 +1347,7 @@ void ImGui::NewLine()
if (window->DC.CurrLineSize.y > 0.0f) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height. if (window->DC.CurrLineSize.y > 0.0f) // In the event that we are on a line with items that is smaller that FontSize high, we will preserve its height.
ItemSize(ImVec2(0, 0)); ItemSize(ImVec2(0, 0));
else else
ItemSize(ImVec2(0.0f, g.FontSize)); ItemSize(ImVec2(0.0f, g.FontLineHeight));
window->DC.LayoutType = backup_layout_type; window->DC.LayoutType = backup_layout_type;
} }
@ -1358,7 +1358,7 @@ void ImGui::AlignTextToFramePadding()
return; return;
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
window->DC.CurrLineSize.y = ImMax(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y * 2); window->DC.CurrLineSize.y = ImMax(window->DC.CurrLineSize.y, g.FontLineHeight + g.Style.FramePadding.y * 2);
window->DC.CurrLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, g.Style.FramePadding.y); window->DC.CurrLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, g.Style.FramePadding.y);
} }
@ -1573,7 +1573,7 @@ static float CalcMaxPopupHeightFromItemCount(int items_count)
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (items_count <= 0) if (items_count <= 0)
return FLT_MAX; return FLT_MAX;
return (g.FontSize + g.Style.ItemSpacing.y) * items_count - g.Style.ItemSpacing.y + (g.Style.WindowPadding.y * 2); return (g.FontLineHeight + g.Style.ItemSpacing.y) * items_count - g.Style.ItemSpacing.y + (g.Style.WindowPadding.y * 2);
} }
bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags) bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags)
@ -3634,8 +3634,8 @@ static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* t
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImFont* font = g.Font; ImFont* font = g.Font;
const float line_height = g.FontSize; const float line_height = g.FontLineHeight;
const float scale = line_height / font->FontSize; const float scale = g.FontSize / font->FontSize;
ImVec2 text_size = ImVec2(0, 0); ImVec2 text_size = ImVec2(0, 0);
float line_width = 0.0f; float line_width = 0.0f;
@ -3989,7 +3989,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
BeginGroup(); BeginGroup();
const ImGuiID id = window->GetID(label); const ImGuiID id = window->GetID(label);
const ImVec2 label_size = CalcTextSize(label, NULL, true); const ImVec2 label_size = CalcTextSize(label, NULL, true);
const ImVec2 frame_size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? g.FontSize * 8.0f : label_size.y) + style.FramePadding.y * 2.0f); // Arbitrary default of 8 lines high for multi-line const ImVec2 frame_size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? g.FontLineHeight * 8.0f : label_size.y) + style.FramePadding.y * 2.0f); // Arbitrary default of 8 lines high for multi-line
const ImVec2 total_size = ImVec2(frame_size.x + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), frame_size.y); const ImVec2 total_size = ImVec2(frame_size.x + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), frame_size.y);
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
@ -4195,7 +4195,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Edit in progress // Edit in progress
const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX; const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX;
const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y) : (g.FontSize * 0.5f)); const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y) : (g.FontLineHeight * 0.5f));
const bool is_osx = io.ConfigMacOSXBehaviors; const bool is_osx = io.ConfigMacOSXBehaviors;
if (select_all) if (select_all)
@ -4294,7 +4294,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
IM_ASSERT(state != NULL); IM_ASSERT(state != NULL);
IM_ASSERT(io.KeyMods == GetMergedKeyModFlags() && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods"); // We rarely do this check, but if anything let's do it here. IM_ASSERT(io.KeyMods == GetMergedKeyModFlags() && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods"); // We rarely do this check, but if anything let's do it here.
const int row_count_per_page = ImMax((int)((inner_size.y - style.FramePadding.y) / g.FontSize), 1); const int row_count_per_page = ImMax((int)((inner_size.y - style.FramePadding.y) / g.FontLineHeight), 1);
state->Stb.row_count_per_page = row_count_per_page; state->Stb.row_count_per_page = row_count_per_page;
const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0); const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0);
@ -4319,10 +4319,10 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); } if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); } else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); } else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontLineHeight, 0.0f)); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); } else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontLineHeight, GetScrollMaxY())); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_PageUp) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGUP | k_mask); scroll_y -= row_count_per_page * g.FontSize; } else if (IsKeyPressedMap(ImGuiKey_PageUp) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGUP | k_mask); scroll_y -= row_count_per_page * g.FontLineHeight; }
else if (IsKeyPressedMap(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontSize; } else if (IsKeyPressedMap(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontLineHeight; }
else if (IsKeyPressedMap(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); } else if (IsKeyPressedMap(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); } else if (IsKeyPressedMap(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly && !is_cut) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); } else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly && !is_cut) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
@ -4665,16 +4665,16 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Calculate 2d position by finding the beginning of the line and measuring distance // Calculate 2d position by finding the beginning of the line and measuring distance
cursor_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x; cursor_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[0], text_begin), searches_input_ptr[0]).x;
cursor_offset.y = searches_result_line_no[0] * g.FontSize; cursor_offset.y = searches_result_line_no[0] * g.FontLineHeight;
if (searches_result_line_no[1] >= 0) if (searches_result_line_no[1] >= 0)
{ {
select_start_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x; select_start_offset.x = InputTextCalcTextSizeW(ImStrbolW(searches_input_ptr[1], text_begin), searches_input_ptr[1]).x;
select_start_offset.y = searches_result_line_no[1] * g.FontSize; select_start_offset.y = searches_result_line_no[1] * g.FontLineHeight;
} }
// Store text height (note that we haven't calculated text width at all, see GitHub issues #383, #1224) // Store text height (note that we haven't calculated text width at all, see GitHub issues #383, #1224)
if (is_multiline) if (is_multiline)
text_size = ImVec2(inner_size.x, line_count * g.FontSize); text_size = ImVec2(inner_size.x, line_count * g.FontLineHeight);
} }
// Scroll // Scroll
@ -4699,8 +4699,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (is_multiline) if (is_multiline)
{ {
// Test if cursor is vertically visible // Test if cursor is vertically visible
if (cursor_offset.y - g.FontSize < scroll_y) if (cursor_offset.y - g.FontLineHeight < scroll_y)
scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize); scroll_y = ImMax(0.0f, cursor_offset.y - g.FontLineHeight);
else if (cursor_offset.y - (inner_size.y - style.FramePadding.y * 2.0f) >= scroll_y) else if (cursor_offset.y - (inner_size.y - style.FramePadding.y * 2.0f) >= scroll_y)
scroll_y = cursor_offset.y - inner_size.y + style.FramePadding.y * 2.0f; scroll_y = cursor_offset.y - inner_size.y + style.FramePadding.y * 2.0f;
const float scroll_max_y = ImMax((text_size.y + style.FramePadding.y * 2.0f) - inner_size.y, 0.0f); const float scroll_max_y = ImMax((text_size.y + style.FramePadding.y * 2.0f) - inner_size.y, 0.0f);
@ -4725,7 +4725,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
ImVec2 rect_pos = draw_pos + select_start_offset - draw_scroll; ImVec2 rect_pos = draw_pos + select_start_offset - draw_scroll;
for (const ImWchar* p = text_selected_begin; p < text_selected_end; ) for (const ImWchar* p = text_selected_begin; p < text_selected_end; )
{ {
if (rect_pos.y > clip_rect.w + g.FontSize) if (rect_pos.y > clip_rect.w + g.FontLineHeight)
break; break;
if (rect_pos.y < clip_rect.y) if (rect_pos.y < clip_rect.y)
{ {
@ -4739,13 +4739,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
{ {
ImVec2 rect_size = InputTextCalcTextSizeW(p, text_selected_end, &p, NULL, true); ImVec2 rect_size = InputTextCalcTextSizeW(p, text_selected_end, &p, NULL, true);
if (rect_size.x <= 0.0f) rect_size.x = IM_FLOOR(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines if (rect_size.x <= 0.0f) rect_size.x = IM_FLOOR(g.Font->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines
ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos + ImVec2(rect_size.x, bg_offy_dn)); ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontLineHeight), rect_pos + ImVec2(rect_size.x, bg_offy_dn));
rect.ClipWith(clip_rect); rect.ClipWith(clip_rect);
if (rect.Overlaps(clip_rect)) if (rect.Overlaps(clip_rect))
draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color); draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color);
} }
rect_pos.x = draw_pos.x - draw_scroll.x; rect_pos.x = draw_pos.x - draw_scroll.x;
rect_pos.y += g.FontSize; rect_pos.y += g.FontLineHeight;
} }
} }
@ -4753,7 +4753,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length) if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
{ {
ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text); ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect); draw_window->DrawList->AddText(g.Font, g.FontSize, g.FontLineHeight, g.FontBaselineOffset, draw_pos - draw_scroll, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);
} }
// Draw blinking cursor // Draw blinking cursor
@ -4762,23 +4762,20 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
state->CursorAnim += io.DeltaTime; state->CursorAnim += io.DeltaTime;
bool cursor_is_visible = (!g.IO.ConfigInputTextCursorBlink) || (state->CursorAnim <= 0.0f) || ImFmod(state->CursorAnim, 1.20f) <= 0.80f; bool cursor_is_visible = (!g.IO.ConfigInputTextCursorBlink) || (state->CursorAnim <= 0.0f) || ImFmod(state->CursorAnim, 1.20f) <= 0.80f;
ImVec2 cursor_screen_pos = ImFloor(draw_pos + cursor_offset - draw_scroll); ImVec2 cursor_screen_pos = ImFloor(draw_pos + cursor_offset - draw_scroll);
ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f); ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontLineHeight + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - g.FontLineHeight+ g.FontLineHeight - 1.5f);
if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect)) if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text)); draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text));
// Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.) // Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
if (!is_readonly) if (!is_readonly)
{ g.PlatformImePos = ImVec2(cursor_screen_pos.x - 1.0f, cursor_screen_pos.y - g.FontLineHeight);
g.PlatformImePos = ImVec2(cursor_screen_pos.x - 1, cursor_screen_pos.y - g.FontSize);
g.PlatformImePosViewport = window->Viewport;
}
} }
} }
else else
{ {
// Render text only (no selection, no cursor) // Render text only (no selection, no cursor)
if (is_multiline) if (is_multiline)
text_size = ImVec2(inner_size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_display_end) * g.FontSize); // We don't need width text_size = ImVec2(inner_size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_display_end) * g.FontLineHeight); // We don't need width
else if (!is_displaying_hint && g.ActiveId == id) else if (!is_displaying_hint && g.ActiveId == id)
buf_display_end = buf_display + state->CurLenA; buf_display_end = buf_display + state->CurLenA;
else if (!is_displaying_hint) else if (!is_displaying_hint)
@ -4787,7 +4784,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length) if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
{ {
ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text); ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect); draw_window->DrawList->AddText(g.Font, g.FontSize, g.FontLineHeight, g.FontBaselineOffset, draw_pos, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);
} }
} }
@ -5625,7 +5622,7 @@ void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags
Separator(); Separator();
} }
ImVec2 sz(g.FontSize * 3 + g.Style.FramePadding.y * 2, g.FontSize * 3 + g.Style.FramePadding.y * 2); ImVec2 sz(g.FontSize * 3 + g.Style.FramePadding.y * 2, g.FontLineHeight * 3 + g.Style.FramePadding.y * 2);
ImVec4 cf(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); ImVec4 cf(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]);
int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]); int cr = IM_F32_TO_INT8_SAT(col[0]), cg = IM_F32_TO_INT8_SAT(col[1]), cb = IM_F32_TO_INT8_SAT(col[2]), ca = (flags & ImGuiColorEditFlags_NoAlpha) ? 255 : IM_F32_TO_INT8_SAT(col[3]);
ColorButton("##preview", cf, (flags & (ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)) | ImGuiColorEditFlags_NoTooltip, sz); ColorButton("##preview", cf, (flags & (ImGuiColorEditFlags_InputMask_ | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)) | ImGuiColorEditFlags_NoTooltip, sz);
@ -5707,7 +5704,7 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (allow_opt_picker) if (allow_opt_picker)
{ {
ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (GetFrameHeight() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontLineHeight * 8 - (GetFrameHeight() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function
PushItemWidth(picker_size.x); PushItemWidth(picker_size.x);
for (int picker_type = 0; picker_type < 2; picker_type++) for (int picker_type = 0; picker_type < 2; picker_type++)
{ {
@ -5898,7 +5895,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
const ImVec2 label_size = CalcTextSize(label, label_end, false); const ImVec2 label_size = CalcTextSize(label, label_end, false);
// We vertically grow up to current line height up the typical widget height. // We vertically grow up to current line height up the typical widget height.
const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y * 2), label_size.y + padding.y * 2); const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontLineHeight + style.FramePadding.y * 2), label_size.y + padding.y * 2);
ImRect frame_bb; ImRect frame_bb;
frame_bb.Min.x = (flags & ImGuiTreeNodeFlags_SpanFullWidth) ? window->WorkRect.Min.x : window->DC.CursorPos.x; frame_bb.Min.x = (flags & ImGuiTreeNodeFlags_SpanFullWidth) ? window->WorkRect.Min.x : window->DC.CursorPos.x;
frame_bb.Min.y = window->DC.CursorPos.y; frame_bb.Min.y = window->DC.CursorPos.y;
@ -5912,9 +5909,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
frame_bb.Max.x += IM_FLOOR(window->WindowPadding.x * 0.5f); frame_bb.Max.x += IM_FLOOR(window->WindowPadding.x * 0.5f);
} }
const float text_offset_x = g.FontSize + (display_frame ? padding.x * 3 : padding.x * 2); // Collapser arrow width + Spacing const float text_offset_x = g.FontLineHeight + (display_frame ? padding.x * 3 : padding.x * 2); // Collapser arrow width + Spacing
const float text_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it const float text_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it
const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x * 2 : 0.0f); // Include collapser const float text_width = g.FontLineHeight + (label_size.x > 0.0f ? label_size.x + padding.x * 2 : 0.0f); // Include collapser
ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y); ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y);
ItemSize(ImVec2(text_width, frame_height), padding.y); ItemSize(ImVec2(text_width, frame_height), padding.y);
@ -6033,7 +6030,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding); RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding);
RenderNavHighlight(frame_bb, id, nav_highlight_flags); RenderNavHighlight(frame_bb, id, nav_highlight_flags);
if (flags & ImGuiTreeNodeFlags_Bullet) if (flags & ImGuiTreeNodeFlags_Bullet)
RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col); RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontLineHeight * 0.5f), text_col);
else if (!is_leaf) else if (!is_leaf)
RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f); RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f);
else // Leaf without bullet, left-adjusted text else // Leaf without bullet, left-adjusted text
@ -6055,9 +6052,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
} }
RenderNavHighlight(frame_bb, id, nav_highlight_flags); RenderNavHighlight(frame_bb, id, nav_highlight_flags);
if (flags & ImGuiTreeNodeFlags_Bullet) if (flags & ImGuiTreeNodeFlags_Bullet)
RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col); RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontLineHeight * 0.5f), text_col);
else if (!is_leaf) else if (!is_leaf)
RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize * 0.15f), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f); RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontLineHeight * 0.15f), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f);
if (g.LogEnabled) if (g.LogEnabled)
LogSetNextTextDecoration(">", NULL); LogSetNextTextDecoration(">", NULL);
RenderText(text_pos, label, label_end, false); RenderText(text_pos, label, label_end, false);
@ -6170,7 +6167,7 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFl
// FIXME: CloseButton can overlap into text, need find a way to clip the text somehow. // FIXME: CloseButton can overlap into text, need find a way to clip the text somehow.
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiLastItemData last_item_backup = g.LastItemData; ImGuiLastItemData last_item_backup = g.LastItemData;
float button_size = g.FontSize; float button_size = g.FontLineHeight;
float button_x = ImMax(g.LastItemData.Rect.Min.x, g.LastItemData.Rect.Max.x - g.Style.FramePadding.x * 2.0f - button_size); float button_x = ImMax(g.LastItemData.Rect.Min.x, g.LastItemData.Rect.Max.x - g.Style.FramePadding.x * 2.0f - button_size);
float button_y = g.LastItemData.Rect.Min.y; float button_y = g.LastItemData.Rect.Min.y;
ImGuiID close_button_id = GetIDWithSeed("#CLOSE", NULL, id); ImGuiID close_button_id = GetIDWithSeed("#CLOSE", NULL, id);
@ -6998,7 +6995,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
ImGuiWindow* child_menu_window = (g.BeginPopupStack.Size < g.OpenPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].SourceWindow == window) ? g.OpenPopupStack[g.BeginPopupStack.Size].Window : NULL; ImGuiWindow* child_menu_window = (g.BeginPopupStack.Size < g.OpenPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].SourceWindow == window) ? g.OpenPopupStack[g.BeginPopupStack.Size].Window : NULL;
if (g.HoveredWindow == window && child_menu_window != NULL && !(window->Flags & ImGuiWindowFlags_MenuBar)) if (g.HoveredWindow == window && child_menu_window != NULL && !(window->Flags & ImGuiWindowFlags_MenuBar))
{ {
float ref_unit = g.FontSize; // FIXME-DPI float ref_unit = g.FontLineHeight; // FIXME-DPI
ImRect next_window_rect = child_menu_window->Rect(); ImRect next_window_rect = child_menu_window->Rect();
ImVec2 ta = (g.IO.MousePos - g.IO.MouseDelta); ImVec2 ta = (g.IO.MousePos - g.IO.MouseDelta);
ImVec2 tb = (window->Pos.x < child_menu_window->Pos.x) ? next_window_rect.GetTL() : next_window_rect.GetTR(); ImVec2 tb = (window->Pos.x < child_menu_window->Pos.x) ? next_window_rect.GetTL() : next_window_rect.GetTR();
@ -7158,7 +7155,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
PopStyleColor(); PopStyleColor();
} }
if (selected) if (selected)
RenderCheckMark(window->DrawList, pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f); RenderCheckMark(window->DrawList, pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontLineHeight * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f);
} }
IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0)); IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0));
if (!enabled) if (!enabled)
@ -7279,7 +7276,7 @@ bool ImGui::BeginTabBar(const char* str_id, ImGuiTabBarFlags flags)
ImGuiID id = window->GetID(str_id); ImGuiID id = window->GetID(str_id);
ImGuiTabBar* tab_bar = g.TabBars.GetOrAddByKey(id); ImGuiTabBar* tab_bar = g.TabBars.GetOrAddByKey(id);
ImRect tab_bar_bb = ImRect(window->DC.CursorPos.x, window->DC.CursorPos.y, window->WorkRect.Max.x, window->DC.CursorPos.y + g.FontSize + g.Style.FramePadding.y * 2); ImRect tab_bar_bb = ImRect(window->DC.CursorPos.x, window->DC.CursorPos.y, window->WorkRect.Max.x, window->DC.CursorPos.y + g.FontLineHeight + g.Style.FramePadding.y * 2);
tab_bar->ID = id; tab_bar->ID = id;
return BeginTabBarEx(tab_bar, tab_bar_bb, flags | ImGuiTabBarFlags_IsFocused, NULL); return BeginTabBarEx(tab_bar, tab_bar_bb, flags | ImGuiTabBarFlags_IsFocused, NULL);
} }
@ -7605,9 +7602,9 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
{ {
// Scrolling speed adjust itself so we can always reach our target in 1/3 seconds. // Scrolling speed adjust itself so we can always reach our target in 1/3 seconds.
// Teleport if we are aiming far off the visible line // Teleport if we are aiming far off the visible line
tab_bar->ScrollingSpeed = ImMax(tab_bar->ScrollingSpeed, 70.0f * g.FontSize); tab_bar->ScrollingSpeed = ImMax(tab_bar->ScrollingSpeed, 70.0f * g.FontLineHeight);
tab_bar->ScrollingSpeed = ImMax(tab_bar->ScrollingSpeed, ImFabs(tab_bar->ScrollingTarget - tab_bar->ScrollingAnim) / 0.3f); tab_bar->ScrollingSpeed = ImMax(tab_bar->ScrollingSpeed, ImFabs(tab_bar->ScrollingTarget - tab_bar->ScrollingAnim) / 0.3f);
const bool teleport = (tab_bar->PrevFrameVisible + 1 < g.FrameCount) || (tab_bar->ScrollingTargetDistToVisibility > 10.0f * g.FontSize); const bool teleport = (tab_bar->PrevFrameVisible + 1 < g.FrameCount) || (tab_bar->ScrollingTargetDistToVisibility > 10.0f * g.FontLineHeight);
tab_bar->ScrollingAnim = teleport ? tab_bar->ScrollingTarget : ImLinearSweep(tab_bar->ScrollingAnim, tab_bar->ScrollingTarget, g.IO.DeltaTime * tab_bar->ScrollingSpeed); tab_bar->ScrollingAnim = teleport ? tab_bar->ScrollingTarget : ImLinearSweep(tab_bar->ScrollingAnim, tab_bar->ScrollingTarget, g.IO.DeltaTime * tab_bar->ScrollingSpeed);
} }
else else
@ -7846,7 +7843,7 @@ static ImGuiTabItem* ImGui::TabBarScrollingButtons(ImGuiTabBar* tab_bar)
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
const ImVec2 arrow_button_size(g.FontSize - 2.0f, g.FontSize + g.Style.FramePadding.y * 2.0f); const ImVec2 arrow_button_size(g.FontSize - 2.0f, g.FontLineHeight + g.Style.FramePadding.y * 2.0f);
const float scrolling_buttons_width = arrow_button_size.x * 2.0f; const float scrolling_buttons_width = arrow_button_size.x * 2.0f;
const ImVec2 backup_cursor_pos = window->DC.CursorPos; const ImVec2 backup_cursor_pos = window->DC.CursorPos;
@ -7908,7 +7905,7 @@ static ImGuiTabItem* ImGui::TabBarTabListPopupButton(ImGuiTabBar* tab_bar)
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
// We use g.Style.FramePadding.y to match the square ArrowButton size // We use g.Style.FramePadding.y to match the square ArrowButton size
const float tab_list_popup_button_width = g.FontSize + g.Style.FramePadding.y; const float tab_list_popup_button_width = g.FontLineHeight + g.Style.FramePadding.y;
const ImVec2 backup_cursor_pos = window->DC.CursorPos; const ImVec2 backup_cursor_pos = window->DC.CursorPos;
window->DC.CursorPos = ImVec2(tab_bar->BarRect.Min.x - g.Style.FramePadding.y, tab_bar->BarRect.Min.y); window->DC.CursorPos = ImVec2(tab_bar->BarRect.Min.x - g.Style.FramePadding.y, tab_bar->BarRect.Min.y);
tab_bar->BarRect.Min.x += tab_list_popup_button_width; tab_bar->BarRect.Min.x += tab_list_popup_button_width;