Fix vertical centering of multi-line UI labels

Also calculate text height in `TextWidth`.

Use calculated text height to verically center UI labels.

The text cursor flags (in particular, the `TEXTFLAG_STOP_AT_END` flag) must also be passed to `TextWidth`. Otherwise, for example, when `TEXTFLAG_STOP_AT_END` is missing, the wrong text height is calculated, as text is rendered over multiple lines instead of stopping at the end of the first line.

Closes #5396.
This commit is contained in:
Robert Müller 2023-04-09 17:28:58 +02:00
parent 07c59d130b
commit 9693d4beac
4 changed files with 20 additions and 17 deletions

View file

@ -831,18 +831,20 @@ public:
SetRenderFlags(OldRenderFlags);
}
float TextWidth(float Size, const char *pText, int StrLength, float LineWidth, float *pAlignedHeight = nullptr, float *pMaxCharacterHeightInLine = nullptr) override
float TextWidth(float Size, const char *pText, int StrLength, float LineWidth, int Flags = 0, float *pHeight = nullptr, float *pAlignedFontSize = nullptr, float *pMaxCharacterHeightInLine = nullptr) override
{
CTextCursor Cursor;
SetCursor(&Cursor, 0, 0, Size, 0);
SetCursor(&Cursor, 0, 0, Size, Flags);
Cursor.m_LineWidth = LineWidth;
const unsigned OldRenderFlags = m_RenderFlags;
if(LineWidth <= 0)
SetRenderFlags(OldRenderFlags | ETextRenderFlags::TEXT_RENDER_FLAG_NO_FIRST_CHARACTER_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_LAST_CHARACTER_ADVANCE);
TextEx(&Cursor, pText, StrLength);
SetRenderFlags(OldRenderFlags);
if(pAlignedHeight != nullptr)
*pAlignedHeight = Cursor.m_AlignedFontSize;
if(pHeight != nullptr)
*pHeight = Cursor.Height();
if(pAlignedFontSize != nullptr)
*pAlignedFontSize = Cursor.m_AlignedFontSize;
if(pMaxCharacterHeightInLine != nullptr)
*pMaxCharacterHeightInLine = Cursor.m_MaxCharacterHeight;
return Cursor.m_LongestLineWidth;

View file

@ -229,7 +229,7 @@ public:
virtual void TextSelectionColor(float r, float g, float b, float a) = 0;
virtual void TextSelectionColor(ColorRGBA rgb) = 0;
virtual void Text(float x, float y, float Size, const char *pText, float LineWidth) = 0;
virtual float TextWidth(float Size, const char *pText, int StrLength, float LineWidth, float *pAlignedHeight = nullptr, float *pMaxCharacterHeightInLine = nullptr) = 0;
virtual float TextWidth(float Size, const char *pText, int StrLength, float LineWidth, int Flags = 0, float *pHeight = nullptr, float *pAlignedFontSize = nullptr, float *pMaxCharacterHeightInLine = nullptr) = 0;
virtual int TextLineCount(float Size, const char *pText, float LineWidth) = 0;
virtual ColorRGBA GetTextColor() const = 0;

View file

@ -862,8 +862,7 @@ void CMenus::RenderSettingsTee(CUIRect MainView)
OriginalRect.VSplitLeft(60.0f, 0, &Label);
{
SLabelProperties Props;
Props.m_MaxWidth = Label.w;
Props.m_AlignVertically = 0;
Props.m_MaxWidth = Label.w - 5.0f;
UI()->DoLabel(&Label, pSkinToBeDraw->GetName(), 12.0f, TEXTALIGN_LEFT, Props);
}
if(g_Config.m_Debug)

View file

@ -519,10 +519,12 @@ void CUI::DoSmoothScrollLogic(float *pScrollOffset, float *pScrollOffsetChange,
void CUI::DoLabel(const CUIRect *pRect, const char *pText, float Size, int Align, const SLabelProperties &LabelProps)
{
int Flags = LabelProps.m_StopAtEnd ? TEXTFLAG_STOP_AT_END : 0;
float TextHeight = 0.0f;
float AlignedFontSize = 0.0f;
float MaxCharacterHeightInLine = 0.0f;
float MaxTextWidth = LabelProps.m_MaxWidth != -1 ? LabelProps.m_MaxWidth : pRect->w;
float TextWidth = TextRender()->TextWidth(Size, pText, -1, LabelProps.m_MaxWidth, &AlignedFontSize, &MaxCharacterHeightInLine);
float TextWidth = TextRender()->TextWidth(Size, pText, -1, LabelProps.m_MaxWidth, Flags, &TextHeight, &AlignedFontSize, &MaxCharacterHeightInLine);
while(TextWidth > MaxTextWidth + 0.001f)
{
if(!LabelProps.m_EnableWidthCheck)
@ -530,7 +532,7 @@ void CUI::DoLabel(const CUIRect *pRect, const char *pText, float Size, int Align
if(Size < 4.0f)
break;
Size -= 1.0f;
TextWidth = TextRender()->TextWidth(Size, pText, -1, LabelProps.m_MaxWidth, &AlignedFontSize, &MaxCharacterHeightInLine);
TextWidth = TextRender()->TextWidth(Size, pText, -1, LabelProps.m_MaxWidth, Flags, &TextHeight, &AlignedFontSize, &MaxCharacterHeightInLine);
}
float CursorX = 0.0f;
@ -547,15 +549,14 @@ void CUI::DoLabel(const CUIRect *pRect, const char *pText, float Size, int Align
CursorX = pRect->x + pRect->w - TextWidth;
}
float CursorY = pRect->y + (pRect->h - AlignedFontSize) / 2.f;
float CursorY = pRect->y + (pRect->h - TextHeight) / 2.f;
if(LabelProps.m_AlignVertically == 0)
{
CursorY = pRect->y + (pRect->h - AlignedFontSize) / 2.f - (AlignedFontSize - MaxCharacterHeightInLine) / 2.f;
}
CTextCursor Cursor;
int Flags = TEXTFLAG_RENDER | (LabelProps.m_StopAtEnd ? TEXTFLAG_STOP_AT_END : 0);
TextRender()->SetCursor(&Cursor, AlignmentHori, AlignmentVert, Size, Flags);
TextRender()->SetCursor(&Cursor, CursorX, CursorY, Size, TEXTFLAG_RENDER | Flags);
Cursor.m_LineWidth = (float)LabelProps.m_MaxWidth;
if(LabelProps.m_pSelCursor)
{
@ -581,10 +582,12 @@ void CUI::DoLabel(const CUIRect *pRect, const char *pText, float Size, int Align
void CUI::DoLabel(CUIElement::SUIElementRect &RectEl, const CUIRect *pRect, const char *pText, float Size, int Align, const SLabelProperties &LabelProps, int StrLen, const CTextCursor *pReadCursor)
{
int Flags = pReadCursor ? (pReadCursor->m_Flags & ~TEXTFLAG_RENDER) : LabelProps.m_StopAtEnd ? TEXTFLAG_STOP_AT_END : 0;
float TextHeight = 0.0f;
float AlignedFontSize = 0.0f;
float MaxCharacterHeightInLine = 0.0f;
float MaxTextWidth = LabelProps.m_MaxWidth != -1 ? LabelProps.m_MaxWidth : pRect->w;
float TextWidth = TextRender()->TextWidth(Size, pText, -1, LabelProps.m_MaxWidth, &AlignedFontSize, &MaxCharacterHeightInLine);
float TextWidth = TextRender()->TextWidth(Size, pText, -1, LabelProps.m_MaxWidth, Flags, &TextHeight, &AlignedFontSize, &MaxCharacterHeightInLine);
while(TextWidth > MaxTextWidth + 0.001f)
{
if(!LabelProps.m_EnableWidthCheck)
@ -592,7 +595,7 @@ void CUI::DoLabel(CUIElement::SUIElementRect &RectEl, const CUIRect *pRect, cons
if(Size < 4.0f)
break;
Size -= 1.0f;
TextWidth = TextRender()->TextWidth(Size, pText, -1, LabelProps.m_MaxWidth, &AlignedFontSize, &MaxCharacterHeightInLine);
TextWidth = TextRender()->TextWidth(Size, pText, -1, LabelProps.m_MaxWidth, Flags, &TextHeight, &AlignedFontSize, &MaxCharacterHeightInLine);
}
float CursorX = 0;
@ -609,7 +612,7 @@ void CUI::DoLabel(CUIElement::SUIElementRect &RectEl, const CUIRect *pRect, cons
CursorX = pRect->x + pRect->w - TextWidth;
}
float CursorY = pRect->y + (pRect->h - AlignedFontSize) / 2.f;
float CursorY = pRect->y + (pRect->h - TextHeight) / 2.f;
if(LabelProps.m_AlignVertically == 0)
{
CursorY = pRect->y + (pRect->h - AlignedFontSize) / 2.f - (AlignedFontSize - MaxCharacterHeightInLine) / 2.f;
@ -622,8 +625,7 @@ void CUI::DoLabel(CUIElement::SUIElementRect &RectEl, const CUIRect *pRect, cons
}
else
{
int Flags = TEXTFLAG_RENDER | (LabelProps.m_StopAtEnd ? TEXTFLAG_STOP_AT_END : 0);
TextRender()->SetCursor(&Cursor, CursorX, CursorY, Size, Flags);
TextRender()->SetCursor(&Cursor, CursorX, CursorY, Size, TEXTFLAG_RENDER | Flags);
}
Cursor.m_LineWidth = LabelProps.m_MaxWidth;