6551: Fix Y Alignment by respecting cursor height independent of character … r=Robyt3 a=Jupeyy

…height

since the cursor height is simply the font size, but obv not all characters use the full font size, it must additionally make sure that this size isn't ignored in the y offset calculation (since it makes the characters render at the offset of the cursor height), so basically:
0 + FontSize == Character start
CharacterHeight != FontSize

that moves the character down.

Also added back the render flags, i think it logically makes sense if they are there, since a character could have y bearing, even tho in this case it doesn't seem the case.

fixes #6538 

I haven't extensively checked this, and maybe `@Robyt3` prefers to fix it differently, I'd be ok with this, it's just for showcase

## Checklist

- [ ] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: Jupeyy <jupjopjap@gmail.com>
This commit is contained in:
bors[bot] 2023-05-08 19:45:54 +00:00 committed by GitHub
commit 23ce76210d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 21 deletions

View file

@ -839,18 +839,20 @@ public:
TextEx(&Cursor, pText, -1);
}
float TextWidth(float Size, const char *pText, int StrLength = -1, float LineWidth = -1.0f, int Flags = 0, float *pHeight = nullptr, float *pAlignedFontSize = nullptr, float *pMaxCharacterHeightInLine = nullptr) override
float TextWidth(float Size, const char *pText, int StrLength = -1, float LineWidth = -1.0f, int Flags = 0, const STextSizeProperties &TextSizeProps = {}) override
{
CTextCursor Cursor;
SetCursor(&Cursor, 0, 0, Size, Flags);
Cursor.m_LineWidth = LineWidth;
TextEx(&Cursor, pText, StrLength);
if(pHeight != nullptr)
*pHeight = Cursor.Height();
if(pAlignedFontSize != nullptr)
*pAlignedFontSize = Cursor.m_AlignedFontSize;
if(pMaxCharacterHeightInLine != nullptr)
*pMaxCharacterHeightInLine = Cursor.m_MaxCharacterHeight;
if(TextSizeProps.m_pHeight != nullptr)
*TextSizeProps.m_pHeight = Cursor.Height();
if(TextSizeProps.m_pAlignedFontSize != nullptr)
*TextSizeProps.m_pAlignedFontSize = Cursor.m_AlignedFontSize;
if(TextSizeProps.m_pMaxCharacterHeightInLine != nullptr)
*TextSizeProps.m_pMaxCharacterHeightInLine = Cursor.m_MaxCharacterHeight;
if(TextSizeProps.m_pLineCount != nullptr)
*TextSizeProps.m_pLineCount = Cursor.m_LineCount;
return Cursor.m_LongestLineWidth;
}

View file

@ -221,6 +221,14 @@ struct STextContainerIndex
void Reset() { m_Index = -1; }
};
struct STextSizeProperties
{
float *m_pHeight = nullptr;
float *m_pAlignedFontSize = nullptr;
float *m_pMaxCharacterHeightInLine = nullptr;
int *m_pLineCount = nullptr;
};
class ITextRender : public IInterface
{
MACRO_INTERFACE("textrender", 0)
@ -279,7 +287,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 = -1.0f) = 0;
virtual float TextWidth(float Size, const char *pText, int StrLength = -1, float LineWidth = -1.0f, int Flags = 0, float *pHeight = nullptr, float *pAlignedFontSize = nullptr, float *pMaxCharacterHeightInLine = nullptr) = 0;
virtual float TextWidth(float Size, const char *pText, int StrLength = -1, float LineWidth = -1.0f, int Flags = 0, const STextSizeProperties &TextSizeProps = {}) = 0;
virtual STextBoundingBox TextBoundingBox(float Size, const char *pText, int StrLength = -1, float LineWidth = -1.0f, int Flags = 0) = 0;
virtual ColorRGBA GetTextColor() const = 0;

View file

@ -547,11 +547,24 @@ void CUI::DoSmoothScrollLogic(float *pScrollOffset, float *pScrollOffsetChange,
}
}
static vec2 CalcFontSizeAndBoundingBox(ITextRender *pTextRender, const char *pText, int Flags, float &Size, float MaxWidth, const SLabelProperties &LabelProps)
struct SCursorAndBoundingBox
{
vec2 m_TextSize;
float m_BiggestCharacterHeight;
int m_LineCount;
};
static SCursorAndBoundingBox CalcFontSizeCursorHeightAndBoundingBox(ITextRender *pTextRender, const char *pText, int Flags, float &Size, float MaxWidth, const SLabelProperties &LabelProps)
{
float TextBoundingHeight = 0.0f;
float TextHeight = 0.0f;
int LineCount = 0;
float MaxTextWidth = LabelProps.m_MaxWidth != -1 ? LabelProps.m_MaxWidth : MaxWidth;
float TextWidth = pTextRender->TextWidth(Size, pText, -1, LabelProps.m_MaxWidth, Flags, &TextHeight);
STextSizeProperties TextSizeProps{};
TextSizeProps.m_pHeight = &TextHeight;
TextSizeProps.m_pMaxCharacterHeightInLine = &TextBoundingHeight;
TextSizeProps.m_pLineCount = &LineCount;
float TextWidth = pTextRender->TextWidth(Size, pText, -1, LabelProps.m_MaxWidth, Flags, TextSizeProps);
while(TextWidth > MaxTextWidth + 0.001f)
{
if(!LabelProps.m_EnableWidthCheck)
@ -559,12 +572,16 @@ static vec2 CalcFontSizeAndBoundingBox(ITextRender *pTextRender, const char *pTe
if(Size < 4.0f)
break;
Size -= 1.0f;
TextWidth = pTextRender->TextWidth(Size, pText, -1, LabelProps.m_MaxWidth, Flags, &TextHeight);
TextWidth = pTextRender->TextWidth(Size, pText, -1, LabelProps.m_MaxWidth, Flags, TextSizeProps);
}
return vec2(TextWidth, TextHeight);
SCursorAndBoundingBox Res{};
Res.m_TextSize = vec2(TextWidth, TextHeight);
Res.m_BiggestCharacterHeight = TextBoundingHeight;
Res.m_LineCount = LineCount;
return Res;
}
vec2 CUI::CalcAlignedCursorPos(const CUIRect *pRect, vec2 TextSize, int Align)
vec2 CUI::CalcAlignedCursorPos(const CUIRect *pRect, vec2 TextSize, int Align, const float *pBiggestCharHeight)
{
vec2 Cursor(pRect->x, pRect->y);
@ -581,7 +598,7 @@ vec2 CUI::CalcAlignedCursorPos(const CUIRect *pRect, vec2 TextSize, int Align)
const int VerticalAlign = Align & TEXTALIGN_MASK_VERTICAL;
if(VerticalAlign == TEXTALIGN_MIDDLE)
{
Cursor.y += (pRect->h - TextSize.y) / 2.0f;
Cursor.y += pBiggestCharHeight != nullptr ? ((pRect->h - *pBiggestCharHeight) / 2.0f - (TextSize.y - *pBiggestCharHeight)) : (pRect->h - TextSize.y) / 2.0f;
}
else if(VerticalAlign == TEXTALIGN_BOTTOM)
{
@ -594,8 +611,8 @@ vec2 CUI::CalcAlignedCursorPos(const CUIRect *pRect, vec2 TextSize, int Align)
void CUI::DoLabel(const CUIRect *pRect, const char *pText, float Size, int Align, const SLabelProperties &LabelProps)
{
const int Flags = LabelProps.m_StopAtEnd ? TEXTFLAG_STOP_AT_END : 0;
const vec2 TextBounds = CalcFontSizeAndBoundingBox(TextRender(), pText, Flags, Size, pRect->w, LabelProps);
const vec2 CursorPos = CalcAlignedCursorPos(pRect, TextBounds, Align);
const SCursorAndBoundingBox TextBounds = CalcFontSizeCursorHeightAndBoundingBox(TextRender(), pText, Flags, Size, pRect->w, LabelProps);
const vec2 CursorPos = CalcAlignedCursorPos(pRect, TextBounds.m_TextSize, Align, TextBounds.m_LineCount == 1 ? &TextBounds.m_BiggestCharacterHeight : nullptr);
CTextCursor Cursor;
TextRender()->SetCursor(&Cursor, CursorPos.x, CursorPos.y, Size, TEXTFLAG_RENDER | Flags);
@ -606,7 +623,7 @@ 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)
{
const int Flags = pReadCursor ? (pReadCursor->m_Flags & ~TEXTFLAG_RENDER) : LabelProps.m_StopAtEnd ? TEXTFLAG_STOP_AT_END : 0;
const vec2 TextBounds = CalcFontSizeAndBoundingBox(TextRender(), pText, Flags, Size, pRect->w, LabelProps);
const SCursorAndBoundingBox TextBounds = CalcFontSizeCursorHeightAndBoundingBox(TextRender(), pText, Flags, Size, pRect->w, LabelProps);
CTextCursor Cursor;
if(pReadCursor)
@ -615,7 +632,7 @@ void CUI::DoLabel(CUIElement::SUIElementRect &RectEl, const CUIRect *pRect, cons
}
else
{
const vec2 CursorPos = CalcAlignedCursorPos(pRect, TextBounds, Align);
const vec2 CursorPos = CalcAlignedCursorPos(pRect, TextBounds.m_TextSize, Align);
TextRender()->SetCursor(&Cursor, CursorPos.x, CursorPos.y, Size, TEXTFLAG_RENDER | Flags);
}
Cursor.m_LineWidth = LabelProps.m_MaxWidth;
@ -798,7 +815,9 @@ bool CUI::DoClearableEditBox(CLineInput *pLineInput, const CUIRect *pRect, float
bool ReturnValue = DoEditBox(pLineInput, &EditBox, FontSize, Corners & ~IGraphics::CORNER_R);
ClearButton.Draw(ColorRGBA(1.0f, 1.0f, 1.0f, 0.33f * ButtonColorMul(pLineInput->GetClearButtonId())), Corners & ~IGraphics::CORNER_L, 3.0f);
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
DoLabel(&ClearButton, "×", ClearButton.h * CUI::ms_FontmodHeight * 0.8f, TEXTALIGN_MC);
TextRender()->SetRenderFlags(0);
if(DoButtonLogic(pLineInput->GetClearButtonId(), 0, &ClearButton))
{
pLineInput->Clear();
@ -1177,7 +1196,9 @@ void CUI::ShowPopupMessage(float X, float Y, SMessagePopupContext *pContext)
{
const float TextWidth = minimum(std::ceil(TextRender()->TextWidth(SMessagePopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, -1, -1.0f)), SMessagePopupContext::POPUP_MAX_WIDTH);
float TextHeight = 0.0f;
TextRender()->TextWidth(SMessagePopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, -1, TextWidth, 0, &TextHeight);
STextSizeProperties TextSizeProps{};
TextSizeProps.m_pHeight = &TextHeight;
TextRender()->TextWidth(SMessagePopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, -1, TextWidth, 0, TextSizeProps);
pContext->m_pUI = this;
DoPopupMenu(pContext, X, Y, TextWidth + 10.0f, TextHeight + 10.0f, pContext, PopupMessage);
}
@ -1202,7 +1223,9 @@ void CUI::ShowPopupConfirm(float X, float Y, SConfirmPopupContext *pContext)
{
const float TextWidth = minimum(std::ceil(TextRender()->TextWidth(SConfirmPopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, -1, -1.0f)), SConfirmPopupContext::POPUP_MAX_WIDTH);
float TextHeight = 0.0f;
TextRender()->TextWidth(SConfirmPopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, -1, TextWidth, 0, &TextHeight);
STextSizeProperties TextSizeProps{};
TextSizeProps.m_pHeight = &TextHeight;
TextRender()->TextWidth(SConfirmPopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, -1, TextWidth, 0, TextSizeProps);
const float PopupHeight = TextHeight + SConfirmPopupContext::POPUP_BUTTON_HEIGHT + SConfirmPopupContext::POPUP_BUTTON_SPACING + 10.0f;
pContext->m_pUI = this;
pContext->m_Result = SConfirmPopupContext::UNSET;

View file

@ -433,7 +433,7 @@ public:
int DoDraggableButtonLogic(const void *pID, int Checked, const CUIRect *pRect, bool *pClicked, bool *pAbrupted);
int DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float *pY);
void DoSmoothScrollLogic(float *pScrollOffset, float *pScrollOffsetChange, float ViewPortSize, float TotalSize, bool SmoothClamp = false, float ScrollSpeed = 10.0f);
static vec2 CalcAlignedCursorPos(const CUIRect *pRect, vec2 TextSize, int Align);
static vec2 CalcAlignedCursorPos(const CUIRect *pRect, vec2 TextSize, int Align, const float *pBiggestCharHeight = nullptr);
void DoLabel(const CUIRect *pRect, const char *pText, float Size, int Align, const SLabelProperties &LabelProps = {});