mirror of https://github.com/OpenTTD/OpenTTD
Codechange: Add version of DrawStringMultiLine that performs clipping test. (#14189)
Normally DrawStringMultiLine does not perform any clipping, as the return value may be needed if it the text is not drawn. In some specific cases the height is already known, so it is possible to test for clipping, which can cut down on layouting time for text which won't be visible.pull/14186/head
parent
2f020abe74
commit
8b14faaa40
|
@ -239,7 +239,7 @@ public:
|
|||
for (auto it = first; it != last; ++it) {
|
||||
const BridgeSpec *b = it->spec;
|
||||
DrawSpriteIgnorePadding(b->sprite, b->pal, tr.WithWidth(this->icon_width, rtl), SA_HOR_CENTER | SA_BOTTOM);
|
||||
DrawStringMultiLine(tr.Indent(this->icon_width + WidgetDimensions::scaled.hsep_normal, rtl), GetBridgeSelectString(*it));
|
||||
DrawStringMultiLineWithClipping(tr.Indent(this->icon_width + WidgetDimensions::scaled.hsep_normal, rtl), GetBridgeSelectString(*it));
|
||||
tr = tr.Translate(0, this->resize.step_height);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -194,14 +194,14 @@ public:
|
|||
|
||||
case WID_EM_MESSAGE:
|
||||
if (this->detailed_msg.empty()) {
|
||||
DrawStringMultiLine(r, this->summary_msg.GetDecodedString(), TC_FROMSTRING, SA_CENTER);
|
||||
DrawStringMultiLineWithClipping(r, this->summary_msg.GetDecodedString(), TC_FROMSTRING, SA_CENTER);
|
||||
} else if (this->extra_msg.empty()) {
|
||||
/* Extra space when message is shorter than company face window */
|
||||
int extra = (r.Height() - this->height_summary - this->height_detailed - WidgetDimensions::scaled.vsep_wide) / 2;
|
||||
|
||||
/* Note: NewGRF supplied error message often do not start with a colour code, so default to white. */
|
||||
DrawStringMultiLine(r.WithHeight(this->height_summary + extra, false), this->summary_msg.GetDecodedString(), TC_WHITE, SA_CENTER);
|
||||
DrawStringMultiLine(r.WithHeight(this->height_detailed + extra, true), this->detailed_msg.GetDecodedString(), TC_WHITE, SA_CENTER);
|
||||
DrawStringMultiLineWithClipping(r.WithHeight(this->height_summary + extra, false), this->summary_msg.GetDecodedString(), TC_WHITE, SA_CENTER);
|
||||
DrawStringMultiLineWithClipping(r.WithHeight(this->height_detailed + extra, true), this->detailed_msg.GetDecodedString(), TC_WHITE, SA_CENTER);
|
||||
} else {
|
||||
/* Extra space when message is shorter than company face window */
|
||||
int extra = (r.Height() - this->height_summary - this->height_detailed - this->height_extra - (WidgetDimensions::scaled.vsep_wide * 2)) / 3;
|
||||
|
@ -210,9 +210,9 @@ public:
|
|||
Rect top_section = r.WithHeight(this->height_summary + extra, false);
|
||||
Rect bottom_section = r.WithHeight(this->height_extra + extra, true);
|
||||
Rect middle_section = { top_section.left, top_section.bottom, top_section.right, bottom_section.top };
|
||||
DrawStringMultiLine(top_section, this->summary_msg.GetDecodedString(), TC_WHITE, SA_CENTER);
|
||||
DrawStringMultiLine(middle_section, this->detailed_msg.GetDecodedString(), TC_WHITE, SA_CENTER);
|
||||
DrawStringMultiLine(bottom_section, this->extra_msg.GetDecodedString(), TC_WHITE, SA_CENTER);
|
||||
DrawStringMultiLineWithClipping(top_section, this->summary_msg.GetDecodedString(), TC_WHITE, SA_CENTER);
|
||||
DrawStringMultiLineWithClipping(middle_section, this->detailed_msg.GetDecodedString(), TC_WHITE, SA_CENTER);
|
||||
DrawStringMultiLineWithClipping(bottom_section, this->extra_msg.GetDecodedString(), TC_WHITE, SA_CENTER);
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
35
src/gfx.cpp
35
src/gfx.cpp
|
@ -839,6 +839,41 @@ int DrawStringMultiLine(int left, int right, int top, int bottom, StringID str,
|
|||
return DrawStringMultiLine(left, right, top, bottom, GetString(str), colour, align, underline, fontsize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a multiline string, possibly over multiple lines, if the region is within the current display clipping area.
|
||||
* @note With clipping, it is not possible to determine how tall the rendered text will be, as it's not layouted.
|
||||
* Regulard DrawStringMultiLine must be used if the height needs to be known.
|
||||
*
|
||||
* @param left The left most position to draw on.
|
||||
* @param right The right most position to draw on.
|
||||
* @param top The top most position to draw on.
|
||||
* @param bottom The bottom most position to draw on.
|
||||
* @param str String to draw.
|
||||
* @param colour Colour used for drawing the string, for details see _string_colourmap in
|
||||
* table/palettes.h or docs/ottd-colourtext-palette.png or the enum TextColour in gfx_type.h
|
||||
* @param align The horizontal and vertical alignment of the string.
|
||||
* @param underline Whether to underline all strings
|
||||
* @param fontsize The size of the initial characters.
|
||||
*
|
||||
* @return true iff the string was drawn.
|
||||
*/
|
||||
bool DrawStringMultiLineWithClipping(int left, int right, int top, int bottom, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
|
||||
{
|
||||
/* The string may contain control chars to change the font, just use the biggest font for clipping. */
|
||||
int max_height = std::max({GetCharacterHeight(FS_SMALL), GetCharacterHeight(FS_NORMAL), GetCharacterHeight(FS_LARGE), GetCharacterHeight(FS_MONO)});
|
||||
|
||||
/* Funny glyphs may extent outside the usual bounds, so relax the clipping somewhat. */
|
||||
int extra = max_height / 2;
|
||||
|
||||
if (_cur_dpi->top + _cur_dpi->height + extra < top || _cur_dpi->top > bottom + extra ||
|
||||
_cur_dpi->left + _cur_dpi->width + extra < left || _cur_dpi->left > right + extra) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DrawStringMultiLine(left, right, top, bottom, str, colour, align, underline, fontsize);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the string dimension in pixels. The height and width are returned
|
||||
* in a single Dimension value. TINYFONT, BIGFONT modifiers are only
|
||||
|
|
|
@ -99,6 +99,7 @@ int DrawString(int left, int right, int top, std::string_view str, TextColour co
|
|||
int DrawString(int left, int right, int top, StringID str, TextColour colour = TC_FROMSTRING, StringAlignment align = SA_LEFT, bool underline = false, FontSize fontsize = FS_NORMAL);
|
||||
int DrawStringMultiLine(int left, int right, int top, int bottom, std::string_view str, TextColour colour = TC_FROMSTRING, StringAlignment align = (SA_TOP | SA_LEFT), bool underline = false, FontSize fontsize = FS_NORMAL);
|
||||
int DrawStringMultiLine(int left, int right, int top, int bottom, StringID str, TextColour colour = TC_FROMSTRING, StringAlignment align = (SA_TOP | SA_LEFT), bool underline = false, FontSize fontsize = FS_NORMAL);
|
||||
bool DrawStringMultiLineWithClipping(int left, int right, int top, int bottom, std::string_view str, TextColour colour = TC_FROMSTRING, StringAlignment align = (SA_TOP | SA_LEFT), bool underline = false, FontSize fontsize = FS_NORMAL);
|
||||
|
||||
void DrawCharCentered(char32_t c, const Rect &r, TextColour colour);
|
||||
|
||||
|
@ -129,6 +130,11 @@ inline int DrawStringMultiLine(const Rect &r, StringID str, TextColour colour =
|
|||
return DrawStringMultiLine(r.left, r.right, r.top, r.bottom, str, colour, align, underline, fontsize);
|
||||
}
|
||||
|
||||
inline bool DrawStringMultiLineWithClipping(const Rect &r, std::string_view str, TextColour colour = TC_FROMSTRING, StringAlignment align = (SA_TOP | SA_LEFT), bool underline = false, FontSize fontsize = FS_NORMAL)
|
||||
{
|
||||
return DrawStringMultiLineWithClipping(r.left, r.right, r.top, r.bottom, str, colour, align, underline, fontsize);
|
||||
}
|
||||
|
||||
inline void GfxFillRect(const Rect &r, int colour, FillRectMode mode = FILLRECT_OPAQUE)
|
||||
{
|
||||
GfxFillRect(r.left, r.top, r.right, r.bottom, colour, mode);
|
||||
|
|
|
@ -454,11 +454,11 @@ protected:
|
|||
TimerGameEconomy::Year year = this->year;
|
||||
for (int i = 0; i < this->num_on_x_axis; i++) {
|
||||
if (rtl) {
|
||||
DrawStringMultiLine(x + x_sep, x, y, this->height,
|
||||
DrawStringMultiLineWithClipping(x + x_sep, x, y, this->height,
|
||||
GetString(month == 0 ? STR_GRAPH_X_LABEL_MONTH_YEAR : STR_GRAPH_X_LABEL_MONTH, STR_MONTH_ABBREV_JAN + month, year),
|
||||
GRAPH_AXIS_LABEL_COLOUR, SA_LEFT);
|
||||
} else {
|
||||
DrawStringMultiLine(x, x + x_sep, y, this->height,
|
||||
DrawStringMultiLineWithClipping(x, x + x_sep, y, this->height,
|
||||
GetString(month == 0 ? STR_GRAPH_X_LABEL_MONTH_YEAR : STR_GRAPH_X_LABEL_MONTH, STR_MONTH_ABBREV_JAN + month, year),
|
||||
GRAPH_AXIS_LABEL_COLOUR, SA_LEFT);
|
||||
}
|
||||
|
|
|
@ -928,7 +928,7 @@ struct GameOptionsWindow : Window {
|
|||
|
||||
/* Draw the 'some search results are hidden' notice. */
|
||||
if (this->warn_missing != WHR_NONE) {
|
||||
DrawStringMultiLine(panel.WithHeight(this->warn_lines * GetCharacterHeight(FS_NORMAL)),
|
||||
DrawStringMultiLineWithClipping(panel.WithHeight(this->warn_lines * GetCharacterHeight(FS_NORMAL)),
|
||||
GetString(warn_str, _game_settings_restrict_dropdown[this->filter.min_cat]),
|
||||
TC_BLACK, SA_CENTER);
|
||||
}
|
||||
|
|
|
@ -712,7 +712,7 @@ public:
|
|||
|
||||
switch (ce.pe->type) {
|
||||
case SPET_TEXT:
|
||||
y_offset = DrawStringMultiLine(ce.bounds.left, ce.bounds.right, ce.bounds.top - scrollpos, ce.bounds.bottom - scrollpos,
|
||||
DrawStringMultiLineWithClipping(ce.bounds.left, ce.bounds.right, ce.bounds.top - scrollpos, ce.bounds.bottom - scrollpos,
|
||||
ce.pe->text.GetDecodedString(), TC_BLACK, SA_TOP | SA_LEFT);
|
||||
break;
|
||||
|
||||
|
|
|
@ -592,7 +592,7 @@ void TextfileWindow::AfterLoadMarkdown()
|
|||
|
||||
int y_offset = (line.top - pos) * line_height;
|
||||
if (IsWidgetLowered(WID_TF_WRAPTEXT)) {
|
||||
DrawStringMultiLine(fr.left, fr.right, y_offset, fr.bottom, line.text, line.colour, SA_TOP | SA_LEFT, false, FS_MONO);
|
||||
DrawStringMultiLineWithClipping(fr.left, fr.right, y_offset, y_offset + (line.bottom - line.top) * line_height, line.text, line.colour, SA_TOP | SA_LEFT, false, FS_MONO);
|
||||
} else {
|
||||
DrawString(fr.left, fr.right, y_offset, line.text, line.colour, SA_TOP | SA_LEFT, false, FS_MONO);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue