Browse Source

Adding text rendering flag to adjust spacing to fit horizontally

Now also works for multiline strings
pull/1999/head
thebigMuh 5 years ago committed by Anders Jenbo
parent
commit
7fbcfeb35c
  1. 29
      Source/DiabloUI/ui_item.h
  2. 4
      Source/control.cpp
  3. 53
      Source/engine/render/text_render.cpp
  4. 11
      Source/engine/render/text_render.hpp

29
Source/DiabloUI/ui_item.h

@ -24,20 +24,21 @@ enum UiType : uint8_t {
enum UiFlags : uint16_t { enum UiFlags : uint16_t {
// clang-format off // clang-format off
UIS_SMALL = 1 << 0, UIS_SMALL = 1 << 0,
UIS_MED = 1 << 1, UIS_MED = 1 << 1,
UIS_BIG = 1 << 2, UIS_BIG = 1 << 2,
UIS_HUGE = 1 << 3, UIS_HUGE = 1 << 3,
UIS_CENTER = 1 << 4, UIS_CENTER = 1 << 4,
UIS_RIGHT = 1 << 5, UIS_RIGHT = 1 << 5,
UIS_VCENTER = 1 << 6, UIS_VCENTER = 1 << 6,
UIS_SILVER = 1 << 7, UIS_SILVER = 1 << 7,
UIS_GOLD = 1 << 8, UIS_GOLD = 1 << 8,
UIS_RED = 1 << 9, UIS_RED = 1 << 9,
UIS_BLUE = 1 << 10, UIS_BLUE = 1 << 10,
UIS_BLACK = 1 << 11, UIS_BLACK = 1 << 11,
UIS_DISABLED = 1 << 12, UIS_DISABLED = 1 << 12,
UIS_HIDDEN = 1 << 13, UIS_HIDDEN = 1 << 13,
UIS_FIT_SPACING = 1 << 14,
// clang-format on // clang-format on
}; };

4
Source/control.cpp

@ -1095,14 +1095,14 @@ static void PrintInfo(const CelOutputBuffer &out)
int yo = 0; int yo = 0;
int lo = 1; int lo = 1;
if (infostr[0] != '\0') { if (infostr[0] != '\0') {
DrawString(out, infostr, line, infoclr | UIS_CENTER, 2); DrawString(out, infostr, line, infoclr | UIS_CENTER | UIS_FIT_SPACING, 2);
yo = 1; yo = 1;
lo = 0; lo = 0;
} }
for (int i = 0; i < pnumlines; i++) { for (int i = 0; i < pnumlines; i++) {
line.y = PANEL_Y + LineOffsets[pnumlines - lo][i + yo]; line.y = PANEL_Y + LineOffsets[pnumlines - lo][i + yo];
DrawString(out, panelstr[i], line, infoclr | UIS_CENTER, 2); DrawString(out, panelstr[i], line, infoclr | UIS_CENTER | UIS_FIT_SPACING, 2);
} }
} }

53
Source/engine/render/text_render.cpp

@ -194,12 +194,13 @@ void PrintChar(const CelOutputBuffer &out, int sx, int sy, int nCel, text_color
} }
} }
int GetLineWidth(const char *text, GameFontTables size, int spacing) int GetLineWidth(const char *text, GameFontTables size, int spacing, int *charactersInLine)
{ {
int lineWidth = 0; int lineWidth = 0;
size_t textLength = strlen(text); size_t textLength = strlen(text);
for (unsigned i = 0; i < textLength; i++) { size_t i = 0;
for (; i < textLength; i++) {
if (text[i] == '\n') if (text[i] == '\n')
break; break;
@ -207,9 +208,23 @@ int GetLineWidth(const char *text, GameFontTables size, int spacing)
lineWidth += fontkern[size][frame] + spacing; lineWidth += fontkern[size][frame] + spacing;
} }
if (charactersInLine != nullptr)
*charactersInLine = i;
return lineWidth != 0 ? (lineWidth - spacing) : 0; return lineWidth != 0 ? (lineWidth - spacing) : 0;
} }
int AdjustSpacingToFitHorizontally(int &lineWidth, int maxSpacing, int charactersInLine, int availableWidth)
{
if (lineWidth <= availableWidth || charactersInLine < 2)
return maxSpacing;
const int overhang = lineWidth - availableWidth;
const int spacingRedux = (overhang + charactersInLine - 2) / (charactersInLine - 1);
lineWidth -= spacingRedux * (charactersInLine - 1);
return maxSpacing - spacingRedux;
}
void WordWrapGameString(char *text, size_t width, size_t size, int spacing) void WordWrapGameString(char *text, size_t width, size_t size, int spacing)
{ {
const size_t textLength = strlen(text); const size_t textLength = strlen(text);
@ -272,28 +287,44 @@ void DrawString(const CelOutputBuffer &out, const char *text, const SDL_Rect &re
color = COL_BLACK; color = COL_BLACK;
const int w = rect.w != 0 ? rect.w : out.w() - rect.x; const int w = rect.w != 0 ? rect.w : out.w() - rect.x;
const int h = rect.h != 0 ? rect.h : out.h() - rect.x; const int h = rect.h != 0 ? rect.h : out.h() - rect.y;
const size_t textLength = strlen(text);
int charactersInLine = 0;
int lineWidth = 0;
if ((flags & (UIS_CENTER | UIS_RIGHT | UIS_FIT_SPACING)) != 0)
lineWidth = GetLineWidth(text, size, spacing, &charactersInLine);
int maxSpacing = spacing;
if ((flags & UIS_FIT_SPACING) != 0)
spacing = AdjustSpacingToFitHorizontally(lineWidth, maxSpacing, charactersInLine, rect.w);
int sx = rect.x; int sx = rect.x;
if ((flags & UIS_CENTER) != 0) if ((flags & UIS_CENTER) != 0)
sx += (w - GetLineWidth(text, size, spacing)) / 2; sx += (w - lineWidth) / 2;
else if ((flags & UIS_RIGHT) != 0) else if ((flags & UIS_RIGHT) != 0)
sx += w - GetLineWidth(text, size, spacing); sx += w - lineWidth;
int sy = rect.y; int sy = rect.y;
int rightMargin = rect.x + w; int rightMargin = rect.x + w;
int bottomMargin = rect.y + h; int bottomMargin = rect.y + h;
const size_t textLength = strlen(text);
for (unsigned i = 0; i < textLength; i++) { for (unsigned i = 0; i < textLength; i++) {
uint8_t frame = fontframe[size][gbFontTransTbl[static_cast<uint8_t>(text[i])]]; uint8_t frame = fontframe[size][gbFontTransTbl[static_cast<uint8_t>(text[i])]];
int symbolWidth = fontkern[size][frame] + spacing; int symbolWidth = fontkern[size][frame];
if (text[i] == '\n' || sx + symbolWidth - spacing > rightMargin) { if (text[i] == '\n' || sx + symbolWidth > rightMargin) {
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);
sx = rect.x; sx = rect.x;
if ((flags & UIS_CENTER) != 0) if ((flags & UIS_CENTER) != 0)
sx += (w - GetLineWidth(&text[i + 1], size)) / 2; sx += (w - lineWidth) / 2;
else if ((flags & UIS_RIGHT) != 0) else if ((flags & UIS_RIGHT) != 0)
sx += w - GetLineWidth(&text[i + 1], size, spacing); sx += w - lineWidth;
sy += LineHeights[size]; sy += LineHeights[size];
if (sy > bottomMargin) if (sy > bottomMargin)
return; return;
@ -302,7 +333,7 @@ void DrawString(const CelOutputBuffer &out, const char *text, const SDL_Rect &re
PrintChar(out, sx, sy, frame, color); PrintChar(out, sx, sy, frame, color);
} }
if (text[i] != '\n') if (text[i] != '\n')
sx += symbolWidth; sx += symbolWidth + spacing;
} }
if (drawTextCursor) { if (drawTextCursor) {
CelDrawTo(out, sx, sy, *pSPentSpn2Cels, PentSpn2Spin()); CelDrawTo(out, sx, sy, *pSPentSpn2Cels, PentSpn2Spin());

11
Source/engine/render/text_render.hpp

@ -50,7 +50,16 @@ void FreeText();
* @param col text_color color value * @param col text_color color value
*/ */
void PrintChar(const CelOutputBuffer &out, int sx, int sy, int nCel, text_color col); void PrintChar(const CelOutputBuffer &out, int sx, int sy, int nCel, text_color col);
int GetLineWidth(const char *text, GameFontTables size = GameFontSmall, int spacing = 1);
/**
* @brief Calculate pixel width of first line of text, respecting kerning
* @param text Text to check, will read until first eol or terminator
* @param size Font size to use
* @param spacing Extra spacing to add per character
* @param charactersInLine Receives characters read until newline or terminator
* @return Line width in pixels
*/
int GetLineWidth(const char *text, GameFontTables size = GameFontSmall, int spacing = 1, int *charactersInLine = nullptr);
void WordWrapGameString(char *text, size_t width, size_t size = GameFontSmall, int spacing = 1); void WordWrapGameString(char *text, size_t width, size_t size = GameFontSmall, int spacing = 1);
void DrawString(const CelOutputBuffer &out, const char *text, const SDL_Rect &rect, uint16_t flags = 0, int spacing = 1, bool drawTextCursor = false); void DrawString(const CelOutputBuffer &out, const char *text, const SDL_Rect &rect, uint16_t flags = 0, int spacing = 1, bool drawTextCursor = false);
int PentSpn2Spin(); int PentSpn2Spin();

Loading…
Cancel
Save