Commit 0a9dd6d4 authored by Morten Stenshorne's avatar Morten Stenshorne Committed by Commit Bot

[LayoutNG] Implement NGColumnLayoutAlgorithm::ComputeMinMaxSize().

Intrinsic sizing for multicol used to be defined in the intrinsic and
extrinsic sizing CSS spec, but it must have been removed at some point.

All we have for inspiration now is the implementation in the legacy engine,
which landed with https://chromiumcodereview.appspot.com/23763002 back in 2013.
That, and common sense. :) The principles of min/max width calculation are,
after all, quite simple:

1. Figure out how much width we need to prevent avoidable overflow (min)
2. Figure out how much width we need to prevent avoidable soft wrapping (max)

Cq-Include-Trybots: master.tryserver.chromium.linux:linux_layout_tests_layout_ng
Change-Id: Id465449369d0227883e08228ce33346eb5b5cdba
Reviewed-on: https://chromium-review.googlesource.com/700460
Commit-Queue: Morten Stenshorne <mstensho@opera.com>
Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#506680}
parent df6c5c83
......@@ -4,6 +4,7 @@
#include "core/layout/ng/ng_column_layout_algorithm.h"
#include <algorithm>
#include "core/layout/ng/inline/ng_baseline.h"
#include "core/layout/ng/ng_block_layout_algorithm.h"
#include "core/layout/ng/ng_box_fragment.h"
......@@ -81,8 +82,32 @@ RefPtr<NGLayoutResult> NGColumnLayoutAlgorithm::Layout() {
}
Optional<MinMaxSize> NGColumnLayoutAlgorithm::ComputeMinMaxSize() const {
DCHECK(0) << "Min/max calculation not yet implemented for multicol";
return WTF::nullopt;
// First calculate the min/max sizes of columns.
Optional<MinMaxSize> min_max_sizes =
NGBlockLayoutAlgorithm(Node(), ConstraintSpace()).ComputeMinMaxSize();
DCHECK(min_max_sizes.has_value());
MinMaxSize sizes = min_max_sizes.value();
// If column-width is non-auto, pick the larger of that and intrinsic column
// width.
if (!Style().HasAutoColumnWidth()) {
sizes.min_size =
std::max(sizes.min_size, LayoutUnit(Style().ColumnWidth()));
sizes.max_size = std::max(sizes.max_size, sizes.min_size);
}
// Now convert those column min/max values to multicol container min/max
// values. We typically have multiple columns and also gaps between them.
int column_count = Style().ColumnCount();
DCHECK_GE(column_count, 1);
sizes.min_size *= column_count;
sizes.max_size *= column_count;
LayoutUnit column_gap = ResolveUsedColumnGap(Style());
LayoutUnit gap_extra = column_gap * (column_count - 1);
sizes.min_size += gap_extra;
sizes.max_size += gap_extra;
return sizes;
}
RefPtr<NGConstraintSpace>
......
......@@ -6,6 +6,7 @@
#include "core/layout/ng/ng_base_layout_algorithm_test.h"
#include "core/layout/ng/ng_block_layout_algorithm.h"
#include "core/layout/ng/ng_column_layout_algorithm.h"
namespace blink {
namespace {
......@@ -731,5 +732,62 @@ TEST_F(NGColumnLayoutAlgorithmTest, BorderAndPadding) {
EXPECT_EQ(expectation, dump);
}
TEST_F(NGColumnLayoutAlgorithmTest, MinMax) {
// The multicol container here contains two inline-blocks with a line break
// opportunity between them. We'll test what min/max values we get for the
// multicol container when specifying both column-count and column-width, only
// column-count, and only column-width.
SetBodyInnerHTML(R"HTML(
<style>
#multicol {
column-gap: 10px;
width: fit-content;
}
#multicol span { display:inline-block; width:50px; height:50px; }
</style>
<div id="container">
<div id="multicol">
<div>
<span></span><wbr><span></span>
</div>
</div>
</div>
)HTML");
LayoutObject* layout_object = GetLayoutObjectByElementId("multicol");
ASSERT_TRUE(layout_object);
ASSERT_TRUE(layout_object->IsBox());
NGBlockNode node = NGBlockNode(ToLayoutBox(layout_object));
ComputedStyle* style = layout_object->MutableStyle();
RefPtr<NGConstraintSpace> space = ConstructBlockLayoutTestConstraintSpace(
kHorizontalTopBottom, TextDirection::kLtr,
NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite));
NGColumnLayoutAlgorithm algorithm(node, *space.get());
Optional<MinMaxSize> size;
// Both column-count and column-width set.
style->SetColumnCount(3);
style->SetColumnWidth(80);
size = algorithm.ComputeMinMaxSize();
ASSERT_TRUE(size.has_value());
EXPECT_EQ(LayoutUnit(260), size->min_size);
EXPECT_EQ(LayoutUnit(320), size->max_size);
// Only column-count set.
style->SetHasAutoColumnWidth();
size = algorithm.ComputeMinMaxSize();
ASSERT_TRUE(size.has_value());
EXPECT_EQ(LayoutUnit(170), size->min_size);
EXPECT_EQ(LayoutUnit(320), size->max_size);
// Only column-width set.
style->SetColumnWidth(80);
style->SetHasAutoColumnCount();
size = algorithm.ComputeMinMaxSize();
ASSERT_TRUE(size.has_value());
EXPECT_EQ(LayoutUnit(80), size->min_size);
EXPECT_EQ(LayoutUnit(100), size->max_size);
}
} // anonymous namespace
} // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment