| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2012 Apple Inc. All rights reserved. | 2 * Copyright (C) 2012 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 LayoutMultiColumnSet* newSet = LayoutMultiColumnSet::createAnonymous(*this,
multicolContainer->styleRef()); | 389 LayoutMultiColumnSet* newSet = LayoutMultiColumnSet::createAnonymous(*this,
multicolContainer->styleRef()); |
| 390 multicolContainer->LayoutBlock::addChild(newSet, insertBefore); | 390 multicolContainer->LayoutBlock::addChild(newSet, insertBefore); |
| 391 invalidateColumnSets(); | 391 invalidateColumnSets(); |
| 392 | 392 |
| 393 // We cannot handle immediate column set siblings (and there's no need for i
t, either). | 393 // We cannot handle immediate column set siblings (and there's no need for i
t, either). |
| 394 // There has to be at least one spanner separating them. | 394 // There has to be at least one spanner separating them. |
| 395 ASSERT(!newSet->previousSiblingMultiColumnBox() || !newSet->previousSiblingM
ultiColumnBox()->isLayoutMultiColumnSet()); | 395 ASSERT(!newSet->previousSiblingMultiColumnBox() || !newSet->previousSiblingM
ultiColumnBox()->isLayoutMultiColumnSet()); |
| 396 ASSERT(!newSet->nextSiblingMultiColumnBox() || !newSet->nextSiblingMultiColu
mnBox()->isLayoutMultiColumnSet()); | 396 ASSERT(!newSet->nextSiblingMultiColumnBox() || !newSet->nextSiblingMultiColu
mnBox()->isLayoutMultiColumnSet()); |
| 397 } | 397 } |
| 398 | 398 |
| 399 void LayoutMultiColumnFlowThread::createAndInsertSpannerPlaceholder(LayoutBox* s
panner, LayoutBox* insertBefore) | 399 void LayoutMultiColumnFlowThread::createAndInsertSpannerPlaceholder(LayoutBox* s
pannerObjectInFlowThread, LayoutObject* insertedBeforeInFlowThread) |
| 400 { | 400 { |
| 401 LayoutBox* insertBeforeColumnBox = nullptr; |
| 402 LayoutMultiColumnSet* setToSplit = nullptr; |
| 403 if (insertedBeforeInFlowThread) { |
| 404 // The spanner is inserted before something. Figure out what this entail
s. If the |
| 405 // next object is a spanner too, it means that we can simply insert a ne
w spanner |
| 406 // placeholder in front of its placeholder. |
| 407 insertBeforeColumnBox = insertedBeforeInFlowThread->spannerPlaceholder()
; |
| 408 if (!insertBeforeColumnBox) { |
| 409 // The next object isn't a spanner; it's regular column content. Exa
mine what |
| 410 // comes right before us in the flow thread, then. |
| 411 LayoutObject* previousLayoutObject = previousInPreOrderSkippingOutOf
Flow(this, spannerObjectInFlowThread); |
| 412 if (!previousLayoutObject || previousLayoutObject == this) { |
| 413 // The spanner is inserted as the first child of the multicol co
ntainer, |
| 414 // which means that we simply insert a new spanner placeholder a
t the |
| 415 // beginning. |
| 416 insertBeforeColumnBox = firstMultiColumnBox(); |
| 417 } else if (LayoutMultiColumnSpannerPlaceholder* previousPlaceholder
= containingColumnSpannerPlaceholder(previousLayoutObject)) { |
| 418 // Before us is another spanner. We belong right after it then. |
| 419 insertBeforeColumnBox = previousPlaceholder->nextSiblingMultiCol
umnBox(); |
| 420 } else { |
| 421 // We're inside regular column content with both feet. Find out
which column |
| 422 // set this is. It needs to be split it into two sets, so that w
e can insert |
| 423 // a new spanner placeholder between them. |
| 424 setToSplit = mapDescendantToColumnSet(previousLayoutObject); |
| 425 ASSERT(setToSplit == mapDescendantToColumnSet(insertedBeforeInFl
owThread)); |
| 426 setToSplit->setNeedsLayoutAndFullPaintInvalidation(LayoutInvalid
ationReason::ColumnsChanged); |
| 427 insertBeforeColumnBox = setToSplit->nextSiblingMultiColumnBox(); |
| 428 // We've found out which set that needs to be split. Now proceed
to |
| 429 // inserting the spanner placeholder, and then insert a second c
olumn set. |
| 430 } |
| 431 } |
| 432 ASSERT(setToSplit || insertBeforeColumnBox); |
| 433 } |
| 434 |
| 401 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); | 435 LayoutBlockFlow* multicolContainer = multiColumnBlockFlow(); |
| 402 LayoutMultiColumnSpannerPlaceholder* newPlaceholder = LayoutMultiColumnSpann
erPlaceholder::createAnonymous(multicolContainer->styleRef(), *spanner); | 436 LayoutMultiColumnSpannerPlaceholder* newPlaceholder = LayoutMultiColumnSpann
erPlaceholder::createAnonymous(multicolContainer->styleRef(), *spannerObjectInFl
owThread); |
| 403 multicolContainer->LayoutBlock::addChild(newPlaceholder, insertBefore); | 437 multicolContainer->LayoutBlock::addChild(newPlaceholder, insertBeforeColumnB
ox); |
| 404 spanner->setSpannerPlaceholder(*newPlaceholder); | 438 spannerObjectInFlowThread->setSpannerPlaceholder(*newPlaceholder); |
| 439 |
| 440 if (setToSplit) |
| 441 createAndInsertMultiColumnSet(insertBeforeColumnBox); |
| 442 } |
| 443 |
| 444 void LayoutMultiColumnFlowThread::destroySpannerPlaceholder(LayoutMultiColumnSpa
nnerPlaceholder* placeholder) |
| 445 { |
| 446 if (LayoutBox* nextColumnBox = placeholder->nextSiblingMultiColumnBox()) { |
| 447 LayoutBox* previousColumnBox = placeholder->previousSiblingMultiColumnBo
x(); |
| 448 if (nextColumnBox && nextColumnBox->isLayoutMultiColumnSet() |
| 449 && previousColumnBox && previousColumnBox->isLayoutMultiColumnSet())
{ |
| 450 // Need to merge two column sets. |
| 451 nextColumnBox->destroy(); |
| 452 previousColumnBox->setNeedsLayout(LayoutInvalidationReason::ColumnsC
hanged); |
| 453 invalidateColumnSets(); |
| 454 } |
| 455 } |
| 456 placeholder->destroy(); |
| 405 } | 457 } |
| 406 | 458 |
| 407 bool LayoutMultiColumnFlowThread::descendantIsValidColumnSpanner(LayoutObject* d
escendant) const | 459 bool LayoutMultiColumnFlowThread::descendantIsValidColumnSpanner(LayoutObject* d
escendant) const |
| 408 { | 460 { |
| 409 // We assume that we're inside the flow thread. This function is not to be c
alled otherwise. | 461 // We assume that we're inside the flow thread. This function is not to be c
alled otherwise. |
| 410 ASSERT(descendant->isDescendantOf(this)); | 462 ASSERT(descendant->isDescendantOf(this)); |
| 411 | 463 |
| 412 // We're evaluating if the descendant should be turned into a proper spanner
. It shouldn't | 464 // We're evaluating if the descendant should be turned into a proper spanner
. It shouldn't |
| 413 // already be one. | 465 // already be one. |
| 414 ASSERT(!descendant->spannerPlaceholder()); | 466 ASSERT(!descendant->spannerPlaceholder()); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 539 for (LayoutObject* layoutObject = descendant; layoutObject; layoutObject = n
ext) { | 591 for (LayoutObject* layoutObject = descendant; layoutObject; layoutObject = n
ext) { |
| 540 if (shouldSkipInsertedOrRemovedChild(this, *layoutObject)) { | 592 if (shouldSkipInsertedOrRemovedChild(this, *layoutObject)) { |
| 541 next = layoutObject->nextInPreOrderAfterChildren(descendant); | 593 next = layoutObject->nextInPreOrderAfterChildren(descendant); |
| 542 continue; | 594 continue; |
| 543 } | 595 } |
| 544 next = layoutObject->nextInPreOrder(descendant); | 596 next = layoutObject->nextInPreOrder(descendant); |
| 545 if (containingColumnSpannerPlaceholder(layoutObject)) | 597 if (containingColumnSpannerPlaceholder(layoutObject)) |
| 546 continue; // Inside a column spanner. Nothing to do, then. | 598 continue; // Inside a column spanner. Nothing to do, then. |
| 547 if (descendantIsValidColumnSpanner(layoutObject)) { | 599 if (descendantIsValidColumnSpanner(layoutObject)) { |
| 548 // This layoutObject is a spanner, so it needs to establish a spanne
r placeholder. | 600 // This layoutObject is a spanner, so it needs to establish a spanne
r placeholder. |
| 549 LayoutBox* insertBefore = nullptr; | 601 createAndInsertSpannerPlaceholder(toLayoutBox(layoutObject), objectA
fterSubtree); |
| 550 LayoutMultiColumnSet* setToSplit = nullptr; | |
| 551 if (objectAfterSubtree) { | |
| 552 // The spanner is inserted before something. Figure out what thi
s entails. If the | |
| 553 // next layoutObject is a spanner too, it means that we can simp
ly insert a new spanner | |
| 554 // placeholder in front of its placeholder. | |
| 555 insertBefore = objectAfterSubtree->spannerPlaceholder(); | |
| 556 if (!insertBefore) { | |
| 557 // The next layoutObject isn't a spanner; it's regular colum
n content. Examine what | |
| 558 // comes right before us in the flow thread, then. | |
| 559 LayoutObject* previousLayoutObject = previousInPreOrderSkipp
ingOutOfFlow(this, layoutObject); | |
| 560 if (!previousLayoutObject || previousLayoutObject == this) { | |
| 561 // The spanner is inserted as the first child of the mul
ticol container, | |
| 562 // which means that we simply insert a new spanner place
holder at the | |
| 563 // beginning. | |
| 564 insertBefore = firstMultiColumnBox(); | |
| 565 } else if (LayoutMultiColumnSpannerPlaceholder* previousPlac
eholder = containingColumnSpannerPlaceholder(previousLayoutObject)) { | |
| 566 // Before us is another spanner. We belong right after i
t then. | |
| 567 insertBefore = previousPlaceholder->nextSiblingMultiColu
mnBox(); | |
| 568 } else { | |
| 569 // We're inside regular column content with both feet. F
ind out which column | |
| 570 // set this is. It needs to be split it into two sets, s
o that we can insert | |
| 571 // a new spanner placeholder between them. | |
| 572 setToSplit = mapDescendantToColumnSet(previousLayoutObje
ct); | |
| 573 ASSERT(setToSplit == mapDescendantToColumnSet(objectAfte
rSubtree)); | |
| 574 setToSplit->setNeedsLayoutAndFullPaintInvalidation(Layou
tInvalidationReason::ColumnsChanged); | |
| 575 insertBefore = setToSplit->nextSiblingMultiColumnBox(); | |
| 576 // We've found out which set that needs to be split. Now
proceed to | |
| 577 // inserting the spanner placeholder, and then insert a
second column set. | |
| 578 } | |
| 579 } | |
| 580 ASSERT(setToSplit || insertBefore); | |
| 581 } | |
| 582 createAndInsertSpannerPlaceholder(toLayoutBox(layoutObject), insertB
efore); | |
| 583 if (setToSplit) | |
| 584 createAndInsertMultiColumnSet(insertBefore); | |
| 585 continue; | 602 continue; |
| 586 } | 603 } |
| 587 // This layoutObject is regular column content (i.e. not a spanner). Cre
ate a set if necessary. | 604 // This layoutObject is regular column content (i.e. not a spanner). Cre
ate a set if necessary. |
| 588 if (objectAfterSubtree) { | 605 if (objectAfterSubtree) { |
| 589 if (LayoutMultiColumnSpannerPlaceholder* placeholder = objectAfterSu
btree->spannerPlaceholder()) { | 606 if (LayoutMultiColumnSpannerPlaceholder* placeholder = objectAfterSu
btree->spannerPlaceholder()) { |
| 590 // If inserted right before a spanner, we need to make sure that
there's a set for us there. | 607 // If inserted right before a spanner, we need to make sure that
there's a set for us there. |
| 591 LayoutBox* previous = placeholder->previousSiblingMultiColumnBox
(); | 608 LayoutBox* previous = placeholder->previousSiblingMultiColumnBox
(); |
| 592 if (!previous || !previous->isLayoutMultiColumnSet()) | 609 if (!previous || !previous->isLayoutMultiColumnSet()) |
| 593 createAndInsertMultiColumnSet(placeholder); | 610 createAndInsertMultiColumnSet(placeholder); |
| 594 } else { | 611 } else { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 623 next = layoutObject->nextInPreOrderAfterChildren(descendant); | 640 next = layoutObject->nextInPreOrderAfterChildren(descendant); |
| 624 continue; | 641 continue; |
| 625 } | 642 } |
| 626 processedSomething = true; | 643 processedSomething = true; |
| 627 LayoutMultiColumnSpannerPlaceholder* placeholder = layoutObject->spanner
Placeholder(); | 644 LayoutMultiColumnSpannerPlaceholder* placeholder = layoutObject->spanner
Placeholder(); |
| 628 if (!placeholder) { | 645 if (!placeholder) { |
| 629 next = layoutObject->nextInPreOrder(descendant); | 646 next = layoutObject->nextInPreOrder(descendant); |
| 630 continue; | 647 continue; |
| 631 } | 648 } |
| 632 next = layoutObject->nextInPreOrderAfterChildren(descendant); // It's a
spanner. Its children are of no interest to us. | 649 next = layoutObject->nextInPreOrderAfterChildren(descendant); // It's a
spanner. Its children are of no interest to us. |
| 633 if (LayoutBox* nextColumnBox = placeholder->nextSiblingMultiColumnBox())
{ | 650 destroySpannerPlaceholder(placeholder); |
| 634 LayoutBox* previousColumnBox = placeholder->previousSiblingMultiColu
mnBox(); | |
| 635 if (nextColumnBox && nextColumnBox->isLayoutMultiColumnSet() | |
| 636 && previousColumnBox && previousColumnBox->isLayoutMultiColumnSe
t()) { | |
| 637 // Need to merge two column sets. | |
| 638 nextColumnBox->destroy(); | |
| 639 previousColumnBox->setNeedsLayout(LayoutInvalidationReason::Colu
mnsChanged); | |
| 640 invalidateColumnSets(); | |
| 641 } | |
| 642 } | |
| 643 placeholder->destroy(); | |
| 644 } | 651 } |
| 645 if (hadContainingPlaceholder || !processedSomething) | 652 if (hadContainingPlaceholder || !processedSomething) |
| 646 return; // No column content will be removed, so we can stop here. | 653 return; // No column content will be removed, so we can stop here. |
| 647 | 654 |
| 648 // Column content will be removed. Does this mean that we should destroy a c
olumn set? | 655 // Column content will be removed. Does this mean that we should destroy a c
olumn set? |
| 649 LayoutMultiColumnSpannerPlaceholder* adjacentPreviousSpannerPlaceholder = nu
llptr; | 656 LayoutMultiColumnSpannerPlaceholder* adjacentPreviousSpannerPlaceholder = nu
llptr; |
| 650 LayoutObject* previousLayoutObject = previousInPreOrderSkippingOutOfFlow(thi
s, descendant); | 657 LayoutObject* previousLayoutObject = previousInPreOrderSkippingOutOfFlow(thi
s, descendant); |
| 651 if (previousLayoutObject && previousLayoutObject != this) { | 658 if (previousLayoutObject && previousLayoutObject != this) { |
| 652 adjacentPreviousSpannerPlaceholder = containingColumnSpannerPlaceholder(
previousLayoutObject); | 659 adjacentPreviousSpannerPlaceholder = containingColumnSpannerPlaceholder(
previousLayoutObject); |
| 653 if (!adjacentPreviousSpannerPlaceholder) | 660 if (!adjacentPreviousSpannerPlaceholder) |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 797 } | 804 } |
| 798 | 805 |
| 799 bool LayoutMultiColumnFlowThread::isPageLogicalHeightKnown() const | 806 bool LayoutMultiColumnFlowThread::isPageLogicalHeightKnown() const |
| 800 { | 807 { |
| 801 if (LayoutMultiColumnSet* columnSet = lastMultiColumnSet()) | 808 if (LayoutMultiColumnSet* columnSet = lastMultiColumnSet()) |
| 802 return columnSet->pageLogicalHeight(); | 809 return columnSet->pageLogicalHeight(); |
| 803 return false; | 810 return false; |
| 804 } | 811 } |
| 805 | 812 |
| 806 } | 813 } |
| OLD | NEW |