Greatly improve borders rendering, added a few tests.

Fixed `UIStyle::getProperty`, now respects specificity.
Fixed `StyleSheetPropertiesParser::addProperty` when inserted an already existing property.
This commit is contained in:
Martín Lucas Golini
2026-04-28 21:52:31 -03:00
parent 350bc8a95d
commit f765eae28d
7 changed files with 382 additions and 48 deletions

View File

@@ -0,0 +1,171 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background-color: #f5f5f5;
font: 11px Verdana, Sans-Serif;
color: #333;
padding: 8px;
}
.row { clear: both; margin-bottom: 4px; }
.label {
float: left;
width: 130px;
font-size: 9px;
line-height: 1.2;
color: #555;
padding-top: 2px;
padding-right: 4px;
text-align: right;
}
.box {
float: left;
width: 48px;
height: 48px;
margin: 2px;
background-color: #e8f0f8;
font-size: 8px;
text-align: center;
padding: 4px;
overflow: hidden;
}
.clearfix { clear: both; }
</style>
</head>
<body>
<!-- ============ 1 BORDER ============ -->
<div class="row">
<div class="label">1 border</div>
<div class="box" style="border-top: 4px solid #e74c3c;">top</div>
<div class="box" style="border-right: 4px solid #27ae60;">right</div>
<div class="box" style="border-bottom: 4px solid #2980b9;">bottom</div>
<div class="box" style="border-left: 4px solid #8e44ad;">left</div>
</div>
<div class="row">
<div class="label">1 border 8px</div>
<div class="box" style="border-top: 8px solid #c0392b;">top</div>
<div class="box" style="border-right: 8px solid #1e8449;">right</div>
<div class="box" style="border-bottom: 8px solid #1f618d;">bottom</div>
<div class="box" style="border-left: 8px solid #6c3483;">left</div>
</div>
<!-- ============ 2 ADJACENT BORDERS ============ -->
<div class="row">
<div class="label">2 adj borders</div>
<div class="box" style="border-top: 4px solid #e74c3c; border-right: 4px solid #27ae60;">top+right</div>
<div class="box" style="border-right: 4px solid #27ae60; border-bottom: 4px solid #2980b9;">right+bot</div>
<div class="box" style="border-bottom: 4px solid #2980b9; border-left: 4px solid #8e44ad;">bot+left</div>
<div class="box" style="border-left: 4px solid #8e44ad; border-top: 4px solid #e74c3c;">left+top</div>
</div>
<div class="row">
<div class="label">2 adj 2px/8px</div>
<div class="box" style="border-top: 2px solid #e74c3c; border-right: 8px solid #27ae60;">t2/r8</div>
<div class="box" style="border-right: 8px solid #27ae60; border-bottom: 2px solid #2980b9;">r8/b2</div>
<div class="box" style="border-bottom: 2px solid #2980b9; border-left: 8px solid #8e44ad;">b2/l8</div>
<div class="box" style="border-left: 8px solid #8e44ad; border-top: 2px solid #e74c3c;">l8/t2</div>
</div>
<!-- ============ 2 OPPOSITE BORDERS ============ -->
<div class="row">
<div class="label">2 opp borders</div>
<div class="box" style="border-top: 4px solid #e74c3c; border-bottom: 4px solid #2980b9;">top+bot</div>
<div class="box" style="border-left: 4px solid #8e44ad; border-right: 4px solid #27ae60;">left+right</div>
<div class="box" style="border-top: 8px solid #c0392b; border-bottom: 2px solid #1f618d;">t8/b2</div>
<div class="box" style="border-left: 2px solid #6c3483; border-right: 8px solid #1e8449;">l2/r8</div>
</div>
<!-- ============ 3 BORDERS ============ -->
<div class="row">
<div class="label">3 borders</div>
<div class="box" style="border-top: 4px solid #e74c3c; border-right: 4px solid #27ae60; border-bottom: 4px solid #2980b9;">no left</div>
<div class="box" style="border-right: 4px solid #27ae60; border-bottom: 4px solid #2980b9; border-left: 4px solid #8e44ad;">no top</div>
<div class="box" style="border-bottom: 4px solid #2980b9; border-left: 4px solid #8e44ad; border-top: 4px solid #e74c3c;">no right</div>
<div class="box" style="border-left: 4px solid #8e44ad; border-top: 4px solid #e74c3c; border-right: 4px solid #27ae60;">no bottom</div>
</div>
<div class="row">
<div class="label">3 brdrs mixed</div>
<div class="box" style="border-top: 8px solid #c0392b; border-right: 2px solid #1e8449; border-bottom: 4px solid #1f618d;">t8/r2/b4</div>
<div class="box" style="border-right: 2px solid #27ae60; border-bottom: 8px solid #2980b9; border-left: 4px solid #6c3483;">r2/b8/l4</div>
<div class="box" style="border-bottom: 4px solid #2980b9; border-left: 8px solid #8e44ad; border-top: 2px solid #e74c3c;">b4/l8/t2</div>
<div class="box" style="border-left: 2px solid #8e44ad; border-top: 4px solid #e74c3c; border-right: 8px solid #27ae60;">l2/t4/r8</div>
</div>
<!-- ============ 4 BORDERS ============ -->
<div class="row">
<div class="label">4 borders</div>
<div class="box" style="border: 4px solid #555;">all 4px</div>
<div class="box" style="border: 1px solid #555;">all 1px</div>
<div class="box" style="border: 8px solid #555;">all 8px</div>
<div class="box" style="border-top: 2px solid #e74c3c; border-right: 4px solid #27ae60; border-bottom: 6px solid #2980b9; border-left: 8px solid #8e44ad;">mixed</div>
</div>
<div class="row">
<div class="label">4 brdrs colors</div>
<div class="box" style="border: 6px solid #e67e22;">orange</div>
<div class="box" style="border: 3px solid #1abc9c;">teal</div>
<div class="box" style="border: 10px solid #9b59b6;">purple</div>
<div class="box" style="border-top: 10px solid #f1c40f; border-right: 6px solid #e74c3c; border-bottom: 3px solid #2ecc71; border-left: 1px solid #3498db;">multi</div>
</div>
<!-- ============ 4 BORDERS + RADIUS ============ -->
<div class="row">
<div class="label">radius all same</div>
<div class="box" style="border: 4px solid #e74c3c; border-radius: 4px;">r4</div>
<div class="box" style="border: 4px solid #27ae60; border-radius: 8px;">r8</div>
<div class="box" style="border: 4px solid #2980b9; border-radius: 12px;">r12</div>
<div class="box" style="border: 4px solid #8e44ad; border-radius: 20px;">r20</div>
</div>
<div class="row">
<div class="label">radius diff</div>
<div class="box" style="border: 4px solid #e74c3c; border-top-left-radius: 16px; border-bottom-right-radius: 16px;">tl+br</div>
<div class="box" style="border: 4px solid #27ae60; border-top-right-radius: 16px; border-bottom-left-radius: 16px;">tr+bl</div>
<div class="box" style="border: 4px solid #2980b9; border-top-left-radius: 4px; border-top-right-radius: 8px; border-bottom-right-radius: 12px; border-bottom-left-radius: 2px;">mixed</div>
<div class="box" style="border: 4px solid #8e44ad; border-top-left-radius: 32px;">tl32</div>
</div>
<!-- ============ PARTIAL BORDERS + RADIUS ============ -->
<div class="row">
<div class="label">part+radius</div>
<div class="box" style="border-top: 4px solid #e74c3c; border-right: 4px solid #27ae60; border-radius: 8px;">t+r r8</div>
<div class="box" style="border-bottom: 4px solid #2980b9; border-left: 4px solid #8e44ad; border-radius: 12px;">b+l r12</div>
<div class="box" style="border-top: 4px solid #e74c3c; border-bottom: 4px solid #2980b9; border-radius: 8px;">t+b r8</div>
<div class="box" style="border: 4px solid #27ae60; border-left: 0px; border-radius: 8px;">noL r8</div>
</div>
<div class="row">
<div class="label">part+radius2</div>
<div class="box" style="border: 4px solid #e74c3c; border-bottom: 0px; border-radius: 8px;">noB r8</div>
<div class="box" style="border: 4px solid #2980b9; border-top: 0px; border-radius: 8px;">noT r8</div>
<div class="box" style="border: 4px solid #8e44ad; border-right: 0px; border-radius: 8px;">noR r8</div>
<div class="box" style="border-top: 2px solid #e74c3c; border-left: 6px solid #8e44ad; border-radius: 6px;">t2+l6</div>
</div>
<!-- ============ THICK BORDERS + RADIUS ============ -->
<div class="row">
<div class="label">thick+radius</div>
<div class="box" style="border: 8px solid #e74c3c; border-radius: 12px;">8px/r12</div>
<div class="box" style="border: 12px solid #27ae60; border-radius: 16px;">12/r16</div>
<div class="box" style="border: 3px solid #2980b9; border-radius: 32px;">3px/r32</div>
<div class="box" style="border-top: 12px solid #e74c3c; border-radius: 8px;">t12</div>
</div>
<!-- ============ DIFFERENT SIZES ============ -->
<div class="row">
<div class="label">large boxes</div>
<div class="box" style="width: 96px; height: 96px; border: 6px solid #e74c3c; border-radius: 16px;">96x96</div>
<div class="box" style="width: 96px; height: 48px; border: 4px solid #27ae60;">96x48</div>
<div class="box" style="width: 48px; height: 96px; border: 4px solid #2980b9; border-radius: 8px;">48x96</div>
<div class="box" style="width: 96px; height: 96px; border: 2px solid #e74c3c; border-top: 10px solid #8e44ad; border-left: 1px solid #2ecc71;">mixed96</div>
</div>
<div class="clearfix"></div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@@ -149,14 +149,120 @@ void Borders::createBorders( VertexBuffer* vbo, const Borders& borders, const Ve
borderRight = eemin( (int)( size.getWidth() * 0.5f ), (int)borders.right.width );
}
// draw top border
if ( borderTop ) {
double leftW = eemin( halfWidth, eemax( 0.f, borders.radius.topLeft.x ) );
double rightW = eemin( halfHeight, eemax( 0.f, borders.radius.topRight.x ) );
double leftH = eemin( halfWidth, eemax( 0.f, borders.radius.topLeft.y ) );
double rightH = eemin( halfHeight, eemax( 0.f, borders.radius.topRight.y ) );
bool hasTop = borderTop > 0;
bool hasRight = borderRight > 0;
bool hasBottom = borderBottom > 0;
bool hasLeft = borderLeft > 0;
if ( leftW ) {
if ( !hasTop && !hasRight && !hasBottom && !hasLeft )
return;
// Pre-compute arc radii for each corner
double tlArcW = eemin( halfWidth, eemax( 0.f, borders.radius.topLeft.x ) );
double tlArcH = eemin( halfWidth, eemax( 0.f, borders.radius.topLeft.y ) );
double trArcW = eemin( halfHeight, eemax( 0.f, borders.radius.topRight.x ) );
double trArcH = eemin( halfHeight, eemax( 0.f, borders.radius.topRight.y ) );
double brArcW = eemin( halfHeight, eemax( 0.f, borders.radius.bottomRight.x ) );
double brArcH = eemin( halfHeight, eemax( 0.f, borders.radius.bottomRight.y ) );
double blArcW = eemin( halfWidth, eemax( 0.f, borders.radius.bottomLeft.x ) );
double blArcH = eemin( halfWidth, eemax( 0.f, borders.radius.bottomLeft.y ) );
// Corner positions
Vector2f tlInner( pos.x + borderLeft, pos.y + borderTop );
Vector2f tlOuter( pos.x, pos.y );
Vector2f trInner( pos.x + size.getWidth() - borderRight, pos.y + borderTop );
Vector2f trOuter( pos.x + size.getWidth(), pos.y );
Vector2f brInner( pos.x + size.getWidth() - borderRight,
pos.y + size.getHeight() - borderBottom );
Vector2f brOuter( pos.x + size.getWidth(), pos.y + size.getHeight() );
Vector2f blInner( pos.x + borderLeft, pos.y + size.getHeight() - borderBottom );
Vector2f blOuter( pos.x, pos.y + size.getHeight() );
// Helper: compute arc outer vertex at a given angle
auto arcOuterPos = []( const Vector2f& center, double rW, double rH,
double angleDeg ) -> Vector2f {
return Vector2f( center.x + rW * Math::cosAng( angleDeg ),
center.y + rH * Math::sinAng( angleDeg ) );
};
// Helper: compute arc inner vertex at a given angle
auto arcInnerPos = []( const Vector2f& center, double rW, double rH, double angleDeg,
double lineW, const Vector2f& basePos ) -> Vector2f {
if ( rW > lineW )
return Vector2f( center.x + ( rW - lineW ) * Math::cosAng( angleDeg ),
center.y + ( rH - lineW ) * Math::sinAng( angleDeg ) );
return basePos;
};
// Pre-compute first inner vertex of each border (used as bridge targets)
// Top border first inner (top-left corner)
Vector2f topFirstInner;
if ( tlArcW > 0 && hasLeft ) {
Vector2f tlCenter( pos.x + tlArcW, pos.y + tlArcH );
topFirstInner =
arcInnerPos( tlCenter, tlArcW, tlArcH, 225, borderTop,
Vector2f( pos.x + borderLeft, pos.y + borderTop ) );
} else {
topFirstInner = tlInner;
}
// Right border first inner (top-right corner)
Vector2f rightFirstInner;
if ( trArcW > 0 && hasTop ) {
Vector2f trCenter( pos.x + size.getWidth() - trArcW, pos.y + trArcH );
rightFirstInner =
arcInnerPos( trCenter, trArcW, trArcH, 315, borderRight,
Vector2f( pos.x + size.getWidth() - borderRight, pos.y + borderTop ) );
} else {
rightFirstInner = trInner;
}
// Bottom border first inner (bottom-right corner)
Vector2f bottomFirstInner;
if ( brArcW > 0 && hasRight ) {
Vector2f brCenter( pos.x + size.getWidth() - brArcW,
pos.y + size.getHeight() - brArcH );
bottomFirstInner =
arcInnerPos( brCenter, brArcW, brArcH, 45, borderBottom,
Vector2f( pos.x + size.getWidth() - borderRight,
pos.y + size.getHeight() - borderBottom ) );
} else {
bottomFirstInner = brInner;
}
// Left border first inner (bottom-left corner)
Vector2f leftFirstInner;
if ( blArcW > 0 && hasBottom ) {
Vector2f blCenter( pos.x + blArcW, pos.y + size.getHeight() - blArcH );
leftFirstInner =
arcInnerPos( blCenter, blArcW, blArcH, 135, borderLeft,
Vector2f( pos.x + borderLeft,
pos.y + size.getHeight() - borderBottom ) );
} else {
leftFirstInner = blInner;
}
// Helper: insert degenerate triangle bridge between two disconnected border sections
auto addBridge = [&]( const Vector2f& fromOuter, const Vector2f& toInner,
const Color& bridgeColor ) {
vbo->addVertex( fromOuter );
vbo->addColor( bridgeColor );
vbo->addVertex( toInner );
vbo->addColor( bridgeColor );
vbo->addVertex( toInner );
vbo->addColor( bridgeColor );
};
Vector2f lastOuter; // last emitted outer vertex, used as bridge source
// --- draw top border ---
if ( hasTop ) {
double leftW = tlArcW;
double rightW = trArcW;
double leftH = tlArcH;
double rightH = trArcH;
if ( leftW && hasLeft ) {
double endAngle = 270;
double startAngle = 225;
@@ -170,7 +276,7 @@ void Borders::createBorders( VertexBuffer* vbo, const Borders& borders, const Ve
vbo->addColor( borders.top.color );
}
if ( rightW ) {
if ( rightW && hasRight ) {
double startAngle = 270;
double endAngle = 315;
Vector2f basePos( pos.x + size.getWidth() - borderRight, pos.y + borderTop );
@@ -191,22 +297,33 @@ void Borders::createBorders( VertexBuffer* vbo, const Borders& borders, const Ve
borderAddArc( vbo, tPos, rightW, rightH, startAngle, endAngle, borders.top.color,
borderTop, basePos );
lastOuter = arcOuterPos( tPos, rightW, rightH, endAngle );
} else {
vbo->addVertex( Vector2f( pos.x + size.getWidth() - borderRight, pos.y + borderTop ) );
vbo->addColor( borders.top.color );
vbo->addVertex( Vector2f( pos.x + size.getWidth(), pos.y ) );
vbo->addColor( borders.top.color );
lastOuter = trOuter;
}
if ( !hasRight ) {
if ( hasBottom )
addBridge( lastOuter, bottomFirstInner, borders.top.color );
else if ( hasLeft )
addBridge( lastOuter, leftFirstInner, borders.top.color );
}
}
// draw right border
if ( borderRight ) {
double topW = eemin( halfWidth, eemax( 0.f, borders.radius.topRight.x ) );
double bottomW = eemin( halfHeight, eemax( 0.f, borders.radius.bottomRight.x ) );
double topH = eemin( halfWidth, eemax( 0.f, borders.radius.topRight.y ) );
double bottomH = eemin( halfHeight, eemax( 0.f, borders.radius.bottomRight.y ) );
// --- draw right border ---
if ( hasRight ) {
double topW = trArcW;
double bottomW = brArcW;
double topH = trArcH;
double bottomH = brArcH;
if ( topW ) {
if ( topW && hasTop ) {
double startAngle = 315;
double endAngle = 360;
Vector2f basePos( pos.x + size.getWidth() - borderRight, pos.y + borderTop );
@@ -220,7 +337,7 @@ void Borders::createBorders( VertexBuffer* vbo, const Borders& borders, const Ve
vbo->addColor( borders.right.color );
}
if ( bottomH ) {
if ( bottomH && hasBottom ) {
double startAngle = 0;
double endAngle = 45;
Vector2f basePos( pos.x + size.getWidth() - borderRight,
@@ -243,23 +360,29 @@ void Borders::createBorders( VertexBuffer* vbo, const Borders& borders, const Ve
borderAddArc( vbo, tPos, bottomW, bottomH, startAngle, endAngle, borders.right.color,
borderRight, basePos );
lastOuter = arcOuterPos( tPos, bottomW, bottomH, endAngle );
} else {
vbo->addVertex( Vector2f( pos.x + size.getWidth() - borderRight,
pos.y + size.getHeight() - borderBottom ) );
vbo->addColor( borders.right.color );
vbo->addVertex( Vector2f( pos.x + size.getWidth(), pos.y + size.getHeight() ) );
vbo->addColor( borders.right.color );
lastOuter = brOuter;
}
if ( !hasBottom && hasLeft )
addBridge( lastOuter, leftFirstInner, borders.right.color );
}
// draw bottom border
if ( borderBottom ) {
double leftW = eemin( halfWidth, eemax( 0.f, borders.radius.bottomLeft.x ) );
double rightW = eemin( halfHeight, eemax( 0.f, borders.radius.bottomRight.x ) );
double leftH = eemin( halfWidth, eemax( 0.f, borders.radius.bottomLeft.y ) );
double rightH = eemin( halfHeight, eemax( 0.f, borders.radius.bottomRight.y ) );
// --- draw bottom border ---
if ( hasBottom ) {
double leftW = blArcW;
double rightW = brArcW;
double leftH = blArcH;
double rightH = brArcH;
if ( rightW ) {
if ( rightW && hasRight ) {
double startAngle = 45;
double endAngle = 90;
Vector2f basePos( pos.x + size.getWidth() - borderRight,
@@ -277,7 +400,7 @@ void Borders::createBorders( VertexBuffer* vbo, const Borders& borders, const Ve
vbo->addColor( borders.bottom.color );
}
if ( leftW ) {
if ( leftW && hasLeft ) {
double startAngle = 90;
double endAngle = 135;
Vector2f basePos( pos.x + borderLeft, pos.y + size.getHeight() - borderBottom );
@@ -299,23 +422,30 @@ void Borders::createBorders( VertexBuffer* vbo, const Borders& borders, const Ve
borderAddArc( vbo, tPos, leftW, leftH, startAngle, endAngle, borders.bottom.color,
borderBottom, basePos );
lastOuter = arcOuterPos( tPos, leftW, leftH, endAngle );
} else {
vbo->addVertex(
Vector2f( pos.x + borderLeft, pos.y + size.getHeight() - borderBottom ) );
vbo->addColor( borders.bottom.color );
vbo->addVertex( Vector2f( pos.x, pos.y + size.getHeight() ) );
vbo->addColor( borders.bottom.color );
lastOuter = blOuter;
}
// After bottom, only left remains (already checked or skipped).
// Bottom and left are adjacent, no bridge needed.
}
// draw left border
if ( borderLeft ) {
double topW = eemin( halfWidth, eemax( 0.f, borders.radius.topLeft.x ) );
double bottomW = eemin( halfHeight, eemax( 0.f, borders.radius.bottomLeft.x ) );
double topH = eemin( halfWidth, eemax( 0.f, borders.radius.topLeft.y ) );
double bottomH = eemin( halfHeight, eemax( 0.f, borders.radius.bottomLeft.y ) );
// --- draw left border ---
if ( hasLeft ) {
double topW = tlArcW;
double bottomW = blArcW;
double topH = tlArcH;
double bottomH = blArcH;
if ( bottomW ) {
if ( bottomW && hasBottom ) {
double startAngle = 135;
double endAngle = 180;
Vector2f basePos( pos.x + borderLeft, pos.y + size.getHeight() - borderBottom );
@@ -331,7 +461,7 @@ void Borders::createBorders( VertexBuffer* vbo, const Borders& borders, const Ve
vbo->addColor( borders.left.color );
}
if ( topW ) {
if ( topW && hasTop ) {
double startAngle = 180;
double endAngle = 225;
Vector2f basePos( pos.x + borderLeft, pos.y + borderTop );

View File

@@ -147,13 +147,13 @@ void StyleSheetPropertiesParser::addProperty( std::string name, std::string valu
StyleSheetSpecification::instance()->getShorthand( name )->parse( value );
for ( auto& property : properties )
mProperties.emplace( std::make_pair( property.getId(), std::move( property ) ) );
mProperties[property.getId()] = std::move( property );
} else {
if ( String::startsWith( name, "--" ) ) {
mVariables[String::hash( name )] = StyleSheetVariable( name, value );
} else {
StyleSheetProperty property( name, value );
mProperties.emplace( std::make_pair( property.getId(), std::move( property ) ) );
mProperties[property.getId()] = std::move( property );
}
}
}

View File

@@ -210,12 +210,11 @@ UnorderedSet<UIWidget*>& UIStyle::getStructurallyVolatileChildren() {
}
const CSS::StyleSheetProperty* UIStyle::getProperty( const CSS::PropertyId& id ) {
const CSS::StyleSheetProperty* prop = nullptr;
if ( mGlobalDefinition && ( prop = mGlobalDefinition->getProperty( (Uint32)id ) ) )
return prop;
if ( mElementStyle )
prop = mElementStyle->getPropertyById( id );
return prop;
const auto* gProp = mGlobalDefinition ? mGlobalDefinition->getProperty( (Uint32)id ) : nullptr;
const auto* elProp = mElementStyle ? mElementStyle->getPropertyById( id ) : nullptr;
if ( elProp && gProp )
return elProp->getSpecificity() > gProp->getSpecificity() ? elProp : gProp;
return elProp ? elProp : gProp;
}
bool UIStyle::hasProperty( const CSS::PropertyId& propertyId ) const {

View File

@@ -1846,7 +1846,7 @@ bool UIWidget::applyProperty( const StyleSheetProperty& attribute ) {
StyleSheetSelectorRule::SpecificityImportant ) );
}
setLayoutWidthPolicy( SizePolicy::Fixed );
setSize( eefloor( lengthFromValueAsDp( attribute ) ), getSize().getHeight() );
setSize( eefloor( lengthFromValueAsDp( attribute ) ), mDpSize.getHeight() );
notifyLayoutAttrChange();
}
break;
@@ -1860,7 +1860,7 @@ bool UIWidget::applyProperty( const StyleSheetProperty& attribute ) {
StyleSheetSelectorRule::SpecificityImportant ) );
}
setLayoutHeightPolicy( SizePolicy::Fixed );
setSize( getSize().getWidth(), eefloor( lengthFromValueAsDp( attribute ) ) );
setSize( mDpSize.getWidth(), eefloor( lengthFromValueAsDp( attribute ) ) );
notifyLayoutAttrChange();
}
break;
@@ -2276,12 +2276,12 @@ void UIWidget::loadFromXmlNode( const pugi::xml_node& node ) {
StyleSheetPropertiesParser propertiesParser;
propertiesParser.parse( std::string_view{ ait->value() } );
if ( !propertiesParser.getProperties().empty() ) {
for ( auto& [_, property] : propertiesParser.getProperties() ) {
auto propertyImportant( property );
propertyImportant.setImportant( true );
if ( mStyle )
mStyle->setStyleSheetProperty( propertyImportant );
applyProperty( propertyImportant );
for ( auto& [_, prop] : propertiesParser.getProperties() ) {
auto property( prop );
property.setSpecificity( StyleSheetSelectorRule::SpecificityInline );
if ( NULL != mStyle )
mStyle->setStyleSheetProperty( property );
applyProperty( property );
}
}
continue;

View File

@@ -802,3 +802,37 @@ UTEST( UILayout, listStyleInheritanceFromUl ) {
Engine::destroySingleton();
}
UTEST( UIBorder, renderingVariations ) {
auto win = Engine::instance()->createWindow(
WindowSettings( 1200, 900, "Border Rendering 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/border_tests.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-border-rendering", "html" );
Engine::destroySingleton();
}