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 {
// clang-format off
UIS_SMALL = 1 << 0,
UIS_MED = 1 << 1,
UIS_BIG = 1 << 2,
UIS_HUGE = 1 << 3,
UIS_CENTER = 1 << 4,
UIS_RIGHT = 1 << 5,
UIS_VCENTER = 1 << 6,
UIS_SILVER = 1 << 7,
UIS_GOLD = 1 << 8,
UIS_RED = 1 << 9,
UIS_BLUE = 1 << 10,
UIS_BLACK = 1 << 11,
UIS_DISABLED = 1 << 12,
UIS_HIDDEN = 1 << 13,
UIS_SMALL = 1 << 0,
UIS_MED = 1 << 1,
UIS_BIG = 1 << 2,
UIS_HUGE = 1 << 3,
UIS_CENTER = 1 << 4,
UIS_RIGHT = 1 << 5,
UIS_VCENTER = 1 << 6,
UIS_SILVER = 1 << 7,
UIS_GOLD = 1 << 8,
UIS_RED = 1 << 9,
UIS_BLUE = 1 << 10,
UIS_BLACK = 1 << 11,
UIS_DISABLED = 1 << 12,
UIS_HIDDEN = 1 << 13,
UIS_FIT_SPACING = 1 << 14,
// clang-format on
};

4
Source/control.cpp

@ -1095,14 +1095,14 @@ static void PrintInfo(const CelOutputBuffer &out)
int yo = 0;
int lo = 1;
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;
lo = 0;
}
for (int i = 0; i < pnumlines; i++) {
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;
size_t textLength = strlen(text);
for (unsigned i = 0; i < textLength; i++) {
size_t i = 0;
for (; i < textLength; i++) {
if (text[i] == '\n')
break;
@ -207,9 +208,23 @@ int GetLineWidth(const char *text, GameFontTables size, int spacing)
lineWidth += fontkern[size][frame] + spacing;
}
if (charactersInLine != nullptr)
*charactersInLine = i;
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)
{
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;
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;
if ((flags & UIS_CENTER) != 0)
sx += (w - GetLineWidth(text, size, spacing)) / 2;
sx += (w - lineWidth) / 2;
else if ((flags & UIS_RIGHT) != 0)
sx += w - GetLineWidth(text, size, spacing);
sx += w - lineWidth;
int sy = rect.y;
int rightMargin = rect.x + w;
int bottomMargin = rect.y + h;
const size_t textLength = strlen(text);
for (unsigned i = 0; i < textLength; i++) {
uint8_t frame = fontframe[size][gbFontTransTbl[static_cast<uint8_t>(text[i])]];
int symbolWidth = fontkern[size][frame] + spacing;
if (text[i] == '\n' || sx + symbolWidth - spacing > rightMargin) {
int symbolWidth = fontkern[size][frame];
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;
if ((flags & UIS_CENTER) != 0)
sx += (w - GetLineWidth(&text[i + 1], size)) / 2;
sx += (w - lineWidth) / 2;
else if ((flags & UIS_RIGHT) != 0)
sx += w - GetLineWidth(&text[i + 1], size, spacing);
sx += w - lineWidth;
sy += LineHeights[size];
if (sy > bottomMargin)
return;
@ -302,7 +333,7 @@ void DrawString(const CelOutputBuffer &out, const char *text, const SDL_Rect &re
PrintChar(out, sx, sy, frame, color);
}
if (text[i] != '\n')
sx += symbolWidth;
sx += symbolWidth + spacing;
}
if (drawTextCursor) {
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
*/
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 DrawString(const CelOutputBuffer &out, const char *text, const SDL_Rect &rect, uint16_t flags = 0, int spacing = 1, bool drawTextCursor = false);
int PentSpn2Spin();

Loading…
Cancel
Save