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

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutBlock.cpp

Issue 1759853003: Merge contiguous anonymous blocks after removing a float or out-of-pos-element between them (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@585604-4
Patch Set: Updated Created 4 years, 9 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
« no previous file with comments | « third_party/WebKit/LayoutTests/fast/block/float/add-float-back-to-anonymous-block-previous-expected.txt ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2007 David Smith (catfish.man@gmail.com) 4 * (C) 2007 David Smith (catfish.man@gmail.com)
5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
6 * Copyright (C) Research In Motion Limited 2010. All rights reserved. 6 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
7 * 7 *
8 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public 9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 || oldStyle.paddingLeft() != newStyle.paddingLeft() 244 || oldStyle.paddingLeft() != newStyle.paddingLeft()
245 || oldStyle.paddingRight() != newStyle.paddingRight(); 245 || oldStyle.paddingRight() != newStyle.paddingRight();
246 } 246 }
247 247
248 return oldStyle.borderTopWidth() != newStyle.borderTopWidth() 248 return oldStyle.borderTopWidth() != newStyle.borderTopWidth()
249 || oldStyle.borderBottomWidth() != newStyle.borderBottomWidth() 249 || oldStyle.borderBottomWidth() != newStyle.borderBottomWidth()
250 || oldStyle.paddingTop() != newStyle.paddingTop() 250 || oldStyle.paddingTop() != newStyle.paddingTop()
251 || oldStyle.paddingBottom() != newStyle.paddingBottom(); 251 || oldStyle.paddingBottom() != newStyle.paddingBottom();
252 } 252 }
253 253
254 static bool canMergeContiguousAnonymousBlocks(LayoutObject* prev, LayoutObject* next)
255 {
256 if ((prev && (!prev->isAnonymousBlock() || toLayoutBlock(prev)->continuation () || toLayoutBlock(prev)->beingDestroyed()))
257 || (next && (!next->isAnonymousBlock() || toLayoutBlock(next)->continuat ion() || toLayoutBlock(next)->beingDestroyed())))
258 return false;
259
260 if ((prev && (prev->isRubyRun() || prev->isRubyBase()))
261 || (next && (next->isRubyRun() || next->isRubyBase())))
262 return false;
263
264 return true;
265 }
266
267 static bool mergeContiguousAnonymousBlocks(LayoutObject* prev, LayoutObject*& ne xt)
268 {
269 if (!prev || !next || !canMergeContiguousAnonymousBlocks(prev, next))
270 return false;
271
272 prev->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvali dationReason::AnonymousBlockChange);
273 LayoutBlockFlow* nextBlock = toLayoutBlockFlow(next);
274 LayoutBlockFlow* prevBlock = toLayoutBlockFlow(prev);
275
276 // If the inlineness of children of the two block don't match, we'd need spe cial code here
277 // (but there should be no need for it).
278 ASSERT(nextBlock->childrenInline() == prevBlock->childrenInline());
279 // Take all the children out of the |next| block and put them in
280 // the |prev| block.
281 nextBlock->moveAllChildrenIncludingFloatsTo(prevBlock, nextBlock->hasLayer() || prevBlock->hasLayer());
282 // Delete the now-empty block's lines and nuke it.
283 nextBlock->deleteLineBoxTree();
284 nextBlock->destroy();
285 next = nullptr;
286 return true;
287 }
288
254 static void addNextFloatingOrOutOfFlowSiblingsToBlock(LayoutBlock* block) 289 static void addNextFloatingOrOutOfFlowSiblingsToBlock(LayoutBlock* block)
255 { 290 {
256 if (!block->parent() || !block->parent()->isLayoutBlockFlow()) 291 if (!block->parent() || !block->parent()->isLayoutBlockFlow())
257 return; 292 return;
258 if (block->beingDestroyed() || block->documentBeingDestroyed()) 293 if (block->beingDestroyed() || block->documentBeingDestroyed())
259 return; 294 return;
260 295
261 LayoutObject* child = block->nextSibling(); 296 LayoutObject* child = block->nextSibling();
262 while (child && child->isFloatingOrOutOfFlowPositioned()) { 297 while (child && child->isFloatingOrOutOfFlowPositioned()) {
263 LayoutObject* sibling = child->nextSibling(); 298 LayoutObject* sibling = child->nextSibling();
264 toLayoutBlock(block->parent())->moveChildTo(block, child, nullptr, false ); 299 toLayoutBlock(block->parent())->moveChildTo(block, child, nullptr, false );
265 child = sibling; 300 child = sibling;
266 } 301 }
302
303 LayoutObject* next = block->nextSibling();
304 mergeContiguousAnonymousBlocks(block, next);
267 } 305 }
268 306
269 static void addPreviousFloatingOrOutOfFlowSiblingsToBlock(LayoutBlock* block) 307 static void addPreviousFloatingOrOutOfFlowSiblingsToBlock(LayoutBlock* block)
270 { 308 {
271 if (!block->parent() || !block->parent()->isLayoutBlockFlow()) 309 if (!block->parent() || !block->parent()->isLayoutBlockFlow())
272 return; 310 return;
273 if (block->beingDestroyed() || block->documentBeingDestroyed()) 311 if (block->beingDestroyed() || block->documentBeingDestroyed())
274 return; 312 return;
275 313
276 LayoutObject* child = block->previousSibling(); 314 LayoutObject* child = block->previousSibling();
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
613 if (child->parent()->isLayoutGrid()) 651 if (child->parent()->isLayoutGrid())
614 toLayoutGrid(child->parent())->dirtyGrid(); 652 toLayoutGrid(child->parent())->dirtyGrid();
615 653
616 // Now remove the leftover anonymous block from the tree, and destroy it. We 'll rip it out 654 // Now remove the leftover anonymous block from the tree, and destroy it. We 'll rip it out
617 // manually from the tree before destroying it, because we don't want to tri gger any tree 655 // manually from the tree before destroying it, because we don't want to tri gger any tree
618 // adjustments with regards to anonymous blocks (or any other kind of undesi red chain-reaction). 656 // adjustments with regards to anonymous blocks (or any other kind of undesi red chain-reaction).
619 children()->removeChildNode(this, child, false); 657 children()->removeChildNode(this, child, false);
620 child->destroy(); 658 child->destroy();
621 } 659 }
622 660
623 static bool canMergeContiguousAnonymousBlocks(LayoutObject* oldChild, LayoutObje ct* prev, LayoutObject* next)
624 {
625 if (oldChild->documentBeingDestroyed() || oldChild->isInline() || oldChild-> virtualContinuation())
626 return false;
627
628 if ((prev && (!prev->isAnonymousBlock() || toLayoutBlock(prev)->continuation () || toLayoutBlock(prev)->beingDestroyed()))
629 || (next && (!next->isAnonymousBlock() || toLayoutBlock(next)->continuat ion() || toLayoutBlock(next)->beingDestroyed())))
630 return false;
631
632 if ((prev && (prev->isRubyRun() || prev->isRubyBase()))
633 || (next && (next->isRubyRun() || next->isRubyBase())))
634 return false;
635
636 return true;
637 }
638
639 void LayoutBlock::makeChildrenInlineIfPossible() 661 void LayoutBlock::makeChildrenInlineIfPossible()
640 { 662 {
641 ASSERT(isLayoutBlockFlow()); 663 ASSERT(isLayoutBlockFlow());
642 // Collapsing away anonymous wrappers isn't relevant for the children of ano nymous blocks, unless they are ruby bases. 664 // Collapsing away anonymous wrappers isn't relevant for the children of ano nymous blocks, unless they are ruby bases.
643 if (isAnonymousBlock() && !isRubyBase()) 665 if (isAnonymousBlock() && !isRubyBase())
644 return; 666 return;
645 667
646 Vector<LayoutBlock*, 3> blocksToRemove; 668 Vector<LayoutBlock*, 3> blocksToRemove;
647 for (LayoutObject* child = firstChild(); child; child = child->nextSibling() ) { 669 for (LayoutObject* child = firstChild(); child; child = child->nextSibling() ) {
648 if (child->isFloating()) 670 if (child->isFloating())
(...skipping 26 matching lines...) Expand all
675 // now - they will be rebuilt at layout. 697 // now - they will be rebuilt at layout.
676 toLayoutBlockFlow(this)->removeFloatingObjectsFromDescendants(); 698 toLayoutBlockFlow(this)->removeFloatingObjectsFromDescendants();
677 699
678 for (size_t i = 0; i < blocksToRemove.size(); i++) 700 for (size_t i = 0; i < blocksToRemove.size(); i++)
679 collapseAnonymousBlockChild(this, blocksToRemove[i]); 701 collapseAnonymousBlockChild(this, blocksToRemove[i]);
680 setChildrenInline(true); 702 setChildrenInline(true);
681 } 703 }
682 704
683 void LayoutBlock::collapseAnonymousBlockChild(LayoutBlock* parent, LayoutBlock* child) 705 void LayoutBlock::collapseAnonymousBlockChild(LayoutBlock* parent, LayoutBlock* child)
684 { 706 {
707 if (!parent->canCollapseAnonymousBlockChild())
708 return;
685 // It's possible that this block's destruction may have been triggered by th e 709 // It's possible that this block's destruction may have been triggered by th e
686 // child's removal. Just bail if the anonymous child block is already being 710 // child's removal. Just bail if the anonymous child block is already being
687 // destroyed. See crbug.com/282088 711 // destroyed. See crbug.com/282088
688 if (child->beingDestroyed()) 712 if (child->beingDestroyed())
689 return; 713 return;
690 if (child->continuation()) 714 if (child->continuation())
691 return; 715 return;
692 // Ruby elements use anonymous wrappers for ruby runs and ruby bases by desi gn, so we don't remove them. 716 // Ruby elements use anonymous wrappers for ruby runs and ruby bases by desi gn, so we don't remove them.
693 if (child->isRubyRun() || child->isRubyBase()) 717 if (child->isRubyRun() || child->isRubyBase())
694 return; 718 return;
(...skipping 13 matching lines...) Expand all
708 if (documentBeingDestroyed()) { 732 if (documentBeingDestroyed()) {
709 LayoutBox::removeChild(oldChild); 733 LayoutBox::removeChild(oldChild);
710 return; 734 return;
711 } 735 }
712 736
713 // If this child is a block, and if our previous and next siblings are 737 // If this child is a block, and if our previous and next siblings are
714 // both anonymous blocks with inline content, then we can go ahead and 738 // both anonymous blocks with inline content, then we can go ahead and
715 // fold the inline content back together. 739 // fold the inline content back together.
716 LayoutObject* prev = oldChild->previousSibling(); 740 LayoutObject* prev = oldChild->previousSibling();
717 LayoutObject* next = oldChild->nextSibling(); 741 LayoutObject* next = oldChild->nextSibling();
718 bool canMergeAnonymousBlocks = canMergeContiguousAnonymousBlocks(oldChild, p rev, next); 742 bool mergedAnonymousBlocks = !oldChild->documentBeingDestroyed() && !oldChil d->isInline() && !oldChild->virtualContinuation() && mergeContiguousAnonymousBlo cks(prev, next);
719 if (canMergeAnonymousBlocks && prev && next) {
720 prev->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutIn validationReason::AnonymousBlockChange);
721 LayoutBlockFlow* nextBlock = toLayoutBlockFlow(next);
722 LayoutBlockFlow* prevBlock = toLayoutBlockFlow(prev);
723
724 // If the inlineness of children of the two block don't match, we'd need special code here
725 // (but there should be no need for it).
726 ASSERT(nextBlock->childrenInline() == prevBlock->childrenInline());
727
728 // Take all the children out of the |next| block and put them in
729 // the |prev| block.
730 nextBlock->moveAllChildrenIncludingFloatsTo(prevBlock, nextBlock->hasLay er() || prevBlock->hasLayer());
731
732 // Delete the now-empty block's lines and nuke it.
733 nextBlock->deleteLineBoxTree();
734 nextBlock->destroy();
735 next = nullptr;
736 }
737 743
738 LayoutBox::removeChild(oldChild); 744 LayoutBox::removeChild(oldChild);
739 745
740 LayoutObject* child = prev ? prev : next; 746 LayoutObject* child = prev ? prev : next;
741 if (canMergeAnonymousBlocks && child && !child->previousSibling() && !child- >nextSibling() && canCollapseAnonymousBlockChild()) { 747 if (mergedAnonymousBlocks && child && !child->previousSibling() && !child->n extSibling()) {
742 // The removal has knocked us down to containing only a single anonymous 748 // The removal has knocked us down to containing only a single anonymous
743 // box. We can go ahead and pull the content right back up into our 749 // box. We can go ahead and pull the content right back up into our
744 // box. 750 // box.
745 collapseAnonymousBlockChild(this, toLayoutBlock(child)); 751 collapseAnonymousBlockChild(this, toLayoutBlock(child));
746 } 752 }
747 753
748 if (!firstChild()) { 754 if (!firstChild()) {
749 // If this was our last child be sure to clear out our line boxes. 755 // If this was our last child be sure to clear out our line boxes.
750 if (childrenInline()) 756 if (childrenInline())
751 deleteLineBoxTree(); 757 deleteLineBoxTree();
(...skipping 2103 matching lines...) Expand 10 before | Expand all | Expand 10 after
2855 void LayoutBlock::showLineTreeAndMark(const InlineBox* markedBox1, const char* m arkedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const Layout Object* obj) const 2861 void LayoutBlock::showLineTreeAndMark(const InlineBox* markedBox1, const char* m arkedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const Layout Object* obj) const
2856 { 2862 {
2857 showLayoutObject(); 2863 showLayoutObject();
2858 for (const RootInlineBox* root = firstRootBox(); root; root = root->nextRoot Box()) 2864 for (const RootInlineBox* root = firstRootBox(); root; root = root->nextRoot Box())
2859 root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLa bel2, obj, 1); 2865 root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLa bel2, obj, 1);
2860 } 2866 }
2861 2867
2862 #endif 2868 #endif
2863 2869
2864 } // namespace blink 2870 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/LayoutTests/fast/block/float/add-float-back-to-anonymous-block-previous-expected.txt ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698