Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(37)

Side by Side Diff: third_party/WebKit/Source/core/layout/ng/ng_block_layout_algorithm_test.cc

Issue 2336353002: Collapse bottom margins of a last child and its parent if parent's height=auto (Closed)
Patch Set: add CORE_EXPORT Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/layout/ng/ng_block_layout_algorithm.h" 5 #include "core/layout/ng/ng_block_layout_algorithm.h"
6 6
7 #include "core/layout/ng/ng_box.h" 7 #include "core/layout/ng/ng_box.h"
8 #include "core/layout/ng/ng_constraint_space.h" 8 #include "core/layout/ng/ng_constraint_space.h"
9 #include "core/layout/ng/ng_physical_fragment.h" 9 #include "core/layout/ng/ng_physical_fragment.h"
10 #include "core/layout/ng/ng_length_utils.h" 10 #include "core/layout/ng/ng_length_utils.h"
11 #include "core/layout/ng/ng_units.h"
11 #include "core/style/ComputedStyle.h" 12 #include "core/style/ComputedStyle.h"
12 #include "testing/gtest/include/gtest/gtest.h" 13 #include "testing/gtest/include/gtest/gtest.h"
13 14
14 namespace blink { 15 namespace blink {
15 namespace { 16 namespace {
16 17
17 class NGBlockLayoutAlgorithmTest : public ::testing::Test { 18 class NGBlockLayoutAlgorithmTest : public ::testing::Test {
18 protected: 19 protected:
19 void SetUp() override { style_ = ComputedStyle::create(); } 20 void SetUp() override { style_ = ComputedStyle::create(); }
20 21
22 NGPhysicalFragment* RunBlockLayoutAlgorithm(const NGConstraintSpace* space,
23 NGBox* first_child) {
24 NGBlockLayoutAlgorithm algorithm(style_, first_child);
25 NGPhysicalFragment* frag;
26 while (!algorithm.Layout(space, &frag))
27 continue;
28 return frag;
29 }
30
21 RefPtr<ComputedStyle> style_; 31 RefPtr<ComputedStyle> style_;
22 }; 32 };
23 33
24 TEST_F(NGBlockLayoutAlgorithmTest, FixedSize) { 34 TEST_F(NGBlockLayoutAlgorithmTest, FixedSize) {
25 style_->setWidth(Length(30, Fixed)); 35 style_->setWidth(Length(30, Fixed));
26 style_->setHeight(Length(40, Fixed)); 36 style_->setHeight(Length(40, Fixed));
27 37
28 NGConstraintSpace* space = new NGConstraintSpace( 38 auto* space = new NGConstraintSpace(
29 HorizontalTopBottom, NGLogicalSize(LayoutUnit(100), NGSizeIndefinite)); 39 HorizontalTopBottom, NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
40 NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, nullptr);
30 41
31 NGBlockLayoutAlgorithm algorithm(style_, nullptr);
32 NGPhysicalFragment* frag;
33 while (!algorithm.Layout(space, &frag))
34 ;
35 EXPECT_EQ(frag->Width(), LayoutUnit(30)); 42 EXPECT_EQ(frag->Width(), LayoutUnit(30));
36 EXPECT_EQ(frag->Height(), LayoutUnit(40)); 43 EXPECT_EQ(frag->Height(), LayoutUnit(40));
37 } 44 }
38 45
39 // Verifies that two children are laid out with the correct size and position. 46 // Verifies that two children are laid out with the correct size and position.
40 TEST_F(NGBlockLayoutAlgorithmTest, LayoutBlockChildren) { 47 TEST_F(NGBlockLayoutAlgorithmTest, LayoutBlockChildren) {
41 const int kWidth = 30; 48 const int kWidth = 30;
42 const int kHeight1 = 20; 49 const int kHeight1 = 20;
43 const int kHeight2 = 30; 50 const int kHeight2 = 30;
44 const int kMarginTop = 5; 51 const int kMarginTop = 5;
45 const int kMarginBottom = 20; 52 const int kMarginBottom = 20;
46 style_->setWidth(Length(kWidth, Fixed)); 53 style_->setWidth(Length(kWidth, Fixed));
47 54
48 NGConstraintSpace* space = new NGConstraintSpace(
49 HorizontalTopBottom, NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
50
51 RefPtr<ComputedStyle> first_style = ComputedStyle::create(); 55 RefPtr<ComputedStyle> first_style = ComputedStyle::create();
52 first_style->setHeight(Length(kHeight1, Fixed)); 56 first_style->setHeight(Length(kHeight1, Fixed));
53 NGBox* first_child = new NGBox(first_style.get()); 57 NGBox* first_child = new NGBox(first_style.get());
54 58
55 RefPtr<ComputedStyle> second_style = ComputedStyle::create(); 59 RefPtr<ComputedStyle> second_style = ComputedStyle::create();
56 second_style->setHeight(Length(kHeight2, Fixed)); 60 second_style->setHeight(Length(kHeight2, Fixed));
57 second_style->setMarginTop(Length(kMarginTop, Fixed)); 61 second_style->setMarginTop(Length(kMarginTop, Fixed));
58 second_style->setMarginBottom(Length(kMarginBottom, Fixed)); 62 second_style->setMarginBottom(Length(kMarginBottom, Fixed));
59 NGBox* second_child = new NGBox(second_style.get()); 63 NGBox* second_child = new NGBox(second_style.get());
60 64
61 first_child->SetNextSibling(second_child); 65 first_child->SetNextSibling(second_child);
62 66
63 NGBlockLayoutAlgorithm algorithm(style_, first_child); 67 auto* space = new NGConstraintSpace(
64 NGPhysicalFragment* frag; 68 HorizontalTopBottom, NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
65 while (!algorithm.Layout(space, &frag)) 69 NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, first_child);
66 ; 70
67 EXPECT_EQ(frag->Width(), LayoutUnit(kWidth)); 71 EXPECT_EQ(frag->Width(), LayoutUnit(kWidth));
68 EXPECT_EQ(frag->Height(), LayoutUnit(kHeight1 + kHeight2 + kMarginTop)); 72 EXPECT_EQ(frag->Height(), LayoutUnit(kHeight1 + kHeight2 + kMarginTop));
69 EXPECT_EQ(frag->Type(), NGPhysicalFragmentBase::FragmentBox); 73 EXPECT_EQ(frag->Type(), NGPhysicalFragmentBase::FragmentBox);
70 ASSERT_EQ(frag->Children().size(), 2UL); 74 ASSERT_EQ(frag->Children().size(), 2UL);
71 75
72 const NGPhysicalFragmentBase* child = frag->Children()[0]; 76 const NGPhysicalFragmentBase* child = frag->Children()[0];
73 EXPECT_EQ(child->Height(), kHeight1); 77 EXPECT_EQ(child->Height(), kHeight1);
74 EXPECT_EQ(child->TopOffset(), 0); 78 EXPECT_EQ(child->TopOffset(), 0);
75 79
76 child = frag->Children()[1]; 80 child = frag->Children()[1];
(...skipping 22 matching lines...) Expand all
99 div1_style->setMarginTop(Length(kDiv1MarginTop, Fixed)); 103 div1_style->setMarginTop(Length(kDiv1MarginTop, Fixed));
100 NGBox* div1 = new NGBox(div1_style.get()); 104 NGBox* div1 = new NGBox(div1_style.get());
101 105
102 // DIV2 106 // DIV2
103 RefPtr<ComputedStyle> div2_style = ComputedStyle::create(); 107 RefPtr<ComputedStyle> div2_style = ComputedStyle::create();
104 div2_style->setMarginTop(Length(kDiv2MarginTop, Fixed)); 108 div2_style->setMarginTop(Length(kDiv2MarginTop, Fixed));
105 NGBox* div2 = new NGBox(div2_style.get()); 109 NGBox* div2 = new NGBox(div2_style.get());
106 110
107 div1->SetFirstChild(div2); 111 div1->SetFirstChild(div2);
108 112
109 NGConstraintSpace* space = new NGConstraintSpace( 113 auto* space = new NGConstraintSpace(
110 HorizontalTopBottom, NGLogicalSize(LayoutUnit(100), NGSizeIndefinite)); 114 HorizontalTopBottom, NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
111 NGBlockLayoutAlgorithm algorithm(style_, div1); 115 NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, div1);
112 NGPhysicalFragment* frag;
113 while (!algorithm.Layout(space, &frag))
114 ;
115 116
116 EXPECT_EQ(frag->MarginStrut().margin_block_start, kDiv1MarginTop); 117 EXPECT_EQ(frag->MarginStrut(), NGMarginStrut({LayoutUnit(kDiv1MarginTop)}));
117 ASSERT_EQ(frag->Children().size(), 1UL); 118 ASSERT_EQ(frag->Children().size(), 1UL);
118 const NGPhysicalFragmentBase* div2_fragment = frag->Children()[0]; 119 const NGPhysicalFragmentBase* div2_fragment = frag->Children()[0];
119 EXPECT_EQ(div2_fragment->MarginStrut().margin_block_start, kDiv2MarginTop); 120 EXPECT_EQ(div2_fragment->MarginStrut(),
121 NGMarginStrut({LayoutUnit(kDiv2MarginTop)}));
120 } 122 }
121 123
122 // Verifies the collapsing margins case for the next pair: 124 // Verifies the collapsing margins case for the next pair:
123 // - bottom margin of box and top margin of its next in-flow following sibling. 125 // - bottom margin of box and top margin of its next in-flow following sibling.
124 // 126 //
125 // Test case's HTML representation: 127 // Test case's HTML representation:
126 // <div style="margin-bottom: 20px; height: 50px;"> <!-- DIV1 --> 128 // <div style="margin-bottom: 20px; height: 50px;"> <!-- DIV1 -->
127 // <div style="margin-bottom: -15px"></div> <!-- DIV2 --> 129 // <div style="margin-bottom: -15px"></div> <!-- DIV2 -->
128 // </div> 130 // </div>
129 // <div style="margin-top: 10px; height: 50px;"> <!-- DIV3 --> 131 // <div style="margin-top: 10px; height: 50px;"> <!-- DIV3 -->
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 163
162 // DIV4 164 // DIV4
163 RefPtr<ComputedStyle> div4_style = ComputedStyle::create(); 165 RefPtr<ComputedStyle> div4_style = ComputedStyle::create();
164 div4_style->setMarginTop(Length(kDiv4MarginTop, Fixed)); 166 div4_style->setMarginTop(Length(kDiv4MarginTop, Fixed));
165 NGBox* div4 = new NGBox(div4_style.get()); 167 NGBox* div4 = new NGBox(div4_style.get());
166 168
167 div1->SetFirstChild(div2); 169 div1->SetFirstChild(div2);
168 div3->SetFirstChild(div4); 170 div3->SetFirstChild(div4);
169 div1->SetNextSibling(div3); 171 div1->SetNextSibling(div3);
170 172
171 NGConstraintSpace* space = new NGConstraintSpace( 173 auto* space = new NGConstraintSpace(
172 HorizontalTopBottom, NGLogicalSize(LayoutUnit(100), NGSizeIndefinite)); 174 HorizontalTopBottom, NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
173 NGBlockLayoutAlgorithm algorithm(style_, div1); 175 NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, div1);
174 NGPhysicalFragment* frag;
175 while (!algorithm.Layout(space, &frag))
176 ;
177 176
178 ASSERT_EQ(frag->Children().size(), 2UL); 177 ASSERT_EQ(frag->Children().size(), 2UL);
179 178
180 const NGPhysicalFragmentBase* child = frag->Children()[0]; 179 const NGPhysicalFragmentBase* child = frag->Children()[0];
181 EXPECT_EQ(child->Height(), kHeight); 180 EXPECT_EQ(child->Height(), kHeight);
182 EXPECT_EQ(child->TopOffset(), 0); 181 EXPECT_EQ(child->TopOffset(), 0);
183 182
184 child = frag->Children()[1]; 183 child = frag->Children()[1];
185 EXPECT_EQ(child->Height(), kHeight); 184 EXPECT_EQ(child->Height(), kHeight);
186 EXPECT_EQ(child->TopOffset(), kHeight + kExpectedCollapsedMargin); 185 EXPECT_EQ(child->TopOffset(), kHeight + kExpectedCollapsedMargin);
187 } 186 }
188 187
188 // Verifies the collapsing margins case for the next pair:
189 // - bottom margin of a last in-flow child and bottom margin of its parent if
190 // the parent has 'auto' computed height
191 //
192 // Test case's HTML representation:
193 // <div style="margin-bottom: 20px; height: 50px;"> <!-- DIV1 -->
194 // <div style="margin-bottom: 200px; height: 50px;"/> <!-- DIV2 -->
195 // </div>
196 //
197 // Expected:
198 // 1) Margins are collapsed with the result = std::max(20, 200)
199 // if DIV1.height == auto
200 // 2) Margins are NOT collapsed if DIV1.height != auto
201 TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase3) {
202 const int kHeight = 50;
203 const int kDiv1MarginBottom = 20;
204 const int kDiv2MarginBottom = 200;
205
206 // DIV1
207 RefPtr<ComputedStyle> div1_style = ComputedStyle::create();
208 div1_style->setMarginBottom(Length(kDiv1MarginBottom, Fixed));
209 NGBox* div1 = new NGBox(div1_style.get());
210
211 // DIV2
212 RefPtr<ComputedStyle> div2_style = ComputedStyle::create();
213 div2_style->setHeight(Length(kHeight, Fixed));
214 div2_style->setMarginBottom(Length(kDiv2MarginBottom, Fixed));
215 NGBox* div2 = new NGBox(div2_style.get());
216
217 div1->SetFirstChild(div2);
218
219 auto* space = new NGConstraintSpace(
220 HorizontalTopBottom, NGLogicalSize(LayoutUnit(100), NGSizeIndefinite));
221 NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, div1);
222
223 // Verify that margins are collapsed.
224 EXPECT_EQ(frag->MarginStrut(),
225 NGMarginStrut({LayoutUnit(0), LayoutUnit(kDiv2MarginBottom)}));
226
227 // Verify that margins are NOT collapsed.
228 div1_style->setHeight(Length(kHeight, Fixed));
229 frag = RunBlockLayoutAlgorithm(space, div1);
230 EXPECT_EQ(frag->MarginStrut(),
231 NGMarginStrut({LayoutUnit(0), LayoutUnit(kDiv1MarginBottom)}));
232 }
233
189 // Verifies that a box's size includes its borders and padding, and that 234 // Verifies that a box's size includes its borders and padding, and that
190 // children are positioned inside the content box. 235 // children are positioned inside the content box.
191 // 236 //
192 // Test case's HTML representation: 237 // Test case's HTML representation:
193 // <style> 238 // <style>
194 // #div1 { width:100px; height:100px; } 239 // #div1 { width:100px; height:100px; }
195 // #div1 { border-style:solid; border-width:1px 2px 3px 4px; } 240 // #div1 { border-style:solid; border-width:1px 2px 3px 4px; }
196 // #div1 { padding:5px 6px 7px 8px; } 241 // #div1 { padding:5px 6px 7px 8px; }
197 // </style> 242 // </style>
198 // <div id="div1"> 243 // <div id="div1">
(...skipping 28 matching lines...) Expand all
227 div1_style->setPaddingRight(Length(kPaddingRight, Fixed)); 272 div1_style->setPaddingRight(Length(kPaddingRight, Fixed));
228 div1_style->setPaddingBottom(Length(kPaddingBottom, Fixed)); 273 div1_style->setPaddingBottom(Length(kPaddingBottom, Fixed));
229 div1_style->setPaddingLeft(Length(kPaddingLeft, Fixed)); 274 div1_style->setPaddingLeft(Length(kPaddingLeft, Fixed));
230 NGBox* div1 = new NGBox(div1_style.get()); 275 NGBox* div1 = new NGBox(div1_style.get());
231 276
232 RefPtr<ComputedStyle> div2_style = ComputedStyle::create(); 277 RefPtr<ComputedStyle> div2_style = ComputedStyle::create();
233 NGBox* div2 = new NGBox(div2_style.get()); 278 NGBox* div2 = new NGBox(div2_style.get());
234 279
235 div1->SetFirstChild(div2); 280 div1->SetFirstChild(div2);
236 281
237 NGConstraintSpace* space = new NGConstraintSpace( 282 auto* space = new NGConstraintSpace(
238 HorizontalTopBottom, NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite)); 283 HorizontalTopBottom, NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite));
239 NGBlockLayoutAlgorithm algorithm(style_, div1); 284 NGPhysicalFragment* frag = RunBlockLayoutAlgorithm(space, div1);
240 NGPhysicalFragment* frag;
241 while (!algorithm.Layout(space, &frag))
242 ;
243 285
244 ASSERT_EQ(frag->Children().size(), 1UL); 286 ASSERT_EQ(frag->Children().size(), 1UL);
245 287
246 // div1 288 // div1
247 const NGPhysicalFragmentBase* child = frag->Children()[0]; 289 const NGPhysicalFragmentBase* child = frag->Children()[0];
248 EXPECT_EQ(kBorderLeft + kPaddingLeft + kWidth + kPaddingRight + kBorderRight, 290 EXPECT_EQ(kBorderLeft + kPaddingLeft + kWidth + kPaddingRight + kBorderRight,
249 child->Width()); 291 child->Width());
250 EXPECT_EQ(kBorderTop + kPaddingTop + kHeight + kPaddingBottom + kBorderBottom, 292 EXPECT_EQ(kBorderTop + kPaddingTop + kHeight + kPaddingBottom + kBorderBottom,
251 child->Height()); 293 child->Height());
252 294
253 ASSERT_TRUE(child->Type() == NGPhysicalFragmentBase::FragmentBox); 295 ASSERT_TRUE(child->Type() == NGPhysicalFragmentBase::FragmentBox);
254 ASSERT_EQ(static_cast<const NGPhysicalFragment*>(child)->Children().size(), 296 ASSERT_EQ(static_cast<const NGPhysicalFragment*>(child)->Children().size(),
255 1UL); 297 1UL);
256 298
257 // div2 299 // div2
258 child = static_cast<const NGPhysicalFragment*>(child)->Children()[0]; 300 child = static_cast<const NGPhysicalFragment*>(child)->Children()[0];
259 EXPECT_EQ(kBorderTop + kPaddingTop, child->TopOffset()); 301 EXPECT_EQ(kBorderTop + kPaddingTop, child->TopOffset());
260 EXPECT_EQ(kBorderLeft + kPaddingLeft, child->LeftOffset()); 302 EXPECT_EQ(kBorderLeft + kPaddingLeft, child->LeftOffset());
261 } 303 }
262 } // namespace 304 } // namespace
263 } // namespace blink 305 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698