Fix baseline alignment for inline-blocks in RichText.

This commit is contained in:
Martín Lucas Golini
2026-05-31 02:25:03 -03:00
parent 50334d4481
commit 8853acd901
2 changed files with 42 additions and 5 deletions

View File

@@ -61,8 +61,7 @@ static Float getBaselineAlignedOffset( const RichText::RenderParagraph& line, co
case RichText::BaselineAlignment::TextBottom:
return baseline + getParentDescent( parentFontStyle ) - size.getHeight();
case RichText::BaselineAlignment::Middle:
return getParentAscent( parentFontStyle ) + getFontXHeight( parentFontStyle ) * 0.5f -
size.getHeight() * 0.5f;
return baseline + getFontXHeight( parentFontStyle ) * 0.5f - size.getHeight() * 0.5f;
case RichText::BaselineAlignment::Top:
return 0.f;
case RichText::BaselineAlignment::Bottom:
@@ -830,8 +829,12 @@ class RichTextInlineLayouter {
Float baseline = span.baseline;
RichText::BaselineAlignValue baselineAlign = effectiveInlineBaselineAlign(
inlineItems, span.inlinePath, span.baselineAlign );
Float offsetY = getBaselineAlignedOffset(
line, span.size, baseline, span.size.getHeight(), baselineAlign, defaultStyle );
Float offsetY = baselineAlign.type == RichText::BaselineAlignment::Middle &&
baseline > 0.f && baseline < span.size.getHeight()
? line.maxAscent - baseline
: getBaselineAlignedOffset( line, span.size, baseline,
span.size.getHeight(),
baselineAlign, defaultStyle );
if ( preserveFloatPositions && isFloat ) {
span.position.y = 0;
continue;

View File

@@ -252,7 +252,41 @@ UTEST( RichText, VerticalAlignAtomicBoxes ) {
RichText::InlineClear::None, 10.f, middleAlign );
middleRt.getSize();
ASSERT_EQ( middleRt.getLines().front().spans.size(), (size_t)2 );
EXPECT_GT( middleRt.getLines().front().spans[1].position.y, baselineY );
EXPECT_NEAR( middleRt.getLines().front().spans[1].position.y, baselineY, 0.001f );
RichText mixedRt;
mixedRt.getFontStyleConfig().Font = font;
mixedRt.getFontStyleConfig().CharacterSize = 20;
mixedRt.addSpan( "Large", nullptr, 30 );
mixedRt.addCustomSize( Sizef( 10, 10 ), RichText::InlineFloat::None,
RichText::InlineClear::None, 5.f, middleAlign );
mixedRt.getSize();
ASSERT_EQ( mixedRt.getLines().front().spans.size(), (size_t)2 );
const auto& mixedLine = mixedRt.getLines().front();
Float expectedMiddleY = mixedLine.maxAscent - 5.f;
EXPECT_NEAR( mixedLine.spans[1].position.y, expectedMiddleY, 0.001f );
RichText nestedRt;
nestedRt.getFontStyleConfig().Font = font;
nestedRt.getFontStyleConfig().CharacterSize = 16;
FontStyleConfig smallStyle = nestedRt.getFontStyleConfig();
smallStyle.CharacterSize = 10;
nestedRt.addSpan( "Title ", nullptr, 16 );
nestedRt.pushInlineBox( Rectf::Zero, Rectf::Zero, 0, {}, Color::Transparent, 0,
Color::Transparent, 0, {} );
nestedRt.addInlineText( "(", smallStyle, Rectf::Zero, Rectf::Zero, 0, {} );
nestedRt.addCustomSize( Sizef( 36, 14 ), RichText::InlineFloat::None,
RichText::InlineClear::None, font->getAscent( 10 ), middleAlign );
nestedRt.addInlineText( ")", smallStyle, Rectf::Zero, Rectf::Zero, 0, {} );
nestedRt.popInlineBox();
nestedRt.getSize();
ASSERT_EQ( nestedRt.getLines().front().spans.size(), (size_t)4 );
const auto& nestedOpenParen = nestedRt.getLines().front().spans[1];
const auto& nestedAtomic = nestedRt.getLines().front().spans[2];
ASSERT_TRUE( nestedOpenParen.text != nullptr );
EXPECT_STRINGEQ( nestedOpenParen.text->getString(), "(" );
EXPECT_EQ( nestedAtomic.type, RichText::RenderSpan::Type::AtomicBox );
EXPECT_NEAR( nestedAtomic.position.y, nestedOpenParen.position.y, 0.5f );
RichText::BaselineAlignValue lengthAlign;
lengthAlign.type = RichText::BaselineAlignment::Length;