Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/dom/NodeComputedStyle.h" | |
| 8 #include "core/dom/TagCollection.h" | |
| 9 #include "core/layout/ng/layout_ng_block_flow.h" | |
| 7 #include "core/layout/ng/ng_block_node.h" | 10 #include "core/layout/ng/ng_block_node.h" |
| 8 #include "core/layout/ng/ng_constraint_space.h" | 11 #include "core/layout/ng/ng_constraint_space.h" |
| 9 #include "core/layout/ng/ng_constraint_space_builder.h" | 12 #include "core/layout/ng/ng_constraint_space_builder.h" |
| 13 #include "core/layout/ng/ng_floating_object.h" | |
| 10 #include "core/layout/ng/ng_length_utils.h" | 14 #include "core/layout/ng/ng_length_utils.h" |
| 15 #include "core/layout/LayoutTestHelper.h" | |
| 11 #include "core/layout/ng/ng_physical_box_fragment.h" | 16 #include "core/layout/ng/ng_physical_box_fragment.h" |
| 12 #include "core/layout/ng/ng_physical_fragment.h" | 17 #include "core/layout/ng/ng_physical_fragment.h" |
| 13 #include "core/layout/ng/ng_units.h" | 18 #include "core/layout/ng/ng_units.h" |
| 14 #include "core/layout/LayoutTestHelper.h" | 19 #include "testing/gmock/include/gmock/gmock.h" |
| 15 #include "core/style/ComputedStyle.h" | 20 #include "core/style/ComputedStyle.h" |
| 16 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
| 17 | 22 |
| 18 namespace blink { | 23 namespace blink { |
| 19 namespace { | 24 namespace { |
| 20 | 25 |
| 26 using testing::ElementsAre; | |
| 27 using testing::Pointee; | |
| 28 | |
| 21 NGConstraintSpace* ConstructConstraintSpace(NGWritingMode writing_mode, | 29 NGConstraintSpace* ConstructConstraintSpace(NGWritingMode writing_mode, |
| 22 TextDirection direction, | 30 TextDirection direction, |
| 23 NGLogicalSize size, | 31 NGLogicalSize size, |
| 24 bool shrink_to_fit = false) { | 32 bool shrink_to_fit = false) { |
| 25 return NGConstraintSpaceBuilder(writing_mode) | 33 return NGConstraintSpaceBuilder(writing_mode) |
| 26 .SetAvailableSize(size) | 34 .SetAvailableSize(size) |
| 27 .SetPercentageResolutionSize(size) | 35 .SetPercentageResolutionSize(size) |
| 28 .SetTextDirection(direction) | 36 .SetTextDirection(direction) |
| 29 .SetWritingMode(writing_mode) | 37 .SetWritingMode(writing_mode) |
| 30 .SetIsShrinkToFit(shrink_to_fit) | 38 .SetIsShrinkToFit(shrink_to_fit) |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 49 NGBlockNode* first_child) { | 57 NGBlockNode* first_child) { |
| 50 NGBlockNode parent(style_.get()); | 58 NGBlockNode parent(style_.get()); |
| 51 parent.SetFirstChild(first_child); | 59 parent.SetFirstChild(first_child); |
| 52 | 60 |
| 53 NGBlockLayoutAlgorithm algorithm(style_.get(), first_child, space); | 61 NGBlockLayoutAlgorithm algorithm(style_.get(), first_child, space); |
| 54 | 62 |
| 55 NGPhysicalFragment* fragment = algorithm.Layout(); | 63 NGPhysicalFragment* fragment = algorithm.Layout(); |
| 56 return toNGPhysicalBoxFragment(fragment); | 64 return toNGPhysicalBoxFragment(fragment); |
| 57 } | 65 } |
| 58 | 66 |
| 67 std::pair<NGPhysicalBoxFragment*, NGConstraintSpace*> | |
| 68 RunBlockLayoutAlgorithmForElement(Element* element) { | |
| 69 LayoutNGBlockFlow* block_flow = | |
| 70 toLayoutNGBlockFlow(element->layoutObject()); | |
| 71 NGConstraintSpace* space = | |
| 72 NGConstraintSpace::CreateFromLayoutObject(*block_flow); | |
| 73 NGPhysicalBoxFragment* fragment = RunBlockLayoutAlgorithm( | |
| 74 space, new NGBlockNode(element->layoutObject()->slowFirstChild())); | |
| 75 return std::make_pair(fragment, space); | |
| 76 } | |
| 77 | |
| 59 MinAndMaxContentSizes RunComputeMinAndMax(NGBlockNode* first_child) { | 78 MinAndMaxContentSizes RunComputeMinAndMax(NGBlockNode* first_child) { |
| 60 // The constraint space is not used for min/max computation, but we need | 79 // The constraint space is not used for min/max computation, but we need |
| 61 // it to create the algorithm. | 80 // it to create the algorithm. |
| 62 NGConstraintSpace* space = | 81 NGConstraintSpace* space = |
| 63 ConstructConstraintSpace(kHorizontalTopBottom, TextDirection::kLtr, | 82 ConstructConstraintSpace(kHorizontalTopBottom, TextDirection::kLtr, |
| 64 NGLogicalSize(LayoutUnit(), LayoutUnit())); | 83 NGLogicalSize(LayoutUnit(), LayoutUnit())); |
| 65 NGBlockLayoutAlgorithm algorithm(style_.get(), first_child, space); | 84 NGBlockLayoutAlgorithm algorithm(style_.get(), first_child, space); |
| 66 MinAndMaxContentSizes sizes; | 85 MinAndMaxContentSizes sizes; |
| 67 EXPECT_TRUE(algorithm.ComputeMinAndMaxContentSizes(&sizes)); | 86 EXPECT_TRUE(algorithm.ComputeMinAndMaxContentSizes(&sizes)); |
| 68 return sizes; | 87 return sizes; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 160 // DIV2 | 179 // DIV2 |
| 161 child = static_cast<const NGPhysicalBoxFragment*>(child)->Children()[0]; | 180 child = static_cast<const NGPhysicalBoxFragment*>(child)->Children()[0]; |
| 162 | 181 |
| 163 EXPECT_EQ(kHeight, child->Height()); | 182 EXPECT_EQ(kHeight, child->Height()); |
| 164 EXPECT_EQ(0, child->TopOffset()); | 183 EXPECT_EQ(0, child->TopOffset()); |
| 165 EXPECT_EQ(kMarginLeft, child->LeftOffset()); | 184 EXPECT_EQ(kMarginLeft, child->LeftOffset()); |
| 166 } | 185 } |
| 167 | 186 |
| 168 // Verifies the collapsing margins case for the next pair: | 187 // Verifies the collapsing margins case for the next pair: |
| 169 // - top margin of a box and top margin of its first in-flow child. | 188 // - top margin of a box and top margin of its first in-flow child. |
| 170 // | 189 // Verifies that floats are positioned at the top of the first child that can |
| 171 // Test case's HTML representation: | 190 // determine its position after margins collapsed. |
| 172 // <div style="margin-top: 20px; height: 50px;"> <!-- DIV1 --> | 191 // TODO(glebl): Enable with new the float/margins collapsing algorithm. |
| 173 // <div style="margin-top: 10px"></div> <!-- DIV2 --> | 192 TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_CollapsingMarginsCase1WithFloats) { |
| 174 // </div> | 193 setBodyInnerHTML( |
| 175 // | 194 "<style>" |
| 176 // Expected: | 195 " #container {" |
| 177 // - Empty margin strut of the fragment that establishes new formatting context | 196 " height: 200px;" |
| 178 // - Margins are collapsed resulting a single margin 20px = max(20px, 10px) | 197 " width: 200px;" |
| 179 // - The top offset of DIV2 == 20px | 198 " margin-top: 10px;" |
| 180 TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase1) { | 199 " padding: 0 7px;" |
| 181 const int kHeight = 50; | 200 " background-color: red;" |
| 182 const int kDiv1MarginTop = 20; | 201 " }" |
| 183 const int kDiv2MarginTop = 10; | 202 " #first-child {" |
| 184 | 203 " margin-top: 20px;" |
| 185 // DIV1 | 204 " height: 10px;" |
| 186 RefPtr<ComputedStyle> div1_style = ComputedStyle::create(); | 205 " background-color: blue;" |
| 187 div1_style->setHeight(Length(kHeight, Fixed)); | 206 " }" |
| 188 div1_style->setMarginTop(Length(kDiv1MarginTop, Fixed)); | 207 " #float-child-left {" |
| 189 NGBlockNode* div1 = new NGBlockNode(div1_style.get()); | 208 " float: left;" |
| 190 | 209 " height: 10px;" |
| 191 // DIV2 | 210 " width: 10px;" |
| 192 RefPtr<ComputedStyle> div2_style = ComputedStyle::create(); | 211 " padding: 10px;" |
| 193 div2_style->setMarginTop(Length(kDiv2MarginTop, Fixed)); | 212 " margin: 10px;" |
| 194 NGBlockNode* div2 = new NGBlockNode(div2_style.get()); | 213 " background-color: green;" |
| 195 | 214 " }" |
| 196 div1->SetFirstChild(div2); | 215 " #float-child-right {" |
| 197 | 216 " float: right;" |
| 198 auto* space = | 217 " height: 30px;" |
| 199 NGConstraintSpaceBuilder(kHorizontalTopBottom) | 218 " width: 30px;" |
| 200 .SetAvailableSize(NGLogicalSize(LayoutUnit(100), NGSizeIndefinite)) | 219 " background-color: pink;" |
| 201 .SetPercentageResolutionSize( | 220 " }" |
| 202 NGLogicalSize(LayoutUnit(100), NGSizeIndefinite)) | 221 "</style>" |
| 203 .SetTextDirection(TextDirection::kLtr) | 222 "<div id='container'>" |
| 204 .SetIsNewFormattingContext(true) | 223 " <div id='float-child-left'></div>" |
| 205 .ToConstraintSpace(); | 224 " <div id='float-child-right'></div>" |
| 206 NGPhysicalBoxFragment* frag = RunBlockLayoutAlgorithm(space, div1); | 225 " <div id='first-child'></div>" |
| 207 | 226 "</div>"); |
| 208 EXPECT_TRUE(frag->MarginStrut().IsEmpty()); | 227 |
| 209 ASSERT_EQ(frag->Children().size(), 1UL); | 228 // ** Run LayoutNG algorithm ** |
| 210 const NGPhysicalBoxFragment* div2_fragment = | 229 NGConstraintSpace* space; |
| 211 static_cast<const NGPhysicalBoxFragment*>(frag->Children()[0].get()); | 230 NGPhysicalBoxFragment* fragment; |
| 212 EXPECT_EQ(NGDeprecatedMarginStrut({LayoutUnit(kDiv2MarginTop)}), | 231 std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement( |
| 213 div2_fragment->MarginStrut()); | 232 document().getElementsByTagName("html")->item(0)); |
| 214 EXPECT_EQ(kDiv1MarginTop, div2_fragment->TopOffset()); | 233 ASSERT_EQ(fragment->Children().size(), 1UL); |
| 234 auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]); | |
| 235 // 20 = max(first child's margin top, containers's margin top) | |
| 236 int body_top_offset = 20; | |
| 237 EXPECT_THAT(LayoutUnit(body_top_offset), body_fragment->TopOffset()); | |
| 238 // 8 = body's margin | |
| 239 int body_left_offset = 8; | |
| 240 EXPECT_THAT(LayoutUnit(body_left_offset), body_fragment->LeftOffset()); | |
| 241 ASSERT_EQ(1UL, body_fragment->Children().size()); | |
| 242 auto* container_fragment = | |
| 243 toNGPhysicalBoxFragment(body_fragment->Children()[0]); | |
| 244 // 0 = collapsed with body's margin | |
| 245 EXPECT_THAT(LayoutUnit(0), container_fragment->TopOffset()); | |
| 246 ASSERT_EQ(1UL, container_fragment->Children().size()); | |
| 247 auto* first_child_fragment = | |
| 248 toNGPhysicalBoxFragment(container_fragment->Children()[0]); | |
| 249 // 0 = collapsed with container's margin | |
| 250 EXPECT_THAT(LayoutUnit(0), first_child_fragment->TopOffset()); | |
| 251 | |
| 252 // ** Verify layout tree ** | |
| 253 Element* first_child = document().getElementById("first-child"); | |
| 254 int first_child_block_offset = body_top_offset; | |
| 255 EXPECT_EQ(first_child_block_offset, first_child->offsetTop()); | |
| 256 | |
| 257 // The left float to be positioned at first-child's top. | |
|
ikilpatrick
2017/01/24 22:05:37
So I was more pushing back on the wording here, it
Gleb Lanbin
2017/01/24 22:30:43
Done.
| |
| 258 Element* float_child_left = document().getElementById("float-child-left"); | |
| 259 // first_child_block_offset + 10(float-child-left's margin) | |
| 260 int float_child_left_block_offset = first_child_block_offset + 10; | |
| 261 EXPECT_EQ(float_child_left_block_offset, float_child_left->offsetTop()); | |
| 262 | |
| 263 // The right float to be positioned at first-child's top. | |
|
ikilpatrick
2017/01/24 22:05:37
and here.
Gleb Lanbin
2017/01/24 22:30:43
Done.
| |
| 264 Element* float_child_right = document().getElementById("float-child-right"); | |
| 265 // Should be equal to first_child_block_offset | |
| 266 int float_child_right_block_offset = first_child_block_offset; | |
| 267 EXPECT_EQ(float_child_right_block_offset, float_child_right->offsetTop()); | |
| 268 | |
| 269 // ** Verify exclusions ** | |
| 270 // float-child-left's height(10) + padding(2x10) + margin(2x10) = 50px | |
| 271 NGLogicalSize exclusion1_size = {LayoutUnit(50), LayoutUnit(50)}; | |
| 272 // float-child-left's inline offset | |
| 273 // 15 = body's margin(8) + container's inline padding(7) | |
| 274 NGLogicalOffset exclusion1_offset = {LayoutUnit(15), | |
| 275 LayoutUnit(first_child_block_offset)}; | |
| 276 NGLogicalRect exclusion1_rect = {exclusion1_offset, exclusion1_size}; | |
| 277 NGExclusion expected_exclusion1 = {exclusion1_rect, NGExclusion::kFloatLeft}; | |
| 278 | |
| 279 NGLogicalSize exclusion2_size = {LayoutUnit(30), LayoutUnit(30)}; | |
| 280 // float-child-right's inline offset | |
| 281 // right_float_offset = 200 container's width - right float width 30 = 170 | |
| 282 // 185 = body's margin(8) + right_float_offset(170) + container's padding(7) | |
| 283 NGLogicalOffset exclusion2_offset = {LayoutUnit(185), | |
| 284 LayoutUnit(first_child_block_offset)}; | |
| 285 NGLogicalRect exclusion2_rect = {exclusion2_offset, exclusion2_size}; | |
| 286 NGExclusion expected_exclusion2 = {exclusion2_rect, NGExclusion::kFloatRight}; | |
| 287 | |
| 288 EXPECT_THAT(space->Exclusions()->storage, | |
| 289 (ElementsAre(Pointee(expected_exclusion1), | |
| 290 Pointee(expected_exclusion2)))); | |
| 215 } | 291 } |
| 216 | 292 |
| 217 // Verifies the collapsing margins case for the next pair: | 293 // Verifies the collapsing margins case for the next pair: |
| 218 // - bottom margin of box and top margin of its next in-flow following sibling. | 294 // - bottom margin of box and top margin of its next in-flow following sibling. |
| 219 // | 295 // - top and bottom margins of a box that does not establish a new block |
| 220 // Test case's HTML representation: | 296 // formatting context and that has zero computed 'min-height', zero or 'auto' |
| 221 // <div style="margin-bottom: 20px; height: 50px;"> <!-- DIV1 --> | 297 // computed 'height', and no in-flow children |
| 222 // <div style="margin-bottom: -15px"></div> <!-- DIV2 --> | 298 // TODO(glebl): Enable with new the float/margins collapsing algorithm. |
| 223 // <div></div> <!-- DIV3 --> | 299 TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_CollapsingMarginsCase2WithFloats) { |
| 224 // </div> | 300 setBodyInnerHTML( |
| 225 // <div></div> <!-- DIV4 --> | 301 "<style>" |
| 226 // <div style="margin-top: 10px; height: 50px;"> <!-- DIV5 --> | 302 "#first-child {" |
| 227 // <div></div> <!-- DIV6 --> | 303 " background-color: red;" |
| 228 // <div style="margin-top: -30px"></div> <!-- DIV7 --> | 304 " height: 50px;" |
| 229 // </div> | 305 " margin-bottom: 20px;" |
| 230 // | 306 "}" |
| 231 // Expected: | 307 "#float-between-empties {" |
| 232 // Margins are collapsed resulting an overlap | 308 " background-color: green;" |
| 233 // -10px = max(20px, 10px) - max(abs(-15px), abs(-30px)) | 309 " float: left;" |
| 234 // between DIV2 and DIV3. Zero-height blocks are ignored. | 310 " height: 30px;" |
| 235 TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase2) { | 311 " width: 30px;" |
| 236 const int kHeight = 50; | 312 "}" |
| 237 const int kDiv1MarginBottom = 20; | 313 "#float-between-nonempties {" |
| 238 const int kDiv2MarginBottom = -15; | 314 " background-color: lightgreen;" |
| 239 const int kDiv5MarginTop = 10; | 315 " float: left;" |
| 240 const int kDiv7MarginTop = -30; | 316 " height: 40px;" |
| 241 const int kExpectedCollapsedMargin = -10; | 317 " width: 40px;" |
| 242 | 318 "}" |
| 243 // DIV1 | 319 "#float-top-align {" |
| 244 RefPtr<ComputedStyle> div1_style = ComputedStyle::create(); | 320 " background-color: seagreen;" |
| 245 div1_style->setHeight(Length(kHeight, Fixed)); | 321 " float: left;" |
| 246 div1_style->setMarginBottom(Length(kDiv1MarginBottom, Fixed)); | 322 " height: 50px;" |
| 247 NGBlockNode* div1 = new NGBlockNode(div1_style.get()); | 323 " width: 50px;" |
| 248 | 324 "}" |
| 249 // DIV2 | 325 "#second-child {" |
| 250 RefPtr<ComputedStyle> div2_style = ComputedStyle::create(); | 326 " background-color: blue;" |
| 251 div2_style->setMarginBottom(Length(kDiv2MarginBottom, Fixed)); | 327 " height: 50px;" |
| 252 NGBlockNode* div2 = new NGBlockNode(div2_style.get()); | 328 " margin-top: 10px;" |
| 253 | 329 "}" |
| 254 // Empty DIVs: DIV3, DIV4, DIV6 | 330 "</style>" |
| 255 NGBlockNode* div3 = new NGBlockNode(ComputedStyle::create().get()); | 331 "<div id='first-child'>" |
| 256 NGBlockNode* div4 = new NGBlockNode(ComputedStyle::create().get()); | 332 " <div id='empty1' style='margin-bottom: -15px'></div>" |
| 257 NGBlockNode* div6 = new NGBlockNode(ComputedStyle::create().get()); | 333 " <div id='float-between-empties'></div>" |
| 258 | 334 " <div id='empty2'></div>" |
| 259 // DIV5 | 335 "</div>" |
| 260 RefPtr<ComputedStyle> div5_style = ComputedStyle::create(); | 336 "<div id='float-between-nonempties'></div>" |
| 261 div5_style->setHeight(Length(kHeight, Fixed)); | 337 "<div id='second-child'>" |
| 262 div5_style->setMarginTop(Length(kDiv5MarginTop, Fixed)); | 338 " <div id='float-top-align'></div>" |
| 263 NGBlockNode* div5 = new NGBlockNode(div5_style.get()); | 339 " <div id='empty3'></div>" |
| 264 | 340 " <div id='empty4' style='margin-top: -30px'></div>" |
| 265 // DIV7 | 341 "</div>" |
| 266 RefPtr<ComputedStyle> div7_style = ComputedStyle::create(); | 342 "<div id='empty5'></div>"); |
| 267 div7_style->setMarginTop(Length(kDiv7MarginTop, Fixed)); | 343 |
| 268 NGBlockNode* div7 = new NGBlockNode(div7_style.get()); | 344 // ** Run LayoutNG algorithm ** |
| 269 | 345 NGConstraintSpace* space; |
| 270 div1->SetFirstChild(div2); | 346 NGPhysicalBoxFragment* fragment; |
| 271 div2->SetNextSibling(div3); | 347 std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement( |
| 272 div1->SetNextSibling(div4); | 348 document().getElementsByTagName("html")->item(0)); |
| 273 div4->SetNextSibling(div5); | 349 |
| 274 div5->SetFirstChild(div6); | 350 auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]); |
| 275 div6->SetNextSibling(div7); | 351 // -7 = empty1's margin(-15) + body's margin(8) |
| 276 | 352 int body_top_offset = -7; |
| 277 auto* space = ConstructConstraintSpace( | 353 EXPECT_THAT(LayoutUnit(body_top_offset), body_fragment->TopOffset()); |
| 278 kHorizontalTopBottom, TextDirection::kLtr, | 354 int body_left_offset = 8; |
| 279 NGLogicalSize(LayoutUnit(100), NGSizeIndefinite)); | 355 EXPECT_THAT(LayoutUnit(body_top_offset), body_fragment->TopOffset()); |
| 280 NGPhysicalBoxFragment* frag = RunBlockLayoutAlgorithm(space, div1); | 356 ASSERT_EQ(3UL, body_fragment->Children().size()); |
| 281 | 357 |
| 282 ASSERT_EQ(frag->Children().size(), 3UL); | 358 auto* first_child_fragment = |
| 283 | 359 toNGPhysicalBoxFragment(body_fragment->Children()[0]); |
| 284 // DIV1 | 360 EXPECT_THAT(LayoutUnit(), first_child_fragment->TopOffset()); |
| 285 const NGPhysicalFragment* child = frag->Children()[0]; | 361 |
| 286 EXPECT_EQ(kHeight, child->Height()); | 362 auto* second_child_fragment = |
| 287 EXPECT_EQ(0, child->TopOffset()); | 363 toNGPhysicalBoxFragment(body_fragment->Children()[1]); |
| 288 | 364 // 40 = first_child's height(50) - margin's collapsing result(10) |
| 289 // DIV5 | 365 int second_child_block_offset = 40; |
| 290 child = frag->Children()[2]; | 366 EXPECT_THAT(LayoutUnit(second_child_block_offset), |
| 291 EXPECT_EQ(kHeight, child->Height()); | 367 second_child_fragment->TopOffset()); |
| 292 EXPECT_EQ(kHeight + kExpectedCollapsedMargin, child->TopOffset()); | 368 |
| 369 auto* empty5_fragment = toNGPhysicalBoxFragment(body_fragment->Children()[2]); | |
| 370 // 90 = first_child's height(50) + collapsed margins(-10) + | |
| 371 // second child's height(50) | |
| 372 int empty5_fragment_block_offset = 90; | |
| 373 EXPECT_THAT(LayoutUnit(empty5_fragment_block_offset), | |
| 374 empty5_fragment->TopOffset()); | |
| 375 | |
| 376 ASSERT_EQ(3UL, body_fragment->PositionedFloats().size()); | |
| 377 auto float_nonempties_fragment = | |
| 378 body_fragment->PositionedFloats().at(1)->fragment; | |
| 379 // 70 = first_child's height(50) + first child's margin-bottom(20) | |
| 380 EXPECT_THAT(LayoutUnit(70), float_nonempties_fragment->TopOffset()); | |
| 381 EXPECT_THAT(LayoutUnit(0), float_nonempties_fragment->LeftOffset()); | |
| 382 | |
| 383 // ** Verify layout tree ** | |
| 384 Element* first_child = document().getElementById("first-child"); | |
| 385 // -7 = body_top_offset | |
| 386 EXPECT_EQ(body_top_offset, first_child->offsetTop()); | |
| 387 | |
| 388 NGLogicalSize float_empties_exclusion_size = {LayoutUnit(30), LayoutUnit(30)}; | |
| 389 NGLogicalOffset float_empties_exclusion_offset = { | |
| 390 LayoutUnit(body_left_offset), LayoutUnit(body_top_offset)}; | |
| 391 NGLogicalRect float_empties_exclusion_rect = {float_empties_exclusion_offset, | |
| 392 float_empties_exclusion_size}; | |
| 393 NGExclusion float_empties_exclusion = {float_empties_exclusion_rect, | |
| 394 NGExclusion::kFloatLeft}; | |
| 395 | |
| 396 NGLogicalSize float_nonempties_exclusion_size = {LayoutUnit(40), | |
| 397 LayoutUnit(40)}; | |
| 398 // 63 = first_child_margin_strut(20) + first-child's height(50) + | |
| 399 // body_top_offset(-7) | |
| 400 NGLogicalOffset float_nonempties_exclusion_offset = { | |
| 401 LayoutUnit(body_left_offset), LayoutUnit(63)}; | |
| 402 NGLogicalRect float_nonempties_exclusion_rect = { | |
| 403 float_nonempties_exclusion_offset, float_nonempties_exclusion_size}; | |
| 404 NGExclusion float_nonempties_exclusion = {float_nonempties_exclusion_rect, | |
| 405 NGExclusion::kFloatLeft}; | |
| 406 | |
| 407 NGLogicalSize float_top_align_exclusion_size = {LayoutUnit(50), | |
| 408 LayoutUnit(50)}; | |
| 409 // 63 = float_nonempties_exclusion_offset because of the top edge alignment | |
| 410 // rule. | |
| 411 // 48 = body's margin + float_nonempties_exclusion_size | |
| 412 NGLogicalOffset float_top_align_exclusion_offset = {LayoutUnit(48), | |
| 413 LayoutUnit(63)}; | |
| 414 NGLogicalRect float_top_align_exclusion_rect = { | |
| 415 float_top_align_exclusion_offset, float_top_align_exclusion_size}; | |
| 416 NGExclusion float_top_align_exclusion = {float_top_align_exclusion_rect, | |
| 417 NGExclusion::kFloatLeft}; | |
| 418 | |
| 419 EXPECT_THAT(space->Exclusions()->storage, | |
| 420 (ElementsAre(Pointee(float_empties_exclusion), | |
| 421 Pointee(float_nonempties_exclusion), | |
| 422 Pointee(float_top_align_exclusion)))); | |
| 293 } | 423 } |
| 294 | 424 |
| 295 // Verifies the collapsing margins case for the next pair: | 425 // Verifies the collapsing margins case for the next pair: |
| 296 // - bottom margin of a last in-flow child and bottom margin of its parent if | 426 // - bottom margin of a last in-flow child and bottom margin of its parent if |
| 297 // the parent has 'auto' computed height | 427 // the parent has 'auto' computed height |
| 298 // | 428 // TODO(glebl): Enable with new the float/margins collapsing algorithm. |
| 299 // Test case's HTML representation: | 429 TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_CollapsingMarginsCase3) { |
| 300 // <div style="margin-bottom: 20px; height: 50px;"> <!-- DIV1 --> | 430 setBodyInnerHTML( |
| 301 // <div style="margin-bottom: 200px; height: 50px;"/> <!-- DIV2 --> | 431 "<style>" |
| 302 // </div> | 432 " #container {" |
| 303 // | 433 " margin-bottom: 20px;" |
| 304 // Expected: | 434 " }" |
| 305 // 1) Margins are collapsed with the result = std::max(20, 200) | 435 " #child {" |
| 306 // if DIV1.height == auto | 436 " margin-bottom: 200px;" |
| 307 // 2) Margins are NOT collapsed if DIV1.height != auto | 437 " height: 50px;" |
| 308 TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase3) { | 438 " }" |
| 309 const int kHeight = 50; | 439 "</style>" |
| 310 const int kDiv1MarginBottom = 20; | 440 "<div id='container'>" |
| 311 const int kDiv2MarginBottom = 200; | 441 " <div id='child'></div>" |
| 312 | 442 "</div>"); |
| 313 // DIV1 | 443 |
| 314 RefPtr<ComputedStyle> div1_style = ComputedStyle::create(); | 444 const NGPhysicalBoxFragment* body_fragment; |
| 315 div1_style->setMarginBottom(Length(kDiv1MarginBottom, Fixed)); | 445 const NGPhysicalBoxFragment* container_fragment; |
| 316 NGBlockNode* div1 = new NGBlockNode(div1_style.get()); | 446 const NGPhysicalBoxFragment* child_fragment; |
| 317 | 447 const NGPhysicalBoxFragment* fragment; |
| 318 // DIV2 | 448 auto run_test = [&](const Length& container_height) { |
| 319 RefPtr<ComputedStyle> div2_style = ComputedStyle::create(); | 449 Element* container = document().getElementById("container"); |
| 320 div2_style->setHeight(Length(kHeight, Fixed)); | 450 container->mutableComputedStyle()->setHeight(container_height); |
| 321 div2_style->setMarginBottom(Length(kDiv2MarginBottom, Fixed)); | 451 std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement( |
| 322 NGBlockNode* div2 = new NGBlockNode(div2_style.get()); | 452 document().getElementsByTagName("html")->item(0)); |
| 323 | 453 ASSERT_EQ(1UL, fragment->Children().size()); |
| 324 div1->SetFirstChild(div2); | 454 body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]); |
| 325 | 455 container_fragment = toNGPhysicalBoxFragment(body_fragment->Children()[0]); |
| 326 auto* space = ConstructConstraintSpace( | 456 ASSERT_EQ(1UL, container_fragment->Children().size()); |
| 327 kHorizontalTopBottom, TextDirection::kLtr, | 457 child_fragment = toNGPhysicalBoxFragment(container_fragment->Children()[0]); |
| 328 NGLogicalSize(LayoutUnit(100), NGSizeIndefinite)); | 458 }; |
| 329 NGPhysicalBoxFragment* frag = RunBlockLayoutAlgorithm(space, div1); | 459 |
| 330 | 460 // height == auto |
| 331 // Verify that margins are collapsed. | 461 run_test(Length(Auto)); |
| 332 EXPECT_EQ( | 462 // Margins are collapsed with the result 200 = std::max(20, 200) |
| 333 NGDeprecatedMarginStrut({LayoutUnit(0), LayoutUnit(kDiv2MarginBottom)}), | 463 // The fragment size 258 == body's margin 8 + child's height 50 + 200 |
| 334 frag->MarginStrut()); | 464 EXPECT_EQ(NGPhysicalSize(LayoutUnit(800), LayoutUnit(258)), fragment->Size()); |
| 335 | 465 // EXPECT_EQ(NGMarginStrut({LayoutUnit(200)}), |
| 336 // Verify that margins are NOT collapsed. | 466 // container_fragment->EndMarginStrut()); |
| 337 div1_style->setHeight(Length(kHeight, Fixed)); | 467 |
| 338 frag = RunBlockLayoutAlgorithm(space, div1); | 468 // height == fixed |
| 339 EXPECT_EQ( | 469 run_test(Length(50, Fixed)); |
| 340 NGDeprecatedMarginStrut({LayoutUnit(0), LayoutUnit(kDiv1MarginBottom)}), | 470 // Margins are not collapsed, so fragment still has margins == 20. |
| 341 frag->MarginStrut()); | 471 // The fragment size 78 == body's margin 8 + child's height 50 + 20 |
| 472 // EXPECT_EQ(NGPhysicalSize(LayoutUnit(800), LayoutUnit(78)), | |
| 473 // fragment->Size()); | |
| 474 // EXPECT_EQ(NGMarginStrut(), container_fragment->EndMarginStrut()); | |
| 342 } | 475 } |
| 343 | 476 |
| 344 // Verifies that 2 adjoining margins are not collapsed if there is padding or | 477 // Verifies that 2 adjoining margins are not collapsed if there is padding or |
| 345 // border that separates them. | 478 // border that separates them. |
| 346 // | 479 // TODO(glebl): Enable with new the float/margins collapsing algorithm. |
| 347 // Test case's HTML representation: | 480 TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_CollapsingMarginsCase4) { |
| 348 // <div style="margin: 30px 0px; padding: 20px 0px;"> <!-- DIV1 --> | 481 setBodyInnerHTML( |
| 349 // <div style="margin: 200px 0px; height: 50px;"/> <!-- DIV2 --> | 482 "<style>" |
| 350 // </div> | 483 " #container {" |
| 351 // | 484 " margin: 30px 0px;" |
| 352 // Expected: | 485 " width: 200px;" |
| 353 // Margins do NOT collapse if there is an interfering padding or border. | 486 " }" |
| 354 TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase4) { | 487 " #child {" |
| 355 const int kHeight = 50; | 488 " margin: 200px 0px;" |
| 356 const int kDiv1Margin = 30; | 489 " height: 50px;" |
| 357 const int kDiv1Padding = 20; | 490 " background-color: blue;" |
| 358 const int kDiv2Margin = 200; | 491 " }" |
| 359 | 492 "</style>" |
| 360 // DIV1 | 493 "<div id='container'>" |
| 361 RefPtr<ComputedStyle> div1_style = ComputedStyle::create(); | 494 " <div id='child'></div>" |
| 362 div1_style->setMarginTop(Length(kDiv1Margin, Fixed)); | 495 "</div>"); |
| 363 div1_style->setMarginBottom(Length(kDiv1Margin, Fixed)); | 496 |
| 364 div1_style->setPaddingTop(Length(kDiv1Padding, Fixed)); | 497 const NGPhysicalBoxFragment* body_fragment; |
| 365 div1_style->setPaddingBottom(Length(kDiv1Padding, Fixed)); | 498 const NGPhysicalBoxFragment* container_fragment; |
| 366 NGBlockNode* div1 = new NGBlockNode(div1_style.get()); | 499 const NGPhysicalBoxFragment* child_fragment; |
| 367 | 500 const NGPhysicalBoxFragment* fragment; |
| 368 // DIV2 | 501 auto run_test = [&](const Length& container_padding_top) { |
| 369 RefPtr<ComputedStyle> div2_style = ComputedStyle::create(); | 502 Element* container = document().getElementById("container"); |
| 370 div2_style->setHeight(Length(kHeight, Fixed)); | 503 container->mutableComputedStyle()->setPaddingTop(container_padding_top); |
| 371 div2_style->setMarginTop(Length(kDiv2Margin, Fixed)); | 504 std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement( |
| 372 div2_style->setMarginBottom(Length(kDiv2Margin, Fixed)); | 505 document().getElementsByTagName("html")->item(0)); |
| 373 NGBlockNode* div2 = new NGBlockNode(div2_style.get()); | 506 ASSERT_EQ(1UL, fragment->Children().size()); |
| 374 | 507 body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]); |
| 375 div1->SetFirstChild(div2); | 508 container_fragment = toNGPhysicalBoxFragment(body_fragment->Children()[0]); |
| 376 | 509 ASSERT_EQ(1UL, container_fragment->Children().size()); |
| 377 auto* space = ConstructConstraintSpace( | 510 child_fragment = toNGPhysicalBoxFragment(container_fragment->Children()[0]); |
| 378 kHorizontalTopBottom, TextDirection::kLtr, | 511 }; |
| 379 NGLogicalSize(LayoutUnit(100), NGSizeIndefinite)); | 512 |
| 380 NGPhysicalBoxFragment* frag = RunBlockLayoutAlgorithm(space, div1); | 513 // with padding |
| 381 | 514 run_test(Length(20, Fixed)); |
| 382 // Verify that margins do NOT collapse. | 515 // 500 = child's height 50 + 2xmargin 400 + paddint-top 20 + |
| 383 frag = RunBlockLayoutAlgorithm(space, div1); | 516 // container's margin 30 |
| 384 EXPECT_EQ(NGDeprecatedMarginStrut( | 517 EXPECT_EQ(NGPhysicalSize(LayoutUnit(800), LayoutUnit(500)), fragment->Size()); |
| 385 {LayoutUnit(kDiv1Margin), LayoutUnit(kDiv1Margin)}), | 518 // 30 = max(body's margin 8, container margin 30) |
| 386 frag->MarginStrut()); | 519 EXPECT_EQ(LayoutUnit(30), body_fragment->TopOffset()); |
| 387 ASSERT_EQ(frag->Children().size(), 1UL); | 520 // 220 = container's padding top 20 + child's margin |
| 388 | 521 EXPECT_EQ(LayoutUnit(220), child_fragment->TopOffset()); |
| 389 EXPECT_EQ(NGDeprecatedMarginStrut( | 522 |
| 390 {LayoutUnit(kDiv2Margin), LayoutUnit(kDiv2Margin)}), | 523 // without padding |
| 391 static_cast<const NGPhysicalBoxFragment*>(frag->Children()[0].get()) | 524 run_test(Length(0, Fixed)); |
| 392 ->MarginStrut()); | 525 // 450 = 2xmax(body's margin 8, container's margin 30, child's margin 200) + |
| 393 | 526 // child's height 50 |
| 394 // Reset padding and verify that margins DO collapse. | 527 EXPECT_EQ(NGPhysicalSize(LayoutUnit(800), LayoutUnit(450)), fragment->Size()); |
| 395 div1_style->setPaddingTop(Length(0, Fixed)); | 528 // 200 = (body's margin 8, container's margin 30, child's margin 200) |
| 396 div1_style->setPaddingBottom(Length(0, Fixed)); | 529 EXPECT_EQ(LayoutUnit(200), body_fragment->TopOffset()); |
| 397 frag = RunBlockLayoutAlgorithm(space, div1); | 530 // 0 = collapsed margins |
| 398 EXPECT_EQ(NGDeprecatedMarginStrut( | 531 EXPECT_EQ(LayoutUnit(0), child_fragment->TopOffset()); |
| 399 {LayoutUnit(kDiv2Margin), LayoutUnit(kDiv2Margin)}), | |
| 400 frag->MarginStrut()); | |
| 401 } | 532 } |
| 402 | 533 |
| 403 // Verifies that margins of 2 adjoining blocks with different writing modes | 534 // Verifies that margins of 2 adjoining blocks with different writing modes |
| 404 // get collapsed. | 535 // get collapsed. |
| 405 // | 536 // |
| 406 // Test case's HTML representation: | 537 // Test case's HTML representation: |
| 407 // <div style="writing-mode: vertical-lr;"> | 538 // <div style="writing-mode: vertical-lr;"> |
| 408 // <div style="margin-right: 60px; width: 60px;">vertical</div> | 539 // <div style="margin-right: 60px; width: 60px;">vertical</div> |
| 409 // <div style="margin-left: 100px; writing-mode: horizontal-tb;"> | 540 // <div style="margin-left: 100px; writing-mode: horizontal-tb;"> |
| 410 // horizontal | 541 // horizontal |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 625 EXPECT_EQ(NGPhysicalFragment::kFragmentBox, frag->Type()); | 756 EXPECT_EQ(NGPhysicalFragment::kFragmentBox, frag->Type()); |
| 626 EXPECT_EQ(LayoutUnit(kWidth + kPaddingLeft), frag->WidthOverflow()); | 757 EXPECT_EQ(LayoutUnit(kWidth + kPaddingLeft), frag->WidthOverflow()); |
| 627 ASSERT_EQ(1UL, frag->Children().size()); | 758 ASSERT_EQ(1UL, frag->Children().size()); |
| 628 | 759 |
| 629 const NGPhysicalFragment* child = frag->Children()[0]; | 760 const NGPhysicalFragment* child = frag->Children()[0]; |
| 630 EXPECT_EQ(LayoutUnit(kChildWidth), child->Width()); | 761 EXPECT_EQ(LayoutUnit(kChildWidth), child->Width()); |
| 631 EXPECT_EQ(LayoutUnit(kPaddingLeft + 10), child->LeftOffset()); | 762 EXPECT_EQ(LayoutUnit(kPaddingLeft + 10), child->LeftOffset()); |
| 632 EXPECT_EQ(LayoutUnit(0), child->TopOffset()); | 763 EXPECT_EQ(LayoutUnit(0), child->TopOffset()); |
| 633 } | 764 } |
| 634 | 765 |
| 635 // Verifies that 3 Left/Right float fragments and one regular block fragment | 766 // Verifies that floats can be correctly positioned if they are inside of nested |
| 636 // are correctly positioned by the algorithm. | 767 // empty blocks. |
| 637 // | 768 // TODO(glebl): Enable with new the float/margins collapsing algorithm. |
| 638 // Test case's HTML representation: | 769 TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_PositionFloatInsideEmptyBlocks) { |
| 639 // <div id="parent" style="width: 200px; height: 200px;"> | 770 setBodyInnerHTML( |
| 640 // <div style="float:left; width: 30px; height: 30px; | 771 "<!DOCTYPE html>" |
| 641 // margin-top: 10px;"/> <!-- DIV1 --> | 772 "<style>" |
| 642 // <div style="width: 30px; height: 30px;"/> <!-- DIV2 --> | 773 " #container {" |
| 643 // <div style="float:right; width: 50px; height: 50px;"/> <!-- DIV3 --> | 774 " height: 200px;" |
| 644 // <div style="float:left; width: 120px; height: 120px; | 775 " width: 200px;" |
| 645 // margin-left: 30px;"/> <!-- DIV4 --> | 776 " }" |
| 646 // </div> | 777 " #empty1 {" |
| 647 // | 778 " margin: 20px;" |
| 648 // Expected: | 779 " padding: 0 20px;" |
| 649 // - Left float(DIV1) is positioned at the left. | 780 " }" |
| 650 // - Regular block (DIV2) is positioned behind DIV1. | 781 " #empty2 {" |
| 651 // - Right float(DIV3) is positioned at the right below DIV2 | 782 " margin: 15px;" |
| 652 // - Left float(DIV4) is positioned at the left below DIV3. | 783 " padding: 0 15px;" |
| 653 TEST_F(NGBlockLayoutAlgorithmTest, PositionFloatFragments) { | 784 " }" |
| 654 const int kParentLeftPadding = 10; | 785 " #float {" |
| 655 const int kDiv1TopMargin = 10; | 786 " float: left;" |
| 656 const int kParentSize = 200; | 787 " height: 5px;" |
| 657 const int kDiv1Size = 30; | 788 " width: 5px;" |
| 658 const int kDiv2Size = 30; | 789 " padding: 10px;" |
| 659 const int kDiv3Size = 50; | 790 " margin: 10px;" |
| 660 const int kDiv4Size = kParentSize - kDiv3Size; | 791 " background-color: green;" |
| 661 const int kDiv4LeftMargin = kDiv1Size; | 792 " }" |
| 662 | 793 "</style>" |
| 663 style_->setHeight(Length(kParentSize, Fixed)); | 794 "<div id='container'>" |
| 664 style_->setWidth(Length(kParentSize, Fixed)); | 795 " <div id='empty1'>" |
| 665 style_->setPaddingLeft(Length(kParentLeftPadding, Fixed)); | 796 " <div id='empty2'>" |
| 666 | 797 " <div id='float'></div>" |
| 667 // DIV1 | 798 " </div>" |
| 668 RefPtr<ComputedStyle> div1_style = ComputedStyle::create(); | 799 " </div>" |
| 669 div1_style->setWidth(Length(kDiv1Size, Fixed)); | 800 "</div>"); |
| 670 div1_style->setHeight(Length(kDiv1Size, Fixed)); | 801 |
| 671 div1_style->setFloating(EFloat::kLeft); | 802 // ** Run LayoutNG algorithm ** |
| 672 div1_style->setMarginTop(Length(kDiv1TopMargin, Fixed)); | 803 NGConstraintSpace* space; |
| 673 NGBlockNode* div1 = new NGBlockNode(div1_style.get()); | 804 NGPhysicalBoxFragment* fragment; |
| 674 | 805 std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement( |
| 675 // DIV2 | 806 document().getElementsByTagName("html")->item(0)); |
| 676 RefPtr<ComputedStyle> div2_style = ComputedStyle::create(); | 807 |
| 677 div2_style->setWidth(Length(kDiv2Size, Fixed)); | 808 auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]); |
| 678 div2_style->setHeight(Length(kDiv2Size, Fixed)); | 809 // 20 = std::max(empty1's margin, empty2's margin, body's margin) |
| 679 NGBlockNode* div2 = new NGBlockNode(div2_style.get()); | 810 int body_top_offset = 20; |
| 680 | 811 EXPECT_THAT(LayoutUnit(body_top_offset), body_fragment->TopOffset()); |
| 681 // DIV3 | 812 ASSERT_EQ(1UL, body_fragment->Children().size()); |
| 682 RefPtr<ComputedStyle> div3_style = ComputedStyle::create(); | 813 auto* container_fragment = |
| 683 div3_style->setWidth(Length(kDiv3Size, Fixed)); | 814 toNGPhysicalBoxFragment(body_fragment->Children()[0]); |
| 684 div3_style->setHeight(Length(kDiv3Size, Fixed)); | 815 ASSERT_EQ(1UL, container_fragment->Children().size()); |
| 685 div3_style->setFloating(EFloat::kRight); | 816 |
| 686 NGBlockNode* div3 = new NGBlockNode(div3_style.get()); | 817 auto* empty1_fragment = |
| 687 | 818 toNGPhysicalBoxFragment(container_fragment->Children()[0]); |
| 688 // DIV4 | 819 // 0, vertical margins got collapsed |
| 689 RefPtr<ComputedStyle> div4_style = ComputedStyle::create(); | 820 EXPECT_THAT(LayoutUnit(), empty1_fragment->TopOffset()); |
| 690 div4_style->setWidth(Length(kDiv4Size, Fixed)); | 821 // 20 empty1's margin |
| 691 div4_style->setHeight(Length(kDiv4Size, Fixed)); | 822 int empty1_inline_offset = 20; |
| 692 div4_style->setMarginLeft(Length(kDiv4LeftMargin, Fixed)); | 823 EXPECT_THAT(LayoutUnit(empty1_inline_offset), empty1_fragment->LeftOffset()); |
| 693 div4_style->setFloating(EFloat::kLeft); | 824 ASSERT_EQ(empty1_fragment->Children().size(), 1UL); |
| 694 NGBlockNode* div4 = new NGBlockNode(div4_style.get()); | 825 |
| 695 | 826 auto* empty2_fragment = |
| 696 div1->SetNextSibling(div2); | 827 toNGPhysicalBoxFragment(empty1_fragment->Children()[0]); |
| 697 div2->SetNextSibling(div3); | 828 // 0, vertical margins got collapsed |
| 698 div3->SetNextSibling(div4); | 829 EXPECT_THAT(LayoutUnit(), empty2_fragment->TopOffset()); |
| 699 | 830 // 35 = empty1's padding(20) + empty2's padding(15) |
| 700 auto* space = ConstructConstraintSpace( | 831 int empty2_inline_offset = 35; |
| 701 kHorizontalTopBottom, TextDirection::kLtr, | 832 EXPECT_THAT(LayoutUnit(empty2_inline_offset), empty2_fragment->LeftOffset()); |
| 702 NGLogicalSize(LayoutUnit(kParentSize), LayoutUnit(kParentSize))); | 833 |
| 703 NGPhysicalBoxFragment* frag = RunBlockLayoutAlgorithm(space, div1); | 834 ASSERT_EQ(1UL, body_fragment->PositionedFloats().size()); |
| 704 ASSERT_EQ(frag->Children().size(), 4UL); | 835 auto float_fragment = body_fragment->PositionedFloats().at(0)->fragment; |
| 705 | 836 // 10 = float's padding |
| 706 // DIV1 | 837 EXPECT_THAT(LayoutUnit(10), float_fragment->TopOffset()); |
| 707 const NGPhysicalFragment* child1 = frag->Children()[0]; | 838 // 25 = empty2's padding(15) + float's padding(10) |
| 708 EXPECT_EQ(kDiv1TopMargin, child1->TopOffset()); | 839 int float_inline_offset = 25; |
| 709 EXPECT_EQ(kParentLeftPadding, child1->LeftOffset()); | 840 EXPECT_THAT(float_fragment->LeftOffset(), LayoutUnit(float_inline_offset)); |
| 710 | 841 |
| 711 // DIV2 | 842 // ** Verify layout tree ** |
| 712 const NGPhysicalFragment* child2 = frag->Children()[1]; | 843 Element* left_float = document().getElementById("float"); |
| 713 EXPECT_EQ(0, child2->TopOffset()); | 844 // 88 = body's margin(8) + |
| 714 EXPECT_EQ(kParentLeftPadding, child2->LeftOffset()); | 845 // empty1's padding and margin + empty2's padding and margins + float's |
| 715 | 846 // padding |
| 716 // DIV3 | 847 EXPECT_THAT(left_float->offsetLeft(), 88); |
| 717 const NGPhysicalFragment* child3 = frag->Children()[2]; | 848 // 30 = body_top_offset(collapsed margins result) + float's padding |
| 718 EXPECT_EQ(kDiv2Size, child3->TopOffset()); | 849 EXPECT_THAT(body_top_offset + 10, left_float->offsetTop()); |
| 719 EXPECT_EQ(kParentLeftPadding + kParentSize - kDiv3Size, child3->LeftOffset()); | 850 |
| 720 | 851 // ** Legacy Floating objects ** |
| 721 // DIV4 | 852 Element* body = document().getElementsByTagName("body")->item(0); |
| 722 const NGPhysicalFragment* child4 = frag->Children()[3]; | 853 auto& floating_objects = |
| 723 EXPECT_EQ(kDiv2Size + kDiv3Size, child4->TopOffset()); | 854 const_cast<FloatingObjects*>( |
| 724 EXPECT_EQ(kParentLeftPadding + kDiv4LeftMargin, child4->LeftOffset()); | 855 toLayoutBlockFlow(body->layoutObject())->floatingObjects()) |
| 856 ->mutableSet(); | |
| 857 ASSERT_EQ(1UL, floating_objects.size()); | |
| 858 auto floating_object = floating_objects.takeFirst(); | |
| 859 ASSERT_TRUE(floating_object->isPlaced()); | |
| 860 // 80 = float_inline_offset(25) + accumulative offset of empty blocks(35 + 20) | |
| 861 EXPECT_THAT(LayoutUnit(80), floating_object->x()); | |
| 862 // 10 = float's padding | |
| 863 EXPECT_THAT(LayoutUnit(10), floating_object->y()); | |
| 725 } | 864 } |
| 726 | 865 |
| 866 // Verifies that left/right floating and regular blocks can be positioned | |
| 867 // correctly by the algorithm. | |
| 868 // TODO(glebl): Enable with new the float/margins collapsing algorithm. | |
| 869 TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_PositionFloatFragments) { | |
| 870 setBodyInnerHTML( | |
| 871 "<style>" | |
| 872 " #container {" | |
| 873 " height: 200px;" | |
| 874 " width: 200px;" | |
| 875 " }" | |
| 876 " #left-float {" | |
| 877 " background-color: red;" | |
| 878 " float:left;" | |
| 879 " height: 30px;" | |
| 880 " width: 30px;" | |
| 881 " }" | |
| 882 " #left-wide-float {" | |
| 883 " background-color: greenyellow;" | |
| 884 " float:left;" | |
| 885 " height: 30px;" | |
| 886 " width: 180px;" | |
| 887 " }" | |
| 888 " #regular {" | |
| 889 " width: 40px;" | |
| 890 " height: 40px;" | |
| 891 " background-color: green;" | |
| 892 " }" | |
| 893 " #right-float {" | |
| 894 " background-color: cyan;" | |
| 895 " float:right;" | |
| 896 " width: 50px;" | |
| 897 " height: 50px;" | |
| 898 " }" | |
| 899 " #left-float-with-margin {" | |
| 900 " background-color: black;" | |
| 901 " float:left;" | |
| 902 " height: 120px;" | |
| 903 " margin: 10px;" | |
| 904 " width: 120px;" | |
| 905 " }" | |
| 906 "</style>" | |
| 907 "<div id='container'>" | |
| 908 " <div id='left-float'></div>" | |
| 909 " <div id='left-wide-float'></div>" | |
| 910 " <div id='regular'></div>" | |
| 911 " <div id='right-float'></div>" | |
| 912 " <div id='left-float-with-margin'></div>" | |
| 913 "</div>"); | |
| 914 | |
| 915 // ** Run LayoutNG algorithm ** | |
| 916 NGConstraintSpace* space; | |
| 917 NGPhysicalBoxFragment* fragment; | |
| 918 std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement( | |
| 919 document().getElementsByTagName("html")->item(0)); | |
| 920 | |
| 921 // ** Verify LayoutNG fragments and the list of positioned floats ** | |
| 922 EXPECT_THAT(LayoutUnit(), fragment->TopOffset()); | |
| 923 ASSERT_EQ(1UL, fragment->Children().size()); | |
| 924 auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]); | |
| 925 EXPECT_THAT(LayoutUnit(8), body_fragment->TopOffset()); | |
| 926 auto* container_fragment = | |
| 927 toNGPhysicalBoxFragment(body_fragment->Children()[0]); | |
| 928 ASSERT_EQ(1UL, container_fragment->Children().size()); | |
| 929 ASSERT_EQ(4UL, container_fragment->PositionedFloats().size()); | |
| 930 | |
| 931 // ** Verify layout tree ** | |
| 932 Element* left_float = document().getElementById("left-float"); | |
| 933 // 8 = body's margin-top | |
| 934 int left_float_block_offset = 8; | |
| 935 EXPECT_EQ(left_float_block_offset, left_float->offsetTop()); | |
| 936 auto left_float_fragment = | |
| 937 container_fragment->PositionedFloats().at(0)->fragment; | |
| 938 EXPECT_THAT(LayoutUnit(), left_float_fragment->TopOffset()); | |
| 939 | |
| 940 Element* left_wide_float = document().getElementById("left-wide-float"); | |
| 941 // left-wide-float is positioned right below left-float as it's too wide. | |
| 942 // 38 = left_float_block_offset + | |
| 943 // left-float's height 30 | |
| 944 int left_wide_float_block_offset = 38; | |
| 945 EXPECT_EQ(left_wide_float_block_offset, left_wide_float->offsetTop()); | |
| 946 auto left_wide_float_fragment = | |
| 947 container_fragment->PositionedFloats().at(1)->fragment; | |
| 948 // 30 = left-float's height. | |
| 949 EXPECT_THAT(LayoutUnit(30), left_wide_float_fragment->TopOffset()); | |
| 950 | |
| 951 Element* regular = document().getElementById("regular"); | |
| 952 // regular_block_offset = body's margin-top 8 | |
| 953 int regular_block_offset = 8; | |
| 954 EXPECT_EQ(regular_block_offset, regular->offsetTop()); | |
| 955 auto* regular_block_fragment = | |
| 956 toNGPhysicalBoxFragment(container_fragment->Children()[0]); | |
| 957 EXPECT_THAT(LayoutUnit(), regular_block_fragment->TopOffset()); | |
| 958 | |
| 959 Element* right_float = document().getElementById("right-float"); | |
| 960 // 158 = body's margin-left 8 + container's width 200 - right_float's width 50 | |
| 961 int right_float_inline_offset = 158; | |
| 962 // it's positioned right after our left_wide_float | |
| 963 // 68 = left_wide_float_block_offset 38 + left-wide-float's height 30 | |
| 964 int right_float_block_offset = left_wide_float_block_offset + 30; | |
| 965 EXPECT_EQ(right_float_inline_offset, right_float->offsetLeft()); | |
| 966 EXPECT_EQ(right_float_block_offset, right_float->offsetTop()); | |
| 967 auto right_float_fragment = | |
| 968 container_fragment->PositionedFloats().at(2)->fragment; | |
| 969 // 60 = right_float_block_offset(68) - body's margin(8) | |
| 970 EXPECT_THAT(LayoutUnit(right_float_block_offset - 8), | |
| 971 right_float_fragment->TopOffset()); | |
| 972 // 150 = right_float_inline_offset(158) - body's margin(8) | |
| 973 EXPECT_THAT(LayoutUnit(right_float_inline_offset - 8), | |
| 974 right_float_fragment->LeftOffset()); | |
| 975 | |
| 976 Element* left_float_with_margin = | |
| 977 document().getElementById("left-float-with-margin"); | |
| 978 // 18 = body's margin(8) + left-float-with-margin's margin(10) | |
| 979 int left_float_with_margin_inline_offset = 18; | |
| 980 EXPECT_EQ(left_float_with_margin_inline_offset, | |
| 981 left_float_with_margin->offsetLeft()); | |
| 982 // 78 = left_wide_float_block_offset 38 + left-wide-float's height 30 + | |
| 983 // left-float-with-margin's margin(10) | |
| 984 int left_float_with_margin_block_offset = 78; | |
| 985 EXPECT_EQ(left_float_with_margin_block_offset, | |
| 986 left_float_with_margin->offsetTop()); | |
| 987 auto left_float_with_margin_fragment = | |
| 988 container_fragment->PositionedFloats().at(3)->fragment; | |
| 989 // 70 = left_float_with_margin_block_offset(78) - body's margin(8) | |
| 990 EXPECT_THAT(LayoutUnit(left_float_with_margin_block_offset - 8), | |
| 991 left_float_with_margin_fragment->TopOffset()); | |
| 992 // 10 = left_float_with_margin_inline_offset(18) - body's margin(8) | |
| 993 EXPECT_THAT(LayoutUnit(left_float_with_margin_inline_offset - 8), | |
| 994 left_float_with_margin_fragment->LeftOffset()); | |
| 995 | |
| 996 // ** Verify exclusions ** | |
| 997 NGLogicalSize left_float_exclusion_size = {LayoutUnit(30), LayoutUnit(30)}; | |
| 998 // this should be equal to body's margin(8) | |
| 999 NGLogicalOffset left_float_exclusion_offset = {LayoutUnit(8), LayoutUnit(8)}; | |
| 1000 NGLogicalRect left_float_exclusion_rect = {left_float_exclusion_offset, | |
| 1001 left_float_exclusion_size}; | |
| 1002 NGExclusion left_float_exclusion = {left_float_exclusion_rect, | |
| 1003 NGExclusion::kFloatLeft}; | |
| 1004 | |
| 1005 NGLogicalSize left_wide_exclusion_size = {LayoutUnit(180), LayoutUnit(30)}; | |
| 1006 NGLogicalOffset left_wide_exclusion_offset = { | |
| 1007 LayoutUnit(8), LayoutUnit(left_wide_float_block_offset)}; | |
| 1008 NGLogicalRect left_wide_exclusion_rect = {left_wide_exclusion_offset, | |
| 1009 left_wide_exclusion_size}; | |
| 1010 NGExclusion left_wide_exclusion = {left_wide_exclusion_rect, | |
| 1011 NGExclusion::kFloatLeft}; | |
| 1012 | |
| 1013 NGLogicalSize right_float_exclusion_size = {LayoutUnit(50), LayoutUnit(50)}; | |
| 1014 NGLogicalOffset right_float_exclusion_offset = { | |
| 1015 LayoutUnit(right_float_inline_offset), | |
| 1016 LayoutUnit(right_float_block_offset)}; | |
| 1017 NGLogicalRect right_float_exclusion_rect = {right_float_exclusion_offset, | |
| 1018 right_float_exclusion_size}; | |
| 1019 NGExclusion right_float_exclusion = {right_float_exclusion_rect, | |
| 1020 NGExclusion::kFloatRight}; | |
| 1021 | |
| 1022 // left-float-with-margin's size(120) + margin(2x10) | |
| 1023 NGLogicalSize left_float_with_margin_exclusion_size = {LayoutUnit(140), | |
| 1024 LayoutUnit(140)}; | |
| 1025 // Exclusion starts from the right_float_block_offset position. | |
| 1026 NGLogicalOffset left_float_with_margin_exclusion_offset = { | |
| 1027 LayoutUnit(8), LayoutUnit(right_float_block_offset)}; | |
| 1028 NGLogicalRect left_float_with_margin_exclusion_rect = { | |
| 1029 left_float_with_margin_exclusion_offset, | |
| 1030 left_float_with_margin_exclusion_size}; | |
| 1031 NGExclusion left_float_with_margin_exclusion = { | |
| 1032 left_float_with_margin_exclusion_rect, NGExclusion::kFloatLeft}; | |
| 1033 | |
| 1034 EXPECT_THAT( | |
| 1035 space->Exclusions()->storage, | |
| 1036 (ElementsAre(Pointee(left_float_exclusion), Pointee(left_wide_exclusion), | |
| 1037 Pointee(right_float_exclusion), | |
| 1038 Pointee(left_float_with_margin_exclusion)))); | |
| 1039 } | |
| 1040 | |
| 727 // Verifies that NG block layout algorithm respects "clear" CSS property. | 1041 // Verifies that NG block layout algorithm respects "clear" CSS property. |
| 728 // | 1042 // TODO(glebl): Enable with new the float/margins collapsing algorithm. |
| 729 // Test case's HTML representation: | 1043 TEST_F(NGBlockLayoutAlgorithmTest, DISABLED_PositionFragmentsWithClear) { |
| 730 // <div id="parent" style="width: 200px; height: 200px;"> | 1044 setBodyInnerHTML( |
| 731 // <div style="float: left; width: 30px; height: 30px;"/> <!-- DIV1 --> | 1045 "<style>" |
| 732 // <div style="float: right; width: 40px; height: 40px; | 1046 " #container {" |
| 733 // clear: left;"/> <!-- DIV2 --> | 1047 " height: 200px;" |
| 734 // <div style="clear: ...; width: 50px; height: 50px;"/> <!-- DIV3 --> | 1048 " width: 200px;" |
| 735 // </div> | 1049 " }" |
| 736 // | 1050 " #float-left {" |
| 737 // Expected: | 1051 " background-color: red;" |
| 738 // - DIV2 is positioned below DIV1 because it has clear: left; | 1052 " float: left;" |
| 739 // - DIV3 is positioned below DIV1 if clear: left; | 1053 " height: 30px;" |
| 740 // - DIV3 is positioned below DIV2 if clear: right; | 1054 " width: 30px;" |
| 741 // - DIV3 is positioned below DIV2 if clear: both; | 1055 " }" |
| 742 TEST_F(NGBlockLayoutAlgorithmTest, PositionFragmentsWithClear) { | 1056 " #float-right {" |
| 743 const int kParentSize = 200; | 1057 " background-color: blue;" |
| 744 const int kDiv1Size = 30; | 1058 " float: right;" |
| 745 const int kDiv2Size = 40; | 1059 " height: 170px;" |
| 746 const int kDiv3Size = 50; | 1060 " width: 40px;" |
| 747 | 1061 " }" |
| 748 style_->setHeight(Length(kParentSize, Fixed)); | 1062 " #clearance {" |
| 749 style_->setWidth(Length(kParentSize, Fixed)); | 1063 " background-color: yellow;" |
| 750 | 1064 " height: 60px;" |
| 751 // DIV1 | 1065 " width: 60px;" |
| 752 RefPtr<ComputedStyle> div1_style = ComputedStyle::create(); | 1066 " margin: 20px;" |
| 753 div1_style->setWidth(Length(kDiv1Size, Fixed)); | 1067 " }" |
| 754 div1_style->setHeight(Length(kDiv1Size, Fixed)); | 1068 " #block {" |
| 755 div1_style->setFloating(EFloat::kLeft); | 1069 " margin: 40px;" |
| 756 NGBlockNode* div1 = new NGBlockNode(div1_style.get()); | 1070 " background-color: black;" |
| 757 | 1071 " height: 60px;" |
| 758 // DIV2 | 1072 " width: 60px;" |
| 759 RefPtr<ComputedStyle> div2_style = ComputedStyle::create(); | 1073 " }" |
| 760 div2_style->setWidth(Length(kDiv2Size, Fixed)); | 1074 " #adjoining-clearance {" |
| 761 div2_style->setHeight(Length(kDiv2Size, Fixed)); | 1075 " background-color: green;" |
| 762 div2_style->setClear(EClear::ClearLeft); | 1076 " clear: left;" |
| 763 div2_style->setFloating(EFloat::kRight); | 1077 " height: 20px;" |
| 764 NGBlockNode* div2 = new NGBlockNode(div2_style.get()); | 1078 " width: 20px;" |
| 765 | 1079 " margin: 30px;" |
| 766 // DIV3 | 1080 " }" |
| 767 RefPtr<ComputedStyle> div3_style = ComputedStyle::create(); | 1081 "</style>" |
| 768 div3_style->setWidth(Length(kDiv3Size, Fixed)); | 1082 "<div id='container'>" |
| 769 div3_style->setHeight(Length(kDiv3Size, Fixed)); | 1083 " <div id='float-left'></div>" |
| 770 NGBlockNode* div3 = new NGBlockNode(div3_style.get()); | 1084 " <div id='float-right'></div>" |
| 771 | 1085 " <div id='clearance'></div>" |
| 772 div1->SetNextSibling(div2); | 1086 " <div id='block'></div>" |
| 773 div2->SetNextSibling(div3); | 1087 " <div id='adjoining-clearance'></div>" |
| 774 | 1088 "</div>"); |
| 775 // clear: left; | 1089 |
| 776 div3_style->setClear(EClear::ClearLeft); | 1090 const NGPhysicalBoxFragment* clerance_fragment; |
| 777 auto* space = ConstructConstraintSpace( | 1091 const NGPhysicalBoxFragment* body_fragment; |
| 778 kHorizontalTopBottom, TextDirection::kLtr, | 1092 const NGPhysicalBoxFragment* container_fragment; |
| 779 NGLogicalSize(LayoutUnit(kParentSize), LayoutUnit(kParentSize))); | 1093 const NGPhysicalBoxFragment* block_fragment; |
| 780 NGPhysicalBoxFragment* frag = RunBlockLayoutAlgorithm(space, div1); | 1094 const NGPhysicalBoxFragment* adjoining_clearance_fragment; |
| 781 const NGPhysicalFragment* child3 = frag->Children()[2]; | 1095 auto run_with_clearance = [&](EClear clear_value) { |
| 782 EXPECT_EQ(kDiv1Size, child3->TopOffset()); | 1096 NGPhysicalBoxFragment* fragment; |
| 783 | 1097 Element* el_with_clear = document().getElementById("clearance"); |
| 784 // clear: right; | 1098 el_with_clear->mutableComputedStyle()->setClear(clear_value); |
| 785 div3_style->setClear(EClear::ClearRight); | 1099 std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement( |
| 786 space = ConstructConstraintSpace( | 1100 document().getElementsByTagName("html")->item(0)); |
| 787 kHorizontalTopBottom, TextDirection::kLtr, | 1101 ASSERT_EQ(1UL, fragment->Children().size()); |
| 788 NGLogicalSize(LayoutUnit(kParentSize), LayoutUnit(kParentSize))); | 1102 body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0]); |
| 789 frag = RunBlockLayoutAlgorithm(space, div1); | 1103 container_fragment = toNGPhysicalBoxFragment(body_fragment->Children()[0]); |
| 790 child3 = frag->Children()[2]; | 1104 ASSERT_EQ(3UL, container_fragment->Children().size()); |
| 791 EXPECT_EQ(kDiv1Size + kDiv2Size, child3->TopOffset()); | 1105 clerance_fragment = |
| 792 | 1106 toNGPhysicalBoxFragment(container_fragment->Children()[0]); |
| 793 // clear: both; | 1107 block_fragment = toNGPhysicalBoxFragment(container_fragment->Children()[1]); |
| 794 div3_style->setClear(EClear::ClearBoth); | 1108 adjoining_clearance_fragment = |
| 795 space = ConstructConstraintSpace( | 1109 toNGPhysicalBoxFragment(container_fragment->Children()[2]); |
| 796 kHorizontalTopBottom, TextDirection::kLtr, | 1110 }; |
| 797 NGLogicalSize(LayoutUnit(kParentSize), LayoutUnit(kParentSize))); | 1111 |
| 798 frag = RunBlockLayoutAlgorithm(space, div1); | 1112 // clear: none |
| 799 space = ConstructConstraintSpace( | 1113 run_with_clearance(EClear::ClearNone); |
| 800 kHorizontalTopBottom, TextDirection::kLtr, | 1114 // 20 = std::max(body's margin 8, clearance's margins 20) |
| 801 NGLogicalSize(LayoutUnit(kParentSize), LayoutUnit(kParentSize))); | 1115 EXPECT_EQ(LayoutUnit(20), body_fragment->TopOffset()); |
| 802 child3 = frag->Children()[2]; | 1116 EXPECT_EQ(LayoutUnit(0), container_fragment->TopOffset()); |
| 803 EXPECT_EQ(kDiv1Size + kDiv2Size, child3->TopOffset()); | 1117 // 0 = collapsed margins |
| 1118 EXPECT_EQ(LayoutUnit(0), clerance_fragment->TopOffset()); | |
| 1119 // 100 = clearance's height 60 + | |
| 1120 // std::max(clearance's margins 20, block's margins 40) | |
| 1121 EXPECT_EQ(LayoutUnit(100), block_fragment->TopOffset()); | |
| 1122 // 200 = 100 + block's height 60 + max(adjoining_clearance's margins 30, | |
| 1123 // block's margins 40) | |
| 1124 EXPECT_EQ(LayoutUnit(200), adjoining_clearance_fragment->TopOffset()); | |
| 1125 | |
| 1126 // clear: right | |
| 1127 run_with_clearance(EClear::ClearRight); | |
| 1128 // 8 = body's margin. This doesn't collapse its margins with 'clearance' block | |
| 1129 // as it's not an adjoining block to body. | |
| 1130 EXPECT_EQ(LayoutUnit(8), body_fragment->TopOffset()); | |
| 1131 EXPECT_EQ(LayoutUnit(0), container_fragment->TopOffset()); | |
| 1132 // 170 = float-right's height | |
| 1133 EXPECT_EQ(LayoutUnit(170), clerance_fragment->TopOffset()); | |
| 1134 // 270 = float-right's height + clearance's height 60 + | |
| 1135 // max(clearance's margin 20, block margin 40) | |
| 1136 EXPECT_EQ(LayoutUnit(270), block_fragment->TopOffset()); | |
| 1137 // 370 = block's offset 270 + block's height 60 + | |
| 1138 // std::max(block's margin 40, adjoining_clearance's margin 30) | |
| 1139 EXPECT_EQ(LayoutUnit(370), adjoining_clearance_fragment->TopOffset()); | |
| 1140 | |
| 1141 // clear: left | |
| 1142 run_with_clearance(EClear::ClearLeft); | |
| 1143 // 8 = body's margin. This doesn't collapse its margins with 'clearance' block | |
| 1144 // as it's not an adjoining block to body. | |
| 1145 EXPECT_EQ(LayoutUnit(8), body_fragment->TopOffset()); | |
| 1146 EXPECT_EQ(LayoutUnit(0), container_fragment->TopOffset()); | |
| 1147 // 30 = float_left's height | |
| 1148 EXPECT_EQ(LayoutUnit(30), clerance_fragment->TopOffset()); | |
| 1149 // 130 = float_left's height + clearance's height 60 + | |
| 1150 // max(clearance's margin 20, block margin 40) | |
| 1151 EXPECT_EQ(LayoutUnit(130), block_fragment->TopOffset()); | |
| 1152 // 230 = block's offset 130 + block's height 60 + | |
| 1153 // std::max(block's margin 40, adjoining_clearance's margin 30) | |
| 1154 EXPECT_EQ(LayoutUnit(230), adjoining_clearance_fragment->TopOffset()); | |
| 1155 | |
| 1156 // clear: both | |
| 1157 // same as clear: right | |
| 1158 run_with_clearance(EClear::ClearBoth); | |
| 1159 EXPECT_EQ(LayoutUnit(8), body_fragment->TopOffset()); | |
| 1160 EXPECT_EQ(LayoutUnit(0), container_fragment->TopOffset()); | |
| 1161 EXPECT_EQ(LayoutUnit(170), clerance_fragment->TopOffset()); | |
| 1162 EXPECT_EQ(LayoutUnit(270), block_fragment->TopOffset()); | |
| 1163 EXPECT_EQ(LayoutUnit(370), adjoining_clearance_fragment->TopOffset()); | |
| 804 } | 1164 } |
| 805 | 1165 |
| 806 // Verifies that we compute the right min and max-content size. | 1166 // Verifies that we compute the right min and max-content size. |
| 807 TEST_F(NGBlockLayoutAlgorithmTest, ComputeMinMaxContent) { | 1167 TEST_F(NGBlockLayoutAlgorithmTest, ComputeMinMaxContent) { |
| 808 const int kWidth = 50; | 1168 const int kWidth = 50; |
| 809 const int kWidthChild1 = 20; | 1169 const int kWidthChild1 = 20; |
| 810 const int kWidthChild2 = 30; | 1170 const int kWidthChild2 = 30; |
| 811 | 1171 |
| 812 // This should have no impact on the min/max content size. | 1172 // This should have no impact on the min/max content size. |
| 813 style_->setWidth(Length(kWidth, Fixed)); | 1173 style_->setWidth(Length(kWidth, Fixed)); |
| (...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1563 EXPECT_EQ(LayoutUnit(194), fragment->LeftOffset()); | 1923 EXPECT_EQ(LayoutUnit(194), fragment->LeftOffset()); |
| 1564 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | 1924 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); |
| 1565 EXPECT_EQ(LayoutUnit(16), fragment->Width()); | 1925 EXPECT_EQ(LayoutUnit(16), fragment->Width()); |
| 1566 EXPECT_EQ(LayoutUnit(50), fragment->Height()); | 1926 EXPECT_EQ(LayoutUnit(50), fragment->Height()); |
| 1567 EXPECT_EQ(0UL, fragment->Children().size()); | 1927 EXPECT_EQ(0UL, fragment->Children().size()); |
| 1568 EXPECT_FALSE(iterator.NextChild()); | 1928 EXPECT_FALSE(iterator.NextChild()); |
| 1569 } | 1929 } |
| 1570 | 1930 |
| 1571 } // namespace | 1931 } // namespace |
| 1572 } // namespace blink | 1932 } // namespace blink |
| OLD | NEW |