Merge branch 'master' into docking

# Conflicts:
#	imgui.cpp
This commit is contained in:
ocornut
2025-05-30 22:00:26 +02:00
7 changed files with 86 additions and 27 deletions

View File

@@ -43,6 +43,12 @@ Breaking changes:
- TreeNode: renamed ImGuiTreeNodeFlags_NavLeftJumpsBackHere to ImGuiTreeNodeFlags_NavLeftJumpsToParent - TreeNode: renamed ImGuiTreeNodeFlags_NavLeftJumpsBackHere to ImGuiTreeNodeFlags_NavLeftJumpsToParent
for clarity. Kept inline redirection enum (will obsolete). (#1079, #8639) for clarity. Kept inline redirection enum (will obsolete). (#1079, #8639)
- Fonts: changed ImFont::CalcWordWrapPositionA() to ImFont::CalcWordWrapPosition():
- old: const char* CalcWordWrapPositionA(float scale, const char* text, ....);
- new: const char* CalcWordWrapPosition (float size, const char* text, ....);
The leading 'float scale' parameters was changed to 'float size'.
This was necessary as 'scale' is assuming standard font size which is a concept we aim to
eliminate in an upcoming update. Kept inline redirection function.
- Commented out PushAllowKeyboardFocus()/PopAllowKeyboardFocus() which was obsoleted - Commented out PushAllowKeyboardFocus()/PopAllowKeyboardFocus() which was obsoleted
in 1.89.4 (March 2023). (#3092) in 1.89.4 (March 2023). (#3092)
- PushAllowKeyboardFocus(bool tab_stop) --> PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop); - PushAllowKeyboardFocus(bool tab_stop) --> PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop);
@@ -51,7 +57,9 @@ Breaking changes:
in 1.89.6 (June 2023). in 1.89.6 (June 2023).
- ForceDisplayRangeByIndices() --> IncludeItemsByIndex() - ForceDisplayRangeByIndices() --> IncludeItemsByIndex()
- Backends: SDL3: Fixed casing typo in function name: (#8509, #8163, #7998, #7988) [@puugz] - Backends: SDL3: Fixed casing typo in function name: (#8509, #8163, #7998, #7988) [@puugz]
- Imgui_ImplSDLGPU3_PrepareDrawData() -> ImGui_ImplSDLGPU3_PrepareDrawData() - Imgui_ImplSDLGPU3_PrepareDrawData() --> ImGui_ImplSDLGPU3_PrepareDrawData()
- Internals: RenderTextEllipsis() function removed the 'float clip_max_x' parameter directly
preceding 'float ellipsis_max_x'. Values were identical for a vast majority of users. (#8387)
Other changes: Other changes:
@@ -97,8 +105,16 @@ Other changes:
which mitigates edge case issues in multi-viewport scenarios where abnormally large which mitigates edge case issues in multi-viewport scenarios where abnormally large
windows (e.g. determined programmatically) can lead to renderer backend trying to windows (e.g. determined programmatically) can lead to renderer backend trying to
create abnormally large framebuffers. create abnormally large framebuffers.
- TextLinkOpenURL(): added bool return value on click. (#8645, #8451, #7660)
- Scroll: fixed contents size, scrollbar visibility and scrolling resetting issues
with abnormally large contents ranges. (#3609, #8215)
- Clipper: some mitigation/improvements for abnormally large contents ranges. (#3609, #8215)
- Nav: fixed assertion when holding gamepad FaceLeft/West button to open - Nav: fixed assertion when holding gamepad FaceLeft/West button to open
CTRL+Tab windowing + pressing a keyboard key. (#8525) CTRL+Tab windowing + pressing a keyboard key. (#8525)
- Nav: fixed scroll fallback (when there are no interactive widgets to jump to) not
being enabled on windows with menu or title bar.
- Nav: fixed an issue handling PageUp/PageDown on windows with abnormally large contents
range which could lead to clipper requesting very large ranges.
- Error Handling: added better error report and recovery for extraneous - Error Handling: added better error report and recovery for extraneous
EndPopup() call. (#1651, #8499) EndPopup() call. (#1651, #8499)
- Error Handling: added better error report and recovery when calling EndFrame() - Error Handling: added better error report and recovery when calling EndFrame()
@@ -106,7 +122,7 @@ Other changes:
- Fonts: reworked text ellipsis logic to ensure a "..." is always displayed instead - Fonts: reworked text ellipsis logic to ensure a "..." is always displayed instead
of a single character. (#7024) of a single character. (#7024)
- Fonts: word-wrapping code handle ideographic comma & full stop (U+3001, U+3002). (#8540) - Fonts: word-wrapping code handle ideographic comma & full stop (U+3001, U+3002). (#8540)
- Fonts: fixed CalcWordWrapPositionA() fallback when width is too small to wrap: - Fonts: fixed CalcWordWrapPosition() fallback when width is too small to wrap:
would use a +1 offset instead of advancing to the next UTF-8 codepoint. (#8540) would use a +1 offset instead of advancing to the next UTF-8 codepoint. (#8540)
- Style, InputText: added ImGuiCol_InputTextCursor to configure color of - Style, InputText: added ImGuiCol_InputTextCursor to configure color of
the InputText cursor/caret. (#7031) the InputText cursor/caret. (#7031)
@@ -276,6 +292,7 @@ Other changes:
- Debug Tools: Added io.ConfigDebugHighlightIdConflictsShowItemPicker (defaults to true) - Debug Tools: Added io.ConfigDebugHighlightIdConflictsShowItemPicker (defaults to true)
to allow disabled Item Picker suggestion in user facing builds. (#7961, #7669) to allow disabled Item Picker suggestion in user facing builds. (#7961, #7669)
- Debug Tools: Tweaked layout of ID Stack Tool and always display full path. (#4631) - Debug Tools: Tweaked layout of ID Stack Tool and always display full path. (#4631)
- imgui_freetype: update lunasvg API to support v3.0+. (#8656, #6842, #6591) [@moretromain]
- Misc: Various zealous warning fixes for newer version of Clang. - Misc: Various zealous warning fixes for newer version of Clang.
- Misc: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursors - Misc: Added ImGuiMouseCursor_Wait and ImGuiMouseCursor_Progress mouse cursors
(busy/wait/hourglass shape, with or without an arrow cursor). (busy/wait/hourglass shape, with or without an arrow cursor).

View File

@@ -440,10 +440,15 @@ CODE
- likewise io.MousePos and GetMousePos() will use OS coordinates. - likewise io.MousePos and GetMousePos() will use OS coordinates.
If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos. If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos.
- 2025/05/23 (1.92.0) - Fonts: changed ImFont::CalcWordWrapPositionA() to ImFont::CalcWordWrapPosition()
- old: const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, ....);
- new: const char* ImFont::CalcWordWrapPosition (float size, const char* text, ....);
The leading 'float scale' parameters was changed to 'float size'. This was necessary as 'scale' is assuming standard font size which is a concept we aim to eliminate in an upcoming update. Kept inline redirection function.
- 2025/05/15 (1.92.0) - TreeNode: renamed ImGuiTreeNodeFlags_NavLeftJumpsBackHere to ImGuiTreeNodeFlags_NavLeftJumpsToParent for clarity. Kept inline redirection enum (will obsolete). - 2025/05/15 (1.92.0) - TreeNode: renamed ImGuiTreeNodeFlags_NavLeftJumpsBackHere to ImGuiTreeNodeFlags_NavLeftJumpsToParent for clarity. Kept inline redirection enum (will obsolete).
- 2025/05/15 (1.92.0) - Commented out PushAllowKeyboardFocus()/PopAllowKeyboardFocus() which was obsoleted in 1.89.4. Use PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop)/PopItemFlag() instead. (#3092) - 2025/05/15 (1.92.0) - Commented out PushAllowKeyboardFocus()/PopAllowKeyboardFocus() which was obsoleted in 1.89.4. Use PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop)/PopItemFlag() instead. (#3092)
- 2025/05/15 (1.92.0) - Commented out ImGuiListClipper::ForceDisplayRangeByIndices() which was obsoleted in 1.89.6. Use ImGuiListClipper::IncludeItemsByIndex() instead. - 2025/05/15 (1.92.0) - Commented out ImGuiListClipper::ForceDisplayRangeByIndices() which was obsoleted in 1.89.6. Use ImGuiListClipper::IncludeItemsByIndex() instead.
- 2025/03/05 (1.91.9) - BeginMenu(): Internals: reworked mangling of menu windows to use "###Menu_00" etc. instead of "##Menu_00", allowing them to also store the menu name before it. This shouldn't affect code unless directly accessing menu window from their mangled name. - 2025/03/05 (1.91.9) - BeginMenu(): Internals: reworked mangling of menu windows to use "###Menu_00" etc. instead of "##Menu_00", allowing them to also store the menu name before it. This shouldn't affect code unless directly accessing menu window from their mangled name.
- 2025/04/16 (1.91.9) - Internals: RenderTextEllipsis() function removed the 'float clip_max_x' parameter directly preceding 'float ellipsis_max_x'. Values were identical for a vast majority of users. (#8387)
- 2025/02/27 (1.91.9) - Image(): removed 'tint_col' and 'border_col' parameter from Image() function. Added ImageWithBg() replacement. (#8131, #8238) - 2025/02/27 (1.91.9) - Image(): removed 'tint_col' and 'border_col' parameter from Image() function. Added ImageWithBg() replacement. (#8131, #8238)
- old: void Image (ImTextureID tex_id, ImVec2 image_size, ImVec2 uv0 = (0,0), ImVec2 uv1 = (1,1), ImVec4 tint_col = (1,1,1,1), ImVec4 border_col = (0,0,0,0)); - old: void Image (ImTextureID tex_id, ImVec2 image_size, ImVec2 uv0 = (0,0), ImVec2 uv1 = (1,1), ImVec4 tint_col = (1,1,1,1), ImVec4 border_col = (0,0,0,0));
- new: void Image (ImTextureID tex_id, ImVec2 image_size, ImVec2 uv0 = (0,0), ImVec2 uv1 = (1,1)); - new: void Image (ImTextureID tex_id, ImVec2 image_size, ImVec2 uv0 = (0,0), ImVec2 uv1 = (1,1));
@@ -3250,10 +3255,17 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
if (table) if (table)
IM_ASSERT(table->RowPosY1 == clipper->StartPosY && table->RowPosY2 == window->DC.CursorPos.y); IM_ASSERT(table->RowPosY1 == clipper->StartPosY && table->RowPosY2 == window->DC.CursorPos.y);
clipper->ItemsHeight = (window->DC.CursorPos.y - clipper->StartPosY) / (float)(clipper->DisplayEnd - clipper->DisplayStart); bool affected_by_floating_point_precision = ImIsFloatAboveGuaranteedIntegerPrecision((float)clipper->StartPosY) || ImIsFloatAboveGuaranteedIntegerPrecision(window->DC.CursorPos.y);
bool affected_by_floating_point_precision = ImIsFloatAboveGuaranteedIntegerPrecision(clipper->StartPosY) || ImIsFloatAboveGuaranteedIntegerPrecision(window->DC.CursorPos.y);
if (affected_by_floating_point_precision) if (affected_by_floating_point_precision)
{
// Mitigation/hack for very large range: assume last time height constitute line height.
clipper->ItemsHeight = window->DC.PrevLineSize.y + g.Style.ItemSpacing.y; // FIXME: Technically wouldn't allow multi-line entries. clipper->ItemsHeight = window->DC.PrevLineSize.y + g.Style.ItemSpacing.y; // FIXME: Technically wouldn't allow multi-line entries.
window->DC.CursorPos.y = (float)(clipper->StartPosY + clipper->ItemsHeight);
}
else
{
clipper->ItemsHeight = (float)(window->DC.CursorPos.y - clipper->StartPosY) / (float)(clipper->DisplayEnd - clipper->DisplayStart);
}
if (clipper->ItemsHeight == 0.0f && clipper->ItemsCount == INT_MAX) // Accept that no item have been submitted if in indeterminate mode. if (clipper->ItemsHeight == 0.0f && clipper->ItemsCount == INT_MAX) // Accept that no item have been submitted if in indeterminate mode.
return false; return false;
IM_ASSERT(clipper->ItemsHeight > 0.0f && "Unable to calculate item height! First item hasn't moved the cursor vertically!"); IM_ASSERT(clipper->ItemsHeight > 0.0f && "Unable to calculate item height! First item hasn't moved the cursor vertically!");
@@ -3277,7 +3289,10 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
// Add range selected to be included for navigation // Add range selected to be included for navigation
const bool is_nav_request = (g.NavMoveScoringItems && g.NavWindow && g.NavWindow->RootWindowForNav == window->RootWindowForNav); const bool is_nav_request = (g.NavMoveScoringItems && g.NavWindow && g.NavWindow->RootWindowForNav == window->RootWindowForNav);
if (is_nav_request) if (is_nav_request)
{
data->Ranges.push_back(ImGuiListClipperRange::FromPositions(g.NavScoringRect.Min.y, g.NavScoringRect.Max.y, 0, 0));
data->Ranges.push_back(ImGuiListClipperRange::FromPositions(g.NavScoringNoClipRect.Min.y, g.NavScoringNoClipRect.Max.y, 0, 0)); data->Ranges.push_back(ImGuiListClipperRange::FromPositions(g.NavScoringNoClipRect.Min.y, g.NavScoringNoClipRect.Max.y, 0, 0));
}
if (is_nav_request && (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) && g.NavTabbingDir == -1) if (is_nav_request && (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) && g.NavTabbingDir == -1)
data->Ranges.push_back(ImGuiListClipperRange::FromIndices(clipper->ItemsCount - 1, clipper->ItemsCount)); data->Ranges.push_back(ImGuiListClipperRange::FromIndices(clipper->ItemsCount - 1, clipper->ItemsCount));
@@ -3766,6 +3781,7 @@ void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, cons
// Another overly complex function until we reorganize everything into a nice all-in-one helper. // Another overly complex function until we reorganize everything into a nice all-in-one helper.
// This is made more complex because we have dissociated the layout rectangle (pos_min..pos_max) from 'ellipsis_max_x' which may be beyond it. // This is made more complex because we have dissociated the layout rectangle (pos_min..pos_max) from 'ellipsis_max_x' which may be beyond it.
// This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move. // This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move.
// (BREAKING) On 2025/04/16 we removed the 'float clip_max_x' parameters which was preceeding 'float ellipsis_max' and was the same value for 99% of users.
void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known) void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@@ -5394,7 +5410,6 @@ void ImGui::NewFrame()
UpdateViewportsNewFrame(); UpdateViewportsNewFrame();
// Setup current font and draw list shared data // Setup current font and draw list shared data
// FIXME-VIEWPORT: the concept of a single ClipRectFullscreen is not ideal!
SetupDrawListSharedData(); SetupDrawListSharedData();
UpdateFontsNewFrame(); UpdateFontsNewFrame();
@@ -6676,10 +6691,10 @@ static void CalcWindowContentSizes(ImGuiWindow* window, ImVec2* content_size_cur
return; return;
} }
content_size_current->x = (window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : IM_TRUNC(window->DC.CursorMaxPos.x - window->DC.CursorStartPos.x); content_size_current->x = (window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : ImTrunc64(window->DC.CursorMaxPos.x - window->DC.CursorStartPos.x);
content_size_current->y = (window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : IM_TRUNC(window->DC.CursorMaxPos.y - window->DC.CursorStartPos.y); content_size_current->y = (window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : ImTrunc64(window->DC.CursorMaxPos.y - window->DC.CursorStartPos.y);
content_size_ideal->x = (window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : IM_TRUNC(ImMax(window->DC.CursorMaxPos.x, window->DC.IdealMaxPos.x) - window->DC.CursorStartPos.x); content_size_ideal->x = (window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : ImTrunc64(ImMax(window->DC.CursorMaxPos.x, window->DC.IdealMaxPos.x) - window->DC.CursorStartPos.x);
content_size_ideal->y = (window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : IM_TRUNC(ImMax(window->DC.CursorMaxPos.y, window->DC.IdealMaxPos.y) - window->DC.CursorStartPos.y); content_size_ideal->y = (window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : ImTrunc64(ImMax(window->DC.CursorMaxPos.y, window->DC.IdealMaxPos.y) - window->DC.CursorStartPos.y);
} }
static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window, const ImVec2& size_contents) static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window, const ImVec2& size_contents)
@@ -11820,7 +11835,7 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window)
} }
scroll[axis] = scroll_target - center_ratio * (window->SizeFull[axis] - decoration_size[axis]); scroll[axis] = scroll_target - center_ratio * (window->SizeFull[axis] - decoration_size[axis]);
} }
scroll[axis] = IM_ROUND(ImMax(scroll[axis], 0.0f)); scroll[axis] = ImRound64(ImMax(scroll[axis], 0.0f));
if (!window->Collapsed && !window->SkipItems) if (!window->Collapsed && !window->SkipItems)
scroll[axis] = ImMin(scroll[axis], window->ScrollMax[axis]); scroll[axis] = ImMin(scroll[axis], window->ScrollMax[axis]);
} }
@@ -14058,7 +14073,7 @@ void ImGui::NavUpdateCreateMoveRequest()
//if (!g.NavScoringNoClipRect.IsInverted()) { GetForegroundDrawList()->AddRect(g.NavScoringNoClipRect.Min, g.NavScoringNoClipRect.Max, IM_COL32(255, 200, 0, 255)); } // [DEBUG] //if (!g.NavScoringNoClipRect.IsInverted()) { GetForegroundDrawList()->AddRect(g.NavScoringNoClipRect.Min, g.NavScoringNoClipRect.Max, IM_COL32(255, 200, 0, 255)); } // [DEBUG]
} }
g.NavScoringRect = scoring_rect; g.NavScoringRect = scoring_rect;
g.NavScoringNoClipRect.Add(scoring_rect); //g.NavScoringNoClipRect.Add(scoring_rect);
} }
void ImGui::NavUpdateCreateTabbingRequest() void ImGui::NavUpdateCreateTabbingRequest()
@@ -14277,7 +14292,7 @@ static float ImGui::NavUpdatePageUpPageDown()
if (g.NavLayer != ImGuiNavLayer_Main) if (g.NavLayer != ImGuiNavLayer_Main)
NavRestoreLayer(ImGuiNavLayer_Main); NavRestoreLayer(ImGuiNavLayer_Main);
if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavWindowHasScrollY) if ((window->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Main)) == 0 && window->DC.NavWindowHasScrollY)
{ {
// Fallback manual-scroll when window has no navigable item // Fallback manual-scroll when window has no navigable item
if (IsKeyPressed(ImGuiKey_PageUp, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner)) if (IsKeyPressed(ImGuiKey_PageUp, ImGuiInputFlags_Repeat, ImGuiKeyOwner_NoOwner))

15
imgui.h
View File

@@ -29,7 +29,7 @@
// Library Version // Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.92.0 WIP" #define IMGUI_VERSION "1.92.0 WIP"
#define IMGUI_VERSION_NUM 19196 #define IMGUI_VERSION_NUM 19197
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch #define IMGUI_HAS_VIEWPORT // Viewport WIP branch
#define IMGUI_HAS_DOCK // Docking WIP branch #define IMGUI_HAS_DOCK // Docking WIP branch
@@ -567,13 +567,14 @@ namespace ImGui
IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-FLT_MIN, 0), const char* overlay = NULL); IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-FLT_MIN, 0), const char* overlay = NULL);
IMGUI_API void Bullet(); // draw a small circle + keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses IMGUI_API void Bullet(); // draw a small circle + keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses
IMGUI_API bool TextLink(const char* label); // hyperlink text button, return true when clicked IMGUI_API bool TextLink(const char* label); // hyperlink text button, return true when clicked
IMGUI_API void TextLinkOpenURL(const char* label, const char* url = NULL); // hyperlink text button, automatically open file/url when clicked IMGUI_API bool TextLinkOpenURL(const char* label, const char* url = NULL); // hyperlink text button, automatically open file/url when clicked
// Widgets: Images // Widgets: Images
// - Read about ImTextureID here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples // - Read about ImTextureID here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
// - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above. // - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above.
// - Image() pads adds style.ImageBorderSize on each side, ImageButton() adds style.FramePadding on each side. // - Image() pads adds style.ImageBorderSize on each side, ImageButton() adds style.FramePadding on each side.
// - ImageButton() draws a background based on regular Button() color + optionally an inner background if specified. // - ImageButton() draws a background based on regular Button() color + optionally an inner background if specified.
// - An obsolete version of Image(), before 1.91.9 (March 2025), had a 'tint_col' parameter which is now supported by the ImageWithBg() function.
IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1)); IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1));
IMGUI_API void ImageWithBg(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); IMGUI_API void ImageWithBg(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1));
IMGUI_API bool ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); IMGUI_API bool ImageButton(const char* str_id, ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1));
@@ -2822,7 +2823,7 @@ struct ImGuiListClipper
int DisplayEnd; // End of items to display (exclusive) int DisplayEnd; // End of items to display (exclusive)
int ItemsCount; // [Internal] Number of items int ItemsCount; // [Internal] Number of items
float ItemsHeight; // [Internal] Height of item after a first step and item submission can calculate it float ItemsHeight; // [Internal] Height of item after a first step and item submission can calculate it
float StartPosY; // [Internal] Cursor position at the time of Begin() or after table frozen rows are all processed double StartPosY; // [Internal] Cursor position at the time of Begin() or after table frozen rows are all processed
double StartSeekOffsetY; // [Internal] Account for frozen rows in a table and initial loss of precision in very large windows. double StartSeekOffsetY; // [Internal] Account for frozen rows in a table and initial loss of precision in very large windows.
void* TempData; // [Internal] Internal data void* TempData; // [Internal] Internal data
@@ -3647,10 +3648,14 @@ 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); // utf8 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); // utf8
IMGUI_API const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width); IMGUI_API const char* CalcWordWrapPosition(float size, const char* text, const char* text_end, float wrap_width);
IMGUI_API void RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, ImWchar c, const ImVec4* cpu_fine_clip = NULL); IMGUI_API void RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, ImWchar c, const ImVec4* cpu_fine_clip = NULL);
IMGUI_API void RenderText(ImDrawList* draw_list, float size, const 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); IMGUI_API void RenderText(ImDrawList* draw_list, float size, const 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);
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
inline const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) { return CalcWordWrapPosition(FontSize * scale, text, text_end, wrap_width); }
#endif
// [Internal] Don't use! // [Internal] Don't use!
IMGUI_API void BuildLookupTable(); IMGUI_API void BuildLookupTable();
IMGUI_API void ClearOutputData(); IMGUI_API void ClearOutputData();
@@ -3907,7 +3912,7 @@ struct ImGuiPlatformImeData
namespace ImGui namespace ImGui
{ {
// OBSOLETED in 1.91.9 (from February 2025) // OBSOLETED in 1.91.9 (from February 2025)
IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col); // <-- border_col was removed in favor of ImGuiCol_ImageBorder. IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col); // <-- 'border_col' was removed in favor of ImGuiCol_ImageBorder. If you use 'tint_col', use ImageWithBg() instead.
// OBSOLETED in 1.91.0 (from July 2024) // OBSOLETED in 1.91.0 (from July 2024)
static inline void PushButtonRepeat(bool repeat) { PushItemFlag(ImGuiItemFlags_ButtonRepeat, repeat); } static inline void PushButtonRepeat(bool repeat) { PushItemFlag(ImGuiItemFlags_ButtonRepeat, repeat); }
static inline void PopButtonRepeat() { PopItemFlag(); } static inline void PopButtonRepeat() { PopItemFlag(); }

View File

@@ -3942,7 +3942,7 @@ static inline const char* CalcWordWrapNextLineStartA(const char* text, const cha
// Simple word-wrapping for English, not full-featured. Please submit failing cases! // Simple word-wrapping for English, not full-featured. Please submit failing cases!
// This will return the next location to wrap from. If no wrapping if necessary, this will fast-forward to e.g. text_end. // This will return the next location to wrap from. If no wrapping if necessary, this will fast-forward to e.g. text_end.
// FIXME: Much possible improvements (don't cut things like "word !", "word!!!" but cut within "word,,,,", more sensible support for punctuations, support for Unicode punctuations, etc.) // FIXME: Much possible improvements (don't cut things like "word !", "word!!!" but cut within "word,,,,", more sensible support for punctuations, support for Unicode punctuations, etc.)
const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const char* ImFont::CalcWordWrapPosition(float size, const char* text, const char* text_end, float wrap_width)
{ {
// For references, possible wrap point marked with ^ // For references, possible wrap point marked with ^
// "aaa bbb, ccc,ddd. eee fff. ggg!" // "aaa bbb, ccc,ddd. eee fff. ggg!"
@@ -3958,6 +3958,7 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c
float line_width = 0.0f; float line_width = 0.0f;
float word_width = 0.0f; float word_width = 0.0f;
float blank_width = 0.0f; float blank_width = 0.0f;
const float scale = size / FontSize;
wrap_width /= scale; // We work with unscaled widths to avoid scaling every characters wrap_width /= scale; // We work with unscaled widths to avoid scaling every characters
const char* word_end = text; const char* word_end = text;
@@ -4061,7 +4062,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons
{ {
// Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature. // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.
if (!word_wrap_eol) if (!word_wrap_eol)
word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - line_width); word_wrap_eol = CalcWordWrapPosition(size, s, text_end, wrap_width - line_width);
if (s >= word_wrap_eol) if (s >= word_wrap_eol)
{ {
@@ -4181,10 +4182,10 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im
const char* line_end = (const char*)ImMemchr(s, '\n', text_end - s); const char* line_end = (const char*)ImMemchr(s, '\n', text_end - s);
if (word_wrap_enabled) if (word_wrap_enabled)
{ {
// FIXME-OPT: This is not optimal as do first do a search for \n before calling CalcWordWrapPositionA(). // FIXME-OPT: This is not optimal as do first do a search for \n before calling CalcWordWrapPosition().
// If the specs for CalcWordWrapPositionA() were reworked to optionally return on \n we could combine both. // If the specs for CalcWordWrapPosition() were reworked to optionally return on \n we could combine both.
// However it is still better than nothing performing the fast-forward! // However it is still better than nothing performing the fast-forward!
s = CalcWordWrapPositionA(scale, s, line_end ? line_end : text_end, wrap_width); s = CalcWordWrapPosition(size, s, line_end ? line_end : text_end, wrap_width);
s = CalcWordWrapNextLineStartA(s, text_end); s = CalcWordWrapNextLineStartA(s, text_end);
} }
else else
@@ -4229,7 +4230,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im
{ {
// Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature. // Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.
if (!word_wrap_eol) if (!word_wrap_eol)
word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - (x - origin_x)); word_wrap_eol = CalcWordWrapPosition(size, s, text_end, wrap_width - (x - origin_x));
if (s >= word_wrap_eol) if (s >= word_wrap_eol)
{ {

View File

@@ -507,6 +507,8 @@ static inline float ImTrunc(float f)
static inline ImVec2 ImTrunc(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); } static inline ImVec2 ImTrunc(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); }
static inline float ImFloor(float f) { return (float)((f >= 0 || (float)(int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf() static inline float ImFloor(float f) { return (float)((f >= 0 || (float)(int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf()
static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2(ImFloor(v.x), ImFloor(v.y)); } static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2(ImFloor(v.x), ImFloor(v.y)); }
static inline float ImTrunc64(float f) { return (float)(ImS64)(f); }
static inline float ImRound64(float f) { return (float)(ImS64)(f + 0.5f); }
static inline int ImModPositive(int a, int b) { return (a + b) % b; } static inline int ImModPositive(int a, int b) { return (a + b) % b; }
static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; } static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); } static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }

View File

@@ -1535,13 +1535,13 @@ bool ImGui::TextLink(const char* label)
return pressed; return pressed;
} }
void ImGui::TextLinkOpenURL(const char* label, const char* url) bool ImGui::TextLinkOpenURL(const char* label, const char* url)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (url == NULL) if (url == NULL)
url = label; url = label;
if (TextLink(label)) bool pressed = TextLink(label);
if (g.PlatformIO.Platform_OpenInShellFn != NULL) if (pressed && g.PlatformIO.Platform_OpenInShellFn != NULL)
g.PlatformIO.Platform_OpenInShellFn(&g, url); g.PlatformIO.Platform_OpenInShellFn(&g, url);
SetItemTooltip(LocalizeGetMsg(ImGuiLocKey_OpenLink_s), url); // It is more reassuring for user to _always_ display URL when we same as label SetItemTooltip(LocalizeGetMsg(ImGuiLocKey_OpenLink_s), url); // It is more reassuring for user to _always_ display URL when we same as label
if (BeginPopupContextItem()) if (BeginPopupContextItem())
@@ -1550,6 +1550,7 @@ void ImGui::TextLinkOpenURL(const char* label, const char* url)
SetClipboardText(url); SetClipboardText(url);
EndPopup(); EndPopup();
} }
return pressed;
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------

View File

@@ -880,8 +880,12 @@ static FT_Error ImGuiLunasvgPortRender(FT_GlyphSlot slot, FT_Pointer* _state)
// rows is height, pitch (or stride) equals to width * sizeof(int32) // rows is height, pitch (or stride) equals to width * sizeof(int32)
lunasvg::Bitmap bitmap((uint8_t*)slot->bitmap.buffer, slot->bitmap.width, slot->bitmap.rows, slot->bitmap.pitch); lunasvg::Bitmap bitmap((uint8_t*)slot->bitmap.buffer, slot->bitmap.width, slot->bitmap.rows, slot->bitmap.pitch);
#if LUNASVG_VERSION_MAJOR >= 3
state->svg->render(bitmap, state->matrix); // state->matrix is already scaled and translated
#else
state->svg->setMatrix(state->svg->matrix().identity()); // Reset the svg matrix to the default value state->svg->setMatrix(state->svg->matrix().identity()); // Reset the svg matrix to the default value
state->svg->render(bitmap, state->matrix); // state->matrix is already scaled and translated state->svg->render(bitmap, state->matrix); // state->matrix is already scaled and translated
#endif
state->err = FT_Err_Ok; state->err = FT_Err_Ok;
return state->err; return state->err;
} }
@@ -904,7 +908,11 @@ static FT_Error ImGuiLunasvgPortPresetSlot(FT_GlyphSlot slot, FT_Bool cache, FT_
return state->err; return state->err;
} }
#if LUNASVG_VERSION_MAJOR >= 3
lunasvg::Box box = state->svg->boundingBox();
#else
lunasvg::Box box = state->svg->box(); lunasvg::Box box = state->svg->box();
#endif
double scale = std::min(metrics.x_ppem / box.w, metrics.y_ppem / box.h); double scale = std::min(metrics.x_ppem / box.w, metrics.y_ppem / box.h);
double xx = (double)document->transform.xx / (1 << 16); double xx = (double)document->transform.xx / (1 << 16);
double xy = -(double)document->transform.xy / (1 << 16); double xy = -(double)document->transform.xy / (1 << 16);
@@ -913,6 +921,15 @@ static FT_Error ImGuiLunasvgPortPresetSlot(FT_GlyphSlot slot, FT_Bool cache, FT_
double x0 = (double)document->delta.x / 64 * box.w / metrics.x_ppem; double x0 = (double)document->delta.x / 64 * box.w / metrics.x_ppem;
double y0 = -(double)document->delta.y / 64 * box.h / metrics.y_ppem; double y0 = -(double)document->delta.y / 64 * box.h / metrics.y_ppem;
#if LUNASVG_VERSION_MAJOR >= 3
// Scale, transform and pre-translate the matrix for the rendering step
state->matrix = lunasvg::Matrix::translated(-box.x, -box.y);
state->matrix.multiply(lunasvg::Matrix(xx, xy, yx, yy, x0, y0));
state->matrix.scale(scale, scale);
// Apply updated transformation to the bounding box
box.transform(state->matrix);
#else
// Scale and transform, we don't translate the svg yet // Scale and transform, we don't translate the svg yet
state->matrix.identity(); state->matrix.identity();
state->matrix.scale(scale, scale); state->matrix.scale(scale, scale);
@@ -924,6 +941,7 @@ static FT_Error ImGuiLunasvgPortPresetSlot(FT_GlyphSlot slot, FT_Bool cache, FT_
// Get the box again after the transformation // Get the box again after the transformation
box = state->svg->box(); box = state->svg->box();
#endif
// Calculate the bitmap size // Calculate the bitmap size
slot->bitmap_left = FT_Int(box.x); slot->bitmap_left = FT_Int(box.x);