From e0330c1696b8fcb4b5ffb10db27410d02ea5c6d4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 28 Sep 2022 14:54:38 +0200 Subject: [PATCH] Fonts, Text: Fixed wrapped-text not doing a fast-forward on lines above the clipping region. (#5720) which would result in an abnormal number of vertices created. --- docs/CHANGELOG.txt | 3 +++ imgui_draw.cpp | 17 ++++++++++++++--- imgui_internal.h | 2 ++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 596448a0a..d08a9ff32 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -138,6 +138,9 @@ Other Changes: - Nav: Fixed moving/resizing window with gamepad or keyboard when running at very high framerate. - Nav: Pressing Space/GamepadFaceDown on a repeating button uses the same repeating rate as a mouse hold. - Nav: Fixed an issue opening a menu with Right key from a non-menu window. +- Fonts, Text: Fixed wrapped-text not doing a fast-forward on lines above the clipping region, + which would result in an abnormal number of vertices created (was slower and more likely to + asserts with 16-bits ImDrawVtx). (#5720) - Platform IME: [Windows] Removed call to ImmAssociateContextEx() leading to freeze on some setups. (#2589, #5535, #5264, #4972) - Misc: ImGuiKey is now a typed enum, allowing ImGuiKey_XXX symbols to be named in debuggers. (#4921) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index e7eda792b..27fcd6dbc 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -3563,11 +3563,22 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im // Fast-forward to first visible line const char* s = text_begin; - if (y + line_height < clip_rect.y && !word_wrap_enabled) + if (y + line_height < clip_rect.y) while (y + line_height < clip_rect.y && s < text_end) { - s = (const char*)memchr(s, '\n', text_end - s); - s = s ? s + 1 : text_end; + const char* line_end = (const char*)memchr(s, '\n', text_end - s); + if (word_wrap_enabled) + { + // FIXME-OPT: This is not optimal as do first do a search for \n before calling CalcWordWrapPositionA(). + // If the specs for CalcWordWrapPositionA() were reworked to optionally return on \n we could combine both. + // However it is still better than nothing performing the fast-forward! + s = CalcWordWrapPositionA(scale, s, line_end, wrap_width); + s = CalcWordWrapNextLineStartA(s, text_end); + } + else + { + s = line_end ? line_end + 1 : text_end; + } y += line_height; } diff --git a/imgui_internal.h b/imgui_internal.h index 427ebdece..382cd8a08 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -334,8 +334,10 @@ IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* bu IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end); IMGUI_API void ImStrTrimBlanks(char* str); IMGUI_API const char* ImStrSkipBlank(const char* str); +IM_MSVC_RUNTIME_CHECKS_OFF static inline bool ImCharIsBlankA(char c) { return c == ' ' || c == '\t'; } static inline bool ImCharIsBlankW(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; } +IM_MSVC_RUNTIME_CHECKS_RESTORE // Helpers: Formatting IMGUI_API int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) IM_FMTARGS(3);