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 |