From 3d4b98845ada37979ab4d00ff4ef1fcb5166f6cc Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Tue, 28 May 2024 19:33:44 +0100 Subject: [PATCH] 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. --- src/gfx.cpp | 20 +++++++++++--------- src/gfx_layout.cpp | 5 ++--- src/gfx_layout.h | 4 ++-- src/textfile_gui.cpp | 2 +- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/gfx.cpp b/src/gfx.cpp index 3d652ab18d..5cc3ee9b90 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -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(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); } diff --git a/src/gfx_layout.cpp b/src/gfx_layout.cpp index 28a3c7a57d..392ba1fa4a 100644 --- a/src/gfx_layout.cpp +++ b/src/gfx_layout.cpp @@ -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'); diff --git a/src/gfx_layout.h b/src/gfx_layout.h index 636b5cdadc..42b809f561 100644 --- a/src/gfx_layout.h +++ b/src/gfx_layout.h @@ -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; diff --git a/src/textfile_gui.cpp b/src/textfile_gui.cpp index a95c15ac48..1ae7673715 100644 --- a/src/textfile_gui.cpp +++ b/src/textfile_gui.cpp @@ -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(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;