mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-05-28 17:16:29 +03:00
Added support for margin and padding in text spans.
This commit is contained in:
65
bin/unit_tests/assets/html/anchor_margins.html
Normal file
65
bin/unit_tests/assets/html/anchor_margins.html
Normal file
@@ -0,0 +1,65 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #1e2a38;
|
||||
font:
|
||||
13px Verdana,
|
||||
Sans-Serif;
|
||||
color: #d0d8e0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #60c0e0;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background-color: #2a3a4a;
|
||||
color: #80d8f0;
|
||||
}
|
||||
|
||||
nav {
|
||||
background-color: #162028;
|
||||
text-align: center;
|
||||
padding: 8px;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
border-bottom: 1px solid #2a3a4a;
|
||||
}
|
||||
|
||||
nav a {
|
||||
margin: 0 10px;
|
||||
font:
|
||||
bold 11px Verdana,
|
||||
Sans-Serif;
|
||||
text-decoration: none;
|
||||
color: #80b8d0;
|
||||
}
|
||||
|
||||
nav a:hover {
|
||||
background-color: #2a3a4a;
|
||||
color: #a0d8f0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<a href="#home">Home</a>
|
||||
<a href="#features">Features</a>
|
||||
<a href="#super-enhancement">Super Enhancement</a>
|
||||
<a href="#downloads">Downloads</a>
|
||||
<a href="#coming">Coming Soon</a>
|
||||
<a href="#legal">Legal</a>
|
||||
</nav>
|
||||
</body>
|
||||
</html>
|
||||
BIN
bin/unit_tests/assets/html/eepp-ui-anchor-margins.webp
Normal file
BIN
bin/unit_tests/assets/html/eepp-ui-anchor-margins.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
BIN
bin/unit_tests/assets/html/eepp-ui-span-padding.webp
Normal file
BIN
bin/unit_tests/assets/html/eepp-ui-span-padding.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
56
bin/unit_tests/assets/html/span_padding.html
Normal file
56
bin/unit_tests/assets/html/span_padding.html
Normal file
@@ -0,0 +1,56 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #1e2a38;
|
||||
font:
|
||||
16px Verdana,
|
||||
Sans-Serif;
|
||||
color: #d0d8e0;
|
||||
line-height: 1.5;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.padded-span {
|
||||
background-color: #c06060;
|
||||
color: #ffffff;
|
||||
padding: 10px 20px;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.large-padding {
|
||||
background-color: #60c060;
|
||||
color: #ffffff;
|
||||
padding: 30px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.mixed-padding {
|
||||
background-color: #6060c0;
|
||||
color: #ffffff;
|
||||
padding-left: 50px;
|
||||
padding-right: 10px;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
This is normal text with a <span class="padded-span">padded span</span> inside it.
|
||||
</div>
|
||||
<div style="margin-top: 40px;">
|
||||
Here is a <span class="large-padding">large padded span</span> which should increase the line height and spacing.
|
||||
</div>
|
||||
<div style="margin-top: 40px;">
|
||||
Finally, a <span class="mixed-padding">mixed padding span</span> to test asymmetrical padding values.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -33,6 +33,9 @@ class EE_API RichText : public Drawable {
|
||||
*/
|
||||
void addSpan( const String& text, const FontStyleConfig& style );
|
||||
|
||||
void addSpan( const String& text, const FontStyleConfig& style, const Rectf& margin,
|
||||
const Rectf& padding );
|
||||
|
||||
/**
|
||||
* @brief Adds a text span with individual style parameters.
|
||||
* @param text The text content.
|
||||
@@ -82,7 +85,13 @@ class EE_API RichText : public Drawable {
|
||||
bool isBlock{ false };
|
||||
};
|
||||
|
||||
using Block = std::variant<std::shared_ptr<Text>, std::shared_ptr<Drawable>, CustomBlock>;
|
||||
struct SpanBlock {
|
||||
std::shared_ptr<Text> text;
|
||||
Rectf margin;
|
||||
Rectf padding;
|
||||
};
|
||||
|
||||
using Block = std::variant<SpanBlock, std::shared_ptr<Drawable>, CustomBlock>;
|
||||
|
||||
/**
|
||||
* @brief Adds a drawable (e.g., an image) into the text flow.
|
||||
|
||||
@@ -57,7 +57,27 @@ void RichText::draw( const Float& X, const Float& Y, const Vector2f& scale, cons
|
||||
std::visit(
|
||||
Overloaded{
|
||||
|
||||
[&]( const std::shared_ptr<Text>& text ) {
|
||||
[&]( const SpanBlock& spanBlock ) {
|
||||
const std::shared_ptr<Text>& text = spanBlock.text;
|
||||
Color oldBgColor = text->getFontStyleConfig().BackgroundColor;
|
||||
|
||||
if ( oldBgColor != Color::Transparent ) {
|
||||
Primitives p;
|
||||
p.setColor( oldBgColor );
|
||||
Rectf bgRect(
|
||||
Vector2f(
|
||||
std::trunc( X + pos.x - spanBlock.padding.Left ),
|
||||
std::trunc( Y + line.y + pos.y - spanBlock.padding.Top ) ),
|
||||
Sizef( span.size.getWidth() + spanBlock.padding.Left +
|
||||
spanBlock.padding.Right,
|
||||
span.size.getHeight() + spanBlock.padding.Top +
|
||||
spanBlock.padding.Bottom ) );
|
||||
p.drawRectangle( bgRect, rotation, scale );
|
||||
}
|
||||
|
||||
if ( oldBgColor != Color::Transparent )
|
||||
text->setBackgroundColor( Color::Transparent );
|
||||
|
||||
bool selectionApplied = false;
|
||||
if ( mSelectionColor != Color::Transparent ) {
|
||||
TextSelectionRange spanSel = {
|
||||
@@ -85,6 +105,9 @@ void RichText::draw( const Float& X, const Float& Y, const Vector2f& scale, cons
|
||||
rotation, effect, rotationCenter, scaleCenter );
|
||||
}
|
||||
|
||||
if ( oldBgColor != Color::Transparent )
|
||||
text->setBackgroundColor( oldBgColor );
|
||||
|
||||
if ( selectionApplied )
|
||||
text->invalidateColors();
|
||||
},
|
||||
@@ -127,9 +150,9 @@ Int64 RichText::findCharacterFromPos( const Vector2i& pos ) const {
|
||||
if ( pos.y >= line.y && pos.y < line.y + line.height ) {
|
||||
for ( const auto& span : line.spans ) {
|
||||
if ( pos.x >= span.position.x && pos.x < span.position.x + span.size.getWidth() ) {
|
||||
if ( auto pText = std::get_if<std::shared_ptr<Text>>( &span.block ) ) {
|
||||
if ( auto pText = std::get_if<SpanBlock>( &span.block ) ) {
|
||||
return span.startCharIndex +
|
||||
( *pText )->findCharacterFromPos( Vector2i(
|
||||
pText->text->findCharacterFromPos( Vector2i(
|
||||
pos.x - span.position.x, pos.y - line.y - span.position.y ) );
|
||||
} else {
|
||||
return ( pos.x < span.position.x + span.size.getWidth() * 0.5f )
|
||||
@@ -166,8 +189,8 @@ Vector2f RichText::findCharacterPos( Int64 index ) const {
|
||||
for ( const auto& line : mLines ) {
|
||||
for ( const auto& span : line.spans ) {
|
||||
if ( index >= span.startCharIndex && index < span.endCharIndex ) {
|
||||
if ( auto pText = std::get_if<std::shared_ptr<Text>>( &span.block ) ) {
|
||||
Vector2f p = ( *pText )->findCharacterPos( index - span.startCharIndex );
|
||||
if ( auto pText = std::get_if<SpanBlock>( &span.block ) ) {
|
||||
Vector2f p = pText->text->findCharacterPos( index - span.startCharIndex );
|
||||
return { span.position.x + p.x, line.y + span.position.y + p.y };
|
||||
} else {
|
||||
return { span.position.x, line.y + span.position.y };
|
||||
@@ -197,8 +220,8 @@ SmallVector<Rectf> RichText::getSelectionRects() const {
|
||||
Int64 spanEnd = std::min( end, span.endCharIndex );
|
||||
|
||||
if ( spanStart < spanEnd ) {
|
||||
if ( auto pText = std::get_if<std::shared_ptr<Text>>( &span.block ) ) {
|
||||
auto spanRects = ( *pText )->getSelectionRects(
|
||||
if ( auto pText = std::get_if<SpanBlock>( &span.block ) ) {
|
||||
auto spanRects = pText->text->getSelectionRects(
|
||||
{ spanStart - span.startCharIndex, spanEnd - span.startCharIndex } );
|
||||
for ( auto& rect : spanRects ) {
|
||||
rect.move( { span.position.x, line.y + span.position.y } );
|
||||
@@ -237,9 +260,9 @@ String RichText::getSelectionString() const {
|
||||
Int64 spanEnd = std::min( end, span.endCharIndex );
|
||||
|
||||
if ( spanStart < spanEnd ) {
|
||||
if ( auto pText = std::get_if<std::shared_ptr<Text>>( &span.block ) ) {
|
||||
res += ( *pText )->getString().substr( spanStart - span.startCharIndex,
|
||||
spanEnd - spanStart );
|
||||
if ( auto pText = std::get_if<SpanBlock>( &span.block ) ) {
|
||||
res += pText->text->getString().substr( spanStart - span.startCharIndex,
|
||||
spanEnd - spanStart );
|
||||
} else {
|
||||
// It's a drawable or custom size, it takes 1 "character" index.
|
||||
res += ' ';
|
||||
@@ -264,14 +287,15 @@ Sizef RichText::getPixelsSize() {
|
||||
return getSize();
|
||||
}
|
||||
|
||||
void RichText::addSpan( const String& text, const FontStyleConfig& style ) {
|
||||
void RichText::addSpan( const String& text, const FontStyleConfig& style, const Rectf& margin,
|
||||
const Rectf& padding ) {
|
||||
if ( text.empty() )
|
||||
return;
|
||||
|
||||
auto span = std::make_shared<Text>();
|
||||
span->setString( text );
|
||||
span->setStyleConfig( style );
|
||||
mBlocks.push_back( span ); // Implicitly constructs the variant's Text alternative
|
||||
mBlocks.push_back( SpanBlock{ span, margin, padding } );
|
||||
invalidateLayout();
|
||||
}
|
||||
|
||||
@@ -287,6 +311,10 @@ void RichText::addCustomSize( const Sizef& size, bool isBlock ) {
|
||||
invalidateLayout();
|
||||
}
|
||||
|
||||
void RichText::addSpan( const String& text, const FontStyleConfig& style ) {
|
||||
addSpan( text, style, Rectf(), Rectf() );
|
||||
}
|
||||
|
||||
void RichText::addSpan( const String& text, Font* font, Uint32 characterSize, Color color,
|
||||
Uint32 style, Color backgroundColor ) {
|
||||
FontStyleConfig config;
|
||||
@@ -332,9 +360,9 @@ void RichText::setMaxWidth( Float width ) {
|
||||
void RichText::invalidate() {
|
||||
invalidateLayout();
|
||||
for ( auto& block : mBlocks ) {
|
||||
if ( auto pText = std::get_if<std::shared_ptr<Text>>( &block ) ) {
|
||||
if ( *pText )
|
||||
( *pText )->invalidate();
|
||||
if ( auto pText = std::get_if<SpanBlock>( &block ) ) {
|
||||
if ( pText->text )
|
||||
pText->text->invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -342,8 +370,8 @@ void RichText::invalidate() {
|
||||
Float RichText::getMinIntrinsicWidth() {
|
||||
Float minW = 0;
|
||||
for ( auto& block : mBlocks ) {
|
||||
if ( auto pText = std::get_if<std::shared_ptr<Text>>( &block ) ) {
|
||||
auto& span = *pText;
|
||||
if ( auto pText = std::get_if<SpanBlock>( &block ) ) {
|
||||
auto& span = pText->text;
|
||||
if ( !span || span->getString().empty() )
|
||||
continue;
|
||||
const String& s = span->getString();
|
||||
@@ -359,7 +387,9 @@ Float RichText::getMinIntrinsicWidth() {
|
||||
end++;
|
||||
if ( start < end ) {
|
||||
minW = std::max( minW, Text::getTextWidth( s.substr( start, end - start ),
|
||||
span->getFontStyleConfig() ) );
|
||||
span->getFontStyleConfig() ) +
|
||||
pText->margin.Left + pText->margin.Right +
|
||||
pText->padding.Left + pText->padding.Right );
|
||||
}
|
||||
start = end;
|
||||
}
|
||||
@@ -376,23 +406,25 @@ Float RichText::getMaxIntrinsicWidth() {
|
||||
Float maxW = 0;
|
||||
Float curX = 0;
|
||||
for ( auto& block : mBlocks ) {
|
||||
if ( auto pText = std::get_if<std::shared_ptr<Text>>( &block ) ) {
|
||||
auto& span = *pText;
|
||||
if ( auto pText = std::get_if<SpanBlock>( &block ) ) {
|
||||
auto& span = pText->text;
|
||||
if ( !span || span->getString().empty() )
|
||||
continue;
|
||||
|
||||
const String& s = span->getString();
|
||||
size_t start = 0;
|
||||
size_t end = 0;
|
||||
curX += pText->margin.Left + pText->padding.Left;
|
||||
while ( ( end = s.find( '\n', start ) ) != String::InvalidPos ) {
|
||||
curX += Text::getTextWidth( s.substr( start, end - start ),
|
||||
span->getFontStyleConfig(), 4, span->getTextHints() );
|
||||
maxW = std::max( maxW, curX );
|
||||
maxW = std::max( maxW, curX + pText->margin.Right + pText->padding.Right );
|
||||
curX = 0;
|
||||
start = end + 1;
|
||||
}
|
||||
curX += Text::getTextWidth( s.substr( start ), span->getFontStyleConfig(), 4,
|
||||
span->getTextHints() );
|
||||
span->getTextHints() ) +
|
||||
pText->margin.Right + pText->padding.Right;
|
||||
} else if ( auto pDrawable = std::get_if<std::shared_ptr<Drawable>>( &block ) ) {
|
||||
curX += ( *pDrawable )->getPixelsSize().getWidth();
|
||||
} else if ( auto pSize = std::get_if<CustomBlock>( &block ) ) {
|
||||
@@ -423,8 +455,8 @@ void RichText::updateLayout() {
|
||||
Int64 curCharIdx = 0;
|
||||
|
||||
for ( auto& block : mBlocks ) {
|
||||
if ( auto pText = std::get_if<std::shared_ptr<Text>>( &block ) ) {
|
||||
auto& span = *pText;
|
||||
if ( auto pText = std::get_if<SpanBlock>( &block ) ) {
|
||||
auto& span = pText->text;
|
||||
if ( !span || span->getString().empty() )
|
||||
continue;
|
||||
|
||||
@@ -432,6 +464,11 @@ void RichText::updateLayout() {
|
||||
if ( !fontStyle.Font )
|
||||
continue;
|
||||
|
||||
Float extraLeft = pText->margin.Left + pText->padding.Left;
|
||||
curX += extraLeft;
|
||||
if ( !mLines.empty() )
|
||||
mLines.back().width += extraLeft;
|
||||
|
||||
Uint32 textHints = span->getTextHints();
|
||||
|
||||
LineWrapInfoEx wrapInfo = LineWrap::computeLineBreaksEx(
|
||||
@@ -460,7 +497,7 @@ void RichText::updateLayout() {
|
||||
Float spanWidth = renderSpanText->getTextWidth();
|
||||
|
||||
RenderSpan renderSpan;
|
||||
renderSpan.block = renderSpanText;
|
||||
renderSpan.block = SpanBlock{ renderSpanText, pText->margin, pText->padding };
|
||||
renderSpan.position = { curX, 0 }; // Y adjusted later
|
||||
renderSpan.size =
|
||||
Sizef( spanWidth, height ); // Configured BEFORE pushing to vector
|
||||
@@ -478,12 +515,30 @@ void RichText::updateLayout() {
|
||||
currentLine.width += spanWidth;
|
||||
}
|
||||
|
||||
if ( i == wrapInfo.wraps.size() - 2 && !isNewline ) {
|
||||
Float extraRight = pText->margin.Right + pText->padding.Right;
|
||||
curX += extraRight;
|
||||
mLines.back().width += extraRight;
|
||||
if ( !isNewline && mMaxWidth > 0 && curX > mMaxWidth ) {
|
||||
// the margin forced a wrap
|
||||
maxWidth = std::max( maxWidth, curX );
|
||||
mLines.push_back( RenderParagraph() );
|
||||
curX = 0;
|
||||
continue; // skip the next newline check
|
||||
}
|
||||
}
|
||||
|
||||
// If it's a newline, or if it's not the very last segment (which means it wrapped),
|
||||
// start a new line. Exception: If the last segment was just a newline, we already
|
||||
// handled it.
|
||||
if ( i < wrapInfo.wraps.size() - 2 || isNewline ) {
|
||||
if ( isNewline ) {
|
||||
curCharIdx++;
|
||||
if ( i == wrapInfo.wraps.size() - 2 ) {
|
||||
Float extraRight = pText->margin.Right + pText->padding.Right;
|
||||
curX += extraRight;
|
||||
mLines.back().width += extraRight;
|
||||
}
|
||||
}
|
||||
maxWidth = std::max( maxWidth, curX );
|
||||
mLines.push_back( RenderParagraph() );
|
||||
@@ -562,8 +617,8 @@ void RichText::updateLayout() {
|
||||
|
||||
Float maxLineHeight = 0;
|
||||
for ( auto& span : line.spans ) {
|
||||
if ( auto pText = std::get_if<std::shared_ptr<Text>>( &span.block ) ) {
|
||||
auto& textBlock = *pText;
|
||||
if ( auto pText = std::get_if<SpanBlock>( &span.block ) ) {
|
||||
auto& textBlock = pText->text;
|
||||
Float offsetY = line.maxAscent - textBlock->getCharacterSize();
|
||||
span.position.x += xOffset;
|
||||
span.position.y = offsetY;
|
||||
|
||||
@@ -592,7 +592,9 @@ void UIRichText::rebuildRichText( UILayout* container, RichText& richText, Intri
|
||||
if ( widget->isType( UI_TYPE_TEXTSPAN ) ) {
|
||||
UITextSpan* span = widget->asType<UITextSpan>();
|
||||
if ( !span->getText().empty() ) {
|
||||
richText.addSpan( span->getText(), span->getFontStyleConfig() );
|
||||
Rectf margin = span->getLayoutPixelsMargin();
|
||||
Rectf padding = span->getPixelsPadding();
|
||||
richText.addSpan( span->getText(), span->getFontStyleConfig(), margin, padding );
|
||||
}
|
||||
Node* spanChild = span->getFirstChild();
|
||||
while ( spanChild != NULL ) {
|
||||
|
||||
@@ -362,8 +362,8 @@ UTEST( UIRichText, IntegrationAndLayoutVerification ) {
|
||||
ASSERT_EQ( blocks.size(), (size_t)4 );
|
||||
|
||||
// Check Text block
|
||||
EXPECT_TRUE( std::holds_alternative<std::shared_ptr<Graphics::Text>>( blocks[1] ) );
|
||||
auto text1 = std::get<std::shared_ptr<Graphics::Text>>( blocks[1] );
|
||||
EXPECT_TRUE( std::holds_alternative<RichText::SpanBlock>( blocks[1] ) );
|
||||
auto text1 = std::get<RichText::SpanBlock>( blocks[1] ).text;
|
||||
EXPECT_TRUE( text1->getFillColor() == Color::fromString( "#FF0000" ) );
|
||||
|
||||
// Check CustomSize block
|
||||
@@ -374,7 +374,7 @@ UTEST( UIRichText, IntegrationAndLayoutVerification ) {
|
||||
UI::UIWidget* placeholder = rt->find<UI::UIWidget>( "placeholder" );
|
||||
ASSERT_TRUE( placeholder != nullptr );
|
||||
|
||||
auto text0 = std::get<std::shared_ptr<Graphics::Text>>( blocks[0] );
|
||||
auto text0 = std::get<RichText::SpanBlock>( blocks[0] ).text;
|
||||
Vector2f pos = placeholder->getPixelsPosition();
|
||||
Float expectedX = text0->getTextWidth() + text1->getTextWidth();
|
||||
EXPECT_NEAR( pos.x, expectedX, 2.0f );
|
||||
@@ -464,10 +464,10 @@ UTEST( UIRichText, NestedWidgetsIntegration ) {
|
||||
ASSERT_EQ( blocks.size(), (size_t)4 );
|
||||
|
||||
// Check block types
|
||||
EXPECT_TRUE( std::holds_alternative<std::shared_ptr<Graphics::Text>>( blocks[0] ) );
|
||||
EXPECT_TRUE( std::holds_alternative<std::shared_ptr<Graphics::Text>>( blocks[1] ) );
|
||||
EXPECT_TRUE( std::holds_alternative<RichText::SpanBlock>( blocks[0] ) );
|
||||
EXPECT_TRUE( std::holds_alternative<RichText::SpanBlock>( blocks[1] ) );
|
||||
EXPECT_TRUE( std::holds_alternative<RichText::CustomBlock>( blocks[2] ) );
|
||||
EXPECT_TRUE( std::holds_alternative<std::shared_ptr<Graphics::Text>>( blocks[3] ) );
|
||||
EXPECT_TRUE( std::holds_alternative<RichText::SpanBlock>( blocks[3] ) );
|
||||
|
||||
EXPECT_EQ( std::get<RichText::CustomBlock>( blocks[2] ).size.getWidth(),
|
||||
PixelDensity::dpToPx( 50 ) );
|
||||
@@ -478,8 +478,8 @@ UTEST( UIRichText, NestedWidgetsIntegration ) {
|
||||
UI::UIWidget* placeholder = rt->find<UI::UIWidget>( "placeholder" );
|
||||
ASSERT_TRUE( placeholder != nullptr );
|
||||
|
||||
auto text0 = std::get<std::shared_ptr<Graphics::Text>>( blocks[0] );
|
||||
auto text1 = std::get<std::shared_ptr<Graphics::Text>>( blocks[1] );
|
||||
auto text0 = std::get<RichText::SpanBlock>( blocks[0] ).text;
|
||||
auto text1 = std::get<RichText::SpanBlock>( blocks[1] ).text;
|
||||
|
||||
Vector2f pos = placeholder->getScreenPos();
|
||||
Float expectedX = text0->getTextWidth() + text1->getTextWidth();
|
||||
@@ -528,14 +528,14 @@ UTEST( UIRichText, DefaultStyleInheritance ) {
|
||||
// blocks[1] should be "Small" with overridden size and color
|
||||
ASSERT_TRUE( blocks.size() >= 2 );
|
||||
|
||||
EXPECT_TRUE( std::holds_alternative<std::shared_ptr<Graphics::Text>>( blocks[0] ) );
|
||||
auto text0 = std::get<std::shared_ptr<Graphics::Text>>( blocks[0] );
|
||||
EXPECT_TRUE( std::holds_alternative<RichText::SpanBlock>( blocks[0] ) );
|
||||
auto text0 = std::get<RichText::SpanBlock>( blocks[0] ).text;
|
||||
EXPECT_EQ( text0->getCharacterSize(), rt->getFontSize() );
|
||||
EXPECT_EQ( text0->getFillColor().getValue(), rt->getFontColor().getValue() );
|
||||
EXPECT_EQ( text0->getFillColor().getValue(), Color::fromString( "#FF0000" ).getValue() );
|
||||
|
||||
EXPECT_TRUE( std::holds_alternative<std::shared_ptr<Graphics::Text>>( blocks[1] ) );
|
||||
auto text1 = std::get<std::shared_ptr<Graphics::Text>>( blocks[1] );
|
||||
EXPECT_TRUE( std::holds_alternative<RichText::SpanBlock>( blocks[1] ) );
|
||||
auto text1 = std::get<RichText::SpanBlock>( blocks[1] ).text;
|
||||
EXPECT_EQ( text1->getCharacterSize(), (unsigned int)PixelDensity::dpToPxI( 16 ) );
|
||||
EXPECT_EQ( text1->getFillColor().getValue(), Color::fromString( "#00FF00" ).getValue() );
|
||||
|
||||
|
||||
@@ -140,6 +140,74 @@ UTEST( UIHTMLTable, complexLayout2 ) {
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( UIRichText, anchorMargins ) {
|
||||
auto win = Engine::instance()->createWindow(
|
||||
WindowSettings( 800, 600, "Anchor Margins Test", WindowStyle::Default,
|
||||
WindowBackend::Default, 32, {}, 1, false, true ),
|
||||
ContextSettings( false, 0, 0, GLv_default, true, false ) );
|
||||
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
|
||||
|
||||
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
|
||||
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
|
||||
ASSERT_TRUE( font != nullptr && font->loaded() );
|
||||
FontFamily::loadFromRegular( font );
|
||||
|
||||
UI::UISceneNode* sceneNode = UI::UISceneNode::New();
|
||||
SceneManager::instance()->add( sceneNode );
|
||||
UI::UIThemeManager* themeManager = sceneNode->getUIThemeManager();
|
||||
themeManager->setDefaultFont( font );
|
||||
sceneNode->setURI( "file://" + Sys::getProcessPath() + "assets/html/" );
|
||||
std::string html;
|
||||
FileSystem::fileGet( "assets/html/anchor_margins.html", html );
|
||||
sceneNode->loadLayoutFromString( HTMLFormatter::HTMLtoXML( html ) );
|
||||
win->setClearColor( Color::White );
|
||||
|
||||
win->getInput()->update();
|
||||
SceneManager::instance()->update();
|
||||
|
||||
win->clear();
|
||||
SceneManager::instance()->draw();
|
||||
win->display();
|
||||
|
||||
compareImages( utest_state, utest_result, win, "eepp-ui-anchor-margins", "html" );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( UIRichText, spanPadding ) {
|
||||
auto win = Engine::instance()->createWindow(
|
||||
WindowSettings( 800, 600, "Span Padding Test", WindowStyle::Default, WindowBackend::Default,
|
||||
32, {}, 1, false, true ),
|
||||
ContextSettings( false, 0, 0, GLv_default, true, false ) );
|
||||
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
|
||||
|
||||
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
|
||||
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
|
||||
ASSERT_TRUE( font != nullptr && font->loaded() );
|
||||
FontFamily::loadFromRegular( font );
|
||||
|
||||
UI::UISceneNode* sceneNode = UI::UISceneNode::New();
|
||||
SceneManager::instance()->add( sceneNode );
|
||||
UI::UIThemeManager* themeManager = sceneNode->getUIThemeManager();
|
||||
themeManager->setDefaultFont( font );
|
||||
sceneNode->setURI( "file://" + Sys::getProcessPath() + "assets/html/" );
|
||||
std::string html;
|
||||
FileSystem::fileGet( "assets/html/span_padding.html", html );
|
||||
sceneNode->loadLayoutFromString( HTMLFormatter::HTMLtoXML( html ) );
|
||||
win->setClearColor( Color::White );
|
||||
|
||||
win->getInput()->update();
|
||||
SceneManager::instance()->update();
|
||||
|
||||
win->clear();
|
||||
SceneManager::instance()->draw();
|
||||
win->display();
|
||||
|
||||
compareImages( utest_state, utest_result, win, "eepp-ui-span-padding", "html" );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( UIHTMLTable, complexLayout3 ) {
|
||||
auto win = Engine::instance()->createWindow(
|
||||
WindowSettings( 1024, 650, "HTML Tables Test 3", WindowStyle::Default,
|
||||
@@ -587,8 +655,7 @@ UTEST( UILayout, listStyleTypeDecimal ) {
|
||||
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
const auto* propDef =
|
||||
StyleSheetSpecification::instance()->getProperty( "list-style-type" );
|
||||
const auto* propDef = StyleSheetSpecification::instance()->getProperty( "list-style-type" );
|
||||
ASSERT_TRUE( propDef != nullptr );
|
||||
|
||||
auto* li1 = sceneNode->getRoot()->find( "li1" )->asType<UIRichText>();
|
||||
@@ -619,8 +686,7 @@ UTEST( UILayout, listStyleTypeDisc ) {
|
||||
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
const auto* propDef =
|
||||
StyleSheetSpecification::instance()->getProperty( "list-style-type" );
|
||||
const auto* propDef = StyleSheetSpecification::instance()->getProperty( "list-style-type" );
|
||||
ASSERT_TRUE( propDef != nullptr );
|
||||
|
||||
auto* li1 = sceneNode->getRoot()->find( "li1" )->asType<UIRichText>();
|
||||
@@ -651,10 +717,8 @@ UTEST( UILayout, listStyleShorthand ) {
|
||||
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
const auto* typeDef =
|
||||
StyleSheetSpecification::instance()->getProperty( "list-style-type" );
|
||||
const auto* posDef =
|
||||
StyleSheetSpecification::instance()->getProperty( "list-style-position" );
|
||||
const auto* typeDef = StyleSheetSpecification::instance()->getProperty( "list-style-type" );
|
||||
const auto* posDef = StyleSheetSpecification::instance()->getProperty( "list-style-position" );
|
||||
|
||||
for ( const char* id : { "li1", "li2", "li3", "li4", "li5", "li6" } ) {
|
||||
auto* li = sceneNode->getRoot()->find( id )->asType<UIWidget>();
|
||||
@@ -662,18 +726,27 @@ UTEST( UILayout, listStyleShorthand ) {
|
||||
EXPECT_TRUE( li->isType( UI_TYPE_HTML_LIST_ITEM ) );
|
||||
}
|
||||
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li1" )->asType<UIRichText>()->getPropertyString( typeDef ) == "decimal" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li1" )->asType<UIRichText>()->getPropertyString( posDef ) == "outside" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li1" )->asType<UIRichText>()->getPropertyString(
|
||||
typeDef ) == "decimal" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li1" )->asType<UIRichText>()->getPropertyString(
|
||||
posDef ) == "outside" );
|
||||
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li2" )->asType<UIRichText>()->getPropertyString( typeDef ) == "lower-alpha" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li2" )->asType<UIRichText>()->getPropertyString( posDef ) == "inside" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li2" )->asType<UIRichText>()->getPropertyString(
|
||||
typeDef ) == "lower-alpha" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li2" )->asType<UIRichText>()->getPropertyString(
|
||||
posDef ) == "inside" );
|
||||
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li3" )->asType<UIRichText>()->getPropertyString( typeDef ) == "none" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li3" )->asType<UIRichText>()->getPropertyString(
|
||||
typeDef ) == "none" );
|
||||
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li4" )->asType<UIRichText>()->getPropertyString( typeDef ) == "disc" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li5" )->asType<UIRichText>()->getPropertyString( typeDef ) == "square" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li5" )->asType<UIRichText>()->getPropertyString( posDef ) == "outside" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li6" )->asType<UIRichText>()->getPropertyString( typeDef ) == "circle" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li4" )->asType<UIRichText>()->getPropertyString(
|
||||
typeDef ) == "disc" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li5" )->asType<UIRichText>()->getPropertyString(
|
||||
typeDef ) == "square" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li5" )->asType<UIRichText>()->getPropertyString(
|
||||
posDef ) == "outside" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li6" )->asType<UIRichText>()->getPropertyString(
|
||||
typeDef ) == "circle" );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
@@ -714,14 +787,18 @@ UTEST( UILayout, listStyleInheritanceFromUl ) {
|
||||
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
const auto* typeDef =
|
||||
StyleSheetSpecification::instance()->getProperty( "list-style-type" );
|
||||
const auto* typeDef = StyleSheetSpecification::instance()->getProperty( "list-style-type" );
|
||||
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "h1" )->asType<UIRichText>()->getPropertyString( typeDef ) == "upper-roman" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "a1" )->asType<UIRichText>()->getPropertyString( typeDef ) == "circle" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "b1" )->asType<UIRichText>()->getPropertyString( typeDef ) == "disc" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "c1" )->asType<UIRichText>()->getPropertyString( typeDef ) == "square" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "d1" )->asType<UIRichText>()->getPropertyString( typeDef ) == "decimal" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "h1" )->asType<UIRichText>()->getPropertyString(
|
||||
typeDef ) == "upper-roman" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "a1" )->asType<UIRichText>()->getPropertyString(
|
||||
typeDef ) == "circle" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "b1" )->asType<UIRichText>()->getPropertyString(
|
||||
typeDef ) == "disc" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "c1" )->asType<UIRichText>()->getPropertyString(
|
||||
typeDef ) == "square" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "d1" )->asType<UIRichText>()->getPropertyString(
|
||||
typeDef ) == "decimal" );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user