diff --git a/Source/automap.cpp b/Source/automap.cpp index 197eaba75..09a25e7a0 100644 --- a/Source/automap.cpp +++ b/Source/automap.cpp @@ -383,24 +383,24 @@ uint16_t GetAutomapType(Point map, bool view) void DrawAutomapText(const CelOutputBuffer &out) { char desc[256]; - int nextLine = 20; + Point linePosition { 8, 20 }; if (gbIsMultiplayer) { if (strcasecmp("0.0.0.0", szPlayerName) != 0) { strcat(strcpy(desc, _("game: ")), szPlayerName); - DrawString(out, desc, { 8, nextLine, 0, 0 }); - nextLine += 15; + DrawString(out, desc, linePosition); + linePosition.y += 15; } if (szPlayerDescript[0] != '\0') { strcat(strcpy(desc, _("password: ")), szPlayerDescript); - DrawString(out, desc, { 8, nextLine, 0, 0 }); - nextLine += 15; + DrawString(out, desc, linePosition); + linePosition.y += 15; } } if (setlevel) { - DrawString(out, _(quest_level_names[setlvlnum]), { 8, nextLine, 0, 0 }); + DrawString(out, _(quest_level_names[setlvlnum]), linePosition); return; } @@ -413,7 +413,7 @@ void DrawAutomapText(const CelOutputBuffer &out) strcpy(desc, fmt::format(_("Level: {:d}"), currlevel).c_str()); } - DrawString(out, desc, { 8, nextLine, 0, 0 }); + DrawString(out, desc, linePosition); } } diff --git a/Source/control.cpp b/Source/control.cpp index 232a9d17b..e19a10c98 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -324,15 +324,13 @@ static void DrawSpell(const CelOutputBuffer &out) static void PrintSBookHotkey(const CelOutputBuffer &out, Point position, const std::string &text) { - int &x = position.x; - int &y = position.y; - x -= GetLineWidth(text.c_str()) + 5; - x += SPLICONLENGTH; - y += 17; - y -= SPLICONLENGTH; - - DrawString(out, text.c_str(), { x - 1, y + 1, 0, 0 }, UIS_BLACK); - DrawString(out, text.c_str(), { x + 0, y + 0, 0, 0 }, UIS_SILVER); + // Align the hot key text with the top-right corner of the spell icon + position += { SPLICONLENGTH - (GetLineWidth(text.c_str()) + 5), 17 - SPLICONLENGTH }; + + // Draw a drop shadow below and to the left of the text + DrawString(out, text.c_str(), position + Point { -1, 1 }, UIS_BLACK); + // Then draw the text over the top + DrawString(out, text.c_str(), position, UIS_SILVER); } void DrawSpellList(const CelOutputBuffer &out) @@ -1104,7 +1102,7 @@ static void PrintInfo(const CelOutputBuffer &out) if (talkflag) return; - SDL_Rect line { PANEL_X + 177, PANEL_Y + LineOffsets[pnumlines][0], 288, 0 }; + Rectangle line { PANEL_X + 177, PANEL_Y + LineOffsets[pnumlines][0], 288, 0 }; int yo = 0; int lo = 1; @@ -1115,7 +1113,7 @@ static void PrintInfo(const CelOutputBuffer &out) } for (int i = 0; i < pnumlines; i++) { - line.y = PANEL_Y + LineOffsets[pnumlines - lo][i + yo]; + line.position.y = PANEL_Y + LineOffsets[pnumlines - lo][i + yo]; DrawString(out, panelstr[i], line, infoclr | UIS_CENTER | UIS_FIT_SPACING, 2); } } @@ -1700,22 +1698,40 @@ void DrawGoldSplit(const CelOutputBuffer &out, int amount) CelDrawTo(out, { dialogX, 178 }, *pGBoxBuff, 1); - strcpy( + constexpr auto bufferSize = sizeof(tempstr) / sizeof(*tempstr); + + // strncpy copies up to the maximum number of characters specified, it does not ensure that a null character is + // written to the end of the c-string. To be safe we specify a limit one character shorter than the buffer size and + // ensure that the buffer ends in a null character manually. + strncpy( tempstr, fmt::format(ngettext( /* TRANSLATORS: {:d} is a number. Dialog is shown when splitting a stash of Gold.*/ "You have {:d} gold piece. How many do you want to remove?", "You have {:d} gold pieces. How many do you want to remove?", initialDropGoldValue), initialDropGoldValue) - .c_str()); + .c_str(), + bufferSize - 1); + // Ensure the prompt shown to the player is terminated properly (in case the formatted/translated string ends up + // being longer than 255 characters) + tempstr[bufferSize - 1] = '\0'; + + // Pre-wrap the string at spaces, otherwise DrawString would hard wrap in the middle of words WordWrapGameString(tempstr, 200); + + // The split gold dialog is roughly 4 lines high, but we need at least one line for the player to input an amount. + // Using a clipping region 50 units high (approx 3 lines with a lineheight of 17) to ensure there is enough room left + // for the text entered by the player. DrawString(out, tempstr, { dialogX + 31, 87, 200, 50 }, UIS_GOLD | UIS_CENTER, 1, 17); tempstr[0] = '\0'; if (amount > 0) { - sprintf(tempstr, "%u", amount); + // snprintf ensures that the destination buffer ends in a null character. + snprintf(tempstr, bufferSize, "%u", amount); } - DrawString(out, tempstr, { dialogX + 37, 140, 0, 0 }, UIS_SILVER, 1, -1, true); + // Even a ten digit amount of gold only takes up about half a line. There's no need to wrap or clip text here so we + // use the Point form of DrawString. + DrawString(out, tempstr, Point { dialogX + 37, 140 }, UIS_SILVER, 1, -1, true); } void control_drop_gold(char vkey) diff --git a/Source/controls/modifier_hints.cpp b/Source/controls/modifier_hints.cpp index 585112d11..ab16b63d1 100644 --- a/Source/controls/modifier_hints.cpp +++ b/Source/controls/modifier_hints.cpp @@ -98,16 +98,20 @@ uint16_t CircleMenuHintTextColor(bool active) return active ? UIS_BLUE : UIS_GOLD; } -void DrawCircleMenuHint(const CelOutputBuffer &out, const CircleMenuHint &hint, int x, int y) +/** + * @brief Draws hint text for a four button layout with the top/left edge of the bounding box at the position given by origin. + * @param out The output buffer to draw on. + * @param hint Struct describing the text to draw and the dimensions of the layout. + * @param origin Top left corner of the layout (relative to the output buffer). +*/ +void DrawCircleMenuHint(const CelOutputBuffer &out, const CircleMenuHint &hint, const Point &origin) { - DrawString(out, hint.top, { x + hint.xMid - hint.topW / 2, y, 0, 0 }, CircleMenuHintTextColor(IsTopActive(hint))); - y += LineHeight; + DrawString(out, hint.top, origin + Point { hint.xMid - hint.topW / 2, 0 }, CircleMenuHintTextColor(IsTopActive(hint))); - DrawString(out, hint.left, { x, y, 0, 0 }, CircleMenuHintTextColor(IsLeftActive(hint))); - DrawString(out, hint.right, { x + hint.leftW + MidSpaces * SpaceWidth(), y, 0, 0 }, CircleMenuHintTextColor(IsRightActive(hint))); - y += LineHeight; + DrawString(out, hint.left, origin + Point { 0, LineHeight }, CircleMenuHintTextColor(IsLeftActive(hint))); + DrawString(out, hint.right, origin + Point { hint.leftW + MidSpaces * SpaceWidth(), LineHeight }, CircleMenuHintTextColor(IsRightActive(hint))); - DrawString(out, hint.bottom, { x + hint.xMid - hint.bottomW / 2, y, 0, 0 }, CircleMenuHintTextColor(IsBottomActive(hint))); + DrawString(out, hint.bottom, origin + Point { hint.xMid - hint.bottomW / 2, LineHeight * 2 }, CircleMenuHintTextColor(IsBottomActive(hint))); } void DrawStartModifierMenu(const CelOutputBuffer &out) @@ -116,8 +120,8 @@ void DrawStartModifierMenu(const CelOutputBuffer &out) return; static const CircleMenuHint DPad(/*isDpad=*/true, /*top=*/_("Menu"), /*right=*/_("Inv"), /*bottom=*/_("Map"), /*left=*/_("Char")); static const CircleMenuHint Buttons(/*isDpad=*/false, /*top=*/"", /*right=*/"", /*bottom=*/_("Spells"), /*left=*/_("Quests")); - DrawCircleMenuHint(out, DPad, PANEL_LEFT + CircleMarginX, PANEL_TOP - CircleTop); - DrawCircleMenuHint(out, Buttons, PANEL_LEFT + PANEL_WIDTH - Buttons.Width() - CircleMarginX, PANEL_TOP - CircleTop); + DrawCircleMenuHint(out, DPad, { PANEL_LEFT + CircleMarginX, PANEL_TOP - CircleTop }); + DrawCircleMenuHint(out, Buttons, { PANEL_LEFT + PANEL_WIDTH - Buttons.Width() - CircleMarginX, PANEL_TOP - CircleTop }); } void DrawSelectModifierMenu(const CelOutputBuffer &out) @@ -126,10 +130,10 @@ void DrawSelectModifierMenu(const CelOutputBuffer &out) return; if (sgOptions.Controller.bDpadHotkeys) { static const CircleMenuHint DPad(/*isDpad=*/true, /*top=*/"F6", /*right=*/"F8", /*bottom=*/"F7", /*left=*/"F5"); - DrawCircleMenuHint(out, DPad, PANEL_LEFT + CircleMarginX, PANEL_TOP - CircleTop); + DrawCircleMenuHint(out, DPad, { PANEL_LEFT + CircleMarginX, PANEL_TOP - CircleTop }); } static const CircleMenuHint Spells(/*isDpad=*/false, "F6", "F8", "F7", "F5"); - DrawCircleMenuHint(out, Spells, PANEL_LEFT + PANEL_WIDTH - Spells.Width() - CircleMarginX, PANEL_TOP - CircleTop); + DrawCircleMenuHint(out, Spells, { PANEL_LEFT + PANEL_WIDTH - Spells.Width() - CircleMarginX, PANEL_TOP - CircleTop }); } } // namespace diff --git a/Source/engine/render/text_render.cpp b/Source/engine/render/text_render.cpp index 39fc182fb..eb3e9310f 100644 --- a/Source/engine/render/text_render.cpp +++ b/Source/engine/render/text_render.cpp @@ -269,9 +269,9 @@ void WordWrapGameString(char *text, size_t width, GameFontTables size, int spaci } /** - * @todo replace SDL_Rect with cropped CelOutputBuffer + * @todo replace Rectangle with cropped CelOutputBuffer */ -int DrawString(const CelOutputBuffer &out, const char *text, const SDL_Rect &rect, uint16_t flags, int spacing, int lineHeight, bool drawTextCursor) +int DrawString(const CelOutputBuffer &out, const char *text, const Rectangle &rect, uint16_t flags, int spacing, int lineHeight, bool drawTextCursor) { GameFontTables size = GameFontSmall; if ((flags & UIS_MED) != 0) @@ -289,9 +289,6 @@ int DrawString(const CelOutputBuffer &out, const char *text, const SDL_Rect &rec else if ((flags & UIS_BLACK) != 0) color = ColorBlack; - const int w = rect.w != 0 ? rect.w : out.w() - rect.x; - const int h = rect.h != 0 ? rect.h : out.h() - rect.y; - const size_t textLength = strlen(text); int charactersInLine = 0; @@ -301,17 +298,18 @@ int DrawString(const CelOutputBuffer &out, const char *text, const SDL_Rect &rec int maxSpacing = spacing; if ((flags & UIS_FIT_SPACING) != 0) - spacing = AdjustSpacingToFitHorizontally(lineWidth, maxSpacing, charactersInLine, rect.w); + spacing = AdjustSpacingToFitHorizontally(lineWidth, maxSpacing, charactersInLine, rect.size.width); - int sx = rect.x; + Point characterPosition = rect.position; + int sx = rect.position.x; if ((flags & UIS_CENTER) != 0) - sx += (w - lineWidth) / 2; + characterPosition.x += (rect.size.width - lineWidth) / 2; else if ((flags & UIS_RIGHT) != 0) - sx += w - lineWidth; - int sy = rect.y; + characterPosition.x += rect.size.width - lineWidth; + characterPosition.y = rect.position.y; - int rightMargin = rect.x + w; - int bottomMargin = rect.y + h; + int rightMargin = rect.position.x + rect.size.width; + int bottomMargin = rect.size.height != 0 ? rect.position.y + rect.size.height : out.h(); if (lineHeight == -1) lineHeight = LineHeights[size]; @@ -320,31 +318,31 @@ int DrawString(const CelOutputBuffer &out, const char *text, const SDL_Rect &rec for (; i < textLength; i++) { uint8_t frame = FontFrame[size][FontIndex[static_cast(text[i])]]; int symbolWidth = FontKern[size][frame]; - if (text[i] == '\n' || sx + symbolWidth > rightMargin) { - if (sy + lineHeight >= bottomMargin) + if (text[i] == '\n' || characterPosition.x + symbolWidth > rightMargin) { + if (characterPosition.y + lineHeight >= bottomMargin) break; - sy += lineHeight; + characterPosition.y += lineHeight; if ((flags & (UIS_CENTER | UIS_RIGHT | UIS_FIT_SPACING)) != 0) lineWidth = GetLineWidth(&text[i + 1], size, spacing, &charactersInLine); if ((flags & UIS_FIT_SPACING) != 0) - spacing = AdjustSpacingToFitHorizontally(lineWidth, maxSpacing, charactersInLine, rect.w); + spacing = AdjustSpacingToFitHorizontally(lineWidth, maxSpacing, charactersInLine, rect.size.width); - sx = rect.x; + characterPosition.x = rect.position.x; if ((flags & UIS_CENTER) != 0) - sx += (w - lineWidth) / 2; + characterPosition.x += (rect.size.width - lineWidth) / 2; else if ((flags & UIS_RIGHT) != 0) - sx += w - lineWidth; + characterPosition.x += rect.size.width - lineWidth; } if (frame != 0) { - DrawChar(out, { sx, sy }, size, frame, color); + DrawChar(out, characterPosition, size, frame, color); } if (text[i] != '\n') - sx += symbolWidth + spacing; + characterPosition.x += symbolWidth + spacing; } if (drawTextCursor) { - CelDrawTo(out, { sx, sy }, *pSPentSpn2Cels, PentSpn2Spin()); + CelDrawTo(out, characterPosition, *pSPentSpn2Cels, PentSpn2Spin()); } return i; diff --git a/Source/engine/render/text_render.hpp b/Source/engine/render/text_render.hpp index 325d6d830..213528ef4 100644 --- a/Source/engine/render/text_render.hpp +++ b/Source/engine/render/text_render.hpp @@ -12,6 +12,7 @@ #include "DiabloUI/ui_item.h" #include "engine.h" #include "engine/cel_sprite.hpp" +#include "engine/rectangle.hpp" #include "utils/stdcompat/optional.hpp" namespace devilution { @@ -36,7 +37,52 @@ void InitText(); */ int GetLineWidth(const char *text, GameFontTables size = GameFontSmall, int spacing = 1, int *charactersInLine = nullptr); void WordWrapGameString(char *text, size_t width, GameFontTables size = GameFontSmall, int spacing = 1); -int DrawString(const CelOutputBuffer &out, const char *text, const SDL_Rect &rect, uint16_t flags = 0, int spacing = 1, int lineHeight = -1, bool drawTextCursor = false); + +/** + * @brief Draws a line of text within a clipping rectangle (positioned relative to the origin of the output buffer). + * + * Specifying a small width (0 to less than two characters wide) should be avoided as this causes issues when laying + * out the text. To wrap based on available space use the overload taking a Point. If the rect passed through has 0 + * height then the clipping area is extended to the bottom edge of the output buffer. If the clipping rectangle + * dimensions extend past the edge of the output buffer text wrapping will be calculated using those dimensions (as if + * the text was being rendered off screen). The text will not actually be drawn beyond the bounds of the output + * buffer, this is purely to allow for clipping without wrapping. + * + * @param out The screen buffer to draw on. + * @param text String to be drawn. + * @param rect Clipping region relative to the output buffer describing where to draw the text and when to wrap long lines. + * @param flags A combination of UiFlags to describe font size, color, alignment, etc. See ui_items.h for available options + * @param spacing Additional space to add between characters. + * This value may be adjusted if the flag UIS_FIT_SPACING is passed in the flags parameter. + * @param lineHeight Allows overriding the default line height, useful for multi-line strings. + * @param drawTextCursor Whether to draw an animated cursor sprite at the end of the text (default is to display nothing). + * @return The number of characters rendered, including characters "drawn" outside the buffer. +*/ +int DrawString(const CelOutputBuffer &out, const char *text, const Rectangle &rect, uint16_t flags = 0, int spacing = 1, int lineHeight = -1, bool drawTextCursor = false); + +/** + * @brief Draws a line of text at the given position relative to the origin of the output buffer. + * + * This method is provided as a convenience to pass through to DrawString(..., Rectangle, ...) when no explicit + + * clipping/wrapping is requested. Note that this will still wrap the rendered string if it would end up being drawn + * beyond the right edge of the output buffer and clip it if it would extend beyond the bottom edge of the buffer. + * + * @param out The screen buffer to draw on. + * @param text String to be drawn. + * @param position Location of the top left corner of the string relative to the top left corner of the output buffer. + * @param flags A combination of UiFlags to describe font size, color, alignment, etc. See ui_items.h for available options + * @param spacing Additional space to add between characters. + * This value may be adjusted if the flag UIS_FIT_SPACING is passed in the flags parameter. + * @param lineHeight Allows overriding the default line height, useful for multi-line strings. + * @param drawTextCursor Whether to draw an animated cursor sprite at the end of the text (default is to display nothing). + * @return The number of characters rendered (could be less than the string length if it wrapped past the bottom of the buffer). +*/ +inline int DrawString(const CelOutputBuffer &out, const char *text, const Point &position, uint16_t flags = 0, int spacing = 1, int lineHeight = -1, bool drawTextCursor = false) +{ + return DrawString(out, text, { position.x, position.y, out.w() - position.x, 0 }, flags, spacing, lineHeight, drawTextCursor); +} + int PentSpn2Spin(); } // namespace devilution diff --git a/Source/gmenu.cpp b/Source/gmenu.cpp index 542f8d5d5..178a9cfb3 100644 --- a/Source/gmenu.cpp +++ b/Source/gmenu.cpp @@ -41,7 +41,7 @@ void gmenu_draw_pause(const CelOutputBuffer &out) RedBack(out); if (sgpCurrentMenu == nullptr) { light_table_index = 0; - DrawString(out, _("Pause"), { PANEL_LEFT + 252, PANEL_TOP / 2, 0, 0 }, UIS_HUGE, 2); + DrawString(out, _("Pause"), Point { 0, PANEL_TOP / 2 }, UIS_HUGE | UIS_CENTER, 2); } } @@ -177,7 +177,7 @@ static void GmenuDrawMenuItem(const CelOutputBuffer &out, TMenuItem *pItem, int int x = (gnScreenWidth - w) / 2; uint16_t style = (pItem->dwFlags & GMENU_ENABLED) != 0 ? UIS_SILVER : UIS_BLACK; - DrawString(out, _(pItem->pszStr), { x, y, 0, 0 }, style | UIS_HUGE, 2); + DrawString(out, _(pItem->pszStr), Point { x, y }, style | UIS_HUGE, 2); if (pItem == sgpCurrItem) { CelDrawTo(out, { x - 54, y + 1 }, *PentSpin_cel, PentSpn2Spin()); CelDrawTo(out, { x + 4 + w, y + 1 }, *PentSpin_cel, PentSpn2Spin()); diff --git a/Source/inv.cpp b/Source/inv.cpp index b50961aba..aeaf58bf3 100644 --- a/Source/inv.cpp +++ b/Source/inv.cpp @@ -330,14 +330,8 @@ void DrawInvBelt(const CelOutputBuffer &out) if (AllItemsList[myPlayer.SpdList[i].IDidx].iUsable && myPlayer.SpdList[i]._iStatFlag && myPlayer.SpdList[i]._itype != ITYPE_GOLD) { - sprintf(tempstr, "%i", i + 1); - SDL_Rect rect { - InvRect[i + SLOTXY_BELT_FIRST].x + PANEL_X + InventorySlotSizeInPixels.width - GetLineWidth(tempstr), - InvRect[i + SLOTXY_BELT_FIRST].y + PANEL_Y - 1, - 0, - 0 - }; - DrawString(out, tempstr, rect, UIS_SILVER); + snprintf(tempstr, sizeof(tempstr) / sizeof(*tempstr), "%i", i + 1); + DrawString(out, tempstr, { position, InventorySlotSizeInPixels }, UIS_SILVER | UIS_RIGHT); } } } diff --git a/Source/items.cpp b/Source/items.cpp index 9e3ce3c92..1cf6e850a 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -3689,37 +3689,37 @@ void DrawUniqueInfo(const CelOutputBuffer &out) DrawUTextBack(GlobalBackBuffer()); - SDL_Rect rect { 32 + RIGHT_PANEL - SPANEL_WIDTH, 44 + 2 * 12, 257, 0 }; + Rectangle rect { 32 + RIGHT_PANEL - SPANEL_WIDTH, 44 + 2 * 12, 257, 0 }; const UItemStruct &uitem = UniqueItemList[curruitem._iUid]; DrawString(out, _(uitem.UIName), rect, UIS_CENTER); DrawULine(out, 5); - rect.y += (12 - uitem.UINumPL) * 12; + rect.position.y += (12 - uitem.UINumPL) * 12; PrintItemPower(uitem.UIPower1, &curruitem); DrawString(out, tempstr, rect, UIS_SILVER | UIS_CENTER); if (uitem.UINumPL > 1) { - rect.y += 2 * 12; + rect.position.y += 2 * 12; PrintItemPower(uitem.UIPower2, &curruitem); DrawString(out, tempstr, rect, UIS_SILVER | UIS_CENTER); } if (uitem.UINumPL > 2) { - rect.y += 2 * 12; + rect.position.y += 2 * 12; PrintItemPower(uitem.UIPower3, &curruitem); DrawString(out, tempstr, rect, UIS_SILVER | UIS_CENTER); } if (uitem.UINumPL > 3) { - rect.y += 2 * 12; + rect.position.y += 2 * 12; PrintItemPower(uitem.UIPower4, &curruitem); DrawString(out, tempstr, rect, UIS_SILVER | UIS_CENTER); } if (uitem.UINumPL > 4) { - rect.y += 2 * 12; + rect.position.y += 2 * 12; PrintItemPower(uitem.UIPower5, &curruitem); DrawString(out, tempstr, rect, UIS_SILVER | UIS_CENTER); } if (uitem.UINumPL > 5) { - rect.y += 2 * 12; + rect.position.y += 2 * 12; PrintItemPower(uitem.UIPower6, &curruitem); DrawString(out, tempstr, rect, UIS_SILVER | UIS_CENTER); } diff --git a/Source/scrollrt.cpp b/Source/scrollrt.cpp index ec2043946..bfb64b932 100644 --- a/Source/scrollrt.cpp +++ b/Source/scrollrt.cpp @@ -1441,7 +1441,7 @@ static void DrawFPS(const CelOutputBuffer &out) frameend = 0; } snprintf(String, 12, "%i FPS", framerate); - DrawString(out, String, { 8, 65, 0, 0 }, UIS_RED); + DrawString(out, String, Point { 8, 65 }, UIS_RED); } } diff --git a/Source/stores.cpp b/Source/stores.cpp index b7aea56ef..fa57a926b 100644 --- a/Source/stores.cpp +++ b/Source/stores.cpp @@ -2219,21 +2219,21 @@ void FreeStoreMem() pSTextSlidCels = std::nullopt; } -static void DrawSelector(const CelOutputBuffer &out, const SDL_Rect &rect, const char *text, uint16_t flags) +static void DrawSelector(const CelOutputBuffer &out, const Rectangle &rect, const char *text, uint16_t flags) { int lineWidth = GetLineWidth(text); - int x1 = rect.x - 20; + int x1 = rect.position.x - 20; if ((flags & UIS_CENTER) != 0) - x1 += (rect.w - lineWidth) / 2; + x1 += (rect.size.width - lineWidth) / 2; - CelDrawTo(out, { x1, rect.y + 1 }, *pSPentSpn2Cels, PentSpn2Spin()); + CelDrawTo(out, { x1, rect.position.y + 1 }, *pSPentSpn2Cels, PentSpn2Spin()); - int x2 = rect.x + rect.w + 5; + int x2 = rect.position.x + rect.size.width + 5; if ((flags & UIS_CENTER) != 0) - x2 = rect.x + (rect.w - lineWidth) / 2 + lineWidth + 5; + x2 = rect.position.x + (rect.size.width - lineWidth) / 2 + lineWidth + 5; - CelDrawTo(out, { x2, rect.y + 1 }, *pSPentSpn2Cels, PentSpn2Spin()); + CelDrawTo(out, { x2, rect.position.y + 1 }, *pSPentSpn2Cels, PentSpn2Spin()); } void PrintSString(const CelOutputBuffer &out, int margin, int line, const char *text, uint16_t flags, int price) @@ -2251,7 +2251,7 @@ void PrintSString(const CelOutputBuffer &out, int margin, int line, const char * } width -= margin * 2; - const SDL_Rect rect { sx, sy, width, 0 }; + const Rectangle rect { sx, sy, width, 0 }; DrawString(out, text, rect, flags); if (price > 0) { char valstr[32];