| 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" | 7 #include "core/dom/NodeComputedStyle.h" |
| 8 #include "core/dom/TagCollection.h" | 8 #include "core/dom/TagCollection.h" |
| 9 #include "core/layout/ng/layout_ng_block_flow.h" | 9 #include "core/layout/ng/layout_ng_block_flow.h" |
| 10 #include "core/layout/ng/ng_block_node.h" | 10 #include "core/layout/ng/ng_block_node.h" |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 child = static_cast<const NGPhysicalBoxFragment*>(child)->Children()[0].get(); | 188 child = static_cast<const NGPhysicalBoxFragment*>(child)->Children()[0].get(); |
| 189 | 189 |
| 190 EXPECT_EQ(kHeight, child->Height()); | 190 EXPECT_EQ(kHeight, child->Height()); |
| 191 EXPECT_EQ(0, child->TopOffset()); | 191 EXPECT_EQ(0, child->TopOffset()); |
| 192 EXPECT_EQ(kMarginLeft, child->LeftOffset()); | 192 EXPECT_EQ(kMarginLeft, child->LeftOffset()); |
| 193 } | 193 } |
| 194 | 194 |
| 195 // Verifies that floats are positioned at the top of the first child that can | 195 // Verifies that floats are positioned at the top of the first child that can |
| 196 // determine its position after margins collapsed. | 196 // determine its position after margins collapsed. |
| 197 TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase1WithFloats) { | 197 TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase1WithFloats) { |
| 198 setBodyInnerHTML( | 198 setBodyInnerHTML(R"HTML( |
| 199 "<style>" | 199 <style> |
| 200 " #container {" | 200 #container { |
| 201 " height: 200px;" | 201 height: 200px; |
| 202 " width: 200px;" | 202 width: 200px; |
| 203 " margin-top: 10px;" | 203 margin-top: 10px; |
| 204 " padding: 0 7px;" | 204 padding: 0 7px; |
| 205 " background-color: red;" | 205 background-color: red; |
| 206 " }" | 206 } |
| 207 " #first-child {" | 207 #first-child { |
| 208 " margin-top: 20px;" | 208 margin-top: 20px; |
| 209 " height: 10px;" | 209 height: 10px; |
| 210 " background-color: blue;" | 210 background-color: blue; |
| 211 " }" | 211 } |
| 212 " #float-child-left {" | 212 #float-child-left { |
| 213 " float: left;" | 213 float: left; |
| 214 " height: 10px;" | 214 height: 10px; |
| 215 " width: 10px;" | 215 width: 10px; |
| 216 " padding: 10px;" | 216 padding: 10px; |
| 217 " margin: 10px;" | 217 margin: 10px; |
| 218 " background-color: green;" | 218 background-color: green; |
| 219 " }" | 219 } |
| 220 " #float-child-right {" | 220 #float-child-right { |
| 221 " float: right;" | 221 float: right; |
| 222 " height: 30px;" | 222 height: 30px; |
| 223 " width: 30px;" | 223 width: 30px; |
| 224 " background-color: pink;" | 224 background-color: pink; |
| 225 " }" | 225 } |
| 226 "</style>" | 226 </style> |
| 227 "<div id='container'>" | 227 <div id='container'> |
| 228 " <div id='float-child-left'></div>" | 228 <div id='float-child-left'></div> |
| 229 " <div id='float-child-right'></div>" | 229 <div id='float-child-right'></div> |
| 230 " <div id='first-child'></div>" | 230 <div id='first-child'></div> |
| 231 "</div>"); | 231 </div> |
| 232 )HTML"); |
| 232 | 233 |
| 233 // ** Run LayoutNG algorithm ** | 234 // ** Run LayoutNG algorithm ** |
| 234 NGConstraintSpace* space; | 235 NGConstraintSpace* space; |
| 235 RefPtr<NGPhysicalBoxFragment> fragment; | 236 RefPtr<NGPhysicalBoxFragment> fragment; |
| 236 std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement( | 237 std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement( |
| 237 document().getElementsByTagName("html")->item(0)); | 238 document().getElementsByTagName("html")->item(0)); |
| 238 ASSERT_EQ(fragment->Children().size(), 1UL); | 239 ASSERT_EQ(fragment->Children().size(), 1UL); |
| 239 auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0].get()); | 240 auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0].get()); |
| 240 // 20 = max(first child's margin top, containers's margin top) | 241 // 20 = max(first child's margin top, containers's margin top) |
| 241 int body_top_offset = 20; | 242 int body_top_offset = 20; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 (ElementsAre(Pointee(expected_exclusion1), | 298 (ElementsAre(Pointee(expected_exclusion1), |
| 298 Pointee(expected_exclusion2)))); | 299 Pointee(expected_exclusion2)))); |
| 299 } | 300 } |
| 300 | 301 |
| 301 // Verifies the collapsing margins case for the next pairs: | 302 // Verifies the collapsing margins case for the next pairs: |
| 302 // - bottom margin of box and top margin of its next in-flow following sibling. | 303 // - bottom margin of box and top margin of its next in-flow following sibling. |
| 303 // - top and bottom margins of a box that does not establish a new block | 304 // - top and bottom margins of a box that does not establish a new block |
| 304 // formatting context and that has zero computed 'min-height', zero or 'auto' | 305 // formatting context and that has zero computed 'min-height', zero or 'auto' |
| 305 // computed 'height', and no in-flow children | 306 // computed 'height', and no in-flow children |
| 306 TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase2WithFloats) { | 307 TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase2WithFloats) { |
| 307 setBodyInnerHTML( | 308 setBodyInnerHTML(R"HTML( |
| 308 "<style>" | 309 <style> |
| 309 "#first-child {" | 310 #first-child { |
| 310 " background-color: red;" | 311 background-color: red; |
| 311 " height: 50px;" | 312 height: 50px; |
| 312 " margin-bottom: 20px;" | 313 margin-bottom: 20px; |
| 313 "}" | 314 } |
| 314 "#float-between-empties {" | 315 #float-between-empties { |
| 315 " background-color: green;" | 316 background-color: green; |
| 316 " float: left;" | 317 float: left; |
| 317 " height: 30px;" | 318 height: 30px; |
| 318 " width: 30px;" | 319 width: 30px; |
| 319 "}" | 320 } |
| 320 "#float-between-nonempties {" | 321 #float-between-nonempties { |
| 321 " background-color: lightgreen;" | 322 background-color: lightgreen; |
| 322 " float: left;" | 323 float: left; |
| 323 " height: 40px;" | 324 height: 40px; |
| 324 " width: 40px;" | 325 width: 40px; |
| 325 "}" | 326 } |
| 326 "#float-top-align {" | 327 #float-top-align { |
| 327 " background-color: seagreen;" | 328 background-color: seagreen; |
| 328 " float: left;" | 329 float: left; |
| 329 " height: 50px;" | 330 height: 50px; |
| 330 " width: 50px;" | 331 width: 50px; |
| 331 "}" | 332 } |
| 332 "#second-child {" | 333 #second-child { |
| 333 " background-color: blue;" | 334 background-color: blue; |
| 334 " height: 50px;" | 335 height: 50px; |
| 335 " margin-top: 10px;" | 336 margin-top: 10px; |
| 336 "}" | 337 } |
| 337 "</style>" | 338 </style> |
| 338 "<div id='first-child'>" | 339 <div id='first-child'> |
| 339 " <div id='empty1' style='margin-bottom: -15px'></div>" | 340 <div id='empty1' style='margin-bottom: -15px'></div> |
| 340 " <div id='float-between-empties'></div>" | 341 <div id='float-between-empties'></div> |
| 341 " <div id='empty2'></div>" | 342 <div id='empty2'></div> |
| 342 "</div>" | 343 </div> |
| 343 "<div id='float-between-nonempties'></div>" | 344 <div id='float-between-nonempties'></div> |
| 344 "<div id='second-child'>" | 345 <div id='second-child'> |
| 345 " <div id='float-top-align'></div>" | 346 <div id='float-top-align'></div> |
| 346 " <div id='empty3'></div>" | 347 <div id='empty3'></div> |
| 347 " <div id='empty4' style='margin-top: -30px'></div>" | 348 <div id='empty4' style='margin-top: -30px'></div> |
| 348 "</div>" | 349 </div> |
| 349 "<div id='empty5'></div>"); | 350 <div id='empty5'></div> |
| 351 )HTML"); |
| 350 | 352 |
| 351 // ** Run LayoutNG algorithm ** | 353 // ** Run LayoutNG algorithm ** |
| 352 NGConstraintSpace* space; | 354 NGConstraintSpace* space; |
| 353 RefPtr<NGPhysicalBoxFragment> fragment; | 355 RefPtr<NGPhysicalBoxFragment> fragment; |
| 354 std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement( | 356 std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement( |
| 355 document().getElementsByTagName("html")->item(0)); | 357 document().getElementsByTagName("html")->item(0)); |
| 356 | 358 |
| 357 auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0].get()); | 359 auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0].get()); |
| 358 // -7 = empty1's margin(-15) + body's margin(8) | 360 // -7 = empty1's margin(-15) + body's margin(8) |
| 359 int body_top_offset = -7; | 361 int body_top_offset = -7; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 EXPECT_THAT(space->Exclusions()->storage, | 430 EXPECT_THAT(space->Exclusions()->storage, |
| 429 (ElementsAre(Pointee(float_empties_exclusion), | 431 (ElementsAre(Pointee(float_empties_exclusion), |
| 430 Pointee(float_nonempties_exclusion), | 432 Pointee(float_nonempties_exclusion), |
| 431 Pointee(float_top_align_exclusion)))); | 433 Pointee(float_top_align_exclusion)))); |
| 432 } | 434 } |
| 433 | 435 |
| 434 // Verifies the collapsing margins case for the next pair: | 436 // Verifies the collapsing margins case for the next pair: |
| 435 // - bottom margin of a last in-flow child and bottom margin of its parent if | 437 // - bottom margin of a last in-flow child and bottom margin of its parent if |
| 436 // the parent has 'auto' computed height | 438 // the parent has 'auto' computed height |
| 437 TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase3) { | 439 TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase3) { |
| 438 setBodyInnerHTML( | 440 setBodyInnerHTML(R"HTML( |
| 439 "<style>" | 441 <style> |
| 440 " #container {" | 442 #container { |
| 441 " margin-bottom: 20px;" | 443 margin-bottom: 20px; |
| 442 " }" | 444 } |
| 443 " #child {" | 445 #child { |
| 444 " margin-bottom: 200px;" | 446 margin-bottom: 200px; |
| 445 " height: 50px;" | 447 height: 50px; |
| 446 " }" | 448 } |
| 447 "</style>" | 449 </style> |
| 448 "<div id='container'>" | 450 <div id='container'> |
| 449 " <div id='child'></div>" | 451 <div id='child'></div> |
| 450 "</div>"); | 452 </div> |
| 453 )HTML"); |
| 451 | 454 |
| 452 const NGPhysicalBoxFragment* body_fragment; | 455 const NGPhysicalBoxFragment* body_fragment; |
| 453 const NGPhysicalBoxFragment* container_fragment; | 456 const NGPhysicalBoxFragment* container_fragment; |
| 454 const NGPhysicalBoxFragment* child_fragment; | 457 const NGPhysicalBoxFragment* child_fragment; |
| 455 RefPtr<const NGPhysicalBoxFragment> fragment; | 458 RefPtr<const NGPhysicalBoxFragment> fragment; |
| 456 auto run_test = [&](const Length& container_height) { | 459 auto run_test = [&](const Length& container_height) { |
| 457 Element* container = document().getElementById("container"); | 460 Element* container = document().getElementById("container"); |
| 458 container->mutableComputedStyle()->setHeight(container_height); | 461 container->mutableComputedStyle()->setHeight(container_height); |
| 459 std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement( | 462 std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement( |
| 460 document().getElementsByTagName("html")->item(0)); | 463 document().getElementsByTagName("html")->item(0)); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 479 run_test(Length(50, Fixed)); | 482 run_test(Length(50, Fixed)); |
| 480 // Margins are not collapsed, so fragment still has margins == 20. | 483 // Margins are not collapsed, so fragment still has margins == 20. |
| 481 // The fragment size 78 == body's margin 8 + child's height 50 + 20 | 484 // The fragment size 78 == body's margin 8 + child's height 50 + 20 |
| 482 EXPECT_EQ(NGPhysicalSize(LayoutUnit(800), LayoutUnit(78)), fragment->Size()); | 485 EXPECT_EQ(NGPhysicalSize(LayoutUnit(800), LayoutUnit(78)), fragment->Size()); |
| 483 EXPECT_EQ(NGMarginStrut(), container_fragment->EndMarginStrut()); | 486 EXPECT_EQ(NGMarginStrut(), container_fragment->EndMarginStrut()); |
| 484 } | 487 } |
| 485 | 488 |
| 486 // Verifies that 2 adjoining margins are not collapsed if there is padding or | 489 // Verifies that 2 adjoining margins are not collapsed if there is padding or |
| 487 // border that separates them. | 490 // border that separates them. |
| 488 TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase4) { | 491 TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase4) { |
| 489 setBodyInnerHTML( | 492 setBodyInnerHTML(R"HTML( |
| 490 "<style>" | 493 <style> |
| 491 " #container {" | 494 #container { |
| 492 " margin: 30px 0px;" | 495 margin: 30px 0px; |
| 493 " width: 200px;" | 496 width: 200px; |
| 494 " }" | 497 } |
| 495 " #child {" | 498 #child { |
| 496 " margin: 200px 0px;" | 499 margin: 200px 0px; |
| 497 " height: 50px;" | 500 height: 50px; |
| 498 " background-color: blue;" | 501 background-color: blue; |
| 499 " }" | 502 } |
| 500 "</style>" | 503 </style> |
| 501 "<div id='container'>" | 504 <div id='container'> |
| 502 " <div id='child'></div>" | 505 <div id='child'></div> |
| 503 "</div>"); | 506 </div> |
| 507 )HTML"); |
| 504 | 508 |
| 505 const NGPhysicalBoxFragment* body_fragment; | 509 const NGPhysicalBoxFragment* body_fragment; |
| 506 const NGPhysicalBoxFragment* container_fragment; | 510 const NGPhysicalBoxFragment* container_fragment; |
| 507 const NGPhysicalBoxFragment* child_fragment; | 511 const NGPhysicalBoxFragment* child_fragment; |
| 508 RefPtr<const NGPhysicalBoxFragment> fragment; | 512 RefPtr<const NGPhysicalBoxFragment> fragment; |
| 509 auto run_test = [&](const Length& container_padding_top) { | 513 auto run_test = [&](const Length& container_padding_top) { |
| 510 Element* container = document().getElementById("container"); | 514 Element* container = document().getElementById("container"); |
| 511 container->mutableComputedStyle()->setPaddingTop(container_padding_top); | 515 container->mutableComputedStyle()->setPaddingTop(container_padding_top); |
| 512 std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement( | 516 std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement( |
| 513 document().getElementsByTagName("html")->item(0)); | 517 document().getElementsByTagName("html")->item(0)); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 537 EXPECT_EQ(NGPhysicalSize(LayoutUnit(800), LayoutUnit(450)), fragment->Size()); | 541 EXPECT_EQ(NGPhysicalSize(LayoutUnit(800), LayoutUnit(450)), fragment->Size()); |
| 538 // 200 = (body's margin 8, container's margin 30, child's margin 200) | 542 // 200 = (body's margin 8, container's margin 30, child's margin 200) |
| 539 EXPECT_EQ(LayoutUnit(200), body_fragment->TopOffset()); | 543 EXPECT_EQ(LayoutUnit(200), body_fragment->TopOffset()); |
| 540 // 0 = collapsed margins | 544 // 0 = collapsed margins |
| 541 EXPECT_EQ(LayoutUnit(0), child_fragment->TopOffset()); | 545 EXPECT_EQ(LayoutUnit(0), child_fragment->TopOffset()); |
| 542 } | 546 } |
| 543 | 547 |
| 544 // Verifies that margins of 2 adjoining blocks with different writing modes | 548 // Verifies that margins of 2 adjoining blocks with different writing modes |
| 545 // get collapsed. | 549 // get collapsed. |
| 546 TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase5) { | 550 TEST_F(NGBlockLayoutAlgorithmTest, CollapsingMarginsCase5) { |
| 547 setBodyInnerHTML( | 551 setBodyInnerHTML(R"HTML( |
| 548 "<style>" | 552 <style> |
| 549 // TODO(glebl): Remove the fixed height | 553 #container { |
| 550 // Fix this once min/max algorithm handles orthogonal children. | 554 margin-top: 10px; |
| 551 " body {" | 555 writing-mode: vertical-lr; |
| 552 " height: 500px;" | 556 } |
| 553 " }" | 557 #vertical { |
| 554 " #container {" | 558 margin-right: 90px; |
| 555 " margin-top: 10px;" | 559 background-color: red; |
| 556 // TODO(glebl): Remove the fixed height | 560 height: 70px; |
| 557 // Fix this once min/max algorithm handles orthogonal children. | 561 width: 30px; |
| 558 " width: 500px;" | 562 } |
| 559 " writing-mode: vertical-lr;" | 563 #horizontal { |
| 560 " }" | 564 background-color: blue; |
| 561 " #vertical {" | 565 margin-left: 100px; |
| 562 " margin-right: 90px;" | 566 writing-mode: horizontal-tb; |
| 563 " background-color: red;" | 567 height: 60px; |
| 564 " height: 70px;" | 568 width: 30px; |
| 565 " width: 30px;" | 569 } |
| 566 " }" | 570 </style> |
| 567 " #horizontal {" | 571 <div id='container'> |
| 568 " background-color: blue;" | 572 <div id='vertical'></div> |
| 569 " margin-left: 100px;" | 573 <div id='horizontal'></div> |
| 570 " writing-mode: horizontal-tb;" | 574 </div> |
| 571 " height: 60px;" | 575 )HTML"); |
| 572 " width: 30px;" | |
| 573 " }" | |
| 574 "</style>" | |
| 575 "<div id='container'>" | |
| 576 " <div id='vertical'></div>" | |
| 577 " <div id='horizontal'></div>" | |
| 578 "</div>"); | |
| 579 RefPtr<NGPhysicalBoxFragment> fragment; | 576 RefPtr<NGPhysicalBoxFragment> fragment; |
| 580 std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement( | 577 std::tie(fragment, std::ignore) = RunBlockLayoutAlgorithmForElement( |
| 581 document().getElementsByTagName("html")->item(0)); | 578 document().getElementsByTagName("html")->item(0)); |
| 582 | 579 |
| 583 // body | 580 // body |
| 584 auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0].get()); | 581 auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0].get()); |
| 585 // 10 = std::max(body's margin 8, container's margin top) | 582 // 10 = std::max(body's margin 8, container's margin top) |
| 586 int body_top_offset = 10; | 583 int body_top_offset = 10; |
| 587 EXPECT_THAT(body_fragment->TopOffset(), LayoutUnit(body_top_offset)); | 584 EXPECT_THAT(body_fragment->TopOffset(), LayoutUnit(body_top_offset)); |
| 588 int body_left_offset = 8; | 585 int body_left_offset = 8; |
| 589 EXPECT_THAT(body_fragment->LeftOffset(), LayoutUnit(body_left_offset)); | 586 EXPECT_THAT(body_fragment->LeftOffset(), LayoutUnit(body_left_offset)); |
| 590 // height = 70. std::max(vertical height's 70, horizontal's height's 60) | 587 // height = 70. std::max(vertical height's 70, horizontal's height's 60) |
| 591 // TODO(glebl): Should be 70! Fix this once min/max algorithm handles | 588 // TODO(glebl): Should be 70! Fix this once min/max algorithm handles |
| 592 // orthogonal children. | 589 // orthogonal children. |
| 593 int body_fragment_block_size = 500; | 590 int body_fragment_block_size = 130; |
| 594 ASSERT_EQ( | 591 ASSERT_EQ( |
| 595 NGPhysicalSize(LayoutUnit(784), LayoutUnit(body_fragment_block_size)), | 592 NGPhysicalSize(LayoutUnit(784), LayoutUnit(body_fragment_block_size)), |
| 596 body_fragment->Size()); | 593 body_fragment->Size()); |
| 597 ASSERT_EQ(1UL, body_fragment->Children().size()); | 594 ASSERT_EQ(1UL, body_fragment->Children().size()); |
| 598 | 595 |
| 599 // container | 596 // container |
| 600 auto* container_fragment = | 597 auto* container_fragment = |
| 601 toNGPhysicalBoxFragment(body_fragment->Children()[0].get()); | 598 toNGPhysicalBoxFragment(body_fragment->Children()[0].get()); |
| 602 // Container's margins are collapsed with body's fragment. | 599 // Container's margins are collapsed with body's fragment. |
| 603 EXPECT_THAT(container_fragment->TopOffset(), LayoutUnit()); | 600 EXPECT_THAT(container_fragment->TopOffset(), LayoutUnit()); |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 806 | 803 |
| 807 const NGPhysicalFragment* child = frag->Children()[0].get(); | 804 const NGPhysicalFragment* child = frag->Children()[0].get(); |
| 808 EXPECT_EQ(LayoutUnit(kChildWidth), child->Width()); | 805 EXPECT_EQ(LayoutUnit(kChildWidth), child->Width()); |
| 809 EXPECT_EQ(LayoutUnit(kPaddingLeft + 10), child->LeftOffset()); | 806 EXPECT_EQ(LayoutUnit(kPaddingLeft + 10), child->LeftOffset()); |
| 810 EXPECT_EQ(LayoutUnit(0), child->TopOffset()); | 807 EXPECT_EQ(LayoutUnit(0), child->TopOffset()); |
| 811 } | 808 } |
| 812 | 809 |
| 813 // Verifies that floats can be correctly positioned if they are inside of nested | 810 // Verifies that floats can be correctly positioned if they are inside of nested |
| 814 // empty blocks. | 811 // empty blocks. |
| 815 TEST_F(NGBlockLayoutAlgorithmTest, PositionFloatInsideEmptyBlocks) { | 812 TEST_F(NGBlockLayoutAlgorithmTest, PositionFloatInsideEmptyBlocks) { |
| 816 setBodyInnerHTML( | 813 setBodyInnerHTML(R"HTML( |
| 817 "<!DOCTYPE html>" | 814 <style> |
| 818 "<style>" | 815 #container { |
| 819 " #container {" | 816 height: 200px; |
| 820 " height: 200px;" | 817 width: 200px; |
| 821 " width: 200px;" | 818 } |
| 822 " }" | 819 #empty1 { |
| 823 " #empty1 {" | 820 margin: 20px; |
| 824 " margin: 20px;" | 821 padding: 0 20px; |
| 825 " padding: 0 20px;" | 822 } |
| 826 " }" | 823 #empty2 { |
| 827 " #empty2 {" | 824 margin: 15px; |
| 828 " margin: 15px;" | 825 padding: 0 15px; |
| 829 " padding: 0 15px;" | 826 } |
| 830 " }" | 827 #float { |
| 831 " #float {" | 828 float: left; |
| 832 " float: left;" | 829 height: 5px; |
| 833 " height: 5px;" | 830 width: 5px; |
| 834 " width: 5px;" | 831 padding: 10px; |
| 835 " padding: 10px;" | 832 margin: 10px; |
| 836 " margin: 10px;" | 833 background-color: green; |
| 837 " background-color: green;" | 834 } |
| 838 " }" | 835 </style> |
| 839 "</style>" | 836 <div id='container'> |
| 840 "<div id='container'>" | 837 <div id='empty1'> |
| 841 " <div id='empty1'>" | 838 <div id='empty2'> |
| 842 " <div id='empty2'>" | 839 <div id='float'></div> |
| 843 " <div id='float'></div>" | 840 </div> |
| 844 " </div>" | 841 </div> |
| 845 " </div>" | 842 </div> |
| 846 "</div>"); | 843 )HTML"); |
| 847 | 844 |
| 848 // ** Run LayoutNG algorithm ** | 845 // ** Run LayoutNG algorithm ** |
| 849 NGConstraintSpace* space; | 846 NGConstraintSpace* space; |
| 850 RefPtr<NGPhysicalBoxFragment> fragment; | 847 RefPtr<NGPhysicalBoxFragment> fragment; |
| 851 std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement( | 848 std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement( |
| 852 document().getElementsByTagName("html")->item(0)); | 849 document().getElementsByTagName("html")->item(0)); |
| 853 | 850 |
| 854 auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0].get()); | 851 auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0].get()); |
| 855 // 20 = std::max(empty1's margin, empty2's margin, body's margin) | 852 // 20 = std::max(empty1's margin, empty2's margin, body's margin) |
| 856 int body_top_offset = 20; | 853 int body_top_offset = 20; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 905 ASSERT_TRUE(floating_object->isPlaced()); | 902 ASSERT_TRUE(floating_object->isPlaced()); |
| 906 // 80 = float_inline_offset(25) + accumulative offset of empty blocks(35 + 20) | 903 // 80 = float_inline_offset(25) + accumulative offset of empty blocks(35 + 20) |
| 907 EXPECT_THAT(LayoutUnit(80), floating_object->x()); | 904 EXPECT_THAT(LayoutUnit(80), floating_object->x()); |
| 908 // 10 = float's padding | 905 // 10 = float's padding |
| 909 EXPECT_THAT(LayoutUnit(10), floating_object->y()); | 906 EXPECT_THAT(LayoutUnit(10), floating_object->y()); |
| 910 } | 907 } |
| 911 | 908 |
| 912 // Verifies that left/right floating and regular blocks can be positioned | 909 // Verifies that left/right floating and regular blocks can be positioned |
| 913 // correctly by the algorithm. | 910 // correctly by the algorithm. |
| 914 TEST_F(NGBlockLayoutAlgorithmTest, PositionFloatFragments) { | 911 TEST_F(NGBlockLayoutAlgorithmTest, PositionFloatFragments) { |
| 915 setBodyInnerHTML( | 912 setBodyInnerHTML(R"HTML( |
| 916 "<style>" | 913 <style> |
| 917 " #container {" | 914 #container { |
| 918 " height: 200px;" | 915 height: 200px; |
| 919 " width: 200px;" | 916 width: 200px; |
| 920 " }" | 917 } |
| 921 " #left-float {" | 918 #left-float { |
| 922 " background-color: red;" | 919 background-color: red; |
| 923 " float:left;" | 920 float: left; |
| 924 " height: 30px;" | 921 height: 30px; |
| 925 " width: 30px;" | 922 width: 30px; |
| 926 " }" | 923 } |
| 927 " #left-wide-float {" | 924 #left-wide-float { |
| 928 " background-color: greenyellow;" | 925 background-color: greenyellow; |
| 929 " float:left;" | 926 float: left; |
| 930 " height: 30px;" | 927 height: 30px; |
| 931 " width: 180px;" | 928 width: 180px; |
| 932 " }" | 929 } |
| 933 " #regular {" | 930 #regular { |
| 934 " width: 40px;" | 931 width: 40px; |
| 935 " height: 40px;" | 932 height: 40px; |
| 936 " background-color: green;" | 933 background-color: green; |
| 937 " }" | 934 } |
| 938 " #right-float {" | 935 #right-float { |
| 939 " background-color: cyan;" | 936 background-color: cyan; |
| 940 " float:right;" | 937 float: right; |
| 941 " width: 50px;" | 938 width: 50px; |
| 942 " height: 50px;" | 939 height: 50px; |
| 943 " }" | 940 } |
| 944 " #left-float-with-margin {" | 941 #left-float-with-margin { |
| 945 " background-color: black;" | 942 background-color: black; |
| 946 " float:left;" | 943 float: left; |
| 947 " height: 120px;" | 944 height: 120px; |
| 948 " margin: 10px;" | 945 margin: 10px; |
| 949 " width: 120px;" | 946 width: 120px; |
| 950 " }" | 947 } |
| 951 "</style>" | 948 </style> |
| 952 "<div id='container'>" | 949 <div id='container'> |
| 953 " <div id='left-float'></div>" | 950 <div id='left-float'></div> |
| 954 " <div id='left-wide-float'></div>" | 951 <div id='left-wide-float'></div> |
| 955 " <div id='regular'></div>" | 952 <div id='regular'></div> |
| 956 " <div id='right-float'></div>" | 953 <div id='right-float'></div> |
| 957 " <div id='left-float-with-margin'></div>" | 954 <div id='left-float-with-margin'></div> |
| 958 "</div>"); | 955 </div> |
| 956 )HTML"); |
| 959 | 957 |
| 960 // ** Run LayoutNG algorithm ** | 958 // ** Run LayoutNG algorithm ** |
| 961 NGConstraintSpace* space; | 959 NGConstraintSpace* space; |
| 962 RefPtr<NGPhysicalBoxFragment> fragment; | 960 RefPtr<NGPhysicalBoxFragment> fragment; |
| 963 std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement( | 961 std::tie(fragment, space) = RunBlockLayoutAlgorithmForElement( |
| 964 document().getElementsByTagName("html")->item(0)); | 962 document().getElementsByTagName("html")->item(0)); |
| 965 | 963 |
| 966 // ** Verify LayoutNG fragments and the list of positioned floats ** | 964 // ** Verify LayoutNG fragments and the list of positioned floats ** |
| 967 ASSERT_EQ(1UL, fragment->Children().size()); | 965 ASSERT_EQ(1UL, fragment->Children().size()); |
| 968 auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0].get()); | 966 auto* body_fragment = toNGPhysicalBoxFragment(fragment->Children()[0].get()); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1077 | 1075 |
| 1078 EXPECT_THAT( | 1076 EXPECT_THAT( |
| 1079 space->Exclusions()->storage, | 1077 space->Exclusions()->storage, |
| 1080 (ElementsAre(Pointee(left_float_exclusion), Pointee(left_wide_exclusion), | 1078 (ElementsAre(Pointee(left_float_exclusion), Pointee(left_wide_exclusion), |
| 1081 Pointee(right_float_exclusion), | 1079 Pointee(right_float_exclusion), |
| 1082 Pointee(left_float_with_margin_exclusion)))); | 1080 Pointee(left_float_with_margin_exclusion)))); |
| 1083 } | 1081 } |
| 1084 | 1082 |
| 1085 // Verifies that NG block layout algorithm respects "clear" CSS property. | 1083 // Verifies that NG block layout algorithm respects "clear" CSS property. |
| 1086 TEST_F(NGBlockLayoutAlgorithmTest, PositionFragmentsWithClear) { | 1084 TEST_F(NGBlockLayoutAlgorithmTest, PositionFragmentsWithClear) { |
| 1087 setBodyInnerHTML( | 1085 setBodyInnerHTML(R"HTML( |
| 1088 "<style>" | 1086 <style> |
| 1089 " #container {" | 1087 #container { |
| 1090 " height: 200px;" | 1088 height: 200px; |
| 1091 " width: 200px;" | 1089 width: 200px; |
| 1092 " }" | 1090 } |
| 1093 " #float-left {" | 1091 #float-left { |
| 1094 " background-color: red;" | 1092 background-color: red; |
| 1095 " float: left;" | 1093 float: left; |
| 1096 " height: 30px;" | 1094 height: 30px; |
| 1097 " width: 30px;" | 1095 width: 30px; |
| 1098 " }" | 1096 } |
| 1099 " #float-right {" | 1097 #float-right { |
| 1100 " background-color: blue;" | 1098 background-color: blue; |
| 1101 " float: right;" | 1099 float: right; |
| 1102 " height: 170px;" | 1100 height: 170px; |
| 1103 " width: 40px;" | 1101 width: 40px; |
| 1104 " }" | 1102 } |
| 1105 " #clearance {" | 1103 #clearance { |
| 1106 " background-color: yellow;" | 1104 background-color: yellow; |
| 1107 " height: 60px;" | 1105 height: 60px; |
| 1108 " width: 60px;" | 1106 width: 60px; |
| 1109 " margin: 20px;" | 1107 margin: 20px; |
| 1110 " }" | 1108 } |
| 1111 " #block {" | 1109 #block { |
| 1112 " margin: 40px;" | 1110 margin: 40px; |
| 1113 " background-color: black;" | 1111 background-color: black; |
| 1114 " height: 60px;" | 1112 height: 60px; |
| 1115 " width: 60px;" | 1113 width: 60px; |
| 1116 " }" | 1114 } |
| 1117 " #adjoining-clearance {" | 1115 #adjoining-clearance { |
| 1118 " background-color: green;" | 1116 background-color: green; |
| 1119 " clear: left;" | 1117 clear: left; |
| 1120 " height: 20px;" | 1118 height: 20px; |
| 1121 " width: 20px;" | 1119 width: 20px; |
| 1122 " margin: 30px;" | 1120 margin: 30px; |
| 1123 " }" | 1121 } |
| 1124 "</style>" | 1122 </style> |
| 1125 "<div id='container'>" | 1123 <div id='container'> |
| 1126 " <div id='float-left'></div>" | 1124 <div id='float-left'></div> |
| 1127 " <div id='float-right'></div>" | 1125 <div id='float-right'></div> |
| 1128 " <div id='clearance'></div>" | 1126 <div id='clearance'></div> |
| 1129 " <div id='block'></div>" | 1127 <div id='block'></div> |
| 1130 " <div id='adjoining-clearance'></div>" | 1128 <div id='adjoining-clearance'></div> |
| 1131 "</div>"); | 1129 </div> |
| 1130 )HTML"); |
| 1132 | 1131 |
| 1133 const NGPhysicalBoxFragment* clerance_fragment; | 1132 const NGPhysicalBoxFragment* clerance_fragment; |
| 1134 const NGPhysicalBoxFragment* body_fragment; | 1133 const NGPhysicalBoxFragment* body_fragment; |
| 1135 const NGPhysicalBoxFragment* container_fragment; | 1134 const NGPhysicalBoxFragment* container_fragment; |
| 1136 const NGPhysicalBoxFragment* block_fragment; | 1135 const NGPhysicalBoxFragment* block_fragment; |
| 1137 const NGPhysicalBoxFragment* adjoining_clearance_fragment; | 1136 const NGPhysicalBoxFragment* adjoining_clearance_fragment; |
| 1138 auto run_with_clearance = [&](EClear clear_value) { | 1137 auto run_with_clearance = [&](EClear clear_value) { |
| 1139 RefPtr<NGPhysicalBoxFragment> fragment; | 1138 RefPtr<NGPhysicalBoxFragment> fragment; |
| 1140 Element* el_with_clear = document().getElementById("clearance"); | 1139 Element* el_with_clear = document().getElementById("clearance"); |
| 1141 el_with_clear->mutableComputedStyle()->setClear(clear_value); | 1140 el_with_clear->mutableComputedStyle()->setClear(clear_value); |
| (...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2000 EXPECT_EQ(LayoutUnit(194), fragment->LeftOffset()); | 1999 EXPECT_EQ(LayoutUnit(194), fragment->LeftOffset()); |
| 2001 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); | 2000 EXPECT_EQ(LayoutUnit(), fragment->TopOffset()); |
| 2002 EXPECT_EQ(LayoutUnit(16), fragment->Width()); | 2001 EXPECT_EQ(LayoutUnit(16), fragment->Width()); |
| 2003 EXPECT_EQ(LayoutUnit(50), fragment->Height()); | 2002 EXPECT_EQ(LayoutUnit(50), fragment->Height()); |
| 2004 EXPECT_EQ(0UL, fragment->Children().size()); | 2003 EXPECT_EQ(0UL, fragment->Children().size()); |
| 2005 EXPECT_FALSE(iterator.NextChild()); | 2004 EXPECT_FALSE(iterator.NextChild()); |
| 2006 } | 2005 } |
| 2007 | 2006 |
| 2008 } // namespace | 2007 } // namespace |
| 2009 } // namespace blink | 2008 } // namespace blink |
| OLD | NEW |