Codechange: Remove initial colour from layouter cache. (#12728)

Initial colour is now always TC_INVALID, which is substituted with the desired colour when drawing the layout line.

This allows strings which differ only by initial colour to use the same layout cache entry, increasing the efficacy of the cache.
This commit is contained in:
Peter Nelson 2024-05-28 19:33:44 +01:00 committed by GitHub
parent 605dff4920
commit 3d4b98845a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 16 additions and 15 deletions

View File

@ -491,11 +491,12 @@ static void SetColourRemap(TextColour colour)
* will be drawn in the right direction.
* @param underline Whether to underline what has been drawn or not.
* @param truncation Whether to perform string truncation or not.
* @param default_colour Colour of text if not specified within string.
*
* @return In case of left or center alignment the right most pixel we have drawn to.
* In case of right alignment the left most pixel we have drawn to.
*/
static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left, int right, StringAlignment align, bool underline, bool truncation)
static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left, int right, StringAlignment align, bool underline, bool truncation, TextColour default_colour)
{
if (line.CountRuns() == 0) return 0;
@ -589,6 +590,7 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left,
FontCache *fc = f->fc;
TextColour colour = f->colour;
if (colour == TC_INVALID) colour = default_colour;
colour_has_shadow = (colour & TC_NO_SHADE) == 0 && colour != TC_BLACK;
SetColourRemap(do_shadow ? TC_BLACK : colour); // the last run also sets the colour for the truncation dots
if (do_shadow && (!fc->GetDrawGlyphShadow() || !colour_has_shadow)) continue;
@ -665,10 +667,10 @@ int DrawString(int left, int right, int top, std::string_view str, TextColour co
return 0;
}
Layouter layout(str, INT32_MAX, colour, fontsize);
Layouter layout(str, INT32_MAX, fontsize);
if (layout.empty()) return 0;
return DrawLayoutLine(*layout.front(), top, left, right, align, underline, true);
return DrawLayoutLine(*layout.front(), top, left, right, align, underline, true, colour);
}
/**
@ -702,7 +704,7 @@ int DrawString(int left, int right, int top, StringID str, TextColour colour, St
int GetStringHeight(std::string_view str, int maxw, FontSize fontsize)
{
assert(maxw > 0);
Layouter layout(str, maxw, TC_FROMSTRING, fontsize);
Layouter layout(str, maxw, fontsize);
return layout.GetBounds().height;
}
@ -778,7 +780,7 @@ int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_vi
* do we really want to support fonts of 0 or less pixels high? */
if (maxh <= 0) return top;
Layouter layout(str, maxw, colour, fontsize);
Layouter layout(str, maxw, fontsize);
int total_height = layout.GetBounds().height;
int y;
switch (align & SA_VERT_MASK) {
@ -807,7 +809,7 @@ int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_vi
last_line = y + line_height;
if (first_line > y) first_line = y;
DrawLayoutLine(*line, y, left, right, align, underline, false);
DrawLayoutLine(*line, y, left, right, align, underline, false, colour);
}
y += line_height;
}
@ -848,7 +850,7 @@ int DrawStringMultiLine(int left, int right, int top, int bottom, StringID str,
*/
Dimension GetStringBoundingBox(std::string_view str, FontSize start_fontsize)
{
Layouter layout(str, INT32_MAX, TC_FROMSTRING, start_fontsize);
Layouter layout(str, INT32_MAX, start_fontsize);
return layout.GetBounds();
}
@ -907,7 +909,7 @@ Point GetCharPosInString(std::string_view str, const char *ch, FontSize start_fo
assert(ch >= str.data() && (ch - str.data()) <= static_cast<ptrdiff_t>(str.size()));
auto it_ch = str.begin() + (ch - str.data());
Layouter layout(str, INT32_MAX, TC_FROMSTRING, start_fontsize);
Layouter layout(str, INT32_MAX, start_fontsize);
return layout.GetCharPosition(it_ch);
}
@ -922,7 +924,7 @@ ptrdiff_t GetCharAtPosition(std::string_view str, int x, FontSize start_fontsize
{
if (x < 0) return -1;
Layouter layout(str, INT32_MAX, TC_FROMSTRING, start_fontsize);
Layouter layout(str, INT32_MAX, start_fontsize);
return layout.GetCharAtPosition(x, 0);
}

View File

@ -125,12 +125,11 @@ static inline void GetLayouter(Layouter::LineCacheItem &line, std::string_view s
* Create a new layouter.
* @param str The string to create the layout for.
* @param maxw The maximum width.
* @param colour The colour of the font.
* @param fontsize The size of font to use.
*/
Layouter::Layouter(std::string_view str, int maxw, TextColour colour, FontSize fontsize) : string(str)
Layouter::Layouter(std::string_view str, int maxw, FontSize fontsize) : string(str)
{
FontState state(colour, fontsize);
FontState state(TC_INVALID, fontsize);
while (true) {
auto line_length = str.find_first_of('\n');

View File

@ -36,7 +36,7 @@ struct FontState {
*/
inline void SetColour(TextColour c)
{
assert((c & TC_COLOUR_MASK) >= TC_BLUE && (c & TC_COLOUR_MASK) <= TC_BLACK);
assert(((c & TC_COLOUR_MASK) >= TC_BLUE && (c & TC_COLOUR_MASK) <= TC_BLACK) || (c & TC_COLOUR_MASK) == TC_INVALID);
assert((c & (TC_COLOUR_MASK | TC_FLAGS_MASK)) == c);
if ((this->cur_colour & TC_FORCED) == 0) this->cur_colour = c;
}
@ -174,7 +174,7 @@ private:
public:
static Font *GetFont(FontSize size, TextColour colour);
Layouter(std::string_view str, int maxw = INT32_MAX, TextColour colour = TC_FROMSTRING, FontSize fontsize = FS_NORMAL);
Layouter(std::string_view str, int maxw = INT32_MAX, FontSize fontsize = FS_NORMAL);
Dimension GetBounds();
Point GetCharPosition(std::string_view::const_iterator ch) const;
ptrdiff_t GetCharAtPosition(int x, size_t line_index) const;

View File

@ -331,7 +331,7 @@ void TextfileWindow::CheckHyperlinkClick(Point pt)
/* Build line layout to figure out character position that was clicked. */
uint window_width = IsWidgetLowered(WID_TF_WRAPTEXT) ? this->GetWidget<NWidgetCore>(WID_TF_BACKGROUND)->current_x - WidgetDimensions::scaled.frametext.Horizontal() : INT_MAX;
Layouter layout(this->lines[line_index].text, window_width, this->lines[line_index].colour, FS_MONO);
Layouter layout(this->lines[line_index].text, window_width, FS_MONO);
assert(subline < layout.size());
ptrdiff_t char_index = layout.GetCharAtPosition(pt.x - WidgetDimensions::scaled.frametext.left, subline);
if (char_index < 0) return;