2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
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.
6 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
25 #include "RenderBlock.h"
27 #include "AXObjectCache.h"
28 #include "ColumnInfo.h"
32 #include "FloatQuad.h"
34 #include "FrameSelection.h"
35 #include "FrameView.h"
36 #include "GraphicsContext.h"
37 #include "HTMLNames.h"
38 #include "HitTestLocation.h"
39 #include "HitTestResult.h"
40 #include "InlineIterator.h"
41 #include "InlineTextBox.h"
42 #include "LayoutRepainter.h"
43 #include "LogicalSelectionOffsetCaches.h"
44 #include "OverflowEvent.h"
46 #include "PaintInfo.h"
47 #include "RenderBoxRegionInfo.h"
48 #include "RenderCombineText.h"
49 #include "RenderDeprecatedFlexibleBox.h"
50 #include "RenderFlexibleBox.h"
51 #include "RenderInline.h"
52 #include "RenderLayer.h"
53 #include "RenderMarquee.h"
54 #include "RenderNamedFlowThread.h"
55 #include "RenderRegion.h"
56 #include "RenderTableCell.h"
57 #include "RenderTextFragment.h"
58 #include "RenderTheme.h"
59 #include "RenderView.h"
60 #include "SVGTextRunRenderingContext.h"
62 #include "ShadowRoot.h"
63 #include "TransformState.h"
64 #include <wtf/StackStats.h>
65 #include <wtf/TemporaryChange.h>
67 #if ENABLE(CSS_SHAPES)
68 #include "ExclusionShapeInsideInfo.h"
69 #include "ExclusionShapeOutsideInfo.h"
74 using namespace Unicode;
78 using namespace HTMLNames;
80 struct SameSizeAsRenderBlock : public RenderBox {
82 RenderObjectChildList children;
83 RenderLineBoxList lineBoxes;
87 COMPILE_ASSERT(sizeof(RenderBlock) == sizeof(SameSizeAsRenderBlock), RenderBlock_should_stay_small);
89 struct SameSizeAsFloatingObject {
93 uint32_t bitfields : 8;
96 COMPILE_ASSERT(sizeof(RenderBlock::MarginValues) == sizeof(LayoutUnit[4]), MarginValues_should_stay_small);
98 struct SameSizeAsMarginInfo {
99 uint32_t bitfields : 16;
100 LayoutUnit margins[2];
103 typedef WTF::HashMap<const RenderBox*, OwnPtr<ColumnInfo> > ColumnInfoMap;
104 static ColumnInfoMap* gColumnInfoMap = 0;
106 static TrackedDescendantsMap* gPositionedDescendantsMap = 0;
107 static TrackedDescendantsMap* gPercentHeightDescendantsMap = 0;
109 static TrackedContainerMap* gPositionedContainerMap = 0;
110 static TrackedContainerMap* gPercentHeightContainerMap = 0;
112 typedef WTF::HashMap<RenderBlock*, OwnPtr<ListHashSet<RenderInline*> > > ContinuationOutlineTableMap;
114 typedef WTF::HashSet<RenderBlock*> DelayedUpdateScrollInfoSet;
115 static int gDelayUpdateScrollInfo = 0;
116 static DelayedUpdateScrollInfoSet* gDelayedUpdateScrollInfoSet = 0;
118 static bool gColumnFlowSplitEnabled = true;
120 bool RenderBlock::s_canPropagateFloatIntoSibling = false;
122 // This class helps dispatching the 'overflow' event on layout change. overflow can be set on RenderBoxes, yet the existing code
123 // only works on RenderBlocks. If this change, this class should be shared with other RenderBoxes.
124 class OverflowEventDispatcher {
125 WTF_MAKE_NONCOPYABLE(OverflowEventDispatcher);
127 OverflowEventDispatcher(const RenderBlock* block)
129 , m_hadHorizontalLayoutOverflow(false)
130 , m_hadVerticalLayoutOverflow(false)
132 m_shouldDispatchEvent = !m_block->isAnonymous() && m_block->hasOverflowClip() && m_block->document()->hasListenerType(Document::OVERFLOWCHANGED_LISTENER);
133 if (m_shouldDispatchEvent) {
134 m_hadHorizontalLayoutOverflow = m_block->hasHorizontalLayoutOverflow();
135 m_hadVerticalLayoutOverflow = m_block->hasVerticalLayoutOverflow();
139 ~OverflowEventDispatcher()
141 if (!m_shouldDispatchEvent)
144 bool hasHorizontalLayoutOverflow = m_block->hasHorizontalLayoutOverflow();
145 bool hasVerticalLayoutOverflow = m_block->hasVerticalLayoutOverflow();
147 bool horizontalLayoutOverflowChanged = hasHorizontalLayoutOverflow != m_hadHorizontalLayoutOverflow;
148 bool verticalLayoutOverflowChanged = hasVerticalLayoutOverflow != m_hadVerticalLayoutOverflow;
149 if (horizontalLayoutOverflowChanged || verticalLayoutOverflowChanged) {
150 if (FrameView* frameView = m_block->document()->view())
151 frameView->scheduleEvent(OverflowEvent::create(horizontalLayoutOverflowChanged, hasHorizontalLayoutOverflow, verticalLayoutOverflowChanged, hasVerticalLayoutOverflow), m_block->node());
156 const RenderBlock* m_block;
157 bool m_shouldDispatchEvent;
158 bool m_hadHorizontalLayoutOverflow;
159 bool m_hadVerticalLayoutOverflow;
162 // Our MarginInfo state used when laying out block children.
163 RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, LayoutUnit beforeBorderPadding, LayoutUnit afterBorderPadding)
164 : m_atBeforeSideOfBlock(true)
165 , m_atAfterSideOfBlock(false)
166 , m_hasMarginBeforeQuirk(false)
167 , m_hasMarginAfterQuirk(false)
168 , m_determinedMarginBeforeQuirk(false)
169 , m_discardMargin(false)
171 RenderStyle* blockStyle = block->style();
172 ASSERT(block->isRenderView() || block->parent());
173 m_canCollapseWithChildren = !block->isRenderView() && !block->isRoot() && !block->isOutOfFlowPositioned()
174 && !block->isFloating() && !block->isTableCell() && !block->hasOverflowClip() && !block->isInlineBlockOrInlineTable()
175 && !block->isRenderFlowThread() && !block->isWritingModeRoot() && !block->parent()->isFlexibleBox()
176 && blockStyle->hasAutoColumnCount() && blockStyle->hasAutoColumnWidth() && !blockStyle->columnSpan();
178 m_canCollapseMarginBeforeWithChildren = m_canCollapseWithChildren && !beforeBorderPadding && blockStyle->marginBeforeCollapse() != MSEPARATE;
180 // If any height other than auto is specified in CSS, then we don't collapse our bottom
181 // margins with our children's margins. To do otherwise would be to risk odd visual
182 // effects when the children overflow out of the parent block and yet still collapse
183 // with it. We also don't collapse if we have any bottom border/padding.
184 m_canCollapseMarginAfterWithChildren = m_canCollapseWithChildren && (afterBorderPadding == 0) &&
185 (blockStyle->logicalHeight().isAuto() && !blockStyle->logicalHeight().value()) && blockStyle->marginAfterCollapse() != MSEPARATE;
187 m_quirkContainer = block->isTableCell() || block->isBody();
189 m_discardMargin = m_canCollapseMarginBeforeWithChildren && block->mustDiscardMarginBefore();
191 m_positiveMargin = (m_canCollapseMarginBeforeWithChildren && !block->mustDiscardMarginBefore()) ? block->maxPositiveMarginBefore() : LayoutUnit();
192 m_negativeMargin = (m_canCollapseMarginBeforeWithChildren && !block->mustDiscardMarginBefore()) ? block->maxNegativeMarginBefore() : LayoutUnit();
195 // -------------------------------------------------------------------------------------------------------
197 RenderBlock::RenderBlock(ContainerNode* node)
200 , m_hasMarginBeforeQuirk(false)
201 , m_hasMarginAfterQuirk(false)
202 , m_beingDestroyed(false)
203 , m_hasMarkupTruncation(false)
204 , m_hasBorderOrPaddingLogicalWidthChanged(false)
206 setChildrenInline(true);
207 COMPILE_ASSERT(sizeof(RenderBlock::FloatingObject) == sizeof(SameSizeAsFloatingObject), FloatingObject_should_stay_small);
208 COMPILE_ASSERT(sizeof(RenderBlock::MarginInfo) == sizeof(SameSizeAsMarginInfo), MarginInfo_should_stay_small);
211 static void removeBlockFromDescendantAndContainerMaps(RenderBlock* block, TrackedDescendantsMap*& descendantMap, TrackedContainerMap*& containerMap)
213 if (OwnPtr<TrackedRendererListHashSet> descendantSet = descendantMap->take(block)) {
214 TrackedRendererListHashSet::iterator end = descendantSet->end();
215 for (TrackedRendererListHashSet::iterator descendant = descendantSet->begin(); descendant != end; ++descendant) {
216 TrackedContainerMap::iterator it = containerMap->find(*descendant);
217 ASSERT(it != containerMap->end());
218 if (it == containerMap->end())
220 HashSet<RenderBlock*>* containerSet = it->value.get();
221 ASSERT(containerSet->contains(block));
222 containerSet->remove(block);
223 if (containerSet->isEmpty())
224 containerMap->remove(it);
229 RenderBlock::~RenderBlock()
231 if (m_floatingObjects)
232 deleteAllValues(m_floatingObjects->set());
235 gColumnInfoMap->take(this);
237 if (gPercentHeightDescendantsMap)
238 removeBlockFromDescendantAndContainerMaps(this, gPercentHeightDescendantsMap, gPercentHeightContainerMap);
239 if (gPositionedDescendantsMap)
240 removeBlockFromDescendantAndContainerMaps(this, gPositionedDescendantsMap, gPositionedContainerMap);
243 RenderBlock* RenderBlock::createAnonymous(Document* document)
245 RenderBlock* renderer = new (document->renderArena()) RenderBlock(0);
246 renderer->setDocumentForAnonymous(document);
250 void RenderBlock::willBeDestroyed()
252 // Mark as being destroyed to avoid trouble with merges in removeChild().
253 m_beingDestroyed = true;
255 if (!documentBeingDestroyed()) {
256 if (firstChild() && firstChild()->isRunIn())
257 moveRunInToOriginalPosition(firstChild());
260 // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will
261 // properly dirty line boxes that they are removed from. Effects that do :before/:after only on hover could crash otherwise.
262 children()->destroyLeftoverChildren();
264 // Destroy our continuation before anything other than anonymous children.
265 // The reason we don't destroy it before anonymous children is that they may
266 // have continuations of their own that are anonymous children of our continuation.
267 RenderBoxModelObject* continuation = this->continuation();
269 continuation->destroy();
273 if (!documentBeingDestroyed()) {
274 if (firstLineBox()) {
275 // We can't wait for RenderBox::destroy to clear the selection,
276 // because by then we will have nuked the line boxes.
277 // FIXME: The FrameSelection should be responsible for this when it
278 // is notified of DOM mutations.
279 if (isSelectionBorder())
280 view()->clearSelection();
282 // If we are an anonymous block, then our line boxes might have children
283 // that will outlast this block. In the non-anonymous block case those
284 // children will be destroyed by the time we return from this function.
285 if (isAnonymousBlock()) {
286 for (InlineFlowBox* box = firstLineBox(); box; box = box->nextLineBox()) {
287 while (InlineBox* childBox = box->firstChild())
292 parent()->dirtyLinesFromChangedChild(this);
295 m_lineBoxes.deleteLineBoxes(renderArena());
298 lineGridBox()->destroy(renderArena());
300 if (UNLIKELY(gDelayedUpdateScrollInfoSet != 0))
301 gDelayedUpdateScrollInfoSet->remove(this);
303 RenderBox::willBeDestroyed();
306 void RenderBlock::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
308 RenderStyle* oldStyle = style();
309 s_canPropagateFloatIntoSibling = oldStyle ? !isFloatingOrOutOfFlowPositioned() && !avoidsFloats() : false;
311 setReplaced(newStyle->isDisplayInlineType());
313 if (oldStyle && parent() && diff == StyleDifferenceLayout && oldStyle->position() != newStyle->position()) {
314 if (newStyle->position() == StaticPosition)
315 // Clear our positioned objects list. Our absolutely positioned descendants will be
316 // inserted into our containing block's positioned objects list during layout.
317 removePositionedObjects(0, NewContainingBlock);
318 else if (oldStyle->position() == StaticPosition) {
319 // Remove our absolutely positioned descendants from their current containing block.
320 // They will be inserted into our positioned objects list during layout.
321 RenderObject* cb = parent();
322 while (cb && (cb->style()->position() == StaticPosition || (cb->isInline() && !cb->isReplaced())) && !cb->isRenderView()) {
323 if (cb->style()->position() == RelativePosition && cb->isInline() && !cb->isReplaced()) {
324 cb = cb->containingBlock();
330 if (cb->isRenderBlock())
331 toRenderBlock(cb)->removePositionedObjects(this, NewContainingBlock);
334 if (containsFloats() && !isFloating() && !isOutOfFlowPositioned() && newStyle->hasOutOfFlowPosition())
335 markAllDescendantsWithFloatsForLayout();
338 RenderBox::styleWillChange(diff, newStyle);
341 static bool borderOrPaddingLogicalWidthChanged(const RenderStyle* oldStyle, const RenderStyle* newStyle)
343 if (newStyle->isHorizontalWritingMode())
344 return oldStyle->borderLeftWidth() != newStyle->borderLeftWidth()
345 || oldStyle->borderRightWidth() != newStyle->borderRightWidth()
346 || oldStyle->paddingLeft() != newStyle->paddingLeft()
347 || oldStyle->paddingRight() != newStyle->paddingRight();
349 return oldStyle->borderTopWidth() != newStyle->borderTopWidth()
350 || oldStyle->borderBottomWidth() != newStyle->borderBottomWidth()
351 || oldStyle->paddingTop() != newStyle->paddingTop()
352 || oldStyle->paddingBottom() != newStyle->paddingBottom();
355 void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
357 RenderBox::styleDidChange(diff, oldStyle);
359 RenderStyle* newStyle = style();
361 #if ENABLE(CSS_SHAPES)
362 // FIXME: Bug 89993: Style changes should affect the ExclusionShapeInsideInfos for other render blocks that
363 // share the same ExclusionShapeInsideInfo
364 updateExclusionShapeInsideInfoAfterStyleChange(newStyle->resolvedShapeInside(), oldStyle ? oldStyle->resolvedShapeInside() : 0);
367 if (!isAnonymousBlock()) {
368 // Ensure that all of our continuation blocks pick up the new style.
369 for (RenderBlock* currCont = blockElementContinuation(); currCont; currCont = currCont->blockElementContinuation()) {
370 RenderBoxModelObject* nextCont = currCont->continuation();
371 currCont->setContinuation(0);
372 currCont->setStyle(newStyle);
373 currCont->setContinuation(nextCont);
377 propagateStyleToAnonymousChildren(true);
380 // After our style changed, if we lose our ability to propagate floats into next sibling
381 // blocks, then we need to find the top most parent containing that overhanging float and
382 // then mark its descendants with floats for layout and clear all floats from its next
383 // sibling blocks that exist in our floating objects list. See bug 56299 and 62875.
384 bool canPropagateFloatIntoSibling = !isFloatingOrOutOfFlowPositioned() && !avoidsFloats();
385 if (diff == StyleDifferenceLayout && s_canPropagateFloatIntoSibling && !canPropagateFloatIntoSibling && hasOverhangingFloats()) {
386 RenderBlock* parentBlock = this;
387 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
388 FloatingObjectSetIterator end = floatingObjectSet.end();
390 for (RenderObject* curr = parent(); curr && !curr->isRenderView(); curr = curr->parent()) {
391 if (curr->isRenderBlock()) {
392 RenderBlock* currBlock = toRenderBlock(curr);
394 if (currBlock->hasOverhangingFloats()) {
395 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
396 RenderBox* renderer = (*it)->renderer();
397 if (currBlock->hasOverhangingFloat(renderer)) {
398 parentBlock = currBlock;
406 parentBlock->markAllDescendantsWithFloatsForLayout();
407 parentBlock->markSiblingsWithFloatsForLayout();
410 // It's possible for our border/padding to change, but for the overall logical width of the block to
411 // end up being the same. We keep track of this change so in layoutBlock, we can know to set relayoutChildren=true.
412 m_hasBorderOrPaddingLogicalWidthChanged = oldStyle && diff == StyleDifferenceLayout && needsLayout() && borderOrPaddingLogicalWidthChanged(oldStyle, newStyle);
415 RenderBlock* RenderBlock::continuationBefore(RenderObject* beforeChild)
417 if (beforeChild && beforeChild->parent() == this)
420 RenderBlock* curr = toRenderBlock(continuation());
421 RenderBlock* nextToLast = this;
422 RenderBlock* last = this;
424 if (beforeChild && beforeChild->parent() == curr) {
425 if (curr->firstChild() == beforeChild)
432 curr = toRenderBlock(curr->continuation());
435 if (!beforeChild && !last->firstChild())
440 void RenderBlock::addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild)
442 RenderBlock* flow = continuationBefore(beforeChild);
443 ASSERT(!beforeChild || beforeChild->parent()->isAnonymousColumnSpanBlock() || beforeChild->parent()->isRenderBlock());
444 RenderBoxModelObject* beforeChildParent = 0;
446 beforeChildParent = toRenderBoxModelObject(beforeChild->parent());
448 RenderBoxModelObject* cont = flow->continuation();
450 beforeChildParent = cont;
452 beforeChildParent = flow;
455 if (newChild->isFloatingOrOutOfFlowPositioned()) {
456 beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
460 // A continuation always consists of two potential candidates: a block or an anonymous
461 // column span box holding column span children.
462 bool childIsNormal = newChild->isInline() || !newChild->style()->columnSpan();
463 bool bcpIsNormal = beforeChildParent->isInline() || !beforeChildParent->style()->columnSpan();
464 bool flowIsNormal = flow->isInline() || !flow->style()->columnSpan();
466 if (flow == beforeChildParent) {
467 flow->addChildIgnoringContinuation(newChild, beforeChild);
471 // The goal here is to match up if we can, so that we can coalesce and create the
472 // minimal # of continuations needed for the inline.
473 if (childIsNormal == bcpIsNormal) {
474 beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
477 if (flowIsNormal == childIsNormal) {
478 flow->addChildIgnoringContinuation(newChild, 0); // Just treat like an append.
481 beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
485 void RenderBlock::addChildToAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild)
487 ASSERT(!continuation()); // We don't yet support column spans that aren't immediate children of the multi-column block.
489 // The goal is to locate a suitable box in which to place our child.
490 RenderBlock* beforeChildParent = 0;
492 RenderObject* curr = beforeChild;
493 while (curr && curr->parent() != this)
494 curr = curr->parent();
495 beforeChildParent = toRenderBlock(curr);
496 ASSERT(beforeChildParent);
497 ASSERT(beforeChildParent->isAnonymousColumnsBlock() || beforeChildParent->isAnonymousColumnSpanBlock());
499 beforeChildParent = toRenderBlock(lastChild());
501 // If the new child is floating or positioned it can just go in that block.
502 if (newChild->isFloatingOrOutOfFlowPositioned()) {
503 beforeChildParent->addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild);
507 // See if the child can be placed in the box.
508 bool newChildHasColumnSpan = newChild->style()->columnSpan() && !newChild->isInline();
509 bool beforeChildParentHoldsColumnSpans = beforeChildParent->isAnonymousColumnSpanBlock();
511 if (newChildHasColumnSpan == beforeChildParentHoldsColumnSpans) {
512 beforeChildParent->addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild);
517 // Create a new block of the correct type.
518 RenderBlock* newBox = newChildHasColumnSpan ? createAnonymousColumnSpanBlock() : createAnonymousColumnsBlock();
519 children()->appendChildNode(this, newBox);
520 newBox->addChildIgnoringAnonymousColumnBlocks(newChild, 0);
524 RenderObject* immediateChild = beforeChild;
525 bool isPreviousBlockViable = true;
526 while (immediateChild->parent() != this) {
527 if (isPreviousBlockViable)
528 isPreviousBlockViable = !immediateChild->previousSibling();
529 immediateChild = immediateChild->parent();
531 if (isPreviousBlockViable && immediateChild->previousSibling()) {
532 toRenderBlock(immediateChild->previousSibling())->addChildIgnoringAnonymousColumnBlocks(newChild, 0); // Treat like an append.
536 // Split our anonymous blocks.
537 RenderObject* newBeforeChild = splitAnonymousBoxesAroundChild(beforeChild);
540 // Create a new anonymous box of the appropriate type.
541 RenderBlock* newBox = newChildHasColumnSpan ? createAnonymousColumnSpanBlock() : createAnonymousColumnsBlock();
542 children()->insertChildNode(this, newBox, newBeforeChild);
543 newBox->addChildIgnoringAnonymousColumnBlocks(newChild, 0);
547 RenderBlock* RenderBlock::containingColumnsBlock(bool allowAnonymousColumnBlock)
549 RenderBlock* firstChildIgnoringAnonymousWrappers = 0;
550 for (RenderObject* curr = this; curr; curr = curr->parent()) {
551 if (!curr->isRenderBlock() || curr->isFloatingOrOutOfFlowPositioned() || curr->isTableCell() || curr->isRoot() || curr->isRenderView() || curr->hasOverflowClip()
552 || curr->isInlineBlockOrInlineTable())
555 // FIXME: Tables, RenderButtons, and RenderListItems all do special management
556 // of their children that breaks when the flow is split through them. Disabling
557 // multi-column for them to avoid this problem.
558 if (curr->isTable() || curr->isRenderButton() || curr->isListItem())
561 RenderBlock* currBlock = toRenderBlock(curr);
562 if (!currBlock->createsAnonymousWrapper())
563 firstChildIgnoringAnonymousWrappers = currBlock;
565 if (currBlock->style()->specifiesColumns() && (allowAnonymousColumnBlock || !currBlock->isAnonymousColumnsBlock()))
566 return firstChildIgnoringAnonymousWrappers;
568 if (currBlock->isAnonymousColumnSpanBlock())
574 RenderBlock* RenderBlock::clone() const
576 RenderBlock* cloneBlock;
577 if (isAnonymousBlock()) {
578 cloneBlock = createAnonymousBlock();
579 cloneBlock->setChildrenInline(childrenInline());
582 RenderObject* cloneRenderer = toElement(node())->createRenderer(renderArena(), style());
583 cloneBlock = toRenderBlock(cloneRenderer);
584 cloneBlock->setStyle(style());
586 // This takes care of setting the right value of childrenInline in case
587 // generated content is added to cloneBlock and 'this' does not have
588 // generated content added yet.
589 cloneBlock->setChildrenInline(cloneBlock->firstChild() ? cloneBlock->firstChild()->isInline() : childrenInline());
591 cloneBlock->setFlowThreadState(flowThreadState());
595 void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock,
596 RenderBlock* middleBlock,
597 RenderObject* beforeChild, RenderBoxModelObject* oldCont)
599 // Create a clone of this inline.
600 RenderBlock* cloneBlock = clone();
601 if (!isAnonymousBlock())
602 cloneBlock->setContinuation(oldCont);
604 if (!beforeChild && isAfterContent(lastChild()))
605 beforeChild = lastChild();
607 // If we are moving inline children from |this| to cloneBlock, then we need
608 // to clear our line box tree.
609 if (beforeChild && childrenInline())
612 // Now take all of the children from beforeChild to the end and remove
613 // them from |this| and place them in the clone.
614 moveChildrenTo(cloneBlock, beforeChild, 0, true);
616 // Hook |clone| up as the continuation of the middle block.
617 if (!cloneBlock->isAnonymousBlock())
618 middleBlock->setContinuation(cloneBlock);
620 // We have been reparented and are now under the fromBlock. We need
621 // to walk up our block parent chain until we hit the containing anonymous columns block.
622 // Once we hit the anonymous columns block we're done.
623 RenderBoxModelObject* curr = toRenderBoxModelObject(parent());
624 RenderBoxModelObject* currChild = this;
625 RenderObject* currChildNextSibling = currChild->nextSibling();
627 while (curr && curr != fromBlock) {
628 ASSERT_WITH_SECURITY_IMPLICATION(curr->isRenderBlock());
630 RenderBlock* blockCurr = toRenderBlock(curr);
632 // Create a new clone.
633 RenderBlock* cloneChild = cloneBlock;
634 cloneBlock = blockCurr->clone();
636 // Insert our child clone as the first child.
637 cloneBlock->addChildIgnoringContinuation(cloneChild, 0);
639 // Hook the clone up as a continuation of |curr|. Note we do encounter
640 // anonymous blocks possibly as we walk up the block chain. When we split an
641 // anonymous block, there's no need to do any continuation hookup, since we haven't
642 // actually split a real element.
643 if (!blockCurr->isAnonymousBlock()) {
644 oldCont = blockCurr->continuation();
645 blockCurr->setContinuation(cloneBlock);
646 cloneBlock->setContinuation(oldCont);
649 // Now we need to take all of the children starting from the first child
650 // *after* currChild and append them all to the clone.
651 blockCurr->moveChildrenTo(cloneBlock, currChildNextSibling, 0, true);
653 // Keep walking up the chain.
655 currChildNextSibling = currChild->nextSibling();
656 curr = toRenderBoxModelObject(curr->parent());
659 // Now we are at the columns block level. We need to put the clone into the toBlock.
660 toBlock->children()->appendChildNode(toBlock, cloneBlock);
662 // Now take all the children after currChild and remove them from the fromBlock
663 // and put them in the toBlock.
664 fromBlock->moveChildrenTo(toBlock, currChildNextSibling, 0, true);
667 void RenderBlock::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
668 RenderObject* newChild, RenderBoxModelObject* oldCont)
670 RenderBlock* pre = 0;
671 RenderBlock* block = containingColumnsBlock();
673 // Delete our line boxes before we do the inline split into continuations.
674 block->deleteLineBoxTree();
676 bool madeNewBeforeBlock = false;
677 if (block->isAnonymousColumnsBlock()) {
678 // We can reuse this block and make it the preBlock of the next continuation.
680 pre->removePositionedObjects(0);
681 pre->removeFloatingObjects();
682 block = toRenderBlock(block->parent());
684 // No anonymous block available for use. Make one.
685 pre = block->createAnonymousColumnsBlock();
686 pre->setChildrenInline(false);
687 madeNewBeforeBlock = true;
690 RenderBlock* post = block->createAnonymousColumnsBlock();
691 post->setChildrenInline(false);
693 RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling();
694 if (madeNewBeforeBlock)
695 block->children()->insertChildNode(block, pre, boxFirst);
696 block->children()->insertChildNode(block, newBlockBox, boxFirst);
697 block->children()->insertChildNode(block, post, boxFirst);
698 block->setChildrenInline(false);
700 if (madeNewBeforeBlock)
701 block->moveChildrenTo(pre, boxFirst, 0, true);
703 splitBlocks(pre, post, newBlockBox, beforeChild, oldCont);
705 // We already know the newBlockBox isn't going to contain inline kids, so avoid wasting
706 // time in makeChildrenNonInline by just setting this explicitly up front.
707 newBlockBox->setChildrenInline(false);
709 // We delayed adding the newChild until now so that the |newBlockBox| would be fully
710 // connected, thus allowing newChild access to a renderArena should it need
711 // to wrap itself in additional boxes (e.g., table construction).
712 newBlockBox->addChild(newChild);
714 // Always just do a full layout in order to ensure that line boxes (especially wrappers for images)
715 // get deleted properly. Because objects moves from the pre block into the post block, we want to
716 // make new line boxes instead of leaving the old line boxes around.
717 pre->setNeedsLayoutAndPrefWidthsRecalc();
718 block->setNeedsLayoutAndPrefWidthsRecalc();
719 post->setNeedsLayoutAndPrefWidthsRecalc();
722 void RenderBlock::makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, RenderBlock* newBlockBox, RenderObject* newChild)
724 RenderBlock* pre = 0;
725 RenderBlock* post = 0;
726 RenderBlock* block = this; // Eventually block will not just be |this|, but will also be a block nested inside |this|. Assign to a variable
727 // so that we don't have to patch all of the rest of the code later on.
729 // Delete the block's line boxes before we do the split.
730 block->deleteLineBoxTree();
732 if (beforeChild && beforeChild->parent() != this)
733 beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
735 if (beforeChild != firstChild()) {
736 pre = block->createAnonymousColumnsBlock();
737 pre->setChildrenInline(block->childrenInline());
741 post = block->createAnonymousColumnsBlock();
742 post->setChildrenInline(block->childrenInline());
745 RenderObject* boxFirst = block->firstChild();
747 block->children()->insertChildNode(block, pre, boxFirst);
748 block->children()->insertChildNode(block, newBlockBox, boxFirst);
750 block->children()->insertChildNode(block, post, boxFirst);
751 block->setChildrenInline(false);
753 // The pre/post blocks always have layers, so we know to always do a full insert/remove (so we pass true as the last argument).
754 block->moveChildrenTo(pre, boxFirst, beforeChild, true);
755 block->moveChildrenTo(post, beforeChild, 0, true);
757 // We already know the newBlockBox isn't going to contain inline kids, so avoid wasting
758 // time in makeChildrenNonInline by just setting this explicitly up front.
759 newBlockBox->setChildrenInline(false);
761 // We delayed adding the newChild until now so that the |newBlockBox| would be fully
762 // connected, thus allowing newChild access to a renderArena should it need
763 // to wrap itself in additional boxes (e.g., table construction).
764 newBlockBox->addChild(newChild);
766 // Always just do a full layout in order to ensure that line boxes (especially wrappers for images)
767 // get deleted properly. Because objects moved from the pre block into the post block, we want to
768 // make new line boxes instead of leaving the old line boxes around.
770 pre->setNeedsLayoutAndPrefWidthsRecalc();
771 block->setNeedsLayoutAndPrefWidthsRecalc();
773 post->setNeedsLayoutAndPrefWidthsRecalc();
776 RenderBlock* RenderBlock::columnsBlockForSpanningElement(RenderObject* newChild)
778 // FIXME: This function is the gateway for the addition of column-span support. It will
779 // be added to in three stages:
780 // (1) Immediate children of a multi-column block can span.
781 // (2) Nested block-level children with only block-level ancestors between them and the multi-column block can span.
782 // (3) Nested children with block or inline ancestors between them and the multi-column block can span (this is when we
783 // cross the streams and have to cope with both types of continuations mixed together).
784 // This function currently supports (1) and (2).
785 RenderBlock* columnsBlockAncestor = 0;
786 if (!newChild->isText() && newChild->style()->columnSpan() && !newChild->isBeforeOrAfterContent()
787 && !newChild->isFloatingOrOutOfFlowPositioned() && !newChild->isInline() && !isAnonymousColumnSpanBlock()) {
788 columnsBlockAncestor = containingColumnsBlock(false);
789 if (columnsBlockAncestor) {
790 // Make sure that none of the parent ancestors have a continuation.
791 // If yes, we do not want split the block into continuations.
792 RenderObject* curr = this;
793 while (curr && curr != columnsBlockAncestor) {
794 if (curr->isRenderBlock() && toRenderBlock(curr)->continuation()) {
795 columnsBlockAncestor = 0;
798 curr = curr->parent();
802 return columnsBlockAncestor;
805 void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild)
807 if (beforeChild && beforeChild->parent() != this) {
808 RenderObject* beforeChildContainer = beforeChild->parent();
809 while (beforeChildContainer->parent() != this)
810 beforeChildContainer = beforeChildContainer->parent();
811 ASSERT(beforeChildContainer);
813 if (beforeChildContainer->isAnonymous()) {
814 // If the requested beforeChild is not one of our children, then this is because
815 // there is an anonymous container within this object that contains the beforeChild.
816 RenderObject* beforeChildAnonymousContainer = beforeChildContainer;
817 if (beforeChildAnonymousContainer->isAnonymousBlock()
818 #if ENABLE(FULLSCREEN_API)
819 // Full screen renderers and full screen placeholders act as anonymous blocks, not tables:
820 || beforeChildAnonymousContainer->isRenderFullScreen()
821 || beforeChildAnonymousContainer->isRenderFullScreenPlaceholder()
824 // Insert the child into the anonymous block box instead of here.
825 if (newChild->isInline() || beforeChild->parent()->firstChild() != beforeChild)
826 beforeChild->parent()->addChild(newChild, beforeChild);
828 addChild(newChild, beforeChild->parent());
832 ASSERT(beforeChildAnonymousContainer->isTable());
833 if (newChild->isTablePart()) {
834 // Insert into the anonymous table.
835 beforeChildAnonymousContainer->addChild(newChild, beforeChild);
839 beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
841 ASSERT(beforeChild->parent() == this);
842 if (beforeChild->parent() != this) {
843 // We should never reach here. If we do, we need to use the
844 // safe fallback to use the topmost beforeChild container.
845 beforeChild = beforeChildContainer;
848 // We will reach here when beforeChild is a run-in element.
849 // If run-in element precedes a block-level element, it becomes the
850 // the first inline child of that block level element. The insertion
851 // point will be before that block-level element.
852 ASSERT(beforeChild->isRunIn());
853 beforeChild = beforeChildContainer;
857 // Nothing goes before the intruded run-in.
858 if (beforeChild && beforeChild->isRunIn() && runInIsPlacedIntoSiblingBlock(beforeChild))
859 beforeChild = beforeChild->nextSibling();
861 // Check for a spanning element in columns.
862 if (gColumnFlowSplitEnabled) {
863 RenderBlock* columnsBlockAncestor = columnsBlockForSpanningElement(newChild);
864 if (columnsBlockAncestor) {
865 TemporaryChange<bool> columnFlowSplitEnabled(gColumnFlowSplitEnabled, false);
866 // We are placing a column-span element inside a block.
867 RenderBlock* newBox = createAnonymousColumnSpanBlock();
869 if (columnsBlockAncestor != this && !isRenderFlowThread()) {
870 // We are nested inside a multi-column element and are being split by the span. We have to break up
871 // our block into continuations.
872 RenderBoxModelObject* oldContinuation = continuation();
874 // When we split an anonymous block, there's no need to do any continuation hookup,
875 // since we haven't actually split a real element.
876 if (!isAnonymousBlock())
877 setContinuation(newBox);
879 splitFlow(beforeChild, newBox, newChild, oldContinuation);
883 // We have to perform a split of this block's children. This involves creating an anonymous block box to hold
884 // the column-spanning |newChild|. We take all of the children from before |newChild| and put them into
885 // one anonymous columns block, and all of the children after |newChild| go into another anonymous block.
886 makeChildrenAnonymousColumnBlocks(beforeChild, newBox, newChild);
891 bool madeBoxesNonInline = false;
893 // A block has to either have all of its children inline, or all of its children as blocks.
894 // So, if our children are currently inline and a block child has to be inserted, we move all our
895 // inline children into anonymous block boxes.
896 if (childrenInline() && !newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned()) {
897 // This is a block with inline content. Wrap the inline content in anonymous blocks.
898 makeChildrenNonInline(beforeChild);
899 madeBoxesNonInline = true;
901 if (beforeChild && beforeChild->parent() != this) {
902 beforeChild = beforeChild->parent();
903 ASSERT(beforeChild->isAnonymousBlock());
904 ASSERT(beforeChild->parent() == this);
906 } else if (!childrenInline() && (newChild->isFloatingOrOutOfFlowPositioned() || newChild->isInline())) {
907 // If we're inserting an inline child but all of our children are blocks, then we have to make sure
908 // it is put into an anomyous block box. We try to use an existing anonymous box if possible, otherwise
909 // a new one is created and inserted into our list of children in the appropriate position.
910 RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : lastChild();
912 if (afterChild && afterChild->isAnonymousBlock()) {
913 afterChild->addChild(newChild);
917 if (newChild->isInline()) {
918 // No suitable existing anonymous box - create a new one.
919 RenderBlock* newBox = createAnonymousBlock();
920 RenderBox::addChild(newBox, beforeChild);
921 newBox->addChild(newChild);
926 RenderBox::addChild(newChild, beforeChild);
928 // Handle placement of run-ins.
929 placeRunInIfNeeded(newChild);
931 if (madeBoxesNonInline && parent() && isAnonymousBlock() && parent()->isRenderBlock())
932 toRenderBlock(parent())->removeLeftoverAnonymousBlock(this);
933 // this object may be dead here
936 void RenderBlock::addChild(RenderObject* newChild, RenderObject* beforeChild)
938 if (continuation() && !isAnonymousBlock())
939 addChildToContinuation(newChild, beforeChild);
941 addChildIgnoringContinuation(newChild, beforeChild);
944 void RenderBlock::addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild)
946 if (!isAnonymousBlock() && firstChild() && (firstChild()->isAnonymousColumnsBlock() || firstChild()->isAnonymousColumnSpanBlock()))
947 addChildToAnonymousColumnBlocks(newChild, beforeChild);
949 addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild);
952 static void getInlineRun(RenderObject* start, RenderObject* boundary,
953 RenderObject*& inlineRunStart,
954 RenderObject*& inlineRunEnd)
956 // Beginning at |start| we find the largest contiguous run of inlines that
957 // we can. We denote the run with start and end points, |inlineRunStart|
958 // and |inlineRunEnd|. Note that these two values may be the same if
959 // we encounter only one inline.
961 // We skip any non-inlines we encounter as long as we haven't found any
964 // |boundary| indicates a non-inclusive boundary point. Regardless of whether |boundary|
965 // is inline or not, we will not include it in a run with inlines before it. It's as though we encountered
968 // Start by skipping as many non-inlines as we can.
969 RenderObject * curr = start;
972 while (curr && !(curr->isInline() || curr->isFloatingOrOutOfFlowPositioned()))
973 curr = curr->nextSibling();
975 inlineRunStart = inlineRunEnd = curr;
978 return; // No more inline children to be found.
980 sawInline = curr->isInline();
982 curr = curr->nextSibling();
983 while (curr && (curr->isInline() || curr->isFloatingOrOutOfFlowPositioned()) && (curr != boundary)) {
985 if (curr->isInline())
987 curr = curr->nextSibling();
989 } while (!sawInline);
992 void RenderBlock::deleteLineBoxTree()
994 if (containsFloats()) {
995 // Clear references to originating lines, since the lines are being deleted
996 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
997 FloatingObjectSetIterator end = floatingObjectSet.end();
998 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
999 ASSERT(!((*it)->m_originatingLine) || (*it)->m_originatingLine->renderer() == this);
1000 (*it)->m_originatingLine = 0;
1003 m_lineBoxes.deleteLineBoxTree(renderArena());
1005 if (AXObjectCache* cache = document()->existingAXObjectCache())
1006 cache->recomputeIsIgnored(this);
1009 RootInlineBox* RenderBlock::createRootInlineBox()
1011 return new (renderArena()) RootInlineBox(this);
1014 RootInlineBox* RenderBlock::createAndAppendRootInlineBox()
1016 RootInlineBox* rootBox = createRootInlineBox();
1017 m_lineBoxes.appendLineBox(rootBox);
1019 if (UNLIKELY(AXObjectCache::accessibilityEnabled()) && m_lineBoxes.firstLineBox() == rootBox) {
1020 if (AXObjectCache* cache = document()->existingAXObjectCache())
1021 cache->recomputeIsIgnored(this);
1027 void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
1029 // makeChildrenNonInline takes a block whose children are *all* inline and it
1030 // makes sure that inline children are coalesced under anonymous
1031 // blocks. If |insertionPoint| is defined, then it represents the insertion point for
1032 // the new block child that is causing us to have to wrap all the inlines. This
1033 // means that we cannot coalesce inlines before |insertionPoint| with inlines following
1034 // |insertionPoint|, because the new child is going to be inserted in between the inlines,
1036 ASSERT(isInlineBlockOrInlineTable() || !isInline());
1037 ASSERT(!insertionPoint || insertionPoint->parent() == this);
1039 setChildrenInline(false);
1041 RenderObject *child = firstChild();
1045 deleteLineBoxTree();
1047 // Since we are going to have block children, we have to move
1048 // back the run-in to its original place.
1049 if (child->isRunIn()) {
1050 moveRunInToOriginalPosition(child);
1051 child = firstChild();
1055 RenderObject *inlineRunStart, *inlineRunEnd;
1056 getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd);
1058 if (!inlineRunStart)
1061 child = inlineRunEnd->nextSibling();
1063 RenderBlock* block = createAnonymousBlock();
1064 children()->insertChildNode(this, block, inlineRunStart);
1065 moveChildrenTo(block, inlineRunStart, child);
1069 for (RenderObject *c = firstChild(); c; c = c->nextSibling())
1070 ASSERT(!c->isInline());
1076 void RenderBlock::removeLeftoverAnonymousBlock(RenderBlock* child)
1078 ASSERT(child->isAnonymousBlock());
1079 ASSERT(!child->childrenInline());
1081 if (child->continuation() || (child->firstChild() && (child->isAnonymousColumnSpanBlock() || child->isAnonymousColumnsBlock())))
1084 RenderObject* firstAnChild = child->m_children.firstChild();
1085 RenderObject* lastAnChild = child->m_children.lastChild();
1087 RenderObject* o = firstAnChild;
1090 o = o->nextSibling();
1092 firstAnChild->setPreviousSibling(child->previousSibling());
1093 lastAnChild->setNextSibling(child->nextSibling());
1094 if (child->previousSibling())
1095 child->previousSibling()->setNextSibling(firstAnChild);
1096 if (child->nextSibling())
1097 child->nextSibling()->setPreviousSibling(lastAnChild);
1099 if (child == m_children.firstChild())
1100 m_children.setFirstChild(firstAnChild);
1101 if (child == m_children.lastChild())
1102 m_children.setLastChild(lastAnChild);
1104 if (child == m_children.firstChild())
1105 m_children.setFirstChild(child->nextSibling());
1106 if (child == m_children.lastChild())
1107 m_children.setLastChild(child->previousSibling());
1109 if (child->previousSibling())
1110 child->previousSibling()->setNextSibling(child->nextSibling());
1111 if (child->nextSibling())
1112 child->nextSibling()->setPreviousSibling(child->previousSibling());
1115 child->children()->setFirstChild(0);
1118 // Remove all the information in the flow thread associated with the leftover anonymous block.
1119 child->removeFromRenderFlowThread();
1121 child->setParent(0);
1122 child->setPreviousSibling(0);
1123 child->setNextSibling(0);
1128 static bool canMergeContiguousAnonymousBlocks(RenderObject* oldChild, RenderObject* prev, RenderObject* next)
1130 if (oldChild->documentBeingDestroyed() || oldChild->isInline() || oldChild->virtualContinuation())
1133 if ((prev && (!prev->isAnonymousBlock() || toRenderBlock(prev)->continuation() || toRenderBlock(prev)->beingDestroyed()))
1134 || (next && (!next->isAnonymousBlock() || toRenderBlock(next)->continuation() || toRenderBlock(next)->beingDestroyed())))
1137 // FIXME: This check isn't required when inline run-ins can't be split into continuations.
1138 if (prev && prev->firstChild() && prev->firstChild()->isInline() && prev->firstChild()->isRunIn())
1141 if ((prev && (prev->isRubyRun() || prev->isRubyBase()))
1142 || (next && (next->isRubyRun() || next->isRubyBase())))
1148 // Make sure the types of the anonymous blocks match up.
1149 return prev->isAnonymousColumnsBlock() == next->isAnonymousColumnsBlock()
1150 && prev->isAnonymousColumnSpanBlock() == next->isAnonymousColumnSpanBlock();
1153 void RenderBlock::collapseAnonymousBoxChild(RenderBlock* parent, RenderObject* child)
1155 parent->setNeedsLayoutAndPrefWidthsRecalc();
1156 parent->setChildrenInline(child->childrenInline());
1157 RenderObject* nextSibling = child->nextSibling();
1159 RenderFlowThread* childFlowThread = child->flowThreadContainingBlock();
1160 CurrentRenderFlowThreadMaintainer flowThreadMaintainer(childFlowThread);
1162 RenderBlock* anonBlock = toRenderBlock(parent->children()->removeChildNode(parent, child, child->hasLayer()));
1163 anonBlock->moveAllChildrenTo(parent, nextSibling, child->hasLayer());
1164 // Delete the now-empty block's lines and nuke it.
1165 anonBlock->deleteLineBoxTree();
1166 if (childFlowThread && childFlowThread->isRenderNamedFlowThread())
1167 toRenderNamedFlowThread(childFlowThread)->removeFlowChildInfo(anonBlock);
1168 anonBlock->destroy();
1171 void RenderBlock::moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert)
1173 moveAllChildrenTo(toBlock, fullRemoveInsert);
1175 // When a portion of the render tree is being detached, anonymous blocks
1176 // will be combined as their children are deleted. In this process, the
1177 // anonymous block later in the tree is merged into the one preceeding it.
1178 // It can happen that the later block (this) contains floats that the
1179 // previous block (toBlock) did not contain, and thus are not in the
1180 // floating objects list for toBlock. This can result in toBlock containing
1181 // floats that are not in it's floating objects list, but are in the
1182 // floating objects lists of siblings and parents. This can cause problems
1183 // when the float itself is deleted, since the deletion code assumes that
1184 // if a float is not in it's containing block's floating objects list, it
1185 // isn't in any floating objects list. In order to preserve this condition
1186 // (removing it has serious performance implications), we need to copy the
1187 // floating objects from the old block (this) to the new block (toBlock).
1188 // The float's metrics will likely all be wrong, but since toBlock is
1189 // already marked for layout, this will get fixed before anything gets
1191 // See bug https://bugs.webkit.org/show_bug.cgi?id=115566
1192 if (m_floatingObjects) {
1193 if (!toBlock->m_floatingObjects)
1194 toBlock->createFloatingObjects();
1196 const FloatingObjectSet& fromFloatingObjectSet = m_floatingObjects->set();
1197 FloatingObjectSetIterator end = fromFloatingObjectSet.end();
1199 for (FloatingObjectSetIterator it = fromFloatingObjectSet.begin(); it != end; ++it) {
1200 FloatingObject* floatingObject = *it;
1202 // Don't insert the object again if it's already in the list
1203 if (toBlock->containsFloat(floatingObject->renderer()))
1206 toBlock->m_floatingObjects->add(floatingObject->clone());
1211 void RenderBlock::removeChild(RenderObject* oldChild)
1213 // No need to waste time in merging or removing empty anonymous blocks.
1214 // We can just bail out if our document is getting destroyed.
1215 if (documentBeingDestroyed()) {
1216 RenderBox::removeChild(oldChild);
1220 // This protects against column split flows when anonymous blocks are getting merged.
1221 TemporaryChange<bool> columnFlowSplitEnabled(gColumnFlowSplitEnabled, false);
1223 // If this child is a block, and if our previous and next siblings are
1224 // both anonymous blocks with inline content, then we can go ahead and
1225 // fold the inline content back together.
1226 RenderObject* prev = oldChild->previousSibling();
1227 RenderObject* next = oldChild->nextSibling();
1228 bool canMergeAnonymousBlocks = canMergeContiguousAnonymousBlocks(oldChild, prev, next);
1229 if (canMergeAnonymousBlocks && prev && next) {
1230 prev->setNeedsLayoutAndPrefWidthsRecalc();
1231 RenderBlock* nextBlock = toRenderBlock(next);
1232 RenderBlock* prevBlock = toRenderBlock(prev);
1234 if (prev->childrenInline() != next->childrenInline()) {
1235 RenderBlock* inlineChildrenBlock = prev->childrenInline() ? prevBlock : nextBlock;
1236 RenderBlock* blockChildrenBlock = prev->childrenInline() ? nextBlock : prevBlock;
1238 // Place the inline children block inside of the block children block instead of deleting it.
1239 // In order to reuse it, we have to reset it to just be a generic anonymous block. Make sure
1240 // to clear out inherited column properties by just making a new style, and to also clear the
1241 // column span flag if it is set.
1242 ASSERT(!inlineChildrenBlock->continuation());
1243 RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK);
1244 // Cache this value as it might get changed in setStyle() call.
1245 bool inlineChildrenBlockHasLayer = inlineChildrenBlock->hasLayer();
1246 inlineChildrenBlock->setStyle(newStyle);
1247 children()->removeChildNode(this, inlineChildrenBlock, inlineChildrenBlockHasLayer);
1249 // Now just put the inlineChildrenBlock inside the blockChildrenBlock.
1250 blockChildrenBlock->children()->insertChildNode(blockChildrenBlock, inlineChildrenBlock, prev == inlineChildrenBlock ? blockChildrenBlock->firstChild() : 0,
1251 inlineChildrenBlockHasLayer || blockChildrenBlock->hasLayer());
1252 next->setNeedsLayoutAndPrefWidthsRecalc();
1254 // inlineChildrenBlock got reparented to blockChildrenBlock, so it is no longer a child
1255 // of "this". we null out prev or next so that is not used later in the function.
1256 if (inlineChildrenBlock == prevBlock)
1261 // Take all the children out of the |next| block and put them in
1262 // the |prev| block.
1263 nextBlock->moveAllChildrenIncludingFloatsTo(prevBlock, nextBlock->hasLayer() || prevBlock->hasLayer());
1265 // Delete the now-empty block's lines and nuke it.
1266 nextBlock->deleteLineBoxTree();
1267 nextBlock->destroy();
1272 RenderBox::removeChild(oldChild);
1274 RenderObject* child = prev ? prev : next;
1275 if (canMergeAnonymousBlocks && child && !child->previousSibling() && !child->nextSibling() && canCollapseAnonymousBlockChild()) {
1276 // The removal has knocked us down to containing only a single anonymous
1277 // box. We can go ahead and pull the content right back up into our
1279 collapseAnonymousBoxChild(this, child);
1280 } else if (((prev && prev->isAnonymousBlock()) || (next && next->isAnonymousBlock())) && canCollapseAnonymousBlockChild()) {
1281 // It's possible that the removal has knocked us down to a single anonymous
1282 // block with pseudo-style element siblings (e.g. first-letter). If these
1283 // are floating, then we need to pull the content up also.
1284 RenderBlock* anonBlock = toRenderBlock((prev && prev->isAnonymousBlock()) ? prev : next);
1285 if ((anonBlock->previousSibling() || anonBlock->nextSibling())
1286 && (!anonBlock->previousSibling() || (anonBlock->previousSibling()->style()->styleType() != NOPSEUDO && anonBlock->previousSibling()->isFloating() && !anonBlock->previousSibling()->previousSibling()))
1287 && (!anonBlock->nextSibling() || (anonBlock->nextSibling()->style()->styleType() != NOPSEUDO && anonBlock->nextSibling()->isFloating() && !anonBlock->nextSibling()->nextSibling()))) {
1288 collapseAnonymousBoxChild(this, anonBlock);
1292 if (!firstChild()) {
1293 // If this was our last child be sure to clear out our line boxes.
1294 if (childrenInline())
1295 deleteLineBoxTree();
1297 // If we are an empty anonymous block in the continuation chain,
1298 // we need to remove ourself and fix the continuation chain.
1299 if (!beingDestroyed() && isAnonymousBlockContinuation() && !oldChild->isListMarker()) {
1300 RenderObject* containingBlockIgnoringAnonymous = containingBlock();
1301 while (containingBlockIgnoringAnonymous && containingBlockIgnoringAnonymous->isAnonymousBlock())
1302 containingBlockIgnoringAnonymous = containingBlockIgnoringAnonymous->containingBlock();
1303 for (RenderObject* curr = this; curr; curr = curr->previousInPreOrder(containingBlockIgnoringAnonymous)) {
1304 if (curr->virtualContinuation() != this)
1307 // Found our previous continuation. We just need to point it to
1308 // |this|'s next continuation.
1309 RenderBoxModelObject* nextContinuation = continuation();
1310 if (curr->isRenderInline())
1311 toRenderInline(curr)->setContinuation(nextContinuation);
1312 else if (curr->isRenderBlock())
1313 toRenderBlock(curr)->setContinuation(nextContinuation);
1315 ASSERT_NOT_REACHED();
1325 bool RenderBlock::isSelfCollapsingBlock() const
1327 // We are not self-collapsing if we
1328 // (a) have a non-zero height according to layout (an optimization to avoid wasting time)
1330 // (c) have border/padding,
1331 // (d) have a min-height
1332 // (e) have specified that one of our margins can't collapse using a CSS extension
1333 if (logicalHeight() > 0
1334 || isTable() || borderAndPaddingLogicalHeight()
1335 || style()->logicalMinHeight().isPositive()
1336 || style()->marginBeforeCollapse() == MSEPARATE || style()->marginAfterCollapse() == MSEPARATE)
1339 Length logicalHeightLength = style()->logicalHeight();
1340 bool hasAutoHeight = logicalHeightLength.isAuto();
1341 if (logicalHeightLength.isPercent() && !document()->inQuirksMode()) {
1342 hasAutoHeight = true;
1343 for (RenderBlock* cb = containingBlock(); !cb->isRenderView(); cb = cb->containingBlock()) {
1344 if (cb->style()->logicalHeight().isFixed() || cb->isTableCell())
1345 hasAutoHeight = false;
1349 // If the height is 0 or auto, then whether or not we are a self-collapsing block depends
1350 // on whether we have content that is all self-collapsing or not.
1351 if (hasAutoHeight || ((logicalHeightLength.isFixed() || logicalHeightLength.isPercent()) && logicalHeightLength.isZero())) {
1352 // If the block has inline children, see if we generated any line boxes. If we have any
1353 // line boxes, then we can't be self-collapsing, since we have content.
1354 if (childrenInline())
1355 return !firstLineBox();
1357 // Whether or not we collapse is dependent on whether all our normal flow children
1358 // are also self-collapsing.
1359 for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
1360 if (child->isFloatingOrOutOfFlowPositioned())
1362 if (!child->isSelfCollapsingBlock())
1370 void RenderBlock::startDelayUpdateScrollInfo()
1372 if (gDelayUpdateScrollInfo == 0) {
1373 ASSERT(!gDelayedUpdateScrollInfoSet);
1374 gDelayedUpdateScrollInfoSet = new DelayedUpdateScrollInfoSet;
1376 ASSERT(gDelayedUpdateScrollInfoSet);
1377 ++gDelayUpdateScrollInfo;
1380 void RenderBlock::finishDelayUpdateScrollInfo()
1382 --gDelayUpdateScrollInfo;
1383 ASSERT(gDelayUpdateScrollInfo >= 0);
1384 if (gDelayUpdateScrollInfo == 0) {
1385 ASSERT(gDelayedUpdateScrollInfoSet);
1387 OwnPtr<DelayedUpdateScrollInfoSet> infoSet(adoptPtr(gDelayedUpdateScrollInfoSet));
1388 gDelayedUpdateScrollInfoSet = 0;
1390 for (DelayedUpdateScrollInfoSet::iterator it = infoSet->begin(); it != infoSet->end(); ++it) {
1391 RenderBlock* block = *it;
1392 if (block->hasOverflowClip()) {
1393 block->layer()->updateScrollInfoAfterLayout();
1394 block->clearLayoutOverflow();
1400 void RenderBlock::updateScrollInfoAfterLayout()
1402 if (hasOverflowClip()) {
1403 if (style()->isFlippedBlocksWritingMode()) {
1404 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=97937
1405 // Workaround for now. We cannot delay the scroll info for overflow
1406 // for items with opposite writing directions, as the contents needs
1407 // to overflow in that direction
1408 layer()->updateScrollInfoAfterLayout();
1412 if (gDelayUpdateScrollInfo)
1413 gDelayedUpdateScrollInfoSet->add(this);
1415 layer()->updateScrollInfoAfterLayout();
1419 void RenderBlock::layout()
1421 StackStats::LayoutCheckPoint layoutCheckPoint;
1422 OverflowEventDispatcher dispatcher(this);
1424 // Update our first letter info now.
1425 updateFirstLetter();
1427 // Table cells call layoutBlock directly, so don't add any logic here. Put code into
1431 // It's safe to check for control clip here, since controls can never be table cells.
1432 // If we have a lightweight clip, there can never be any overflow from children.
1433 if (hasControlClip() && m_overflow && !gDelayUpdateScrollInfo)
1434 clearLayoutOverflow();
1436 invalidateBackgroundObscurationStatus();
1439 #if ENABLE(CSS_SHAPES)
1440 void RenderBlock::updateExclusionShapeInsideInfoAfterStyleChange(const ExclusionShapeValue* shapeInside, const ExclusionShapeValue* oldShapeInside)
1442 // FIXME: A future optimization would do a deep comparison for equality.
1443 if (shapeInside == oldShapeInside)
1447 ExclusionShapeInsideInfo* exclusionShapeInsideInfo = ensureExclusionShapeInsideInfo();
1448 exclusionShapeInsideInfo->dirtyShapeSize();
1450 setExclusionShapeInsideInfo(nullptr);
1451 markShapeInsideDescendantsForLayout();
1455 void RenderBlock::markShapeInsideDescendantsForLayout()
1457 if (!everHadLayout())
1459 if (childrenInline()) {
1460 setNeedsLayout(true);
1463 for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
1464 if (!child->isRenderBlock())
1466 RenderBlock* childBlock = toRenderBlock(child);
1467 childBlock->markShapeInsideDescendantsForLayout();
1472 static inline bool exclusionInfoRequiresRelayout(const RenderBlock* block)
1474 #if !ENABLE(CSS_SHAPES)
1477 ExclusionShapeInsideInfo* info = block->exclusionShapeInsideInfo();
1479 info->setNeedsLayout(info->shapeSizeDirty());
1481 info = block->layoutExclusionShapeInsideInfo();
1482 return info && info->needsLayout();
1486 bool RenderBlock::updateRegionsAndExclusionsBeforeChildLayout(RenderFlowThread* flowThread)
1488 #if ENABLE(CSS_SHAPES)
1489 if (!flowThread && !exclusionShapeInsideInfo())
1493 return exclusionInfoRequiresRelayout(this);
1495 LayoutUnit oldHeight = logicalHeight();
1496 LayoutUnit oldTop = logicalTop();
1498 // Compute the maximum logical height content may cause this block to expand to
1499 // FIXME: These should eventually use the const computeLogicalHeight rather than updateLogicalHeight
1500 setLogicalHeight(LayoutUnit::max() / 2);
1501 updateLogicalHeight();
1503 #if ENABLE(CSS_SHAPES)
1504 computeExclusionShapeSize();
1507 // Set our start and end regions. No regions above or below us will be considered by our children. They are
1508 // effectively clamped to our region range.
1509 computeRegionRangeForBlock(flowThread);
1511 setLogicalHeight(oldHeight);
1512 setLogicalTop(oldTop);
1514 return exclusionInfoRequiresRelayout(this);
1517 #if ENABLE(CSS_SHAPES)
1518 void RenderBlock::computeExclusionShapeSize()
1520 ExclusionShapeInsideInfo* exclusionShapeInsideInfo = this->exclusionShapeInsideInfo();
1521 if (exclusionShapeInsideInfo) {
1522 bool percentageLogicalHeightResolvable = percentageLogicalHeightIsResolvableFromBlock(this, false);
1523 exclusionShapeInsideInfo->setShapeSize(logicalWidth(), percentageLogicalHeightResolvable ? logicalHeight() : LayoutUnit());
1528 void RenderBlock::updateRegionsAndExclusionsAfterChildLayout(RenderFlowThread* flowThread, bool heightChanged)
1530 #if ENABLE(CSS_SHAPES)
1531 // A previous sibling has changed dimension, so we need to relayout the shape with the content
1532 ExclusionShapeInsideInfo* shapeInsideInfo = layoutExclusionShapeInsideInfo();
1533 if (heightChanged && shapeInsideInfo)
1534 shapeInsideInfo->dirtyShapeSize();
1536 computeRegionRangeForBlock(flowThread);
1539 void RenderBlock::computeRegionRangeForBlock(RenderFlowThread* flowThread)
1542 flowThread->setRegionRangeForBox(this, offsetFromLogicalTopOfFirstPage());
1545 bool RenderBlock::updateLogicalWidthAndColumnWidth()
1547 LayoutUnit oldWidth = logicalWidth();
1548 LayoutUnit oldColumnWidth = desiredColumnWidth();
1550 updateLogicalWidth();
1553 bool hasBorderOrPaddingLogicalWidthChanged = m_hasBorderOrPaddingLogicalWidthChanged;
1554 m_hasBorderOrPaddingLogicalWidthChanged = false;
1556 return oldWidth != logicalWidth() || oldColumnWidth != desiredColumnWidth() || hasBorderOrPaddingLogicalWidthChanged;
1559 void RenderBlock::checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight)
1561 ColumnInfo* colInfo = columnInfo();
1563 if (!pageLogicalHeight) {
1564 // We need to go ahead and set our explicit page height if one exists, so that we can
1565 // avoid doing two layout passes.
1566 updateLogicalHeight();
1567 LayoutUnit columnHeight = contentLogicalHeight();
1568 if (columnHeight > 0) {
1569 pageLogicalHeight = columnHeight;
1570 hasSpecifiedPageLogicalHeight = true;
1572 setLogicalHeight(0);
1575 if (colInfo->columnHeight() != pageLogicalHeight && everHadLayout())
1576 pageLogicalHeightChanged = true;
1578 colInfo->setColumnHeight(pageLogicalHeight);
1580 if (!hasSpecifiedPageLogicalHeight && !pageLogicalHeight)
1581 colInfo->clearForcedBreaks();
1583 colInfo->setPaginationUnit(paginationUnit());
1584 } else if (isRenderFlowThread()) {
1585 pageLogicalHeight = 1; // This is just a hack to always make sure we have a page logical height.
1586 pageLogicalHeightChanged = toRenderFlowThread(this)->pageLogicalSizeChanged();
1590 void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight)
1592 ASSERT(needsLayout());
1594 if (isInline() && !isInlineBlockOrInlineTable()) // Inline <form>s inside various table elements can
1595 return; // cause us to come in here. Just bail.
1597 if (!relayoutChildren && simplifiedLayout())
1600 LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
1602 if (updateLogicalWidthAndColumnWidth())
1603 relayoutChildren = true;
1607 LayoutUnit previousHeight = logicalHeight();
1608 // FIXME: should this start out as borderAndPaddingLogicalHeight() + scrollbarLogicalHeight(),
1609 // for consistency with other render classes?
1610 setLogicalHeight(0);
1612 bool pageLogicalHeightChanged = false;
1613 bool hasSpecifiedPageLogicalHeight = false;
1614 checkForPaginationLogicalHeightChange(pageLogicalHeight, pageLogicalHeightChanged, hasSpecifiedPageLogicalHeight);
1616 RenderView* renderView = view();
1617 RenderStyle* styleToUse = style();
1618 LayoutStateMaintainer statePusher(renderView, this, locationOffset(), hasColumns() || hasTransform() || hasReflection() || styleToUse->isFlippedBlocksWritingMode(), pageLogicalHeight, pageLogicalHeightChanged, columnInfo());
1620 // Regions changing widths can force us to relayout our children.
1621 RenderFlowThread* flowThread = flowThreadContainingBlock();
1622 if (logicalWidthChangedInRegions(flowThread))
1623 relayoutChildren = true;
1624 if (updateRegionsAndExclusionsBeforeChildLayout(flowThread))
1625 relayoutChildren = true;
1627 // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, to track
1628 // our current maximal positive and negative margins. These values are used when we
1629 // are collapsed with adjacent blocks, so for example, if you have block A and B
1630 // collapsing together, then you'd take the maximal positive margin from both A and B
1631 // and subtract it from the maximal negative margin from both A and B to get the
1632 // true collapsed margin. This algorithm is recursive, so when we finish layout()
1633 // our block knows its current maximal positive/negative values.
1635 // Start out by setting our margin values to our current margins. Table cells have
1636 // no margins, so we don't fill in the values for table cells.
1637 bool isCell = isTableCell();
1639 initMaxMarginValues();
1641 setHasMarginBeforeQuirk(styleToUse->hasMarginBeforeQuirk());
1642 setHasMarginAfterQuirk(styleToUse->hasMarginAfterQuirk());
1643 setPaginationStrut(0);
1646 LayoutUnit repaintLogicalTop = 0;
1647 LayoutUnit repaintLogicalBottom = 0;
1648 LayoutUnit maxFloatLogicalBottom = 0;
1649 if (!firstChild() && !isAnonymousBlock())
1650 setChildrenInline(true);
1651 if (childrenInline())
1652 layoutInlineChildren(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
1654 layoutBlockChildren(relayoutChildren, maxFloatLogicalBottom);
1656 // Expand our intrinsic height to encompass floats.
1657 LayoutUnit toAdd = borderAfter() + paddingAfter() + scrollbarLogicalHeight();
1658 if (lowestFloatLogicalBottom() > (logicalHeight() - toAdd) && expandsToEncloseOverhangingFloats())
1659 setLogicalHeight(lowestFloatLogicalBottom() + toAdd);
1661 if (relayoutForPagination(hasSpecifiedPageLogicalHeight, pageLogicalHeight, statePusher))
1664 // Calculate our new height.
1665 LayoutUnit oldHeight = logicalHeight();
1666 LayoutUnit oldClientAfterEdge = clientLogicalBottom();
1668 // Before updating the final size of the flow thread make sure a forced break is applied after the content.
1669 // This ensures the size information is correctly computed for the last auto-height region receiving content.
1670 if (isRenderFlowThread())
1671 toRenderFlowThread(this)->applyBreakAfterContent(oldClientAfterEdge);
1673 updateLogicalHeight();
1674 LayoutUnit newHeight = logicalHeight();
1675 if (oldHeight != newHeight) {
1676 if (oldHeight > newHeight && maxFloatLogicalBottom > newHeight && !childrenInline()) {
1677 // One of our children's floats may have become an overhanging float for us. We need to look for it.
1678 for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
1679 if (child->isBlockFlow() && !child->isFloatingOrOutOfFlowPositioned()) {
1680 RenderBlock* block = toRenderBlock(child);
1681 if (block->lowestFloatLogicalBottom() + block->logicalTop() > newHeight)
1682 addOverhangingFloats(block, false);
1688 bool heightChanged = (previousHeight != newHeight);
1690 relayoutChildren = true;
1692 layoutPositionedObjects(relayoutChildren || isRoot());
1694 updateRegionsAndExclusionsAfterChildLayout(flowThread, heightChanged);
1696 // Add overflow from children (unless we're multi-column, since in that case all our child overflow is clipped anyway).
1697 computeOverflow(oldClientAfterEdge);
1701 fitBorderToLinesIfNeeded();
1703 if (renderView->layoutState()->m_pageLogicalHeight)
1704 setPageLogicalOffset(renderView->layoutState()->pageLogicalOffset(this, logicalTop()));
1706 updateLayerTransform();
1708 // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
1709 // we overflow or not.
1710 updateScrollInfoAfterLayout();
1712 // FIXME: This repaint logic should be moved into a separate helper function!
1713 // Repaint with our new bounds if they are different from our old bounds.
1714 bool didFullRepaint = repainter.repaintAfterLayout();
1715 if (!didFullRepaint && repaintLogicalTop != repaintLogicalBottom && (styleToUse->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) {
1716 // FIXME: We could tighten up the left and right invalidation points if we let layoutInlineChildren fill them in based off the particular lines
1717 // it had to lay out. We wouldn't need the hasOverflowClip() hack in that case either.
1718 LayoutUnit repaintLogicalLeft = logicalLeftVisualOverflow();
1719 LayoutUnit repaintLogicalRight = logicalRightVisualOverflow();
1720 if (hasOverflowClip()) {
1721 // If we have clipped overflow, we should use layout overflow as well, since visual overflow from lines didn't propagate to our block's overflow.
1722 // Note the old code did this as well but even for overflow:visible. The addition of hasOverflowClip() at least tightens up the hack a bit.
1723 // layoutInlineChildren should be patched to compute the entire repaint rect.
1724 repaintLogicalLeft = min(repaintLogicalLeft, logicalLeftLayoutOverflow());
1725 repaintLogicalRight = max(repaintLogicalRight, logicalRightLayoutOverflow());
1728 LayoutRect repaintRect;
1729 if (isHorizontalWritingMode())
1730 repaintRect = LayoutRect(repaintLogicalLeft, repaintLogicalTop, repaintLogicalRight - repaintLogicalLeft, repaintLogicalBottom - repaintLogicalTop);
1732 repaintRect = LayoutRect(repaintLogicalTop, repaintLogicalLeft, repaintLogicalBottom - repaintLogicalTop, repaintLogicalRight - repaintLogicalLeft);
1734 // The repaint rect may be split across columns, in which case adjustRectForColumns() will return the union.
1735 adjustRectForColumns(repaintRect);
1737 repaintRect.inflate(maximalOutlineSize(PaintPhaseOutline));
1739 if (hasOverflowClip()) {
1740 // Adjust repaint rect for scroll offset
1741 repaintRect.move(-scrolledContentOffset());
1743 // Don't allow this rect to spill out of our overflow box.
1744 repaintRect.intersect(LayoutRect(LayoutPoint(), size()));
1747 // Make sure the rect is still non-empty after intersecting for overflow above
1748 if (!repaintRect.isEmpty()) {
1749 repaintRectangle(repaintRect); // We need to do a partial repaint of our content.
1750 if (hasReflection())
1751 repaintRectangle(reflectedRect(repaintRect));
1755 setNeedsLayout(false);
1758 void RenderBlock::addOverflowFromChildren()
1760 if (!hasColumns()) {
1761 if (childrenInline())
1762 addOverflowFromInlineChildren();
1764 addOverflowFromBlockChildren();
1766 ColumnInfo* colInfo = columnInfo();
1767 if (columnCount(colInfo)) {
1768 LayoutRect lastRect = columnRectAt(colInfo, columnCount(colInfo) - 1);
1769 addLayoutOverflow(lastRect);
1770 if (!hasOverflowClip())
1771 addVisualOverflow(lastRect);
1776 void RenderBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats)
1780 // Add overflow from children.
1781 addOverflowFromChildren();
1783 if (!hasColumns() && (recomputeFloats || isRoot() || expandsToEncloseOverhangingFloats() || hasSelfPaintingLayer()))
1784 addOverflowFromFloats();
1786 // Add in the overflow from positioned objects.
1787 addOverflowFromPositionedObjects();
1789 if (hasOverflowClip()) {
1790 // When we have overflow clip, propagate the original spillout since it will include collapsed bottom margins
1791 // and bottom padding. Set the axis we don't care about to be 1, since we want this overflow to always
1792 // be considered reachable.
1793 LayoutRect clientRect(clientBoxRect());
1794 LayoutRect rectToApply;
1795 if (isHorizontalWritingMode())
1796 rectToApply = LayoutRect(clientRect.x(), clientRect.y(), 1, max<LayoutUnit>(0, oldClientAfterEdge - clientRect.y()));
1798 rectToApply = LayoutRect(clientRect.x(), clientRect.y(), max<LayoutUnit>(0, oldClientAfterEdge - clientRect.x()), 1);
1799 addLayoutOverflow(rectToApply);
1800 if (hasRenderOverflow())
1801 m_overflow->setLayoutClientAfterEdge(oldClientAfterEdge);
1804 // Allow our overflow to catch cases where the caret in an empty editable element with negative text indent needs to get painted.
1805 LayoutUnit textIndent = textIndentOffset();
1806 if (textIndent < 0) {
1807 LayoutRect clientRect(clientBoxRect());
1808 LayoutRect rectToApply = LayoutRect(clientRect.x() + min<LayoutUnit>(0, textIndent), clientRect.y(), clientRect.width() - min<LayoutUnit>(0, textIndent), clientRect.height());
1809 addVisualOverflow(rectToApply);
1812 // Add visual overflow from box-shadow and border-image-outset.
1813 addVisualEffectOverflow();
1815 // Add visual overflow from theme.
1816 addVisualOverflowFromTheme();
1818 if (isRenderFlowThread())
1819 toRenderFlowThread(this)->computeOverflowStateForRegions(oldClientAfterEdge);
1822 void RenderBlock::clearLayoutOverflow()
1827 if (visualOverflowRect() == borderBoxRect()) {
1832 m_overflow->setLayoutOverflow(borderBoxRect());
1835 void RenderBlock::addOverflowFromBlockChildren()
1837 for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
1838 if (!child->isFloatingOrOutOfFlowPositioned())
1839 addOverflowFromChild(child);
1843 void RenderBlock::addOverflowFromFloats()
1845 if (!m_floatingObjects)
1848 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
1849 FloatingObjectSetIterator end = floatingObjectSet.end();
1850 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
1851 FloatingObject* r = *it;
1852 if (r->isDescendant())
1853 addOverflowFromChild(r->m_renderer, IntSize(xPositionForFloatIncludingMargin(r), yPositionForFloatIncludingMargin(r)));
1857 void RenderBlock::addOverflowFromPositionedObjects()
1859 TrackedRendererListHashSet* positionedDescendants = positionedObjects();
1860 if (!positionedDescendants)
1863 RenderBox* positionedObject;
1864 TrackedRendererListHashSet::iterator end = positionedDescendants->end();
1865 for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) {
1866 positionedObject = *it;
1868 // Fixed positioned elements don't contribute to layout overflow, since they don't scroll with the content.
1869 if (positionedObject->style()->position() != FixedPosition) {
1870 LayoutUnit x = positionedObject->x();
1871 if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
1872 x -= verticalScrollbarWidth();
1873 addOverflowFromChild(positionedObject, LayoutSize(x, positionedObject->y()));
1878 void RenderBlock::addVisualOverflowFromTheme()
1880 if (!style()->hasAppearance())
1883 IntRect inflatedRect = pixelSnappedBorderBoxRect();
1884 theme()->adjustRepaintRect(this, inflatedRect);
1885 addVisualOverflow(inflatedRect);
1888 bool RenderBlock::expandsToEncloseOverhangingFloats() const
1890 return isInlineBlockOrInlineTable() || isFloatingOrOutOfFlowPositioned() || hasOverflowClip() || (parent() && parent()->isFlexibleBoxIncludingDeprecated())
1891 || hasColumns() || isTableCell() || isTableCaption() || isFieldset() || isWritingModeRoot() || isRoot();
1894 void RenderBlock::adjustPositionedBlock(RenderBox* child, const MarginInfo& marginInfo)
1896 bool isHorizontal = isHorizontalWritingMode();
1897 bool hasStaticBlockPosition = child->style()->hasStaticBlockPosition(isHorizontal);
1899 LayoutUnit logicalTop = logicalHeight();
1900 updateStaticInlinePositionForChild(child, logicalTop);
1902 if (!marginInfo.canCollapseWithMarginBefore()) {
1903 // Positioned blocks don't collapse margins, so add the margin provided by
1904 // the container now. The child's own margin is added later when calculating its logical top.
1905 LayoutUnit collapsedBeforePos = marginInfo.positiveMargin();
1906 LayoutUnit collapsedBeforeNeg = marginInfo.negativeMargin();
1907 logicalTop += collapsedBeforePos - collapsedBeforeNeg;
1910 RenderLayer* childLayer = child->layer();
1911 if (childLayer->staticBlockPosition() != logicalTop) {
1912 childLayer->setStaticBlockPosition(logicalTop);
1913 if (hasStaticBlockPosition)
1914 child->setChildNeedsLayout(true, MarkOnlyThis);
1918 void RenderBlock::adjustFloatingBlock(const MarginInfo& marginInfo)
1920 // The float should be positioned taking into account the bottom margin
1921 // of the previous flow. We add that margin into the height, get the
1922 // float positioned properly, and then subtract the margin out of the
1923 // height again. In the case of self-collapsing blocks, we always just
1924 // use the top margins, since the self-collapsing block collapsed its
1925 // own bottom margin into its top margin.
1927 // Note also that the previous flow may collapse its margin into the top of
1928 // our block. If this is the case, then we do not add the margin in to our
1929 // height when computing the position of the float. This condition can be tested
1930 // for by simply calling canCollapseWithMarginBefore. See
1931 // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for
1932 // an example of this scenario.
1933 LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() ? LayoutUnit() : marginInfo.margin();
1934 setLogicalHeight(logicalHeight() + marginOffset);
1935 positionNewFloats();
1936 setLogicalHeight(logicalHeight() - marginOffset);
1939 static void destroyRunIn(RenderBoxModelObject* runIn)
1941 ASSERT(runIn->isRunIn());
1942 ASSERT(!runIn->firstChild());
1944 // Delete our line box tree. This is needed as our children got moved
1945 // and our line box tree is no longer valid.
1946 if (runIn->isRenderBlock())
1947 toRenderBlock(runIn)->deleteLineBoxTree();
1948 else if (runIn->isRenderInline())
1949 toRenderInline(runIn)->deleteLineBoxTree();
1951 ASSERT_NOT_REACHED();
1956 void RenderBlock::placeRunInIfNeeded(RenderObject* newChild)
1958 if (newChild->isRunIn())
1959 moveRunInUnderSiblingBlockIfNeeded(newChild);
1960 else if (RenderObject* prevSibling = newChild->previousSibling()) {
1961 if (prevSibling->isRunIn())
1962 moveRunInUnderSiblingBlockIfNeeded(prevSibling);
1966 RenderBoxModelObject* RenderBlock::createReplacementRunIn(RenderBoxModelObject* runIn)
1968 ASSERT(runIn->isRunIn());
1969 ASSERT(runIn->node());
1971 RenderBoxModelObject* newRunIn = 0;
1972 if (!runIn->isRenderBlock())
1973 newRunIn = new (renderArena()) RenderBlock(runIn->node());
1975 newRunIn = new (renderArena()) RenderInline(toElement(runIn->node()));
1977 runIn->node()->setRenderer(newRunIn);
1978 newRunIn->setStyle(runIn->style());
1980 runIn->moveAllChildrenTo(newRunIn, true);
1985 void RenderBlock::moveRunInUnderSiblingBlockIfNeeded(RenderObject* runIn)
1987 ASSERT(runIn->isRunIn());
1989 // See if we have inline children. If the children aren't inline,
1990 // then just treat the run-in as a normal block.
1991 if (!runIn->childrenInline())
1994 // FIXME: We don't handle non-block elements with run-in for now.
1995 if (!runIn->isRenderBlock())
1998 // FIXME: We don't support run-ins with or as part of a continuation
1999 // as it makes the back-and-forth placing complex.
2000 if (runIn->isElementContinuation() || runIn->virtualContinuation())
2003 // Check if this node is allowed to run-in. E.g. <select> expects its renderer to
2004 // be a RenderListBox or RenderMenuList, and hence cannot be a RenderInline run-in.
2005 if (!runIn->canBeReplacedWithInlineRunIn())
2008 RenderObject* curr = runIn->nextSibling();
2009 if (!curr || !curr->isRenderBlock() || !curr->childrenInline())
2012 if (toRenderBlock(curr)->beingDestroyed())
2015 // Per CSS3, "A run-in cannot run in to a block that already starts with a
2016 // run-in or that itself is a run-in".
2017 if (curr->isRunIn() || (curr->firstChild() && curr->firstChild()->isRunIn()))
2020 if (curr->isAnonymous() || curr->isFloatingOrOutOfFlowPositioned())
2023 RenderBoxModelObject* oldRunIn = toRenderBoxModelObject(runIn);
2024 RenderBoxModelObject* newRunIn = createReplacementRunIn(oldRunIn);
2025 destroyRunIn(oldRunIn);
2027 // Now insert the new child under |curr| block. Use addChild instead of insertChildNode
2028 // since it handles correct placement of the children, especially where we cannot insert
2029 // anything before the first child. e.g. details tag. See https://bugs.webkit.org/show_bug.cgi?id=58228.
2030 curr->addChild(newRunIn, curr->firstChild());
2032 // Make sure that |this| get a layout since its run-in child moved.
2033 curr->setNeedsLayoutAndPrefWidthsRecalc();
2036 bool RenderBlock::runInIsPlacedIntoSiblingBlock(RenderObject* runIn)
2038 ASSERT(runIn->isRunIn());
2040 // If we don't have a parent, we can't be moved into our sibling block.
2044 // An intruded run-in needs to be an inline.
2045 if (!runIn->isRenderInline())
2051 void RenderBlock::moveRunInToOriginalPosition(RenderObject* runIn)
2053 ASSERT(runIn->isRunIn());
2055 if (!runInIsPlacedIntoSiblingBlock(runIn))
2058 // FIXME: Run-in that are now placed in sibling block can break up into continuation
2059 // chains when new children are added to it. We cannot easily send them back to their
2060 // original place since that requires writing integration logic with RenderInline::addChild
2061 // and all other places that might cause continuations to be created (without blowing away
2062 // |this|). Disabling this feature for now to prevent crashes.
2063 if (runIn->isElementContinuation() || runIn->virtualContinuation())
2066 RenderBoxModelObject* oldRunIn = toRenderBoxModelObject(runIn);
2067 RenderBoxModelObject* newRunIn = createReplacementRunIn(oldRunIn);
2068 destroyRunIn(oldRunIn);
2070 // Add the run-in block as our previous sibling.
2071 parent()->addChild(newRunIn, this);
2073 // Make sure that the parent holding the new run-in gets layout.
2074 parent()->setNeedsLayoutAndPrefWidthsRecalc();
2077 LayoutUnit RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
2079 bool childDiscardMarginBefore = mustDiscardMarginBeforeForChild(child);
2080 bool childDiscardMarginAfter = mustDiscardMarginAfterForChild(child);
2081 bool childIsSelfCollapsing = child->isSelfCollapsingBlock();
2083 // The child discards the before margin when the the after margin has discard in the case of a self collapsing block.
2084 childDiscardMarginBefore = childDiscardMarginBefore || (childDiscardMarginAfter && childIsSelfCollapsing);
2086 // Get the four margin values for the child and cache them.
2087 const MarginValues childMargins = marginValuesForChild(child);
2089 // Get our max pos and neg top margins.
2090 LayoutUnit posTop = childMargins.positiveMarginBefore();
2091 LayoutUnit negTop = childMargins.negativeMarginBefore();
2093 // For self-collapsing blocks, collapse our bottom margins into our
2094 // top to get new posTop and negTop values.
2095 if (childIsSelfCollapsing) {
2096 posTop = max(posTop, childMargins.positiveMarginAfter());
2097 negTop = max(negTop, childMargins.negativeMarginAfter());
2100 // See if the top margin is quirky. We only care if this child has
2101 // margins that will collapse with us.
2102 bool topQuirk = hasMarginBeforeQuirk(child);
2104 if (marginInfo.canCollapseWithMarginBefore()) {
2105 if (!childDiscardMarginBefore && !marginInfo.discardMargin()) {
2106 // This child is collapsing with the top of the
2107 // block. If it has larger margin values, then we need to update
2108 // our own maximal values.
2109 if (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !topQuirk)
2110 setMaxMarginBeforeValues(max(posTop, maxPositiveMarginBefore()), max(negTop, maxNegativeMarginBefore()));
2112 // The minute any of the margins involved isn't a quirk, don't
2113 // collapse it away, even if the margin is smaller (www.webreference.com
2114 // has an example of this, a <dt> with 0.8em author-specified inside
2115 // a <dl> inside a <td>.
2116 if (!marginInfo.determinedMarginBeforeQuirk() && !topQuirk && (posTop - negTop)) {
2117 setHasMarginBeforeQuirk(false);
2118 marginInfo.setDeterminedMarginBeforeQuirk(true);
2121 if (!marginInfo.determinedMarginBeforeQuirk() && topQuirk && !marginBefore())
2122 // We have no top margin and our top child has a quirky margin.
2123 // We will pick up this quirky margin and pass it through.
2124 // This deals with the <td><div><p> case.
2125 // Don't do this for a block that split two inlines though. You do
2126 // still apply margins in this case.
2127 setHasMarginBeforeQuirk(true);
2129 // The before margin of the container will also discard all the margins it is collapsing with.
2130 setMustDiscardMarginBefore();
2133 // Once we find a child with discardMarginBefore all the margins collapsing with us must also discard.
2134 if (childDiscardMarginBefore) {
2135 marginInfo.setDiscardMargin(true);
2136 marginInfo.clearMargin();
2139 if (marginInfo.quirkContainer() && marginInfo.atBeforeSideOfBlock() && (posTop - negTop))
2140 marginInfo.setHasMarginBeforeQuirk(topQuirk);
2142 LayoutUnit beforeCollapseLogicalTop = logicalHeight();
2143 LayoutUnit logicalTop = beforeCollapseLogicalTop;
2144 if (childIsSelfCollapsing) {
2145 // For a self collapsing block both the before and after margins get discarded. The block doesn't contribute anything to the height of the block.
2146 // Also, the child's top position equals the logical height of the container.
2147 if (!childDiscardMarginBefore && !marginInfo.discardMargin()) {
2148 // This child has no height. We need to compute our
2149 // position before we collapse the child's margins together,
2150 // so that we can get an accurate position for the zero-height block.
2151 LayoutUnit collapsedBeforePos = max(marginInfo.positiveMargin(), childMargins.positiveMarginBefore());
2152 LayoutUnit collapsedBeforeNeg = max(marginInfo.negativeMargin(), childMargins.negativeMarginBefore());
2153 marginInfo.setMargin(collapsedBeforePos, collapsedBeforeNeg);
2155 // Now collapse the child's margins together, which means examining our
2156 // bottom margin values as well.
2157 marginInfo.setPositiveMarginIfLarger(childMargins.positiveMarginAfter());
2158 marginInfo.setNegativeMarginIfLarger(childMargins.negativeMarginAfter());
2160 if (!marginInfo.canCollapseWithMarginBefore())
2161 // We need to make sure that the position of the self-collapsing block
2162 // is correct, since it could have overflowing content
2163 // that needs to be positioned correctly (e.g., a block that
2164 // had a specified height of 0 but that actually had subcontent).
2165 logicalTop = logicalHeight() + collapsedBeforePos - collapsedBeforeNeg;
2168 if (mustSeparateMarginBeforeForChild(child)) {
2169 ASSERT(!marginInfo.discardMargin() || (marginInfo.discardMargin() && !marginInfo.margin()));
2170 // If we are at the before side of the block and we collapse, ignore the computed margin
2171 // and just add the child margin to the container height. This will correctly position
2172 // the child inside the container.
2173 LayoutUnit separateMargin = !marginInfo.canCollapseWithMarginBefore() ? marginInfo.margin() : LayoutUnit(0);
2174 setLogicalHeight(logicalHeight() + separateMargin + marginBeforeForChild(child));
2175 logicalTop = logicalHeight();
2176 } else if (!marginInfo.discardMargin() && (!marginInfo.atBeforeSideOfBlock()
2177 || (!marginInfo.canCollapseMarginBeforeWithChildren()
2178 && (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !marginInfo.hasMarginBeforeQuirk())))) {
2179 // We're collapsing with a previous sibling's margins and not
2180 // with the top of the block.
2181 setLogicalHeight(logicalHeight() + max(marginInfo.positiveMargin(), posTop) - max(marginInfo.negativeMargin(), negTop));
2182 logicalTop = logicalHeight();
2185 marginInfo.setDiscardMargin(childDiscardMarginAfter);
2187 if (!marginInfo.discardMargin()) {
2188 marginInfo.setPositiveMargin(childMargins.positiveMarginAfter());
2189 marginInfo.setNegativeMargin(childMargins.negativeMarginAfter());
2191 marginInfo.clearMargin();
2193 if (marginInfo.margin())
2194 marginInfo.setHasMarginAfterQuirk(hasMarginAfterQuirk(child));
2197 // If margins would pull us past the top of the next page, then we need to pull back and pretend like the margins
2198 // collapsed into the page edge.
2199 LayoutState* layoutState = view()->layoutState();
2200 if (layoutState->isPaginated() && layoutState->pageLogicalHeight() && logicalTop > beforeCollapseLogicalTop
2201 && hasNextPage(beforeCollapseLogicalTop)) {
2202 LayoutUnit oldLogicalTop = logicalTop;
2203 logicalTop = min(logicalTop, nextPageLogicalTop(beforeCollapseLogicalTop));
2204 setLogicalHeight(logicalHeight() + (logicalTop - oldLogicalTop));
2207 // If we have collapsed into a previous sibling and so reduced the height of the parent, ensure any floats that now
2208 // overhang from the previous sibling are added to our parent. If the child's previous sibling itself is a float the child will avoid
2209 // or clear it anyway, so don't worry about any floating children it may contain.
2210 LayoutUnit oldLogicalHeight = logicalHeight();
2211 setLogicalHeight(logicalTop);
2212 RenderObject* prev = child->previousSibling();
2213 if (prev && prev->isBlockFlow() && !prev->isFloatingOrOutOfFlowPositioned()) {
2214 RenderBlock* block = toRenderBlock(prev);
2215 if (block->containsFloats() && !block->avoidsFloats() && (block->logicalTop() + block->lowestFloatLogicalBottom()) > logicalTop)
2216 addOverhangingFloats(block, false);
2218 setLogicalHeight(oldLogicalHeight);
2223 LayoutUnit RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos)
2225 LayoutUnit heightIncrease = getClearDelta(child, yPos);
2226 if (!heightIncrease)
2229 if (child->isSelfCollapsingBlock()) {
2230 bool childDiscardMargin = mustDiscardMarginBeforeForChild(child) || mustDiscardMarginAfterForChild(child);
2232 // For self-collapsing blocks that clear, they can still collapse their
2233 // margins with following siblings. Reset the current margins to represent
2234 // the self-collapsing block's margins only.
2235 // If DISCARD is specified for -webkit-margin-collapse, reset the margin values.
2236 if (!childDiscardMargin) {
2237 MarginValues childMargins = marginValuesForChild(child);
2238 marginInfo.setPositiveMargin(max(childMargins.positiveMarginBefore(), childMargins.positiveMarginAfter()));
2239 marginInfo.setNegativeMargin(max(childMargins.negativeMarginBefore(), childMargins.negativeMarginAfter()));
2241 marginInfo.clearMargin();
2242 marginInfo.setDiscardMargin(childDiscardMargin);
2245 // "If the top and bottom margins of an element with clearance are adjoining, its margins collapse with
2246 // the adjoining margins of following siblings but that resulting margin does not collapse with the bottom margin of the parent block."
2247 // So the parent's bottom margin cannot collapse through this block or any subsequent self-collapsing blocks. Check subsequent siblings
2248 // for a block with height - if none is found then don't allow the margins to collapse with the parent.
2249 bool wouldCollapseMarginsWithParent = marginInfo.canCollapseMarginAfterWithChildren();
2250 for (RenderBox* curr = child->nextSiblingBox(); curr && wouldCollapseMarginsWithParent; curr = curr->nextSiblingBox()) {
2251 if (!curr->isFloatingOrOutOfFlowPositioned() && !curr->isSelfCollapsingBlock())
2252 wouldCollapseMarginsWithParent = false;
2254 if (wouldCollapseMarginsWithParent)
2255 marginInfo.setCanCollapseMarginAfterWithChildren(false);
2257 // CSS2.1: "the amount of clearance is set so that clearance + margin-top = [height of float], i.e., clearance = [height of float] - margin-top"
2258 // Move the top of the child box to the bottom of the float ignoring the child's top margin.
2259 LayoutUnit collapsedMargin = collapsedMarginBeforeForChild(child);
2260 setLogicalHeight(child->logicalTop() - collapsedMargin);
2261 // A negative collapsed margin-top value cancels itself out as it has already been factored into |yPos| above.
2262 heightIncrease -= max(LayoutUnit(), collapsedMargin);
2264 // Increase our height by the amount we had to clear.
2265 setLogicalHeight(logicalHeight() + heightIncrease);
2267 if (marginInfo.canCollapseWithMarginBefore()) {
2268 // We can no longer collapse with the top of the block since a clear
2269 // occurred. The empty blocks collapse into the cleared block.
2270 // FIXME: This isn't quite correct. Need clarification for what to do
2271 // if the height the cleared block is offset by is smaller than the
2272 // margins involved.
2273 setMaxMarginBeforeValues(oldTopPosMargin, oldTopNegMargin);
2274 marginInfo.setAtBeforeSideOfBlock(false);
2276 // In case the child discarded the before margin of the block we need to reset the mustDiscardMarginBefore flag to the initial value.
2277 setMustDiscardMarginBefore(style()->marginBeforeCollapse() == MDISCARD);
2280 LayoutUnit logicalTop = yPos + heightIncrease;
2281 // After margin collapsing, one of our floats may now intrude into the child. If the child doesn't contain floats of its own it
2282 // won't get picked up for relayout even though the logical top estimate was wrong - so add the newly intruding float now.
2283 if (containsFloats() && child->isRenderBlock() && !toRenderBlock(child)->containsFloats() && !child->avoidsFloats() && lowestFloatLogicalBottom() > logicalTop)
2284 toRenderBlock(child)->addIntrudingFloats(this, logicalLeftOffsetForContent(), logicalTop);
2289 void RenderBlock::marginBeforeEstimateForChild(RenderBox* child, LayoutUnit& positiveMarginBefore, LayoutUnit& negativeMarginBefore, bool& discardMarginBefore) const
2291 // Give up if in quirks mode and we're a body/table cell and the top margin of the child box is quirky.
2292 // Give up if the child specified -webkit-margin-collapse: separate that prevents collapsing.
2293 // FIXME: Use writing mode independent accessor for marginBeforeCollapse.
2294 if ((document()->inQuirksMode() && hasMarginAfterQuirk(child) && (isTableCell() || isBody())) || child->style()->marginBeforeCollapse() == MSEPARATE)
2297 // The margins are discarded by a child that specified -webkit-margin-collapse: discard.
2298 // FIXME: Use writing mode independent accessor for marginBeforeCollapse.
2299 if (child->style()->marginBeforeCollapse() == MDISCARD) {
2300 positiveMarginBefore = 0;
2301 negativeMarginBefore = 0;
2302 discardMarginBefore = true;
2306 LayoutUnit beforeChildMargin = marginBeforeForChild(child);
2307 positiveMarginBefore = max(positiveMarginBefore, beforeChildMargin);
2308 negativeMarginBefore = max(negativeMarginBefore, -beforeChildMargin);
2310 if (!child->isRenderBlock())
2313 RenderBlock* childBlock = toRenderBlock(child);
2314 if (childBlock->childrenInline() || childBlock->isWritingModeRoot())
2317 MarginInfo childMarginInfo(childBlock, childBlock->borderBefore() + childBlock->paddingBefore(), childBlock->borderAfter() + childBlock->paddingAfter());
2318 if (!childMarginInfo.canCollapseMarginBeforeWithChildren())
2321 RenderBox* grandchildBox = childBlock->firstChildBox();
2322 for ( ; grandchildBox; grandchildBox = grandchildBox->nextSiblingBox()) {
2323 if (!grandchildBox->isFloatingOrOutOfFlowPositioned())
2327 // Give up if there is clearance on the box, since it probably won't collapse into us.
2328 if (!grandchildBox || grandchildBox->style()->clear() != CNONE)
2331 // Make sure to update the block margins now for the grandchild box so that we're looking at current values.
2332 if (grandchildBox->needsLayout()) {
2333 grandchildBox->computeAndSetBlockDirectionMargins(this);
2334 if (grandchildBox->isRenderBlock()) {
2335 RenderBlock* grandchildBlock = toRenderBlock(grandchildBox);
2336 grandchildBlock->setHasMarginBeforeQuirk(grandchildBox->style()->hasMarginBeforeQuirk());
2337 grandchildBlock->setHasMarginAfterQuirk(grandchildBox->style()->hasMarginAfterQuirk());
2341 // Collapse the margin of the grandchild box with our own to produce an estimate.
2342 childBlock->marginBeforeEstimateForChild(grandchildBox, positiveMarginBefore, negativeMarginBefore, discardMarginBefore);
2345 LayoutUnit RenderBlock::estimateLogicalTopPosition(RenderBox* child, const MarginInfo& marginInfo, LayoutUnit& estimateWithoutPagination)
2347 // FIXME: We need to eliminate the estimation of vertical position, because when it's wrong we sometimes trigger a pathological
2348 // relayout if there are intruding floats.
2349 LayoutUnit logicalTopEstimate = logicalHeight();
2350 if (!marginInfo.canCollapseWithMarginBefore()) {
2351 LayoutUnit positiveMarginBefore = 0;
2352 LayoutUnit negativeMarginBefore = 0;
2353 bool discardMarginBefore = false;
2354 if (child->selfNeedsLayout()) {
2355 // Try to do a basic estimation of how the collapse is going to go.
2356 marginBeforeEstimateForChild(child, positiveMarginBefore, negativeMarginBefore, discardMarginBefore);
2358 // Use the cached collapsed margin values from a previous layout. Most of the time they
2360 MarginValues marginValues = marginValuesForChild(child);
2361 positiveMarginBefore = max(positiveMarginBefore, marginValues.positiveMarginBefore());
2362 negativeMarginBefore = max(negativeMarginBefore, marginValues.negativeMarginBefore());
2363 discardMarginBefore = mustDiscardMarginBeforeForChild(child);
2366 // Collapse the result with our current margins.
2367 if (!discardMarginBefore)
2368 logicalTopEstimate += max(marginInfo.positiveMargin(), positiveMarginBefore) - max(marginInfo.negativeMargin(), negativeMarginBefore);
2371 // Adjust logicalTopEstimate down to the next page if the margins are so large that we don't fit on the current
2373 LayoutState* layoutState = view()->layoutState();
2374 if (layoutState->isPaginated() && layoutState->pageLogicalHeight() && logicalTopEstimate > logicalHeight()
2375 && hasNextPage(logicalHeight()))
2376 logicalTopEstimate = min(logicalTopEstimate, nextPageLogicalTop(logicalHeight()));
2378 logicalTopEstimate += getClearDelta(child, logicalTopEstimate);
2380 estimateWithoutPagination = logicalTopEstimate;
2382 if (layoutState->isPaginated()) {
2383 // If the object has a page or column break value of "before", then we should shift to the top of the next page.
2384 logicalTopEstimate = applyBeforeBreak(child, logicalTopEstimate);
2386 // For replaced elements and scrolled elements, we want to shift them to the next page if they don't fit on the current one.
2387 logicalTopEstimate = adjustForUnsplittableChild(child, logicalTopEstimate);
2389 if (!child->selfNeedsLayout() && child->isRenderBlock())
2390 logicalTopEstimate += toRenderBlock(child)->paginationStrut();
2393 return logicalTopEstimate;
2396 LayoutUnit RenderBlock::computeStartPositionDeltaForChildAvoidingFloats(const RenderBox* child, LayoutUnit childMarginStart, RenderRegion* region)
2398 LayoutUnit startPosition = startOffsetForContent(region);
2400 // Add in our start margin.
2401 LayoutUnit oldPosition = startPosition + childMarginStart;
2402 LayoutUnit newPosition = oldPosition;
2404 LayoutUnit blockOffset = logicalTopForChild(child);
2406 blockOffset = max(blockOffset, blockOffset + (region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage()));
2408 LayoutUnit startOff = startOffsetForLine(blockOffset, false, region, logicalHeightForChild(child));
2410 if (style()->textAlign() != WEBKIT_CENTER && !child->style()->marginStartUsing(style()).isAuto()) {
2411 if (childMarginStart < 0)
2412 startOff += childMarginStart;
2413 newPosition = max(newPosition, startOff); // Let the float sit in the child's margin if it can fit.
2414 } else if (startOff != startPosition)
2415 newPosition = startOff + childMarginStart;
2417 return newPosition - oldPosition;
2420 void RenderBlock::determineLogicalLeftPositionForChild(RenderBox* child, ApplyLayoutDeltaMode applyDelta)
2422 LayoutUnit startPosition = borderStart() + paddingStart();
2423 if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
2424 startPosition -= verticalScrollbarWidth();
2425 LayoutUnit totalAvailableLogicalWidth = borderAndPaddingLogicalWidth() + availableLogicalWidth();
2427 // Add in our start margin.
2428 LayoutUnit childMarginStart = marginStartForChild(child);
2429 LayoutUnit newPosition = startPosition + childMarginStart;
2431 // Some objects (e.g., tables, horizontal rules, overflow:auto blocks) avoid floats. They need
2432 // to shift over as necessary to dodge any floats that might get in the way.
2433 if (child->avoidsFloats() && containsFloats() && !flowThreadContainingBlock())
2434 newPosition += computeStartPositionDeltaForChildAvoidingFloats(child, marginStartForChild(child));
2436 setLogicalLeftForChild(child, style()->isLeftToRightDirection() ? newPosition : totalAvailableLogicalWidth - newPosition - logicalWidthForChild(child), applyDelta);
2439 void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo)
2441 if (marginInfo.canCollapseWithMarginAfter() && !marginInfo.canCollapseWithMarginBefore()) {
2442 // Update the after side margin of the container to discard if the after margin of the last child also discards and we collapse with it.
2443 // Don't update the max margin values because we won't need them anyway.
2444 if (marginInfo.discardMargin()) {
2445 setMustDiscardMarginAfter();
2449 // Update our max pos/neg bottom margins, since we collapsed our bottom margins
2450 // with our children.
2451 setMaxMarginAfterValues(max(maxPositiveMarginAfter(), marginInfo.positiveMargin()), max(maxNegativeMarginAfter(), marginInfo.negativeMargin()));
2453 if (!marginInfo.hasMarginAfterQuirk())
2454 setHasMarginAfterQuirk(false);
2456 if (marginInfo.hasMarginAfterQuirk() && !marginAfter())
2457 // We have no bottom margin and our last child has a quirky margin.
2458 // We will pick up this quirky margin and pass it through.
2459 // This deals with the <td><div><p> case.
2460 setHasMarginAfterQuirk(true);
2464 void RenderBlock::handleAfterSideOfBlock(LayoutUnit beforeSide, LayoutUnit afterSide, MarginInfo& marginInfo)
2466 marginInfo.setAtAfterSideOfBlock(true);
2468 // If we can't collapse with children then go ahead and add in the bottom margin.
2469 if (!marginInfo.discardMargin() && (!marginInfo.canCollapseWithMarginAfter() && !marginInfo.canCollapseWithMarginBefore()
2470 && (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !marginInfo.hasMarginAfterQuirk())))
2471 setLogicalHeight(logicalHeight() + marginInfo.margin());
2473 // Now add in our bottom border/padding.
2474 setLogicalHeight(logicalHeight() + afterSide);
2476 // Negative margins can cause our height to shrink below our minimal height (border/padding).
2477 // If this happens, ensure that the computed height is increased to the minimal height.
2478 setLogicalHeight(max(logicalHeight(), beforeSide + afterSide));
2480 // Update our bottom collapsed margin info.
2481 setCollapsedBottomMargin(marginInfo);
2484 void RenderBlock::setLogicalLeftForChild(RenderBox* child, LayoutUnit logicalLeft, ApplyLayoutDeltaMode applyDelta)
2486 if (isHorizontalWritingMode()) {
2487 if (applyDelta == ApplyLayoutDelta)
2488 view()->addLayoutDelta(LayoutSize(child->x() - logicalLeft, 0));
2489 child->setX(logicalLeft);
2491 if (applyDelta == ApplyLayoutDelta)
2492 view()->addLayoutDelta(LayoutSize(0, child->y() - logicalLeft));
2493 child->setY(logicalLeft);
2497 void RenderBlock::setLogicalTopForChild(RenderBox* child, LayoutUnit logicalTop, ApplyLayoutDeltaMode applyDelta)
2499 if (isHorizontalWritingMode()) {
2500 if (applyDelta == ApplyLayoutDelta)
2501 view()->addLayoutDelta(LayoutSize(0, child->y() - logicalTop));
2502 child->setY(logicalTop);
2504 if (applyDelta == ApplyLayoutDelta)
2505 view()->addLayoutDelta(LayoutSize(child->x() - logicalTop, 0));
2506 child->setX(logicalTop);
2510 void RenderBlock::updateBlockChildDirtyBitsBeforeLayout(bool relayoutChildren, RenderBox* child)
2512 // FIXME: Technically percentage height objects only need a relayout if their percentage isn't going to be turned into
2513 // an auto value. Add a method to determine this, so that we can avoid the relayout.
2514 if (relayoutChildren || (child->hasRelativeLogicalHeight() && !isRenderView()) || child->hasViewportPercentageLogicalHeight())
2515 child->setChildNeedsLayout(true, MarkOnlyThis);
2517 // If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths.
2518 if (relayoutChildren && child->needsPreferredWidthsRecalculation())
2519 child->setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
2522 void RenderBlock::layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloatLogicalBottom)
2524 if (gPercentHeightDescendantsMap) {
2525 if (TrackedRendererListHashSet* descendants = gPercentHeightDescendantsMap->get(this)) {
2526 TrackedRendererListHashSet::iterator end = descendants->end();
2527 for (TrackedRendererListHashSet::iterator it = descendants->begin(); it != end; ++it) {
2528 RenderBox* box = *it;
2529 while (box != this) {
2530 if (box->normalChildNeedsLayout())
2532 box->setChildNeedsLayout(true, MarkOnlyThis);
2533 box = box->containingBlock();
2542 LayoutUnit beforeEdge = borderBefore() + paddingBefore();
2543 LayoutUnit afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeight();
2545 setLogicalHeight(beforeEdge);
2547 // Lay out our hypothetical grid line as though it occurs at the top of the block.
2548 if (view()->layoutState()->lineGrid() == this)
2549 layoutLineGridBox();
2551 // The margin struct caches all our current margin collapsing state. The compact struct caches state when we encounter compacts,
2552 MarginInfo marginInfo(this, beforeEdge, afterEdge);
2554 // Fieldsets need to find their legend and position it inside the border of the object.
2555 // The legend then gets skipped during normal layout. The same is true for ruby text.
2556 // It doesn't get included in the normal layout process but is instead skipped.
2557 RenderObject* childToExclude = layoutSpecialExcludedChild(relayoutChildren);
2559 LayoutUnit previousFloatLogicalBottom = 0;
2560 maxFloatLogicalBottom = 0;
2562 RenderBox* next = firstChildBox();
2565 RenderBox* child = next;
2566 next = child->nextSiblingBox();
2568 if (childToExclude == child)
2569 continue; // Skip this child, since it will be positioned by the specialized subclass (fieldsets and ruby runs).
2571 updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, child);
2573 if (child->isOutOfFlowPositioned()) {
2574 child->containingBlock()->insertPositionedObject(child);
2575 adjustPositionedBlock(child, marginInfo);
2578 if (child->isFloating()) {
2579 insertFloatingObject(child);
2580 adjustFloatingBlock(marginInfo);
2584 // Lay out the child.
2585 layoutBlockChild(child, marginInfo, previousFloatLogicalBottom, maxFloatLogicalBottom);
2588 // Now do the handling of the bottom of the block, adding in our bottom border/padding and
2589 // determining the correct collapsed bottom margin information.
2590 handleAfterSideOfBlock(beforeEdge, afterEdge, marginInfo);
2593 void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom)
2595 LayoutUnit oldPosMarginBefore = maxPositiveMarginBefore();
2596 LayoutUnit oldNegMarginBefore = maxNegativeMarginBefore();
2598 // The child is a normal flow object. Compute the margins we will use for collapsing now.
2599 child->computeAndSetBlockDirectionMargins(this);
2601 // Try to guess our correct logical top position. In most cases this guess will
2602 // be correct. Only if we're wrong (when we compute the real logical top position)
2603 // will we have to potentially relayout.
2604 LayoutUnit estimateWithoutPagination;
2605 LayoutUnit logicalTopEstimate = estimateLogicalTopPosition(child, marginInfo, estimateWithoutPagination);
2607 // Cache our old rect so that we can dirty the proper repaint rects if the child moves.
2608 LayoutRect oldRect = child->frameRect();
2609 LayoutUnit oldLogicalTop = logicalTopForChild(child);
2611 #if !ASSERT_DISABLED
2612 LayoutSize oldLayoutDelta = view()->layoutDelta();
2614 // Go ahead and position the child as though it didn't collapse with the top.
2615 setLogicalTopForChild(child, logicalTopEstimate, ApplyLayoutDelta);
2617 RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
2618 bool markDescendantsWithFloats = false;
2619 if (logicalTopEstimate != oldLogicalTop && !child->avoidsFloats() && childRenderBlock && childRenderBlock->containsFloats())
2620 markDescendantsWithFloats = true;
2621 #if ENABLE(SUBPIXEL_LAYOUT)
2622 else if (UNLIKELY(logicalTopEstimate.mightBeSaturated()))
2623 // logicalTopEstimate, returned by estimateLogicalTopPosition, might be saturated for
2624 // very large elements. If it does the comparison with oldLogicalTop might yield a
2625 // false negative as adding and removing margins, borders etc from a saturated number
2626 // might yield incorrect results. If this is the case always mark for layout.
2627 markDescendantsWithFloats = true;
2629 else if (!child->avoidsFloats() || child->shrinkToAvoidFloats()) {
2630 // If an element might be affected by the presence of floats, then always mark it for
2632 LayoutUnit fb = max(previousFloatLogicalBottom, lowestFloatLogicalBottom());
2633 if (fb > logicalTopEstimate)
2634 markDescendantsWithFloats = true;
2637 if (childRenderBlock) {
2638 if (markDescendantsWithFloats)
2639 childRenderBlock->markAllDescendantsWithFloatsForLayout();
2640 if (!child->isWritingModeRoot())
2641 previousFloatLogicalBottom = max(previousFloatLogicalBottom, oldLogicalTop + childRenderBlock->lowestFloatLogicalBottom());
2644 if (!child->needsLayout())
2645 child->markForPaginationRelayoutIfNeeded();
2647 bool childHadLayout = child->everHadLayout();
2648 bool childNeededLayout = child->needsLayout();
2649 if (childNeededLayout)
2652 // Cache if we are at the top of the block right now.
2653 bool atBeforeSideOfBlock = marginInfo.atBeforeSideOfBlock();
2655 // Now determine the correct ypos based off examination of collapsing margin
2657 LayoutUnit logicalTopBeforeClear = collapseMargins(child, marginInfo);
2659 // Now check for clear.
2660 LayoutUnit logicalTopAfterClear = clearFloatsIfNeeded(child, marginInfo, oldPosMarginBefore, oldNegMarginBefore, logicalTopBeforeClear);
2662 bool paginated = view()->layoutState()->isPaginated();
2664 logicalTopAfterClear = adjustBlockChildForPagination(logicalTopAfterClear, estimateWithoutPagination, child,
2665 atBeforeSideOfBlock && logicalTopBeforeClear == logicalTopAfterClear);
2667 setLogicalTopForChild(child, logicalTopAfterClear, ApplyLayoutDelta);
2669 // Now we have a final top position. See if it really does end up being different from our estimate.
2670 // clearFloatsIfNeeded can also mark the child as needing a layout even though we didn't move. This happens
2671 // when collapseMargins dynamically adds overhanging floats because of a child with negative margins.
2672 if (logicalTopAfterClear != logicalTopEstimate || child->needsLayout() || (paginated && childRenderBlock && childRenderBlock->shouldBreakAtLineToAvoidWidow())) {
2673 if (child->shrinkToAvoidFloats()) {
2674 // The child's width depends on the line width.
2675 // When the child shifts to clear an item, its width can
2676 // change (because it has more available line width).
2677 // So go ahead and mark the item as dirty.
2678 child->setChildNeedsLayout(true, MarkOnlyThis);
2681 if (childRenderBlock) {
2682 if (!child->avoidsFloats() && childRenderBlock->containsFloats())
2683 childRenderBlock->markAllDescendantsWithFloatsForLayout();
2684 if (!child->needsLayout())
2685 child->markForPaginationRelayoutIfNeeded();
2688 // Our guess was wrong. Make the child lay itself out again.
2689 child->layoutIfNeeded();
2692 // We are no longer at the top of the block if we encounter a non-empty child.
2693 // This has to be done after checking for clear, so that margins can be reset if a clear occurred.
2694 if (marginInfo.atBeforeSideOfBlock() && !child->isSelfCollapsingBlock())
2695 marginInfo.setAtBeforeSideOfBlock(false);
2697 // Now place the child in the correct left position
2698 determineLogicalLeftPositionForChild(child, ApplyLayoutDelta);
2700 // Update our height now that the child has been placed in the correct position.
2701 setLogicalHeight(logicalHeight() + logicalHeightForChild(child));
2702 if (mustSeparateMarginAfterForChild(child)) {
2703 setLogicalHeight(logicalHeight() + marginAfterForChild(child));
2704 marginInfo.clearMargin();
2706 // If the child has overhanging floats that intrude into following siblings (or possibly out
2707 // of this block), then the parent gets notified of the floats now.
2708 if (childRenderBlock && childRenderBlock->containsFloats())
2709 maxFloatLogicalBottom = max(maxFloatLogicalBottom, addOverhangingFloats(toRenderBlock(child), !childNeededLayout));
2711 LayoutSize childOffset = child->location() - oldRect.location();
2712 if (childOffset.width() || childOffset.height()) {
2713 view()->addLayoutDelta(childOffset);
2715 // If the child moved, we have to repaint it as well as any floating/positioned
2716 // descendants. An exception is if we need a layout. In this case, we know we're going to
2717 // repaint ourselves (and the child) anyway.
2718 if (childHadLayout && !selfNeedsLayout() && child->checkForRepaintDuringLayout())
2719 child->repaintDuringLayoutIfMoved(oldRect);
2722 if (!childHadLayout && child->checkForRepaintDuringLayout()) {
2724 child->repaintOverhangingFloats(true);
2728 // Check for an after page/column break.
2729 LayoutUnit newHeight = applyAfterBreak(child, logicalHeight(), marginInfo);
2730 if (newHeight != height())
2731 setLogicalHeight(newHeight);
2734 ASSERT(view()->layoutDeltaMatches(oldLayoutDelta));
2737 void RenderBlock::simplifiedNormalFlowLayout()
2739 if (childrenInline()) {
2740 ListHashSet<RootInlineBox*> lineBoxes;
2741 for (InlineWalker walker(this); !walker.atEnd(); walker.advance()) {
2742 RenderObject* o = walker.current();
2743 if (!o->isOutOfFlowPositioned() && (o->isReplaced() || o->isFloating())) {
2744 o->layoutIfNeeded();
2745 if (toRenderBox(o)->inlineBoxWrapper()) {
2746 RootInlineBox* box = toRenderBox(o)->inlineBoxWrapper()->root();
2749 } else if (o->isText() || (o->isRenderInline() && !walker.atEndOfInline()))
2750 o->setNeedsLayout(false);
2753 // FIXME: Glyph overflow will get lost in this case, but not really a big deal.
2754 GlyphOverflowAndFallbackFontsMap textBoxDataMap;
2755 for (ListHashSet<RootInlineBox*>::const_iterator it = lineBoxes.begin(); it != lineBoxes.end(); ++it) {
2756 RootInlineBox* box = *it;
2757 box->computeOverflow(box->lineTop(), box->lineBottom(), textBoxDataMap);
2760 for (RenderBox* box = firstChildBox(); box; box = box->nextSiblingBox()) {
2761 if (!box->isOutOfFlowPositioned())
2762 box->layoutIfNeeded();
2767 bool RenderBlock::simplifiedLayout()
2769 if ((!posChildNeedsLayout() && !needsSimplifiedNormalFlowLayout()) || normalChildNeedsLayout() || selfNeedsLayout())
2772 LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasColumns() || hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
2774 if (needsPositionedMovementLayout() && !tryLayoutDoingPositionedMovementOnly())
2777 // Lay out positioned descendants or objects that just need to recompute overflow.
2778 if (needsSimplifiedNormalFlowLayout())
2779 simplifiedNormalFlowLayout();
2781 // Lay out our positioned objects if our positioned child bit is set.
2782 // Also, if an absolute position element inside a relative positioned container moves, and the absolute element has a fixed position
2783 // child, neither the fixed element nor its container learn of the movement since posChildNeedsLayout() is only marked as far as the
2784 // relative positioned container. So if we can have fixed pos objects in our positioned objects list check if any of them
2785 // are statically positioned and thus need to move with their absolute ancestors.
2786 bool canContainFixedPosObjects = canContainFixedPositionObjects();
2787 if (posChildNeedsLayout() || canContainFixedPosObjects)
2788 layoutPositionedObjects(false, !posChildNeedsLayout() && canContainFixedPosObjects);
2790 // Recompute our overflow information.
2791 // FIXME: We could do better here by computing a temporary overflow object from layoutPositionedObjects and only
2792 // updating our overflow if we either used to have overflow or if the new temporary object has overflow.
2793 // For now just always recompute overflow. This is no worse performance-wise than the old code that called rightmostPosition and
2794 // lowestPosition on every relayout so it's not a regression.
2795 // computeOverflow expects the bottom edge before we clamp our height. Since this information isn't available during
2796 // simplifiedLayout, we cache the value in m_overflow.
2797 LayoutUnit oldClientAfterEdge = hasRenderOverflow() ? m_overflow->layoutClientAfterEdge() : clientLogicalBottom();
2798 computeOverflow(oldClientAfterEdge, true);
2802 updateLayerTransform();
2804 updateScrollInfoAfterLayout();
2806 setNeedsLayout(false);
2810 void RenderBlock::markFixedPositionObjectForLayoutIfNeeded(RenderObject* child)
2812 if (child->style()->position() != FixedPosition)
2815 bool hasStaticBlockPosition = child->style()->hasStaticBlockPosition(isHorizontalWritingMode());
2816 bool hasStaticInlinePosition = child->style()->hasStaticInlinePosition(isHorizontalWritingMode());
2817 if (!hasStaticBlockPosition && !hasStaticInlinePosition)
2820 RenderObject* o = child->parent();
2821 while (o && !o->isRenderView() && o->style()->position() != AbsolutePosition)
2823 if (o->style()->position() != AbsolutePosition)
2826 RenderBox* box = toRenderBox(child);
2827 if (hasStaticInlinePosition) {
2828 LogicalExtentComputedValues computedValues;
2829 box->computeLogicalWidthInRegion(computedValues);
2830 LayoutUnit newLeft = computedValues.m_position;
2831 if (newLeft != box->logicalLeft())
2832 child->setChildNeedsLayout(true, MarkOnlyThis);
2833 } else if (hasStaticBlockPosition) {
2834 LayoutUnit oldTop = box->logicalTop();
2835 box->updateLogicalHeight();
2836 if (box->logicalTop() != oldTop)
2837 child->setChildNeedsLayout(true, MarkOnlyThis);
2841 void RenderBlock::layoutPositionedObjects(bool relayoutChildren, bool fixedPositionObjectsOnly)
2843 TrackedRendererListHashSet* positionedDescendants = positionedObjects();
2844 if (!positionedDescendants)
2848 view()->layoutState()->clearPaginationInformation(); // Positioned objects are not part of the column flow, so they don't paginate with the columns.
2851 TrackedRendererListHashSet::iterator end = positionedDescendants->end();
2852 for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) {
2855 // A fixed position element with an absolute positioned ancestor has no way of knowing if the latter has changed position. So
2856 // if this is a fixed position element, mark it for layout if it has an abspos ancestor and needs to move with that ancestor, i.e.
2857 // it has static position.
2858 markFixedPositionObjectForLayoutIfNeeded(r);
2859 if (fixedPositionObjectsOnly) {
2860 r->layoutIfNeeded();
2864 // When a non-positioned block element moves, it may have positioned children that are implicitly positioned relative to the
2865 // non-positioned block. Rather than trying to detect all of these movement cases, we just always lay out positioned
2866 // objects that are positioned implicitly like this. Such objects are rare, and so in typical DHTML menu usage (where everything is
2867 // positioned explicitly) this should not incur a performance penalty.
2868 if (relayoutChildren || (r->style()->hasStaticBlockPosition(isHorizontalWritingMode()) && r->parent() != this))
2869 r->setChildNeedsLayout(true, MarkOnlyThis);
2871 // If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths.
2872 if (relayoutChildren && r->needsPreferredWidthsRecalculation())
2873 r->setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
2875 if (!r->needsLayout())
2876 r->markForPaginationRelayoutIfNeeded();
2878 // We don't have to do a full layout. We just have to update our position. Try that first. If we have shrink-to-fit width
2879 // and we hit the available width constraint, the layoutIfNeeded() will catch it and do a full layout.
2880 if (r->needsPositionedMovementLayoutOnly() && r->tryLayoutDoingPositionedMovementOnly())
2881 r->setNeedsLayout(false);
2883 // If we are paginated or in a line grid, go ahead and compute a vertical position for our object now.
2884 // If it's wrong we'll lay out again.
2885 LayoutUnit oldLogicalTop = 0;
2886 bool needsBlockDirectionLocationSetBeforeLayout = r->needsLayout() && view()->layoutState()->needsBlockDirectionLocationSetBeforeLayout();
2887 if (needsBlockDirectionLocationSetBeforeLayout) {
2888 if (isHorizontalWritingMode() == r->isHorizontalWritingMode())
2889 r->updateLogicalHeight();
2891 r->updateLogicalWidth();
2892 oldLogicalTop = logicalTopForChild(r);
2895 r->layoutIfNeeded();
2897 // Lay out again if our estimate was wrong.
2898 if (needsBlockDirectionLocationSetBeforeLayout && logicalTopForChild(r) != oldLogicalTop) {
2899 r->setChildNeedsLayout(true, MarkOnlyThis);
2900 r->layoutIfNeeded();
2905 view()->layoutState()->m_columnInfo = columnInfo(); // FIXME: Kind of gross. We just put this back into the layout state so that pop() will work.
2908 void RenderBlock::markPositionedObjectsForLayout()
2910 TrackedRendererListHashSet* positionedDescendants = positionedObjects();
2911 if (positionedDescendants) {
2913 TrackedRendererListHashSet::iterator end = positionedDescendants->end();
2914 for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) {
2916 r->setChildNeedsLayout(true);
2921 void RenderBlock::markForPaginationRelayoutIfNeeded()
2923 ASSERT(!needsLayout());
2927 if (view()->layoutState()->pageLogicalHeightChanged() || (view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(this, logicalTop()) != pageLogicalOffset()) || shouldBreakAtLineToAvoidWidow())
2928 setChildNeedsLayout(true, MarkOnlyThis);
2931 void RenderBlock::repaintOverhangingFloats(bool paintAllDescendants)
2933 // Repaint any overhanging floats (if we know we're the one to paint them).
2934 // Otherwise, bail out.
2935 if (!hasOverhangingFloats())
2938 // FIXME: Avoid disabling LayoutState. At the very least, don't disable it for floats originating
2939 // in this block. Better yet would be to push extra state for the containers of other floats.
2940 LayoutStateDisabler layoutStateDisabler(view());
2941 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
2942 FloatingObjectSetIterator end = floatingObjectSet.end();
2943 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
2944 FloatingObject* r = *it;
2945 // Only repaint the object if it is overhanging, is not in its own layer, and
2946 // is our responsibility to paint (m_shouldPaint is set). When paintAllDescendants is true, the latter
2947 // condition is replaced with being a descendant of us.
2948 if (logicalBottomForFloat(r) > logicalHeight() && ((paintAllDescendants && r->m_renderer->isDescendantOf(this)) || r->shouldPaint()) && !r->m_renderer->hasSelfPaintingLayer()) {
2949 r->m_renderer->repaint();
2950 r->m_renderer->repaintOverhangingFloats(false);
2955 void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
2957 LayoutPoint adjustedPaintOffset = paintOffset + location();
2959 PaintPhase phase = paintInfo.phase;
2961 // Check if we need to do anything at all.
2962 // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
2963 // paints the root's background.
2965 LayoutRect overflowBox = overflowRectForPaintRejection();
2966 flipForWritingMode(overflowBox);
2967 overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
2968 overflowBox.moveBy(adjustedPaintOffset);
2969 if (!overflowBox.intersects(paintInfo.rect))
2973 bool pushedClip = pushContentsClip(paintInfo, adjustedPaintOffset);
2974 paintObject(paintInfo, adjustedPaintOffset);
2976 popContentsClip(paintInfo, phase, adjustedPaintOffset);
2978 // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
2979 // z-index. We paint after we painted the background/border, so that the scrollbars will
2980 // sit above the background/border.
2981 if (hasOverflowClip() && style()->visibility() == VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground) && paintInfo.shouldPaintWithinRoot(this) && !paintInfo.paintRootBackgroundOnly())
2982 layer()->paintOverflowControls(paintInfo.context, roundedIntPoint(adjustedPaintOffset), paintInfo.rect);
2985 void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
2987 if (paintInfo.context->paintingDisabled())
2990 const Color& ruleColor = style()->visitedDependentColor(CSSPropertyWebkitColumnRuleColor);
2991 bool ruleTransparent = style()->columnRuleIsTransparent();
2992 EBorderStyle ruleStyle = style()->columnRuleStyle();
2993 LayoutUnit ruleThickness = style()->columnRuleWidth();
2994 LayoutUnit colGap = columnGap();
2995 bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent;
2999 ColumnInfo* colInfo = columnInfo();
3000 unsigned colCount = columnCount(colInfo);
3002 bool antialias = shouldAntialiasLines(paintInfo.context);
3004 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) {
3005 bool leftToRight = style()->isLeftToRightDirection() ^ colInfo->progressionIsReversed();
3006 LayoutUnit currLogicalLeftOffset = leftToRight ? LayoutUnit() : contentLogicalWidth();
3007 LayoutUnit ruleAdd = logicalLeftOffsetForContent();
3008 LayoutUnit ruleLogicalLeft = leftToRight ? LayoutUnit() : contentLogicalWidth();
3009 LayoutUnit inlineDirectionSize = colInfo->desiredColumnWidth();
3010 BoxSide boxSide = isHorizontalWritingMode()
3011 ? leftToRight ? BSLeft : BSRight
3012 : leftToRight ? BSTop : BSBottom;
3014 for (unsigned i = 0; i < colCount; i++) {
3015 // Move to the next position.
3017 ruleLogicalLeft += inlineDirectionSize + colGap / 2;
3018 currLogicalLeftOffset += inlineDirectionSize + colGap;
3020 ruleLogicalLeft -= (inlineDirectionSize + colGap / 2);
3021 currLogicalLeftOffset -= (inlineDirectionSize + colGap);
3024 // Now paint the column rule.
3025 if (i < colCount - 1) {
3026 LayoutUnit ruleLeft = isHorizontalWritingMode() ? paintOffset.x() + ruleLogicalLeft - ruleThickness / 2 + ruleAdd : paintOffset.x() + borderLeft() + paddingLeft();
3027 LayoutUnit ruleRight = isHorizontalWritingMode() ? ruleLeft + ruleThickness : ruleLeft + contentWidth();
3028 LayoutUnit ruleTop = isHorizontalWritingMode() ? paintOffset.y() + borderTop() + paddingTop() : paintOffset.y() + ruleLogicalLeft - ruleThickness / 2 + ruleAdd;
3029 LayoutUnit ruleBottom = isHorizontalWritingMode() ? ruleTop + contentHeight() : ruleTop + ruleThickness;
3030 IntRect pixelSnappedRuleRect = pixelSnappedIntRectFromEdges(ruleLeft, ruleTop, ruleRight, ruleBottom);
3031 drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);
3034 ruleLogicalLeft = currLogicalLeftOffset;
3037 bool topToBottom = !style()->isFlippedBlocksWritingMode() ^ colInfo->progressionIsReversed();
3038 LayoutUnit ruleLeft = isHorizontalWritingMode()
3039 ? borderLeft() + paddingLeft()
3040 : colGap / 2 - colGap - ruleThickness / 2 + (!colInfo->progressionIsReversed() ? borderBefore() + paddingBefore() : borderAfter() + paddingAfter());
3041 LayoutUnit ruleWidth = isHorizontalWritingMode() ? contentWidth() : ruleThickness;
3042 LayoutUnit ruleTop = isHorizontalWritingMode()
3043 ? colGap / 2 - colGap - ruleThickness / 2 + (!colInfo->progressionIsReversed() ? borderBefore() + paddingBefore() : borderAfter() + paddingAfter())
3044 : borderStart() + paddingStart();
3045 LayoutUnit ruleHeight = isHorizontalWritingMode() ? ruleThickness : contentHeight();
3046 LayoutRect ruleRect(ruleLeft, ruleTop, ruleWidth, ruleHeight);
3049 if (isHorizontalWritingMode())
3050 ruleRect.setY(height() - ruleRect.maxY());
3052 ruleRect.setX(width() - ruleRect.maxX());
3055 ruleRect.moveBy(paintOffset);
3057 BoxSide boxSide = isHorizontalWritingMode()
3058 ? topToBottom ? BSTop : BSBottom
3059 : topToBottom ? BSLeft : BSRight;
3061 LayoutSize step(0, topToBottom ? colInfo->columnHeight() + colGap : -(colInfo->columnHeight() + colGap));
3062 if (!isHorizontalWritingMode())
3063 step = step.transposedSize();
3065 for (unsigned i = 1; i < colCount; i++) {
3066 ruleRect.move(step);
3067 IntRect pixelSnappedRuleRect = pixelSnappedIntRect(ruleRect);
3068 drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);
3073 void RenderBlock::paintColumnContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset, bool paintingFloats)
3075 // We need to do multiple passes, breaking up our child painting into strips.
3076 GraphicsContext* context = paintInfo.context;
3077 ColumnInfo* colInfo = columnInfo();
3078 unsigned colCount = columnCount(colInfo);
3081 LayoutUnit currLogicalTopOffset = 0;
3082 LayoutUnit colGap = columnGap();
3083 for (unsigned i = 0; i < colCount; i++) {
3084 // For each rect, we clip to the rect, and then we adjust our coords.
3085 LayoutRect colRect = columnRectAt(colInfo, i);
3086 flipForWritingMode(colRect);
3087 LayoutUnit logicalLeftOffset = (isHorizontalWritingMode() ? colRect.x() : colRect.y()) - logicalLeftOffsetForContent();
3088 LayoutSize offset = isHorizontalWritingMode() ? LayoutSize(logicalLeftOffset, currLogicalTopOffset) : LayoutSize(currLogicalTopOffset, logicalLeftOffset);
3089 if (colInfo->progressionAxis() == ColumnInfo::BlockAxis) {
3090 if (isHorizontalWritingMode())
3091 offset.expand(0, colRect.y() - borderTop() - paddingTop());
3093 offset.expand(colRect.x() - borderLeft() - paddingLeft(), 0);
3095 colRect.moveBy(paintOffset);
3096 PaintInfo info(paintInfo);
3097 info.rect.intersect(pixelSnappedIntRect(colRect));
3099 if (!info.rect.isEmpty()) {
3100 GraphicsContextStateSaver stateSaver(*context);
3101 LayoutRect clipRect(colRect);
3103 if (i < colCount - 1) {
3104 if (isHorizontalWritingMode())
3105 clipRect.expand(colGap / 2, 0);
3107 clipRect.expand(0, colGap / 2);
3109 // Each strip pushes a clip, since column boxes are specified as being
3110 // like overflow:hidden.
3111 // FIXME: Content and column rules that extend outside column boxes at the edges of the multi-column element
3112 // are clipped according to the 'overflow' property.
3113 context->clip(pixelSnappedIntRect(clipRect));
3115 // Adjust our x and y when painting.
3116 LayoutPoint adjustedPaintOffset = paintOffset + offset;
3118 paintFloats(info, adjustedPaintOffset, paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip);
3120 paintContents(info, adjustedPaintOffset);
3123 LayoutUnit blockDelta = (isHorizontalWritingMode() ? colRect.height() : colRect.width());
3124 if (style()->isFlippedBlocksWritingMode())
3125 currLogicalTopOffset += blockDelta;
3127 currLogicalTopOffset -= blockDelta;
3131 void RenderBlock::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
3133 // Avoid painting descendants of the root element when stylesheets haven't loaded. This eliminates FOUC.
3134 // It's ok not to draw, because later on, when all the stylesheets do load, styleResolverChanged() on the Document
3135 // will do a full repaint.
3136 if (document()->didLayoutWithPendingStylesheets() && !isRenderView())
3139 if (childrenInline())
3140 m_lineBoxes.paint(this, paintInfo, paintOffset);
3142 PaintPhase newPhase = (paintInfo.phase == PaintPhaseChildOutlines) ? PaintPhaseOutline : paintInfo.phase;
3143 newPhase = (newPhase == PaintPhaseChildBlockBackgrounds) ? PaintPhaseChildBlockBackground : newPhase;
3145 // We don't paint our own background, but we do let the kids paint their backgrounds.
3146 PaintInfo paintInfoForChild(paintInfo);
3147 paintInfoForChild.phase = newPhase;
3148 paintInfoForChild.updateSubtreePaintRootForChildren(this);
3150 // FIXME: Paint-time pagination is obsolete and is now only used by embedded WebViews inside AppKit
3151 // NSViews. Do not add any more code for this.
3152 bool usePrintRect = !view()->printRect().isEmpty();
3153 paintChildren(paintInfo, paintOffset, paintInfoForChild, usePrintRect);
3157 void RenderBlock::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& paintInfoForChild, bool usePrintRect)
3159 for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
3160 if (!paintChild(child, paintInfo, paintOffset, paintInfoForChild, usePrintRect))
3165 bool RenderBlock::paintChild(RenderBox* child, PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& paintInfoForChild, bool usePrintRect)
3167 // Check for page-break-before: always, and if it's set, break and bail.
3168 bool checkBeforeAlways = !childrenInline() && (usePrintRect && child->style()->pageBreakBefore() == PBALWAYS);
3169 LayoutUnit absoluteChildY = paintOffset.y() + child->y();
3170 if (checkBeforeAlways
3171 && absoluteChildY > paintInfo.rect.y()
3172 && absoluteChildY < paintInfo.rect.maxY()) {
3173 view()->setBestTruncatedAt(absoluteChildY, this, true);
3177 RenderView* renderView = view();
3178 if (!child->isFloating() && child->isReplaced() && usePrintRect && child->height() <= renderView->printRect().height()) {
3179 // Paginate block-level replaced elements.
3180 if (absoluteChildY + child->height() > renderView->printRect().maxY()) {
3181 if (absoluteChildY < renderView->truncatedAt())
3182 renderView->setBestTruncatedAt(absoluteChildY, child);
3183 // If we were able to truncate, don't paint.
3184 if (absoluteChildY >= renderView->truncatedAt())
3189 LayoutPoint childPoint = flipForWritingModeForChild(child, paintOffset);
3190 if (!child->hasSelfPaintingLayer() && !child->isFloating())
3191 child->paint(paintInfoForChild, childPoint);
3193 // Check for page-break-after: always, and if it's set, break and bail.
3194 bool checkAfterAlways = !childrenInline() && (usePrintRect && child->style()->pageBreakAfter() == PBALWAYS);
3195 if (checkAfterAlways
3196 && (absoluteChildY + child->height()) > paintInfo.rect.y()
3197 && (absoluteChildY + child->height()) < paintInfo.rect.maxY()) {
3198 view()->setBestTruncatedAt(absoluteChildY + child->height() + max<LayoutUnit>(0, child->collapsedMarginAfter()), this, true);
3205 void RenderBlock::paintCaret(PaintInfo& paintInfo, const LayoutPoint& paintOffset, CaretType type)
3207 // Paint the caret if the FrameSelection says so or if caret browsing is enabled
3208 bool caretBrowsing = frame()->settings() && frame()->settings()->caretBrowsingEnabled();
3209 RenderObject* caretPainter;
3210 bool isContentEditable;
3211 if (type == CursorCaret) {
3212 caretPainter = frame()->selection()->caretRenderer();
3213 isContentEditable = frame()->selection()->rendererIsEditable();
3215 caretPainter = frame()->page()->dragCaretController()->caretRenderer();
3216 isContentEditable = frame()->page()->dragCaretController()->isContentEditable();
3219 if (caretPainter == this && (isContentEditable || caretBrowsing)) {
3220 if (type == CursorCaret)
3221 frame()->selection()->paintCaret(paintInfo.context, paintOffset, paintInfo.rect);
3223 frame()->page()->dragCaretController()->paintDragCaret(frame(), paintInfo.context, paintOffset, paintInfo.rect);
3227 void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
3229 PaintPhase paintPhase = paintInfo.phase;
3231 // 1. paint background, borders etc
3232 if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && style()->visibility() == VISIBLE) {
3233 if (hasBoxDecorations())
3234 paintBoxDecorations(paintInfo, paintOffset);
3235 if (hasColumns() && !paintInfo.paintRootBackgroundOnly())
3236 paintColumnRules(paintInfo, paintOffset);
3239 if (paintPhase == PaintPhaseMask && style()->visibility() == VISIBLE) {
3240 paintMask(paintInfo, paintOffset);
3244 // We're done. We don't bother painting any children.
3245 if (paintPhase == PaintPhaseBlockBackground || paintInfo.paintRootBackgroundOnly())
3248 // Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div).
3249 LayoutPoint scrolledOffset = paintOffset;
3250 if (hasOverflowClip())
3251 scrolledOffset.move(-scrolledContentOffset());
3253 // 2. paint contents
3254 if (paintPhase != PaintPhaseSelfOutline) {
3256 paintColumnContents(paintInfo, scrolledOffset);
3258 paintContents(paintInfo, scrolledOffset);
3261 // 3. paint selection
3262 // FIXME: Make this work with multi column layouts. For now don't fill gaps.
3263 bool isPrinting = document()->printing();
3264 if (!isPrinting && !hasColumns())
3265 paintSelection(paintInfo, scrolledOffset); // Fill in gaps in selection on lines and between blocks.
3268 if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip) {
3270 paintColumnContents(paintInfo, scrolledOffset, true);
3272 paintFloats(paintInfo, scrolledOffset, paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip);
3275 // 5. paint outline.
3276 if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style()->visibility() == VISIBLE)
3277 paintOutline(paintInfo, LayoutRect(paintOffset, size()));
3279 // 6. paint continuation outlines.
3280 if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)) {
3281 RenderInline* inlineCont = inlineElementContinuation();
3282 if (inlineCont && inlineCont->hasOutline() && inlineCont->style()->visibility() == VISIBLE) {
3283 RenderInline* inlineRenderer = toRenderInline(inlineCont->node()->renderer());
3284 RenderBlock* cb = containingBlock();
3286 bool inlineEnclosedInSelfPaintingLayer = false;
3287 for (RenderBoxModelObject* box = inlineRenderer; box != cb; box = box->parent()->enclosingBoxModelObject()) {
3288 if (box->hasSelfPaintingLayer()) {
3289 inlineEnclosedInSelfPaintingLayer = true;
3294 // Do not add continuations for outline painting by our containing block if we are a relative positioned
3295 // anonymous block (i.e. have our own layer), paint them straightaway instead. This is because a block depends on renderers in its continuation table being
3296 // in the same layer.
3297 if (!inlineEnclosedInSelfPaintingLayer && !hasLayer())
3298 cb->addContinuationWithOutline(inlineRenderer);
3299 else if (!inlineRenderer->firstLineBox() || (!inlineEnclosedInSelfPaintingLayer && hasLayer()))
3300 inlineRenderer->paintOutline(paintInfo, paintOffset - locationOffset() + inlineRenderer->containingBlock()->location());
3302 paintContinuationOutlines(paintInfo, paintOffset);
3306 // If the caret's node's render object's containing block is this block, and the paint action is PaintPhaseForeground,
3307 // then paint the caret.
3308 if (paintPhase == PaintPhaseForeground) {
3309 paintCaret(paintInfo, paintOffset, CursorCaret);
3310 paintCaret(paintInfo, paintOffset, DragCaret);
3314 LayoutPoint RenderBlock::flipFloatForWritingModeForChild(const FloatingObject* child, const LayoutPoint& point) const
3316 if (!style()->isFlippedBlocksWritingMode())
3319 // This is similar to RenderBox::flipForWritingModeForChild. We have to subtract out our left/top offsets twice, since
3320 // it's going to get added back in. We hide this complication here so that the calling code looks normal for the unflipped
3322 if (isHorizontalWritingMode())
3323 return LayoutPoint(point.x(), point.y() + height() - child->renderer()->height() - 2 * yPositionForFloatIncludingMargin(child));
3324 return LayoutPoint(point.x() + width() - child->renderer()->width() - 2 * xPositionForFloatIncludingMargin(child), point.y());
3327 void RenderBlock::paintFloats(PaintInfo& paintInfo, const LayoutPoint& paintOffset, bool preservePhase)
3329 if (!m_floatingObjects)
3332 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3333 FloatingObjectSetIterator end = floatingObjectSet.end();
3334 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
3335 FloatingObject* r = *it;
3336 // Only paint the object if our m_shouldPaint flag is set.
3337 if (r->shouldPaint() && !r->m_renderer->hasSelfPaintingLayer()) {
3338 PaintInfo currentPaintInfo(paintInfo);
3339 currentPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
3340 LayoutPoint childPoint = flipFloatForWritingModeForChild(r, LayoutPoint(paintOffset.x() + xPositionForFloatIncludingMargin(r) - r->m_renderer->x(), paintOffset.y() + yPositionForFloatIncludingMargin(r) - r->m_renderer->y()));
3341 r->m_renderer->paint(currentPaintInfo, childPoint);
3342 if (!preservePhase) {
3343 currentPaintInfo.phase = PaintPhaseChildBlockBackgrounds;
3344 r->m_renderer->paint(currentPaintInfo, childPoint);
3345 currentPaintInfo.phase = PaintPhaseFloat;
3346 r->m_renderer->paint(currentPaintInfo, childPoint);
3347 currentPaintInfo.phase = PaintPhaseForeground;
3348 r->m_renderer->paint(currentPaintInfo, childPoint);
3349 currentPaintInfo.phase = PaintPhaseOutline;
3350 r->m_renderer->paint(currentPaintInfo, childPoint);
3356 RenderInline* RenderBlock::inlineElementContinuation() const
3358 RenderBoxModelObject* continuation = this->continuation();
3359 return continuation && continuation->isInline() ? toRenderInline(continuation) : 0;
3362 RenderBlock* RenderBlock::blockElementContinuation() const
3364 RenderBoxModelObject* currentContinuation = continuation();
3365 if (!currentContinuation || currentContinuation->isInline())
3367 RenderBlock* nextContinuation = toRenderBlock(currentContinuation);
3368 if (nextContinuation->isAnonymousBlock())
3369 return nextContinuation->blockElementContinuation();
3370 return nextContinuation;
3373 static ContinuationOutlineTableMap* continuationOutlineTable()
3375 DEFINE_STATIC_LOCAL(ContinuationOutlineTableMap, table, ());
3379 void RenderBlock::addContinuationWithOutline(RenderInline* flow)
3381 // We can't make this work if the inline is in a layer. We'll just rely on the broken
3383 ASSERT(!flow->layer() && !flow->isInlineElementContinuation());
3385 ContinuationOutlineTableMap* table = continuationOutlineTable();
3386 ListHashSet<RenderInline*>* continuations = table->get(this);
3387 if (!continuations) {
3388 continuations = new ListHashSet<RenderInline*>;
3389 table->set(this, adoptPtr(continuations));
3392 continuations->add(flow);
3395 bool RenderBlock::paintsContinuationOutline(RenderInline* flow)
3397 ContinuationOutlineTableMap* table = continuationOutlineTable();
3398 if (table->isEmpty())
3401 ListHashSet<RenderInline*>* continuations = table->get(this);
3405 return continuations->contains(flow);
3408 void RenderBlock::paintContinuationOutlines(PaintInfo& info, const LayoutPoint& paintOffset)
3410 ContinuationOutlineTableMap* table = continuationOutlineTable();
3411 if (table->isEmpty())
3414 OwnPtr<ListHashSet<RenderInline*> > continuations = table->take(this);
3418 LayoutPoint accumulatedPaintOffset = paintOffset;
3419 // Paint each continuation outline.
3420 ListHashSet<RenderInline*>::iterator end = continuations->end();
3421 for (ListHashSet<RenderInline*>::iterator it = continuations->begin(); it != end; ++it) {
3422 // Need to add in the coordinates of the intervening blocks.
3423 RenderInline* flow = *it;
3424 RenderBlock* block = flow->containingBlock();
3425 for ( ; block && block != this; block = block->containingBlock())
3426 accumulatedPaintOffset.moveBy(block->location());
3428 flow->paintOutline(info, accumulatedPaintOffset);
3432 bool RenderBlock::shouldPaintSelectionGaps() const
3434 return selectionState() != SelectionNone && style()->visibility() == VISIBLE && isSelectionRoot();
3437 bool RenderBlock::isSelectionRoot() const
3439 if (isPseudoElement())
3441 ASSERT(node() || isAnonymous());
3443 // FIXME: Eventually tables should have to learn how to fill gaps between cells, at least in simple non-spanning cases.
3447 if (isBody() || isRoot() || hasOverflowClip()
3448 || isPositioned() || isFloating()
3449 || isTableCell() || isInlineBlockOrInlineTable()
3450 || hasTransform() || hasReflection() || hasMask() || isWritingModeRoot()
3451 || isRenderFlowThread())
3454 if (view() && view()->selectionStart()) {
3455 Node* startElement = view()->selectionStart()->node();
3456 if (startElement && startElement->rootEditableElement() == node())
3463 GapRects RenderBlock::selectionGapRectsForRepaint(const RenderLayerModelObject* repaintContainer)
3465 ASSERT(!needsLayout());
3467 if (!shouldPaintSelectionGaps())
3470 TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint());
3471 mapLocalToContainer(repaintContainer, transformState, ApplyContainerFlip | UseTransforms);
3472 LayoutPoint offsetFromRepaintContainer = roundedLayoutPoint(transformState.mappedPoint());
3474 if (hasOverflowClip())
3475 offsetFromRepaintContainer -= scrolledContentOffset();
3477 LogicalSelectionOffsetCaches cache(this);
3478 LayoutUnit lastTop = 0;
3479 LayoutUnit lastLeft = logicalLeftSelectionOffset(this, lastTop, cache);
3480 LayoutUnit lastRight = logicalRightSelectionOffset(this, lastTop, cache);
3482 return selectionGaps(this, offsetFromRepaintContainer, IntSize(), lastTop, lastLeft, lastRight, cache);
3485 void RenderBlock::paintSelection(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
3487 if (shouldPaintSelectionGaps() && paintInfo.phase == PaintPhaseForeground) {
3488 LogicalSelectionOffsetCaches cache(this);
3489 LayoutUnit lastTop = 0;
3490 LayoutUnit lastLeft = logicalLeftSelectionOffset(this, lastTop, cache);
3491 LayoutUnit lastRight = logicalRightSelectionOffset(this, lastTop, cache);
3492 GraphicsContextStateSaver stateSaver(*paintInfo.context);
3494 LayoutRect gapRectsBounds = selectionGaps(this, paintOffset, LayoutSize(), lastTop, lastLeft, lastRight, cache, &paintInfo);
3495 if (!gapRectsBounds.isEmpty()) {
3496 if (RenderLayer* layer = enclosingLayer()) {
3497 gapRectsBounds.moveBy(-paintOffset);
3499 LayoutRect localBounds(gapRectsBounds);
3500 flipForWritingMode(localBounds);
3501 gapRectsBounds = localToContainerQuad(FloatRect(localBounds), layer->renderer()).enclosingBoundingBox();
3502 if (layer->renderer()->hasOverflowClip())
3503 gapRectsBounds.move(layer->renderBox()->scrolledContentOffset());
3505 layer->addBlockSelectionGapsBounds(gapRectsBounds);
3511 static void clipOutPositionedObjects(const PaintInfo* paintInfo, const LayoutPoint& offset, TrackedRendererListHashSet* positionedObjects)
3513 if (!positionedObjects)
3516 TrackedRendererListHashSet::const_iterator end = positionedObjects->end();
3517 for (TrackedRendererListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
3519 paintInfo->context->clipOut(IntRect(offset.x() + r->x(), offset.y() + r->y(), r->width(), r->height()));
3523 static LayoutUnit blockDirectionOffset(RenderBlock* rootBlock, const LayoutSize& offsetFromRootBlock)
3525 return rootBlock->isHorizontalWritingMode() ? offsetFromRootBlock.height() : offsetFromRootBlock.width();
3528 static LayoutUnit inlineDirectionOffset(RenderBlock* rootBlock, const LayoutSize& offsetFromRootBlock)
3530 return rootBlock->isHorizontalWritingMode() ? offsetFromRootBlock.width() : offsetFromRootBlock.height();
3533 LayoutRect RenderBlock::logicalRectToPhysicalRect(const LayoutPoint& rootBlockPhysicalPosition, const LayoutRect& logicalRect)
3536 if (isHorizontalWritingMode())
3537 result = logicalRect;
3539 result = LayoutRect(logicalRect.y(), logicalRect.x(), logicalRect.height(), logicalRect.width());
3540 flipForWritingMode(result);
3541 result.moveBy(rootBlockPhysicalPosition);
3545 GapRects RenderBlock::selectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
3546 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
3548 // IMPORTANT: Callers of this method that intend for painting to happen need to do a save/restore.
3549 // Clip out floating and positioned objects when painting selection gaps.
3551 // Note that we don't clip out overflow for positioned objects. We just stick to the border box.
3552 LayoutRect flippedBlockRect(offsetFromRootBlock.width(), offsetFromRootBlock.height(), width(), height());
3553 rootBlock->flipForWritingMode(flippedBlockRect);
3554 flippedBlockRect.moveBy(rootBlockPhysicalPosition);
3555 clipOutPositionedObjects(paintInfo, flippedBlockRect.location(), positionedObjects());
3556 if (isBody() || isRoot()) // The <body> must make sure to examine its containingBlock's positioned objects.
3557 for (RenderBlock* cb = containingBlock(); cb && !cb->isRenderView(); cb = cb->containingBlock())
3558 clipOutPositionedObjects(paintInfo, LayoutPoint(cb->x(), cb->y()), cb->positionedObjects()); // FIXME: Not right for flipped writing modes.
3559 if (m_floatingObjects) {
3560 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3561 FloatingObjectSetIterator end = floatingObjectSet.end();
3562 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
3563 FloatingObject* r = *it;
3564 LayoutRect floatBox(offsetFromRootBlock.width() + xPositionForFloatIncludingMargin(r),
3565 offsetFromRootBlock.height() + yPositionForFloatIncludingMargin(r),
3566 r->m_renderer->width(), r->m_renderer->height());
3567 rootBlock->flipForWritingMode(floatBox);
3568 floatBox.move(rootBlockPhysicalPosition.x(), rootBlockPhysicalPosition.y());
3569 paintInfo->context->clipOut(pixelSnappedIntRect(floatBox));
3574 // FIXME: overflow: auto/scroll regions need more math here, since painting in the border box is different from painting in the padding box (one is scrolled, the other is
3577 if (!isBlockFlow()) // FIXME: Make multi-column selection gap filling work someday.
3580 if (hasColumns() || hasTransform() || style()->columnSpan()) {
3581 // FIXME: We should learn how to gap fill multiple columns and transforms eventually.
3582 lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalHeight();
3583 lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight(), cache);
3584 lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight(), cache);
3588 if (childrenInline())
3589 result = inlineSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, cache, paintInfo);
3591 result = blockSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, cache, paintInfo);
3593 // Go ahead and fill the vertical gap all the way to the bottom of our block if the selection extends past our block.
3594 if (rootBlock == this && (selectionState() != SelectionBoth && selectionState() != SelectionEnd)) {
3595 result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock,
3596 lastLogicalTop, lastLogicalLeft, lastLogicalRight, logicalHeight(), cache, paintInfo));
3602 GapRects RenderBlock::inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
3603 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
3607 bool containsStart = selectionState() == SelectionStart || selectionState() == SelectionBoth;
3609 if (!firstLineBox()) {
3610 if (containsStart) {
3611 // Go ahead and update our lastLogicalTop to be the bottom of the block. <hr>s or empty blocks with height can trip this
3613 lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalHeight();
3614 lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight(), cache);
3615 lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight(), cache);
3620 RootInlineBox* lastSelectedLine = 0;
3621 RootInlineBox* curr;
3622 for (curr = firstRootBox(); curr && !curr->hasSelectedChildren(); curr = curr->nextRootBox()) { }
3624 // Now paint the gaps for the lines.
3625 for (; curr && curr->hasSelectedChildren(); curr = curr->nextRootBox()) {
3626 LayoutUnit selTop = curr->selectionTopAdjustedForPrecedingBlock();
3627 LayoutUnit selHeight = curr->selectionHeightAdjustedForPrecedingBlock();
3629 if (!containsStart && !lastSelectedLine &&
3630 selectionState() != SelectionStart && selectionState() != SelectionBoth)
3631 result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, selTop, cache, paintInfo));
3633 LayoutRect logicalRect(curr->logicalLeft(), selTop, curr->logicalWidth(), selTop + selHeight);
3634 logicalRect.move(isHorizontalWritingMode() ? offsetFromRootBlock : offsetFromRootBlock.transposedSize());
3635 LayoutRect physicalRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, logicalRect);
3636 if (!paintInfo || (isHorizontalWritingMode() && physicalRect.y() < paintInfo->rect.maxY() && physicalRect.maxY() > paintInfo->rect.y())
3637 || (!isHorizontalWritingMode() && physicalRect.x() < paintInfo->rect.maxX() && physicalRect.maxX() > paintInfo->rect.x()))
3638 result.unite(curr->lineSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, selTop, selHeight, cache, paintInfo));
3640 lastSelectedLine = curr;
3643 if (containsStart && !lastSelectedLine)
3644 // VisibleSelection must start just after our last line.
3645 lastSelectedLine = lastRootBox();
3647 if (lastSelectedLine && selectionState() != SelectionEnd && selectionState() != SelectionBoth) {
3648 // Go ahead and update our lastY to be the bottom of the last selected line.
3649 lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + lastSelectedLine->selectionBottom();
3650 lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, lastSelectedLine->selectionBottom(), cache);
3651 lastLogicalRight = logicalRightSelectionOffset(rootBlock, lastSelectedLine->selectionBottom(), cache);
3656 GapRects RenderBlock::blockSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
3657 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
3661 // Go ahead and jump right to the first block child that contains some selected objects.
3663 for (curr = firstChildBox(); curr && curr->selectionState() == SelectionNone; curr = curr->nextSiblingBox()) { }
3668 LogicalSelectionOffsetCaches childCache(this, cache);
3670 for (bool sawSelectionEnd = false; curr && !sawSelectionEnd; curr = curr->nextSiblingBox()) {
3671 SelectionState childState = curr->selectionState();
3672 if (childState == SelectionBoth || childState == SelectionEnd)
3673 sawSelectionEnd = true;
3675 if (curr->isFloatingOrOutOfFlowPositioned())
3676 continue; // We must be a normal flow object in order to even be considered.
3678 if (curr->hasPaintOffset() && curr->hasLayer()) {
3679 // If the relposition offset is anything other than 0, then treat this just like an absolute positioned element.
3680 // Just disregard it completely.
3681 LayoutSize relOffset = curr->layer()->paintOffset();
3682 if (relOffset.width() || relOffset.height())
3686 bool paintsOwnSelection = curr->shouldPaintSelectionGaps() || curr->isTable(); // FIXME: Eventually we won't special-case table like this.
3687 bool fillBlockGaps = paintsOwnSelection || (curr->canBeSelectionLeaf() && childState != SelectionNone);
3688 if (fillBlockGaps) {
3689 // We need to fill the vertical gap above this object.
3690 if (childState == SelectionEnd || childState == SelectionInside) {
3691 // Fill the gap above the object.
3692 result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock,
3693 lastLogicalTop, lastLogicalLeft, lastLogicalRight, curr->logicalTop(), cache, paintInfo));
3696 // Only fill side gaps for objects that paint their own selection if we know for sure the selection is going to extend all the way *past*
3697 // our object. We know this if the selection did not end inside our object.
3698 if (paintsOwnSelection && (childState == SelectionStart || sawSelectionEnd))
3699 childState = SelectionNone;
3701 // Fill side gaps on this object based off its state.
3702 bool leftGap, rightGap;
3703 getSelectionGapInfo(childState, leftGap, rightGap);
3706 result.uniteLeft(logicalLeftSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalLeft(), curr->logicalTop(), curr->logicalHeight(), cache, paintInfo));
3708 result.uniteRight(logicalRightSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalRight(), curr->logicalTop(), curr->logicalHeight(), cache, paintInfo));
3710 // Update lastLogicalTop to be just underneath the object. lastLogicalLeft and lastLogicalRight extend as far as
3711 // they can without bumping into floating or positioned objects. Ideally they will go right up
3712 // to the border of the root selection block.
3713 lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + curr->logicalBottom();
3714 lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, curr->logicalBottom(), cache);
3715 lastLogicalRight = logicalRightSelectionOffset(rootBlock, curr->logicalBottom(), cache);
3716 } else if (childState != SelectionNone) {
3717 // We must be a block that has some selected object inside it. Go ahead and recur.
3718 result.unite(toRenderBlock(curr)->selectionGaps(rootBlock, rootBlockPhysicalPosition, LayoutSize(offsetFromRootBlock.width() + curr->x(), offsetFromRootBlock.height() + curr->y()),
3719 lastLogicalTop, lastLogicalLeft, lastLogicalRight, childCache, paintInfo));
3725 LayoutRect RenderBlock::blockSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
3726 LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const LogicalSelectionOffsetCaches& cache, const PaintInfo* paintInfo)
3728 LayoutUnit logicalTop = lastLogicalTop;
3729 LayoutUnit logicalHeight = blockDirectionOffset(rootBlock, offsetFro