| 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 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 } | 438 } |
| 439 LayoutBox* nextColumnBox = placeholder->nextSiblingMultiColumnBox(); | 439 LayoutBox* nextColumnBox = placeholder->nextSiblingMultiColumnBox(); |
| 440 if (nextColumnBox && nextColumnBox->isLayoutMultiColumnSet()) { | 440 if (nextColumnBox && nextColumnBox->isLayoutMultiColumnSet()) { |
| 441 LayoutMultiColumnSet* nextSet = toLayoutMultiColumnSet(nextColumnBox); | 441 LayoutMultiColumnSet* nextSet = toLayoutMultiColumnSet(nextColumnBox); |
| 442 m_lastSetWorkedOn = nextSet; | 442 m_lastSetWorkedOn = nextSet; |
| 443 nextSet->beginFlow(logicalTopInFlowThread); | 443 nextSet->beginFlow(logicalTopInFlowThread); |
| 444 } | 444 } |
| 445 return adjustment; | 445 return adjustment; |
| 446 } | 446 } |
| 447 | 447 |
| 448 // When processing layout objects to remove or when processing layout objects th
at have just been |
| 449 // inserted, certain types of objects should be skipped. |
| 450 static bool shouldSkipInsertedOrRemovedChild(const LayoutObject& child) |
| 451 { |
| 452 if (child.isLayoutFlowThread()) { |
| 453 // Found an inner flow thread. We need to skip it and its descendants. |
| 454 return true; |
| 455 } |
| 456 if (child.isLayoutMultiColumnSet() || child.isLayoutMultiColumnSpannerPlaceh
older()) { |
| 457 // Column sets and spanner placeholders in a child multicol context don'
t affect the parent |
| 458 // flow thread. |
| 459 return true; |
| 460 } |
| 461 return false; |
| 462 } |
| 463 |
| 448 void LayoutMultiColumnFlowThread::flowThreadDescendantWasInserted(LayoutObject*
descendant) | 464 void LayoutMultiColumnFlowThread::flowThreadDescendantWasInserted(LayoutObject*
descendant) |
| 449 { | 465 { |
| 450 ASSERT(!m_isBeingEvacuated); | 466 ASSERT(!m_isBeingEvacuated); |
| 451 LayoutObject* nextRenderer = descendant->nextInPreOrderAfterChildren(this); | 467 LayoutObject* objectAfterSubtree = descendant->nextInPreOrderAfterChildren(t
his); |
| 452 // This method ensures that the list of column sets and spanner placeholders
reflects the | 468 // This method ensures that the list of column sets and spanner placeholders
reflects the |
| 453 // multicol content after having inserted a descendant (or descendant subtre
e). See the header | 469 // multicol content after having inserted a descendant (or descendant subtre
e). See the header |
| 454 // file for more information. Go through the subtree that was just inserted
and create column | 470 // file for more information. Go through the subtree that was just inserted
and create column |
| 455 // sets (needed by regular column content) and spanner placeholders (one nee
ded by each spanner) | 471 // sets (needed by regular column content) and spanner placeholders (one nee
ded by each spanner) |
| 456 // where needed. | 472 // where needed. |
| 457 for (LayoutObject* renderer = descendant; renderer; renderer = renderer->nex
tInPreOrder(descendant)) { | 473 LayoutObject* next; |
| 458 if (containingColumnSpannerPlaceholder(renderer)) | 474 for (LayoutObject* layoutObject = descendant; layoutObject; layoutObject = n
ext) { |
| 475 if (shouldSkipInsertedOrRemovedChild(*layoutObject)) { |
| 476 next = layoutObject->nextInPreOrderAfterChildren(descendant); |
| 477 continue; |
| 478 } |
| 479 next = layoutObject->nextInPreOrder(descendant); |
| 480 if (containingColumnSpannerPlaceholder(layoutObject)) |
| 459 continue; // Inside a column spanner. Nothing to do, then. | 481 continue; // Inside a column spanner. Nothing to do, then. |
| 460 if (descendantIsValidColumnSpanner(renderer)) { | 482 if (descendantIsValidColumnSpanner(layoutObject)) { |
| 461 // This renderer is a spanner, so it needs to establish a spanner pl
aceholder. | 483 // This layoutObject is a spanner, so it needs to establish a spanne
r placeholder. |
| 462 LayoutBox* insertBefore = 0; | 484 LayoutBox* insertBefore = 0; |
| 463 LayoutMultiColumnSet* setToSplit = 0; | 485 LayoutMultiColumnSet* setToSplit = 0; |
| 464 if (nextRenderer) { | 486 if (objectAfterSubtree) { |
| 465 // The spanner is inserted before something. Figure out what thi
s entails. If the | 487 // The spanner is inserted before something. Figure out what thi
s entails. If the |
| 466 // next renderer is a spanner too, it means that we can simply i
nsert a new spanner | 488 // next layoutObject is a spanner too, it means that we can simp
ly insert a new spanner |
| 467 // placeholder in front of its placeholder. | 489 // placeholder in front of its placeholder. |
| 468 insertBefore = nextRenderer->spannerPlaceholder(); | 490 insertBefore = objectAfterSubtree->spannerPlaceholder(); |
| 469 if (!insertBefore) { | 491 if (!insertBefore) { |
| 470 // The next renderer isn't a spanner; it's regular column co
ntent. Examine what | 492 // The next layoutObject isn't a spanner; it's regular colum
n content. Examine what |
| 471 // comes right before us in the flow thread, then. | 493 // comes right before us in the flow thread, then. |
| 472 LayoutObject* previousRenderer = renderer->previousInPreOrde
r(this); | 494 LayoutObject* previousLayoutObject = layoutObject->previousI
nPreOrder(this); |
| 473 if (!previousRenderer || previousRenderer == this) { | 495 if (!previousLayoutObject || previousLayoutObject == this) { |
| 474 // The spanner is inserted as the first child of the mul
ticol container, | 496 // The spanner is inserted as the first child of the mul
ticol container, |
| 475 // which means that we simply insert a new spanner place
holder at the | 497 // which means that we simply insert a new spanner place
holder at the |
| 476 // beginning. | 498 // beginning. |
| 477 insertBefore = firstMultiColumnBox(); | 499 insertBefore = firstMultiColumnBox(); |
| 478 } else if (LayoutMultiColumnSpannerPlaceholder* previousPlac
eholder = containingColumnSpannerPlaceholder(previousRenderer)) { | 500 } else if (LayoutMultiColumnSpannerPlaceholder* previousPlac
eholder = containingColumnSpannerPlaceholder(previousLayoutObject)) { |
| 479 // Before us is another spanner. We belong right after i
t then. | 501 // Before us is another spanner. We belong right after i
t then. |
| 480 insertBefore = previousPlaceholder->nextSiblingMultiColu
mnBox(); | 502 insertBefore = previousPlaceholder->nextSiblingMultiColu
mnBox(); |
| 481 } else { | 503 } else { |
| 482 // We're inside regular column content with both feet. F
ind out which column | 504 // We're inside regular column content with both feet. F
ind out which column |
| 483 // set this is. It needs to be split it into two sets, s
o that we can insert | 505 // set this is. It needs to be split it into two sets, s
o that we can insert |
| 484 // a new spanner placeholder between them. | 506 // a new spanner placeholder between them. |
| 485 setToSplit = findSetRendering(previousRenderer); | 507 setToSplit = findSetRendering(previousLayoutObject); |
| 486 ASSERT(setToSplit == findSetRendering(nextRenderer)); | 508 ASSERT(setToSplit == findSetRendering(objectAfterSubtree
)); |
| 487 setToSplit->setNeedsLayoutAndFullPaintInvalidation(Layou
tInvalidationReason::ColumnsChanged); | 509 setToSplit->setNeedsLayoutAndFullPaintInvalidation(Layou
tInvalidationReason::ColumnsChanged); |
| 488 insertBefore = setToSplit->nextSiblingMultiColumnBox(); | 510 insertBefore = setToSplit->nextSiblingMultiColumnBox(); |
| 489 // We've found out which set that needs to be split. Now
proceed to | 511 // We've found out which set that needs to be split. Now
proceed to |
| 490 // inserting the spanner placeholder, and then insert a
second column set. | 512 // inserting the spanner placeholder, and then insert a
second column set. |
| 491 } | 513 } |
| 492 } | 514 } |
| 493 ASSERT(setToSplit || insertBefore); | 515 ASSERT(setToSplit || insertBefore); |
| 494 } | 516 } |
| 495 createAndInsertSpannerPlaceholder(toLayoutBox(renderer), insertBefor
e); | 517 createAndInsertSpannerPlaceholder(toLayoutBox(layoutObject), insertB
efore); |
| 496 if (setToSplit) | 518 if (setToSplit) |
| 497 createAndInsertMultiColumnSet(insertBefore); | 519 createAndInsertMultiColumnSet(insertBefore); |
| 498 continue; | 520 continue; |
| 499 } | 521 } |
| 500 // This renderer is regular column content (i.e. not a spanner). Create
a set if necessary. | 522 // This layoutObject is regular column content (i.e. not a spanner). Cre
ate a set if necessary. |
| 501 if (nextRenderer) { | 523 if (objectAfterSubtree) { |
| 502 if (LayoutMultiColumnSpannerPlaceholder* placeholder = nextRenderer-
>spannerPlaceholder()) { | 524 if (LayoutMultiColumnSpannerPlaceholder* placeholder = objectAfterSu
btree->spannerPlaceholder()) { |
| 503 // If inserted right before a spanner, we need to make sure that
there's a set for us there. | 525 // If inserted right before a spanner, we need to make sure that
there's a set for us there. |
| 504 LayoutBox* previous = placeholder->previousSiblingMultiColumnBox
(); | 526 LayoutBox* previous = placeholder->previousSiblingMultiColumnBox
(); |
| 505 if (!previous || !previous->isLayoutMultiColumnSet()) | 527 if (!previous || !previous->isLayoutMultiColumnSet()) |
| 506 createAndInsertMultiColumnSet(placeholder); | 528 createAndInsertMultiColumnSet(placeholder); |
| 507 } else { | 529 } else { |
| 508 // Otherwise, since |nextRenderer| isn't a spanner, it has to me
an that there's | 530 // Otherwise, since |objectAfterSubtree| isn't a spanner, it has
to mean that there's |
| 509 // already a set for that content. We can use it for this render
er too. | 531 // already a set for that content. We can use it for this layout
Object too. |
| 510 ASSERT(findSetRendering(nextRenderer)); | 532 ASSERT(findSetRendering(objectAfterSubtree)); |
| 511 ASSERT(findSetRendering(renderer) == findSetRendering(nextRender
er)); | 533 ASSERT(findSetRendering(layoutObject) == findSetRendering(object
AfterSubtree)); |
| 512 } | 534 } |
| 513 } else { | 535 } else { |
| 514 // Inserting at the end. Then we just need to make sure that there's
a column set at the end. | 536 // Inserting at the end. Then we just need to make sure that there's
a column set at the end. |
| 515 LayoutBox* lastColumnBox = lastMultiColumnBox(); | 537 LayoutBox* lastColumnBox = lastMultiColumnBox(); |
| 516 if (!lastColumnBox || !lastColumnBox->isLayoutMultiColumnSet()) | 538 if (!lastColumnBox || !lastColumnBox->isLayoutMultiColumnSet()) |
| 517 createAndInsertMultiColumnSet(); | 539 createAndInsertMultiColumnSet(); |
| 518 } | 540 } |
| 519 } | 541 } |
| 520 } | 542 } |
| 521 | 543 |
| 522 void LayoutMultiColumnFlowThread::flowThreadDescendantWillBeRemoved(LayoutObject
* descendant) | 544 void LayoutMultiColumnFlowThread::flowThreadDescendantWillBeRemoved(LayoutObject
* descendant) |
| 523 { | 545 { |
| 524 // This method ensures that the list of column sets and spanner placeholders
reflects the | 546 // This method ensures that the list of column sets and spanner placeholders
reflects the |
| 525 // multicol content that we'll be left with after removal of a descendant (o
r descendant | 547 // multicol content that we'll be left with after removal of a descendant (o
r descendant |
| 526 // subtree). See the header file for more information. Removing content may
mean that we need to | 548 // subtree). See the header file for more information. Removing content may
mean that we need to |
| 527 // remove column sets and/or spanner placeholders. | 549 // remove column sets and/or spanner placeholders. |
| 528 if (m_isBeingEvacuated) | 550 if (m_isBeingEvacuated) |
| 529 return; | 551 return; |
| 530 bool hadContainingPlaceholder = containingColumnSpannerPlaceholder(descendan
t); | 552 bool hadContainingPlaceholder = containingColumnSpannerPlaceholder(descendan
t); |
| 553 bool processedSomething = false; |
| 531 LayoutObject* next; | 554 LayoutObject* next; |
| 532 // Remove spanner placeholders that are no longer needed, and merge column s
ets around them. | 555 // Remove spanner placeholders that are no longer needed, and merge column s
ets around them. |
| 533 for (LayoutObject* renderer = descendant; renderer; renderer = next) { | 556 for (LayoutObject* layoutObject = descendant; layoutObject; layoutObject = n
ext) { |
| 534 LayoutMultiColumnSpannerPlaceholder* placeholder = renderer->spannerPlac
eholder(); | 557 if (shouldSkipInsertedOrRemovedChild(*layoutObject)) { |
| 535 if (!placeholder) { | 558 next = layoutObject->nextInPreOrderAfterChildren(descendant); |
| 536 next = renderer->nextInPreOrder(descendant); | |
| 537 continue; | 559 continue; |
| 538 } | 560 } |
| 539 next = renderer->nextInPreOrderAfterChildren(descendant); // It's a span
ner. Its children are of no interest to us. | 561 processedSomething = true; |
| 562 LayoutMultiColumnSpannerPlaceholder* placeholder = layoutObject->spanner
Placeholder(); |
| 563 if (!placeholder) { |
| 564 next = layoutObject->nextInPreOrder(descendant); |
| 565 continue; |
| 566 } |
| 567 next = layoutObject->nextInPreOrderAfterChildren(descendant); // It's a
spanner. Its children are of no interest to us. |
| 540 if (LayoutBox* nextColumnBox = placeholder->nextSiblingMultiColumnBox())
{ | 568 if (LayoutBox* nextColumnBox = placeholder->nextSiblingMultiColumnBox())
{ |
| 541 LayoutBox* previousColumnBox = placeholder->previousSiblingMultiColu
mnBox(); | 569 LayoutBox* previousColumnBox = placeholder->previousSiblingMultiColu
mnBox(); |
| 542 if (nextColumnBox && nextColumnBox->isLayoutMultiColumnSet() | 570 if (nextColumnBox && nextColumnBox->isLayoutMultiColumnSet() |
| 543 && previousColumnBox && previousColumnBox->isLayoutMultiColumnSe
t()) { | 571 && previousColumnBox && previousColumnBox->isLayoutMultiColumnSe
t()) { |
| 544 // Need to merge two column sets. | 572 // Need to merge two column sets. |
| 545 nextColumnBox->destroy(); | 573 nextColumnBox->destroy(); |
| 546 previousColumnBox->setNeedsLayout(LayoutInvalidationReason::Colu
mnsChanged); | 574 previousColumnBox->setNeedsLayout(LayoutInvalidationReason::Colu
mnsChanged); |
| 547 invalidateRegions(); | 575 invalidateRegions(); |
| 548 } | 576 } |
| 549 } | 577 } |
| 550 placeholder->destroy(); | 578 placeholder->destroy(); |
| 551 } | 579 } |
| 552 if (hadContainingPlaceholder) | 580 if (hadContainingPlaceholder || !processedSomething) |
| 553 return; // We're only removing a spanner (or something inside one), whic
h means that no column content will be removed. | 581 return; // No column content will be removed, so we can stop here. |
| 554 | 582 |
| 555 // Column content will be removed. Does this mean that we should destroy a c
olumn set? | 583 // Column content will be removed. Does this mean that we should destroy a c
olumn set? |
| 556 LayoutMultiColumnSpannerPlaceholder* adjacentPreviousSpannerPlaceholder = 0; | 584 LayoutMultiColumnSpannerPlaceholder* adjacentPreviousSpannerPlaceholder = 0; |
| 557 LayoutObject* previousRenderer = descendant->previousInPreOrder(this); | 585 LayoutObject* previousLayoutObject = descendant->previousInPreOrder(this); |
| 558 if (previousRenderer && previousRenderer != this) { | 586 if (previousLayoutObject && previousLayoutObject != this) { |
| 559 adjacentPreviousSpannerPlaceholder = containingColumnSpannerPlaceholder(
previousRenderer); | 587 adjacentPreviousSpannerPlaceholder = containingColumnSpannerPlaceholder(
previousLayoutObject); |
| 560 if (!adjacentPreviousSpannerPlaceholder) | 588 if (!adjacentPreviousSpannerPlaceholder) |
| 561 return; // Preceded by column content. Set still needed. | 589 return; // Preceded by column content. Set still needed. |
| 562 } | 590 } |
| 563 LayoutMultiColumnSpannerPlaceholder* adjacentNextSpannerPlaceholder = 0; | 591 LayoutMultiColumnSpannerPlaceholder* adjacentNextSpannerPlaceholder = 0; |
| 564 LayoutObject* nextRenderer = descendant->nextInPreOrderAfterChildren(this); | 592 LayoutObject* nextLayoutObject = descendant->nextInPreOrderAfterChildren(thi
s); |
| 565 if (nextRenderer) { | 593 if (nextLayoutObject) { |
| 566 adjacentNextSpannerPlaceholder = containingColumnSpannerPlaceholder(next
Renderer); | 594 adjacentNextSpannerPlaceholder = containingColumnSpannerPlaceholder(next
LayoutObject); |
| 567 if (!adjacentNextSpannerPlaceholder) | 595 if (!adjacentNextSpannerPlaceholder) |
| 568 return; // Followed by column content. Set still needed. | 596 return; // Followed by column content. Set still needed. |
| 569 } | 597 } |
| 570 // We have now determined that, with the removal of |descendant|, we should
remove a column | 598 // We have now determined that, with the removal of |descendant|, we should
remove a column |
| 571 // set. Locate it and remove it. Do it without involving findSetRendering(),
as that might be | 599 // set. Locate it and remove it. Do it without involving findSetRendering(),
as that might be |
| 572 // very slow. Deduce the right set from the spanner placeholders that we've
already found. | 600 // very slow. Deduce the right set from the spanner placeholders that we've
already found. |
| 573 LayoutMultiColumnSet* columnSetToRemove; | 601 LayoutMultiColumnSet* columnSetToRemove; |
| 574 if (adjacentNextSpannerPlaceholder) { | 602 if (adjacentNextSpannerPlaceholder) { |
| 575 columnSetToRemove = toLayoutMultiColumnSet(adjacentNextSpannerPlaceholde
r->previousSiblingMultiColumnBox()); | 603 columnSetToRemove = toLayoutMultiColumnSet(adjacentNextSpannerPlaceholde
r->previousSiblingMultiColumnBox()); |
| 576 ASSERT(!adjacentPreviousSpannerPlaceholder || columnSetToRemove == adjac
entPreviousSpannerPlaceholder->nextSiblingMultiColumnBox()); | 604 ASSERT(!adjacentPreviousSpannerPlaceholder || columnSetToRemove == adjac
entPreviousSpannerPlaceholder->nextSiblingMultiColumnBox()); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 } | 703 } |
| 676 | 704 |
| 677 bool LayoutMultiColumnFlowThread::isPageLogicalHeightKnown() const | 705 bool LayoutMultiColumnFlowThread::isPageLogicalHeightKnown() const |
| 678 { | 706 { |
| 679 if (LayoutMultiColumnSet* columnSet = lastMultiColumnSet()) | 707 if (LayoutMultiColumnSet* columnSet = lastMultiColumnSet()) |
| 680 return columnSet->pageLogicalHeight(); | 708 return columnSet->pageLogicalHeight(); |
| 681 return false; | 709 return false; |
| 682 } | 710 } |
| 683 | 711 |
| 684 } | 712 } |
| OLD | NEW |