|
@@ -2489,7 +2489,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.
|
|
|
// This is made more complex because we have dissociated the layout rectangle (pos_min..pos_max) which define _where_ the ellipsis is, from actual clipping of text and limit of the ellipsis display.
|
|
|
// 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.
|
|
|
-void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, 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 clip_max_x, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
if (text_end_full == NULL)
|
|
@@ -2503,15 +2503,42 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min,
|
|
|
// min max ellipsis_max
|
|
|
// <-> this is generally some padding value
|
|
|
|
|
|
- // FIXME-STYLE: RenderPixelEllipsis() style should use actual font data.
|
|
|
const ImFont* font = draw_list->_Data->Font;
|
|
|
const float font_size = draw_list->_Data->FontSize;
|
|
|
- const int ellipsis_dot_count = 3;
|
|
|
- const float ellipsis_width = (1.0f + 1.0f) * ellipsis_dot_count - 1.0f;
|
|
|
const char* text_end_ellipsis = NULL;
|
|
|
+ const ImFontGlyph* glyph;
|
|
|
+ int ellipsis_char_num = 1;
|
|
|
+ ImWchar ellipsis_codepoint = font->EllipsisCodePoint;
|
|
|
|
|
|
+ if (ellipsis_codepoint != (ImWchar)-1)
|
|
|
+ glyph = font->FindGlyph(ellipsis_codepoint);
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ellipsis_codepoint = (ImWchar)'.';
|
|
|
+ glyph = font->FindGlyph(ellipsis_codepoint);
|
|
|
+ ellipsis_char_num = 3;
|
|
|
+ }
|
|
|
+
|
|
|
+ float ellipsis_glyph_width = glyph->X1; // Width of the glyph with no padding on either side
|
|
|
+ float ellipsis_width = ellipsis_glyph_width; // Full width of entire ellipsis
|
|
|
+ float push_left = 1.f;
|
|
|
+
|
|
|
+ if (ellipsis_char_num > 1)
|
|
|
+ {
|
|
|
+ const float spacing_between_dots = 1.f * (draw_list->_Data->FontSize / font->FontSize);
|
|
|
+ ellipsis_glyph_width = glyph->X1 - glyph->X0 + spacing_between_dots;
|
|
|
+ // Full ellipsis size without free spacing after it.
|
|
|
+ ellipsis_width = ellipsis_glyph_width * (float)ellipsis_char_num - spacing_between_dots;
|
|
|
+ if (glyph->X0 > 1.f)
|
|
|
+ {
|
|
|
+ // Pushing ellipsis to the left will be accomplished by rendering the dot (X0).
|
|
|
+ push_left = 0.f;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
float text_width = ImMax((pos_max.x - ellipsis_width) - pos_min.x, 1.0f);
|
|
|
float text_size_clipped_x = font->CalcTextSizeA(font_size, text_width, 0.0f, text, text_end_full, &text_end_ellipsis).x;
|
|
|
+
|
|
|
if (text == text_end_ellipsis && text_end_ellipsis < text_end_full)
|
|
|
{
|
|
|
// Always display at least 1 character if there's no room for character + ellipsis
|
|
@@ -2524,11 +2551,66 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min,
|
|
|
text_end_ellipsis--;
|
|
|
text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x; // Ascii blanks are always 1 byte
|
|
|
}
|
|
|
+
|
|
|
+ if (text_end_ellipsis != text_end_full)
|
|
|
+ {
|
|
|
+ // +---- First invisible character we arrived at.
|
|
|
+ // / +-- Character that we hope to be first invisible.
|
|
|
+ // [l][i]
|
|
|
+ // ||||
|
|
|
+ // \ \__ extra_spacing when two characters got hidden
|
|
|
+ // \___ extra_spacing when one character got hidden
|
|
|
+ unsigned c = 0;
|
|
|
+ float extra_spacing = 0;
|
|
|
+ const char* text_end_ellipsis_prev = text_end_ellipsis;
|
|
|
+ text_end_ellipsis += ImTextCharFromUtf8(&c, text_end_ellipsis, text_end_full);
|
|
|
+ if (c && !ImCharIsBlankW(c))
|
|
|
+ {
|
|
|
+ const ImFontGlyph* hidden_glyph = font->FindGlyph(c);
|
|
|
+ // Free space after first invisible glyph
|
|
|
+ extra_spacing = hidden_glyph->AdvanceX - hidden_glyph->X1;
|
|
|
+ c = 0;
|
|
|
+ text_end_ellipsis += ImTextCharFromUtf8(&c, text_end_ellipsis, text_end_full);
|
|
|
+ if (c && !ImCharIsBlankW(c))
|
|
|
+ {
|
|
|
+ hidden_glyph = font->FindGlyph(text_end_ellipsis[1]);
|
|
|
+ // Space before next invisible glyph. This intentionally ignores space from the first invisible
|
|
|
+ // glyph as that space will serve as spacing between ellipsis and last visible character. Without
|
|
|
+ // doing this we may get into awkward situations where ellipsis pretty much sticks to the last
|
|
|
+ // visible character. This issue manifests with the default font for word "Brocolli" there both i
|
|
|
+ // and l are very thin. Unfortunately this makes fonts with wider gaps (like monospace) look a bit
|
|
|
+ // worse, but it is a fair middle ground.
|
|
|
+ extra_spacing = hidden_glyph->X0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (extra_spacing > 0)
|
|
|
+ {
|
|
|
+ // Repeat calculation hoping that we will get extra character visible
|
|
|
+ text_width += extra_spacing;
|
|
|
+ // Text length calculation is essentially an optimized version of this:
|
|
|
+ // text_size_clipped_x = font->CalcTextSizeA(font_size, text_width, 0.0f, text, text_end_full, &text_end_ellipsis).x;
|
|
|
+ // It avoids calculating entire width of the string.
|
|
|
+ text_size_clipped_x += font->CalcTextSizeA(font_size, text_width - text_size_clipped_x, 0.0f, text_end_ellipsis_prev, text_end_full, &text_end_ellipsis).x;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ text_end_ellipsis = text_end_ellipsis_prev;
|
|
|
+ }
|
|
|
+
|
|
|
RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f));
|
|
|
|
|
|
- const float ellipsis_x = pos_min.x + text_size_clipped_x + 1.0f;
|
|
|
- if (ellipsis_x + ellipsis_width - 1.0f <= ellipsis_max_x)
|
|
|
- RenderPixelEllipsis(draw_list, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_dot_count);
|
|
|
+ // This variable pushes ellipsis to the left from last visible character. This is mostly useful when rendering
|
|
|
+ // ellipsis character contained in the font. If we render ellipsis manually space is already adequate and extra
|
|
|
+ // spacing is not needed.
|
|
|
+ float ellipsis_x = pos_min.x + text_size_clipped_x + push_left;
|
|
|
+ if (ellipsis_x + ellipsis_width - push_left <= ellipsis_max_x)
|
|
|
+ {
|
|
|
+ for (int i = 0; i < ellipsis_char_num; i++)
|
|
|
+ {
|
|
|
+ font->RenderChar(draw_list, font_size, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_codepoint);
|
|
|
+ ellipsis_x += ellipsis_glyph_width;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
else
|
|
|
{
|