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

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

Powered by Google App Engine
This is Rietveld 408576698