RenderText(), InputTextMultiline(): Optimization for large text by using memchr, wmemchr, wcschr when appropriate.

This commit is contained in:
omar 2018-10-12 12:34:47 +02:00
parent 0fe48cbb61
commit 9cf94d5dd6
4 changed files with 20 additions and 22 deletions

View File

@ -59,6 +59,7 @@ Other Changes:
introduced in 1.50 and broken in 1.60. (#1698, #894, #713). introduced in 1.50 and broken in 1.60. (#1698, #894, #713).
- TextUnformatted(): Fixed a case where large-text path would read bytes past the text_end marker depending - TextUnformatted(): Fixed a case where large-text path would read bytes past the text_end marker depending
on the position of new lines in the buffer (it wasn't affecting the output but still not the right thing to do!) on the position of new lines in the buffer (it wasn't affecting the output but still not the right thing to do!)
- InputTextMultiline(), RenderText(): Some optimization for very large text buffers, useful for non-optimized builds.
- BeginMenu(): Fixed menu popup horizontal offset being off the item in the menu bar when WindowPadding=0.0f. - BeginMenu(): Fixed menu popup horizontal offset being off the item in the menu bar when WindowPadding=0.0f.
- ArrowButton(): Fixed arrow shape being horizontally misaligned by (FramePadding.y-FramePadding.x) if they are different. - ArrowButton(): Fixed arrow shape being horizontally misaligned by (FramePadding.y-FramePadding.x) if they are different.
- Drag and Drop: Added GetDragDropPayload() to peek directly into the payload (if any) from anywhere. (#143) - Drag and Drop: Added GetDragDropPayload() to peek directly into the payload (if any) from anywhere. (#143)

View File

@ -850,6 +850,7 @@ CODE
#include <ctype.h> // toupper, isprint #include <ctype.h> // toupper, isprint
#include <stdio.h> // vsnprintf, sscanf, printf #include <stdio.h> // vsnprintf, sscanf, printf
#include <wchar.h> // wcslen
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
#include <stddef.h> // intptr_t #include <stddef.h> // intptr_t
#else #else
@ -1210,9 +1211,7 @@ const char* ImStrchrRange(const char* str, const char* str_end, char c)
int ImStrlenW(const ImWchar* str) int ImStrlenW(const ImWchar* str)
{ {
int n = 0; return (int)wcslen((const wchar_t*)str);
while (*str++) n++;
return n;
} }
// Find end-of-line. Return pointer will point to either first \n, either str_end. // Find end-of-line. Return pointer will point to either first \n, either str_end.

View File

@ -2646,11 +2646,11 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
// Fast-forward to first visible line // Fast-forward to first visible line
const char* s = text_begin; const char* s = text_begin;
if (y + line_height < clip_rect.y && !word_wrap_enabled) if (y + line_height < clip_rect.y && !word_wrap_enabled)
while (y + line_height < clip_rect.y) while (y + line_height < clip_rect.y && s < text_end)
{ {
while (s < text_end) s = (const char*)memchr(s, '\n', text_end - s) + 1;
if (*s++ == '\n') if (s == NULL)
break; s = text_end;
y += line_height; y += line_height;
} }
@ -2660,15 +2660,15 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
{ {
const char* s_end = s; const char* s_end = s;
float y_end = y; float y_end = y;
while (y_end < clip_rect.w) while (y_end < clip_rect.w && s_end < text_end)
{ {
while (s_end < text_end) s_end = (const char*)memchr(s_end, '\n', text_end - s_end) + 1;
if (*s_end++ == '\n')
break;
y_end += line_height; y_end += line_height;
} }
text_end = s_end; text_end = s_end;
} }
if (s == text_end)
return;
// Reserve vertices for remaining worse case (over-reserving is useful and easily amortized) // Reserve vertices for remaining worse case (over-reserving is useful and easily amortized)
const int vtx_count_max = (int)(text_end - s) * 4; const int vtx_count_max = (int)(text_end - s) * 4;

View File

@ -36,6 +36,7 @@ Index of this file:
#include "imgui_internal.h" #include "imgui_internal.h"
#include <ctype.h> // toupper, isprint #include <ctype.h> // toupper, isprint
#include <wchar.h> // wmemchr
#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
#include <stddef.h> // intptr_t #include <stddef.h> // intptr_t
#else #else
@ -2906,7 +2907,7 @@ static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos, int n)
obj->CurLenA -= ImTextCountUtf8BytesFromStr(dst, dst + n); obj->CurLenA -= ImTextCountUtf8BytesFromStr(dst, dst + n);
obj->CurLenW -= n; obj->CurLenW -= n;
// Offset remaining text // Offset remaining text (FIXME-OPT: Use memmove)
const ImWchar* src = obj->TextW.Data + pos + n; const ImWchar* src = obj->TextW.Data + pos + n;
while (ImWchar c = *src++) while (ImWchar c = *src++)
*dst++ = c; *dst++ = c;
@ -3617,13 +3618,12 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
// In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter. // In multi-line mode, we never exit the loop until all lines are counted, so add one extra to the searches_remaining counter.
searches_remaining += is_multiline ? 1 : 0; searches_remaining += is_multiline ? 1 : 0;
int line_count = 0; int line_count = 0;
for (const ImWchar* s = text_begin; *s != 0; s++) for (const ImWchar* s = text_begin; (s = (const ImWchar*)wcschr((const wchar_t*)s, (wchar_t)'\n')) != NULL; s++)
if (*s == '\n') {
{ line_count++;
line_count++; if (searches_result_line_number[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_number[0] = line_count; if (--searches_remaining <= 0) break; }
if (searches_result_line_number[0] == -1 && s >= searches_input_ptr[0]) { searches_result_line_number[0] = line_count; if (--searches_remaining <= 0) break; } if (searches_result_line_number[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_number[1] = line_count; if (--searches_remaining <= 0) break; }
if (searches_result_line_number[1] == -1 && s >= searches_input_ptr[1]) { searches_result_line_number[1] = line_count; if (--searches_remaining <= 0) break; } }
}
line_count++; line_count++;
if (searches_result_line_number[0] == -1) searches_result_line_number[0] = line_count; if (searches_result_line_number[0] == -1) searches_result_line_number[0] = line_count;
if (searches_result_line_number[1] == -1) searches_result_line_number[1] = line_count; if (searches_result_line_number[1] == -1) searches_result_line_number[1] = line_count;
@ -3691,9 +3691,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
break; break;
if (rect_pos.y < clip_rect.y) if (rect_pos.y < clip_rect.y)
{ {
while (p < text_selected_end) p = (const ImWchar*)wmemchr((const wchar_t*)p, '\n', text_selected_end - p) + 1;
if (*p++ == '\n')
break;
} }
else else
{ {