|
@@ -3333,11 +3333,21 @@ const ImFontGlyph* ImFont::FindGlyphNoFallback(ImWchar c) const
|
|
|
return &Glyphs.Data[i];
|
|
|
}
|
|
|
|
|
|
-const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const
|
|
|
+// Wrapping skips upcoming blanks
|
|
|
+static inline const char* CalcWordWrapNextLineStartA(const char* text, const char* text_end)
|
|
|
{
|
|
|
- // Simple word-wrapping for English, not full-featured. Please submit failing cases!
|
|
|
- // FIXME: Much possible improvements (don't cut things like "word !", "word!!!" but cut within "word,,,,", more sensible support for punctuations, support for Unicode punctuations, etc.)
|
|
|
+ while (text < text_end && ImCharIsBlankA(*text))
|
|
|
+ text++;
|
|
|
+ if (*text == '\n')
|
|
|
+ text++;
|
|
|
+ return text;
|
|
|
+}
|
|
|
|
|
|
+// Simple word-wrapping for English, not full-featured. Please submit failing cases!
|
|
|
+// This will return the next location to wrap from. If no wrapping if necessary, this will fast-forward to e.g. text_end.
|
|
|
+// FIXME: Much possible improvements (don't cut things like "word !", "word!!!" but cut within "word,,,,", more sensible support for punctuations, support for Unicode punctuations, etc.)
|
|
|
+const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const
|
|
|
+{
|
|
|
// For references, possible wrap point marked with ^
|
|
|
// "aaa bbb, ccc,ddd. eee fff. ggg!"
|
|
|
// ^ ^ ^ ^ ^__ ^ ^
|
|
@@ -3349,7 +3359,6 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c
|
|
|
|
|
|
// Cut words that cannot possibly fit within one line.
|
|
|
// e.g.: "The tropical fish" with ~5 characters worth of width --> "The tr" "opical" "fish"
|
|
|
-
|
|
|
float line_width = 0.0f;
|
|
|
float word_width = 0.0f;
|
|
|
float blank_width = 0.0f;
|
|
@@ -3429,6 +3438,10 @@ const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const c
|
|
|
s = next_s;
|
|
|
}
|
|
|
|
|
|
+ // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity.
|
|
|
+ // +1 may not be a character start point in UTF-8 but it's ok because caller loops use (text >= word_wrap_eol).
|
|
|
+ if (s == text && text < text_end)
|
|
|
+ return s + 1;
|
|
|
return s;
|
|
|
}
|
|
|
|
|
@@ -3453,11 +3466,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons
|
|
|
{
|
|
|
// Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.
|
|
|
if (!word_wrap_eol)
|
|
|
- {
|
|
|
word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - line_width);
|
|
|
- if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity.
|
|
|
- word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below
|
|
|
- }
|
|
|
|
|
|
if (s >= word_wrap_eol)
|
|
|
{
|
|
@@ -3466,13 +3475,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons
|
|
|
text_size.y += line_height;
|
|
|
line_width = 0.0f;
|
|
|
word_wrap_eol = NULL;
|
|
|
-
|
|
|
- // Wrapping skips upcoming blanks
|
|
|
- while (s < text_end)
|
|
|
- {
|
|
|
- const char c = *s;
|
|
|
- if (ImCharIsBlankA(c)) { s++; } else if (c == '\n') { s++; break; } else { break; }
|
|
|
- }
|
|
|
+ s = CalcWordWrapNextLineStartA(s, text_end); // Wrapping skips upcoming blanks
|
|
|
continue;
|
|
|
}
|
|
|
}
|
|
@@ -3557,7 +3560,6 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im
|
|
|
const float scale = size / FontSize;
|
|
|
const float line_height = FontSize * scale;
|
|
|
const bool word_wrap_enabled = (wrap_width > 0.0f);
|
|
|
- const char* word_wrap_eol = NULL;
|
|
|
|
|
|
// Fast-forward to first visible line
|
|
|
const char* s = text_begin;
|
|
@@ -3597,6 +3599,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im
|
|
|
unsigned int vtx_current_idx = draw_list->_VtxCurrentIdx;
|
|
|
|
|
|
const ImU32 col_untinted = col | ~IM_COL32_A_MASK;
|
|
|
+ const char* word_wrap_eol = NULL;
|
|
|
|
|
|
while (s < text_end)
|
|
|
{
|
|
@@ -3604,24 +3607,14 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, Im
|
|
|
{
|
|
|
// Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.
|
|
|
if (!word_wrap_eol)
|
|
|
- {
|
|
|
word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - (x - start_x));
|
|
|
- if (word_wrap_eol == s) // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity.
|
|
|
- word_wrap_eol++; // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below
|
|
|
- }
|
|
|
|
|
|
if (s >= word_wrap_eol)
|
|
|
{
|
|
|
x = start_x;
|
|
|
y += line_height;
|
|
|
word_wrap_eol = NULL;
|
|
|
-
|
|
|
- // Wrapping skips upcoming blanks
|
|
|
- while (s < text_end)
|
|
|
- {
|
|
|
- const char c = *s;
|
|
|
- if (ImCharIsBlankA(c)) { s++; } else if (c == '\n') { s++; break; } else { break; }
|
|
|
- }
|
|
|
+ s = CalcWordWrapNextLineStartA(s, text_end); // Wrapping skips upcoming blanks
|
|
|
continue;
|
|
|
}
|
|
|
}
|