From 1da8a52ce7f45b8aebe6e0b53393a322548d5a83 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 11 Feb 2015 12:10:45 +0000 Subject: [PATCH] CalcTextSize*() functions which are often speed bottleneck for large contents are about 25% faster. Caching character advance contiguously, pulled inline, no int->float conversion. --- imgui.cpp | 35 +++++++++++++++++++---------------- imgui.h | 1 + 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 72875c82..5a6fdd4e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -268,6 +268,7 @@ - columns: declare column set (each column: fixed size, %, fill, distribute default size among fills) - columns: columns header to act as button (~sort op) and allow resize/reorder - columns: user specify columns size + - columns: tree node example actually has a small bug (opening node in right column extends the column different from opening node in left column) - combo: turn child handling code into pop up helper - combo: contents should extends to fit label if combo widget is small - listbox: multiple selection @@ -282,7 +283,7 @@ - file selection widget -> build the tool in our codebase to improve model-dialog idioms - slider: allow using the [-]/[+] buttons used by InputFloat()/InputInt() - slider: initial absolute click is imprecise. change to relative movement slider? hide mouse cursor, allow more precise input using less screen-space. - - text edit: clean up the mess caused by converting UTF-8 <> wchar. the code is rather ineficient right now. + - text edit: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now. - text edit: centered text for slider as input text so it matches typical positioning. - text edit: flag to disable live update of the user buffer. - text edit: field resize behavior - field could stretch when being edited? hover tooltip shows more text? @@ -7211,6 +7212,7 @@ void ImFont::Clear() DisplayOffset = ImVec2(-0.5f, 0.5f); ContainerAtlas = NULL; Glyphs.clear(); + IndexXAdvance.clear(); IndexLookup.clear(); FallbackGlyph = NULL; } @@ -7305,12 +7307,21 @@ void ImFont::BuildLookupTable() for (size_t i = 0; i != Glyphs.size(); i++) max_codepoint = ImMax(max_codepoint, (int)Glyphs[i].Codepoint); + IndexXAdvance.clear(); + IndexXAdvance.resize((size_t)max_codepoint + 1); IndexLookup.clear(); IndexLookup.resize((size_t)max_codepoint + 1); - for (size_t i = 0; i < IndexLookup.size(); i++) + for (size_t i = 0; i < (size_t)max_codepoint + 1; i++) + { + IndexXAdvance[i] = 0.0f; IndexLookup[i] = -1; + } for (size_t i = 0; i < Glyphs.size(); i++) - IndexLookup[(int)Glyphs[i].Codepoint] = (int)i; + { + const size_t codepoint = (int)Glyphs[i].Codepoint; + IndexXAdvance[codepoint] = Glyphs[i].XAdvance; + IndexLookup[codepoint] = (int)i; + } // Create a glyph to handle TAB // FIXME: Needs proper TAB handling but it needs to be contextualized (can arbitrary say that each string starts at "column 0" @@ -7321,7 +7332,8 @@ void ImFont::BuildLookupTable() tab_glyph = *space_glyph; tab_glyph.Codepoint = '\t'; tab_glyph.XAdvance *= 4; - IndexLookup[(int)tab_glyph.Codepoint] = (int)(Glyphs.size()-1); + IndexXAdvance[(size_t)tab_glyph.Codepoint] = (float)tab_glyph.XAdvance; + IndexLookup[(size_t)tab_glyph.Codepoint] = (int)(Glyphs.size()-1); } } @@ -7534,10 +7546,7 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c continue; } - float char_width = 0.0f; - if (const Glyph* glyph = FindGlyph((unsigned short)c)) - char_width = glyph->XAdvance * scale; - + const float char_width = ((size_t)c < IndexXAdvance.size()) ? IndexXAdvance[(size_t)c] * scale : 0.0f; if (c == ' ' || c == '\t') { if (inside_word) @@ -7639,10 +7648,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons continue; } - float char_width = 0.0f; - if (const Glyph* glyph = FindGlyph((unsigned short)c)) - char_width = glyph->XAdvance * scale; - + const float char_width = ((size_t)c < IndexXAdvance.size()) ? IndexXAdvance[(size_t)c] * scale : 0.0f; if (line_width + char_width >= max_width) break; @@ -7686,10 +7692,7 @@ ImVec2 ImFont::CalcTextSizeW(float size, float max_width, const ImWchar* text_be continue; } - float char_width = 0.0f; - if (const Glyph* glyph = FindGlyph((unsigned short)c)) - char_width = glyph->XAdvance * scale; - + const float char_width = ((size_t)c < IndexXAdvance.size()) ? IndexXAdvance[(size_t)c] * scale : 0.0f; if (line_width + char_width >= max_width) break; diff --git a/imgui.h b/imgui.h index 3842a60c..95f19b2e 100644 --- a/imgui.h +++ b/imgui.h @@ -910,6 +910,7 @@ struct ImFont }; ImFontAtlas* ContainerAtlas; // What we has been loaded into ImVector Glyphs; + ImVector IndexXAdvance; // Glyphs->XAdvance directly indexable (for CalcTextSize functions which are often bottleneck in large UI) ImVector IndexLookup; // Index glyphs by Unicode code-point const Glyph* FallbackGlyph; // == FindGlyph(FontFallbackChar)