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

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: 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
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 void LayoutBlock::collapseAnonymousBlockChildAfterMerge(LayoutObject* prev, Layo utObject* next, bool canMergeAnonymousBlocks)
rhogan 2016/03/03 21:48:36 I don't see a good alternative to passing canMerge
255 {
256 if (!canCollapseAnonymousBlockChild())
257 return;
258
259 LayoutObject* child = prev ? prev : next;
260 if (canMergeAnonymousBlocks && child && !child->previousSibling() && !child- >nextSibling()) {
261 // The removal has knocked us down to containing only a single anonymous
262 // box. We can go ahead and pull the content right back up into our
263 // box.
264 collapseAnonymousBlockChild(this, toLayoutBlock(child));
265 } else if (((prev && prev->isAnonymousBlock()) || (next && next->isAnonymous Block()))) {
266 // It's possible that the removal has knocked us down to a single anonym ous
267 // block with pseudo-style element siblings (e.g. first-letter). If thes e
268 // are floating, then we need to pull the content up also.
269 LayoutBlock* anonymousBlock = toLayoutBlock((prev && prev->isAnonymousBl ock()) ? prev : next);
270 if ((anonymousBlock->previousSibling() || anonymousBlock->nextSibling())
271 && (!anonymousBlock->previousSibling() || (anonymousBlock->previousS ibling()->style()->styleType() != NOPSEUDO && anonymousBlock->previousSibling()- >isFloating() && !anonymousBlock->previousSibling()->previousSibling()))
272 && (!anonymousBlock->nextSibling() || (anonymousBlock->nextSibling() ->style()->styleType() != NOPSEUDO && anonymousBlock->nextSibling()->isFloating( ) && !anonymousBlock->nextSibling()->nextSibling()))) {
273 collapseAnonymousBlockChild(this, anonymousBlock);
274 }
275 }
276 }
277
278 static bool canMergeContiguousAnonymousBlocks(LayoutObject* prev, LayoutObject* next)
279 {
280 if ((prev && (!prev->isAnonymousBlock() || toLayoutBlock(prev)->continuation () || toLayoutBlock(prev)->beingDestroyed()))
281 || (next && (!next->isAnonymousBlock() || toLayoutBlock(next)->continuat ion() || toLayoutBlock(next)->beingDestroyed())))
282 return false;
283
284 if ((prev && (prev->isRubyRun() || prev->isRubyBase()))
285 || (next && (next->isRubyRun() || next->isRubyBase())))
286 return false;
287
288 return true;
289 }
290
291 static void mergeContiguousAnonymousBlocks(LayoutBlock* parent, LayoutObject*& p rev, LayoutObject*& next)
292 {
293 ASSERT(canMergeContiguousAnonymousBlocks(prev, next));
294 if (!prev || !next)
295 return;
296
297 prev->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvali dationReason::AnonymousBlockChange);
298 LayoutBlockFlow* nextBlock = toLayoutBlockFlow(next);
299 LayoutBlockFlow* prevBlock = toLayoutBlockFlow(prev);
300
301 if (prev->childrenInline() != next->childrenInline()) {
302 LayoutBlock* inlineChildrenBlock = prev->childrenInline() ? prevBlock : nextBlock;
303 LayoutBlock* blockChildrenBlock = prev->childrenInline() ? nextBlock : p revBlock;
304
305 // Place the inline children block inside of the block children block in stead of deleting it.
306 ASSERT(!inlineChildrenBlock->continuation());
307 bool inlineChildrenBlockHasLayer = inlineChildrenBlock->hasLayer();
308 parent->children()->removeChildNode(parent, inlineChildrenBlock, inlineC hildrenBlockHasLayer);
309
310 // Now just put the inlineChildrenBlock inside the blockChildrenBlock.
311 blockChildrenBlock->children()->insertChildNode(blockChildrenBlock, inli neChildrenBlock, prev == inlineChildrenBlock ? blockChildrenBlock->firstChild() : 0,
312 inlineChildrenBlockHasLayer || blockChildrenBlock->hasLayer());
313 next->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutIn validationReason::AnonymousBlockChange);
314
315 // inlineChildrenBlock got reparented to blockChildrenBlock, so it is no longer a child
316 // of "this". we null out prev or next so that is not used later in the function.
317 if (inlineChildrenBlock == prevBlock)
318 prev = nullptr;
319 else
320 next = nullptr;
321 } else {
322 // Take all the children out of the |next| block and put them in
323 // the |prev| block.
324 nextBlock->moveAllChildrenIncludingFloatsTo(prevBlock, nextBlock->hasLay er() || prevBlock->hasLayer());
325
326 // Delete the now-empty block's lines and nuke it.
327 nextBlock->deleteLineBoxTree();
328 nextBlock->destroy();
329 next = nullptr;
330 }
331 }
332
254 static void addNextFloatingOrOutOfFlowSiblingsToBlock(LayoutBlock* block) 333 static void addNextFloatingOrOutOfFlowSiblingsToBlock(LayoutBlock* block)
255 { 334 {
256 if (!block->parent() || !block->parent()->isLayoutBlockFlow()) 335 if (!block->parent() || !block->parent()->isLayoutBlockFlow())
257 return; 336 return;
258 if (block->beingDestroyed() || block->documentBeingDestroyed()) 337 if (block->beingDestroyed() || block->documentBeingDestroyed())
259 return; 338 return;
260 339
261 LayoutObject* child = block->nextSibling(); 340 LayoutObject* child = block->nextSibling();
341 LayoutBlock* parent = toLayoutBlock(block->parent());
262 while (child && child->isFloatingOrOutOfFlowPositioned()) { 342 while (child && child->isFloatingOrOutOfFlowPositioned()) {
263 LayoutObject* sibling = child->nextSibling(); 343 LayoutObject* sibling = child->nextSibling();
264 toLayoutBlock(block->parent())->moveChildTo(block, child, nullptr, false ); 344 parent->moveChildTo(block, child, nullptr, false);
265 child = sibling; 345 child = sibling;
266 } 346 }
347
348 LayoutObject* prev = block;
349 LayoutObject* next = block->nextSibling();
350 if (canMergeContiguousAnonymousBlocks(prev, next)) {
351 mergeContiguousAnonymousBlocks(parent, prev, next);
352 parent->collapseAnonymousBlockChildAfterMerge(prev, next, true);
rhogan 2016/03/03 21:48:36 Was forced into the use of parent-> by canCollapse
353 }
267 } 354 }
268 355
269 static void addPreviousFloatingOrOutOfFlowSiblingsToBlock(LayoutBlock* block) 356 static void addPreviousFloatingOrOutOfFlowSiblingsToBlock(LayoutBlock* block)
270 { 357 {
271 if (!block->parent() || !block->parent()->isLayoutBlockFlow()) 358 if (!block->parent() || !block->parent()->isLayoutBlockFlow())
272 return; 359 return;
273 if (block->beingDestroyed() || block->documentBeingDestroyed()) 360 if (block->beingDestroyed() || block->documentBeingDestroyed())
274 return; 361 return;
275 362
276 LayoutObject* child = block->previousSibling(); 363 LayoutObject* child = block->previousSibling();
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
613 if (child->parent()->isLayoutGrid()) 700 if (child->parent()->isLayoutGrid())
614 toLayoutGrid(child->parent())->dirtyGrid(); 701 toLayoutGrid(child->parent())->dirtyGrid();
615 702
616 // Now remove the leftover anonymous block from the tree, and destroy it. We 'll rip it out 703 // 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 704 // 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). 705 // adjustments with regards to anonymous blocks (or any other kind of undesi red chain-reaction).
619 children()->removeChildNode(this, child, false); 706 children()->removeChildNode(this, child, false);
620 child->destroy(); 707 child->destroy();
621 } 708 }
622 709
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() 710 void LayoutBlock::makeChildrenInlineIfPossible()
640 { 711 {
641 ASSERT(isLayoutBlockFlow()); 712 ASSERT(isLayoutBlockFlow());
642 // Collapsing away anonymous wrappers isn't relevant for the children of ano nymous blocks, unless they are ruby bases. 713 // Collapsing away anonymous wrappers isn't relevant for the children of ano nymous blocks, unless they are ruby bases.
643 if (isAnonymousBlock() && !isRubyBase()) 714 if (isAnonymousBlock() && !isRubyBase())
644 return; 715 return;
645 716
646 Vector<LayoutBlock*, 3> blocksToRemove; 717 Vector<LayoutBlock*, 3> blocksToRemove;
647 for (LayoutObject* child = firstChild(); child; child = child->nextSibling() ) { 718 for (LayoutObject* child = firstChild(); child; child = child->nextSibling() ) {
648 if (child->isFloating()) 719 if (child->isFloating())
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 if (documentBeingDestroyed()) { 779 if (documentBeingDestroyed()) {
709 LayoutBox::removeChild(oldChild); 780 LayoutBox::removeChild(oldChild);
710 return; 781 return;
711 } 782 }
712 783
713 // If this child is a block, and if our previous and next siblings are 784 // 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 785 // both anonymous blocks with inline content, then we can go ahead and
715 // fold the inline content back together. 786 // fold the inline content back together.
716 LayoutObject* prev = oldChild->previousSibling(); 787 LayoutObject* prev = oldChild->previousSibling();
717 LayoutObject* next = oldChild->nextSibling(); 788 LayoutObject* next = oldChild->nextSibling();
718 bool canMergeAnonymousBlocks = canMergeContiguousAnonymousBlocks(oldChild, p rev, next); 789 bool canMergeAnonymousBlocks = canMergeContiguousAnonymousBlocks(prev, next) && !oldChild->documentBeingDestroyed() && !oldChild->isInline() && !oldChild->v irtualContinuation();
719 if (canMergeAnonymousBlocks && prev && next) { 790 if (canMergeAnonymousBlocks)
720 prev->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutIn validationReason::AnonymousBlockChange); 791 mergeContiguousAnonymousBlocks(this, prev, next);
721 LayoutBlockFlow* nextBlock = toLayoutBlockFlow(next);
722 LayoutBlockFlow* prevBlock = toLayoutBlockFlow(prev);
723
724 if (prev->childrenInline() != next->childrenInline()) {
725 LayoutBlock* inlineChildrenBlock = prev->childrenInline() ? prevBloc k : nextBlock;
726 LayoutBlock* blockChildrenBlock = prev->childrenInline() ? nextBlock : prevBlock;
727
728 // Place the inline children block inside of the block children bloc k instead of deleting it.
729 ASSERT(!inlineChildrenBlock->continuation());
730 bool inlineChildrenBlockHasLayer = inlineChildrenBlock->hasLayer();
731 children()->removeChildNode(this, inlineChildrenBlock, inlineChildre nBlockHasLayer);
732
733 // Now just put the inlineChildrenBlock inside the blockChildrenBloc k.
734 blockChildrenBlock->children()->insertChildNode(blockChildrenBlock, inlineChildrenBlock, prev == inlineChildrenBlock ? blockChildrenBlock->firstChil d() : 0,
735 inlineChildrenBlockHasLayer || blockChildrenBlock->hasLayer());
736 next->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(Layo utInvalidationReason::AnonymousBlockChange);
737
738 // inlineChildrenBlock got reparented to blockChildrenBlock, so it i s no longer a child
739 // of "this". we null out prev or next so that is not used later in the function.
740 if (inlineChildrenBlock == prevBlock)
741 prev = nullptr;
742 else
743 next = nullptr;
744 } else {
745 // Take all the children out of the |next| block and put them in
746 // the |prev| block.
747 nextBlock->moveAllChildrenIncludingFloatsTo(prevBlock, nextBlock->ha sLayer() || prevBlock->hasLayer());
748
749 // Delete the now-empty block's lines and nuke it.
750 nextBlock->deleteLineBoxTree();
751 nextBlock->destroy();
752 next = nullptr;
753 }
754 }
755 792
756 LayoutBox::removeChild(oldChild); 793 LayoutBox::removeChild(oldChild);
757 794
758 LayoutObject* child = prev ? prev : next; 795 collapseAnonymousBlockChildAfterMerge(prev, next, canMergeAnonymousBlocks);
759 if (canMergeAnonymousBlocks && child && !child->previousSibling() && !child- >nextSibling() && canCollapseAnonymousBlockChild()) {
760 // The removal has knocked us down to containing only a single anonymous
761 // box. We can go ahead and pull the content right back up into our
762 // box.
763 collapseAnonymousBlockChild(this, toLayoutBlock(child));
764 } else if (((prev && prev->isAnonymousBlock()) || (next && next->isAnonymous Block())) && canCollapseAnonymousBlockChild()) {
765 // It's possible that the removal has knocked us down to a single anonym ous
766 // block with pseudo-style element siblings (e.g. first-letter). If thes e
767 // are floating, then we need to pull the content up also.
768 LayoutBlock* anonymousBlock = toLayoutBlock((prev && prev->isAnonymousBl ock()) ? prev : next);
769 if ((anonymousBlock->previousSibling() || anonymousBlock->nextSibling())
770 && (!anonymousBlock->previousSibling() || (anonymousBlock->previousS ibling()->style()->styleType() != NOPSEUDO && anonymousBlock->previousSibling()- >isFloating() && !anonymousBlock->previousSibling()->previousSibling()))
771 && (!anonymousBlock->nextSibling() || (anonymousBlock->nextSibling() ->style()->styleType() != NOPSEUDO && anonymousBlock->nextSibling()->isFloating( ) && !anonymousBlock->nextSibling()->nextSibling()))) {
772 collapseAnonymousBlockChild(this, anonymousBlock);
773 }
774 }
775 796
776 if (!firstChild()) { 797 if (!firstChild()) {
777 // If this was our last child be sure to clear out our line boxes. 798 // If this was our last child be sure to clear out our line boxes.
778 if (childrenInline()) 799 if (childrenInline())
779 deleteLineBoxTree(); 800 deleteLineBoxTree();
780 801
781 // If we are an empty anonymous block in the continuation chain, 802 // If we are an empty anonymous block in the continuation chain,
782 // we need to remove ourself and fix the continuation chain. 803 // we need to remove ourself and fix the continuation chain.
783 if (!beingDestroyed() && isAnonymousBlockContinuation() && !oldChild->is ListMarker()) { 804 if (!beingDestroyed() && isAnonymousBlockContinuation() && !oldChild->is ListMarker()) {
784 LayoutObject* containingBlockIgnoringAnonymous = containingBlock(); 805 LayoutObject* containingBlockIgnoringAnonymous = containingBlock();
(...skipping 2121 matching lines...) Expand 10 before | Expand all | Expand 10 after
2906 void LayoutBlock::showLineTreeAndMark(const InlineBox* markedBox1, const char* m arkedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const Layout Object* obj) const 2927 void LayoutBlock::showLineTreeAndMark(const InlineBox* markedBox1, const char* m arkedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const Layout Object* obj) const
2907 { 2928 {
2908 showLayoutObject(); 2929 showLayoutObject();
2909 for (const RootInlineBox* root = firstRootBox(); root; root = root->nextRoot Box()) 2930 for (const RootInlineBox* root = firstRootBox(); root; root = root->nextRoot Box())
2910 root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLa bel2, obj, 1); 2931 root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLa bel2, obj, 1);
2911 } 2932 }
2912 2933
2913 #endif 2934 #endif
2914 2935
2915 } // namespace blink 2936 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698