Commit 085cf007 authored by glebl's avatar glebl Committed by Commit bot

[LayoutNG] Fix broken layout while using CSS with writing modes.

1) This will set a writing mode to the fragment builder so it can be used at the time when we calculate a physical fragment.
2) Change computeMargin to accept 2 more parameters: Direction and writing mode.

TEST=NGBlockLayoutAlgorithmTest.LayoutBlockChildrenWithWritingMode
BUG=635619

Review-Url: https://codereview.chromium.org/2347773002
Cr-Commit-Position: refs/heads/master@{#419309}
parent 14947f52
...@@ -53,6 +53,8 @@ bool NGBlockLayoutAlgorithm::Layout(const NGConstraintSpace* constraint_space, ...@@ -53,6 +53,8 @@ bool NGBlockLayoutAlgorithm::Layout(const NGConstraintSpace* constraint_space,
content_size_ = border_and_padding_.block_start; content_size_ = border_and_padding_.block_start;
builder_ = new NGFragmentBuilder(NGPhysicalFragmentBase::FragmentBox); builder_ = new NGFragmentBuilder(NGPhysicalFragmentBase::FragmentBox);
builder_->SetDirection(constraint_space->Direction());
builder_->SetWritingMode(constraint_space->WritingMode());
builder_->SetInlineSize(inline_size).SetBlockSize(block_size); builder_->SetInlineSize(inline_size).SetBlockSize(block_size);
current_child_ = first_child_; current_child_ = first_child_;
state_ = kStateChildLayout; state_ = kStateChildLayout;
...@@ -64,7 +66,9 @@ bool NGBlockLayoutAlgorithm::Layout(const NGConstraintSpace* constraint_space, ...@@ -64,7 +66,9 @@ bool NGBlockLayoutAlgorithm::Layout(const NGConstraintSpace* constraint_space,
if (!current_child_->Layout(constraint_space_for_children_, &fragment)) if (!current_child_->Layout(constraint_space_for_children_, &fragment))
return false; return false;
NGBoxStrut child_margins = computeMargins( NGBoxStrut child_margins = computeMargins(
*constraint_space_for_children_, *current_child_->Style()); *constraint_space_for_children_, *current_child_->Style(),
constraint_space_for_children_->WritingMode(),
constraint_space_for_children_->Direction());
LayoutUnit margin_block_start = CollapseMargins( LayoutUnit margin_block_start = CollapseMargins(
*constraint_space, child_margins, fragment->MarginStrut()); *constraint_space, child_margins, fragment->MarginStrut());
......
...@@ -35,8 +35,9 @@ TEST_F(NGBlockLayoutAlgorithmTest, FixedSize) { ...@@ -35,8 +35,9 @@ TEST_F(NGBlockLayoutAlgorithmTest, FixedSize) {
style_->setWidth(Length(30, Fixed)); style_->setWidth(Length(30, Fixed));
style_->setHeight(Length(40, Fixed)); style_->setHeight(Length(40, Fixed));
auto* space = new NGConstraintSpace( auto* space =
HorizontalTopBottom, NGLogicalSize(LayoutUnit(100), NGSizeIndefinite)); new NGConstraintSpace(HorizontalTopBottom, LeftToRight,
NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, nullptr); NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, nullptr);
EXPECT_EQ(frag->Width(), LayoutUnit(30)); EXPECT_EQ(frag->Width(), LayoutUnit(30));
...@@ -64,8 +65,9 @@ TEST_F(NGBlockLayoutAlgorithmTest, LayoutBlockChildren) { ...@@ -64,8 +65,9 @@ TEST_F(NGBlockLayoutAlgorithmTest, LayoutBlockChildren) {
first_child->SetNextSibling(second_child); first_child->SetNextSibling(second_child);
auto* space = new NGConstraintSpace( auto* space =
HorizontalTopBottom, NGLogicalSize(LayoutUnit(100), NGSizeIndefinite)); new NGConstraintSpace(HorizontalTopBottom, LeftToRight,
NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, first_child); NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, first_child);
EXPECT_EQ(frag->Width(), LayoutUnit(kWidth)); EXPECT_EQ(frag->Width(), LayoutUnit(kWidth));
...@@ -82,6 +84,47 @@ TEST_F(NGBlockLayoutAlgorithmTest, LayoutBlockChildren) { ...@@ -82,6 +84,47 @@ TEST_F(NGBlockLayoutAlgorithmTest, LayoutBlockChildren) {
EXPECT_EQ(child->TopOffset(), kHeight1 + kMarginTop); EXPECT_EQ(child->TopOffset(), kHeight1 + kMarginTop);
} }
// Verifies that a child is laid out correctly if it's writing mode is different
// from the parent's one.
//
// Test case's HTML representation:
// <div style="writing-mode: vertical-lr;">
// <div style="width:50px;
// height: 50px; margin-left: 100px;
// writing-mode: horizontal-tb;"></div>
// </div>
TEST_F(NGBlockLayoutAlgorithmTest, LayoutBlockChildrenWithWritingMode) {
const int kWidth = 50;
const int kHeight = 50;
const int kMarginLeft = 100;
RefPtr<ComputedStyle> div1_style = ComputedStyle::create();
div1_style->setWritingMode(LeftToRightWritingMode);
NGBox* div1 = new NGBox(div1_style.get());
RefPtr<ComputedStyle> div2_style = ComputedStyle::create();
div2_style->setHeight(Length(kHeight, Fixed));
div2_style->setWidth(Length(kWidth, Fixed));
div1_style->setWritingMode(TopToBottomWritingMode);
div2_style->setMarginLeft(Length(kMarginLeft, Fixed));
NGBox* div2 = new NGBox(div2_style.get());
div1->SetFirstChild(div2);
auto* space =
new NGConstraintSpace(HorizontalTopBottom, LeftToRight,
NGLogicalSize(LayoutUnit(500), LayoutUnit(500)));
NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, div1);
const NGPhysicalFragmentBase* child = frag->Children()[0];
// DIV2
child = static_cast<const NGPhysicalFragment*>(child)->Children()[0];
EXPECT_EQ(kHeight, child->Height());
EXPECT_EQ(0, child->TopOffset());
EXPECT_EQ(kMarginLeft, child->LeftOffset());
}
// Verifies the collapsing margins case for the next pair: // Verifies the collapsing margins case for the next pair:
// - top margin of a box and top margin of its first in-flow child. // - top margin of a box and top margin of its first in-flow child.
// //
...@@ -110,8 +153,9 @@ TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase1) { ...@@ -110,8 +153,9 @@ TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase1) {
div1->SetFirstChild(div2); div1->SetFirstChild(div2);
auto* space = new NGConstraintSpace( auto* space =
HorizontalTopBottom, NGLogicalSize(LayoutUnit(100), NGSizeIndefinite)); new NGConstraintSpace(HorizontalTopBottom, LeftToRight,
NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, div1); NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, div1);
EXPECT_EQ(frag->MarginStrut(), NGMarginStrut({LayoutUnit(kDiv1MarginTop)})); EXPECT_EQ(frag->MarginStrut(), NGMarginStrut({LayoutUnit(kDiv1MarginTop)}));
...@@ -170,8 +214,9 @@ TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase2) { ...@@ -170,8 +214,9 @@ TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase2) {
div3->SetFirstChild(div4); div3->SetFirstChild(div4);
div1->SetNextSibling(div3); div1->SetNextSibling(div3);
auto* space = new NGConstraintSpace( auto* space =
HorizontalTopBottom, NGLogicalSize(LayoutUnit(100), NGSizeIndefinite)); new NGConstraintSpace(HorizontalTopBottom, LeftToRight,
NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, div1); NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, div1);
ASSERT_EQ(frag->Children().size(), 2UL); ASSERT_EQ(frag->Children().size(), 2UL);
...@@ -216,8 +261,9 @@ TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase3) { ...@@ -216,8 +261,9 @@ TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase3) {
div1->SetFirstChild(div2); div1->SetFirstChild(div2);
auto* space = new NGConstraintSpace( auto* space =
HorizontalTopBottom, NGLogicalSize(LayoutUnit(100), NGSizeIndefinite)); new NGConstraintSpace(HorizontalTopBottom, LeftToRight,
NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, div1); NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, div1);
// Verify that margins are collapsed. // Verify that margins are collapsed.
...@@ -264,8 +310,9 @@ TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase4) { ...@@ -264,8 +310,9 @@ TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase4) {
div1->SetFirstChild(div2); div1->SetFirstChild(div2);
auto* space = new NGConstraintSpace( auto* space =
HorizontalTopBottom, NGLogicalSize(LayoutUnit(100), NGSizeIndefinite)); new NGConstraintSpace(HorizontalTopBottom, LeftToRight,
NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, div1); NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, div1);
// Verify that margins do NOT collapse. // Verify that margins do NOT collapse.
...@@ -332,8 +379,9 @@ TEST_F(NGBlockLayoutAlgorithmTest, BorderAndPadding) { ...@@ -332,8 +379,9 @@ TEST_F(NGBlockLayoutAlgorithmTest, BorderAndPadding) {
div1->SetFirstChild(div2); div1->SetFirstChild(div2);
auto* space = new NGConstraintSpace( auto* space =
HorizontalTopBottom, NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite)); new NGConstraintSpace(HorizontalTopBottom, LeftToRight,
NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite));
NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, div1); NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, div1);
ASSERT_EQ(frag->Children().size(), 1UL); ASSERT_EQ(frag->Children().size(), 1UL);
......
...@@ -34,7 +34,8 @@ bool NGBox::Layout(const NGConstraintSpace* constraint_space, ...@@ -34,7 +34,8 @@ bool NGBox::Layout(const NGConstraintSpace* constraint_space,
algorithm_ = new NGBlockLayoutAlgorithm(Style(), FirstChild()); algorithm_ = new NGBlockLayoutAlgorithm(Style(), FirstChild());
// Change the coordinate system of the constraint space. // Change the coordinate system of the constraint space.
NGConstraintSpace* child_constraint_space = new NGConstraintSpace( NGConstraintSpace* child_constraint_space = new NGConstraintSpace(
FromPlatformWritingMode(Style()->getWritingMode()), constraint_space); FromPlatformWritingMode(Style()->getWritingMode()),
FromPlatformDirection(Style()->direction()), constraint_space);
NGPhysicalFragment* fragment = nullptr; NGPhysicalFragment* fragment = nullptr;
if (!algorithm_->Layout(child_constraint_space, &fragment)) if (!algorithm_->Layout(child_constraint_space, &fragment))
...@@ -83,10 +84,14 @@ bool NGBox::Layout(const NGConstraintSpace* constraint_space, ...@@ -83,10 +84,14 @@ bool NGBox::Layout(const NGConstraintSpace* constraint_space,
} }
LayoutRect overflow = layout_box_->layoutOverflowRect(); LayoutRect overflow = layout_box_->layoutOverflowRect();
// TODO(layout-ng): This does not handle writing modes correctly (for // TODO(layout-ng): This does not handle writing modes correctly (for
// overflow & the enums) // overflow)
NGFragmentBuilder builder(NGPhysicalFragmentBase::FragmentBox); NGFragmentBuilder builder(NGPhysicalFragmentBase::FragmentBox);
builder.SetInlineSize(layout_box_->logicalWidth()) builder.SetInlineSize(layout_box_->logicalWidth())
.SetBlockSize(layout_box_->logicalHeight()) .SetBlockSize(layout_box_->logicalHeight())
.SetDirection(
FromPlatformDirection(layout_box_->styleRef().direction()))
.SetWritingMode(
FromPlatformWritingMode(layout_box_->styleRef().getWritingMode()))
.SetInlineOverflow(overflow.width()) .SetInlineOverflow(overflow.width())
.SetBlockOverflow(overflow.height()); .SetBlockOverflow(overflow.height());
fragment_ = builder.ToFragment(); fragment_ = builder.ToFragment();
......
...@@ -15,33 +15,41 @@ namespace blink { ...@@ -15,33 +15,41 @@ namespace blink {
// remove it requiring that a NGConstraintSpace is created from a // remove it requiring that a NGConstraintSpace is created from a
// NGPhysicalConstraintSpace. // NGPhysicalConstraintSpace.
NGConstraintSpace::NGConstraintSpace(NGWritingMode writing_mode, NGConstraintSpace::NGConstraintSpace(NGWritingMode writing_mode,
NGDirection direction,
NGLogicalSize container_size) NGLogicalSize container_size)
: physical_space_(new NGPhysicalConstraintSpace( : physical_space_(new NGPhysicalConstraintSpace(
container_size.ConvertToPhysical(writing_mode))), container_size.ConvertToPhysical(writing_mode))),
size_(container_size), size_(container_size),
writing_mode_(writing_mode) {} writing_mode_(writing_mode),
direction_(direction) {}
NGConstraintSpace::NGConstraintSpace(NGWritingMode writing_mode, NGConstraintSpace::NGConstraintSpace(NGWritingMode writing_mode,
NGDirection direction,
NGPhysicalConstraintSpace* physical_space) NGPhysicalConstraintSpace* physical_space)
: physical_space_(physical_space), : physical_space_(physical_space),
size_(physical_space->ContainerSize().ConvertToLogical(writing_mode)), size_(physical_space->ContainerSize().ConvertToLogical(writing_mode)),
writing_mode_(writing_mode) {} writing_mode_(writing_mode),
direction_(direction) {}
NGConstraintSpace::NGConstraintSpace(NGWritingMode writing_mode, NGConstraintSpace::NGConstraintSpace(NGWritingMode writing_mode,
NGDirection direction,
const NGConstraintSpace* constraint_space) const NGConstraintSpace* constraint_space)
: physical_space_(constraint_space->PhysicalSpace()), : physical_space_(constraint_space->PhysicalSpace()),
offset_(constraint_space->Offset()), offset_(constraint_space->Offset()),
size_(constraint_space->Size()), size_(constraint_space->Size()),
writing_mode_(writing_mode) {} writing_mode_(writing_mode),
direction_(direction) {}
NGConstraintSpace::NGConstraintSpace(NGWritingMode writing_mode, NGConstraintSpace::NGConstraintSpace(NGWritingMode writing_mode,
NGDirection direction,
const NGConstraintSpace& other, const NGConstraintSpace& other,
NGLogicalOffset offset, NGLogicalOffset offset,
NGLogicalSize size) NGLogicalSize size)
: physical_space_(other.PhysicalSpace()), : physical_space_(other.PhysicalSpace()),
offset_(offset), offset_(offset),
size_(size), size_(size),
writing_mode_(writing_mode) {} writing_mode_(writing_mode),
direction_(direction) {}
NGConstraintSpace::NGConstraintSpace(const NGConstraintSpace& other, NGConstraintSpace::NGConstraintSpace(const NGConstraintSpace& other,
NGLogicalOffset offset, NGLogicalOffset offset,
...@@ -49,7 +57,8 @@ NGConstraintSpace::NGConstraintSpace(const NGConstraintSpace& other, ...@@ -49,7 +57,8 @@ NGConstraintSpace::NGConstraintSpace(const NGConstraintSpace& other,
: physical_space_(other.PhysicalSpace()), : physical_space_(other.PhysicalSpace()),
offset_(offset), offset_(offset),
size_(size), size_(size),
writing_mode_(other.WritingMode()) {} writing_mode_(other.WritingMode()),
direction_(other.Direction()) {}
NGConstraintSpace* NGConstraintSpace::CreateFromLayoutObject( NGConstraintSpace* NGConstraintSpace::CreateFromLayoutObject(
const LayoutBox& box) { const LayoutBox& box) {
...@@ -75,6 +84,7 @@ NGConstraintSpace* NGConstraintSpace::CreateFromLayoutObject( ...@@ -75,6 +84,7 @@ NGConstraintSpace* NGConstraintSpace::CreateFromLayoutObject(
NGConstraintSpace* derived_constraint_space = new NGConstraintSpace( NGConstraintSpace* derived_constraint_space = new NGConstraintSpace(
FromPlatformWritingMode(box.styleRef().getWritingMode()), FromPlatformWritingMode(box.styleRef().getWritingMode()),
FromPlatformDirection(box.styleRef().direction()),
NGLogicalSize(container_logical_width, container_logical_height)); NGLogicalSize(container_logical_width, container_logical_height));
derived_constraint_space->SetOverflowTriggersScrollbar( derived_constraint_space->SetOverflowTriggersScrollbar(
box.styleRef().overflowInlineDirection() == OverflowAuto, box.styleRef().overflowInlineDirection() == OverflowAuto,
......
...@@ -26,24 +26,26 @@ class CORE_EXPORT NGConstraintSpace final ...@@ -26,24 +26,26 @@ class CORE_EXPORT NGConstraintSpace final
: public GarbageCollected<NGConstraintSpace> { : public GarbageCollected<NGConstraintSpace> {
public: public:
// Constructs a constraint space with a new backing NGPhysicalConstraintSpace. // Constructs a constraint space with a new backing NGPhysicalConstraintSpace.
NGConstraintSpace(NGWritingMode, NGLogicalSize); NGConstraintSpace(NGWritingMode, NGDirection, NGLogicalSize);
// Constructs a constraint space based on an existing backing // Constructs a constraint space based on an existing backing
// NGPhysicalConstraintSpace. // NGPhysicalConstraintSpace.
NGConstraintSpace(NGWritingMode, NGPhysicalConstraintSpace*); NGConstraintSpace(NGWritingMode, NGDirection, NGPhysicalConstraintSpace*);
// Constructs a constraint space with a different NGWritingMode. // Constructs a constraint space with a different NGWritingMode and
NGConstraintSpace(NGWritingMode, const NGConstraintSpace*); // NGDirection.
NGConstraintSpace(NGWritingMode, NGDirection, const NGConstraintSpace*);
// Constructs a derived constraint space sharing the same backing // Constructs a derived constraint space sharing the same backing
// NGPhysicalConstraintSpace and NGWritingMode. // NGPhysicalConstraintSpace, NGWritingMode and NGDirection.
NGConstraintSpace(const NGConstraintSpace& other, NGConstraintSpace(const NGConstraintSpace& other,
NGLogicalOffset, NGLogicalOffset,
NGLogicalSize); NGLogicalSize);
// Constructs a derived constraint space sharing the same backing // Constructs a derived constraint space sharing the same backing
// NGPhysicalConstraintSpace and a different NGWritingMode. // NGPhysicalConstraintSpace, a different NGWritingMode and NGDirection.
NGConstraintSpace(NGWritingMode, NGConstraintSpace(NGWritingMode,
NGDirection,
const NGConstraintSpace& other, const NGConstraintSpace& other,
NGLogicalOffset, NGLogicalOffset,
NGLogicalSize); NGLogicalSize);
...@@ -54,6 +56,8 @@ class CORE_EXPORT NGConstraintSpace final ...@@ -54,6 +56,8 @@ class CORE_EXPORT NGConstraintSpace final
NGPhysicalConstraintSpace* PhysicalSpace() const { return physical_space_; } NGPhysicalConstraintSpace* PhysicalSpace() const { return physical_space_; }
NGDirection Direction() const { return static_cast<NGDirection>(direction_); }
NGWritingMode WritingMode() const { NGWritingMode WritingMode() const {
return static_cast<NGWritingMode>(writing_mode_); return static_cast<NGWritingMode>(writing_mode_);
} }
...@@ -116,6 +120,7 @@ class CORE_EXPORT NGConstraintSpace final ...@@ -116,6 +120,7 @@ class CORE_EXPORT NGConstraintSpace final
NGLogicalOffset offset_; NGLogicalOffset offset_;
NGLogicalSize size_; NGLogicalSize size_;
unsigned writing_mode_ : 3; unsigned writing_mode_ : 3;
unsigned direction_ : 1;
}; };
inline std::ostream& operator<<(std::ostream& stream, inline std::ostream& operator<<(std::ostream& stream,
......
...@@ -12,14 +12,15 @@ namespace blink { ...@@ -12,14 +12,15 @@ namespace blink {
namespace { namespace {
TEST(NGConstraintSpaceTest, WritingMode) { TEST(NGConstraintSpaceTest, WritingMode) {
NGConstraintSpace* horz_space = new NGConstraintSpace( NGConstraintSpace* horz_space =
HorizontalTopBottom, NGLogicalSize(LayoutUnit(200), LayoutUnit(100))); new NGConstraintSpace(HorizontalTopBottom, LeftToRight,
NGLogicalSize(LayoutUnit(200), LayoutUnit(100)));
horz_space->SetOverflowTriggersScrollbar(true, false); horz_space->SetOverflowTriggersScrollbar(true, false);
horz_space->SetFixedSize(true, false); horz_space->SetFixedSize(true, false);
horz_space->SetFragmentationType(FragmentColumn); horz_space->SetFragmentationType(FragmentColumn);
NGConstraintSpace* vert_space = NGConstraintSpace* vert_space =
new NGConstraintSpace(VerticalRightLeft, horz_space); new NGConstraintSpace(VerticalRightLeft, LeftToRight, horz_space);
EXPECT_EQ(LayoutUnit(200), horz_space->ContainerSize().inline_size); EXPECT_EQ(LayoutUnit(200), horz_space->ContainerSize().inline_size);
EXPECT_EQ(LayoutUnit(200), vert_space->ContainerSize().block_size); EXPECT_EQ(LayoutUnit(200), vert_space->ContainerSize().block_size);
...@@ -48,7 +49,8 @@ TEST(NGConstraintSpaceTest, LayoutOpportunitiesNoExclusions) { ...@@ -48,7 +49,8 @@ TEST(NGConstraintSpaceTest, LayoutOpportunitiesNoExclusions) {
physical_size.width = LayoutUnit(600); physical_size.width = LayoutUnit(600);
physical_size.height = LayoutUnit(400); physical_size.height = LayoutUnit(400);
auto* physical_space = new NGPhysicalConstraintSpace(physical_size); auto* physical_space = new NGPhysicalConstraintSpace(physical_size);
auto* space = new NGConstraintSpace(HorizontalTopBottom, physical_space); auto* space =
new NGConstraintSpace(HorizontalTopBottom, LeftToRight, physical_space);
bool for_inline_or_bfc = true; bool for_inline_or_bfc = true;
auto* iterator = space->LayoutOpportunities(NGClearNone, for_inline_or_bfc); auto* iterator = space->LayoutOpportunities(NGClearNone, for_inline_or_bfc);
...@@ -72,7 +74,8 @@ TEST(NGConstraintSpaceTest, LayoutOpportunitiesOneExclusion) { ...@@ -72,7 +74,8 @@ TEST(NGConstraintSpaceTest, LayoutOpportunitiesOneExclusion) {
physical_space->AddExclusion(NGExclusion(LayoutUnit(0), LayoutUnit(600), physical_space->AddExclusion(NGExclusion(LayoutUnit(0), LayoutUnit(600),
LayoutUnit(100), LayoutUnit(500))); LayoutUnit(100), LayoutUnit(500)));
auto* space = new NGConstraintSpace(HorizontalTopBottom, physical_space); auto* space =
new NGConstraintSpace(HorizontalTopBottom, LeftToRight, physical_space);
bool for_inline_or_bfc = true; bool for_inline_or_bfc = true;
auto* iterator = space->LayoutOpportunities(NGClearNone, for_inline_or_bfc); auto* iterator = space->LayoutOpportunities(NGClearNone, for_inline_or_bfc);
......
...@@ -70,6 +70,7 @@ NGConstraintSpace* NGLayoutOpportunityIterator::Next() { ...@@ -70,6 +70,7 @@ NGConstraintSpace* NGLayoutOpportunityIterator::Next() {
if (filtered_exclusions_.isEmpty() && current_exclusion_idx_ == 0) { if (filtered_exclusions_.isEmpty() && current_exclusion_idx_ == 0) {
current_exclusion_idx_++; current_exclusion_idx_++;
return new NGConstraintSpace(constraint_space_->WritingMode(), return new NGConstraintSpace(constraint_space_->WritingMode(),
constraint_space_->Direction(),
constraint_space_->PhysicalSpace()); constraint_space_->PhysicalSpace());
} }
......
...@@ -14,6 +14,47 @@ namespace blink { ...@@ -14,6 +14,47 @@ namespace blink {
// - positioned and/or replaced calculations // - positioned and/or replaced calculations
// - Take scrollbars into account // - Take scrollbars into account
namespace {
// Converts physical dimensions to logical ones per
// https://drafts.csswg.org/css-writing-modes-3/#logical-to-physical
// For now it's only used to calculate abstract values for margins.
NGBoxStrut ToLogicalDimensions(const NGPhysicalDimensions& physical_dim,
const NGWritingMode writing_mode,
const NGDirection direction) {
bool is_ltr = direction == LeftToRight;
NGBoxStrut logical_dim;
switch (writing_mode) {
case VerticalRightLeft:
case SidewaysRightLeft:
logical_dim = {is_ltr ? physical_dim.top : physical_dim.bottom,
is_ltr ? physical_dim.bottom : physical_dim.top,
physical_dim.right, physical_dim.left};
break;
case VerticalLeftRight:
logical_dim = {is_ltr ? physical_dim.top : physical_dim.bottom,
is_ltr ? physical_dim.bottom : physical_dim.top,
physical_dim.left, physical_dim.right};
break;
case SidewaysLeftRight:
logical_dim = {is_ltr ? physical_dim.bottom : physical_dim.top,
is_ltr ? physical_dim.top : physical_dim.bottom,
physical_dim.left, physical_dim.right};
break;
default:
NOTREACHED();
/* FALLTHROUGH */
case HorizontalTopBottom:
logical_dim = {is_ltr ? physical_dim.left : physical_dim.right,
is_ltr ? physical_dim.right : physical_dim.left,
physical_dim.top, physical_dim.bottom};
break;
}
return logical_dim;
}
} // namespace
LayoutUnit resolveInlineLength(const NGConstraintSpace& constraintSpace, LayoutUnit resolveInlineLength(const NGConstraintSpace& constraintSpace,
const ComputedStyle& style, const ComputedStyle& style,
const Length& length, const Length& length,
...@@ -32,7 +73,10 @@ LayoutUnit resolveInlineLength(const NGConstraintSpace& constraintSpace, ...@@ -32,7 +73,10 @@ LayoutUnit resolveInlineLength(const NGConstraintSpace& constraintSpace,
switch (length.type()) { switch (length.type()) {
case Auto: case Auto:
case FillAvailable: { case FillAvailable: {
NGBoxStrut margins = computeMargins(constraintSpace, style); NGBoxStrut margins =
computeMargins(constraintSpace, style,
FromPlatformWritingMode(style.getWritingMode()),
FromPlatformDirection(style.direction()));
return container_size - margins.InlineSum(); return container_size - margins.InlineSum();
} }
case Percent: case Percent:
...@@ -88,7 +132,10 @@ LayoutUnit resolveBlockLength(const NGConstraintSpace& constraintSpace, ...@@ -88,7 +132,10 @@ LayoutUnit resolveBlockLength(const NGConstraintSpace& constraintSpace,
LayoutUnit container_size = constraintSpace.ContainerSize().block_size; LayoutUnit container_size = constraintSpace.ContainerSize().block_size;
switch (length.type()) { switch (length.type()) {
case FillAvailable: { case FillAvailable: {
NGBoxStrut margins = computeMargins(constraintSpace, style); NGBoxStrut margins =
computeMargins(constraintSpace, style,
FromPlatformWritingMode(style.getWritingMode()),
FromPlatformDirection(style.direction()));
return container_size - margins.BlockSum(); return container_size - margins.BlockSum();
} }
case Percent: case Percent:
...@@ -178,23 +225,25 @@ LayoutUnit computeBlockSizeForFragment(const NGConstraintSpace& constraintSpace, ...@@ -178,23 +225,25 @@ LayoutUnit computeBlockSizeForFragment(const NGConstraintSpace& constraintSpace,
} }
NGBoxStrut computeMargins(const NGConstraintSpace& constraintSpace, NGBoxStrut computeMargins(const NGConstraintSpace& constraintSpace,
const ComputedStyle& style) { const ComputedStyle& style,
const NGWritingMode writing_mode,
const NGDirection direction) {
// Margins always get computed relative to the inline size: // Margins always get computed relative to the inline size:
// https://www.w3.org/TR/CSS2/box.html#value-def-margin-width // https://www.w3.org/TR/CSS2/box.html#value-def-margin-width
NGBoxStrut margins; NGPhysicalDimensions physical_dim;
margins.inline_start = physical_dim.left =
resolveInlineLength(constraintSpace, style, style.marginStart(), resolveInlineLength(constraintSpace, style, style.marginLeft(),
LengthResolveType::MarginBorderPaddingSize); LengthResolveType::MarginBorderPaddingSize);
margins.inline_end = physical_dim.right =
resolveInlineLength(constraintSpace, style, style.marginEnd(), resolveInlineLength(constraintSpace, style, style.marginRight(),
LengthResolveType::MarginBorderPaddingSize); LengthResolveType::MarginBorderPaddingSize);
margins.block_start = physical_dim.top =
resolveInlineLength(constraintSpace, style, style.marginBefore(), resolveInlineLength(constraintSpace, style, style.marginTop(),
LengthResolveType::MarginBorderPaddingSize); LengthResolveType::MarginBorderPaddingSize);
margins.block_end = physical_dim.bottom =
resolveInlineLength(constraintSpace, style, style.marginAfter(), resolveInlineLength(constraintSpace, style, style.marginBottom(),
LengthResolveType::MarginBorderPaddingSize); LengthResolveType::MarginBorderPaddingSize);
return margins; return ToLogicalDimensions(physical_dim, writing_mode, direction);
} }
NGBoxStrut computeBorders(const ComputedStyle& style) { NGBoxStrut computeBorders(const ComputedStyle& style) {
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#define NGLengthUtils_h #define NGLengthUtils_h
#include "core/CoreExport.h" #include "core/CoreExport.h"
#include "core/layout/ng/ng_direction.h"
#include "core/layout/ng/ng_writing_mode.h"
namespace blink { namespace blink {
class ComputedStyle; class ComputedStyle;
...@@ -52,7 +54,9 @@ CORE_EXPORT LayoutUnit computeBlockSizeForFragment(const NGConstraintSpace&, ...@@ -52,7 +54,9 @@ CORE_EXPORT LayoutUnit computeBlockSizeForFragment(const NGConstraintSpace&,
LayoutUnit contentSize); LayoutUnit contentSize);
CORE_EXPORT NGBoxStrut computeMargins(const NGConstraintSpace&, CORE_EXPORT NGBoxStrut computeMargins(const NGConstraintSpace&,
const ComputedStyle&); const ComputedStyle&,
const NGWritingMode writing_mode,
const NGDirection direction);
CORE_EXPORT NGBoxStrut computeBorders(const ComputedStyle&); CORE_EXPORT NGBoxStrut computeBorders(const ComputedStyle&);
......
...@@ -25,7 +25,7 @@ class NGLengthUtilsTest : public ::testing::Test { ...@@ -25,7 +25,7 @@ class NGLengthUtilsTest : public ::testing::Test {
bool fixed_inline = false, bool fixed_inline = false,
bool fixed_block = false) { bool fixed_block = false) {
NGConstraintSpace* derived_constraint_space = new NGConstraintSpace( NGConstraintSpace* derived_constraint_space = new NGConstraintSpace(
HorizontalTopBottom, HorizontalTopBottom, LeftToRight,
NGLogicalSize(LayoutUnit(inline_size), LayoutUnit(block_size))); NGLogicalSize(LayoutUnit(inline_size), LayoutUnit(block_size)));
derived_constraint_space->SetOverflowTriggersScrollbar(false, false); derived_constraint_space->SetOverflowTriggersScrollbar(false, false);
derived_constraint_space->SetFixedSize(fixed_inline, fixed_block); derived_constraint_space->SetFixedSize(fixed_inline, fixed_block);
...@@ -210,7 +210,8 @@ TEST_F(NGLengthUtilsTest, testMargins) { ...@@ -210,7 +210,8 @@ TEST_F(NGLengthUtilsTest, testMargins) {
NGConstraintSpace* constraintSpace(ConstructConstraintSpace(200, 300)); NGConstraintSpace* constraintSpace(ConstructConstraintSpace(200, 300));
NGBoxStrut margins = computeMargins(*constraintSpace, *style_); NGBoxStrut margins = computeMargins(*constraintSpace, *style_,
HorizontalTopBottom, LeftToRight);
EXPECT_EQ(LayoutUnit(20), margins.block_start); EXPECT_EQ(LayoutUnit(20), margins.block_start);
EXPECT_EQ(LayoutUnit(52), margins.inline_end); EXPECT_EQ(LayoutUnit(52), margins.inline_end);
......
...@@ -89,6 +89,16 @@ struct NGPixelSnappedPhysicalRect { ...@@ -89,6 +89,16 @@ struct NGPixelSnappedPhysicalRect {
int height; int height;
}; };
// Struct to store physical dimensions, independent of writing mode and
// direction.
// See https://drafts.csswg.org/css-writing-modes-3/#abstract-box
struct NGPhysicalDimensions {
LayoutUnit left;
LayoutUnit right;
LayoutUnit top;
LayoutUnit bottom;
};
// This struct is used for storing margins, borders or padding of a box on all // This struct is used for storing margins, borders or padding of a box on all
// four edges. // four edges.
struct NGBoxStrut { struct NGBoxStrut {
......
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