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 |