Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |