srctree

Robin Linden parent 30a85527 3d286a66
layout: Handle {min,max}-{height,width}

Now websites are starting to look like websites!

inlinesplit
layout/layout.cpp added: 151, removed: 2, total 149
@@ -93,6 +93,15 @@ void calculate_width(LayoutBox &box, Rect const &parent) {
assert(box.node != nullptr);
auto width = get_property_or(*box.node, "width", "auto");
int width_px = width == "auto" ? static_cast<int>(parent.width) : to_px(width);
 
if (auto min = get_property(*box.node, "min-width"); min) {
width_px = std::max(width_px, to_px(*min));
}
 
if (auto max = get_property(*box.node, "max-width"); max) {
width_px = std::min(width_px, to_px(*max));
}
 
int underflow = static_cast<int>(parent.width) - width_px;
if (underflow < 0) {
// Overflow, this should adjust the right margin, but for now...
@@ -114,6 +123,14 @@ void calculate_height(LayoutBox &box) {
if (auto height = get_property(*box.node, "height"); height) {
box.dimensions.content.height = static_cast<float>(to_px(*height));
}
 
if (auto min = get_property(*box.node, "min-height"); min) {
box.dimensions.content.height = std::max(box.dimensions.content.height, static_cast<float>(to_px(*min)));
}
 
if (auto max = get_property(*box.node, "max-height"); max) {
box.dimensions.content.height = std::min(box.dimensions.content.height, static_cast<float>(to_px(*max)));
}
}
 
void layout(LayoutBox &box, Rect const &bounds) {
 
layout/layout_test.cpp added: 151, removed: 2, total 149
@@ -185,6 +185,70 @@ int main() {
expect(layout::create_layout(style_root, 1000) == expected_layout);
});
 
etest::test("min-width", [] {
auto dom_root = dom::create_element_node("html", {}, {
dom::create_element_node("body", {}, {
dom::create_element_node("p", {}, {}),
}),
});
 
auto style_root = style::StyledNode{
.node = dom_root,
.properties = {{"min-width", "100px"}},
.children = {
{dom_root.children[0], {{"min-width", "50px"}}, {
{dom_root.children[0].children[0], {}, {}},
}},
},
};
 
auto expected_layout = layout::LayoutBox{
.node = &style_root,
.type = LayoutType::Block,
.dimensions = {{0, 0, 100, 0}},
.children = {
{&style_root.children[0], LayoutType::Block, {{0, 0, 100, 0}}, {
{&style_root.children[0].children[0], LayoutType::Block, {{0, 0, 100, 0}}, {}},
}},
}
};
 
// TOOD(robinlinden): This test breaks if the width here is less than the min width due
// to the hack that reduces the width instead of the right margin.
expect(layout::create_layout(style_root, 100) == expected_layout);
});
 
etest::test("max-width", [] {
auto dom_root = dom::create_element_node("html", {}, {
dom::create_element_node("body", {}, {
dom::create_element_node("p", {}, {}),
}),
});
 
auto style_root = style::StyledNode{
.node = dom_root,
.properties = {{"max-width", "100px"}},
.children = {
{dom_root.children[0], {{"max-width", "50px"}}, {
{dom_root.children[0].children[0], {}, {}},
}},
},
};
 
auto expected_layout = layout::LayoutBox{
.node = &style_root,
.type = LayoutType::Block,
.dimensions = {{0, 0, 100, 0}},
.children = {
{&style_root.children[0], LayoutType::Block, {{0, 0, 50, 0}}, {
{&style_root.children[0].children[0], LayoutType::Block, {{0, 0, 50, 0}}, {}},
}},
}
};
 
expect(layout::create_layout(style_root, 1000) == expected_layout);
});
 
etest::test("less simple width", [] {
auto dom_root = dom::create_element_node("html", {}, {
dom::create_element_node("body", {}, {
@@ -312,6 +376,74 @@ int main() {
expect(layout::create_layout(style_root, 0) == expected_layout);
});
 
etest::test("min-height is respected", [] {
auto dom_root = dom::create_element_node("html", {}, {
dom::create_element_node("body", {}, {
dom::create_element_node("p", {}, {}),
dom::create_element_node("p", {}, {}),
}),
});
 
auto style_root = style::StyledNode{
.node = dom_root,
.properties = {{"min-height", "400px"}},
.children = {
{dom_root.children[0], {}, {
{dom_root.children[0].children[0], {{"height", "25px"}}, {}},
{dom_root.children[0].children[1], {}, {}},
}},
},
};
 
auto expected_layout = layout::LayoutBox{
.node = &style_root,
.type = LayoutType::Block,
.dimensions = {{0, 0, 0, 400}},
.children = {
{&style_root.children[0], LayoutType::Block, {{0, 0, 0, 25}}, {
{&style_root.children[0].children[0], LayoutType::Block, {{0, 0, 0, 25}}, {}},
{&style_root.children[0].children[1], LayoutType::Block, {{0, 25, 0, 0}}, {}},
}},
}
};
 
expect(layout::create_layout(style_root, 0) == expected_layout);
});
 
etest::test("max-height is respected", [] {
auto dom_root = dom::create_element_node("html", {}, {
dom::create_element_node("body", {}, {
dom::create_element_node("p", {}, {}),
dom::create_element_node("p", {}, {}),
}),
});
 
auto style_root = style::StyledNode{
.node = dom_root,
.properties = {{"max-height", "10px"}},
.children = {
{dom_root.children[0], {}, {
{dom_root.children[0].children[0], {{"height", "400px"}}, {}},
{dom_root.children[0].children[1], {}, {}},
}},
},
};
 
auto expected_layout = layout::LayoutBox{
.node = &style_root,
.type = LayoutType::Block,
.dimensions = {{0, 0, 0, 10}},
.children = {
{&style_root.children[0], LayoutType::Block, {{0, 0, 0, 400}}, {
{&style_root.children[0].children[0], LayoutType::Block, {{0, 0, 0, 400}}, {}},
{&style_root.children[0].children[1], LayoutType::Block, {{0, 400, 0, 0}}, {}},
}},
}
};
 
expect(layout::create_layout(style_root, 0) == expected_layout);
});
 
etest::test("to_string", [] {
auto dom_root = dom::create_element_node("html", {}, {
dom::create_element_node("body", {}, {