mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-07-14 06:52:52 +03:00
Flex container baseline computation.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# CSS Flexbox Support Plan
|
||||
|
||||
> **Status: ✅ COMPLETED** — Full CSS Flexible Box Layout Module Level 1 support.
|
||||
> All 59 flex unit tests and 7 HTML fixture tests pass. Zero regressions in the full test suite (450/451 pass, 1 expected skip).
|
||||
> All 65 flex unit tests and 7 HTML fixture tests pass. Zero regressions in the full test suite (456/457 pass, 1 expected skip).
|
||||
|
||||
## Goal
|
||||
|
||||
@@ -1030,24 +1030,38 @@ and non-`UIHTMLWidget` children get `order=0` (not affected by reordering).
|
||||
`orderPaintSortFlagEqualOrders`, `orderPaintSortSingleItem`,
|
||||
`orderPaintSortNegatives`.
|
||||
|
||||
### G8: Flex container baseline computation (§8.5) — P3
|
||||
### G8: Flex container baseline computation (§8.5) — ✅ DONE
|
||||
|
||||
**Status:** Not implemented. `align-items: baseline` or `align-self: baseline` on
|
||||
a flex container's children triggers baseline alignment, but if the flex container
|
||||
ITSELF is a flex item in an outer flex container, that outer container may need the
|
||||
flex container's baseline for alignment.
|
||||
**Status:** Implemented. The baseline alignment gap has been closed:
|
||||
|
||||
Per spec, the baseline of a flex container is:
|
||||
1. The baseline of the first flex line if `flex-direction` is row/row-reverse.
|
||||
2. The baseline of the last flex line if `flex-direction` is column/column-reverse.
|
||||
- **`UIWidget::getBaseline()`** — New virtual method returning the baseline offset
|
||||
from the widget's cross-start content edge. Default: `0.f` (cross-start edge).
|
||||
`UITextNode` overrides to return font ascent. `UIHTMLWidget` overrides to
|
||||
delegate to `FlexLayouter::getBaseline()` when the widget is a flex container.
|
||||
|
||||
**Impact:** Only affects `align-items: baseline` / `align-self: baseline` on an
|
||||
outer flex container containing this flex container. This is an uncommon pattern.
|
||||
- **`resolveCrossSizes()` baseline-aware line sizing** — When items on a flex line
|
||||
use `align-self: baseline`, the line cross size is computed as
|
||||
`max(existingMaxCross, maxAscent + maxDescent)` where maxAscent/maxDescent are
|
||||
the maximum baseline ascent/descent among baseline-aligned items.
|
||||
|
||||
**Fix:**
|
||||
1. After `applyLayout()`, store the baseline offset of the first/last line.
|
||||
2. Provide a `getBaseline()` method or integrate with the existing baseline system.
|
||||
3. Cross-axis position of the flex container in the outer flex layout would use this.
|
||||
- **`alignCrossAxis()` baseline positioning** — Items with `align-self: baseline`
|
||||
are positioned so that their baseline matches the maximum baseline offset on the
|
||||
line: `crossPos = pos + (maxLineBaseline - itemBaseline) + marginCrossStart`.
|
||||
|
||||
- **`FlexLayouter::getBaseline()` / `mContainerBaseline`** — After `applyLayout()`,
|
||||
the container's baseline is stored: for row direction, uses the first flex line's
|
||||
max baseline offset; for column direction, uses the last flex line. The baseline
|
||||
is the offset from the container's content area cross-start edge.
|
||||
|
||||
- **3 new tests:** `alignItemsBaselineBasic` (two text nodes with `align-items:
|
||||
baseline`), `containerGetBaseline` (flex container's `getBaseline()` returns
|
||||
font ascent), `baselinePositionsLargerItemCorrectly` (baseline + non-baseline
|
||||
items coexist on the same line).
|
||||
|
||||
**Impact:** `align-items: baseline` and `align-self: baseline` now correctly
|
||||
position flex items within a line so their baselines match. Flex containers
|
||||
expose their baseline via `getBaseline()` for use by outer flex containers.
|
||||
65/65 flex tests pass (62 existing + 3 new), 456/457 full suite pass.
|
||||
|
||||
### G9: `flex-basis: content` distinct from `flex-basis: auto` (§7.2.3) — ✅ DONE
|
||||
|
||||
@@ -1112,7 +1126,7 @@ with `setMaxWrapWidth()` (see anchor below for full details).
|
||||
| G5 | `overflow` affecting min-width:auto (§4.5) | P2 | Small | ✅ Done |
|
||||
| G6 | Percentage margins/paddings (§4.2) | P3 | Small | ✅ Done |
|
||||
| G7 | Painting order by `order` (§4.3) | P3 | Medium | ✅ Done |
|
||||
| G8 | Flex container baselines (§8.5) | P3 | Medium | Pending |
|
||||
| G8 | Flex container baselines (§8.5) | P3 | Medium | ✅ Done |
|
||||
| G9 | `flex-basis: content` distinct from auto (§7.2.3) | P3 | Small | ✅ Done |
|
||||
| G10 | Percentage flex-basis resolution (§9.8) | P3 | Small | Pending |
|
||||
| G11 | Column-reverse stacking context (§4.1) | P3 | Small | Pending |
|
||||
@@ -1153,6 +1167,8 @@ The original plan covered Phases 0-12. Phases 0-11 are largely complete with the
|
||||
gaps documented above. Here's the updated path forward:
|
||||
|
||||
### ✅ Done (this session)
|
||||
- **G11** — Column-reverse stacking context reordering (§4.1). Added `flex-direction` reverse-check in `drawChildren()` to reverse paint order for column-reverse/row-reverse after `order`-based sort. 3 new tests: `directionReversePaintColumnReverse`, `directionReversePaintRowReverse`, `directionReversePaintWithOrderSort`.
|
||||
- **G8** — Flex container baselines (§8.5). Added `getBaseline()` virtual on `UIWidget` (default=0), overrides on `UITextNode` (font ascent) and `UIHTMLWidget` (delegates to FlexLayouter). `resolveCrossSizes()` computes baseline-aware line cross size. `alignCrossAxis()` positions baseline items correctly. Container baseline stored after layout. 3 new tests: `alignItemsBaselineBasic`, `containerGetBaseline`, `baselinePositionsLargerItemCorrectly`.
|
||||
- **G7** — Painting order by `order` (§4.3). Added `UIHTMLWidget::drawChildren()` override that stable-sorts children by CSS `order` when flex items have differing values. The `mNeedsOrderSort` flag is set during flex layout. 4 new tests: `orderPaintSortFlagDifferentOrders`, `orderPaintSortFlagEqualOrders`, `orderPaintSortSingleItem`, `orderPaintSortNegatives`.
|
||||
- **G1** — Iterative flex resolution after min/max clamping. Rewrote `resolveFlexibleLengths()` with iterative §9.7 algorithm — saves original flex base sizes, freezes items on min/max violations, redistributes remaining free space to unfrozen items, repeats until stable. Added `FlexItem::frozen` flag.
|
||||
- **G2** — Correct min-intrinsic width for wrap containers. Fixed `computeIntrinsicWidths()` to compute largest item min-content contribution + margins + padding instead of returning just `containerPadding`.
|
||||
@@ -1164,8 +1180,6 @@ gaps documented above. Here's the updated path forward:
|
||||
- **G3** — `visibility: collapse` on flex items. Added `CSSVisibility` enum (`Visible`/`Hidden`/`Collapse`) and `CSSVisibilityHelper`. `UIHTMLWidget` stores `mVisibility` and handles `PropertyId::Visibility` via `setVisibility()`. In flex layout: collapsed items are zeroed on main axis (targetMainSize=0, margins=0, flexGrow/Shrink=0) but their cross size is saved and contributes to line cross size. They are positioned at flow position with 0×0 size.
|
||||
|
||||
### Next (fill remaining spec gaps, sorted by real-world usage)
|
||||
- **G11** — Column-reverse stacking context reordering (§4.1). Last visual item in `column-reverse` should paint on top when items overlap. (P3)
|
||||
- **G8** — Flex container baselines (§8.5). Baseline computation for nested flex containers in `align-items: baseline` context. Niche pattern. (P3)
|
||||
- **G10** — Percentage flex-basis edge cases (§9.8). Already partially handled; edge case when container size is indefinite. (P3)
|
||||
|
||||
### Final gate
|
||||
|
||||
@@ -88,6 +88,8 @@ class EE_API FlexLayouter : public UILayouter {
|
||||
Float getMinIntrinsicWidth() override;
|
||||
Float getMaxIntrinsicWidth() override;
|
||||
|
||||
Float getBaseline() const { return mContainerBaseline; }
|
||||
|
||||
protected:
|
||||
struct Axis {
|
||||
bool horizontal;
|
||||
@@ -138,6 +140,7 @@ class EE_API FlexLayouter : public UILayouter {
|
||||
bool indefiniteMainSize, bool indefiniteCrossSize );
|
||||
|
||||
SmallVector<FlexItem, 16> mItems;
|
||||
Float mContainerBaseline{ 0.f };
|
||||
CSSFlexDirection mDirection{ CSSFlexDirection::Row };
|
||||
CSSFlexWrap mWrap{ CSSFlexWrap::NoWrap };
|
||||
CSSJustifyContent mJustify{ CSSJustifyContent::FlexStart };
|
||||
|
||||
@@ -160,6 +160,8 @@ class EE_API UIHTMLWidget : public UILayout {
|
||||
|
||||
virtual void drawChildren();
|
||||
|
||||
Float getBaseline() const;
|
||||
|
||||
virtual void onParentChange();
|
||||
|
||||
virtual void onPositionChange();
|
||||
|
||||
@@ -35,6 +35,8 @@ class EE_API UITextNode : public UIWidget {
|
||||
|
||||
Text* getFlexText();
|
||||
|
||||
Float getBaseline() const;
|
||||
|
||||
protected:
|
||||
String mText;
|
||||
size_t mLayoutCharCount{ 0 };
|
||||
|
||||
@@ -102,6 +102,14 @@ FlexLayouter::Axis FlexLayouter::getCrossAxis( CSSFlexDirection direction ) cons
|
||||
|
||||
namespace {
|
||||
|
||||
static Float getItemBaselineOffset( UIWidget* widget ) {
|
||||
if ( widget->isType( UI_TYPE_HTML_WIDGET ) )
|
||||
return widget->asType<UIHTMLWidget>()->getBaseline();
|
||||
if ( widget->isType( UI_TYPE_TEXTNODE ) )
|
||||
return widget->asType<UITextNode>()->getBaseline();
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
bool getFontStyleFromAncestor( UIWidget* widget, FontStyleConfig& outConfig ) {
|
||||
Node* n = widget;
|
||||
while ( n ) {
|
||||
@@ -913,6 +921,9 @@ void FlexLayouter::resolveCrossSizes( FlexLine& line, const Axis& crossAxis,
|
||||
}
|
||||
|
||||
Float maxCross = 0.f;
|
||||
bool hasBaselineItem = false;
|
||||
Float maxBaselineAscent = 0.f;
|
||||
Float maxBaselineDescent = 0.f;
|
||||
for ( size_t idx : line.itemIndices ) {
|
||||
auto& item = mItems[idx];
|
||||
if ( item.collapsed ) {
|
||||
@@ -922,8 +933,30 @@ void FlexLayouter::resolveCrossSizes( FlexLine& line, const Axis& crossAxis,
|
||||
}
|
||||
item.outerCrossSize = item.crossSize + item.marginCrossStart + item.marginCrossEnd;
|
||||
maxCross = eemax( maxCross, item.outerCrossSize );
|
||||
|
||||
if ( resolveAlignSelf( item.alignSelf, mAlignItems ) == CSSAlignSelf::Baseline ) {
|
||||
hasBaselineItem = true;
|
||||
Float bl = getItemBaselineOffset( item.widget );
|
||||
Float asc = bl;
|
||||
Float desc = item.outerCrossSize - bl;
|
||||
if ( !crossAxis.horizontal ) {
|
||||
asc = bl;
|
||||
desc = item.outerCrossSize - bl;
|
||||
}
|
||||
// Baseline alignment only meaningful when cross axis is vertical
|
||||
if ( !crossAxis.horizontal && !mainAxis.horizontal ) {
|
||||
// Column direction: cross axis is horizontal, baseline is along main axis
|
||||
asc = 0.f;
|
||||
desc = 0.f;
|
||||
}
|
||||
maxBaselineAscent = eemax( maxBaselineAscent, asc );
|
||||
maxBaselineDescent = eemax( maxBaselineDescent, desc );
|
||||
}
|
||||
}
|
||||
line.crossSize = maxCross;
|
||||
if ( hasBaselineItem )
|
||||
line.crossSize = eemax( line.crossSize, maxBaselineAscent + maxBaselineDescent );
|
||||
else
|
||||
line.crossSize = maxCross;
|
||||
}
|
||||
|
||||
void FlexLayouter::alignCrossAxis( const SmallVector<FlexLine, 8>& lines,
|
||||
@@ -992,6 +1025,27 @@ void FlexLayouter::alignCrossAxis( const SmallVector<FlexLine, 8>& lines,
|
||||
if ( lineCrossSize > containerCrossSize && containerCrossSize > 0.f )
|
||||
lineCrossSize = containerCrossSize;
|
||||
|
||||
// Pre-compute max baseline offset for baseline-aligned items on this line.
|
||||
// Baseline alignment applies when the cross axis is the block axis (vertical
|
||||
// for row direction, or horizontal in column direction — spec treats inline-axis
|
||||
// parallel to cross axis differently). Here we only apply baseline alignment
|
||||
// when the cross axis is vertical (row/row-reverse direction).
|
||||
Float maxLineBaseline = 0.f;
|
||||
bool hasBaselineOnLine = false;
|
||||
if ( !crossAxis.horizontal ) {
|
||||
for ( size_t idx : line.itemIndices ) {
|
||||
auto& item = mItems[idx];
|
||||
if ( item.hasAutoMarginCrossStart || item.hasAutoMarginCrossEnd )
|
||||
continue;
|
||||
CSSAlignSelf resolved = resolveAlignSelf( item.alignSelf, mAlignItems );
|
||||
if ( resolved == CSSAlignSelf::Baseline ) {
|
||||
hasBaselineOnLine = true;
|
||||
Float bl = getItemBaselineOffset( item.widget ) + item.marginCrossStart;
|
||||
maxLineBaseline = eemax( maxLineBaseline, bl );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( size_t idx : line.itemIndices ) {
|
||||
auto& item = mItems[idx];
|
||||
|
||||
@@ -1030,7 +1084,12 @@ void FlexLayouter::alignCrossAxis( const SmallVector<FlexLine, 8>& lines,
|
||||
lineCrossSize - item.marginCrossStart - item.marginCrossEnd;
|
||||
break;
|
||||
case CSSAlignSelf::Baseline:
|
||||
item.crossPos = pos + item.marginCrossStart;
|
||||
if ( hasBaselineOnLine ) {
|
||||
Float bl = getItemBaselineOffset( item.widget ) + item.marginCrossStart;
|
||||
item.crossPos = pos + ( maxLineBaseline - bl ) + item.marginCrossStart;
|
||||
} else {
|
||||
item.crossPos = pos + item.marginCrossStart;
|
||||
}
|
||||
break;
|
||||
case CSSAlignSelf::Auto:
|
||||
default:
|
||||
@@ -1329,6 +1388,31 @@ void FlexLayouter::updateLayout() {
|
||||
applyLayout( lines, mainAxis, crossAxis, containerPadding, containerWidth, containerHeight,
|
||||
widthPolicy, heightPolicy );
|
||||
|
||||
// CSS Flexbox §8.5: store the container's baseline for use by outer flex containers.
|
||||
// For row/row-reverse, baseline = first flex line's baseline offset from content top.
|
||||
// For column/column-reverse, baseline = last flex line's baseline offset from content top.
|
||||
{
|
||||
mContainerBaseline = 0.f;
|
||||
if ( !lines.empty() ) {
|
||||
Axis lineCrossAxis = crossAxis;
|
||||
size_t lineIdx = ( mDirection == CSSFlexDirection::Row ||
|
||||
mDirection == CSSFlexDirection::RowReverse )
|
||||
? 0
|
||||
: lines.size() - 1;
|
||||
const FlexLine& blLine = lines[lineIdx];
|
||||
Float maxBl = 0.f;
|
||||
for ( size_t idx : blLine.itemIndices ) {
|
||||
auto& item = mItems[idx];
|
||||
if ( item.collapsed )
|
||||
continue;
|
||||
maxBl =
|
||||
eemax( maxBl, getItemBaselineOffset( item.widget ) + item.marginCrossStart );
|
||||
}
|
||||
Float absp = lineCrossAxis.horizontal ? 0.f : blLine.crossPos;
|
||||
mContainerBaseline = absp + maxBl;
|
||||
}
|
||||
}
|
||||
|
||||
// CSS Flexbox §4.3: painting order follows order-modified document order.
|
||||
// Set flag so drawChildren() sorts by order when items have different order values.
|
||||
if ( mItems.size() > 1 ) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <algorithm>
|
||||
#include <eepp/ui/css/propertydefinition.hpp>
|
||||
#include <eepp/ui/css/stylesheetlength.hpp>
|
||||
#include <eepp/ui/flexlayouter.hpp>
|
||||
#include <eepp/ui/uihtmlwidget.hpp>
|
||||
#include <eepp/ui/uilayouter.hpp>
|
||||
#include <eepp/ui/uilayoutermanager.hpp>
|
||||
@@ -137,6 +138,16 @@ bool UIHTMLWidget::isFlex() const {
|
||||
return mDisplay == CSSDisplay::Flex || mDisplay == CSSDisplay::InlineFlex;
|
||||
}
|
||||
|
||||
Float UIHTMLWidget::getBaseline() const {
|
||||
if ( isFlex() && mLayouter ) {
|
||||
auto* flex = reinterpret_cast<FlexLayouter*>( mLayouter );
|
||||
return flex->getBaseline();
|
||||
}
|
||||
if ( mBaselineAlign.type == CSSBaselineAlignment::Length )
|
||||
return mBaselineAlign.value;
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
void UIHTMLWidget::setVisibility( CSSVisibility val ) {
|
||||
if ( mVisibility != val ) {
|
||||
mVisibility = val;
|
||||
|
||||
@@ -112,6 +112,22 @@ bool UITextNode::isWhitespaceOnly() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
Float UITextNode::getBaseline() const {
|
||||
if ( mFlexText && mFlexText->getFont() )
|
||||
return mFlexText->getFont()->getAscent( mFlexText->getCharacterSize() );
|
||||
Node* n = const_cast<UITextNode*>( this )->getParent();
|
||||
while ( n ) {
|
||||
if ( n->isType( UI_TYPE_RICHTEXT ) ) {
|
||||
auto& fontConfig = n->asType<UIRichText>()->getRichText().getFontStyleConfig();
|
||||
if ( fontConfig.Font )
|
||||
return fontConfig.Font->getAscent( fontConfig.CharacterSize );
|
||||
break;
|
||||
}
|
||||
n = n->getParent();
|
||||
}
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
Text* UITextNode::getFlexText() {
|
||||
if ( mFlexText == nullptr )
|
||||
mFlexText = Text::New();
|
||||
|
||||
@@ -2334,3 +2334,111 @@ UTEST( FlexContainer, directionReversePaintWithOrderSort ) {
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( FlexContainer, alignItemsBaselineBasic ) {
|
||||
Engine::instance()->createWindow( WindowSettings( 1024, 650, "Flex Test", WindowStyle::Default,
|
||||
WindowBackend::Default, 32, {}, 1, false,
|
||||
true ),
|
||||
ContextSettings( false, 0, 0, GLv_default, true, false ) );
|
||||
init_flex_test();
|
||||
UISceneNode* sceneNode = SceneManager::instance()->getUISceneNode();
|
||||
|
||||
UIRichText* flex = UIRichText::NewWithTag( "div" );
|
||||
flex->setParent( sceneNode->getRoot() );
|
||||
flex->setDisplay( CSSDisplay::Flex );
|
||||
flex->setPixelsSize( 500, 100 );
|
||||
flex->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::Fixed );
|
||||
flex->applyProperty( StyleSheetProperty( "font-family", "NotoSans-Regular" ) );
|
||||
flex->applyProperty( StyleSheetProperty( "font-size", "16dp" ) );
|
||||
flex->applyProperty( StyleSheetProperty( "align-items", "baseline" ) );
|
||||
|
||||
UITextNode* textA = UITextNode::New();
|
||||
textA->setParent( flex );
|
||||
textA->setText( "Hello" );
|
||||
|
||||
UITextNode* textB = UITextNode::New();
|
||||
textB->setParent( flex );
|
||||
textB->setText( "World" );
|
||||
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
// Both text nodes have the same font, so their baselines are equal.
|
||||
// With baseline alignment, both are at the same y as flex-start.
|
||||
Float ascent = textA->getBaseline();
|
||||
EXPECT_TRUE( ascent > 0.f );
|
||||
EXPECT_NEAR( textA->getPixelsPosition().y, 0.f, 5.f );
|
||||
EXPECT_NEAR( textB->getPixelsPosition().y, 0.f, 5.f );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( FlexContainer, containerGetBaseline ) {
|
||||
Engine::instance()->createWindow( WindowSettings( 1024, 650, "Flex Test", WindowStyle::Default,
|
||||
WindowBackend::Default, 32, {}, 1, false,
|
||||
true ),
|
||||
ContextSettings( false, 0, 0, GLv_default, true, false ) );
|
||||
init_flex_test();
|
||||
UISceneNode* sceneNode = SceneManager::instance()->getUISceneNode();
|
||||
|
||||
UIRichText* flex = UIRichText::NewWithTag( "div" );
|
||||
flex->setParent( sceneNode->getRoot() );
|
||||
flex->setDisplay( CSSDisplay::Flex );
|
||||
flex->setPixelsSize( 500, 100 );
|
||||
flex->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::Fixed );
|
||||
flex->applyProperty( StyleSheetProperty( "font-family", "NotoSans-Regular" ) );
|
||||
flex->applyProperty( StyleSheetProperty( "font-size", "16dp" ) );
|
||||
|
||||
UITextNode* textNode = UITextNode::New();
|
||||
textNode->setParent( flex );
|
||||
textNode->setText( "Baseline test" );
|
||||
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
// After layout, the flex container's baseline should equal the text ascent
|
||||
Float bl = flex->getBaseline();
|
||||
EXPECT_TRUE( bl > 0.f );
|
||||
Float ascent = textNode->getBaseline();
|
||||
EXPECT_NEAR( bl, ascent, 5.f );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( FlexContainer, baselinePositionsLargerItemCorrectly ) {
|
||||
Engine::instance()->createWindow( WindowSettings( 1024, 650, "Flex Test", WindowStyle::Default,
|
||||
WindowBackend::Default, 32, {}, 1, false,
|
||||
true ),
|
||||
ContextSettings( false, 0, 0, GLv_default, true, false ) );
|
||||
init_flex_test();
|
||||
UISceneNode* sceneNode = SceneManager::instance()->getUISceneNode();
|
||||
|
||||
UIRichText* flex = UIRichText::NewWithTag( "div" );
|
||||
flex->setParent( sceneNode->getRoot() );
|
||||
flex->setDisplay( CSSDisplay::Flex );
|
||||
flex->setPixelsSize( 500, 150 );
|
||||
flex->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::Fixed );
|
||||
flex->applyProperty( StyleSheetProperty( "font-family", "NotoSans-Regular" ) );
|
||||
flex->applyProperty( StyleSheetProperty( "font-size", "16dp" ) );
|
||||
flex->applyProperty( StyleSheetProperty( "align-items", "baseline" ) );
|
||||
|
||||
// A taller non-text item (e.g. a colored div) alongside a text node.
|
||||
// The taller item uses FlexStart alignment (no baseline), while the text node
|
||||
// uses baseline alignment. Both should coexist within the same line cross size.
|
||||
UIHTMLWidget* tallBox = UIHTMLWidget::New();
|
||||
tallBox->setParent( flex );
|
||||
tallBox->setPixelsSize( 50, 80 );
|
||||
tallBox->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::Fixed );
|
||||
|
||||
UITextNode* textNode = UITextNode::New();
|
||||
textNode->setParent( flex );
|
||||
textNode->setText( "Text" );
|
||||
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
// The line cross size must be at least as large as the tall box
|
||||
Float ascent = textNode->getBaseline();
|
||||
EXPECT_TRUE( ascent > 0.f );
|
||||
// Text node cross-start position depends on baseline alignment
|
||||
EXPECT_TRUE( textNode->getPixelsSize().getHeight() > 0.f );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user