OpenRCT2/src/openrct2/drawing/Text.cpp

173 lines
5.2 KiB
C++

/*****************************************************************************
* Copyright (c) 2014-2024 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "Text.h"
#include "../localisation/Formatter.h"
#include "../localisation/Formatting.h"
#include "../localisation/Localisation.h"
#include "Drawing.h"
class StaticLayout
{
private:
u8string Buffer;
TextPaint Paint;
int32_t LineCount = 0;
int32_t LineHeight;
int32_t MaxWidth;
public:
StaticLayout(u8string_view source, const TextPaint& paint, int32_t width)
: Paint(paint)
{
MaxWidth = GfxWrapString(source, width, paint.FontStyle, &Buffer, &LineCount);
LineCount += 1;
LineHeight = FontGetLineHeight(paint.FontStyle);
}
void Draw(DrawPixelInfo& dpi, const ScreenCoordsXY& coords)
{
TextPaint tempPaint = Paint;
auto lineCoords = coords;
switch (Paint.Alignment)
{
case TextAlignment::LEFT:
break;
case TextAlignment::CENTRE:
lineCoords.x += MaxWidth / 2;
break;
case TextAlignment::RIGHT:
lineCoords.x += MaxWidth;
break;
}
const utf8* buffer = Buffer.data();
for (int32_t line = 0; line < LineCount; ++line)
{
DrawText(dpi, lineCoords, tempPaint, buffer);
tempPaint.Colour = TEXT_COLOUR_254;
buffer = GetStringEnd(buffer) + 1;
lineCoords.y += LineHeight;
}
}
int32_t GetHeight() const
{
return LineHeight * LineCount;
}
int32_t GetWidth() const
{
return MaxWidth;
}
int32_t GetLineCount() const
{
return LineCount;
}
};
void DrawText(
DrawPixelInfo& dpi, const ScreenCoordsXY& coords, const TextPaint& paint, const_utf8string text, bool noFormatting)
{
int32_t width = noFormatting ? GfxGetStringWidthNoFormatting(text, paint.FontStyle)
: GfxGetStringWidth(text, paint.FontStyle);
auto alignedCoords = coords;
switch (paint.Alignment)
{
case TextAlignment::LEFT:
break;
case TextAlignment::CENTRE:
alignedCoords.x -= (width - 1) / 2;
break;
case TextAlignment::RIGHT:
alignedCoords.x -= width;
break;
}
TTFDrawString(dpi, text, paint.Colour, alignedCoords, noFormatting, paint.FontStyle, paint.Darkness);
if (paint.UnderlineText == TextUnderline::On)
{
GfxFillRect(
dpi, { { alignedCoords + ScreenCoordsXY{ 0, 11 } }, { alignedCoords + ScreenCoordsXY{ width, 11 } } },
gTextPalette[1]);
if (gTextPalette[2] != 0)
{
GfxFillRect(
dpi, { { alignedCoords + ScreenCoordsXY{ 1, 12 } }, { alignedCoords + ScreenCoordsXY{ width + 1, 12 } } },
gTextPalette[2]);
}
}
}
void DrawTextBasic(DrawPixelInfo& dpi, const ScreenCoordsXY& coords, StringId format)
{
Formatter ft{};
TextPaint textPaint{};
DrawTextBasic(dpi, coords, format, ft, textPaint);
}
void DrawTextBasic(DrawPixelInfo& dpi, const ScreenCoordsXY& coords, StringId format, const Formatter& ft, TextPaint textPaint)
{
utf8 buffer[512];
OpenRCT2::FormatStringLegacy(buffer, sizeof(buffer), format, ft.Data());
DrawText(dpi, coords, textPaint, buffer);
}
void DrawTextEllipsised(DrawPixelInfo& dpi, const ScreenCoordsXY& coords, int32_t width, StringId format)
{
Formatter ft{};
TextPaint textPaint{};
DrawTextEllipsised(dpi, coords, width, format, ft, textPaint);
}
void DrawTextEllipsised(
DrawPixelInfo& dpi, const ScreenCoordsXY& coords, int32_t width, StringId format, const Formatter& ft, TextPaint textPaint)
{
utf8 buffer[512];
OpenRCT2::FormatStringLegacy(buffer, sizeof(buffer), format, ft.Data());
GfxClipString(buffer, width, textPaint.FontStyle);
DrawText(dpi, coords, textPaint, buffer);
}
int32_t DrawTextWrapped(DrawPixelInfo& dpi, const ScreenCoordsXY& coords, int32_t width, StringId format)
{
Formatter ft{};
TextPaint textPaint{};
return DrawTextWrapped(dpi, coords, width, format, ft, textPaint);
}
int32_t DrawTextWrapped(
DrawPixelInfo& dpi, const ScreenCoordsXY& coords, int32_t width, StringId format, const Formatter& ft, TextPaint textPaint)
{
const void* args = ft.Data();
StaticLayout layout(FormatStringIDLegacy(format, args), textPaint, width);
if (textPaint.Alignment == TextAlignment::CENTRE)
{
// The original tried to vertically centre the text, but used line count - 1
int32_t lineCount = layout.GetLineCount();
int32_t lineHeight = layout.GetHeight() / lineCount;
int32_t yOffset = (lineCount - 1) * lineHeight / 2;
layout.Draw(dpi, coords - ScreenCoordsXY{ layout.GetWidth() / 2, yOffset });
}
else
{
layout.Draw(dpi, coords);
}
return layout.GetHeight();
}