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 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 "ColumnInfo.h"
30 #include "FloatQuad.h"
32 #include "FrameSelection.h"
33 #include "FrameView.h"
34 #include "GraphicsContext.h"
35 #include "HTMLFormElement.h"
36 #include "HTMLNames.h"
37 #include "HitTestResult.h"
38 #include "InlineIterator.h"
39 #include "InlineTextBox.h"
40 #include "LayoutRepainter.h"
42 #include "PaintInfo.h"
43 #include "RenderBoxRegionInfo.h"
44 #include "RenderCombineText.h"
45 #include "RenderDeprecatedFlexibleBox.h"
46 #include "RenderFlowThread.h"
47 #include "RenderImage.h"
48 #include "RenderInline.h"
49 #include "RenderLayer.h"
50 #include "RenderMarquee.h"
51 #include "RenderRegion.h"
52 #include "RenderReplica.h"
53 #include "RenderTableCell.h"
54 #include "RenderTextFragment.h"
55 #include "RenderTheme.h"
56 #include "RenderView.h"
58 #include "SVGTextRunRenderingContext.h"
59 #include "TransformState.h"
60 #include <wtf/StdLibExtras.h>
64 using namespace Unicode;
68 using namespace HTMLNames;
70 typedef WTF::HashMap<const RenderBox*, ColumnInfo*> ColumnInfoMap;
71 static ColumnInfoMap* gColumnInfoMap = 0;
73 typedef WTF::HashMap<const RenderBlock*, HashSet<RenderBox*>*> PercentHeightDescendantsMap;
74 static PercentHeightDescendantsMap* gPercentHeightDescendantsMap = 0;
76 typedef WTF::HashMap<const RenderBox*, HashSet<RenderBlock*>*> PercentHeightContainerMap;
77 static PercentHeightContainerMap* gPercentHeightContainerMap = 0;
79 typedef WTF::HashMap<RenderBlock*, ListHashSet<RenderInline*>*> ContinuationOutlineTableMap;
81 typedef WTF::HashSet<RenderBlock*> DelayedUpdateScrollInfoSet;
82 static int gDelayUpdateScrollInfo = 0;
83 static DelayedUpdateScrollInfoSet* gDelayedUpdateScrollInfoSet = 0;
85 bool RenderBlock::s_canPropagateFloatIntoSibling = false;
87 // Our MarginInfo state used when laying out block children.
88 RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, LayoutUnit beforeBorderPadding, LayoutUnit afterBorderPadding)
89 : m_atBeforeSideOfBlock(true)
90 , m_atAfterSideOfBlock(false)
91 , m_marginBeforeQuirk(false)
92 , m_marginAfterQuirk(false)
93 , m_determinedMarginBeforeQuirk(false)
95 // Whether or not we can collapse our own margins with our children. We don't do this
96 // if we had any border/padding (obviously), if we're the root or HTML elements, or if
97 // we're positioned, floating, a table cell.
98 m_canCollapseWithChildren = !block->isRenderView() && !block->isRoot() && !block->isPositioned()
99 && !block->isFloating() && !block->isTableCell() && !block->hasOverflowClip() && !block->isInlineBlockOrInlineTable()
100 && !block->isWritingModeRoot() && block->style()->hasAutoColumnCount() && block->style()->hasAutoColumnWidth()
101 && !block->style()->columnSpan();
103 m_canCollapseMarginBeforeWithChildren = m_canCollapseWithChildren && (beforeBorderPadding == 0) && block->style()->marginBeforeCollapse() != MSEPARATE;
105 // If any height other than auto is specified in CSS, then we don't collapse our bottom
106 // margins with our children's margins. To do otherwise would be to risk odd visual
107 // effects when the children overflow out of the parent block and yet still collapse
108 // with it. We also don't collapse if we have any bottom border/padding.
109 m_canCollapseMarginAfterWithChildren = m_canCollapseWithChildren && (afterBorderPadding == 0) &&
110 (block->style()->logicalHeight().isAuto() && block->style()->logicalHeight().value() == 0) && block->style()->marginAfterCollapse() != MSEPARATE;
112 m_quirkContainer = block->isTableCell() || block->isBody() || block->style()->marginBeforeCollapse() == MDISCARD ||
113 block->style()->marginAfterCollapse() == MDISCARD;
115 m_positiveMargin = m_canCollapseMarginBeforeWithChildren ? block->maxPositiveMarginBefore() : 0;
116 m_negativeMargin = m_canCollapseMarginBeforeWithChildren ? block->maxNegativeMarginBefore() : 0;
119 // -------------------------------------------------------------------------------------------------------
121 RenderBlock::RenderBlock(Node* node)
124 , m_beingDestroyed(false)
125 , m_hasPositionedFloats(false)
127 setChildrenInline(true);
130 RenderBlock::~RenderBlock()
132 if (m_floatingObjects)
133 deleteAllValues(m_floatingObjects->set());
136 delete gColumnInfoMap->take(this);
138 if (gPercentHeightDescendantsMap) {
139 if (HashSet<RenderBox*>* descendantSet = gPercentHeightDescendantsMap->take(this)) {
140 HashSet<RenderBox*>::iterator end = descendantSet->end();
141 for (HashSet<RenderBox*>::iterator descendant = descendantSet->begin(); descendant != end; ++descendant) {
142 HashSet<RenderBlock*>* containerSet = gPercentHeightContainerMap->get(*descendant);
143 ASSERT(containerSet);
146 ASSERT(containerSet->contains(this));
147 containerSet->remove(this);
148 if (containerSet->isEmpty()) {
149 gPercentHeightContainerMap->remove(*descendant);
153 delete descendantSet;
158 void RenderBlock::willBeDestroyed()
160 // Mark as being destroyed to avoid trouble with merges in removeChild().
161 m_beingDestroyed = true;
163 // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will
164 // properly dirty line boxes that they are removed from. Effects that do :before/:after only on hover could crash otherwise.
165 children()->destroyLeftoverChildren();
167 // Destroy our continuation before anything other than anonymous children.
168 // The reason we don't destroy it before anonymous children is that they may
169 // have continuations of their own that are anonymous children of our continuation.
170 RenderBoxModelObject* continuation = this->continuation();
172 continuation->destroy();
176 if (!documentBeingDestroyed()) {
177 if (firstLineBox()) {
178 // We can't wait for RenderBox::destroy to clear the selection,
179 // because by then we will have nuked the line boxes.
180 // FIXME: The FrameSelection should be responsible for this when it
181 // is notified of DOM mutations.
182 if (isSelectionBorder())
183 view()->clearSelection();
185 // If we are an anonymous block, then our line boxes might have children
186 // that will outlast this block. In the non-anonymous block case those
187 // children will be destroyed by the time we return from this function.
188 if (isAnonymousBlock()) {
189 for (InlineFlowBox* box = firstLineBox(); box; box = box->nextLineBox()) {
190 while (InlineBox* childBox = box->firstChild())
195 parent()->dirtyLinesFromChangedChild(this);
198 m_lineBoxes.deleteLineBoxes(renderArena());
200 if (UNLIKELY(gDelayedUpdateScrollInfoSet != 0))
201 gDelayedUpdateScrollInfoSet->remove(this);
203 RenderBox::willBeDestroyed();
206 void RenderBlock::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
208 s_canPropagateFloatIntoSibling = style() ? !isFloatingOrPositioned() && !avoidsFloats() : false;
210 setReplaced(newStyle->isDisplayInlineType());
212 if (style() && parent() && diff == StyleDifferenceLayout && style()->position() != newStyle->position()) {
213 if (newStyle->position() == StaticPosition)
214 // Clear our positioned objects list. Our absolutely positioned descendants will be
215 // inserted into our containing block's positioned objects list during layout.
216 removePositionedObjects(0);
217 else if (style()->position() == StaticPosition) {
218 // Remove our absolutely positioned descendants from their current containing block.
219 // They will be inserted into our positioned objects list during layout.
220 RenderObject* cb = parent();
221 while (cb && (cb->style()->position() == StaticPosition || (cb->isInline() && !cb->isReplaced())) && !cb->isRenderView()) {
222 if (cb->style()->position() == RelativePosition && cb->isInline() && !cb->isReplaced()) {
223 cb = cb->containingBlock();
229 if (cb->isRenderBlock())
230 toRenderBlock(cb)->removePositionedObjects(this);
233 if (containsFloats() && !isFloating() && !isPositioned() && (newStyle->position() == AbsolutePosition || newStyle->position() == FixedPosition))
234 markAllDescendantsWithFloatsForLayout();
237 RenderBox::styleWillChange(diff, newStyle);
240 void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
242 RenderBox::styleDidChange(diff, oldStyle);
244 if (!isAnonymousBlock()) {
245 // Ensure that all of our continuation blocks pick up the new style.
246 for (RenderBlock* currCont = blockElementContinuation(); currCont; currCont = currCont->blockElementContinuation()) {
247 RenderBoxModelObject* nextCont = currCont->continuation();
248 currCont->setContinuation(0);
249 currCont->setStyle(style());
250 currCont->setContinuation(nextCont);
254 propagateStyleToAnonymousChildren(true);
257 // Update pseudos for :before and :after now.
258 if (!isAnonymous() && document()->usesBeforeAfterRules() && canHaveChildren()) {
259 updateBeforeAfterContent(BEFORE);
260 updateBeforeAfterContent(AFTER);
263 // After our style changed, if we lose our ability to propagate floats into next sibling
264 // blocks, then we need to find the top most parent containing that overhanging float and
265 // then mark its descendants with floats for layout and clear all floats from its next
266 // sibling blocks that exist in our floating objects list. See bug 56299 and 62875.
267 bool canPropagateFloatIntoSibling = !isFloatingOrPositioned() && !avoidsFloats();
268 if (diff == StyleDifferenceLayout && s_canPropagateFloatIntoSibling && !canPropagateFloatIntoSibling && hasOverhangingFloats()) {
269 RenderBlock* parentBlock = this;
270 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
271 FloatingObjectSetIterator end = floatingObjectSet.end();
273 for (RenderObject* curr = parent(); curr && !curr->isRenderView(); curr = curr->parent()) {
274 if (curr->isRenderBlock()) {
275 RenderBlock* currBlock = toRenderBlock(curr);
277 if (currBlock->hasOverhangingFloats()) {
278 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
279 RenderBox* renderer = (*it)->renderer();
280 if (currBlock->hasOverhangingFloat(renderer)) {
281 parentBlock = currBlock;
289 parentBlock->markAllDescendantsWithFloatsForLayout();
290 parentBlock->markSiblingsWithFloatsForLayout();
294 void RenderBlock::updateBeforeAfterContent(PseudoId pseudoId)
296 // If this is an anonymous wrapper, then the parent applies its own pseudo-element style to it.
297 if (parent() && parent()->createsAnonymousWrapper())
299 return children()->updateBeforeAfterContent(this, pseudoId);
302 RenderBlock* RenderBlock::continuationBefore(RenderObject* beforeChild)
304 if (beforeChild && beforeChild->parent() == this)
307 RenderBlock* curr = toRenderBlock(continuation());
308 RenderBlock* nextToLast = this;
309 RenderBlock* last = this;
311 if (beforeChild && beforeChild->parent() == curr) {
312 if (curr->firstChild() == beforeChild)
319 curr = toRenderBlock(curr->continuation());
322 if (!beforeChild && !last->firstChild())
327 void RenderBlock::addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild)
329 RenderBlock* flow = continuationBefore(beforeChild);
330 ASSERT(!beforeChild || beforeChild->parent()->isAnonymousColumnSpanBlock() || beforeChild->parent()->isRenderBlock());
331 RenderBoxModelObject* beforeChildParent = 0;
333 beforeChildParent = toRenderBoxModelObject(beforeChild->parent());
335 RenderBoxModelObject* cont = flow->continuation();
337 beforeChildParent = cont;
339 beforeChildParent = flow;
342 if (newChild->isFloatingOrPositioned())
343 return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
345 // A continuation always consists of two potential candidates: a block or an anonymous
346 // column span box holding column span children.
347 bool childIsNormal = newChild->isInline() || !newChild->style()->columnSpan();
348 bool bcpIsNormal = beforeChildParent->isInline() || !beforeChildParent->style()->columnSpan();
349 bool flowIsNormal = flow->isInline() || !flow->style()->columnSpan();
351 if (flow == beforeChildParent)
352 return flow->addChildIgnoringContinuation(newChild, beforeChild);
354 // The goal here is to match up if we can, so that we can coalesce and create the
355 // minimal # of continuations needed for the inline.
356 if (childIsNormal == bcpIsNormal)
357 return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
358 if (flowIsNormal == childIsNormal)
359 return flow->addChildIgnoringContinuation(newChild, 0); // Just treat like an append.
360 return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
364 void RenderBlock::addChildToAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild)
366 ASSERT(!continuation()); // We don't yet support column spans that aren't immediate children of the multi-column block.
368 // The goal is to locate a suitable box in which to place our child.
369 RenderBlock* beforeChildParent = toRenderBlock(beforeChild && beforeChild->parent()->isRenderBlock() ? beforeChild->parent() : lastChild());
371 // If the new child is floating or positioned it can just go in that block.
372 if (newChild->isFloatingOrPositioned())
373 return beforeChildParent->addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild);
375 // See if the child can be placed in the box.
376 bool newChildHasColumnSpan = newChild->style()->columnSpan() && !newChild->isInline();
377 bool beforeChildParentHoldsColumnSpans = beforeChildParent->isAnonymousColumnSpanBlock();
379 if (newChildHasColumnSpan == beforeChildParentHoldsColumnSpans)
380 return beforeChildParent->addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild);
383 // Create a new block of the correct type.
384 RenderBlock* newBox = newChildHasColumnSpan ? createAnonymousColumnSpanBlock() : createAnonymousColumnsBlock();
385 children()->appendChildNode(this, newBox);
386 newBox->addChildIgnoringAnonymousColumnBlocks(newChild, 0);
390 RenderObject* immediateChild = beforeChild;
391 bool isPreviousBlockViable = true;
392 while (immediateChild->parent() != this) {
393 if (isPreviousBlockViable)
394 isPreviousBlockViable = !immediateChild->previousSibling();
395 immediateChild = immediateChild->parent();
397 if (isPreviousBlockViable && immediateChild->previousSibling())
398 return toRenderBlock(immediateChild->previousSibling())->addChildIgnoringAnonymousColumnBlocks(newChild, 0); // Treat like an append.
400 // Split our anonymous blocks.
401 RenderObject* newBeforeChild = splitAnonymousBlocksAroundChild(beforeChild);
403 // Create a new anonymous box of the appropriate type.
404 RenderBlock* newBox = newChildHasColumnSpan ? createAnonymousColumnSpanBlock() : createAnonymousColumnsBlock();
405 children()->insertChildNode(this, newBox, newBeforeChild);
406 newBox->addChildIgnoringAnonymousColumnBlocks(newChild, 0);
410 RenderBlock* RenderBlock::containingColumnsBlock(bool allowAnonymousColumnBlock)
412 for (RenderObject* curr = this; curr; curr = curr->parent()) {
413 if (!curr->isRenderBlock() || curr->isFloatingOrPositioned() || curr->isTableCell() || curr->isRoot() || curr->isRenderView() || curr->hasOverflowClip()
414 || curr->isInlineBlockOrInlineTable())
417 RenderBlock* currBlock = toRenderBlock(curr);
418 if (currBlock->style()->specifiesColumns() && (allowAnonymousColumnBlock || !currBlock->isAnonymousColumnsBlock()))
421 if (currBlock->isAnonymousColumnSpanBlock())
427 RenderBlock* RenderBlock::clone() const
429 RenderBlock* cloneBlock;
430 if (isAnonymousBlock())
431 cloneBlock = createAnonymousBlock();
433 cloneBlock = new (renderArena()) RenderBlock(node());
434 cloneBlock->setStyle(style());
436 cloneBlock->setChildrenInline(childrenInline());
440 void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock,
441 RenderBlock* middleBlock,
442 RenderObject* beforeChild, RenderBoxModelObject* oldCont)
444 // Create a clone of this inline.
445 RenderBlock* cloneBlock = clone();
446 if (!isAnonymousBlock())
447 cloneBlock->setContinuation(oldCont);
449 // Now take all of the children from beforeChild to the end and remove
450 // them from |this| and place them in the clone.
451 if (!beforeChild && isAfterContent(lastChild()))
452 beforeChild = lastChild();
453 moveChildrenTo(cloneBlock, beforeChild, 0);
455 // Hook |clone| up as the continuation of the middle block.
456 if (!cloneBlock->isAnonymousBlock())
457 middleBlock->setContinuation(cloneBlock);
459 // We have been reparented and are now under the fromBlock. We need
460 // to walk up our block parent chain until we hit the containing anonymous columns block.
461 // Once we hit the anonymous columns block we're done.
462 RenderBoxModelObject* curr = toRenderBoxModelObject(parent());
463 RenderBoxModelObject* currChild = this;
465 while (curr && curr != fromBlock) {
466 ASSERT(curr->isRenderBlock());
468 RenderBlock* blockCurr = toRenderBlock(curr);
470 // Create a new clone.
471 RenderBlock* cloneChild = cloneBlock;
472 cloneBlock = blockCurr->clone();
474 // Insert our child clone as the first child.
475 cloneBlock->children()->appendChildNode(cloneBlock, cloneChild);
477 // Hook the clone up as a continuation of |curr|. Note we do encounter
478 // anonymous blocks possibly as we walk up the block chain. When we split an
479 // anonymous block, there's no need to do any continuation hookup, since we haven't
480 // actually split a real element.
481 if (!blockCurr->isAnonymousBlock()) {
482 oldCont = blockCurr->continuation();
483 blockCurr->setContinuation(cloneBlock);
484 cloneBlock->setContinuation(oldCont);
487 // Someone may have indirectly caused a <q> to split. When this happens, the :after content
488 // has to move into the inline continuation. Call updateBeforeAfterContent to ensure that the inline's :after
489 // content gets properly destroyed.
490 if (document()->usesBeforeAfterRules())
491 blockCurr->children()->updateBeforeAfterContent(blockCurr, AFTER);
493 // Now we need to take all of the children starting from the first child
494 // *after* currChild and append them all to the clone.
495 RenderObject* afterContent = isAfterContent(cloneBlock->lastChild()) ? cloneBlock->lastChild() : 0;
496 blockCurr->moveChildrenTo(cloneBlock, currChild->nextSibling(), 0, afterContent);
498 // Keep walking up the chain.
500 curr = toRenderBoxModelObject(curr->parent());
503 // Now we are at the columns block level. We need to put the clone into the toBlock.
504 toBlock->children()->appendChildNode(toBlock, cloneBlock);
506 // Now take all the children after currChild and remove them from the fromBlock
507 // and put them in the toBlock.
508 fromBlock->moveChildrenTo(toBlock, currChild->nextSibling(), 0);
511 void RenderBlock::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
512 RenderObject* newChild, RenderBoxModelObject* oldCont)
514 RenderBlock* pre = 0;
515 RenderBlock* block = containingColumnsBlock();
517 // Delete our line boxes before we do the inline split into continuations.
518 block->deleteLineBoxTree();
520 bool madeNewBeforeBlock = false;
521 if (block->isAnonymousColumnsBlock()) {
522 // We can reuse this block and make it the preBlock of the next continuation.
524 pre->removePositionedObjects(0);
525 block = toRenderBlock(block->parent());
527 // No anonymous block available for use. Make one.
528 pre = block->createAnonymousColumnsBlock();
529 pre->setChildrenInline(false);
530 madeNewBeforeBlock = true;
533 RenderBlock* post = block->createAnonymousColumnsBlock();
534 post->setChildrenInline(false);
536 RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling();
537 if (madeNewBeforeBlock)
538 block->children()->insertChildNode(block, pre, boxFirst);
539 block->children()->insertChildNode(block, newBlockBox, boxFirst);
540 block->children()->insertChildNode(block, post, boxFirst);
541 block->setChildrenInline(false);
543 if (madeNewBeforeBlock)
544 block->moveChildrenTo(pre, boxFirst, 0);
546 splitBlocks(pre, post, newBlockBox, beforeChild, oldCont);
548 // We already know the newBlockBox isn't going to contain inline kids, so avoid wasting
549 // time in makeChildrenNonInline by just setting this explicitly up front.
550 newBlockBox->setChildrenInline(false);
552 // We delayed adding the newChild until now so that the |newBlockBox| would be fully
553 // connected, thus allowing newChild access to a renderArena should it need
554 // to wrap itself in additional boxes (e.g., table construction).
555 newBlockBox->addChild(newChild);
557 // Always just do a full layout in order to ensure that line boxes (especially wrappers for images)
558 // get deleted properly. Because objects moves from the pre block into the post block, we want to
559 // make new line boxes instead of leaving the old line boxes around.
560 pre->setNeedsLayoutAndPrefWidthsRecalc();
561 block->setNeedsLayoutAndPrefWidthsRecalc();
562 post->setNeedsLayoutAndPrefWidthsRecalc();
565 RenderObject* RenderBlock::splitAnonymousBlocksAroundChild(RenderObject* beforeChild)
567 while (beforeChild->parent() != this) {
568 RenderBlock* blockToSplit = toRenderBlock(beforeChild->parent());
569 if (blockToSplit->firstChild() != beforeChild) {
570 // We have to split the parentBlock into two blocks.
571 RenderBlock* post = createAnonymousBlockWithSameTypeAs(blockToSplit);
572 post->setChildrenInline(blockToSplit->childrenInline());
573 RenderBlock* parentBlock = toRenderBlock(blockToSplit->parent());
574 parentBlock->children()->insertChildNode(parentBlock, post, blockToSplit->nextSibling());
575 blockToSplit->moveChildrenTo(post, beforeChild, 0, blockToSplit->hasLayer());
576 post->setNeedsLayoutAndPrefWidthsRecalc();
577 blockToSplit->setNeedsLayoutAndPrefWidthsRecalc();
580 beforeChild = blockToSplit;
585 void RenderBlock::makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, RenderBlock* newBlockBox, RenderObject* newChild)
587 RenderBlock* pre = 0;
588 RenderBlock* post = 0;
589 RenderBlock* block = this; // Eventually block will not just be |this|, but will also be a block nested inside |this|. Assign to a variable
590 // so that we don't have to patch all of the rest of the code later on.
592 // Delete the block's line boxes before we do the split.
593 block->deleteLineBoxTree();
595 if (beforeChild && beforeChild->parent() != this)
596 beforeChild = splitAnonymousBlocksAroundChild(beforeChild);
598 if (beforeChild != firstChild()) {
599 pre = block->createAnonymousColumnsBlock();
600 pre->setChildrenInline(block->childrenInline());
604 post = block->createAnonymousColumnsBlock();
605 post->setChildrenInline(block->childrenInline());
608 RenderObject* boxFirst = block->firstChild();
610 block->children()->insertChildNode(block, pre, boxFirst);
611 block->children()->insertChildNode(block, newBlockBox, boxFirst);
613 block->children()->insertChildNode(block, post, boxFirst);
614 block->setChildrenInline(false);
616 // 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).
617 block->moveChildrenTo(pre, boxFirst, beforeChild, true);
618 block->moveChildrenTo(post, beforeChild, 0, true);
620 // We already know the newBlockBox isn't going to contain inline kids, so avoid wasting
621 // time in makeChildrenNonInline by just setting this explicitly up front.
622 newBlockBox->setChildrenInline(false);
624 // We delayed adding the newChild until now so that the |newBlockBox| would be fully
625 // connected, thus allowing newChild access to a renderArena should it need
626 // to wrap itself in additional boxes (e.g., table construction).
627 newBlockBox->addChild(newChild);
629 // Always just do a full layout in order to ensure that line boxes (especially wrappers for images)
630 // get deleted properly. Because objects moved from the pre block into the post block, we want to
631 // make new line boxes instead of leaving the old line boxes around.
633 pre->setNeedsLayoutAndPrefWidthsRecalc();
634 block->setNeedsLayoutAndPrefWidthsRecalc();
636 post->setNeedsLayoutAndPrefWidthsRecalc();
639 RenderBlock* RenderBlock::columnsBlockForSpanningElement(RenderObject* newChild)
641 // FIXME: This function is the gateway for the addition of column-span support. It will
642 // be added to in three stages:
643 // (1) Immediate children of a multi-column block can span.
644 // (2) Nested block-level children with only block-level ancestors between them and the multi-column block can span.
645 // (3) Nested children with block or inline ancestors between them and the multi-column block can span (this is when we
646 // cross the streams and have to cope with both types of continuations mixed together).
647 // This function currently supports (1) and (2).
648 RenderBlock* columnsBlockAncestor = 0;
649 if (!newChild->isText() && newChild->style()->columnSpan() && !newChild->isFloatingOrPositioned()
650 && !newChild->isInline() && !isAnonymousColumnSpanBlock()) {
651 if (style()->specifiesColumns())
652 columnsBlockAncestor = this;
653 else if (!isInline() && parent() && parent()->isRenderBlock()) {
654 columnsBlockAncestor = toRenderBlock(parent())->containingColumnsBlock(false);
656 if (columnsBlockAncestor) {
657 // Make sure that none of the parent ancestors have a continuation.
658 // If yes, we do not want split the block into continuations.
659 RenderObject* curr = this;
660 while (curr && curr != columnsBlockAncestor) {
661 if (curr->isRenderBlock() && toRenderBlock(curr)->continuation()) {
662 columnsBlockAncestor = 0;
665 curr = curr->parent();
670 return columnsBlockAncestor;
673 void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild)
675 // Make sure we don't append things after :after-generated content if we have it.
677 beforeChild = findAfterContentRenderer();
679 // If the requested beforeChild is not one of our children, then this is because
680 // there is an anonymous container within this object that contains the beforeChild.
681 if (beforeChild && beforeChild->parent() != this) {
682 RenderObject* beforeChildAnonymousContainer = anonymousContainer(beforeChild);
683 ASSERT(beforeChildAnonymousContainer);
684 ASSERT(beforeChildAnonymousContainer->isAnonymous());
686 if (beforeChildAnonymousContainer->isAnonymousBlock()) {
687 // Insert the child into the anonymous block box instead of here.
688 if (newChild->isInline() || beforeChild->parent()->firstChild() != beforeChild)
689 beforeChild->parent()->addChild(newChild, beforeChild);
691 addChild(newChild, beforeChild->parent());
695 ASSERT(beforeChildAnonymousContainer->isTable());
696 if ((newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP)
697 || (newChild->isRenderBlock() && newChild->style()->display() == TABLE_CAPTION)
698 || newChild->isTableSection()
699 || newChild->isTableRow()
700 || newChild->isTableCell()) {
701 // Insert into the anonymous table.
702 beforeChildAnonymousContainer->addChild(newChild, beforeChild);
706 // Go on to insert before the anonymous table.
707 beforeChild = beforeChildAnonymousContainer;
710 // Check for a spanning element in columns.
711 RenderBlock* columnsBlockAncestor = columnsBlockForSpanningElement(newChild);
712 if (columnsBlockAncestor) {
713 // We are placing a column-span element inside a block.
714 RenderBlock* newBox = createAnonymousColumnSpanBlock();
716 if (columnsBlockAncestor != this) {
717 // We are nested inside a multi-column element and are being split by the span. We have to break up
718 // our block into continuations.
719 RenderBoxModelObject* oldContinuation = continuation();
720 setContinuation(newBox);
722 // Someone may have put a <p> inside a <q>, causing a split. When this happens, the :after content
723 // has to move into the inline continuation. Call updateBeforeAfterContent to ensure that our :after
724 // content gets properly destroyed.
725 bool isLastChild = (beforeChild == lastChild());
726 if (document()->usesBeforeAfterRules())
727 children()->updateBeforeAfterContent(this, AFTER);
728 if (isLastChild && beforeChild != lastChild())
729 beforeChild = 0; // We destroyed the last child, so now we need to update our insertion
730 // point to be 0. It's just a straight append now.
732 splitFlow(beforeChild, newBox, newChild, oldContinuation);
736 // We have to perform a split of this block's children. This involves creating an anonymous block box to hold
737 // the column-spanning |newChild|. We take all of the children from before |newChild| and put them into
738 // one anonymous columns block, and all of the children after |newChild| go into another anonymous block.
739 makeChildrenAnonymousColumnBlocks(beforeChild, newBox, newChild);
743 bool madeBoxesNonInline = false;
745 // A block has to either have all of its children inline, or all of its children as blocks.
746 // So, if our children are currently inline and a block child has to be inserted, we move all our
747 // inline children into anonymous block boxes.
748 if (childrenInline() && !newChild->isInline() && !newChild->isFloatingOrPositioned()) {
749 // This is a block with inline content. Wrap the inline content in anonymous blocks.
750 makeChildrenNonInline(beforeChild);
751 madeBoxesNonInline = true;
753 if (beforeChild && beforeChild->parent() != this) {
754 beforeChild = beforeChild->parent();
755 ASSERT(beforeChild->isAnonymousBlock());
756 ASSERT(beforeChild->parent() == this);
758 } else if (!childrenInline() && (newChild->isFloatingOrPositioned() || newChild->isInline())) {
759 // If we're inserting an inline child but all of our children are blocks, then we have to make sure
760 // it is put into an anomyous block box. We try to use an existing anonymous box if possible, otherwise
761 // a new one is created and inserted into our list of children in the appropriate position.
762 RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : lastChild();
764 if (afterChild && afterChild->isAnonymousBlock()) {
765 afterChild->addChild(newChild);
769 if (newChild->isInline()) {
770 // No suitable existing anonymous box - create a new one.
771 RenderBlock* newBox = createAnonymousBlock();
772 RenderBox::addChild(newBox, beforeChild);
773 newBox->addChild(newChild);
778 RenderBox::addChild(newChild, beforeChild);
780 if (madeBoxesNonInline && parent() && isAnonymousBlock() && parent()->isRenderBlock())
781 toRenderBlock(parent())->removeLeftoverAnonymousBlock(this);
782 // this object may be dead here
785 void RenderBlock::addChild(RenderObject* newChild, RenderObject* beforeChild)
787 if (continuation() && !isAnonymousBlock())
788 return addChildToContinuation(newChild, beforeChild);
789 return addChildIgnoringContinuation(newChild, beforeChild);
792 void RenderBlock::addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild)
794 if (!isAnonymousBlock() && firstChild() && (firstChild()->isAnonymousColumnsBlock() || firstChild()->isAnonymousColumnSpanBlock()))
795 return addChildToAnonymousColumnBlocks(newChild, beforeChild);
796 return addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild);
799 static void getInlineRun(RenderObject* start, RenderObject* boundary,
800 RenderObject*& inlineRunStart,
801 RenderObject*& inlineRunEnd)
803 // Beginning at |start| we find the largest contiguous run of inlines that
804 // we can. We denote the run with start and end points, |inlineRunStart|
805 // and |inlineRunEnd|. Note that these two values may be the same if
806 // we encounter only one inline.
808 // We skip any non-inlines we encounter as long as we haven't found any
811 // |boundary| indicates a non-inclusive boundary point. Regardless of whether |boundary|
812 // is inline or not, we will not include it in a run with inlines before it. It's as though we encountered
815 // Start by skipping as many non-inlines as we can.
816 RenderObject * curr = start;
819 while (curr && !(curr->isInline() || curr->isFloatingOrPositioned()))
820 curr = curr->nextSibling();
822 inlineRunStart = inlineRunEnd = curr;
825 return; // No more inline children to be found.
827 sawInline = curr->isInline();
829 curr = curr->nextSibling();
830 while (curr && (curr->isInline() || curr->isFloatingOrPositioned()) && (curr != boundary)) {
832 if (curr->isInline())
834 curr = curr->nextSibling();
836 } while (!sawInline);
839 void RenderBlock::deleteLineBoxTree()
841 m_lineBoxes.deleteLineBoxTree(renderArena());
844 RootInlineBox* RenderBlock::createRootInlineBox()
846 return new (renderArena()) RootInlineBox(this);
849 RootInlineBox* RenderBlock::createAndAppendRootInlineBox()
851 RootInlineBox* rootBox = createRootInlineBox();
852 m_lineBoxes.appendLineBox(rootBox);
856 void RenderBlock::moveChildTo(RenderBlock* to, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert)
858 ASSERT(this == child->parent());
859 ASSERT(!beforeChild || to == beforeChild->parent());
860 to->children()->insertChildNode(to, children()->removeChildNode(this, child, fullRemoveInsert), beforeChild, fullRemoveInsert);
863 void RenderBlock::moveChildrenTo(RenderBlock* to, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert)
865 ASSERT(!beforeChild || to == beforeChild->parent());
866 RenderObject* nextChild = startChild;
867 while (nextChild && nextChild != endChild) {
868 RenderObject* child = nextChild;
869 nextChild = child->nextSibling();
870 to->children()->insertChildNode(to, children()->removeChildNode(this, child, fullRemoveInsert), beforeChild, fullRemoveInsert);
871 if (child == endChild)
876 void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
878 // makeChildrenNonInline takes a block whose children are *all* inline and it
879 // makes sure that inline children are coalesced under anonymous
880 // blocks. If |insertionPoint| is defined, then it represents the insertion point for
881 // the new block child that is causing us to have to wrap all the inlines. This
882 // means that we cannot coalesce inlines before |insertionPoint| with inlines following
883 // |insertionPoint|, because the new child is going to be inserted in between the inlines,
885 ASSERT(isInlineBlockOrInlineTable() || !isInline());
886 ASSERT(!insertionPoint || insertionPoint->parent() == this);
888 setChildrenInline(false);
890 RenderObject *child = firstChild();
897 RenderObject *inlineRunStart, *inlineRunEnd;
898 getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd);
903 child = inlineRunEnd->nextSibling();
905 RenderBlock* block = createAnonymousBlock();
906 children()->insertChildNode(this, block, inlineRunStart);
907 moveChildrenTo(block, inlineRunStart, child);
911 for (RenderObject *c = firstChild(); c; c = c->nextSibling())
912 ASSERT(!c->isInline());
918 void RenderBlock::removeLeftoverAnonymousBlock(RenderBlock* child)
920 ASSERT(child->isAnonymousBlock());
921 ASSERT(!child->childrenInline());
923 if (child->continuation() || (child->firstChild() && (child->isAnonymousColumnSpanBlock() || child->isAnonymousColumnsBlock())))
926 RenderObject* firstAnChild = child->m_children.firstChild();
927 RenderObject* lastAnChild = child->m_children.lastChild();
929 RenderObject* o = firstAnChild;
932 o = o->nextSibling();
934 firstAnChild->setPreviousSibling(child->previousSibling());
935 lastAnChild->setNextSibling(child->nextSibling());
936 if (child->previousSibling())
937 child->previousSibling()->setNextSibling(firstAnChild);
938 if (child->nextSibling())
939 child->nextSibling()->setPreviousSibling(lastAnChild);
941 if (child == m_children.firstChild())
942 m_children.setFirstChild(firstAnChild);
943 if (child == m_children.lastChild())
944 m_children.setLastChild(lastAnChild);
946 if (child == m_children.firstChild())
947 m_children.setFirstChild(child->nextSibling());
948 if (child == m_children.lastChild())
949 m_children.setLastChild(child->previousSibling());
951 if (child->previousSibling())
952 child->previousSibling()->setNextSibling(child->nextSibling());
953 if (child->nextSibling())
954 child->nextSibling()->setPreviousSibling(child->previousSibling());
957 child->setPreviousSibling(0);
958 child->setNextSibling(0);
960 child->children()->setFirstChild(0);
966 static bool canMergeContiguousAnonymousBlocks(RenderObject* oldChild, RenderObject* prev, RenderObject* next)
968 if (oldChild->documentBeingDestroyed() || oldChild->isInline() || oldChild->virtualContinuation())
972 if (oldChild->parent() && oldChild->parent()->isDetails())
976 if ((prev && (!prev->isAnonymousBlock() || toRenderBlock(prev)->continuation() || toRenderBlock(prev)->beingDestroyed()))
977 || (next && (!next->isAnonymousBlock() || toRenderBlock(next)->continuation() || toRenderBlock(next)->beingDestroyed())))
980 // FIXME: This check isn't required when inline run-ins can't be split into continuations.
981 if (prev && prev->firstChild() && prev->firstChild()->isInline() && prev->firstChild()->isRunIn())
984 if ((prev && (prev->isRubyRun() || prev->isRubyBase()))
985 || (next && (next->isRubyRun() || next->isRubyBase())))
991 // Make sure the types of the anonymous blocks match up.
992 return prev->isAnonymousColumnsBlock() == next->isAnonymousColumnsBlock()
993 && prev->isAnonymousColumnSpanBlock() == next->isAnonymousColumnSpanBlock();
996 void RenderBlock::removeChild(RenderObject* oldChild)
998 // If this child is a block, and if our previous and next siblings are
999 // both anonymous blocks with inline content, then we can go ahead and
1000 // fold the inline content back together.
1001 RenderObject* prev = oldChild->previousSibling();
1002 RenderObject* next = oldChild->nextSibling();
1003 bool canMergeAnonymousBlocks = canMergeContiguousAnonymousBlocks(oldChild, prev, next);
1004 if (canMergeAnonymousBlocks && prev && next) {
1005 prev->setNeedsLayoutAndPrefWidthsRecalc();
1006 RenderBlock* nextBlock = toRenderBlock(next);
1007 RenderBlock* prevBlock = toRenderBlock(prev);
1009 if (prev->childrenInline() != next->childrenInline()) {
1010 RenderBlock* inlineChildrenBlock = prev->childrenInline() ? prevBlock : nextBlock;
1011 RenderBlock* blockChildrenBlock = prev->childrenInline() ? nextBlock : prevBlock;
1013 // Place the inline children block inside of the block children block instead of deleting it.
1014 // In order to reuse it, we have to reset it to just be a generic anonymous block. Make sure
1015 // to clear out inherited column properties by just making a new style, and to also clear the
1016 // column span flag if it is set.
1017 ASSERT(!inlineChildrenBlock->continuation());
1018 RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style());
1019 children()->removeChildNode(this, inlineChildrenBlock, inlineChildrenBlock->hasLayer());
1020 inlineChildrenBlock->setStyle(newStyle);
1022 // Now just put the inlineChildrenBlock inside the blockChildrenBlock.
1023 blockChildrenBlock->children()->insertChildNode(blockChildrenBlock, inlineChildrenBlock, prev == inlineChildrenBlock ? blockChildrenBlock->firstChild() : 0,
1024 inlineChildrenBlock->hasLayer() || blockChildrenBlock->hasLayer());
1025 next->setNeedsLayoutAndPrefWidthsRecalc();
1027 // inlineChildrenBlock got reparented to blockChildrenBlock, so it is no longer a child
1028 // of "this". we null out prev or next so that is not used later in the function.
1029 if (inlineChildrenBlock == prevBlock)
1034 // Take all the children out of the |next| block and put them in
1035 // the |prev| block.
1036 nextBlock->moveAllChildrenTo(prevBlock, nextBlock->hasLayer() || prevBlock->hasLayer());
1038 // Delete the now-empty block's lines and nuke it.
1039 nextBlock->deleteLineBoxTree();
1040 nextBlock->destroy();
1045 RenderBox::removeChild(oldChild);
1047 RenderObject* child = prev ? prev : next;
1048 if (canMergeAnonymousBlocks && child && !child->previousSibling() && !child->nextSibling() && !isDeprecatedFlexibleBox()) {
1049 // The removal has knocked us down to containing only a single anonymous
1050 // box. We can go ahead and pull the content right back up into our
1052 setNeedsLayoutAndPrefWidthsRecalc();
1053 setChildrenInline(child->childrenInline());
1054 RenderBlock* anonBlock = toRenderBlock(children()->removeChildNode(this, child, child->hasLayer()));
1055 anonBlock->moveAllChildrenTo(this, child->hasLayer());
1056 // Delete the now-empty block's lines and nuke it.
1057 anonBlock->deleteLineBoxTree();
1058 anonBlock->destroy();
1061 if (!firstChild() && !documentBeingDestroyed()) {
1062 // If this was our last child be sure to clear out our line boxes.
1063 if (childrenInline())
1064 lineBoxes()->deleteLineBoxes(renderArena());
1068 bool RenderBlock::isSelfCollapsingBlock() const
1070 // We are not self-collapsing if we
1071 // (a) have a non-zero height according to layout (an optimization to avoid wasting time)
1073 // (c) have border/padding,
1074 // (d) have a min-height
1075 // (e) have specified that one of our margins can't collapse using a CSS extension
1076 if (logicalHeight() > 0
1077 || isTable() || borderAndPaddingLogicalHeight()
1078 || style()->logicalMinHeight().isPositive()
1079 || style()->marginBeforeCollapse() == MSEPARATE || style()->marginAfterCollapse() == MSEPARATE)
1082 Length logicalHeightLength = style()->logicalHeight();
1083 bool hasAutoHeight = logicalHeightLength.isAuto();
1084 if (logicalHeightLength.isPercent() && !document()->inQuirksMode()) {
1085 hasAutoHeight = true;
1086 for (RenderBlock* cb = containingBlock(); !cb->isRenderView(); cb = cb->containingBlock()) {
1087 if (cb->style()->logicalHeight().isFixed() || cb->isTableCell())
1088 hasAutoHeight = false;
1092 // If the height is 0 or auto, then whether or not we are a self-collapsing block depends
1093 // on whether we have content that is all self-collapsing or not.
1094 if (hasAutoHeight || ((logicalHeightLength.isFixed() || logicalHeightLength.isPercent()) && logicalHeightLength.isZero())) {
1095 // If the block has inline children, see if we generated any line boxes. If we have any
1096 // line boxes, then we can't be self-collapsing, since we have content.
1097 if (childrenInline())
1098 return !firstLineBox();
1100 // Whether or not we collapse is dependent on whether all our normal flow children
1101 // are also self-collapsing.
1102 for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
1103 if (child->isFloatingOrPositioned())
1105 if (!child->isSelfCollapsingBlock())
1113 void RenderBlock::startDelayUpdateScrollInfo()
1115 if (gDelayUpdateScrollInfo == 0) {
1116 ASSERT(!gDelayedUpdateScrollInfoSet);
1117 gDelayedUpdateScrollInfoSet = new DelayedUpdateScrollInfoSet;
1119 ASSERT(gDelayedUpdateScrollInfoSet);
1120 ++gDelayUpdateScrollInfo;
1123 void RenderBlock::finishDelayUpdateScrollInfo()
1125 --gDelayUpdateScrollInfo;
1126 ASSERT(gDelayUpdateScrollInfo >= 0);
1127 if (gDelayUpdateScrollInfo == 0) {
1128 ASSERT(gDelayedUpdateScrollInfoSet);
1130 OwnPtr<DelayedUpdateScrollInfoSet> infoSet(adoptPtr(gDelayedUpdateScrollInfoSet));
1131 gDelayedUpdateScrollInfoSet = 0;
1133 for (DelayedUpdateScrollInfoSet::iterator it = infoSet->begin(); it != infoSet->end(); ++it) {
1134 RenderBlock* block = *it;
1135 if (block->hasOverflowClip()) {
1136 block->layer()->updateScrollInfoAfterLayout();
1142 void RenderBlock::updateScrollInfoAfterLayout()
1144 if (hasOverflowClip()) {
1145 if (gDelayUpdateScrollInfo)
1146 gDelayedUpdateScrollInfoSet->add(this);
1148 layer()->updateScrollInfoAfterLayout();
1152 void RenderBlock::layout()
1154 // Update our first letter info now.
1155 updateFirstLetter();
1157 // Table cells call layoutBlock directly, so don't add any logic here. Put code into
1161 // It's safe to check for control clip here, since controls can never be table cells.
1162 // If we have a lightweight clip, there can never be any overflow from children.
1163 if (hasControlClip() && m_overflow)
1164 clearLayoutOverflow();
1167 void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight, BlockLayoutPass layoutPass)
1169 ASSERT(needsLayout());
1171 if (isInline() && !isInlineBlockOrInlineTable()) // Inline <form>s inside various table elements can
1172 return; // cause us to come in here. Just bail.
1174 if (!relayoutChildren && simplifiedLayout())
1177 LayoutRepainter repainter(*this, m_everHadLayout && checkForRepaintDuringLayout());
1179 LayoutUnit oldWidth = logicalWidth();
1180 LayoutUnit oldColumnWidth = desiredColumnWidth();
1182 computeLogicalWidth();
1187 if (oldWidth != logicalWidth() || oldColumnWidth != desiredColumnWidth())
1188 relayoutChildren = true;
1190 // If nothing changed about our floating positioned objects, let's go ahead and try to place them as
1191 // floats to avoid doing two passes.
1192 BlockLayoutPass floatsLayoutPass = layoutPass;
1193 if (floatsLayoutPass == NormalLayoutPass && !relayoutChildren && !positionedFloatsNeedRelayout())
1194 floatsLayoutPass = PositionedFloatLayoutPass;
1195 clearFloats(floatsLayoutPass);
1197 LayoutUnit previousHeight = logicalHeight();
1198 setLogicalHeight(0);
1199 bool hasSpecifiedPageLogicalHeight = false;
1200 bool pageLogicalHeightChanged = false;
1201 ColumnInfo* colInfo = columnInfo();
1203 if (!pageLogicalHeight) {
1204 // We need to go ahead and set our explicit page height if one exists, so that we can
1205 // avoid doing two layout passes.
1206 computeLogicalHeight();
1207 LayoutUnit columnHeight = contentLogicalHeight();
1208 if (columnHeight > 0) {
1209 pageLogicalHeight = columnHeight;
1210 hasSpecifiedPageLogicalHeight = true;
1212 setLogicalHeight(0);
1214 if (colInfo->columnHeight() != pageLogicalHeight && m_everHadLayout) {
1215 colInfo->setColumnHeight(pageLogicalHeight);
1216 pageLogicalHeightChanged = true;
1219 if (!hasSpecifiedPageLogicalHeight && !pageLogicalHeight)
1220 colInfo->clearForcedBreaks();
1223 RenderView* renderView = view();
1224 LayoutStateMaintainer statePusher(renderView, this, locationOffset(), hasColumns() || hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode(), pageLogicalHeight, pageLogicalHeightChanged, colInfo);
1226 if (inRenderFlowThread()) {
1227 // Regions changing widths can force us to relayout our children.
1228 if (logicalWidthChangedInRegions())
1229 relayoutChildren = true;
1231 // Set our start and end regions. No regions above or below us will be considered by our children. They are
1232 // effectively clamped to our region range.
1233 LayoutUnit oldHeight = logicalHeight();
1234 LayoutUnit oldLogicalTop = logicalTop();
1235 setLogicalHeight(INT_MAX / 2);
1236 computeLogicalHeight();
1237 enclosingRenderFlowThread()->setRegionRangeForBox(this, offsetFromLogicalTopOfFirstPage());
1238 setLogicalHeight(oldHeight);
1239 setLogicalTop(oldLogicalTop);
1242 // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, to track
1243 // our current maximal positive and negative margins. These values are used when we
1244 // are collapsed with adjacent blocks, so for example, if you have block A and B
1245 // collapsing together, then you'd take the maximal positive margin from both A and B
1246 // and subtract it from the maximal negative margin from both A and B to get the
1247 // true collapsed margin. This algorithm is recursive, so when we finish layout()
1248 // our block knows its current maximal positive/negative values.
1250 // Start out by setting our margin values to our current margins. Table cells have
1251 // no margins, so we don't fill in the values for table cells.
1252 bool isCell = isTableCell();
1254 initMaxMarginValues();
1256 setMarginBeforeQuirk(style()->marginBefore().quirk());
1257 setMarginAfterQuirk(style()->marginAfter().quirk());
1260 if (n && n->hasTagName(formTag) && static_cast<HTMLFormElement*>(n)->isMalformed()) {
1261 // See if this form is malformed (i.e., unclosed). If so, don't give the form
1263 setMaxMarginAfterValues(0, 0);
1266 setPaginationStrut(0);
1269 // For overflow:scroll blocks, ensure we have both scrollbars in place always.
1270 if (scrollsOverflow()) {
1271 if (style()->overflowX() == OSCROLL)
1272 layer()->setHasHorizontalScrollbar(true);
1273 if (style()->overflowY() == OSCROLL)
1274 layer()->setHasVerticalScrollbar(true);
1277 LayoutUnit repaintLogicalTop = 0;
1278 LayoutUnit repaintLogicalBottom = 0;
1279 LayoutUnit maxFloatLogicalBottom = 0;
1280 if (!firstChild() && !isAnonymousBlock())
1281 setChildrenInline(true);
1282 if (childrenInline())
1283 layoutInlineChildren(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
1285 layoutBlockChildren(relayoutChildren, maxFloatLogicalBottom);
1287 // Expand our intrinsic height to encompass floats.
1288 LayoutUnit toAdd = borderAfter() + paddingAfter() + scrollbarLogicalHeight();
1289 if (lowestFloatLogicalBottom() > (logicalHeight() - toAdd) && expandsToEncloseOverhangingFloats())
1290 setLogicalHeight(lowestFloatLogicalBottom() + toAdd);
1292 if (layoutColumns(hasSpecifiedPageLogicalHeight, pageLogicalHeight, statePusher))
1295 // Calculate our new height.
1296 LayoutUnit oldHeight = logicalHeight();
1297 LayoutUnit oldClientAfterEdge = clientLogicalBottom();
1298 computeLogicalHeight();
1299 LayoutUnit newHeight = logicalHeight();
1300 if (oldHeight != newHeight) {
1301 if (oldHeight > newHeight && maxFloatLogicalBottom > newHeight && !childrenInline()) {
1302 // One of our children's floats may have become an overhanging float for us. We need to look for it.
1303 for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
1304 if (child->isBlockFlow() && !child->isFloatingOrPositioned()) {
1305 RenderBlock* block = toRenderBlock(child);
1306 if (block->lowestFloatLogicalBottomIncludingPositionedFloats() + block->logicalTop() > newHeight)
1307 addOverhangingFloats(block, false);
1313 if (previousHeight != newHeight)
1314 relayoutChildren = true;
1316 bool needAnotherLayoutPass = layoutPositionedObjects(relayoutChildren || isRoot());
1318 if (inRenderFlowThread())
1319 enclosingRenderFlowThread()->setRegionRangeForBox(this, offsetFromLogicalTopOfFirstPage());
1321 // Add overflow from children (unless we're multi-column, since in that case all our child overflow is clipped anyway).
1322 computeOverflow(oldClientAfterEdge);
1326 if (renderView->layoutState()->m_pageLogicalHeight)
1327 setPageLogicalOffset(renderView->layoutState()->pageLogicalOffset(logicalTop()));
1329 updateLayerTransform();
1331 // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
1332 // we overflow or not.
1333 updateScrollInfoAfterLayout();
1335 // FIXME: This repaint logic should be moved into a separate helper function!
1336 // Repaint with our new bounds if they are different from our old bounds.
1337 bool didFullRepaint = repainter.repaintAfterLayout();
1338 if (!didFullRepaint && repaintLogicalTop != repaintLogicalBottom && (style()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) {
1339 // FIXME: We could tighten up the left and right invalidation points if we let layoutInlineChildren fill them in based off the particular lines
1340 // it had to lay out. We wouldn't need the hasOverflowClip() hack in that case either.
1341 LayoutUnit repaintLogicalLeft = logicalLeftVisualOverflow();
1342 LayoutUnit repaintLogicalRight = logicalRightVisualOverflow();
1343 if (hasOverflowClip()) {
1344 // 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.
1345 // 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.
1346 // layoutInlineChildren should be patched to compute the entire repaint rect.
1347 repaintLogicalLeft = min(repaintLogicalLeft, logicalLeftLayoutOverflow());
1348 repaintLogicalRight = max(repaintLogicalRight, logicalRightLayoutOverflow());
1351 LayoutRect repaintRect;
1352 if (isHorizontalWritingMode())
1353 repaintRect = LayoutRect(repaintLogicalLeft, repaintLogicalTop, repaintLogicalRight - repaintLogicalLeft, repaintLogicalBottom - repaintLogicalTop);
1355 repaintRect = LayoutRect(repaintLogicalTop, repaintLogicalLeft, repaintLogicalBottom - repaintLogicalTop, repaintLogicalRight - repaintLogicalLeft);
1357 // The repaint rect may be split across columns, in which case adjustRectForColumns() will return the union.
1358 adjustRectForColumns(repaintRect);
1360 repaintRect.inflate(maximalOutlineSize(PaintPhaseOutline));
1362 if (hasOverflowClip()) {
1363 // Adjust repaint rect for scroll offset
1364 repaintRect.move(-layer()->scrolledContentOffset());
1366 // Don't allow this rect to spill out of our overflow box.
1367 repaintRect.intersect(LayoutRect(LayoutPoint(), size()));
1370 // Make sure the rect is still non-empty after intersecting for overflow above
1371 if (!repaintRect.isEmpty()) {
1372 // FIXME: Might need rounding once we switch to float, see https://bugs.webkit.org/show_bug.cgi?id=64021
1373 repaintRectangle(repaintRect); // We need to do a partial repaint of our content.
1374 if (hasReflection())
1375 repaintRectangle(reflectedRect(repaintRect));
1379 if (needAnotherLayoutPass && layoutPass == NormalLayoutPass) {
1380 setChildNeedsLayout(true, false);
1381 layoutBlock(false, pageLogicalHeight, PositionedFloatLayoutPass);
1383 setNeedsLayout(false);
1386 void RenderBlock::addOverflowFromChildren()
1388 if (!hasColumns()) {
1389 if (childrenInline())
1390 addOverflowFromInlineChildren();
1392 addOverflowFromBlockChildren();
1394 ColumnInfo* colInfo = columnInfo();
1395 if (columnCount(colInfo)) {
1396 LayoutRect lastRect = columnRectAt(colInfo, columnCount(colInfo) - 1);
1397 if (isHorizontalWritingMode()) {
1398 LayoutUnit overflowLeft = !style()->isLeftToRightDirection() ? min<LayoutUnit>(0, lastRect.x()) : 0;
1399 LayoutUnit overflowRight = style()->isLeftToRightDirection() ? max(width(), lastRect.maxX()) : 0;
1400 LayoutUnit overflowHeight = borderBefore() + paddingBefore() + colInfo->columnHeight();
1401 addLayoutOverflow(LayoutRect(overflowLeft, 0, overflowRight - overflowLeft, overflowHeight));
1402 if (!hasOverflowClip())
1403 addVisualOverflow(LayoutRect(overflowLeft, 0, overflowRight - overflowLeft, overflowHeight));
1405 LayoutRect lastRect = columnRectAt(colInfo, columnCount(colInfo) - 1);
1406 LayoutUnit overflowTop = !style()->isLeftToRightDirection() ? min<LayoutUnit>(0, lastRect.y()) : 0;
1407 LayoutUnit overflowBottom = style()->isLeftToRightDirection() ? max(height(), lastRect.maxY()) : 0;
1408 LayoutUnit overflowWidth = borderBefore() + paddingBefore() + colInfo->columnHeight();
1409 addLayoutOverflow(LayoutRect(0, overflowTop, overflowWidth, overflowBottom - overflowTop));
1410 if (!hasOverflowClip())
1411 addVisualOverflow(LayoutRect(0, overflowTop, overflowWidth, overflowBottom - overflowTop));
1417 void RenderBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats)
1419 // Add overflow from children.
1420 addOverflowFromChildren();
1422 if (!hasColumns() && (recomputeFloats || isRoot() || expandsToEncloseOverhangingFloats() || hasSelfPaintingLayer()))
1423 addOverflowFromFloats();
1425 // Add in the overflow from positioned objects.
1426 addOverflowFromPositionedObjects();
1428 if (hasOverflowClip()) {
1429 // When we have overflow clip, propagate the original spillout since it will include collapsed bottom margins
1430 // and bottom padding. Set the axis we don't care about to be 1, since we want this overflow to always
1431 // be considered reachable.
1432 LayoutRect clientRect(clientBoxRect());
1433 LayoutRect rectToApply;
1434 if (isHorizontalWritingMode())
1435 rectToApply = LayoutRect(clientRect.x(), clientRect.y(), 1, max<LayoutUnit>(0, oldClientAfterEdge - clientRect.y()));
1437 rectToApply = LayoutRect(clientRect.x(), clientRect.y(), max<LayoutUnit>(0, oldClientAfterEdge - clientRect.x()), 1);
1438 addLayoutOverflow(rectToApply);
1441 // Add visual overflow from box-shadow and border-image-outset.
1442 addBoxShadowAndBorderOverflow();
1445 void RenderBlock::addOverflowFromBlockChildren()
1447 for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
1448 if (!child->isFloatingOrPositioned())
1449 addOverflowFromChild(child);
1453 void RenderBlock::addOverflowFromFloats()
1455 if (!m_floatingObjects)
1458 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
1459 FloatingObjectSetIterator end = floatingObjectSet.end();
1460 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
1461 FloatingObject* r = *it;
1462 if (r->m_isDescendant && !r->m_renderer->isPositioned())
1463 addOverflowFromChild(r->m_renderer, IntSize(xPositionForFloatIncludingMargin(r), yPositionForFloatIncludingMargin(r)));
1468 void RenderBlock::addOverflowFromPositionedObjects()
1470 if (!m_positionedObjects)
1473 RenderBox* positionedObject;
1474 Iterator end = m_positionedObjects->end();
1475 for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
1476 positionedObject = *it;
1478 // Fixed positioned elements don't contribute to layout overflow, since they don't scroll with the content.
1479 if (positionedObject->style()->position() != FixedPosition)
1480 addOverflowFromChild(positionedObject);
1484 bool RenderBlock::expandsToEncloseOverhangingFloats() const
1486 return isInlineBlockOrInlineTable() || isFloatingOrPositioned() || hasOverflowClip() || (parent() && parent()->isDeprecatedFlexibleBox())
1487 || hasColumns() || isTableCell() || isFieldset() || isWritingModeRoot() || isRoot();
1490 void RenderBlock::adjustPositionedBlock(RenderBox* child, const MarginInfo& marginInfo)
1492 bool isHorizontal = isHorizontalWritingMode();
1493 bool hasStaticBlockPosition = child->style()->hasStaticBlockPosition(isHorizontal);
1495 LayoutUnit logicalTop = logicalHeight();
1496 setStaticInlinePositionForChild(child, logicalTop, startOffsetForContent(logicalTop));
1498 if (!marginInfo.canCollapseWithMarginBefore()) {
1499 child->computeBlockDirectionMargins(this);
1500 LayoutUnit marginBefore = marginBeforeForChild(child);
1501 LayoutUnit collapsedBeforePos = marginInfo.positiveMargin();
1502 LayoutUnit collapsedBeforeNeg = marginInfo.negativeMargin();
1503 if (marginBefore > 0) {
1504 if (marginBefore > collapsedBeforePos)
1505 collapsedBeforePos = marginBefore;
1507 if (-marginBefore > collapsedBeforeNeg)
1508 collapsedBeforeNeg = -marginBefore;
1510 logicalTop += (collapsedBeforePos - collapsedBeforeNeg) - marginBefore;
1513 RenderLayer* childLayer = child->layer();
1514 if (childLayer->staticBlockPosition() != logicalTop) {
1515 childLayer->setStaticBlockPosition(logicalTop);
1516 if (hasStaticBlockPosition)
1517 child->setChildNeedsLayout(true, false);
1521 void RenderBlock::adjustFloatingBlock(const MarginInfo& marginInfo)
1523 // The float should be positioned taking into account the bottom margin
1524 // of the previous flow. We add that margin into the height, get the
1525 // float positioned properly, and then subtract the margin out of the
1526 // height again. In the case of self-collapsing blocks, we always just
1527 // use the top margins, since the self-collapsing block collapsed its
1528 // own bottom margin into its top margin.
1530 // Note also that the previous flow may collapse its margin into the top of
1531 // our block. If this is the case, then we do not add the margin in to our
1532 // height when computing the position of the float. This condition can be tested
1533 // for by simply calling canCollapseWithMarginBefore. See
1534 // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for
1535 // an example of this scenario.
1536 LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() ? 0 : marginInfo.margin();
1537 setLogicalHeight(logicalHeight() + marginOffset);
1538 positionNewFloats();
1539 setLogicalHeight(logicalHeight() - marginOffset);
1542 bool RenderBlock::handleSpecialChild(RenderBox* child, const MarginInfo& marginInfo)
1544 // Handle in the given order
1545 return handlePositionedChild(child, marginInfo)
1546 || handleFloatingChild(child, marginInfo)
1547 || handleRunInChild(child);
1551 bool RenderBlock::handlePositionedChild(RenderBox* child, const MarginInfo& marginInfo)
1553 if (child->isPositioned()) {
1554 child->containingBlock()->insertPositionedObject(child);
1555 adjustPositionedBlock(child, marginInfo);
1561 bool RenderBlock::handleFloatingChild(RenderBox* child, const MarginInfo& marginInfo)
1563 if (child->isFloating()) {
1564 insertFloatingObject(child);
1565 adjustFloatingBlock(marginInfo);
1571 bool RenderBlock::handleRunInChild(RenderBox* child)
1573 // See if we have a run-in element with inline children. If the
1574 // children aren't inline, then just treat the run-in as a normal
1576 if (!child->isRunIn() || !child->childrenInline())
1578 // FIXME: We don't handle non-block elements with run-in for now.
1579 if (!child->isRenderBlock())
1582 RenderBlock* blockRunIn = toRenderBlock(child);
1583 RenderObject* curr = blockRunIn->nextSibling();
1584 if (!curr || !curr->isRenderBlock() || !curr->childrenInline() || curr->isRunIn() || curr->isAnonymous() || curr->isFloatingOrPositioned())
1587 RenderBlock* currBlock = toRenderBlock(curr);
1589 // Remove the old child.
1590 children()->removeChildNode(this, blockRunIn);
1592 // Create an inline.
1593 Node* runInNode = blockRunIn->node();
1594 RenderInline* inlineRunIn = new (renderArena()) RenderInline(runInNode ? runInNode : document());
1595 inlineRunIn->setStyle(blockRunIn->style());
1597 bool runInIsGenerated = child->style()->styleType() == BEFORE || child->style()->styleType() == AFTER;
1599 // Move the nodes from the old child to the new child, but skip any :before/:after content. It has already
1600 // been regenerated by the new inline.
1601 for (RenderObject* runInChild = blockRunIn->firstChild(); runInChild;) {
1602 RenderObject* nextSibling = runInChild->nextSibling();
1603 if (runInIsGenerated || (runInChild->style()->styleType() != BEFORE && runInChild->style()->styleType() != AFTER)) {
1604 blockRunIn->children()->removeChildNode(blockRunIn, runInChild, false);
1605 inlineRunIn->addChild(runInChild); // Use addChild instead of appendChildNode since it handles correct placement of the children relative to :after-generated content.
1607 runInChild = nextSibling;
1610 // Now insert the new child under |currBlock|. Use addChild instead of insertChildNode since it handles correct placement of the children, esp where we cannot insert
1611 // anything before the first child. e.g. details tag. See https://bugs.webkit.org/show_bug.cgi?id=58228.
1612 currBlock->addChild(inlineRunIn, currBlock->firstChild());
1614 // If the run-in had an element, we need to set the new renderer.
1616 runInNode->setRenderer(inlineRunIn);
1618 // Destroy the block run-in, which includes deleting its line box tree.
1619 blockRunIn->deleteLineBoxTree();
1620 blockRunIn->destroy();
1622 // The block acts like an inline, so just null out its
1628 LayoutUnit RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
1630 // Get the four margin values for the child and cache them.
1631 const MarginValues childMargins = marginValuesForChild(child);
1633 // Get our max pos and neg top margins.
1634 LayoutUnit posTop = childMargins.positiveMarginBefore();
1635 LayoutUnit negTop = childMargins.negativeMarginBefore();
1637 // For self-collapsing blocks, collapse our bottom margins into our
1638 // top to get new posTop and negTop values.
1639 if (child->isSelfCollapsingBlock()) {
1640 posTop = max(posTop, childMargins.positiveMarginAfter());
1641 negTop = max(negTop, childMargins.negativeMarginAfter());
1644 // See if the top margin is quirky. We only care if this child has
1645 // margins that will collapse with us.
1646 bool topQuirk = child->isMarginBeforeQuirk() || style()->marginBeforeCollapse() == MDISCARD;
1648 if (marginInfo.canCollapseWithMarginBefore()) {
1649 // This child is collapsing with the top of the
1650 // block. If it has larger margin values, then we need to update
1651 // our own maximal values.
1652 if (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !topQuirk)
1653 setMaxMarginBeforeValues(max(posTop, maxPositiveMarginBefore()), max(negTop, maxNegativeMarginBefore()));
1655 // The minute any of the margins involved isn't a quirk, don't
1656 // collapse it away, even if the margin is smaller (www.webreference.com
1657 // has an example of this, a <dt> with 0.8em author-specified inside
1658 // a <dl> inside a <td>.
1659 if (!marginInfo.determinedMarginBeforeQuirk() && !topQuirk && (posTop - negTop)) {
1660 setMarginBeforeQuirk(false);
1661 marginInfo.setDeterminedMarginBeforeQuirk(true);
1664 if (!marginInfo.determinedMarginBeforeQuirk() && topQuirk && !marginBefore())
1665 // We have no top margin and our top child has a quirky margin.
1666 // We will pick up this quirky margin and pass it through.
1667 // This deals with the <td><div><p> case.
1668 // Don't do this for a block that split two inlines though. You do
1669 // still apply margins in this case.
1670 setMarginBeforeQuirk(true);
1673 if (marginInfo.quirkContainer() && marginInfo.atBeforeSideOfBlock() && (posTop - negTop))
1674 marginInfo.setMarginBeforeQuirk(topQuirk);
1676 LayoutUnit beforeCollapseLogicalTop = logicalHeight();
1677 LayoutUnit logicalTop = beforeCollapseLogicalTop;
1678 if (child->isSelfCollapsingBlock()) {
1679 // This child has no height. We need to compute our
1680 // position before we collapse the child's margins together,
1681 // so that we can get an accurate position for the zero-height block.
1682 LayoutUnit collapsedBeforePos = max(marginInfo.positiveMargin(), childMargins.positiveMarginBefore());
1683 LayoutUnit collapsedBeforeNeg = max(marginInfo.negativeMargin(), childMargins.negativeMarginBefore());
1684 marginInfo.setMargin(collapsedBeforePos, collapsedBeforeNeg);
1686 // Now collapse the child's margins together, which means examining our
1687 // bottom margin values as well.
1688 marginInfo.setPositiveMarginIfLarger(childMargins.positiveMarginAfter());
1689 marginInfo.setNegativeMarginIfLarger(childMargins.negativeMarginAfter());
1691 if (!marginInfo.canCollapseWithMarginBefore())
1692 // We need to make sure that the position of the self-collapsing block
1693 // is correct, since it could have overflowing content
1694 // that needs to be positioned correctly (e.g., a block that
1695 // had a specified height of 0 but that actually had subcontent).
1696 logicalTop = logicalHeight() + collapsedBeforePos - collapsedBeforeNeg;
1699 if (child->style()->marginBeforeCollapse() == MSEPARATE) {
1700 setLogicalHeight(logicalHeight() + marginInfo.margin() + marginBeforeForChild(child));
1701 logicalTop = logicalHeight();
1703 else if (!marginInfo.atBeforeSideOfBlock() ||
1704 (!marginInfo.canCollapseMarginBeforeWithChildren()
1705 && (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !marginInfo.marginBeforeQuirk()))) {
1706 // We're collapsing with a previous sibling's margins and not
1707 // with the top of the block.
1708 setLogicalHeight(logicalHeight() + max(marginInfo.positiveMargin(), posTop) - max(marginInfo.negativeMargin(), negTop));
1709 logicalTop = logicalHeight();
1712 marginInfo.setPositiveMargin(childMargins.positiveMarginAfter());
1713 marginInfo.setNegativeMargin(childMargins.negativeMarginAfter());
1715 if (marginInfo.margin())
1716 marginInfo.setMarginAfterQuirk(child->isMarginAfterQuirk() || style()->marginAfterCollapse() == MDISCARD);
1719 // If margins would pull us past the top of the next page, then we need to pull back and pretend like the margins
1720 // collapsed into the page edge.
1721 LayoutState* layoutState = view()->layoutState();
1722 if (layoutState->isPaginated() && layoutState->pageLogicalHeight() && logicalTop > beforeCollapseLogicalTop
1723 && hasNextPage(beforeCollapseLogicalTop)) {
1724 LayoutUnit oldLogicalTop = logicalTop;
1725 logicalTop = min(logicalTop, nextPageLogicalTop(beforeCollapseLogicalTop));
1726 setLogicalHeight(logicalHeight() + (logicalTop - oldLogicalTop));
1731 LayoutUnit RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, int oldTopPosMargin, int oldTopNegMargin, int yPos)
1733 LayoutUnit heightIncrease = getClearDelta(child, yPos);
1734 if (!heightIncrease)
1737 if (child->isSelfCollapsingBlock()) {
1738 // For self-collapsing blocks that clear, they can still collapse their
1739 // margins with following siblings. Reset the current margins to represent
1740 // the self-collapsing block's margins only.
1742 // "An element that has had clearance applied to it never collapses its top margin with its parent block's bottom margin.
1743 // Therefore if we are at the bottom of the block, let's go ahead and reset margins to only include the
1744 // self-collapsing block's bottom margin.
1745 bool atBottomOfBlock = true;
1746 for (RenderBox* curr = child->nextSiblingBox(); curr && atBottomOfBlock; curr = curr->nextSiblingBox()) {
1747 if (!curr->isFloatingOrPositioned())
1748 atBottomOfBlock = false;
1751 MarginValues childMargins = marginValuesForChild(child);
1752 if (atBottomOfBlock) {
1753 marginInfo.setPositiveMargin(childMargins.positiveMarginAfter());
1754 marginInfo.setNegativeMargin(childMargins.negativeMarginAfter());
1756 marginInfo.setPositiveMargin(max(childMargins.positiveMarginBefore(), childMargins.positiveMarginAfter()));
1757 marginInfo.setNegativeMargin(max(childMargins.negativeMarginBefore(), childMargins.negativeMarginAfter()));
1760 // Adjust our height such that we are ready to be collapsed with subsequent siblings (or the bottom
1761 // of the parent block).
1762 setLogicalHeight(child->y() - max<LayoutUnit>(0, marginInfo.margin()));
1764 // Increase our height by the amount we had to clear.
1765 setLogicalHeight(height() + heightIncrease);
1767 if (marginInfo.canCollapseWithMarginBefore()) {
1768 // We can no longer collapse with the top of the block since a clear
1769 // occurred. The empty blocks collapse into the cleared block.
1770 // FIXME: This isn't quite correct. Need clarification for what to do
1771 // if the height the cleared block is offset by is smaller than the
1772 // margins involved.
1773 setMaxMarginBeforeValues(oldTopPosMargin, oldTopNegMargin);
1774 marginInfo.setAtBeforeSideOfBlock(false);
1777 return yPos + heightIncrease;
1780 LayoutUnit RenderBlock::estimateLogicalTopPosition(RenderBox* child, const MarginInfo& marginInfo, LayoutUnit& estimateWithoutPagination)
1782 // FIXME: We need to eliminate the estimation of vertical position, because when it's wrong we sometimes trigger a pathological
1783 // relayout if there are intruding floats.
1784 LayoutUnit logicalTopEstimate = logicalHeight();
1785 if (!marginInfo.canCollapseWithMarginBefore()) {
1786 LayoutUnit childMarginBefore = child->selfNeedsLayout() ? marginBeforeForChild(child) : collapsedMarginBeforeForChild(child);
1787 logicalTopEstimate += max(marginInfo.margin(), childMarginBefore);
1790 // Adjust logicalTopEstimate down to the next page if the margins are so large that we don't fit on the current
1792 LayoutState* layoutState = view()->layoutState();
1793 if (layoutState->isPaginated() && layoutState->pageLogicalHeight() && logicalTopEstimate > logicalHeight()
1794 && hasNextPage(logicalHeight()))
1795 logicalTopEstimate = min(logicalTopEstimate, nextPageLogicalTop(logicalHeight()));
1797 logicalTopEstimate += getClearDelta(child, logicalTopEstimate);
1799 estimateWithoutPagination = logicalTopEstimate;
1801 if (layoutState->isPaginated()) {
1802 // If the object has a page or column break value of "before", then we should shift to the top of the next page.
1803 logicalTopEstimate = applyBeforeBreak(child, logicalTopEstimate);
1805 // For replaced elements and scrolled elements, we want to shift them to the next page if they don't fit on the current one.
1806 logicalTopEstimate = adjustForUnsplittableChild(child, logicalTopEstimate);
1808 if (!child->selfNeedsLayout() && child->isRenderBlock())
1809 logicalTopEstimate += toRenderBlock(child)->paginationStrut();
1812 return logicalTopEstimate;
1815 LayoutUnit RenderBlock::computeStartPositionDeltaForChildAvoidingFloats(const RenderBox* child, LayoutUnit childMarginStart,
1816 LayoutUnit childLogicalWidth, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage)
1818 LayoutUnit startPosition = startOffsetForContent(region, offsetFromLogicalTopOfFirstPage);
1820 // Add in our start margin.
1821 LayoutUnit oldPosition = startPosition + childMarginStart;
1822 LayoutUnit newPosition = oldPosition;
1824 LayoutUnit blockOffset = logicalTopForChild(child);
1826 blockOffset = max(blockOffset, blockOffset + (region->offsetFromLogicalTopOfFirstPage() - offsetFromLogicalTopOfFirstPage));
1828 LayoutUnit startOff = startOffsetForLine(blockOffset, false, region, offsetFromLogicalTopOfFirstPage);
1829 if (style()->textAlign() != WEBKIT_CENTER && !child->style()->marginStartUsing(style()).isAuto()) {
1830 if (childMarginStart < 0)
1831 startOff += childMarginStart;
1832 newPosition = max(newPosition, startOff); // Let the float sit in the child's margin if it can fit.
1833 // FIXME: Needs to use epsilon once we switch to float, see https://bugs.webkit.org/show_bug.cgi?id=64021
1834 } else if (startOff != startPosition) {
1835 // The object is shifting to the "end" side of the block. The object might be centered, so we need to
1836 // recalculate our inline direction margins. Note that the containing block content
1837 // width computation will take into account the delta between |startOff| and |startPosition|
1838 // so that we can just pass the content width in directly to the |computeMarginsInContainingBlockInlineDirection|
1840 LayoutUnit oldMarginStart = marginStartForChild(child);
1841 LayoutUnit oldMarginEnd = marginEndForChild(child);
1842 RenderBox* mutableChild = const_cast<RenderBox*>(child);
1843 mutableChild->computeInlineDirectionMargins(this,
1844 availableLogicalWidthForLine(blockOffset, false, region, offsetFromLogicalTopOfFirstPage), childLogicalWidth);
1845 newPosition = startOff + marginStartForChild(child);
1846 if (inRenderFlowThread()) {
1847 setMarginStartForChild(mutableChild, oldMarginStart);
1848 setMarginEndForChild(mutableChild, oldMarginEnd);
1852 return newPosition - oldPosition;
1855 void RenderBlock::determineLogicalLeftPositionForChild(RenderBox* child)
1857 LayoutUnit startPosition = borderStart() + paddingStart();
1858 LayoutUnit totalAvailableLogicalWidth = borderAndPaddingLogicalWidth() + availableLogicalWidth();
1860 // Add in our start margin.
1861 LayoutUnit childMarginStart = marginStartForChild(child);
1862 LayoutUnit newPosition = startPosition + childMarginStart;
1864 // Some objects (e.g., tables, horizontal rules, overflow:auto blocks) avoid floats. They need
1865 // to shift over as necessary to dodge any floats that might get in the way.
1866 if (child->avoidsFloats() && containsFloats() && !inRenderFlowThread())
1867 newPosition += computeStartPositionDeltaForChildAvoidingFloats(child, marginStartForChild(child), logicalWidthForChild(child));
1869 setLogicalLeftForChild(child, style()->isLeftToRightDirection() ? newPosition : totalAvailableLogicalWidth - newPosition - logicalWidthForChild(child), ApplyLayoutDelta);
1872 void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo)
1874 if (marginInfo.canCollapseWithMarginAfter() && !marginInfo.canCollapseWithMarginBefore()) {
1875 // Update our max pos/neg bottom margins, since we collapsed our bottom margins
1876 // with our children.
1877 setMaxMarginAfterValues(max(maxPositiveMarginAfter(), marginInfo.positiveMargin()), max(maxNegativeMarginAfter(), marginInfo.negativeMargin()));
1879 if (!marginInfo.marginAfterQuirk())
1880 setMarginAfterQuirk(false);
1882 if (marginInfo.marginAfterQuirk() && marginAfter() == 0)
1883 // We have no bottom margin and our last child has a quirky margin.
1884 // We will pick up this quirky margin and pass it through.
1885 // This deals with the <td><div><p> case.
1886 setMarginAfterQuirk(true);
1890 void RenderBlock::handleAfterSideOfBlock(LayoutUnit beforeSide, LayoutUnit afterSide, MarginInfo& marginInfo)
1892 marginInfo.setAtAfterSideOfBlock(true);
1894 // If we can't collapse with children then go ahead and add in the bottom margin.
1895 if (!marginInfo.canCollapseWithMarginAfter() && !marginInfo.canCollapseWithMarginBefore()
1896 && (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !marginInfo.marginAfterQuirk()))
1897 setLogicalHeight(logicalHeight() + marginInfo.margin());
1899 // Now add in our bottom border/padding.
1900 setLogicalHeight(logicalHeight() + afterSide);
1902 // Negative margins can cause our height to shrink below our minimal height (border/padding).
1903 // If this happens, ensure that the computed height is increased to the minimal height.
1904 setLogicalHeight(max(logicalHeight(), beforeSide + afterSide));
1906 // Update our bottom collapsed margin info.
1907 setCollapsedBottomMargin(marginInfo);
1910 void RenderBlock::setLogicalLeftForChild(RenderBox* child, LayoutUnit logicalLeft, ApplyLayoutDeltaMode applyDelta)
1912 if (isHorizontalWritingMode()) {
1913 if (applyDelta == ApplyLayoutDelta)
1914 view()->addLayoutDelta(LayoutSize(child->x() - logicalLeft, 0));
1915 child->setX(logicalLeft);
1917 if (applyDelta == ApplyLayoutDelta)
1918 view()->addLayoutDelta(LayoutSize(0, child->y() - logicalLeft));
1919 child->setY(logicalLeft);
1923 void RenderBlock::setLogicalTopForChild(RenderBox* child, LayoutUnit logicalTop, ApplyLayoutDeltaMode applyDelta)
1925 if (isHorizontalWritingMode()) {
1926 if (applyDelta == ApplyLayoutDelta)
1927 view()->addLayoutDelta(LayoutSize(0, child->y() - logicalTop));
1928 child->setY(logicalTop);
1930 if (applyDelta == ApplyLayoutDelta)
1931 view()->addLayoutDelta(LayoutSize(child->x() - logicalTop, 0));
1932 child->setX(logicalTop);
1936 void RenderBlock::layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloatLogicalBottom)
1938 if (gPercentHeightDescendantsMap) {
1939 if (HashSet<RenderBox*>* descendants = gPercentHeightDescendantsMap->get(this)) {
1940 HashSet<RenderBox*>::iterator end = descendants->end();
1941 for (HashSet<RenderBox*>::iterator it = descendants->begin(); it != end; ++it) {
1942 RenderBox* box = *it;
1943 while (box != this) {
1944 if (box->normalChildNeedsLayout())
1946 box->setChildNeedsLayout(true, false);
1947 box = box->containingBlock();
1956 LayoutUnit beforeEdge = borderBefore() + paddingBefore();
1957 LayoutUnit afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeight();
1959 setLogicalHeight(beforeEdge);
1961 // The margin struct caches all our current margin collapsing state. The compact struct caches state when we encounter compacts,
1962 MarginInfo marginInfo(this, beforeEdge, afterEdge);
1964 // Fieldsets need to find their legend and position it inside the border of the object.
1965 // The legend then gets skipped during normal layout. The same is true for ruby text.
1966 // It doesn't get included in the normal layout process but is instead skipped.
1967 RenderObject* childToExclude = layoutSpecialExcludedChild(relayoutChildren);
1969 LayoutUnit previousFloatLogicalBottom = 0;
1970 maxFloatLogicalBottom = 0;
1972 RenderBox* next = firstChildBox();
1975 RenderBox* child = next;
1976 next = child->nextSiblingBox();
1978 if (childToExclude == child)
1979 continue; // Skip this child, since it will be positioned by the specialized subclass (fieldsets and ruby runs).
1981 // Make sure we layout children if they need it.
1982 // FIXME: Technically percentage height objects only need a relayout if their percentage isn't going to be turned into
1983 // an auto value. Add a method to determine this, so that we can avoid the relayout.
1984 if (relayoutChildren || ((child->style()->logicalHeight().isPercent() || child->style()->logicalMinHeight().isPercent() || child->style()->logicalMaxHeight().isPercent()) && !isRenderView()))
1985 child->setChildNeedsLayout(true, false);
1987 // If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths.
1988 if (relayoutChildren && child->needsPreferredWidthsRecalculation())
1989 child->setPreferredLogicalWidthsDirty(true, false);
1991 // Handle the four types of special elements first. These include positioned content, floating content, compacts and
1992 // run-ins. When we encounter these four types of objects, we don't actually lay them out as normal flow blocks.
1993 if (handleSpecialChild(child, marginInfo))
1996 // Lay out the child.
1997 layoutBlockChild(child, marginInfo, previousFloatLogicalBottom, maxFloatLogicalBottom);
2000 // Now do the handling of the bottom of the block, adding in our bottom border/padding and
2001 // determining the correct collapsed bottom margin information.
2002 handleAfterSideOfBlock(beforeEdge, afterEdge, marginInfo);
2005 void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom)
2007 LayoutUnit oldPosMarginBefore = maxPositiveMarginBefore();
2008 LayoutUnit oldNegMarginBefore = maxNegativeMarginBefore();
2010 // The child is a normal flow object. Compute the margins we will use for collapsing now.
2011 child->computeBlockDirectionMargins(this);
2013 // Do not allow a collapse if the margin-before-collapse style is set to SEPARATE.
2014 if (child->style()->marginBeforeCollapse() == MSEPARATE) {
2015 marginInfo.setAtBeforeSideOfBlock(false);
2016 marginInfo.clearMargin();
2019 // Try to guess our correct logical top position. In most cases this guess will
2020 // be correct. Only if we're wrong (when we compute the real logical top position)
2021 // will we have to potentially relayout.
2022 LayoutUnit estimateWithoutPagination;
2023 LayoutUnit logicalTopEstimate = estimateLogicalTopPosition(child, marginInfo, estimateWithoutPagination);
2025 // Cache our old rect so that we can dirty the proper repaint rects if the child moves.
2026 LayoutRect oldRect(child->x(), child->y() , child->width(), child->height());
2027 LayoutUnit oldLogicalTop = logicalTopForChild(child);
2030 LayoutSize oldLayoutDelta = view()->layoutDelta();
2032 // Go ahead and position the child as though it didn't collapse with the top.
2033 setLogicalTopForChild(child, logicalTopEstimate, ApplyLayoutDelta);
2035 RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
2036 bool markDescendantsWithFloats = false;
2037 if (logicalTopEstimate != oldLogicalTop && !child->avoidsFloats() && childRenderBlock && childRenderBlock->containsFloats())
2038 markDescendantsWithFloats = true;
2039 else if (!child->avoidsFloats() || child->shrinkToAvoidFloats()) {
2040 // If an element might be affected by the presence of floats, then always mark it for
2042 LayoutUnit fb = max(previousFloatLogicalBottom, lowestFloatLogicalBottomIncludingPositionedFloats());
2043 if (fb > logicalTopEstimate)
2044 markDescendantsWithFloats = true;
2047 if (childRenderBlock) {
2048 if (markDescendantsWithFloats)
2049 childRenderBlock->markAllDescendantsWithFloatsForLayout();
2050 if (!child->isWritingModeRoot())
2051 previousFloatLogicalBottom = max(previousFloatLogicalBottom, oldLogicalTop + childRenderBlock->lowestFloatLogicalBottomIncludingPositionedFloats());
2054 if (!child->needsLayout())
2055 child->markForPaginationRelayoutIfNeeded();
2057 bool childHadLayout = child->m_everHadLayout;
2058 bool childNeededLayout = child->needsLayout();
2059 if (childNeededLayout)
2062 // Cache if we are at the top of the block right now.
2063 bool atBeforeSideOfBlock = marginInfo.atBeforeSideOfBlock();
2065 // Now determine the correct ypos based off examination of collapsing margin
2067 LayoutUnit logicalTopBeforeClear = collapseMargins(child, marginInfo);
2069 // Now check for clear.
2070 LayoutUnit logicalTopAfterClear = clearFloatsIfNeeded(child, marginInfo, oldPosMarginBefore, oldNegMarginBefore, logicalTopBeforeClear);
2072 bool paginated = view()->layoutState()->isPaginated();
2074 logicalTopAfterClear = adjustBlockChildForPagination(logicalTopAfterClear, estimateWithoutPagination, child,
2075 atBeforeSideOfBlock && logicalTopBeforeClear == logicalTopAfterClear);
2077 setLogicalTopForChild(child, logicalTopAfterClear, ApplyLayoutDelta);
2079 // Now we have a final top position. See if it really does end up being different from our estimate.
2080 if (logicalTopAfterClear != logicalTopEstimate) {
2081 if (child->shrinkToAvoidFloats()) {
2082 // The child's width depends on the line width.
2083 // When the child shifts to clear an item, its width can
2084 // change (because it has more available line width).
2085 // So go ahead and mark the item as dirty.
2086 child->setChildNeedsLayout(true, false);
2089 if (childRenderBlock) {
2090 if (!child->avoidsFloats() && childRenderBlock->containsFloats())
2091 childRenderBlock->markAllDescendantsWithFloatsForLayout();
2092 if (!child->needsLayout())
2093 child->markForPaginationRelayoutIfNeeded();
2096 // Our guess was wrong. Make the child lay itself out again.
2097 child->layoutIfNeeded();
2100 // We are no longer at the top of the block if we encounter a non-empty child.
2101 // This has to be done after checking for clear, so that margins can be reset if a clear occurred.
2102 if (marginInfo.atBeforeSideOfBlock() && !child->isSelfCollapsingBlock())
2103 marginInfo.setAtBeforeSideOfBlock(false);
2105 // Now place the child in the correct left position
2106 determineLogicalLeftPositionForChild(child);
2108 // Update our height now that the child has been placed in the correct position.
2109 setLogicalHeight(logicalHeight() + logicalHeightForChild(child));
2110 if (child->style()->marginAfterCollapse() == MSEPARATE) {
2111 setLogicalHeight(logicalHeight() + marginAfterForChild(child));
2112 marginInfo.clearMargin();
2114 // If the child has overhanging floats that intrude into following siblings (or possibly out
2115 // of this block), then the parent gets notified of the floats now.
2116 if (childRenderBlock && childRenderBlock->containsFloats())
2117 maxFloatLogicalBottom = max(maxFloatLogicalBottom, addOverhangingFloats(toRenderBlock(child), !childNeededLayout));
2119 LayoutSize childOffset(child->x() - oldRect.x(), child->y() - oldRect.y());
2120 if (childOffset.width() || childOffset.height()) {
2121 view()->addLayoutDelta(childOffset);
2123 // If the child moved, we have to repaint it as well as any floating/positioned
2124 // descendants. An exception is if we need a layout. In this case, we know we're going to
2125 // repaint ourselves (and the child) anyway.
2126 if (childHadLayout && !selfNeedsLayout() && child->checkForRepaintDuringLayout())
2127 child->repaintDuringLayoutIfMoved(oldRect);
2130 if (!childHadLayout && child->checkForRepaintDuringLayout()) {
2132 child->repaintOverhangingFloats(true);
2136 // Check for an after page/column break.
2137 LayoutUnit newHeight = applyAfterBreak(child, logicalHeight(), marginInfo);
2138 if (newHeight != height())
2139 setLogicalHeight(newHeight);
2142 // FIXME: Change to use roughlyEquals when we move to float.
2143 // See https://bugs.webkit.org/show_bug.cgi?id=66148
2144 ASSERT(oldLayoutDelta == view()->layoutDelta());
2147 void RenderBlock::simplifiedNormalFlowLayout()
2149 if (childrenInline()) {
2150 ListHashSet<RootInlineBox*> lineBoxes;
2151 for (InlineWalker walker(this); !walker.atEnd(); walker.advance()) {
2152 RenderObject* o = walker.current();
2153 if (!o->isPositioned() && (o->isReplaced() || o->isFloating())) {
2154 o->layoutIfNeeded();
2155 if (toRenderBox(o)->inlineBoxWrapper()) {
2156 RootInlineBox* box = toRenderBox(o)->inlineBoxWrapper()->root();
2159 } else if (o->isText() || (o->isRenderInline() && !walker.atEndOfInline()))
2160 o->setNeedsLayout(false);
2163 // FIXME: Glyph overflow will get lost in this case, but not really a big deal.
2164 GlyphOverflowAndFallbackFontsMap textBoxDataMap;
2165 for (ListHashSet<RootInlineBox*>::const_iterator it = lineBoxes.begin(); it != lineBoxes.end(); ++it) {
2166 RootInlineBox* box = *it;
2167 box->computeOverflow(box->lineTop(), box->lineBottom(), textBoxDataMap);
2170 for (RenderBox* box = firstChildBox(); box; box = box->nextSiblingBox()) {
2171 if (!box->isPositioned())
2172 box->layoutIfNeeded();
2177 bool RenderBlock::simplifiedLayout()
2179 if ((!posChildNeedsLayout() && !needsSimplifiedNormalFlowLayout()) || normalChildNeedsLayout() || selfNeedsLayout())
2182 LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
2184 if (needsPositionedMovementLayout() && !tryLayoutDoingPositionedMovementOnly())
2187 // Lay out positioned descendants or objects that just need to recompute overflow.
2188 if (needsSimplifiedNormalFlowLayout())
2189 simplifiedNormalFlowLayout();
2191 // Lay out our positioned objects if our positioned child bit is set.
2192 if (posChildNeedsLayout() && layoutPositionedObjects(false))
2193 return false; // If a positioned float is causing our normal flow to change, then we have to bail and do a full layout.
2195 // Recompute our overflow information.
2196 // FIXME: We could do better here by computing a temporary overflow object from layoutPositionedObjects and only
2197 // updating our overflow if we either used to have overflow or if the new temporary object has overflow.
2198 // For now just always recompute overflow. This is no worse performance-wise than the old code that called rightmostPosition and
2199 // lowestPosition on every relayout so it's not a regression.
2201 computeOverflow(clientLogicalBottom(), true);
2205 updateLayerTransform();
2207 updateScrollInfoAfterLayout();
2209 setNeedsLayout(false);
2213 bool RenderBlock::positionedFloatsNeedRelayout()
2215 if (!hasPositionedFloats())
2218 RenderBox* positionedObject;
2219 Iterator end = m_positionedObjects->end();
2220 for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
2221 positionedObject = *it;
2222 if (!positionedObject->isFloating())
2225 if (positionedObject->needsLayout())
2228 if (positionedObject->style()->hasStaticBlockPosition(isHorizontalWritingMode()) && positionedObject->parent() != this && positionedObject->parent()->isBlockFlow())
2231 if (view()->layoutState()->pageLogicalHeightChanged() || (view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(logicalTop()) != pageLogicalOffset()))
2238 bool RenderBlock::layoutPositionedObjects(bool relayoutChildren)
2240 if (!m_positionedObjects)
2244 view()->layoutState()->clearPaginationInformation(); // Positioned objects are not part of the column flow, so they don't paginate with the columns.
2246 bool didFloatingBoxRelayout = false;
2249 Iterator end = m_positionedObjects->end();
2250 for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
2252 // When a non-positioned block element moves, it may have positioned children that are implicitly positioned relative to the
2253 // non-positioned block. Rather than trying to detect all of these movement cases, we just always lay out positioned
2254 // objects that are positioned implicitly like this. Such objects are rare, and so in typical DHTML menu usage (where everything is
2255 // positioned explicitly) this should not incur a performance penalty.
2256 if (relayoutChildren || (r->style()->hasStaticBlockPosition(isHorizontalWritingMode()) && r->parent() != this))
2257 r->setChildNeedsLayout(true, false);
2259 // If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths.
2260 if (relayoutChildren && r->needsPreferredWidthsRecalculation())
2261 r->setPreferredLogicalWidthsDirty(true, false);
2263 if (!r->needsLayout())
2264 r->markForPaginationRelayoutIfNeeded();
2266 // FIXME: Technically we could check the old placement and the new placement of the box and only invalidate if
2267 // the margin box of the object actually changed.
2268 if (r->needsLayout() && r->isFloating())
2269 didFloatingBoxRelayout = true;
2271 // 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
2272 // and we hit the available width constraint, the layoutIfNeeded() will catch it and do a full layout.
2273 if (r->needsPositionedMovementLayoutOnly() && r->tryLayoutDoingPositionedMovementOnly())
2274 r->setNeedsLayout(false);
2276 // If we are in a flow thread, go ahead and compute a vertical position for our object now.
2277 // If it's wrong we'll lay out again.
2278 LayoutUnit oldLogicalTop = 0;
2279 bool checkForPaginationRelayout = r->needsLayout() && view()->layoutState()->isPaginated() && view()->layoutState()->pageLogicalHeight();
2280 if (checkForPaginationRelayout) {
2281 if (isHorizontalWritingMode() == r->isHorizontalWritingMode())
2282 r->computeLogicalHeight();
2284 r->computeLogicalWidth();
2285 oldLogicalTop = logicalTopForChild(r);
2288 r->layoutIfNeeded();
2290 // Lay out again if our estimate was wrong.
2291 if (checkForPaginationRelayout && logicalTopForChild(r) != oldLogicalTop) {
2292 r->setChildNeedsLayout(true, false);
2293 r->layoutIfNeeded();
2298 view()->layoutState()->m_columnInfo = columnInfo(); // FIXME: Kind of gross. We just put this back into the layout state so that pop() will work.
2300 return didFloatingBoxRelayout;
2303 void RenderBlock::markPositionedObjectsForLayout()
2305 if (m_positionedObjects) {
2307 Iterator end = m_positionedObjects->end();
2308 for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
2310 r->setChildNeedsLayout(true);
2315 void RenderBlock::markForPaginationRelayoutIfNeeded()
2317 ASSERT(!needsLayout());
2321 if (view()->layoutState()->pageLogicalHeightChanged() || (view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(logicalTop()) != pageLogicalOffset()))
2322 setChildNeedsLayout(true, false);
2325 void RenderBlock::repaintOverhangingFloats(bool paintAllDescendants)
2327 // Repaint any overhanging floats (if we know we're the one to paint them).
2328 // Otherwise, bail out.
2329 if (!hasOverhangingFloats())
2332 // FIXME: Avoid disabling LayoutState. At the very least, don't disable it for floats originating
2333 // in this block. Better yet would be to push extra state for the containers of other floats.
2334 LayoutStateDisabler layoutStateDisabler(view());
2335 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
2336 FloatingObjectSetIterator end = floatingObjectSet.end();
2337 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
2338 FloatingObject* r = *it;
2339 // Only repaint the object if it is overhanging, is not in its own layer, and
2340 // is our responsibility to paint (m_shouldPaint is set). When paintAllDescendants is true, the latter
2341 // condition is replaced with being a descendant of us.
2342 if (logicalBottomForFloat(r) > logicalHeight() && ((paintAllDescendants && r->m_renderer->isDescendantOf(this)) || r->m_shouldPaint) && !r->m_renderer->hasSelfPaintingLayer()) {
2343 r->m_renderer->repaint();
2344 r->m_renderer->repaintOverhangingFloats();
2349 void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
2351 LayoutPoint adjustedPaintOffset = paintOffset + location();
2353 PaintPhase phase = paintInfo.phase;
2355 // Check if we need to do anything at all.
2356 // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
2357 // paints the root's background.
2359 LayoutRect overflowBox = visualOverflowRect();
2360 flipForWritingMode(overflowBox);
2361 overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
2362 overflowBox.moveBy(adjustedPaintOffset);
2363 if (!overflowBox.intersects(paintInfo.rect))
2367 bool pushedClip = pushContentsClip(paintInfo, adjustedPaintOffset);
2368 paintObject(paintInfo, adjustedPaintOffset);
2370 popContentsClip(paintInfo, phase, adjustedPaintOffset);
2372 // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
2373 // z-index. We paint after we painted the background/border, so that the scrollbars will
2374 // sit above the background/border.
2375 if (hasOverflowClip() && style()->visibility() == VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground) && paintInfo.shouldPaintWithinRoot(this))
2376 layer()->paintOverflowControls(paintInfo.context, adjustedPaintOffset, paintInfo.rect);
2379 void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
2381 if (paintInfo.context->paintingDisabled())
2384 const Color& ruleColor = style()->visitedDependentColor(CSSPropertyWebkitColumnRuleColor);
2385 bool ruleTransparent = style()->columnRuleIsTransparent();
2386 EBorderStyle ruleStyle = style()->columnRuleStyle();
2387 LayoutUnit ruleWidth = style()->columnRuleWidth();
2388 LayoutUnit colGap = columnGap();
2389 bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent && ruleWidth <= colGap;
2393 // We need to do multiple passes, breaking up our child painting into strips.
2394 ColumnInfo* colInfo = columnInfo();
2395 unsigned colCount = columnCount(colInfo);
2396 LayoutUnit currLogicalLeftOffset = style()->isLeftToRightDirection() ? 0 : contentLogicalWidth();
2397 LayoutUnit ruleAdd = logicalLeftOffsetForContent();
2398 LayoutUnit ruleLogicalLeft = style()->isLeftToRightDirection() ? 0 : contentLogicalWidth();
2400 bool antialias = shouldAntialiasLines(paintInfo.context);
2401 LayoutUnit inlineDirectionSize = colInfo->desiredColumnWidth();
2403 for (unsigned i = 0; i < colCount; i++) {
2404 // Move to the next position.
2405 if (style()->isLeftToRightDirection()) {
2406 ruleLogicalLeft += inlineDirectionSize + colGap / 2;
2407 currLogicalLeftOffset += inlineDirectionSize + colGap;
2409 ruleLogicalLeft -= (inlineDirectionSize + colGap / 2);
2410 currLogicalLeftOffset -= (inlineDirectionSize + colGap);
2413 // Now paint the column rule.
2414 if (i < colCount - 1) {
2415 LayoutUnit ruleLeft = isHorizontalWritingMode() ? paintOffset.x() + ruleLogicalLeft - ruleWidth / 2 + ruleAdd : paintOffset.x() + borderLeft() + paddingLeft();
2416 LayoutUnit ruleRight = isHorizontalWritingMode() ? ruleLeft + ruleWidth : ruleLeft + contentWidth();
2417 LayoutUnit ruleTop = isHorizontalWritingMode() ? paintOffset.y() + borderTop() + paddingTop() : paintOffset.y() + ruleLogicalLeft - ruleWidth / 2 + ruleAdd;
2418 LayoutUnit ruleBottom = isHorizontalWritingMode() ? ruleTop + contentHeight() : ruleTop + ruleWidth;
2419 BoxSide side = isHorizontalWritingMode()
2420 ? style()->isLeftToRightDirection() ? BSLeft : BSRight
2421 : style()->isLeftToRightDirection() ? BSTop : BSBottom;
2422 drawLineForBoxSide(paintInfo.context, ruleLeft, ruleTop, ruleRight, ruleBottom, side, ruleColor, ruleStyle, 0, 0, antialias);
2425 ruleLogicalLeft = currLogicalLeftOffset;
2429 void RenderBlock::paintColumnContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset, bool paintingFloats)
2431 // We need to do multiple passes, breaking up our child painting into strips.
2432 GraphicsContext* context = paintInfo.context;
2433 ColumnInfo* colInfo = columnInfo();
2434 unsigned colCount = columnCount(colInfo);
2437 LayoutUnit currLogicalTopOffset = 0;
2438 for (unsigned i = 0; i < colCount; i++) {
2439 // For each rect, we clip to the rect, and then we adjust our coords.
2440 LayoutRect colRect = columnRectAt(colInfo, i);
2441 flipForWritingMode(colRect);
2442 LayoutUnit logicalLeftOffset = (isHorizontalWritingMode() ? colRect.x() : colRect.y()) - logicalLeftOffsetForContent();
2443 LayoutSize offset = isHorizontalWritingMode() ? LayoutSize(logicalLeftOffset, currLogicalTopOffset) : LayoutSize(currLogicalTopOffset, logicalLeftOffset);
2444 colRect.moveBy(paintOffset);
2445 PaintInfo info(paintInfo);
2446 info.rect.intersect(colRect);
2448 if (!info.rect.isEmpty()) {
2449 GraphicsContextStateSaver stateSaver(*context);
2451 // Each strip pushes a clip, since column boxes are specified as being
2452 // like overflow:hidden.
2453 context->clip(colRect);
2455 // Adjust our x and y when painting.
2456 LayoutPoint adjustedPaintOffset = paintOffset + offset;
2458 paintFloats(info, adjustedPaintOffset, paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip);
2460 paintContents(info, adjustedPaintOffset);
2463 LayoutUnit blockDelta = (isHorizontalWritingMode() ? colRect.height() : colRect.width());
2464 if (style()->isFlippedBlocksWritingMode())
2465 currLogicalTopOffset += blockDelta;
2467 currLogicalTopOffset -= blockDelta;
2471 void RenderBlock::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
2473 // Avoid painting descendants of the root element when stylesheets haven't loaded. This eliminates FOUC.
2474 // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
2475 // will do a full repaint().
2476 if (document()->didLayoutWithPendingStylesheets() && !isRenderView())
2479 if (childrenInline())
2480 m_lineBoxes.paint(this, paintInfo, paintOffset);
2482 paintChildren(paintInfo, paintOffset);
2485 void RenderBlock::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
2487 PaintPhase newPhase = (paintInfo.phase == PaintPhaseChildOutlines) ? PaintPhaseOutline : paintInfo.phase;
2488 newPhase = (newPhase == PaintPhaseChildBlockBackgrounds) ? PaintPhaseChildBlockBackground : newPhase;
2490 // We don't paint our own background, but we do let the kids paint their backgrounds.
2491 PaintInfo info(paintInfo);
2492 info.phase = newPhase;
2493 info.updatePaintingRootForChildren(this);
2495 // FIXME: Paint-time pagination is obsolete and is now only used by embedded WebViews inside AppKit
2496 // NSViews. Do not add any more code for this.
2497 RenderView* renderView = view();
2498 bool usePrintRect = !renderView->printRect().isEmpty();
2500 for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
2501 // Check for page-break-before: always, and if it's set, break and bail.
2502 bool checkBeforeAlways = !childrenInline() && (usePrintRect && child->style()->pageBreakBefore() == PBALWAYS);
2503 LayoutUnit absoluteChildY = paintOffset.y() + child->y();
2504 if (checkBeforeAlways
2505 && absoluteChildY > paintInfo.rect.y()
2506 && absoluteChildY < paintInfo.rect.maxY()) {
2507 view()->setBestTruncatedAt(absoluteChildY, this, true);
2511 if (!child->isFloating() && child->isReplaced() && usePrintRect && child->height() <= renderView->printRect().height()) {
2512 // Paginate block-level replaced elements.
2513 if (absoluteChildY + child->height() > renderView->printRect().maxY()) {
2514 if (absoluteChildY < renderView->truncatedAt())
2515 renderView->setBestTruncatedAt(absoluteChildY, child);
2516 // If we were able to truncate, don't paint.
2517 if (absoluteChildY >= renderView->truncatedAt())
2522 LayoutPoint childPoint = flipForWritingModeForChild(child, paintOffset);
2523 if (!child->hasSelfPaintingLayer() && !child->isFloating())
2524 child->paint(info, childPoint);
2526 // Check for page-break-after: always, and if it's set, break and bail.
2527 bool checkAfterAlways = !childrenInline() && (usePrintRect && child->style()->pageBreakAfter() == PBALWAYS);
2528 if (checkAfterAlways
2529 && (absoluteChildY + child->height()) > paintInfo.rect.y()
2530 && (absoluteChildY + child->height()) < paintInfo.rect.maxY()) {
2531 view()->setBestTruncatedAt(absoluteChildY + child->height() + max<LayoutUnit>(0, child->collapsedMarginAfter()), this, true);
2537 void RenderBlock::paintCaret(PaintInfo& paintInfo, const LayoutPoint& paintOffset, CaretType type)
2539 // Paint the caret if the FrameSelection says so or if caret browsing is enabled
2540 bool caretBrowsing = frame()->settings() && frame()->settings()->caretBrowsingEnabled();
2541 RenderObject* caretPainter;
2542 bool isContentEditable;
2543 if (type == CursorCaret) {
2544 caretPainter = frame()->selection()->caretRenderer();
2545 isContentEditable = frame()->selection()->isContentEditable();
2547 caretPainter = frame()->page()->dragCaretController()->caretRenderer();
2548 isContentEditable = frame()->page()->dragCaretController()->isContentEditable();
2551 if (caretPainter == this && (isContentEditable || caretBrowsing)) {
2552 // Convert the painting offset into the local coordinate system of this renderer,
2553 // to match the localCaretRect computed by the FrameSelection
2554 LayoutPoint adjustedPaintOffset = paintOffset;
2555 offsetForContents(adjustedPaintOffset);
2557 if (type == CursorCaret)
2558 frame()->selection()->paintCaret(paintInfo.context, adjustedPaintOffset, paintInfo.rect);
2560 frame()->page()->dragCaretController()->paintDragCaret(frame(), paintInfo.context, adjustedPaintOffset, paintInfo.rect);
2564 void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
2566 PaintPhase paintPhase = paintInfo.phase;
2568 // 1. paint background, borders etc
2569 if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && style()->visibility() == VISIBLE) {
2570 if (hasBoxDecorations())
2571 paintBoxDecorations(paintInfo, paintOffset);
2573 paintColumnRules(paintInfo, paintOffset);
2576 if (paintPhase == PaintPhaseMask && style()->visibility() == VISIBLE) {
2577 paintMask(paintInfo, paintOffset);
2581 // We're done. We don't bother painting any children.
2582 if (paintPhase == PaintPhaseBlockBackground)
2585 // Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div).
2586 LayoutPoint scrolledOffset = paintOffset;
2587 if (hasOverflowClip())
2588 scrolledOffset.move(-layer()->scrolledContentOffset());
2590 // 2. paint contents
2591 if (paintPhase != PaintPhaseSelfOutline) {
2593 paintColumnContents(paintInfo, scrolledOffset);
2595 paintContents(paintInfo, scrolledOffset);
2598 // 3. paint selection
2599 // FIXME: Make this work with multi column layouts. For now don't fill gaps.
2600 bool isPrinting = document()->printing();
2601 if (!isPrinting && !hasColumns())
2602 paintSelection(paintInfo, scrolledOffset); // Fill in gaps in selection on lines and between blocks.
2605 if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip) {
2607 paintColumnContents(paintInfo, scrolledOffset, true);
2609 paintFloats(paintInfo, scrolledOffset, paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip);
2612 // 5. paint outline.
2613 if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style()->visibility() == VISIBLE)
2614 paintOutline(paintInfo.context, LayoutRect(paintOffset, size()));
2616 // 6. paint continuation outlines.
2617 if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)) {
2618 RenderInline* inlineCont = inlineElementContinuation();
2619 if (inlineCont && inlineCont->hasOutline() && inlineCont->style()->visibility() == VISIBLE) {
2620 RenderInline* inlineRenderer = toRenderInline(inlineCont->node()->renderer());
2621 RenderBlock* cb = containingBlock();
2623 bool inlineEnclosedInSelfPaintingLayer = false;
2624 for (RenderBoxModelObject* box = inlineRenderer; box != cb; box = box->parent()->enclosingBoxModelObject()) {
2625 if (box->hasSelfPaintingLayer()) {
2626 inlineEnclosedInSelfPaintingLayer = true;
2631 if (!inlineEnclosedInSelfPaintingLayer)
2632 cb->addContinuationWithOutline(inlineRenderer);
2633 else if (!inlineRenderer->firstLineBox())
2634 inlineRenderer->paintOutline(paintInfo.context, paintOffset - locationOffset() + inlineRenderer->containingBlock()->location());
2636 paintContinuationOutlines(paintInfo, paintOffset);
2640 // If the caret's node's render object's containing block is this block, and the paint action is PaintPhaseForeground,
2641 // then paint the caret.
2642 if (paintPhase == PaintPhaseForeground) {
2643 paintCaret(paintInfo, scrolledOffset, CursorCaret);
2644 paintCaret(paintInfo, scrolledOffset, DragCaret);
2648 LayoutPoint RenderBlock::flipFloatForWritingModeForChild(const FloatingObject* child, const LayoutPoint& point) const
2650 if (!style()->isFlippedBlocksWritingMode())
2653 // This is similar to RenderBox::flipForWritingModeForChild. We have to subtract out our left/top offsets twice, since
2654 // it's going to get added back in. We hide this complication here so that the calling code looks normal for the unflipped
2656 if (isHorizontalWritingMode())
2657 return LayoutPoint(point.x(), point.y() + height() - child->renderer()->height() - 2 * yPositionForFloatIncludingMargin(child));
2658 return LayoutPoint(point.x() + width() - child->width() - 2 * xPositionForFloatIncludingMargin(child), point.y());
2661 void RenderBlock::paintFloats(PaintInfo& paintInfo, const LayoutPoint& paintOffset, bool preservePhase)
2663 if (!m_floatingObjects)
2666 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
2667 FloatingObjectSetIterator end = floatingObjectSet.end();
2668 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
2669 FloatingObject* r = *it;
2670 // Only paint the object if our m_shouldPaint flag is set.
2671 if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) {
2672 PaintInfo currentPaintInfo(paintInfo);
2673 currentPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
2674 LayoutPoint childPoint = flipFloatForWritingModeForChild(r, LayoutPoint(paintOffset.x() + xPositionForFloatIncludingMargin(r) - r->m_renderer->x(), paintOffset.y() + yPositionForFloatIncludingMargin(r) - r->m_renderer->y()));
2675 r->m_renderer->paint(currentPaintInfo, childPoint);
2676 if (!preservePhase) {
2677 currentPaintInfo.phase = PaintPhaseChildBlockBackgrounds;
2678 r->m_renderer->paint(currentPaintInfo, childPoint);
2679 currentPaintInfo.phase = PaintPhaseFloat;
2680 r->m_renderer->paint(currentPaintInfo, childPoint);
2681 currentPaintInfo.phase = PaintPhaseForeground;
2682 r->m_renderer->paint(currentPaintInfo, childPoint);
2683 currentPaintInfo.phase = PaintPhaseOutline;
2684 r->m_renderer->paint(currentPaintInfo, childPoint);
2690 void RenderBlock::paintEllipsisBoxes(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
2692 if (!paintInfo.shouldPaintWithinRoot(this) || !firstLineBox())
2695 if (style()->visibility() == VISIBLE && paintInfo.phase == PaintPhaseForeground) {
2696 // We can check the first box and last box and avoid painting if we don't
2698 LayoutUnit yPos = paintOffset.y() + firstLineBox()->y();
2699 LayoutUnit h = lastLineBox()->y() + lastLineBox()->logicalHeight() - firstLineBox()->y();
2700 if (yPos >= paintInfo.rect.maxY() || yPos + h <= paintInfo.rect.y())
2703 // See if our boxes intersect with the dirty rect. If so, then we paint
2704 // them. Note that boxes can easily overlap, so we can't make any assumptions
2705 // based off positions of our first line box or our last line box.
2706 for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
2707 yPos = paintOffset.y() + curr->y();
2708 h = curr->logicalHeight();
2709 if (curr->ellipsisBox() && yPos < paintInfo.rect.maxY() && yPos + h > paintInfo.rect.y())
2710 curr->paintEllipsisBox(paintInfo, paintOffset, curr->lineTop(), curr->lineBottom());
2715 RenderInline* RenderBlock::inlineElementContinuation() const
2717 RenderBoxModelObject* continuation = this->continuation();
2718 return continuation && continuation->isInline() ? toRenderInline(continuation) : 0;
2721 RenderBlock* RenderBlock::blockElementContinuation() const
2723 RenderBoxModelObject* currentContinuation = continuation();
2724 if (!currentContinuation || currentContinuation->isInline())
2726 RenderBlock* nextContinuation = toRenderBlock(currentContinuation);
2727 if (nextContinuation->isAnonymousBlock())
2728 return nextContinuation->blockElementContinuation();
2729 return nextContinuation;
2732 static ContinuationOutlineTableMap* continuationOutlineTable()
2734 DEFINE_STATIC_LOCAL(ContinuationOutlineTableMap, table, ());
2738 void RenderBlock::addContinuationWithOutline(RenderInline* flow)
2740 // We can't make this work if the inline is in a layer. We'll just rely on the broken
2742 ASSERT(!flow->layer() && !flow->isInlineElementContinuation());
2744 ContinuationOutlineTableMap* table = continuationOutlineTable();
2745 ListHashSet<RenderInline*>* continuations = table->get(this);
2746 if (!continuations) {
2747 continuations = new ListHashSet<RenderInline*>;
2748 table->set(this, continuations);
2751 continuations->add(flow);
2754 bool RenderBlock::paintsContinuationOutline(RenderInline* flow)
2756 ContinuationOutlineTableMap* table = continuationOutlineTable();
2757 if (table->isEmpty())
2760 ListHashSet<RenderInline*>* continuations = table->get(this);
2764 return continuations->contains(flow);
2767 void RenderBlock::paintContinuationOutlines(PaintInfo& info, const LayoutPoint& paintOffset)
2769 ContinuationOutlineTableMap* table = continuationOutlineTable();
2770 if (table->isEmpty())
2773 ListHashSet<RenderInline*>* continuations = table->get(this);
2777 LayoutPoint accumulatedPaintOffset = paintOffset;
2778 // Paint each continuation outline.
2779 ListHashSet<RenderInline*>::iterator end = continuations->end();
2780 for (ListHashSet<RenderInline*>::iterator it = continuations->begin(); it != end; ++it) {
2781 // Need to add in the coordinates of the intervening blocks.
2782 RenderInline* flow = *it;
2783 RenderBlock* block = flow->containingBlock();
2784 for ( ; block && block != this; block = block->containingBlock())
2785 accumulatedPaintOffset.moveBy(block->location());
2787 flow->paintOutline(info.context, accumulatedPaintOffset);
2791 delete continuations;
2792 table->remove(this);
2795 bool RenderBlock::shouldPaintSelectionGaps() const
2797 return selectionState() != SelectionNone && style()->visibility() == VISIBLE && isSelectionRoot();
2800 bool RenderBlock::isSelectionRoot() const
2805 // FIXME: Eventually tables should have to learn how to fill gaps between cells, at least in simple non-spanning cases.
2809 if (isBody() || isRoot() || hasOverflowClip() || isRelPositioned() ||
2810 isFloatingOrPositioned() || isTableCell() || isInlineBlockOrInlineTable() || hasTransform() ||
2811 hasReflection() || hasMask() || isWritingModeRoot())
2814 if (view() && view()->selectionStart()) {
2815 Node* startElement = view()->selectionStart()->node();
2816 if (startElement && startElement->rootEditableElement() == node())
2823 GapRects RenderBlock::selectionGapRectsForRepaint(RenderBoxModelObject* repaintContainer)
2825 ASSERT(!needsLayout());
2827 if (!shouldPaintSelectionGaps())
2830 // FIXME: this is broken with transforms
2831 TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint());
2832 mapLocalToContainer(repaintContainer, false, false, transformState);
2833 LayoutPoint offsetFromRepaintContainer = roundedLayoutPoint(transformState.mappedPoint());
2835 if (hasOverflowClip())
2836 offsetFromRepaintContainer -= layer()->scrolledContentOffset();
2838 LayoutUnit lastTop = 0;
2839 LayoutUnit lastLeft = logicalLeftSelectionOffset(this, lastTop);
2840 LayoutUnit lastRight = logicalRightSelectionOffset(this, lastTop);
2842 return selectionGaps(this, offsetFromRepaintContainer, IntSize(), lastTop, lastLeft, lastRight);
2845 void RenderBlock::paintSelection(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
2847 if (shouldPaintSelectionGaps() && paintInfo.phase == PaintPhaseForeground) {
2848 LayoutUnit lastTop = 0;
2849 LayoutUnit lastLeft = logicalLeftSelectionOffset(this, lastTop);
2850 LayoutUnit lastRight = logicalRightSelectionOffset(this, lastTop);
2851 GraphicsContextStateSaver stateSaver(*paintInfo.context);
2853 LayoutRect gapRectsBounds = selectionGaps(this, paintOffset, LayoutSize(), lastTop, lastLeft, lastRight, &paintInfo);
2854 if (!gapRectsBounds.isEmpty()) {
2855 if (RenderLayer* layer = enclosingLayer()) {
2856 gapRectsBounds.moveBy(-paintOffset);
2858 LayoutRect localBounds(gapRectsBounds);
2859 flipForWritingMode(localBounds);
2860 gapRectsBounds = localToContainerQuad(FloatRect(localBounds), layer->renderer()).enclosingBoundingBox();
2861 gapRectsBounds.move(layer->scrolledContentOffset());
2863 layer->addBlockSelectionGapsBounds(gapRectsBounds);
2869 static void clipOutPositionedObjects(const PaintInfo* paintInfo, const LayoutPoint& offset, RenderBlock::PositionedObjectsListHashSet* positionedObjects)
2871 if (!positionedObjects)
2874 RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end();
2875 for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
2877 paintInfo->context->clipOut(LayoutRect(offset.x() + r->x(), offset.y() + r->y(), r->width(), r->height()));
2881 static int blockDirectionOffset(RenderBlock* rootBlock, const LayoutSize& offsetFromRootBlock)
2883 return rootBlock->isHorizontalWritingMode() ? offsetFromRootBlock.height() : offsetFromRootBlock.width();
2886 static int inlineDirectionOffset(RenderBlock* rootBlock, const LayoutSize& offsetFromRootBlock)
2888 return rootBlock->isHorizontalWritingMode() ? offsetFromRootBlock.width() : offsetFromRootBlock.height();
2891 LayoutRect RenderBlock::logicalRectToPhysicalRect(const LayoutPoint& rootBlockPhysicalPosition, const LayoutRect& logicalRect)
2894 if (isHorizontalWritingMode())
2895 result = logicalRect;
2897 result = LayoutRect(logicalRect.y(), logicalRect.x(), logicalRect.height(), logicalRect.width());
2898 flipForWritingMode(result);
2899 result.moveBy(rootBlockPhysicalPosition);
2903 GapRects RenderBlock::selectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
2904 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* paintInfo)
2906 // IMPORTANT: Callers of this method that intend for painting to happen need to do a save/restore.
2907 // Clip out floating and positioned objects when painting selection gaps.
2909 // Note that we don't clip out overflow for positioned objects. We just stick to the border box.
2910 LayoutRect flippedBlockRect(offsetFromRootBlock.width(), offsetFromRootBlock.height(), width(), height());
2911 rootBlock->flipForWritingMode(flippedBlockRect);
2912 flippedBlockRect.moveBy(rootBlockPhysicalPosition);
2913 clipOutPositionedObjects(paintInfo, flippedBlockRect.location(), m_positionedObjects.get());
2914 if (isBody() || isRoot()) // The <body> must make sure to examine its containingBlock's positioned objects.
2915 for (RenderBlock* cb = containingBlock(); cb && !cb->isRenderView(); cb = cb->containingBlock())
2916 clipOutPositionedObjects(paintInfo, LayoutPoint(cb->x(), cb->y()), cb->m_positionedObjects.get()); // FIXME: Not right for flipped writing modes.
2917 if (m_floatingObjects) {
2918 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
2919 FloatingObjectSetIterator end = floatingObjectSet.end();
2920 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
2921 FloatingObject* r = *it;
2922 LayoutRect floatBox(offsetFromRootBlock.width() + xPositionForFloatIncludingMargin(r),
2923 offsetFromRootBlock.height() + yPositionForFloatIncludingMargin(r),
2924 r->m_renderer->width(), r->m_renderer->height());
2925 rootBlock->flipForWritingMode(floatBox);
2926 floatBox.move(rootBlockPhysicalPosition.x(), rootBlockPhysicalPosition.y());
2927 paintInfo->context->clipOut(floatBox);
2932 // 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
2935 if (!isBlockFlow()) // FIXME: Make multi-column selection gap filling work someday.
2938 if (hasColumns() || hasTransform() || style()->columnSpan()) {
2939 // FIXME: We should learn how to gap fill multiple columns and transforms eventually.
2940 lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalHeight();
2941 lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight());
2942 lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight());
2946 if (childrenInline())
2947 result = inlineSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo);
2949 result = blockSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo);
2951 // Go ahead and fill the vertical gap all the way to the bottom of our block if the selection extends past our block.
2952 if (rootBlock == this && (selectionState() != SelectionBoth && selectionState() != SelectionEnd))
2953 result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight,
2954 logicalHeight(), paintInfo));
2958 GapRects RenderBlock::inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
2959 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* paintInfo)
2963 bool containsStart = selectionState() == SelectionStart || selectionState() == SelectionBoth;
2965 if (!firstLineBox()) {
2966 if (containsStart) {
2967 // Go ahead and update our lastLogicalTop to be the bottom of the block. <hr>s or empty blocks with height can trip this
2969 lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalHeight();
2970 lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight());
2971 lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight());
2976 RootInlineBox* lastSelectedLine = 0;
2977 RootInlineBox* curr;
2978 for (curr = firstRootBox(); curr && !curr->hasSelectedChildren(); curr = curr->nextRootBox()) { }
2980 // Now paint the gaps for the lines.
2981 for (; curr && curr->hasSelectedChildren(); curr = curr->nextRootBox()) {
2982 LayoutUnit selTop = curr->selectionTop();
2983 LayoutUnit selHeight = curr->selectionHeight();
2985 if (!containsStart && !lastSelectedLine &&
2986 selectionState() != SelectionStart && selectionState() != SelectionBoth)
2987 result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight,
2988 selTop, paintInfo));
2990 LayoutRect logicalRect(curr->logicalLeft(), selTop, curr->logicalWidth(), selTop + selHeight);
2991 logicalRect.move(isHorizontalWritingMode() ? offsetFromRootBlock : offsetFromRootBlock.transposedSize());
2992 LayoutRect physicalRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, logicalRect);
2993 if (!paintInfo || (isHorizontalWritingMode() && physicalRect.y() < paintInfo->rect.maxY() && physicalRect.maxY() > paintInfo->rect.y())
2994 || (!isHorizontalWritingMode() && physicalRect.x() < paintInfo->rect.maxX() && physicalRect.maxX() > paintInfo->rect.x()))
2995 result.unite(curr->lineSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, selTop, selHeight, paintInfo));
2997 lastSelectedLine = curr;
3000 if (containsStart && !lastSelectedLine)
3001 // VisibleSelection must start just after our last line.
3002 lastSelectedLine = lastRootBox();
3004 if (lastSelectedLine && selectionState() != SelectionEnd && selectionState() != SelectionBoth) {
3005 // Go ahead and update our lastY to be the bottom of the last selected line.
3006 lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + lastSelectedLine->selectionBottom();
3007 lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, lastSelectedLine->selectionBottom());
3008 lastLogicalRight = logicalRightSelectionOffset(rootBlock, lastSelectedLine->selectionBottom());
3013 GapRects RenderBlock::blockSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
3014 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* paintInfo)
3018 // Go ahead and jump right to the first block child that contains some selected objects.
3020 for (curr = firstChildBox(); curr && curr->selectionState() == SelectionNone; curr = curr->nextSiblingBox()) { }
3022 for (bool sawSelectionEnd = false; curr && !sawSelectionEnd; curr = curr->nextSiblingBox()) {
3023 SelectionState childState = curr->selectionState();
3024 if (childState == SelectionBoth || childState == SelectionEnd)
3025 sawSelectionEnd = true;
3027 if (curr->isFloatingOrPositioned())
3028 continue; // We must be a normal flow object in order to even be considered.
3030 if (curr->isRelPositioned() && curr->hasLayer()) {
3031 // If the relposition offset is anything other than 0, then treat this just like an absolute positioned element.
3032 // Just disregard it completely.
3033 LayoutSize relOffset = curr->layer()->relativePositionOffset();
3034 if (relOffset.width() || relOffset.height())
3038 bool paintsOwnSelection = curr->shouldPaintSelectionGaps() || curr->isTable(); // FIXME: Eventually we won't special-case table like this.
3039 bool fillBlockGaps = paintsOwnSelection || (curr->canBeSelectionLeaf() && childState != SelectionNone);
3040 if (fillBlockGaps) {
3041 // We need to fill the vertical gap above this object.
3042 if (childState == SelectionEnd || childState == SelectionInside)
3043 // Fill the gap above the object.
3044 result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight,
3045 curr->logicalTop(), paintInfo));
3047 // 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*
3048 // our object. We know this if the selection did not end inside our object.
3049 if (paintsOwnSelection && (childState == SelectionStart || sawSelectionEnd))
3050 childState = SelectionNone;
3052 // Fill side gaps on this object based off its state.
3053 bool leftGap, rightGap;
3054 getSelectionGapInfo(childState, leftGap, rightGap);
3057 result.uniteLeft(logicalLeftSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalLeft(), curr->logicalTop(), curr->logicalHeight(), paintInfo));
3059 result.uniteRight(logicalRightSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalRight(), curr->logicalTop(), curr->logicalHeight(), paintInfo));
3061 // Update lastLogicalTop to be just underneath the object. lastLogicalLeft and lastLogicalRight extend as far as
3062 // they can without bumping into floating or positioned objects. Ideally they will go right up
3063 // to the border of the root selection block.
3064 lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + curr->logicalBottom();
3065 lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, curr->logicalBottom());
3066 lastLogicalRight = logicalRightSelectionOffset(rootBlock, curr->logicalBottom());
3067 } else if (childState != SelectionNone)
3068 // We must be a block that has some selected object inside it. Go ahead and recur.
3069 result.unite(toRenderBlock(curr)->selectionGaps(rootBlock, rootBlockPhysicalPosition, LayoutSize(offsetFromRootBlock.width() + curr->x(), offsetFromRootBlock.height() + curr->y()),
3070 lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo));
3075 LayoutRect RenderBlock::blockSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
3076 LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const PaintInfo* paintInfo)
3078 LayoutUnit logicalTop = lastLogicalTop;
3079 LayoutUnit logicalHeight = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalBottom - logicalTop;
3080 if (logicalHeight <= static_cast<LayoutUnit>(0))
3081 return LayoutRect();
3083 // Get the selection offsets for the bottom of the gap
3084 LayoutUnit logicalLeft = max(lastLogicalLeft, logicalLeftSelectionOffset(rootBlock, logicalBottom));
3085 LayoutUnit logicalRight = min(lastLogicalRight, logicalRightSelectionOffset(rootBlock, logicalBottom));
3086 LayoutUnit logicalWidth = logicalRight - logicalLeft;
3087 if (logicalWidth <= static_cast<LayoutUnit>(0))
3088 return LayoutRect();
3090 LayoutRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, LayoutRect(logicalLeft, logicalTop, logicalWidth, logicalHeight));
3092 paintInfo->context->fillRect(gapRect, selectionBackgroundColor(), style()->colorSpace());
3096 LayoutRect RenderBlock::logicalLeftSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
3097 RenderObject* selObj, LayoutUnit logicalLeft, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo* paintInfo)
3099 LayoutUnit rootBlockLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalTop;
3100 LayoutUnit rootBlockLogicalLeft = max(logicalLeftSelectionOffset(rootBlock, logicalTop), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight));
3101 LayoutUnit rootBlockLogicalRight = min(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + logicalLeft, min(logicalRightSelectionOffset(rootBlock, logicalTop), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight)));
3102 LayoutUnit rootBlockLogicalWidth = rootBlockLogicalRight - rootBlockLogicalLeft;
3103 if (rootBlockLogicalWidth <= static_cast<LayoutUnit>(0))
3104 return LayoutRect();
3106 LayoutRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, LayoutRect(rootBlockLogicalLeft, rootBlockLogicalTop, rootBlockLogicalWidth, logicalHeight));
3108 paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor(), selObj->style()->colorSpace());
3112 LayoutRect RenderBlock::logicalRightSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
3113 RenderObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo* paintInfo)
3115 LayoutUnit rootBlockLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalTop;
3116 LayoutUnit rootBlockLogicalLeft = max(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + logicalRight, max(logicalLeftSelectionOffset(rootBlock, logicalTop), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight)));
3117 LayoutUnit rootBlockLogicalRight = min(logicalRightSelectionOffset(rootBlock, logicalTop), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight));
3118 LayoutUnit rootBlockLogicalWidth = rootBlockLogicalRight - rootBlockLogicalLeft;
3119 if (rootBlockLogicalWidth <= static_cast<LayoutUnit>(0))
3120 return LayoutRect();
3122 LayoutRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, LayoutRect(rootBlockLogicalLeft, rootBlockLogicalTop, rootBlockLogicalWidth, logicalHeight));
3124 paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor(), selObj->style()->colorSpace());
3128 void RenderBlock::getSelectionGapInfo(SelectionState state, bool& leftGap, bool& rightGap)
3130 bool ltr = style()->isLeftToRightDirection();
3131 leftGap = (state == RenderObject::SelectionInside) ||
3132 (state == RenderObject::SelectionEnd && ltr) ||
3133 (state == RenderObject::SelectionStart && !ltr);
3134 rightGap = (state == RenderObject::SelectionInside) ||
3135 (state == RenderObject::SelectionStart && ltr) ||
3136 (state == RenderObject::SelectionEnd && !ltr);
3139 LayoutUnit RenderBlock::logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position)
3141 LayoutUnit logicalLeft = logicalLeftOffsetForLine(position, false);
3142 if (logicalLeft == logicalLeftOffsetForContent()) {
3143 if (rootBlock != this)
3144 // The border can potentially be further extended by our containingBlock().
3145 return containingBlock()->logicalLeftSelectionOffset(rootBlock, position + logicalTop());
3148 RenderBlock* cb = this;
3149 while (cb != rootBlock) {
3150 logicalLeft += cb->logicalLeft();
3151 cb = cb->containingBlock();
3157 LayoutUnit RenderBlock::logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position)
3159 LayoutUnit logicalRight = logicalRightOffsetForLine(position, false);
3160 if (logicalRight == logicalRightOffsetForContent()) {
3161 if (rootBlock != this)
3162 // The border can potentially be further extended by our containingBlock().
3163 return containingBlock()->logicalRightSelectionOffset(rootBlock, position + logicalTop());
3164 return logicalRight;
3166 RenderBlock* cb = this;
3167 while (cb != rootBlock) {
3168 logicalRight += cb->logicalLeft();
3169 cb = cb->containingBlock();
3172 return logicalRight;
3175 void RenderBlock::insertPositionedObject(RenderBox* o)
3177 if (o->isRenderFlowThread())
3180 // Create the list of special objects if we don't aleady have one
3181 if (!m_positionedObjects)
3182 m_positionedObjects = adoptPtr(new PositionedObjectsListHashSet);
3184 m_positionedObjects->add(o);
3187 void RenderBlock::removePositionedObject(RenderBox* o)
3189 if (m_positionedObjects)
3190 m_positionedObjects->remove(o);
3193 void RenderBlock::removePositionedObjects(RenderBlock* o)
3195 if (!m_positionedObjects)
3200 Iterator end = m_positionedObjects->end();
3202 Vector<RenderBox*, 16> deadObjects;
3204 for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
3206 if (!o || r->isDescendantOf(o)) {
3208 r->setChildNeedsLayout(true, false);
3210 // It is parent blocks job to add positioned child to positioned objects list of its containing block
3211 // Parent layout needs to be invalidated to ensure this happens.
3212 RenderObject* p = r->parent();
3213 while (p && !p->isRenderBlock())
3216 p->setChildNeedsLayout(true);
3218 deadObjects.append(r);
3222 for (unsigned i = 0; i < deadObjects.size(); i++)
3223 m_positionedObjects->remove(deadObjects.at(i));
3226 RenderBlock::FloatingObject* RenderBlock::insertFloatingObject(RenderBox* o)
3228 ASSERT(o->isFloating());
3230 // Create the list of special objects if we don't aleady have one
3231 if (!m_floatingObjects)
3232 m_floatingObjects = adoptPtr(new FloatingObjects(isHorizontalWritingMode()));
3234 // Don't insert the object again if it's already in the list
3235 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3236 FloatingObjectSetIterator it = floatingObjectSet.find<RenderBox*, FloatingObjectHashTranslator>(o);
3237 if (it != floatingObjectSet.end())
3241 // Create the special object entry & append it to the list
3243 FloatingObject* newObj = new FloatingObject(o->style()->floating());
3245 // Our location is irrelevant if we're unsplittable or no pagination is in effect.
3246 // Just go ahead and lay out the float.
3247 if (!o->isPositioned()) {
3248 bool isChildRenderBlock = o->isRenderBlock();
3249 if (isChildRenderBlock && !o->needsLayout() && view()->layoutState()->pageLogicalHeightChanged())
3250 o->setChildNeedsLayout(true, false);
3252 bool affectedByPagination = isChildRenderBlock && view()->layoutState()->m_pageLogicalHeight;
3253 if (!affectedByPagination || isWritingModeRoot()) // We are unsplittable if we're a block flow root.
3254 o->layoutIfNeeded();
3256 o->computeLogicalWidth();
3257 o->computeBlockDirectionMargins(this);
3260 setLogicalWidthForFloat(newObj, logicalWidthForChild(o) + marginStartForChild(o) + marginEndForChild(o));
3262 newObj->m_shouldPaint = !o->hasSelfPaintingLayer(); // If a layer exists, the float will paint itself. Otherwise someone else will.
3263 newObj->m_isDescendant = true;
3264 newObj->m_renderer = o;
3266 m_floatingObjects->add(newObj);
3271 void RenderBlock::removeFloatingObject(RenderBox* o)
3273 if (m_floatingObjects) {
3274 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3275 FloatingObjectSetIterator it = floatingObjectSet.find<RenderBox*, FloatingObjectHashTranslator>(o);
3276 if (it != floatingObjectSet.end()) {
3277 FloatingObject* r = *it;
3278 if (childrenInline()) {
3279 int logicalTop = logicalTopForFloat(r);
3280 int logicalBottom = logicalBottomForFloat(r);
3282 // Fix for https://bugs.webkit.org/show_bug.cgi?id=54995.
3283 if (logicalBottom < 0 || logicalBottom < logicalTop || logicalTop == numeric_limits<int>::max())
3284 logicalBottom = numeric_limits<int>::max();
3286 // Special-case zero- and less-than-zero-height floats: those don't touch
3287 // the line that they're on, but it still needs to be dirtied. This is
3288 // accomplished by pretending they have a height of 1.
3289 logicalBottom = max(logicalBottom, logicalTop + 1);
3291 if (r->m_originatingLine) {
3292 if (!selfNeedsLayout()) {
3293 ASSERT(r->m_originatingLine->renderer() == this);
3294 r->m_originatingLine->markDirty();
3296 #if !ASSERT_DISABLED
3297 r->m_originatingLine = 0;
3300 markLinesDirtyInBlockRange(0, logicalBottom);
3302 m_floatingObjects->remove(r);
3303 ASSERT(!r->m_originatingLine);
3309 void RenderBlock::removeFloatingObjectsBelow(FloatingObject* lastFloat, int logicalOffset)
3311 if (!m_floatingObjects)
3314 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3315 FloatingObject* curr = floatingObjectSet.last();
3316 while (curr != lastFloat && (!curr->isPlaced() || logicalTopForFloat(curr) >= logicalOffset)) {
3317 m_floatingObjects->remove(curr);
3318 ASSERT(!curr->m_originatingLine);
3320 if (floatingObjectSet.isEmpty())
3322 curr = floatingObjectSet.last();
3326 LayoutPoint RenderBlock::computeLogicalLocationForFloat(const FloatingObject* floatingObject, LayoutUnit logicalTopOffset) const
3328 RenderBox* childBox = floatingObject->renderer();
3329 LayoutUnit logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset); // Constant part of right offset.
3330 LayoutUnit logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset.
3331 LayoutUnit floatLogicalWidth = min(logicalWidthForFloat(floatingObject), logicalRightOffset - logicalLeftOffset); // The width we look for.
3333 LayoutUnit floatLogicalLeft;
3335 if (childBox->style()->floating() == LeftFloat) {
3336 LayoutUnit heightRemainingLeft = 1;
3337 LayoutUnit heightRemainingRight = 1;
3338 floatLogicalLeft = logicalLeftOffsetForLine(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft);
3339 while (logicalRightOffsetForLine(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight) - floatLogicalLeft < floatLogicalWidth) {
3340 logicalTopOffset += min(heightRemainingLeft, heightRemainingRight);
3341 floatLogicalLeft = logicalLeftOffsetForLine(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft);
3342 if (inRenderFlowThread()) {
3343 // Have to re-evaluate all of our offsets, since they may have changed.
3344 logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset); // Constant part of right offset.
3345 logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset.
3346 floatLogicalWidth = min(logicalWidthForFloat(floatingObject), logicalRightOffset - logicalLeftOffset);
3349 floatLogicalLeft = max<LayoutUnit>(logicalLeftOffset - borderAndPaddingLogicalLeft(), floatLogicalLeft);
3351 LayoutUnit heightRemainingLeft = 1;
3352 LayoutUnit heightRemainingRight = 1;
3353 floatLogicalLeft = logicalRightOffsetForLine(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight);
3354 while (floatLogicalLeft - logicalLeftOffsetForLine(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft) < floatLogicalWidth) {
3355 logicalTopOffset += min(heightRemainingLeft, heightRemainingRight);
3356 floatLogicalLeft = logicalRightOffsetForLine(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight);
3357 if (inRenderFlowThread()) {
3358 // Have to re-evaluate all of our offsets, since they may have changed.
3359 logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset); // Constant part of right offset.
3360 logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset.
3361 floatLogicalWidth = min(logicalWidthForFloat(floatingObject), logicalRightOffset - logicalLeftOffset);
3364 floatLogicalLeft -= logicalWidthForFloat(floatingObject); // Use the original width of the float here, since the local variable
3365 // |floatLogicalWidth| was capped to the available line width.
3366 // See fast/block/float/clamped-right-float.html.
3369 return LayoutPoint(floatLogicalLeft, logicalTopOffset);
3372 bool RenderBlock::positionNewFloats()
3374 if (!m_floatingObjects)
3377 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3378 if (floatingObjectSet.isEmpty())
3381 // If all floats have already been positioned, then we have no work to do.
3382 if (floatingObjectSet.last()->isPlaced())
3385 // Move backwards through our floating object list until we find a float that has
3386 // already been positioned. Then we'll be able to move forward, positioning all of
3387 // the new floats that need it.
3388 FloatingObjectSetIterator it = floatingObjectSet.end();
3389 --it; // Go to last item.
3390 FloatingObjectSetIterator begin = floatingObjectSet.begin();
3391 FloatingObject* lastPlacedFloatingObject = 0;
3392 while (it != begin) {
3394 if ((*it)->isPlaced()) {
3395 lastPlacedFloatingObject = *it;
3401 LayoutUnit logicalTop = logicalHeight();
3403 // The float cannot start above the top position of the last positioned float.
3404 if (lastPlacedFloatingObject)
3405 logicalTop = max(logicalTopForFloat(lastPlacedFloatingObject), logicalTop);
3407 FloatingObjectSetIterator end = floatingObjectSet.end();
3408 // Now walk through the set of unpositioned floats and place them.
3409 for (; it != end; ++it) {
3410 FloatingObject* floatingObject = *it;
3411 // The containing block is responsible for positioning floats, so if we have floats in our
3412 // list that come from somewhere else, do not attempt to position them. Also don't attempt to handle
3413 // positioned floats, since the positioning layout code handles those.
3414 if (floatingObject->renderer()->containingBlock() != this || floatingObject->renderer()->isPositioned())
3417 RenderBox* childBox = floatingObject->renderer();
3418 LayoutUnit childLogicalLeftMargin = style()->isLeftToRightDirection() ? marginStartForChild(childBox) : marginEndForChild(childBox);
3420 LayoutRect oldRect(childBox->x(), childBox->y() , childBox->width(), childBox->height());
3422 if (childBox->style()->clear() & CLEFT)
3423 logicalTop = max(lowestFloatLogicalBottom(FloatingObject::FloatLeft), logicalTop);
3424 if (childBox->style()->clear() & CRIGHT)
3425 logicalTop = max(lowestFloatLogicalBottom(FloatingObject::FloatRight), logicalTop);
3427 LayoutPoint floatLogicalLocation = computeLogicalLocationForFloat(floatingObject, logicalTop);
3429 setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x());
3430 setLogicalLeftForChild(childBox, floatLogicalLocation.x() + childLogicalLeftMargin);
3431 setLogicalTopForChild(childBox, floatLogicalLocation.y() + marginBeforeForChild(childBox));
3433 if (view()->layoutState()->isPaginated()) {
3434 RenderBlock* childBlock = childBox->isRenderBlock() ? toRenderBlock(childBox) : 0;
3436 if (!childBox->needsLayout())
3437 childBox->markForPaginationRelayoutIfNeeded();
3438 childBox->layoutIfNeeded();
3440 // If we are unsplittable and don't fit, then we need to move down.
3441 // We include our margins as part of the unsplittable area.
3442 LayoutUnit newLogicalTop = adjustForUnsplittableChild(childBox, floatLogicalLocation.y(), true);
3444 // See if we have a pagination strut that is making us move down further.
3445 // Note that an unsplittable child can't also have a pagination strut, so this is
3446 // exclusive with the case above.
3447 if (childBlock && childBlock->paginationStrut()) {
3448 newLogicalTop += childBlock->paginationStrut();
3449 childBlock->setPaginationStrut(0);
3452 if (newLogicalTop != floatLogicalLocation.y()) {
3453 floatingObject->m_paginationStrut = newLogicalTop - floatLogicalLocation.y();
3455 floatLogicalLocation = computeLogicalLocationForFloat(floatingObject, newLogicalTop);
3456 setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x());
3457 setLogicalLeftForChild(childBox, floatLogicalLocation.x() + childLogicalLeftMargin);
3458 setLogicalTopForChild(childBox, floatLogicalLocation.y() + marginBeforeForChild(childBox));
3461 childBlock->setChildNeedsLayout(true, false);
3462 childBox->layoutIfNeeded();
3466 setLogicalTopForFloat(floatingObject, floatLogicalLocation.y());
3467 setLogicalHeightForFloat(floatingObject, logicalHeightForChild(childBox) + marginBeforeForChild(childBox) + marginAfterForChild(childBox));
3469 m_floatingObjects->addPlacedObject(floatingObject);
3471 // If the child moved, we have to repaint it.
3472 if (childBox->checkForRepaintDuringLayout())
3473 childBox->repaintDuringLayoutIfMoved(oldRect);
3478 void RenderBlock::newLine(EClear clear)
3480 positionNewFloats();
3486 newY = lowestFloatLogicalBottom(FloatingObject::FloatLeft);
3489 newY = lowestFloatLogicalBottom(FloatingObject::FloatRight);
3492 newY = lowestFloatLogicalBottom();
3496 if (height() < newY)
3497 setLogicalHeight(newY);
3500 void RenderBlock::addPercentHeightDescendant(RenderBox* descendant)
3502 if (!gPercentHeightDescendantsMap) {
3503 gPercentHeightDescendantsMap = new PercentHeightDescendantsMap;
3504 gPercentHeightContainerMap = new PercentHeightContainerMap;
3507 HashSet<RenderBox*>* descendantSet = gPercentHeightDescendantsMap->get(this);
3508 if (!descendantSet) {
3509 descendantSet = new HashSet<RenderBox*>;
3510 gPercentHeightDescendantsMap->set(this, descendantSet);
3512 bool added = descendantSet->add(descendant).second;
3514 ASSERT(gPercentHeightContainerMap->get(descendant));
3515 ASSERT(gPercentHeightContainerMap->get(descendant)->contains(this));
3519 HashSet<RenderBlock*>* containerSet = gPercentHeightContainerMap->get(descendant);
3520 if (!containerSet) {
3521 containerSet = new HashSet<RenderBlock*>;
3522 gPercentHeightContainerMap->set(descendant, containerSet);
3524 ASSERT(!containerSet->contains(this));
3525 containerSet->add(this);
3528 void RenderBlock::removePercentHeightDescendant(RenderBox* descendant)
3530 if (!gPercentHeightContainerMap)
3533 HashSet<RenderBlock*>* containerSet = gPercentHeightContainerMap->take(descendant);
3537 HashSet<RenderBlock*>::iterator end = containerSet->end();
3538 for (HashSet<RenderBlock*>::iterator it = containerSet->begin(); it != end; ++it) {
3539 RenderBlock* container = *it;
3540 HashSet<RenderBox*>* descendantSet = gPercentHeightDescendantsMap->get(container);
3541 ASSERT(descendantSet);
3544 ASSERT(descendantSet->contains(descendant));
3545 descendantSet->remove(descendant);
3546 if (descendantSet->isEmpty()) {
3547 gPercentHeightDescendantsMap->remove(container);
3548 delete descendantSet;
3552 delete containerSet;
3555 HashSet<RenderBox*>* RenderBlock::percentHeightDescendants() const
3557 return gPercentHeightDescendantsMap ? gPercentHeightDescendantsMap->get(this) : 0;
3560 #if !ASSERT_DISABLED
3561 bool RenderBlock::hasPercentHeightDescendant(RenderBox* descendant)
3564 if (!gPercentHeightContainerMap)
3566 HashSet<RenderBlock*>* containerSet = gPercentHeightContainerMap->take(descendant);
3567 return containerSet && containerSet->size();
3571 template <RenderBlock::FloatingObject::Type FloatTypeValue>
3572 inline void RenderBlock::FloatIntervalSearchAdapter<FloatTypeValue>::collectIfNeeded(const IntervalType& interval) const
3574 const FloatingObject* r = interval.data();
3575 if (r->type() == FloatTypeValue && interval.low() <= m_value && m_value < interval.high()) {
3576 // All the objects returned from the tree should be already placed.
3577 ASSERT(r->isPlaced() && m_renderer->logicalTopForFloat(r) <= m_value && m_renderer->logicalBottomForFloat(r) > m_value);
3579 if (FloatTypeValue == FloatingObject::FloatLeft
3580 && m_renderer->logicalRightForFloat(r) > m_offset) {
3581 m_offset = m_renderer->logicalRightForFloat(r);
3582 if (m_heightRemaining)
3583 *m_heightRemaining = m_renderer->logicalBottomForFloat(r) - m_value;
3586 if (FloatTypeValue == FloatingObject::FloatRight
3587 && m_renderer->logicalLeftForFloat(r) < m_offset) {
3588 m_offset = m_renderer->logicalLeftForFloat(r);
3589 if (m_heightRemaining)
3590 *m_heightRemaining = m_renderer->logicalBottomForFloat(r) - m_value;
3595 LayoutUnit RenderBlock::textIndentOffset() const
3598 if (style()->textIndent().isPercent())
3599 cw = containingBlock()->availableLogicalWidth();
3600 return style()->textIndent().calcMinValue(cw);
3603 LayoutUnit RenderBlock::logicalLeftOffsetForContent(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
3605 LayoutUnit logicalLeftOffset = style()->isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop();
3606 if (!inRenderFlowThread())
3607 return logicalLeftOffset;
3608 LayoutRect boxRect = borderBoxRectInRegion(region, offsetFromLogicalTopOfFirstPage);
3609 return logicalLeftOffset + (isHorizontalWritingMode() ? boxRect.x() : boxRect.y());
3612 LayoutUnit RenderBlock::logicalRightOffsetForContent(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
3614 LayoutUnit logicalRightOffset = style()->isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop();
3615 logicalRightOffset += availableLogicalWidth();
3616 if (!inRenderFlowThread())
3617 return logicalRightOffset;
3618 LayoutRect boxRect = borderBoxRectInRegion(region, offsetFromLogicalTopOfFirstPage);
3619 return logicalRightOffset - (logicalWidth() - (isHorizontalWritingMode() ? boxRect.maxX() : boxRect.maxY()));
3622 LayoutUnit RenderBlock::logicalLeftOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const
3624 LayoutUnit left = fixedOffset;
3625 if (m_floatingObjects && m_floatingObjects->hasLeftObjects()) {
3626 if (heightRemaining)
3627 *heightRemaining = 1;
3629 FloatIntervalSearchAdapter<FloatingObject::FloatLeft> adapter(this, logicalTop, left, heightRemaining);
3630 m_floatingObjects->placedFloatsTree().allOverlapsWithAdapter(adapter);
3633 if (applyTextIndent && style()->isLeftToRightDirection())
3634 left += textIndentOffset();
3639 LayoutUnit RenderBlock::logicalRightOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const
3641 LayoutUnit right = fixedOffset;
3642 if (m_floatingObjects && m_floatingObjects->hasRightObjects()) {
3643 if (heightRemaining)
3644 *heightRemaining = 1;
3646 LayoutUnit rightFloatOffset = fixedOffset;
3647 FloatIntervalSearchAdapter<FloatingObject::FloatRight> adapter(this, logicalTop, rightFloatOffset, heightRemaining);
3648 m_floatingObjects->placedFloatsTree().allOverlapsWithAdapter(adapter);
3649 right = min(right, rightFloatOffset);
3652 if (applyTextIndent && !style()->isLeftToRightDirection())
3653 right -= textIndentOffset();
3658 LayoutUnit RenderBlock::nextFloatLogicalBottomBelow(LayoutUnit logicalHeight) const
3660 if (!m_floatingObjects)
3661 return logicalHeight;
3663 LayoutUnit bottom = numeric_limits<LayoutUnit>::max();
3664 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3665 FloatingObjectSetIterator end = floatingObjectSet.end();
3666 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
3667 FloatingObject* r = *it;
3668 LayoutUnit floatBottom = logicalBottomForFloat(r);
3669 if (floatBottom > logicalHeight)
3670 bottom = min(floatBottom, bottom);
3673 return bottom == numeric_limits<LayoutUnit>::max() ? logicalHeight : bottom;
3676 LayoutUnit RenderBlock::lowestFloatLogicalBottom(FloatingObject::Type floatType) const
3678 if (!m_floatingObjects)
3680 LayoutUnit lowestFloatBottom = 0;
3681 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3682 FloatingObjectSetIterator end = floatingObjectSet.end();
3683 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
3684 FloatingObject* r = *it;
3685 if (r->isPlaced() && r->type() & floatType)
3686 lowestFloatBottom = max(lowestFloatBottom, logicalBottomForFloat(r));
3688 return lowestFloatBottom;
3691 void RenderBlock::markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit logicalBottom, RootInlineBox* highest)
3693 if (logicalTop >= logicalBottom)
3696 RootInlineBox* lowestDirtyLine = lastRootBox();
3697 RootInlineBox* afterLowest = lowestDirtyLine;
3698 while (lowestDirtyLine && lowestDirtyLine->lineBottomWithLeading() >= logicalBottom && logicalBottom < numeric_limits<LayoutUnit>::max()) {
3699 afterLowest = lowestDirtyLine;
3700 lowestDirtyLine = lowestDirtyLine->prevRootBox();
3703 while (afterLowest && afterLowest != highest && (afterLowest->lineBottomWithLeading() >= logicalTop || afterLowest->lineBottomWithLeading() < 0)) {
3704 afterLowest->markDirty();
3705 afterLowest = afterLowest->prevRootBox();
3709 void RenderBlock::addPositionedFloats()