Text: Tweaked rendering of three-dots "..." ellipsis variant. Baking more data. (#2775, #4269)

Ideally we're bake a single glyph but it's currently difficult to setup in our font building process.
This commit is contained in:
ocornut 2023-01-11 16:32:01 +01:00
parent 8801f02949
commit 1297a2be52
4 changed files with 27 additions and 33 deletions

View File

@ -40,6 +40,7 @@ All changes:
- Text: Fix clipping of single-character "..." ellipsis (U+2026 or U+0085) when font - Text: Fix clipping of single-character "..." ellipsis (U+2026 or U+0085) when font
is scaled. Scaling wasn't taken into account, leading to ellipsis character straying is scaled. Scaling wasn't taken into account, leading to ellipsis character straying
slightly out of its expected boundaries. (#2775) slightly out of its expected boundaries. (#2775)
- Text: Tweaked rendering of three-dots "..." ellipsis variant. (#2775, #4269)
----------------------------------------------------------------------- -----------------------------------------------------------------------

View File

@ -3261,29 +3261,10 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con
const float font_size = draw_list->_Data->FontSize; const float font_size = draw_list->_Data->FontSize;
const float font_scale = font_size / font->FontSize; const float font_scale = font_size / font->FontSize;
const char* text_end_ellipsis = NULL; const char* text_end_ellipsis = NULL;
const float ellipsis_width = font->EllipsisWidth * font_scale;
ImWchar ellipsis_char = font->EllipsisChar;
int ellipsis_char_count = 1;
if (ellipsis_char == (ImWchar)-1)
{
ellipsis_char = font->DotChar;
ellipsis_char_count = 3;
}
const ImFontGlyph* glyph = font->FindGlyph(ellipsis_char);
float ellipsis_glyph_width = glyph->X1 * font_scale; // Width of the glyph with no padding on either side
float ellipsis_total_width = ellipsis_glyph_width; // Full width of entire ellipsis
if (ellipsis_char_count > 1)
{
// Full ellipsis size without free spacing after it.
const float spacing_between_dots = 1.0f * font_scale;
ellipsis_glyph_width = (glyph->X1 - glyph->X0) * font_scale + spacing_between_dots;
ellipsis_total_width = ellipsis_glyph_width * (float)ellipsis_char_count - spacing_between_dots;
}
// We can now claim the space between pos_max.x and ellipsis_max.x // We can now claim the space between pos_max.x and ellipsis_max.x
const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_total_width) - pos_min.x, 1.0f); const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_width) - pos_min.x, 1.0f);
float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x; float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x;
if (text == text_end_ellipsis && text_end_ellipsis < text_end_full) if (text == text_end_ellipsis && text_end_ellipsis < text_end_full)
{ {
@ -3300,13 +3281,10 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con
// Render text, render ellipsis // Render text, render ellipsis
RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f)); RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f));
float ellipsis_x = pos_min.x + text_size_clipped_x; ImVec2 ellipsis_pos = ImFloor(ImVec2(pos_min.x + text_size_clipped_x, pos_min.y));
if (ellipsis_x + ellipsis_total_width <= ellipsis_max_x) if (ellipsis_pos.x + ellipsis_width <= ellipsis_max_x)
for (int i = 0; i < ellipsis_char_count; i++) for (int i = 0; i < font->EllipsisCharCount; i++, ellipsis_pos.x += font->EllipsisCharStep * font_scale)
{ font->RenderChar(draw_list, font_size, ellipsis_pos, GetColorU32(ImGuiCol_Text), font->EllipsisChar);
font->RenderChar(draw_list, font_size, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_char);
ellipsis_x += ellipsis_glyph_width;
}
} }
else else
{ {

View File

@ -2859,8 +2859,10 @@ struct ImFont
const ImFontConfig* ConfigData; // 4-8 // in // // Pointer within ContainerAtlas->ConfigData const ImFontConfig* ConfigData; // 4-8 // in // // Pointer within ContainerAtlas->ConfigData
short ConfigDataCount; // 2 // in // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont. short ConfigDataCount; // 2 // in // ~ 1 // Number of ImFontConfig involved in creating this font. Bigger than 1 when merging multiple font sources into one ImFont.
ImWchar FallbackChar; // 2 // out // = FFFD/'?' // Character used if a glyph isn't found. ImWchar FallbackChar; // 2 // out // = FFFD/'?' // Character used if a glyph isn't found.
ImWchar EllipsisChar; // 2 // out // = '...' // Character used for ellipsis rendering. ImWchar EllipsisChar; // 2 // out // = '...'/'.'// Character used for ellipsis rendering.
ImWchar DotChar; // 2 // out // = '.' // Character used for ellipsis rendering (if a single '...' character isn't found) short EllipsisCharCount; // 1 // out // 1 or 3
float EllipsisWidth; // 4 // out // Width
float EllipsisCharStep; // 4 // out // Step between characters when EllipsisCount > 0
bool DirtyLookupTables; // 1 // out // bool DirtyLookupTables; // 1 // out //
float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale() float Scale; // 4 // in // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetWindowFontScale()
float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] float Ascent, Descent; // 4+4 // out // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize]

View File

@ -3112,7 +3112,8 @@ ImFont::ImFont()
FallbackAdvanceX = 0.0f; FallbackAdvanceX = 0.0f;
FallbackChar = (ImWchar)-1; FallbackChar = (ImWchar)-1;
EllipsisChar = (ImWchar)-1; EllipsisChar = (ImWchar)-1;
DotChar = (ImWchar)-1; EllipsisWidth = EllipsisCharStep = 0.0f;
EllipsisCharCount = 0;
FallbackGlyph = NULL; FallbackGlyph = NULL;
ContainerAtlas = NULL; ContainerAtlas = NULL;
ConfigData = NULL; ConfigData = NULL;
@ -3200,8 +3201,20 @@ void ImFont::BuildLookupTable()
const ImWchar dots_chars[] = { (ImWchar)'.', (ImWchar)0xFF0E }; const ImWchar dots_chars[] = { (ImWchar)'.', (ImWchar)0xFF0E };
if (EllipsisChar == (ImWchar)-1) if (EllipsisChar == (ImWchar)-1)
EllipsisChar = FindFirstExistingGlyph(this, ellipsis_chars, IM_ARRAYSIZE(ellipsis_chars)); EllipsisChar = FindFirstExistingGlyph(this, ellipsis_chars, IM_ARRAYSIZE(ellipsis_chars));
if (DotChar == (ImWchar)-1) const ImWchar dot_char = FindFirstExistingGlyph(this, dots_chars, IM_ARRAYSIZE(dots_chars));
DotChar = FindFirstExistingGlyph(this, dots_chars, IM_ARRAYSIZE(dots_chars)); if (EllipsisChar != (ImWchar)-1)
{
EllipsisCharCount = 1;
EllipsisWidth = EllipsisCharStep = FindGlyph(EllipsisChar)->X1;
}
else if (dot_char != (ImWchar)-1)
{
const ImFontGlyph* glyph = FindGlyph(dot_char);
EllipsisChar = dot_char;
EllipsisCharCount = 3;
EllipsisCharStep = (glyph->X1 - glyph->X0) + 1.0f;
EllipsisWidth = EllipsisCharStep * 3.0f - 1.0f;
}
// Setup fallback character // Setup fallback character
const ImWchar fallback_chars[] = { (ImWchar)IM_UNICODE_CODEPOINT_INVALID, (ImWchar)'?', (ImWchar)' ' }; const ImWchar fallback_chars[] = { (ImWchar)IM_UNICODE_CODEPOINT_INVALID, (ImWchar)'?', (ImWchar)' ' };