diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 143168a7..a955d1a8 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -50,6 +50,8 @@ Other Changes: - Scrollbar: Very minor bounding box adjustment to cope with various border size. - ImFontAtlas: FreeType: Added RasterizerFlags::Monochrome flag to disable font anti-aliasing. (#2545) Combine with RasterizerFlags::MonoHinting for best results. +- ImFontGlyphRangesBuilder: Fixed unnecessarily over-sized buffer, which incidentally was also not + fully cleared. Fixed edge case overflow when adding character 0xFFFF. (#2568). [@NIKE3500] - Add native Mac clipboard copy/paste default implementation in core library to match what we are dealing with Win32, and to facilitate integration in custom engines. (#2546) [@andrewwillmott] - Examples/Backends: Don't filter characters under 0x10000 before calling io.AddInputCharacter(), diff --git a/imgui.h b/imgui.h index 75a2ae7f..77fc9c8a 100644 --- a/imgui.h +++ b/imgui.h @@ -1997,12 +1997,13 @@ struct ImFontGlyph // This is essentially a tightly packed of vector of 64k booleans = 8KB storage. struct ImFontGlyphRangesBuilder { - ImVector UsedChars; // Store 1-bit per Unicode code point (0=unused, 1=used) + ImVector UsedChars; // Store 1-bit per Unicode code point (0=unused, 1=used) - ImFontGlyphRangesBuilder() { UsedChars.resize(0x10000 / sizeof(int)); memset(UsedChars.Data, 0, 0x10000 / sizeof(int)); } - bool GetBit(int n) const { int off = (n >> 5); int mask = 1 << (n & 31); return (UsedChars[off] & mask) != 0; } // Get bit n in the array - void SetBit(int n) { int off = (n >> 5); int mask = 1 << (n & 31); UsedChars[off] |= mask; } // Set bit n in the array - void AddChar(ImWchar c) { SetBit(c); } // Add character + ImFontGlyphRangesBuilder() { Clear(); } + inline void Clear() { int size_in_bytes = 0x10000 / 8; UsedChars.resize(size_in_bytes / (int)sizeof(ImU32)); memset(UsedChars.Data, 0, (size_t)size_in_bytes); } + inline bool GetBit(int n) const { int off = (n >> 5); ImU32 mask = 1u << (n & 31); return (UsedChars[off] & mask) != 0; } // Get bit n in the array + inline void SetBit(int n) { int off = (n >> 5); ImU32 mask = 1u << (n & 31); UsedChars[off] |= mask; } // Set bit n in the array + inline void AddChar(ImWchar c) { SetBit(c); } // Add character IMGUI_API void AddText(const char* text, const char* text_end = NULL); // Add string (each character of the UTF-8 string are added) IMGUI_API void AddRanges(const ImWchar* ranges); // Add ranges, e.g. builder.AddRanges(ImFontAtlas::GetGlyphRangesDefault()) to force add all of ASCII/Latin+Ext IMGUI_API void BuildRanges(ImVector* out_ranges); // Output new ranges diff --git a/imgui_draw.cpp b/imgui_draw.cpp index bcea633b..dcbaae06 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2391,11 +2391,12 @@ void ImFontGlyphRangesBuilder::AddRanges(const ImWchar* ranges) void ImFontGlyphRangesBuilder::BuildRanges(ImVector* out_ranges) { - for (int n = 0; n < 0x10000; n++) + int max_codepoint = 0x10000; + for (int n = 0; n < max_codepoint; n++) if (GetBit(n)) { out_ranges->push_back((ImWchar)n); - while (n < 0x10000 && GetBit(n + 1)) + while (n < max_codepoint - 1 && GetBit(n + 1)) n++; out_ranges->push_back((ImWchar)n); }