Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: Source/core/layout/LayoutMultiColumnFlowThread.cpp

Issue 1109513002: [New Multicolumn] Don't enter child multicol contexts when processing object insertions / removals. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: code review: renderer -> layoutObject Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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 }
OLDNEW
« no previous file with comments | « LayoutTests/fast/multicol/inner-multicol-moved-into-continuation-expected.txt ('k') | Source/core/layout/LayoutObject.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698