fix bug where nested align: stretch were not properly working

The way the algorithm work is that you first layout fixed children on the main axis, then compute all the dimensions so that you can layout flexible children. This separation doesn't work anymore if we add the other axis. The solution here is a hacky (but working!) attempt at fixing the issue. We start by doing a pass to set the children dimensions if they are stretch.
This commit is contained in:
Christopher Chedeau
2014-05-19 12:39:27 -07:00
parent eae5cdfe68
commit e53bf49746
4 changed files with 101 additions and 1 deletions

View File

@@ -364,6 +364,25 @@ void layoutNode(css_node_t *node) {
return;
}
// Pre-fill cross axis dimensions when the child is using stretch before
// we call the recursive layout pass
for (int i = 0; i < node->children_count; ++i) {
css_node_t* child = &node->children[i];
if (getAlignItem(node, child) == CSS_ALIGN_STRETCH &&
getPositionType(child) == CSS_POSITION_RELATIVE &&
!isUndefined(node->layout.dimensions[dim[crossAxis]]) &&
!isDimDefined(child, crossAxis) &&
!isPosDefined(child, leading[crossAxis])) {
child->layout.dimensions[dim[crossAxis]] = fmaxf(
node->layout.dimensions[dim[crossAxis]] -
getPaddingAndBorderAxis(node, crossAxis) -
getMarginAxis(child, crossAxis),
// You never want to go smaller than padding
getPaddingAndBorderAxis(child, crossAxis)
);
}
}
// <Loop A> Layout non flexible children and count children by type
// mainContentDim is accumulation of the dimensions and margin of all the

View File

@@ -242,6 +242,25 @@ var computeLayout = (function() {
return;
}
// Pre-fill cross axis dimensions when the child is using stretch before
// we call the recursive layout pass
for (var/*int*/ i = 0; i < node.children.length; ++i) {
var/*css_node_t**/ child = node.children[i];
if (getAlignItem(node, child) === CSS_ALIGN_STRETCH &&
getPositionType(child) === CSS_POSITION_RELATIVE &&
!isUndefined(node.layout[dim[crossAxis]]) &&
!isDimDefined(child, crossAxis) &&
!isPosDefined(child, leading[crossAxis])) {
child.layout[dim[crossAxis]] = fmaxf(
node.layout[dim[crossAxis]] -
getPaddingAndBorderAxis(node, crossAxis) -
getMarginAxis(child, crossAxis),
// You never want to go smaller than padding
getPaddingAndBorderAxis(child, crossAxis)
);
}
}
// <Loop A> Layout non flexible children and count children by type
// mainContentDim is accumulation of the dimensions and margin of all the

View File

@@ -2563,6 +2563,55 @@ int main()
test("should layout node with text and position absolute", root_node, root_layout);
}
{
css_node_t *root_node = new_css_node();
{
css_node_t *node_0 = root_node;
node_0->style.dimensions[CSS_WIDTH] = 300;
init_css_node_children(node_0, 1);
{
css_node_t *node_1;
node_1 = &node_0->children[0];
node_1->style.align_self = CSS_ALIGN_STRETCH;
init_css_node_children(node_1, 1);
{
css_node_t *node_2;
node_2 = &node_1->children[0];
node_2->style.align_self = CSS_ALIGN_STRETCH;
}
}
}
css_node_t *root_layout = new_css_node();
{
css_node_t *node_0 = root_layout;
node_0->layout.position[CSS_TOP] = 0;
node_0->layout.position[CSS_LEFT] = 0;
node_0->layout.dimensions[CSS_WIDTH] = 300;
node_0->layout.dimensions[CSS_HEIGHT] = 0;
init_css_node_children(node_0, 1);
{
css_node_t *node_1;
node_1 = &node_0->children[0];
node_1->layout.position[CSS_TOP] = 0;
node_1->layout.position[CSS_LEFT] = 0;
node_1->layout.dimensions[CSS_WIDTH] = 300;
node_1->layout.dimensions[CSS_HEIGHT] = 0;
init_css_node_children(node_1, 1);
{
css_node_t *node_2;
node_2 = &node_1->children[0];
node_2->layout.position[CSS_TOP] = 0;
node_2->layout.position[CSS_LEFT] = 0;
node_2->layout.dimensions[CSS_WIDTH] = 300;
node_2->layout.dimensions[CSS_HEIGHT] = 0;
}
}
}
test("should layout node with nested alignSelf: stretch", root_node, root_layout);
}
{
css_node_t *root_node = new_css_node();
{

View File

@@ -777,7 +777,20 @@ describe('Layout', function() {
)
});
it('should layout node with nested alignSelf: stretch', function() {
testLayout(
{style: {width: 300}, children: [
{style: {alignSelf: 'stretch'}, children: [
{style: {alignSelf: 'stretch'}}
]}
]},
{width: 300, height: 0, top: 0, left: 0, children: [
{width: 300, height: 0, top: 0, left: 0, children: [
{width: 300, height: 0, top: 0, left: 0}
]}
]}
);
});
it('should layout randomly', function() {
function RNG(seed) {