• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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.
7  *
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.
12  *
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.
17  *
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.
22  */
23 
24 #include "config.h"
25 #include "RenderBlock.h"
26 
27 #include "ColumnInfo.h"
28 #include "Document.h"
29 #include "Element.h"
30 #include "FloatQuad.h"
31 #include "Frame.h"
32 #include "FrameView.h"
33 #include "GraphicsContext.h"
34 #include "HTMLFormElement.h"
35 #include "HTMLNames.h"
36 #include "HitTestResult.h"
37 #include "InlineIterator.h"
38 #include "InlineTextBox.h"
39 #include "PaintInfo.h"
40 #include "RenderCombineText.h"
41 #include "RenderFlexibleBox.h"
42 #include "RenderImage.h"
43 #include "RenderInline.h"
44 #include "RenderLayer.h"
45 #include "RenderMarquee.h"
46 #include "RenderReplica.h"
47 #include "RenderTableCell.h"
48 #include "RenderTextFragment.h"
49 #include "RenderTheme.h"
50 #include "RenderView.h"
51 #include "SelectionController.h"
52 #include "Settings.h"
53 #include "TextRun.h"
54 #include "TransformState.h"
55 #include <wtf/StdLibExtras.h>
56 
57 #ifdef ANDROID_LAYOUT
58 #include "Settings.h"
59 #endif
60 
61 using namespace std;
62 using namespace WTF;
63 using namespace Unicode;
64 
65 namespace WebCore {
66 
67 using namespace HTMLNames;
68 
69 typedef WTF::HashMap<const RenderBox*, ColumnInfo*> ColumnInfoMap;
70 static ColumnInfoMap* gColumnInfoMap = 0;
71 
72 typedef WTF::HashMap<const RenderBlock*, HashSet<RenderBox*>*> PercentHeightDescendantsMap;
73 static PercentHeightDescendantsMap* gPercentHeightDescendantsMap = 0;
74 
75 typedef WTF::HashMap<const RenderBox*, HashSet<RenderBlock*>*> PercentHeightContainerMap;
76 static PercentHeightContainerMap* gPercentHeightContainerMap = 0;
77 
78 typedef WTF::HashMap<RenderBlock*, ListHashSet<RenderInline*>*> ContinuationOutlineTableMap;
79 
80 typedef WTF::HashSet<RenderBlock*> DelayedUpdateScrollInfoSet;
81 static int gDelayUpdateScrollInfo = 0;
82 static DelayedUpdateScrollInfoSet* gDelayedUpdateScrollInfoSet = 0;
83 
84 bool RenderBlock::s_canPropagateFloatIntoSibling = false;
85 
86 // Our MarginInfo state used when laying out block children.
MarginInfo(RenderBlock * block,int beforeBorderPadding,int afterBorderPadding)87 RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, int beforeBorderPadding, int afterBorderPadding)
88     : m_atBeforeSideOfBlock(true)
89     , m_atAfterSideOfBlock(false)
90     , m_marginBeforeQuirk(false)
91     , m_marginAfterQuirk(false)
92     , m_determinedMarginBeforeQuirk(false)
93 {
94     // Whether or not we can collapse our own margins with our children.  We don't do this
95     // if we had any border/padding (obviously), if we're the root or HTML elements, or if
96     // we're positioned, floating, a table cell.
97     m_canCollapseWithChildren = !block->isRenderView() && !block->isRoot() && !block->isPositioned()
98         && !block->isFloating() && !block->isTableCell() && !block->hasOverflowClip() && !block->isInlineBlockOrInlineTable()
99         && !block->isWritingModeRoot();
100 
101     m_canCollapseMarginBeforeWithChildren = m_canCollapseWithChildren && (beforeBorderPadding == 0) && block->style()->marginBeforeCollapse() != MSEPARATE;
102 
103     // If any height other than auto is specified in CSS, then we don't collapse our bottom
104     // margins with our children's margins.  To do otherwise would be to risk odd visual
105     // effects when the children overflow out of the parent block and yet still collapse
106     // with it.  We also don't collapse if we have any bottom border/padding.
107     m_canCollapseMarginAfterWithChildren = m_canCollapseWithChildren && (afterBorderPadding == 0) &&
108         (block->style()->logicalHeight().isAuto() && block->style()->logicalHeight().value() == 0) && block->style()->marginAfterCollapse() != MSEPARATE;
109 
110     m_quirkContainer = block->isTableCell() || block->isBody() || block->style()->marginBeforeCollapse() == MDISCARD ||
111         block->style()->marginAfterCollapse() == MDISCARD;
112 
113     m_positiveMargin = m_canCollapseMarginBeforeWithChildren ? block->maxPositiveMarginBefore() : 0;
114     m_negativeMargin = m_canCollapseMarginBeforeWithChildren ? block->maxNegativeMarginBefore() : 0;
115 }
116 
117 // -------------------------------------------------------------------------------------------------------
118 
RenderBlock(Node * node)119 RenderBlock::RenderBlock(Node* node)
120       : RenderBox(node)
121       , m_floatingObjects(0)
122       , m_positionedObjects(0)
123       , m_rareData(0)
124       , m_lineHeight(-1)
125       , m_beingDestroyed(false)
126 {
127     setChildrenInline(true);
128 }
129 
~RenderBlock()130 RenderBlock::~RenderBlock()
131 {
132     if (m_floatingObjects)
133         deleteAllValues(m_floatingObjects->set());
134 
135     if (hasColumns())
136         delete gColumnInfoMap->take(this);
137 
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);
144                 if (!containerSet)
145                     continue;
146                 ASSERT(containerSet->contains(this));
147                 containerSet->remove(this);
148                 if (containerSet->isEmpty()) {
149                     gPercentHeightContainerMap->remove(*descendant);
150                     delete containerSet;
151                 }
152             }
153             delete descendantSet;
154         }
155     }
156 }
157 
destroy()158 void RenderBlock::destroy()
159 {
160     // Mark as being destroyed to avoid trouble with merges in removeChild().
161     m_beingDestroyed = true;
162 
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();
166 
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();
171     if (continuation) {
172         continuation->destroy();
173         setContinuation(0);
174     }
175 
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 SelectionController should be responsible for this when it
181             // is notified of DOM mutations.
182             if (isSelectionBorder())
183                 view()->clearSelection();
184 
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())
191                         childBox->remove();
192                 }
193             }
194         } else if (isInline() && parent())
195             parent()->dirtyLinesFromChangedChild(this);
196     }
197 
198     m_lineBoxes.deleteLineBoxes(renderArena());
199 
200     RenderBox::destroy();
201 }
202 
styleWillChange(StyleDifference diff,const RenderStyle * newStyle)203 void RenderBlock::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
204 {
205     s_canPropagateFloatIntoSibling = style() ? !isFloatingOrPositioned() && !avoidsFloats() : false;
206 
207     setReplaced(newStyle->isDisplayInlineType());
208 
209     if (style() && parent() && diff == StyleDifferenceLayout && style()->position() != newStyle->position()) {
210         if (newStyle->position() == StaticPosition)
211             // Clear our positioned objects list. Our absolutely positioned descendants will be
212             // inserted into our containing block's positioned objects list during layout.
213             removePositionedObjects(0);
214         else if (style()->position() == StaticPosition) {
215             // Remove our absolutely positioned descendants from their current containing block.
216             // They will be inserted into our positioned objects list during layout.
217             RenderObject* cb = parent();
218             while (cb && (cb->style()->position() == StaticPosition || (cb->isInline() && !cb->isReplaced())) && !cb->isRenderView()) {
219                 if (cb->style()->position() == RelativePosition && cb->isInline() && !cb->isReplaced()) {
220                     cb = cb->containingBlock();
221                     break;
222                 }
223                 cb = cb->parent();
224             }
225 
226             if (cb->isRenderBlock())
227                 toRenderBlock(cb)->removePositionedObjects(this);
228         }
229 
230         if (containsFloats() && !isFloating() && !isPositioned() && (newStyle->position() == AbsolutePosition || newStyle->position() == FixedPosition))
231             markAllDescendantsWithFloatsForLayout();
232     }
233 
234     RenderBox::styleWillChange(diff, newStyle);
235 }
236 
styleDidChange(StyleDifference diff,const RenderStyle * oldStyle)237 void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
238 {
239     RenderBox::styleDidChange(diff, oldStyle);
240 
241     if (!isAnonymousBlock()) {
242         // Ensure that all of our continuation blocks pick up the new style.
243         for (RenderBlock* currCont = blockElementContinuation(); currCont; currCont = currCont->blockElementContinuation()) {
244             RenderBoxModelObject* nextCont = currCont->continuation();
245             currCont->setContinuation(0);
246             currCont->setStyle(style());
247             currCont->setContinuation(nextCont);
248         }
249     }
250 
251     // FIXME: We could save this call when the change only affected non-inherited properties
252     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
253         if (child->isAnonymousBlock()) {
254             RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style());
255             if (style()->specifiesColumns()) {
256                 if (child->style()->specifiesColumns())
257                     newStyle->inheritColumnPropertiesFrom(style());
258                 if (child->style()->columnSpan())
259                     newStyle->setColumnSpan(true);
260             }
261             newStyle->setDisplay(BLOCK);
262             child->setStyle(newStyle.release());
263         }
264     }
265 
266     m_lineHeight = -1;
267 
268     // Update pseudos for :before and :after now.
269     if (!isAnonymous() && document()->usesBeforeAfterRules() && canHaveChildren()) {
270         updateBeforeAfterContent(BEFORE);
271         updateBeforeAfterContent(AFTER);
272     }
273 
274     // After our style changed, if we lose our ability to propagate floats into next sibling
275     // blocks, then we need to find the top most parent containing that overhanging float and
276     // then mark its descendants with floats for layout and clear all floats from its next
277     // sibling blocks that exist in our floating objects list. See bug 56299 and 62875.
278     bool canPropagateFloatIntoSibling = !isFloatingOrPositioned() && !avoidsFloats();
279     if (diff == StyleDifferenceLayout && s_canPropagateFloatIntoSibling && !canPropagateFloatIntoSibling && hasOverhangingFloats()) {
280         RenderBlock* parentBlock = this;
281         FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
282         FloatingObjectSetIterator end = floatingObjectSet.end();
283 
284         for (RenderObject* curr = parent(); curr && !curr->isRenderView(); curr = curr->parent()) {
285             if (curr->isRenderBlock()) {
286                 RenderBlock* currBlock = toRenderBlock(curr);
287 
288                 if (currBlock->hasOverhangingFloats()) {
289                     for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
290                         RenderBox* renderer = (*it)->renderer();
291                         if (currBlock->hasOverhangingFloat(renderer)) {
292                             parentBlock = currBlock;
293                             break;
294                         }
295                     }
296                 }
297             }
298         }
299 
300         parentBlock->markAllDescendantsWithFloatsForLayout();
301         parentBlock->markSiblingsWithFloatsForLayout();
302     }
303 }
304 
updateBeforeAfterContent(PseudoId pseudoId)305 void RenderBlock::updateBeforeAfterContent(PseudoId pseudoId)
306 {
307     // If this is an anonymous wrapper, then the parent applies its own pseudo-element style to it.
308     if (parent() && parent()->createsAnonymousWrapper())
309         return;
310     return children()->updateBeforeAfterContent(this, pseudoId);
311 }
312 
continuationBefore(RenderObject * beforeChild)313 RenderBlock* RenderBlock::continuationBefore(RenderObject* beforeChild)
314 {
315     if (beforeChild && beforeChild->parent() == this)
316         return this;
317 
318     RenderBlock* curr = toRenderBlock(continuation());
319     RenderBlock* nextToLast = this;
320     RenderBlock* last = this;
321     while (curr) {
322         if (beforeChild && beforeChild->parent() == curr) {
323             if (curr->firstChild() == beforeChild)
324                 return last;
325             return curr;
326         }
327 
328         nextToLast = last;
329         last = curr;
330         curr = toRenderBlock(curr->continuation());
331     }
332 
333     if (!beforeChild && !last->firstChild())
334         return nextToLast;
335     return last;
336 }
337 
addChildToContinuation(RenderObject * newChild,RenderObject * beforeChild)338 void RenderBlock::addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild)
339 {
340     RenderBlock* flow = continuationBefore(beforeChild);
341     ASSERT(!beforeChild || beforeChild->parent()->isAnonymousColumnSpanBlock() || beforeChild->parent()->isRenderBlock());
342     RenderBoxModelObject* beforeChildParent = 0;
343     if (beforeChild)
344         beforeChildParent = toRenderBoxModelObject(beforeChild->parent());
345     else {
346         RenderBoxModelObject* cont = flow->continuation();
347         if (cont)
348             beforeChildParent = cont;
349         else
350             beforeChildParent = flow;
351     }
352 
353     if (newChild->isFloatingOrPositioned())
354         return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
355 
356     // A continuation always consists of two potential candidates: a block or an anonymous
357     // column span box holding column span children.
358     bool childIsNormal = newChild->isInline() || !newChild->style()->columnSpan();
359     bool bcpIsNormal = beforeChildParent->isInline() || !beforeChildParent->style()->columnSpan();
360     bool flowIsNormal = flow->isInline() || !flow->style()->columnSpan();
361 
362     if (flow == beforeChildParent)
363         return flow->addChildIgnoringContinuation(newChild, beforeChild);
364 
365     // The goal here is to match up if we can, so that we can coalesce and create the
366     // minimal # of continuations needed for the inline.
367     if (childIsNormal == bcpIsNormal)
368         return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
369     if (flowIsNormal == childIsNormal)
370         return flow->addChildIgnoringContinuation(newChild, 0); // Just treat like an append.
371     return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
372 }
373 
374 
addChildToAnonymousColumnBlocks(RenderObject * newChild,RenderObject * beforeChild)375 void RenderBlock::addChildToAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild)
376 {
377     ASSERT(!continuation()); // We don't yet support column spans that aren't immediate children of the multi-column block.
378 
379     // The goal is to locate a suitable box in which to place our child.
380     RenderBlock* beforeChildParent = toRenderBlock(beforeChild && beforeChild->parent()->isRenderBlock() ? beforeChild->parent() : lastChild());
381 
382     // If the new child is floating or positioned it can just go in that block.
383     if (newChild->isFloatingOrPositioned())
384         return beforeChildParent->addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild);
385 
386     // See if the child can be placed in the box.
387     bool newChildHasColumnSpan = newChild->style()->columnSpan() && !newChild->isInline();
388     bool beforeChildParentHoldsColumnSpans = beforeChildParent->isAnonymousColumnSpanBlock();
389 
390     if (newChildHasColumnSpan == beforeChildParentHoldsColumnSpans)
391         return beforeChildParent->addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild);
392 
393     if (!beforeChild) {
394         // Create a new block of the correct type.
395         RenderBlock* newBox = newChildHasColumnSpan ? createAnonymousColumnSpanBlock() : createAnonymousColumnsBlock();
396         children()->appendChildNode(this, newBox);
397         newBox->addChildIgnoringAnonymousColumnBlocks(newChild, 0);
398         return;
399     }
400 
401     RenderObject* immediateChild = beforeChild;
402     bool isPreviousBlockViable = true;
403     while (immediateChild->parent() != this) {
404         if (isPreviousBlockViable)
405             isPreviousBlockViable = !immediateChild->previousSibling();
406         immediateChild = immediateChild->parent();
407     }
408     if (isPreviousBlockViable && immediateChild->previousSibling())
409         return toRenderBlock(immediateChild->previousSibling())->addChildIgnoringAnonymousColumnBlocks(newChild, 0); // Treat like an append.
410 
411     // Split our anonymous blocks.
412     RenderObject* newBeforeChild = splitAnonymousBlocksAroundChild(beforeChild);
413 
414     // Create a new anonymous box of the appropriate type.
415     RenderBlock* newBox = newChildHasColumnSpan ? createAnonymousColumnSpanBlock() : createAnonymousColumnsBlock();
416     children()->insertChildNode(this, newBox, newBeforeChild);
417     newBox->addChildIgnoringAnonymousColumnBlocks(newChild, 0);
418     return;
419 }
420 
containingColumnsBlock(bool allowAnonymousColumnBlock)421 RenderBlock* RenderBlock::containingColumnsBlock(bool allowAnonymousColumnBlock)
422 {
423     for (RenderObject* curr = this; curr; curr = curr->parent()) {
424         if (!curr->isRenderBlock() || curr->isFloatingOrPositioned() || curr->isTableCell() || curr->isRoot() || curr->isRenderView() || curr->hasOverflowClip()
425             || curr->isInlineBlockOrInlineTable())
426             return 0;
427 
428         RenderBlock* currBlock = toRenderBlock(curr);
429         if (currBlock->style()->specifiesColumns() && (allowAnonymousColumnBlock || !currBlock->isAnonymousColumnsBlock()))
430             return currBlock;
431 
432         if (currBlock->isAnonymousColumnSpanBlock())
433             return 0;
434     }
435     return 0;
436 }
437 
clone() const438 RenderBlock* RenderBlock::clone() const
439 {
440     RenderBlock* cloneBlock;
441     if (isAnonymousBlock())
442         cloneBlock = createAnonymousBlock();
443     else {
444         cloneBlock = new (renderArena()) RenderBlock(node());
445         cloneBlock->setStyle(style());
446     }
447     cloneBlock->setChildrenInline(childrenInline());
448     return cloneBlock;
449 }
450 
splitBlocks(RenderBlock * fromBlock,RenderBlock * toBlock,RenderBlock * middleBlock,RenderObject * beforeChild,RenderBoxModelObject * oldCont)451 void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock,
452                               RenderBlock* middleBlock,
453                               RenderObject* beforeChild, RenderBoxModelObject* oldCont)
454 {
455     // Create a clone of this inline.
456     RenderBlock* cloneBlock = clone();
457     if (!isAnonymousBlock())
458         cloneBlock->setContinuation(oldCont);
459 
460     // Now take all of the children from beforeChild to the end and remove
461     // them from |this| and place them in the clone.
462     if (!beforeChild && isAfterContent(lastChild()))
463         beforeChild = lastChild();
464     moveChildrenTo(cloneBlock, beforeChild, 0);
465 
466     // Hook |clone| up as the continuation of the middle block.
467     if (!cloneBlock->isAnonymousBlock())
468         middleBlock->setContinuation(cloneBlock);
469 
470     // We have been reparented and are now under the fromBlock.  We need
471     // to walk up our block parent chain until we hit the containing anonymous columns block.
472     // Once we hit the anonymous columns block we're done.
473     RenderBoxModelObject* curr = toRenderBoxModelObject(parent());
474     RenderBoxModelObject* currChild = this;
475 
476     while (curr && curr != fromBlock) {
477         ASSERT(curr->isRenderBlock());
478 
479         RenderBlock* blockCurr = toRenderBlock(curr);
480 
481         // Create a new clone.
482         RenderBlock* cloneChild = cloneBlock;
483         cloneBlock = blockCurr->clone();
484 
485         // Insert our child clone as the first child.
486         cloneBlock->children()->appendChildNode(cloneBlock, cloneChild);
487 
488         // Hook the clone up as a continuation of |curr|.  Note we do encounter
489         // anonymous blocks possibly as we walk up the block chain.  When we split an
490         // anonymous block, there's no need to do any continuation hookup, since we haven't
491         // actually split a real element.
492         if (!blockCurr->isAnonymousBlock()) {
493             oldCont = blockCurr->continuation();
494             blockCurr->setContinuation(cloneBlock);
495             cloneBlock->setContinuation(oldCont);
496         }
497 
498         // Someone may have indirectly caused a <q> to split.  When this happens, the :after content
499         // has to move into the inline continuation.  Call updateBeforeAfterContent to ensure that the inline's :after
500         // content gets properly destroyed.
501         if (document()->usesBeforeAfterRules())
502             blockCurr->children()->updateBeforeAfterContent(blockCurr, AFTER);
503 
504         // Now we need to take all of the children starting from the first child
505         // *after* currChild and append them all to the clone.
506         RenderObject* afterContent = isAfterContent(cloneBlock->lastChild()) ? cloneBlock->lastChild() : 0;
507         blockCurr->moveChildrenTo(cloneBlock, currChild->nextSibling(), 0, afterContent);
508 
509         // Keep walking up the chain.
510         currChild = curr;
511         curr = toRenderBoxModelObject(curr->parent());
512     }
513 
514     // Now we are at the columns block level. We need to put the clone into the toBlock.
515     toBlock->children()->appendChildNode(toBlock, cloneBlock);
516 
517     // Now take all the children after currChild and remove them from the fromBlock
518     // and put them in the toBlock.
519     fromBlock->moveChildrenTo(toBlock, currChild->nextSibling(), 0);
520 }
521 
splitFlow(RenderObject * beforeChild,RenderBlock * newBlockBox,RenderObject * newChild,RenderBoxModelObject * oldCont)522 void RenderBlock::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
523                             RenderObject* newChild, RenderBoxModelObject* oldCont)
524 {
525     RenderBlock* pre = 0;
526     RenderBlock* block = containingColumnsBlock();
527 
528     // Delete our line boxes before we do the inline split into continuations.
529     block->deleteLineBoxTree();
530 
531     bool madeNewBeforeBlock = false;
532     if (block->isAnonymousColumnsBlock()) {
533         // We can reuse this block and make it the preBlock of the next continuation.
534         pre = block;
535         pre->removePositionedObjects(0);
536         block = toRenderBlock(block->parent());
537     } else {
538         // No anonymous block available for use.  Make one.
539         pre = block->createAnonymousColumnsBlock();
540         pre->setChildrenInline(false);
541         madeNewBeforeBlock = true;
542     }
543 
544     RenderBlock* post = block->createAnonymousColumnsBlock();
545     post->setChildrenInline(false);
546 
547     RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling();
548     if (madeNewBeforeBlock)
549         block->children()->insertChildNode(block, pre, boxFirst);
550     block->children()->insertChildNode(block, newBlockBox, boxFirst);
551     block->children()->insertChildNode(block, post, boxFirst);
552     block->setChildrenInline(false);
553 
554     if (madeNewBeforeBlock)
555         block->moveChildrenTo(pre, boxFirst, 0);
556 
557     splitBlocks(pre, post, newBlockBox, beforeChild, oldCont);
558 
559     // We already know the newBlockBox isn't going to contain inline kids, so avoid wasting
560     // time in makeChildrenNonInline by just setting this explicitly up front.
561     newBlockBox->setChildrenInline(false);
562 
563     // We delayed adding the newChild until now so that the |newBlockBox| would be fully
564     // connected, thus allowing newChild access to a renderArena should it need
565     // to wrap itself in additional boxes (e.g., table construction).
566     newBlockBox->addChild(newChild);
567 
568     // Always just do a full layout in order to ensure that line boxes (especially wrappers for images)
569     // get deleted properly.  Because objects moves from the pre block into the post block, we want to
570     // make new line boxes instead of leaving the old line boxes around.
571     pre->setNeedsLayoutAndPrefWidthsRecalc();
572     block->setNeedsLayoutAndPrefWidthsRecalc();
573     post->setNeedsLayoutAndPrefWidthsRecalc();
574 }
575 
splitAnonymousBlocksAroundChild(RenderObject * beforeChild)576 RenderObject* RenderBlock::splitAnonymousBlocksAroundChild(RenderObject* beforeChild)
577 {
578     while (beforeChild->parent() != this) {
579         RenderBlock* blockToSplit = toRenderBlock(beforeChild->parent());
580         if (blockToSplit->firstChild() != beforeChild) {
581             // We have to split the parentBlock into two blocks.
582             RenderBlock* post = createAnonymousBlockWithSameTypeAs(blockToSplit);
583             post->setChildrenInline(blockToSplit->childrenInline());
584             RenderBlock* parentBlock = toRenderBlock(blockToSplit->parent());
585             parentBlock->children()->insertChildNode(parentBlock, post, blockToSplit->nextSibling());
586             blockToSplit->moveChildrenTo(post, beforeChild, 0, blockToSplit->hasLayer());
587             post->setNeedsLayoutAndPrefWidthsRecalc();
588             blockToSplit->setNeedsLayoutAndPrefWidthsRecalc();
589             beforeChild = post;
590         } else
591             beforeChild = blockToSplit;
592     }
593     return beforeChild;
594 }
595 
makeChildrenAnonymousColumnBlocks(RenderObject * beforeChild,RenderBlock * newBlockBox,RenderObject * newChild)596 void RenderBlock::makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, RenderBlock* newBlockBox, RenderObject* newChild)
597 {
598     RenderBlock* pre = 0;
599     RenderBlock* post = 0;
600     RenderBlock* block = this; // Eventually block will not just be |this|, but will also be a block nested inside |this|.  Assign to a variable
601                                // so that we don't have to patch all of the rest of the code later on.
602 
603     // Delete the block's line boxes before we do the split.
604     block->deleteLineBoxTree();
605 
606     if (beforeChild && beforeChild->parent() != this)
607         beforeChild = splitAnonymousBlocksAroundChild(beforeChild);
608 
609     if (beforeChild != firstChild()) {
610         pre = block->createAnonymousColumnsBlock();
611         pre->setChildrenInline(block->childrenInline());
612     }
613 
614     if (beforeChild) {
615         post = block->createAnonymousColumnsBlock();
616         post->setChildrenInline(block->childrenInline());
617     }
618 
619     RenderObject* boxFirst = block->firstChild();
620     if (pre)
621         block->children()->insertChildNode(block, pre, boxFirst);
622     block->children()->insertChildNode(block, newBlockBox, boxFirst);
623     if (post)
624         block->children()->insertChildNode(block, post, boxFirst);
625     block->setChildrenInline(false);
626 
627     // 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).
628     block->moveChildrenTo(pre, boxFirst, beforeChild, true);
629     block->moveChildrenTo(post, beforeChild, 0, true);
630 
631     // We already know the newBlockBox isn't going to contain inline kids, so avoid wasting
632     // time in makeChildrenNonInline by just setting this explicitly up front.
633     newBlockBox->setChildrenInline(false);
634 
635     // We delayed adding the newChild until now so that the |newBlockBox| would be fully
636     // connected, thus allowing newChild access to a renderArena should it need
637     // to wrap itself in additional boxes (e.g., table construction).
638     newBlockBox->addChild(newChild);
639 
640     // Always just do a full layout in order to ensure that line boxes (especially wrappers for images)
641     // get deleted properly.  Because objects moved from the pre block into the post block, we want to
642     // make new line boxes instead of leaving the old line boxes around.
643     if (pre)
644         pre->setNeedsLayoutAndPrefWidthsRecalc();
645     block->setNeedsLayoutAndPrefWidthsRecalc();
646     if (post)
647         post->setNeedsLayoutAndPrefWidthsRecalc();
648 }
649 
columnsBlockForSpanningElement(RenderObject * newChild)650 RenderBlock* RenderBlock::columnsBlockForSpanningElement(RenderObject* newChild)
651 {
652     // FIXME: This function is the gateway for the addition of column-span support.  It will
653     // be added to in three stages:
654     // (1) Immediate children of a multi-column block can span.
655     // (2) Nested block-level children with only block-level ancestors between them and the multi-column block can span.
656     // (3) Nested children with block or inline ancestors between them and the multi-column block can span (this is when we
657     // cross the streams and have to cope with both types of continuations mixed together).
658     // This function currently supports (1) and (2).
659     RenderBlock* columnsBlockAncestor = 0;
660     if (!newChild->isText() && newChild->style()->columnSpan() && !newChild->isFloatingOrPositioned()
661         && !newChild->isInline() && !isAnonymousColumnSpanBlock()) {
662         if (style()->specifiesColumns())
663             columnsBlockAncestor = this;
664         else if (parent() && parent()->isRenderBlock())
665             columnsBlockAncestor = toRenderBlock(parent())->containingColumnsBlock(false);
666     }
667     return columnsBlockAncestor;
668 }
669 
addChildIgnoringAnonymousColumnBlocks(RenderObject * newChild,RenderObject * beforeChild)670 void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild)
671 {
672     // Make sure we don't append things after :after-generated content if we have it.
673     if (!beforeChild) {
674         RenderObject* lastRenderer = lastChild();
675         if (isAfterContent(lastRenderer))
676             beforeChild = lastRenderer;
677         else if (lastRenderer && lastRenderer->isAnonymousBlock() && isAfterContent(lastRenderer->lastChild()))
678             beforeChild = lastRenderer->lastChild();
679     }
680 
681     // If the requested beforeChild is not one of our children, then this is because
682     // there is an anonymous container within this object that contains the beforeChild.
683     if (beforeChild && beforeChild->parent() != this) {
684         RenderObject* anonymousChild = beforeChild->parent();
685         ASSERT(anonymousChild);
686 
687         while (anonymousChild->parent() != this)
688             anonymousChild = anonymousChild->parent();
689 
690         ASSERT(anonymousChild->isAnonymous());
691 
692         if (anonymousChild->isAnonymousBlock()) {
693             // Insert the child into the anonymous block box instead of here.
694             if (newChild->isInline() || beforeChild->parent()->firstChild() != beforeChild)
695                 beforeChild->parent()->addChild(newChild, beforeChild);
696             else
697                 addChild(newChild, beforeChild->parent());
698             return;
699         }
700 
701         ASSERT(anonymousChild->isTable());
702         if ((newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP)
703                 || (newChild->isRenderBlock() && newChild->style()->display() == TABLE_CAPTION)
704                 || newChild->isTableSection()
705                 || newChild->isTableRow()
706                 || newChild->isTableCell()) {
707             // Insert into the anonymous table.
708             anonymousChild->addChild(newChild, beforeChild);
709             return;
710         }
711 
712         // Go on to insert before the anonymous table.
713         beforeChild = anonymousChild;
714     }
715 
716     // Check for a spanning element in columns.
717     RenderBlock* columnsBlockAncestor = columnsBlockForSpanningElement(newChild);
718     if (columnsBlockAncestor) {
719         // We are placing a column-span element inside a block.
720         RenderBlock* newBox = createAnonymousColumnSpanBlock();
721 
722         if (columnsBlockAncestor != this) {
723             // We are nested inside a multi-column element and are being split by the span.  We have to break up
724             // our block into continuations.
725             RenderBoxModelObject* oldContinuation = continuation();
726             setContinuation(newBox);
727 
728             // Someone may have put a <p> inside a <q>, causing a split.  When this happens, the :after content
729             // has to move into the inline continuation.  Call updateBeforeAfterContent to ensure that our :after
730             // content gets properly destroyed.
731             bool isLastChild = (beforeChild == lastChild());
732             if (document()->usesBeforeAfterRules())
733                 children()->updateBeforeAfterContent(this, AFTER);
734             if (isLastChild && beforeChild != lastChild())
735                 beforeChild = 0; // We destroyed the last child, so now we need to update our insertion
736                                  // point to be 0.  It's just a straight append now.
737 
738             splitFlow(beforeChild, newBox, newChild, oldContinuation);
739             return;
740         }
741 
742         // We have to perform a split of this block's children.  This involves creating an anonymous block box to hold
743         // the column-spanning |newChild|.  We take all of the children from before |newChild| and put them into
744         // one anonymous columns block, and all of the children after |newChild| go into another anonymous block.
745         makeChildrenAnonymousColumnBlocks(beforeChild, newBox, newChild);
746         return;
747     }
748 
749     bool madeBoxesNonInline = false;
750 
751     // A block has to either have all of its children inline, or all of its children as blocks.
752     // So, if our children are currently inline and a block child has to be inserted, we move all our
753     // inline children into anonymous block boxes.
754     if (childrenInline() && !newChild->isInline() && !newChild->isFloatingOrPositioned()) {
755         // This is a block with inline content. Wrap the inline content in anonymous blocks.
756         makeChildrenNonInline(beforeChild);
757         madeBoxesNonInline = true;
758 
759         if (beforeChild && beforeChild->parent() != this) {
760             beforeChild = beforeChild->parent();
761             ASSERT(beforeChild->isAnonymousBlock());
762             ASSERT(beforeChild->parent() == this);
763         }
764     } else if (!childrenInline() && (newChild->isFloatingOrPositioned() || newChild->isInline())) {
765         // If we're inserting an inline child but all of our children are blocks, then we have to make sure
766         // it is put into an anomyous block box. We try to use an existing anonymous box if possible, otherwise
767         // a new one is created and inserted into our list of children in the appropriate position.
768         RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : lastChild();
769 
770         if (afterChild && afterChild->isAnonymousBlock()) {
771             afterChild->addChild(newChild);
772             return;
773         }
774 
775         if (newChild->isInline()) {
776             // No suitable existing anonymous box - create a new one.
777             RenderBlock* newBox = createAnonymousBlock();
778             RenderBox::addChild(newBox, beforeChild);
779             newBox->addChild(newChild);
780             return;
781         }
782     }
783 
784     RenderBox::addChild(newChild, beforeChild);
785 
786     if (madeBoxesNonInline && parent() && isAnonymousBlock() && parent()->isRenderBlock())
787         toRenderBlock(parent())->removeLeftoverAnonymousBlock(this);
788     // this object may be dead here
789 }
790 
addChild(RenderObject * newChild,RenderObject * beforeChild)791 void RenderBlock::addChild(RenderObject* newChild, RenderObject* beforeChild)
792 {
793     if (continuation() && !isAnonymousBlock())
794         return addChildToContinuation(newChild, beforeChild);
795     return addChildIgnoringContinuation(newChild, beforeChild);
796 }
797 
addChildIgnoringContinuation(RenderObject * newChild,RenderObject * beforeChild)798 void RenderBlock::addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild)
799 {
800     if (!isAnonymousBlock() && firstChild() && (firstChild()->isAnonymousColumnsBlock() || firstChild()->isAnonymousColumnSpanBlock()))
801         return addChildToAnonymousColumnBlocks(newChild, beforeChild);
802     return addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild);
803 }
804 
getInlineRun(RenderObject * start,RenderObject * boundary,RenderObject * & inlineRunStart,RenderObject * & inlineRunEnd)805 static void getInlineRun(RenderObject* start, RenderObject* boundary,
806                          RenderObject*& inlineRunStart,
807                          RenderObject*& inlineRunEnd)
808 {
809     // Beginning at |start| we find the largest contiguous run of inlines that
810     // we can.  We denote the run with start and end points, |inlineRunStart|
811     // and |inlineRunEnd|.  Note that these two values may be the same if
812     // we encounter only one inline.
813     //
814     // We skip any non-inlines we encounter as long as we haven't found any
815     // inlines yet.
816     //
817     // |boundary| indicates a non-inclusive boundary point.  Regardless of whether |boundary|
818     // is inline or not, we will not include it in a run with inlines before it.  It's as though we encountered
819     // a non-inline.
820 
821     // Start by skipping as many non-inlines as we can.
822     RenderObject * curr = start;
823     bool sawInline;
824     do {
825         while (curr && !(curr->isInline() || curr->isFloatingOrPositioned()))
826             curr = curr->nextSibling();
827 
828         inlineRunStart = inlineRunEnd = curr;
829 
830         if (!curr)
831             return; // No more inline children to be found.
832 
833         sawInline = curr->isInline();
834 
835         curr = curr->nextSibling();
836         while (curr && (curr->isInline() || curr->isFloatingOrPositioned()) && (curr != boundary)) {
837             inlineRunEnd = curr;
838             if (curr->isInline())
839                 sawInline = true;
840             curr = curr->nextSibling();
841         }
842     } while (!sawInline);
843 }
844 
deleteLineBoxTree()845 void RenderBlock::deleteLineBoxTree()
846 {
847     m_lineBoxes.deleteLineBoxTree(renderArena());
848 }
849 
createRootInlineBox()850 RootInlineBox* RenderBlock::createRootInlineBox()
851 {
852     return new (renderArena()) RootInlineBox(this);
853 }
854 
createAndAppendRootInlineBox()855 RootInlineBox* RenderBlock::createAndAppendRootInlineBox()
856 {
857     RootInlineBox* rootBox = createRootInlineBox();
858     m_lineBoxes.appendLineBox(rootBox);
859     return rootBox;
860 }
861 
moveChildTo(RenderBlock * to,RenderObject * child,RenderObject * beforeChild,bool fullRemoveInsert)862 void RenderBlock::moveChildTo(RenderBlock* to, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert)
863 {
864     ASSERT(this == child->parent());
865     ASSERT(!beforeChild || to == beforeChild->parent());
866     to->children()->insertChildNode(to, children()->removeChildNode(this, child, fullRemoveInsert), beforeChild, fullRemoveInsert);
867 }
868 
moveChildrenTo(RenderBlock * to,RenderObject * startChild,RenderObject * endChild,RenderObject * beforeChild,bool fullRemoveInsert)869 void RenderBlock::moveChildrenTo(RenderBlock* to, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert)
870 {
871     ASSERT(!beforeChild || to == beforeChild->parent());
872     RenderObject* nextChild = startChild;
873     while (nextChild && nextChild != endChild) {
874         RenderObject* child = nextChild;
875         nextChild = child->nextSibling();
876         to->children()->insertChildNode(to, children()->removeChildNode(this, child, fullRemoveInsert), beforeChild, fullRemoveInsert);
877         if (child == endChild)
878             return;
879     }
880 }
881 
makeChildrenNonInline(RenderObject * insertionPoint)882 void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
883 {
884     // makeChildrenNonInline takes a block whose children are *all* inline and it
885     // makes sure that inline children are coalesced under anonymous
886     // blocks.  If |insertionPoint| is defined, then it represents the insertion point for
887     // the new block child that is causing us to have to wrap all the inlines.  This
888     // means that we cannot coalesce inlines before |insertionPoint| with inlines following
889     // |insertionPoint|, because the new child is going to be inserted in between the inlines,
890     // splitting them.
891     ASSERT(isInlineBlockOrInlineTable() || !isInline());
892     ASSERT(!insertionPoint || insertionPoint->parent() == this);
893 
894     setChildrenInline(false);
895 
896     RenderObject *child = firstChild();
897     if (!child)
898         return;
899 
900     deleteLineBoxTree();
901 
902     while (child) {
903         RenderObject *inlineRunStart, *inlineRunEnd;
904         getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd);
905 
906         if (!inlineRunStart)
907             break;
908 
909         child = inlineRunEnd->nextSibling();
910 
911         RenderBlock* block = createAnonymousBlock();
912         children()->insertChildNode(this, block, inlineRunStart);
913         moveChildrenTo(block, inlineRunStart, child);
914     }
915 
916 #ifndef NDEBUG
917     for (RenderObject *c = firstChild(); c; c = c->nextSibling())
918         ASSERT(!c->isInline());
919 #endif
920 
921     repaint();
922 }
923 
removeLeftoverAnonymousBlock(RenderBlock * child)924 void RenderBlock::removeLeftoverAnonymousBlock(RenderBlock* child)
925 {
926     ASSERT(child->isAnonymousBlock());
927     ASSERT(!child->childrenInline());
928 
929     if (child->continuation() || (child->firstChild() && (child->isAnonymousColumnSpanBlock() || child->isAnonymousColumnsBlock())))
930         return;
931 
932     RenderObject* firstAnChild = child->m_children.firstChild();
933     RenderObject* lastAnChild = child->m_children.lastChild();
934     if (firstAnChild) {
935         RenderObject* o = firstAnChild;
936         while (o) {
937             o->setParent(this);
938             o = o->nextSibling();
939         }
940         firstAnChild->setPreviousSibling(child->previousSibling());
941         lastAnChild->setNextSibling(child->nextSibling());
942         if (child->previousSibling())
943             child->previousSibling()->setNextSibling(firstAnChild);
944         if (child->nextSibling())
945             child->nextSibling()->setPreviousSibling(lastAnChild);
946 
947         if (child == m_children.firstChild())
948             m_children.setFirstChild(firstAnChild);
949         if (child == m_children.lastChild())
950             m_children.setLastChild(lastAnChild);
951     } else {
952         if (child == m_children.firstChild())
953             m_children.setFirstChild(child->nextSibling());
954         if (child == m_children.lastChild())
955             m_children.setLastChild(child->previousSibling());
956 
957         if (child->previousSibling())
958             child->previousSibling()->setNextSibling(child->nextSibling());
959         if (child->nextSibling())
960             child->nextSibling()->setPreviousSibling(child->previousSibling());
961     }
962     child->setParent(0);
963     child->setPreviousSibling(0);
964     child->setNextSibling(0);
965 
966     child->children()->setFirstChild(0);
967     child->m_next = 0;
968 
969     child->destroy();
970 }
971 
canMergeContiguousAnonymousBlocks(RenderObject * oldChild,RenderObject * prev,RenderObject * next)972 static bool canMergeContiguousAnonymousBlocks(RenderObject* oldChild, RenderObject* prev, RenderObject* next)
973 {
974     if (oldChild->documentBeingDestroyed() || oldChild->isInline() || oldChild->virtualContinuation())
975         return false;
976 
977     if (oldChild->parent() && oldChild->parent()->isDetails())
978         return false;
979 
980     if ((prev && (!prev->isAnonymousBlock() || toRenderBlock(prev)->continuation() || toRenderBlock(prev)->beingDestroyed()))
981         || (next && (!next->isAnonymousBlock() || toRenderBlock(next)->continuation() || toRenderBlock(next)->beingDestroyed())))
982         return false;
983 
984     // FIXME: This check isn't required when inline run-ins can't be split into continuations.
985     if (prev && prev->firstChild() && prev->firstChild()->isInline() && prev->firstChild()->isRunIn())
986         return false;
987 
988     if ((prev && (prev->isRubyRun() || prev->isRubyBase()))
989         || (next && (next->isRubyRun() || next->isRubyBase())))
990         return false;
991 
992     if (!prev || !next)
993         return true;
994 
995     // Make sure the types of the anonymous blocks match up.
996     return prev->isAnonymousColumnsBlock() == next->isAnonymousColumnsBlock()
997            && prev->isAnonymousColumnSpanBlock() == next->isAnonymousColumnSpanBlock();
998 }
999 
removeChild(RenderObject * oldChild)1000 void RenderBlock::removeChild(RenderObject* oldChild)
1001 {
1002     // If this child is a block, and if our previous and next siblings are
1003     // both anonymous blocks with inline content, then we can go ahead and
1004     // fold the inline content back together.
1005     RenderObject* prev = oldChild->previousSibling();
1006     RenderObject* next = oldChild->nextSibling();
1007     bool canMergeAnonymousBlocks = canMergeContiguousAnonymousBlocks(oldChild, prev, next);
1008     if (canMergeAnonymousBlocks && prev && next) {
1009         prev->setNeedsLayoutAndPrefWidthsRecalc();
1010         RenderBlock* nextBlock = toRenderBlock(next);
1011         RenderBlock* prevBlock = toRenderBlock(prev);
1012 
1013         if (prev->childrenInline() != next->childrenInline()) {
1014             RenderBlock* inlineChildrenBlock = prev->childrenInline() ? prevBlock : nextBlock;
1015             RenderBlock* blockChildrenBlock = prev->childrenInline() ? nextBlock : prevBlock;
1016 
1017             // Place the inline children block inside of the block children block instead of deleting it.
1018             // In order to reuse it, we have to reset it to just be a generic anonymous block.  Make sure
1019             // to clear out inherited column properties by just making a new style, and to also clear the
1020             // column span flag if it is set.
1021             ASSERT(!inlineChildrenBlock->continuation());
1022             RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style());
1023             children()->removeChildNode(this, inlineChildrenBlock, inlineChildrenBlock->hasLayer());
1024             inlineChildrenBlock->setStyle(newStyle);
1025 
1026             // Now just put the inlineChildrenBlock inside the blockChildrenBlock.
1027             blockChildrenBlock->children()->insertChildNode(blockChildrenBlock, inlineChildrenBlock, prev == inlineChildrenBlock ? blockChildrenBlock->firstChild() : 0,
1028                                                             inlineChildrenBlock->hasLayer() || blockChildrenBlock->hasLayer());
1029             next->setNeedsLayoutAndPrefWidthsRecalc();
1030 
1031             // inlineChildrenBlock got reparented to blockChildrenBlock, so it is no longer a child
1032             // of "this". we null out prev or next so that is not used later in the function.
1033             if (inlineChildrenBlock == prevBlock)
1034                 prev = 0;
1035             else
1036                 next = 0;
1037         } else {
1038             // Take all the children out of the |next| block and put them in
1039             // the |prev| block.
1040             nextBlock->moveAllChildrenTo(prevBlock, nextBlock->hasLayer() || prevBlock->hasLayer());
1041 
1042             // Delete the now-empty block's lines and nuke it.
1043             nextBlock->deleteLineBoxTree();
1044             nextBlock->destroy();
1045             next = 0;
1046         }
1047     }
1048 
1049     RenderBox::removeChild(oldChild);
1050 
1051     RenderObject* child = prev ? prev : next;
1052     if (canMergeAnonymousBlocks && child && !child->previousSibling() && !child->nextSibling() && !isFlexibleBox()) {
1053         // The removal has knocked us down to containing only a single anonymous
1054         // box.  We can go ahead and pull the content right back up into our
1055         // box.
1056         setNeedsLayoutAndPrefWidthsRecalc();
1057         setChildrenInline(child->childrenInline());
1058         RenderBlock* anonBlock = toRenderBlock(children()->removeChildNode(this, child, child->hasLayer()));
1059         anonBlock->moveAllChildrenTo(this, child->hasLayer());
1060         // Delete the now-empty block's lines and nuke it.
1061         anonBlock->deleteLineBoxTree();
1062         anonBlock->destroy();
1063     }
1064 
1065     if (!firstChild() && !documentBeingDestroyed()) {
1066         // If this was our last child be sure to clear out our line boxes.
1067         if (childrenInline())
1068             lineBoxes()->deleteLineBoxes(renderArena());
1069     }
1070 }
1071 
isSelfCollapsingBlock() const1072 bool RenderBlock::isSelfCollapsingBlock() const
1073 {
1074     // We are not self-collapsing if we
1075     // (a) have a non-zero height according to layout (an optimization to avoid wasting time)
1076     // (b) are a table,
1077     // (c) have border/padding,
1078     // (d) have a min-height
1079     // (e) have specified that one of our margins can't collapse using a CSS extension
1080     if (logicalHeight() > 0
1081         || isTable() || borderAndPaddingLogicalHeight()
1082         || style()->logicalMinHeight().isPositive()
1083         || style()->marginBeforeCollapse() == MSEPARATE || style()->marginAfterCollapse() == MSEPARATE)
1084         return false;
1085 
1086     Length logicalHeightLength = style()->logicalHeight();
1087     bool hasAutoHeight = logicalHeightLength.isAuto();
1088     if (logicalHeightLength.isPercent() && !document()->inQuirksMode()) {
1089         hasAutoHeight = true;
1090         for (RenderBlock* cb = containingBlock(); !cb->isRenderView(); cb = cb->containingBlock()) {
1091             if (cb->style()->logicalHeight().isFixed() || cb->isTableCell())
1092                 hasAutoHeight = false;
1093         }
1094     }
1095 
1096     // If the height is 0 or auto, then whether or not we are a self-collapsing block depends
1097     // on whether we have content that is all self-collapsing or not.
1098     if (hasAutoHeight || ((logicalHeightLength.isFixed() || logicalHeightLength.isPercent()) && logicalHeightLength.isZero())) {
1099         // If the block has inline children, see if we generated any line boxes.  If we have any
1100         // line boxes, then we can't be self-collapsing, since we have content.
1101         if (childrenInline())
1102             return !firstLineBox();
1103 
1104         // Whether or not we collapse is dependent on whether all our normal flow children
1105         // are also self-collapsing.
1106         for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
1107             if (child->isFloatingOrPositioned())
1108                 continue;
1109             if (!child->isSelfCollapsingBlock())
1110                 return false;
1111         }
1112         return true;
1113     }
1114     return false;
1115 }
1116 
startDelayUpdateScrollInfo()1117 void RenderBlock::startDelayUpdateScrollInfo()
1118 {
1119     if (gDelayUpdateScrollInfo == 0) {
1120         ASSERT(!gDelayedUpdateScrollInfoSet);
1121         gDelayedUpdateScrollInfoSet = new DelayedUpdateScrollInfoSet;
1122     }
1123     ASSERT(gDelayedUpdateScrollInfoSet);
1124     ++gDelayUpdateScrollInfo;
1125 }
1126 
finishDelayUpdateScrollInfo()1127 void RenderBlock::finishDelayUpdateScrollInfo()
1128 {
1129     --gDelayUpdateScrollInfo;
1130     ASSERT(gDelayUpdateScrollInfo >= 0);
1131     if (gDelayUpdateScrollInfo == 0) {
1132         ASSERT(gDelayedUpdateScrollInfoSet);
1133 
1134         OwnPtr<DelayedUpdateScrollInfoSet> infoSet(gDelayedUpdateScrollInfoSet);
1135         gDelayedUpdateScrollInfoSet = 0;
1136 
1137         for (DelayedUpdateScrollInfoSet::iterator it = infoSet->begin(); it != infoSet->end(); ++it) {
1138             RenderBlock* block = *it;
1139             if (block->hasOverflowClip()) {
1140                 block->layer()->updateScrollInfoAfterLayout();
1141             }
1142         }
1143     }
1144 }
1145 
updateScrollInfoAfterLayout()1146 void RenderBlock::updateScrollInfoAfterLayout()
1147 {
1148     if (hasOverflowClip()) {
1149         if (gDelayUpdateScrollInfo)
1150             gDelayedUpdateScrollInfoSet->add(this);
1151         else
1152             layer()->updateScrollInfoAfterLayout();
1153     }
1154 }
1155 
layout()1156 void RenderBlock::layout()
1157 {
1158     // Update our first letter info now.
1159     updateFirstLetter();
1160 
1161     // Table cells call layoutBlock directly, so don't add any logic here.  Put code into
1162     // layoutBlock().
1163     layoutBlock(false);
1164 
1165     // It's safe to check for control clip here, since controls can never be table cells.
1166     // If we have a lightweight clip, there can never be any overflow from children.
1167     if (hasControlClip() && m_overflow)
1168         clearLayoutOverflow();
1169 }
1170 
layoutBlock(bool relayoutChildren,int pageLogicalHeight)1171 void RenderBlock::layoutBlock(bool relayoutChildren, int pageLogicalHeight)
1172 {
1173     ASSERT(needsLayout());
1174 
1175     if (isInline() && !isInlineBlockOrInlineTable()) // Inline <form>s inside various table elements can
1176         return;                                      // cause us to come in here.  Just bail.
1177 
1178     if (!relayoutChildren && simplifiedLayout())
1179         return;
1180 
1181     LayoutRepainter repainter(*this, m_everHadLayout && checkForRepaintDuringLayout());
1182 
1183     int oldWidth = logicalWidth();
1184     int oldColumnWidth = desiredColumnWidth();
1185 
1186     computeLogicalWidth();
1187     calcColumnWidth();
1188 
1189     m_overflow.clear();
1190 
1191     if (oldWidth != logicalWidth() || oldColumnWidth != desiredColumnWidth())
1192         relayoutChildren = true;
1193 
1194 #ifdef ANDROID_LAYOUT
1195     checkAndSetRelayoutChildren(&relayoutChildren);
1196 #endif
1197 
1198     clearFloats();
1199 
1200     int previousHeight = logicalHeight();
1201     setLogicalHeight(0);
1202     bool hasSpecifiedPageLogicalHeight = false;
1203     bool pageLogicalHeightChanged = false;
1204     ColumnInfo* colInfo = columnInfo();
1205     if (hasColumns()) {
1206         if (!pageLogicalHeight) {
1207             // We need to go ahead and set our explicit page height if one exists, so that we can
1208             // avoid doing two layout passes.
1209             computeLogicalHeight();
1210             int columnHeight = contentLogicalHeight();
1211             if (columnHeight > 0) {
1212                 pageLogicalHeight = columnHeight;
1213                 hasSpecifiedPageLogicalHeight = true;
1214             }
1215             setLogicalHeight(0);
1216         }
1217         if (colInfo->columnHeight() != pageLogicalHeight && m_everHadLayout) {
1218             colInfo->setColumnHeight(pageLogicalHeight);
1219             pageLogicalHeightChanged = true;
1220         }
1221 
1222         if (!hasSpecifiedPageLogicalHeight && !pageLogicalHeight)
1223             colInfo->clearForcedBreaks();
1224     }
1225 
1226     LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode(), pageLogicalHeight, pageLogicalHeightChanged, colInfo);
1227 
1228     // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, to track
1229     // our current maximal positive and negative margins.  These values are used when we
1230     // are collapsed with adjacent blocks, so for example, if you have block A and B
1231     // collapsing together, then you'd take the maximal positive margin from both A and B
1232     // and subtract it from the maximal negative margin from both A and B to get the
1233     // true collapsed margin.  This algorithm is recursive, so when we finish layout()
1234     // our block knows its current maximal positive/negative values.
1235     //
1236     // Start out by setting our margin values to our current margins.  Table cells have
1237     // no margins, so we don't fill in the values for table cells.
1238     bool isCell = isTableCell();
1239     if (!isCell) {
1240         initMaxMarginValues();
1241 
1242         setMarginBeforeQuirk(style()->marginBefore().quirk());
1243         setMarginAfterQuirk(style()->marginAfter().quirk());
1244 
1245         Node* n = node();
1246         if (n && n->hasTagName(formTag) && static_cast<HTMLFormElement*>(n)->isMalformed()) {
1247             // See if this form is malformed (i.e., unclosed). If so, don't give the form
1248             // a bottom margin.
1249             setMaxMarginAfterValues(0, 0);
1250         }
1251 
1252         setPaginationStrut(0);
1253     }
1254 
1255     // For overflow:scroll blocks, ensure we have both scrollbars in place always.
1256     if (scrollsOverflow()) {
1257         if (style()->overflowX() == OSCROLL)
1258             layer()->setHasHorizontalScrollbar(true);
1259         if (style()->overflowY() == OSCROLL)
1260             layer()->setHasVerticalScrollbar(true);
1261     }
1262 
1263     int repaintLogicalTop = 0;
1264     int repaintLogicalBottom = 0;
1265     int maxFloatLogicalBottom = 0;
1266     if (!firstChild() && !isAnonymousBlock())
1267         setChildrenInline(true);
1268     if (childrenInline())
1269         layoutInlineChildren(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
1270     else
1271         layoutBlockChildren(relayoutChildren, maxFloatLogicalBottom);
1272 
1273     // Expand our intrinsic height to encompass floats.
1274     int toAdd = borderAfter() + paddingAfter() + scrollbarLogicalHeight();
1275     if (lowestFloatLogicalBottom() > (logicalHeight() - toAdd) && expandsToEncloseOverhangingFloats())
1276         setLogicalHeight(lowestFloatLogicalBottom() + toAdd);
1277 
1278     if (layoutColumns(hasSpecifiedPageLogicalHeight, pageLogicalHeight, statePusher))
1279         return;
1280 
1281     // Calculate our new height.
1282     int oldHeight = logicalHeight();
1283     int oldClientAfterEdge = clientLogicalBottom();
1284     computeLogicalHeight();
1285     int newHeight = logicalHeight();
1286     if (oldHeight != newHeight) {
1287         if (oldHeight > newHeight && maxFloatLogicalBottom > newHeight && !childrenInline()) {
1288             // One of our children's floats may have become an overhanging float for us. We need to look for it.
1289             for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
1290                 if (child->isBlockFlow() && !child->isFloatingOrPositioned()) {
1291                     RenderBlock* block = toRenderBlock(child);
1292                     if (block->lowestFloatLogicalBottom() + block->logicalTop() > newHeight)
1293                         addOverhangingFloats(block, -block->logicalLeft(), -block->logicalTop(), false);
1294                 }
1295             }
1296         }
1297     }
1298 
1299     if (previousHeight != newHeight)
1300         relayoutChildren = true;
1301 
1302     layoutPositionedObjects(relayoutChildren || isRoot());
1303 
1304     // Add overflow from children (unless we're multi-column, since in that case all our child overflow is clipped anyway).
1305     computeOverflow(oldClientAfterEdge);
1306 
1307     statePusher.pop();
1308 
1309     if (view()->layoutState()->m_pageLogicalHeight)
1310         setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(logicalTop()));
1311 
1312     updateLayerTransform();
1313 
1314     // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
1315     // we overflow or not.
1316     updateScrollInfoAfterLayout();
1317 
1318     // Repaint with our new bounds if they are different from our old bounds.
1319     bool didFullRepaint = repainter.repaintAfterLayout();
1320     if (!didFullRepaint && repaintLogicalTop != repaintLogicalBottom && (style()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) {
1321         // FIXME: We could tighten up the left and right invalidation points if we let layoutInlineChildren fill them in based off the particular lines
1322         // it had to lay out.  We wouldn't need the hasOverflowClip() hack in that case either.
1323         int repaintLogicalLeft = logicalLeftVisualOverflow();
1324         int repaintLogicalRight = logicalRightVisualOverflow();
1325         if (hasOverflowClip()) {
1326             // 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.
1327             // 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.
1328             // layoutInlineChildren should be patched to compute the entire repaint rect.
1329             repaintLogicalLeft = min(repaintLogicalLeft, logicalLeftLayoutOverflow());
1330             repaintLogicalRight = max(repaintLogicalRight, logicalRightLayoutOverflow());
1331         }
1332 
1333         IntRect repaintRect;
1334         if (isHorizontalWritingMode())
1335             repaintRect = IntRect(repaintLogicalLeft, repaintLogicalTop, repaintLogicalRight - repaintLogicalLeft, repaintLogicalBottom - repaintLogicalTop);
1336         else
1337             repaintRect = IntRect(repaintLogicalTop, repaintLogicalLeft, repaintLogicalBottom - repaintLogicalTop, repaintLogicalRight - repaintLogicalLeft);
1338 
1339         // The repaint rect may be split across columns, in which case adjustRectForColumns() will return the union.
1340         adjustRectForColumns(repaintRect);
1341 
1342         repaintRect.inflate(maximalOutlineSize(PaintPhaseOutline));
1343 
1344         if (hasOverflowClip()) {
1345             // Adjust repaint rect for scroll offset
1346             repaintRect.move(-layer()->scrolledContentOffset());
1347 
1348             // Don't allow this rect to spill out of our overflow box.
1349             repaintRect.intersect(IntRect(0, 0, width(), height()));
1350         }
1351 
1352         // Make sure the rect is still non-empty after intersecting for overflow above
1353         if (!repaintRect.isEmpty()) {
1354             repaintRectangle(repaintRect); // We need to do a partial repaint of our content.
1355             if (hasReflection())
1356                 repaintRectangle(reflectedRect(repaintRect));
1357         }
1358     }
1359     setNeedsLayout(false);
1360 }
1361 
addOverflowFromChildren()1362 void RenderBlock::addOverflowFromChildren()
1363 {
1364     if (!hasColumns()) {
1365         if (childrenInline())
1366             addOverflowFromInlineChildren();
1367         else
1368             addOverflowFromBlockChildren();
1369     } else {
1370         ColumnInfo* colInfo = columnInfo();
1371         if (columnCount(colInfo)) {
1372             IntRect lastRect = columnRectAt(colInfo, columnCount(colInfo) - 1);
1373             if (isHorizontalWritingMode()) {
1374                 int overflowLeft = !style()->isLeftToRightDirection() ? min(0, lastRect.x()) : 0;
1375                 int overflowRight = style()->isLeftToRightDirection() ? max(width(), lastRect.maxX()) : 0;
1376                 int overflowHeight = borderBefore() + paddingBefore() + colInfo->columnHeight();
1377                 addLayoutOverflow(IntRect(overflowLeft, 0, overflowRight - overflowLeft, overflowHeight));
1378                 if (!hasOverflowClip())
1379                     addVisualOverflow(IntRect(overflowLeft, 0, overflowRight - overflowLeft, overflowHeight));
1380             } else {
1381                 IntRect lastRect = columnRectAt(colInfo, columnCount(colInfo) - 1);
1382                 int overflowTop = !style()->isLeftToRightDirection() ? min(0, lastRect.y()) : 0;
1383                 int overflowBottom = style()->isLeftToRightDirection() ? max(height(), lastRect.maxY()) : 0;
1384                 int overflowWidth = borderBefore() + paddingBefore() + colInfo->columnHeight();
1385                 addLayoutOverflow(IntRect(0, overflowTop, overflowWidth, overflowBottom - overflowTop));
1386                 if (!hasOverflowClip())
1387                     addVisualOverflow(IntRect(0, overflowTop, overflowWidth, overflowBottom - overflowTop));
1388             }
1389         }
1390     }
1391 }
1392 
computeOverflow(int oldClientAfterEdge,bool recomputeFloats)1393 void RenderBlock::computeOverflow(int oldClientAfterEdge, bool recomputeFloats)
1394 {
1395     // Add overflow from children.
1396     addOverflowFromChildren();
1397 
1398     if (!hasColumns() && (recomputeFloats || isRoot() || expandsToEncloseOverhangingFloats() || hasSelfPaintingLayer()))
1399         addOverflowFromFloats();
1400 
1401     // Add in the overflow from positioned objects.
1402     addOverflowFromPositionedObjects();
1403 
1404     if (hasOverflowClip()) {
1405         // When we have overflow clip, propagate the original spillout since it will include collapsed bottom margins
1406         // and bottom padding.  Set the axis we don't care about to be 1, since we want this overflow to always
1407         // be considered reachable.
1408         IntRect clientRect(clientBoxRect());
1409         IntRect rectToApply;
1410         if (isHorizontalWritingMode())
1411             rectToApply = IntRect(clientRect.x(), clientRect.y(), 1, max(0, oldClientAfterEdge - clientRect.y()));
1412         else
1413             rectToApply = IntRect(clientRect.x(), clientRect.y(), max(0, oldClientAfterEdge - clientRect.x()), 1);
1414         addLayoutOverflow(rectToApply);
1415     }
1416 
1417     // Add visual overflow from box-shadow and reflections.
1418     addShadowOverflow();
1419 }
1420 
addOverflowFromBlockChildren()1421 void RenderBlock::addOverflowFromBlockChildren()
1422 {
1423     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
1424         if (!child->isFloatingOrPositioned())
1425             addOverflowFromChild(child);
1426     }
1427 }
1428 
addOverflowFromFloats()1429 void RenderBlock::addOverflowFromFloats()
1430 {
1431     if (!m_floatingObjects)
1432         return;
1433 
1434     FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
1435     FloatingObjectSetIterator end = floatingObjectSet.end();
1436     for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
1437         FloatingObject* r = *it;
1438         if (r->m_isDescendant)
1439             addOverflowFromChild(r->m_renderer, IntSize(xPositionForFloatIncludingMargin(r), yPositionForFloatIncludingMargin(r)));
1440     }
1441     return;
1442 }
1443 
addOverflowFromPositionedObjects()1444 void RenderBlock::addOverflowFromPositionedObjects()
1445 {
1446     if (!m_positionedObjects)
1447         return;
1448 
1449     RenderBox* positionedObject;
1450     Iterator end = m_positionedObjects->end();
1451     for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
1452         positionedObject = *it;
1453 
1454         // Fixed positioned elements don't contribute to layout overflow, since they don't scroll with the content.
1455         if (positionedObject->style()->position() != FixedPosition)
1456             addOverflowFromChild(positionedObject);
1457     }
1458 }
1459 
expandsToEncloseOverhangingFloats() const1460 bool RenderBlock::expandsToEncloseOverhangingFloats() const
1461 {
1462     return isInlineBlockOrInlineTable() || isFloatingOrPositioned() || hasOverflowClip() || (parent() && parent()->isFlexibleBox())
1463            || hasColumns() || isTableCell() || isFieldset() || isWritingModeRoot();
1464 }
1465 
adjustPositionedBlock(RenderBox * child,const MarginInfo & marginInfo)1466 void RenderBlock::adjustPositionedBlock(RenderBox* child, const MarginInfo& marginInfo)
1467 {
1468     bool isHorizontal = isHorizontalWritingMode();
1469     bool hasStaticBlockPosition = child->style()->hasStaticBlockPosition(isHorizontal);
1470     RenderLayer* childLayer = child->layer();
1471 
1472     childLayer->setStaticInlinePosition(borderAndPaddingStart());
1473 
1474     int logicalTop = logicalHeight();
1475     if (!marginInfo.canCollapseWithMarginBefore()) {
1476         child->computeBlockDirectionMargins(this);
1477         int marginBefore = marginBeforeForChild(child);
1478         int collapsedBeforePos = marginInfo.positiveMargin();
1479         int collapsedBeforeNeg = marginInfo.negativeMargin();
1480         if (marginBefore > 0) {
1481             if (marginBefore > collapsedBeforePos)
1482                 collapsedBeforePos = marginBefore;
1483         } else {
1484             if (-marginBefore > collapsedBeforeNeg)
1485                 collapsedBeforeNeg = -marginBefore;
1486         }
1487         logicalTop += (collapsedBeforePos - collapsedBeforeNeg) - marginBefore;
1488     }
1489     if (childLayer->staticBlockPosition() != logicalTop) {
1490         childLayer->setStaticBlockPosition(logicalTop);
1491         if (hasStaticBlockPosition)
1492             child->setChildNeedsLayout(true, false);
1493     }
1494 }
1495 
adjustFloatingBlock(const MarginInfo & marginInfo)1496 void RenderBlock::adjustFloatingBlock(const MarginInfo& marginInfo)
1497 {
1498     // The float should be positioned taking into account the bottom margin
1499     // of the previous flow.  We add that margin into the height, get the
1500     // float positioned properly, and then subtract the margin out of the
1501     // height again.  In the case of self-collapsing blocks, we always just
1502     // use the top margins, since the self-collapsing block collapsed its
1503     // own bottom margin into its top margin.
1504     //
1505     // Note also that the previous flow may collapse its margin into the top of
1506     // our block.  If this is the case, then we do not add the margin in to our
1507     // height when computing the position of the float.   This condition can be tested
1508     // for by simply calling canCollapseWithMarginBefore.  See
1509     // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for
1510     // an example of this scenario.
1511     int marginOffset = marginInfo.canCollapseWithMarginBefore() ? 0 : marginInfo.margin();
1512     setLogicalHeight(logicalHeight() + marginOffset);
1513     positionNewFloats();
1514     setLogicalHeight(logicalHeight() - marginOffset);
1515 }
1516 
handleSpecialChild(RenderBox * child,const MarginInfo & marginInfo)1517 bool RenderBlock::handleSpecialChild(RenderBox* child, const MarginInfo& marginInfo)
1518 {
1519     // Handle in the given order
1520     return handlePositionedChild(child, marginInfo)
1521         || handleFloatingChild(child, marginInfo)
1522         || handleRunInChild(child);
1523 }
1524 
1525 
handlePositionedChild(RenderBox * child,const MarginInfo & marginInfo)1526 bool RenderBlock::handlePositionedChild(RenderBox* child, const MarginInfo& marginInfo)
1527 {
1528     if (child->isPositioned()) {
1529         child->containingBlock()->insertPositionedObject(child);
1530         adjustPositionedBlock(child, marginInfo);
1531         return true;
1532     }
1533     return false;
1534 }
1535 
handleFloatingChild(RenderBox * child,const MarginInfo & marginInfo)1536 bool RenderBlock::handleFloatingChild(RenderBox* child, const MarginInfo& marginInfo)
1537 {
1538     if (child->isFloating()) {
1539         insertFloatingObject(child);
1540         adjustFloatingBlock(marginInfo);
1541         return true;
1542     }
1543     return false;
1544 }
1545 
handleRunInChild(RenderBox * child)1546 bool RenderBlock::handleRunInChild(RenderBox* child)
1547 {
1548     // See if we have a run-in element with inline children.  If the
1549     // children aren't inline, then just treat the run-in as a normal
1550     // block.
1551     if (!child->isRunIn() || !child->childrenInline())
1552         return false;
1553     // FIXME: We don't handle non-block elements with run-in for now.
1554     if (!child->isRenderBlock())
1555         return false;
1556 
1557     RenderBlock* blockRunIn = toRenderBlock(child);
1558     RenderObject* curr = blockRunIn->nextSibling();
1559     if (!curr || !curr->isRenderBlock() || !curr->childrenInline() || curr->isRunIn() || curr->isAnonymous() || curr->isFloatingOrPositioned())
1560         return false;
1561 
1562     RenderBlock* currBlock = toRenderBlock(curr);
1563 
1564     // Remove the old child.
1565     children()->removeChildNode(this, blockRunIn);
1566 
1567     // Create an inline.
1568     Node* runInNode = blockRunIn->node();
1569     RenderInline* inlineRunIn = new (renderArena()) RenderInline(runInNode ? runInNode : document());
1570     inlineRunIn->setStyle(blockRunIn->style());
1571 
1572     bool runInIsGenerated = child->style()->styleType() == BEFORE || child->style()->styleType() == AFTER;
1573 
1574     // Move the nodes from the old child to the new child, but skip any :before/:after content.  It has already
1575     // been regenerated by the new inline.
1576     for (RenderObject* runInChild = blockRunIn->firstChild(); runInChild;) {
1577         RenderObject* nextSibling = runInChild->nextSibling();
1578         if (runInIsGenerated || (runInChild->style()->styleType() != BEFORE && runInChild->style()->styleType() != AFTER)) {
1579             blockRunIn->children()->removeChildNode(blockRunIn, runInChild, false);
1580             inlineRunIn->addChild(runInChild); // Use addChild instead of appendChildNode since it handles correct placement of the children relative to :after-generated content.
1581         }
1582         runInChild = nextSibling;
1583     }
1584 
1585     // 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
1586     // anything before the first child. e.g. details tag. See https://bugs.webkit.org/show_bug.cgi?id=58228.
1587     currBlock->addChild(inlineRunIn, currBlock->firstChild());
1588 
1589     // If the run-in had an element, we need to set the new renderer.
1590     if (runInNode)
1591         runInNode->setRenderer(inlineRunIn);
1592 
1593     // Destroy the block run-in, which includes deleting its line box tree.
1594     blockRunIn->deleteLineBoxTree();
1595     blockRunIn->destroy();
1596 
1597     // The block acts like an inline, so just null out its
1598     // position.
1599 
1600     return true;
1601 }
1602 
collapseMargins(RenderBox * child,MarginInfo & marginInfo)1603 int RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
1604 {
1605     // Get the four margin values for the child and cache them.
1606     const MarginValues childMargins = marginValuesForChild(child);
1607 
1608     // Get our max pos and neg top margins.
1609     int posTop = childMargins.positiveMarginBefore();
1610     int negTop = childMargins.negativeMarginBefore();
1611 
1612     // For self-collapsing blocks, collapse our bottom margins into our
1613     // top to get new posTop and negTop values.
1614     if (child->isSelfCollapsingBlock()) {
1615         posTop = max(posTop, childMargins.positiveMarginAfter());
1616         negTop = max(negTop, childMargins.negativeMarginAfter());
1617     }
1618 
1619     // See if the top margin is quirky. We only care if this child has
1620     // margins that will collapse with us.
1621     bool topQuirk = child->isMarginBeforeQuirk() || style()->marginBeforeCollapse() == MDISCARD;
1622 
1623     if (marginInfo.canCollapseWithMarginBefore()) {
1624         // This child is collapsing with the top of the
1625         // block.  If it has larger margin values, then we need to update
1626         // our own maximal values.
1627         if (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !topQuirk)
1628             setMaxMarginBeforeValues(max(posTop, maxPositiveMarginBefore()), max(negTop, maxNegativeMarginBefore()));
1629 
1630         // The minute any of the margins involved isn't a quirk, don't
1631         // collapse it away, even if the margin is smaller (www.webreference.com
1632         // has an example of this, a <dt> with 0.8em author-specified inside
1633         // a <dl> inside a <td>.
1634         if (!marginInfo.determinedMarginBeforeQuirk() && !topQuirk && (posTop - negTop)) {
1635             setMarginBeforeQuirk(false);
1636             marginInfo.setDeterminedMarginBeforeQuirk(true);
1637         }
1638 
1639         if (!marginInfo.determinedMarginBeforeQuirk() && topQuirk && !marginBefore())
1640             // We have no top margin and our top child has a quirky margin.
1641             // We will pick up this quirky margin and pass it through.
1642             // This deals with the <td><div><p> case.
1643             // Don't do this for a block that split two inlines though.  You do
1644             // still apply margins in this case.
1645             setMarginBeforeQuirk(true);
1646     }
1647 
1648     if (marginInfo.quirkContainer() && marginInfo.atBeforeSideOfBlock() && (posTop - negTop))
1649         marginInfo.setMarginBeforeQuirk(topQuirk);
1650 
1651     int beforeCollapseLogicalTop = logicalHeight();
1652     int logicalTop = beforeCollapseLogicalTop;
1653     if (child->isSelfCollapsingBlock()) {
1654         // This child has no height.  We need to compute our
1655         // position before we collapse the child's margins together,
1656         // so that we can get an accurate position for the zero-height block.
1657         int collapsedBeforePos = max(marginInfo.positiveMargin(), childMargins.positiveMarginBefore());
1658         int collapsedBeforeNeg = max(marginInfo.negativeMargin(), childMargins.negativeMarginBefore());
1659         marginInfo.setMargin(collapsedBeforePos, collapsedBeforeNeg);
1660 
1661         // Now collapse the child's margins together, which means examining our
1662         // bottom margin values as well.
1663         marginInfo.setPositiveMarginIfLarger(childMargins.positiveMarginAfter());
1664         marginInfo.setNegativeMarginIfLarger(childMargins.negativeMarginAfter());
1665 
1666         if (!marginInfo.canCollapseWithMarginBefore())
1667             // We need to make sure that the position of the self-collapsing block
1668             // is correct, since it could have overflowing content
1669             // that needs to be positioned correctly (e.g., a block that
1670             // had a specified height of 0 but that actually had subcontent).
1671             logicalTop = logicalHeight() + collapsedBeforePos - collapsedBeforeNeg;
1672     }
1673     else {
1674         if (child->style()->marginBeforeCollapse() == MSEPARATE) {
1675             setLogicalHeight(logicalHeight() + marginInfo.margin() + marginBeforeForChild(child));
1676             logicalTop = logicalHeight();
1677         }
1678         else if (!marginInfo.atBeforeSideOfBlock() ||
1679             (!marginInfo.canCollapseMarginBeforeWithChildren()
1680              && (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !marginInfo.marginBeforeQuirk()))) {
1681             // We're collapsing with a previous sibling's margins and not
1682             // with the top of the block.
1683             setLogicalHeight(logicalHeight() + max(marginInfo.positiveMargin(), posTop) - max(marginInfo.negativeMargin(), negTop));
1684             logicalTop = logicalHeight();
1685         }
1686 
1687         marginInfo.setPositiveMargin(childMargins.positiveMarginAfter());
1688         marginInfo.setNegativeMargin(childMargins.negativeMarginAfter());
1689 
1690         if (marginInfo.margin())
1691             marginInfo.setMarginAfterQuirk(child->isMarginAfterQuirk() || style()->marginAfterCollapse() == MDISCARD);
1692     }
1693 
1694     // If margins would pull us past the top of the next page, then we need to pull back and pretend like the margins
1695     // collapsed into the page edge.
1696     bool paginated = view()->layoutState()->isPaginated();
1697     if (paginated && logicalTop > beforeCollapseLogicalTop) {
1698         int oldLogicalTop = logicalTop;
1699         logicalTop = min(logicalTop, nextPageLogicalTop(beforeCollapseLogicalTop));
1700         setLogicalHeight(logicalHeight() + (logicalTop - oldLogicalTop));
1701     }
1702     return logicalTop;
1703 }
1704 
clearFloatsIfNeeded(RenderBox * child,MarginInfo & marginInfo,int oldTopPosMargin,int oldTopNegMargin,int yPos)1705 int RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, int oldTopPosMargin, int oldTopNegMargin, int yPos)
1706 {
1707     int heightIncrease = getClearDelta(child, yPos);
1708     if (!heightIncrease)
1709         return yPos;
1710 
1711     if (child->isSelfCollapsingBlock()) {
1712         // For self-collapsing blocks that clear, they can still collapse their
1713         // margins with following siblings.  Reset the current margins to represent
1714         // the self-collapsing block's margins only.
1715         // CSS2.1 states:
1716         // "An element that has had clearance applied to it never collapses its top margin with its parent block's bottom margin.
1717         // Therefore if we are at the bottom of the block, let's go ahead and reset margins to only include the
1718         // self-collapsing block's bottom margin.
1719         bool atBottomOfBlock = true;
1720         for (RenderBox* curr = child->nextSiblingBox(); curr && atBottomOfBlock; curr = curr->nextSiblingBox()) {
1721             if (!curr->isFloatingOrPositioned())
1722                 atBottomOfBlock = false;
1723         }
1724 
1725         MarginValues childMargins = marginValuesForChild(child);
1726         if (atBottomOfBlock) {
1727             marginInfo.setPositiveMargin(childMargins.positiveMarginAfter());
1728             marginInfo.setNegativeMargin(childMargins.negativeMarginAfter());
1729         } else {
1730             marginInfo.setPositiveMargin(max(childMargins.positiveMarginBefore(), childMargins.positiveMarginAfter()));
1731             marginInfo.setNegativeMargin(max(childMargins.negativeMarginBefore(), childMargins.negativeMarginAfter()));
1732         }
1733 
1734         // Adjust our height such that we are ready to be collapsed with subsequent siblings (or the bottom
1735         // of the parent block).
1736         setLogicalHeight(child->y() - max(0, marginInfo.margin()));
1737     } else
1738         // Increase our height by the amount we had to clear.
1739         setLogicalHeight(height() + heightIncrease);
1740 
1741     if (marginInfo.canCollapseWithMarginBefore()) {
1742         // We can no longer collapse with the top of the block since a clear
1743         // occurred.  The empty blocks collapse into the cleared block.
1744         // FIXME: This isn't quite correct.  Need clarification for what to do
1745         // if the height the cleared block is offset by is smaller than the
1746         // margins involved.
1747         setMaxMarginBeforeValues(oldTopPosMargin, oldTopNegMargin);
1748         marginInfo.setAtBeforeSideOfBlock(false);
1749     }
1750 
1751     return yPos + heightIncrease;
1752 }
1753 
estimateLogicalTopPosition(RenderBox * child,const MarginInfo & marginInfo)1754 int RenderBlock::estimateLogicalTopPosition(RenderBox* child, const MarginInfo& marginInfo)
1755 {
1756     // FIXME: We need to eliminate the estimation of vertical position, because when it's wrong we sometimes trigger a pathological
1757     // relayout if there are intruding floats.
1758     int logicalTopEstimate = logicalHeight();
1759     if (!marginInfo.canCollapseWithMarginBefore()) {
1760         int childMarginBefore = child->selfNeedsLayout() ? marginBeforeForChild(child) : collapsedMarginBeforeForChild(child);
1761         logicalTopEstimate += max(marginInfo.margin(), childMarginBefore);
1762     }
1763 
1764     bool paginated = view()->layoutState()->isPaginated();
1765 
1766     // Adjust logicalTopEstimate down to the next page if the margins are so large that we don't fit on the current
1767     // page.
1768     if (paginated && logicalTopEstimate > logicalHeight())
1769         logicalTopEstimate = min(logicalTopEstimate, nextPageLogicalTop(logicalHeight()));
1770 
1771     logicalTopEstimate += getClearDelta(child, logicalTopEstimate);
1772 
1773     if (paginated) {
1774         // If the object has a page or column break value of "before", then we should shift to the top of the next page.
1775         logicalTopEstimate = applyBeforeBreak(child, logicalTopEstimate);
1776 
1777         // For replaced elements and scrolled elements, we want to shift them to the next page if they don't fit on the current one.
1778         logicalTopEstimate = adjustForUnsplittableChild(child, logicalTopEstimate);
1779 
1780         if (!child->selfNeedsLayout() && child->isRenderBlock())
1781             logicalTopEstimate += toRenderBlock(child)->paginationStrut();
1782     }
1783 
1784     return logicalTopEstimate;
1785 }
1786 
determineLogicalLeftPositionForChild(RenderBox * child)1787 void RenderBlock::determineLogicalLeftPositionForChild(RenderBox* child)
1788 {
1789     int startPosition = borderStart() + paddingStart();
1790     int totalAvailableLogicalWidth = borderAndPaddingLogicalWidth() + availableLogicalWidth();
1791 
1792     // Add in our start margin.
1793     int childMarginStart = marginStartForChild(child);
1794     int newPosition = startPosition + childMarginStart;
1795 
1796     // Some objects (e.g., tables, horizontal rules, overflow:auto blocks) avoid floats.  They need
1797     // to shift over as necessary to dodge any floats that might get in the way.
1798     if (child->avoidsFloats()) {
1799         int startOff = style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(logicalHeight(), false) : totalAvailableLogicalWidth - logicalRightOffsetForLine(logicalHeight(), false);
1800         if (style()->textAlign() != WEBKIT_CENTER && !child->style()->marginStartUsing(style()).isAuto()) {
1801             if (childMarginStart < 0)
1802                 startOff += childMarginStart;
1803             newPosition = max(newPosition, startOff); // Let the float sit in the child's margin if it can fit.
1804         } else if (startOff != startPosition) {
1805             // The object is shifting to the "end" side of the block. The object might be centered, so we need to
1806             // recalculate our inline direction margins. Note that the containing block content
1807             // width computation will take into account the delta between |startOff| and |startPosition|
1808             // so that we can just pass the content width in directly to the |computeMarginsInContainingBlockInlineDirection|
1809             // function.
1810             child->computeInlineDirectionMargins(this, availableLogicalWidthForLine(logicalTopForChild(child), false), logicalWidthForChild(child));
1811             newPosition = startOff + marginStartForChild(child);
1812         }
1813     }
1814 
1815     setLogicalLeftForChild(child, style()->isLeftToRightDirection() ? newPosition : totalAvailableLogicalWidth - newPosition - logicalWidthForChild(child), ApplyLayoutDelta);
1816 }
1817 
setCollapsedBottomMargin(const MarginInfo & marginInfo)1818 void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo)
1819 {
1820     if (marginInfo.canCollapseWithMarginAfter() && !marginInfo.canCollapseWithMarginBefore()) {
1821         // Update our max pos/neg bottom margins, since we collapsed our bottom margins
1822         // with our children.
1823         setMaxMarginAfterValues(max(maxPositiveMarginAfter(), marginInfo.positiveMargin()), max(maxNegativeMarginAfter(), marginInfo.negativeMargin()));
1824 
1825         if (!marginInfo.marginAfterQuirk())
1826             setMarginAfterQuirk(false);
1827 
1828         if (marginInfo.marginAfterQuirk() && marginAfter() == 0)
1829             // We have no bottom margin and our last child has a quirky margin.
1830             // We will pick up this quirky margin and pass it through.
1831             // This deals with the <td><div><p> case.
1832             setMarginAfterQuirk(true);
1833     }
1834 }
1835 
handleAfterSideOfBlock(int beforeSide,int afterSide,MarginInfo & marginInfo)1836 void RenderBlock::handleAfterSideOfBlock(int beforeSide, int afterSide, MarginInfo& marginInfo)
1837 {
1838     marginInfo.setAtAfterSideOfBlock(true);
1839 
1840     // If we can't collapse with children then go ahead and add in the bottom margin.
1841     if (!marginInfo.canCollapseWithMarginAfter() && !marginInfo.canCollapseWithMarginBefore()
1842         && (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !marginInfo.marginAfterQuirk()))
1843         setLogicalHeight(logicalHeight() + marginInfo.margin());
1844 
1845     // Now add in our bottom border/padding.
1846     setLogicalHeight(logicalHeight() + afterSide);
1847 
1848     // Negative margins can cause our height to shrink below our minimal height (border/padding).
1849     // If this happens, ensure that the computed height is increased to the minimal height.
1850     setLogicalHeight(max(logicalHeight(), beforeSide + afterSide));
1851 
1852     // Update our bottom collapsed margin info.
1853     setCollapsedBottomMargin(marginInfo);
1854 }
1855 
setLogicalLeftForChild(RenderBox * child,int logicalLeft,ApplyLayoutDeltaMode applyDelta)1856 void RenderBlock::setLogicalLeftForChild(RenderBox* child, int logicalLeft, ApplyLayoutDeltaMode applyDelta)
1857 {
1858     if (isHorizontalWritingMode()) {
1859         if (applyDelta == ApplyLayoutDelta)
1860             view()->addLayoutDelta(IntSize(child->x() - logicalLeft, 0));
1861         child->setX(logicalLeft);
1862     } else {
1863         if (applyDelta == ApplyLayoutDelta)
1864             view()->addLayoutDelta(IntSize(0, child->y() - logicalLeft));
1865         child->setY(logicalLeft);
1866     }
1867 }
1868 
setLogicalTopForChild(RenderBox * child,int logicalTop,ApplyLayoutDeltaMode applyDelta)1869 void RenderBlock::setLogicalTopForChild(RenderBox* child, int logicalTop, ApplyLayoutDeltaMode applyDelta)
1870 {
1871     if (isHorizontalWritingMode()) {
1872         if (applyDelta == ApplyLayoutDelta)
1873             view()->addLayoutDelta(IntSize(0, child->y() - logicalTop));
1874         child->setY(logicalTop);
1875     } else {
1876         if (applyDelta == ApplyLayoutDelta)
1877             view()->addLayoutDelta(IntSize(child->x() - logicalTop, 0));
1878         child->setX(logicalTop);
1879     }
1880 }
1881 
layoutBlockChildren(bool relayoutChildren,int & maxFloatLogicalBottom)1882 void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatLogicalBottom)
1883 {
1884     if (gPercentHeightDescendantsMap) {
1885         if (HashSet<RenderBox*>* descendants = gPercentHeightDescendantsMap->get(this)) {
1886             HashSet<RenderBox*>::iterator end = descendants->end();
1887             for (HashSet<RenderBox*>::iterator it = descendants->begin(); it != end; ++it) {
1888                 RenderBox* box = *it;
1889                 while (box != this) {
1890                     if (box->normalChildNeedsLayout())
1891                         break;
1892                     box->setChildNeedsLayout(true, false);
1893                     box = box->containingBlock();
1894                     ASSERT(box);
1895                     if (!box)
1896                         break;
1897                 }
1898             }
1899         }
1900     }
1901 
1902     int beforeEdge = borderBefore() + paddingBefore();
1903     int afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeight();
1904 
1905     setLogicalHeight(beforeEdge);
1906 
1907     // The margin struct caches all our current margin collapsing state.  The compact struct caches state when we encounter compacts,
1908     MarginInfo marginInfo(this, beforeEdge, afterEdge);
1909 
1910     // Fieldsets need to find their legend and position it inside the border of the object.
1911     // The legend then gets skipped during normal layout.  The same is true for ruby text.
1912     // It doesn't get included in the normal layout process but is instead skipped.
1913     RenderObject* childToExclude = layoutSpecialExcludedChild(relayoutChildren);
1914 
1915     int previousFloatLogicalBottom = 0;
1916     maxFloatLogicalBottom = 0;
1917 
1918     RenderBox* next = firstChildBox();
1919 
1920     while (next) {
1921         RenderBox* child = next;
1922         next = child->nextSiblingBox();
1923 
1924         if (childToExclude == child)
1925             continue; // Skip this child, since it will be positioned by the specialized subclass (fieldsets and ruby runs).
1926 
1927         // Make sure we layout children if they need it.
1928         // FIXME: Technically percentage height objects only need a relayout if their percentage isn't going to be turned into
1929         // an auto value.  Add a method to determine this, so that we can avoid the relayout.
1930         if (relayoutChildren || ((child->style()->logicalHeight().isPercent() || child->style()->logicalMinHeight().isPercent() || child->style()->logicalMaxHeight().isPercent()) && !isRenderView()))
1931             child->setChildNeedsLayout(true, false);
1932 
1933         // If relayoutChildren is set and the child has percentage padding, we also need to invalidate the child's pref widths.
1934         if (relayoutChildren && (child->style()->paddingStart().isPercent() || child->style()->paddingEnd().isPercent()))
1935             child->setPreferredLogicalWidthsDirty(true, false);
1936 
1937         // Handle the four types of special elements first.  These include positioned content, floating content, compacts and
1938         // run-ins.  When we encounter these four types of objects, we don't actually lay them out as normal flow blocks.
1939         if (handleSpecialChild(child, marginInfo))
1940             continue;
1941 
1942         // Lay out the child.
1943         layoutBlockChild(child, marginInfo, previousFloatLogicalBottom, maxFloatLogicalBottom);
1944     }
1945 
1946     // Now do the handling of the bottom of the block, adding in our bottom border/padding and
1947     // determining the correct collapsed bottom margin information.
1948     handleAfterSideOfBlock(beforeEdge, afterEdge, marginInfo);
1949 }
1950 
layoutBlockChild(RenderBox * child,MarginInfo & marginInfo,int & previousFloatLogicalBottom,int & maxFloatLogicalBottom)1951 void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, int& previousFloatLogicalBottom, int& maxFloatLogicalBottom)
1952 {
1953     int oldPosMarginBefore = maxPositiveMarginBefore();
1954     int oldNegMarginBefore = maxNegativeMarginBefore();
1955 
1956     // The child is a normal flow object.  Compute the margins we will use for collapsing now.
1957     child->computeBlockDirectionMargins(this);
1958 
1959     // Do not allow a collapse if the margin-before-collapse style is set to SEPARATE.
1960     if (child->style()->marginBeforeCollapse() == MSEPARATE) {
1961         marginInfo.setAtBeforeSideOfBlock(false);
1962         marginInfo.clearMargin();
1963     }
1964 
1965     // Try to guess our correct logical top position.  In most cases this guess will
1966     // be correct.  Only if we're wrong (when we compute the real logical top position)
1967     // will we have to potentially relayout.
1968     int logicalTopEstimate = estimateLogicalTopPosition(child, marginInfo);
1969 
1970     // Cache our old rect so that we can dirty the proper repaint rects if the child moves.
1971     IntRect oldRect(child->x(), child->y() , child->width(), child->height());
1972     int oldLogicalTop = logicalTopForChild(child);
1973 
1974 #ifndef NDEBUG
1975     IntSize oldLayoutDelta = view()->layoutDelta();
1976 #endif
1977     // Go ahead and position the child as though it didn't collapse with the top.
1978     setLogicalTopForChild(child, logicalTopEstimate, ApplyLayoutDelta);
1979 
1980     RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
1981     bool markDescendantsWithFloats = false;
1982     if (logicalTopEstimate != oldLogicalTop && !child->avoidsFloats() && childRenderBlock && childRenderBlock->containsFloats())
1983         markDescendantsWithFloats = true;
1984     else if (!child->avoidsFloats() || child->shrinkToAvoidFloats()) {
1985         // If an element might be affected by the presence of floats, then always mark it for
1986         // layout.
1987         int fb = max(previousFloatLogicalBottom, lowestFloatLogicalBottom());
1988         if (fb > logicalTopEstimate)
1989             markDescendantsWithFloats = true;
1990     }
1991 
1992     if (childRenderBlock) {
1993         if (markDescendantsWithFloats)
1994             childRenderBlock->markAllDescendantsWithFloatsForLayout();
1995         if (!child->isWritingModeRoot())
1996             previousFloatLogicalBottom = max(previousFloatLogicalBottom, oldLogicalTop + childRenderBlock->lowestFloatLogicalBottom());
1997     }
1998 
1999     if (!child->needsLayout())
2000         child->markForPaginationRelayoutIfNeeded();
2001 
2002     bool childHadLayout = child->m_everHadLayout;
2003     bool childNeededLayout = child->needsLayout();
2004     if (childNeededLayout)
2005         child->layout();
2006 
2007     // Cache if we are at the top of the block right now.
2008     bool atBeforeSideOfBlock = marginInfo.atBeforeSideOfBlock();
2009 
2010     // Now determine the correct ypos based off examination of collapsing margin
2011     // values.
2012     int logicalTopBeforeClear = collapseMargins(child, marginInfo);
2013 
2014     // Now check for clear.
2015     int logicalTopAfterClear = clearFloatsIfNeeded(child, marginInfo, oldPosMarginBefore, oldNegMarginBefore, logicalTopBeforeClear);
2016 
2017     bool paginated = view()->layoutState()->isPaginated();
2018     if (paginated) {
2019         int oldTop = logicalTopAfterClear;
2020 
2021         // If the object has a page or column break value of "before", then we should shift to the top of the next page.
2022         logicalTopAfterClear = applyBeforeBreak(child, logicalTopAfterClear);
2023 
2024         // For replaced elements and scrolled elements, we want to shift them to the next page if they don't fit on the current one.
2025         int logicalTopBeforeUnsplittableAdjustment = logicalTopAfterClear;
2026         int logicalTopAfterUnsplittableAdjustment = adjustForUnsplittableChild(child, logicalTopAfterClear);
2027 
2028         int paginationStrut = 0;
2029         int unsplittableAdjustmentDelta = logicalTopAfterUnsplittableAdjustment - logicalTopBeforeUnsplittableAdjustment;
2030         if (unsplittableAdjustmentDelta)
2031             paginationStrut = unsplittableAdjustmentDelta;
2032         else if (childRenderBlock && childRenderBlock->paginationStrut())
2033             paginationStrut = childRenderBlock->paginationStrut();
2034 
2035         if (paginationStrut) {
2036             // We are willing to propagate out to our parent block as long as we were at the top of the block prior
2037             // to collapsing our margins, and as long as we didn't clear or move as a result of other pagination.
2038             if (atBeforeSideOfBlock && oldTop == logicalTopBeforeClear && !isPositioned() && !isTableCell()) {
2039                 // FIXME: Should really check if we're exceeding the page height before propagating the strut, but we don't
2040                 // have all the information to do so (the strut only has the remaining amount to push).  Gecko gets this wrong too
2041                 // and pushes to the next page anyway, so not too concerned about it.
2042                 setPaginationStrut(logicalTopAfterClear + paginationStrut);
2043                 if (childRenderBlock)
2044                     childRenderBlock->setPaginationStrut(0);
2045             } else
2046                 logicalTopAfterClear += paginationStrut;
2047         }
2048 
2049         // Similar to how we apply clearance.  Go ahead and boost height() to be the place where we're going to position the child.
2050         setLogicalHeight(logicalHeight() + (logicalTopAfterClear - oldTop));
2051     }
2052 
2053     setLogicalTopForChild(child, logicalTopAfterClear, ApplyLayoutDelta);
2054 
2055     // Now we have a final top position.  See if it really does end up being different from our estimate.
2056     if (logicalTopAfterClear != logicalTopEstimate) {
2057         if (child->shrinkToAvoidFloats()) {
2058             // The child's width depends on the line width.
2059             // When the child shifts to clear an item, its width can
2060             // change (because it has more available line width).
2061             // So go ahead and mark the item as dirty.
2062             child->setChildNeedsLayout(true, false);
2063         }
2064         if (childRenderBlock) {
2065             if (!child->avoidsFloats() && childRenderBlock->containsFloats())
2066                 childRenderBlock->markAllDescendantsWithFloatsForLayout();
2067             if (!child->needsLayout())
2068                 child->markForPaginationRelayoutIfNeeded();
2069         }
2070 
2071         // Our guess was wrong. Make the child lay itself out again.
2072         child->layoutIfNeeded();
2073     }
2074 
2075     // We are no longer at the top of the block if we encounter a non-empty child.
2076     // This has to be done after checking for clear, so that margins can be reset if a clear occurred.
2077     if (marginInfo.atBeforeSideOfBlock() && !child->isSelfCollapsingBlock())
2078         marginInfo.setAtBeforeSideOfBlock(false);
2079 
2080     // Now place the child in the correct left position
2081     determineLogicalLeftPositionForChild(child);
2082 
2083     // Update our height now that the child has been placed in the correct position.
2084     setLogicalHeight(logicalHeight() + logicalHeightForChild(child));
2085     if (child->style()->marginAfterCollapse() == MSEPARATE) {
2086         setLogicalHeight(logicalHeight() + marginAfterForChild(child));
2087         marginInfo.clearMargin();
2088     }
2089     // If the child has overhanging floats that intrude into following siblings (or possibly out
2090     // of this block), then the parent gets notified of the floats now.
2091     if (childRenderBlock && childRenderBlock->containsFloats())
2092         maxFloatLogicalBottom = max(maxFloatLogicalBottom, addOverhangingFloats(toRenderBlock(child), -child->logicalLeft(), -child->logicalTop(), !childNeededLayout));
2093 
2094     IntSize childOffset(child->x() - oldRect.x(), child->y() - oldRect.y());
2095     if (childOffset.width() || childOffset.height()) {
2096         view()->addLayoutDelta(childOffset);
2097 
2098         // If the child moved, we have to repaint it as well as any floating/positioned
2099         // descendants.  An exception is if we need a layout.  In this case, we know we're going to
2100         // repaint ourselves (and the child) anyway.
2101         if (childHadLayout && !selfNeedsLayout() && child->checkForRepaintDuringLayout())
2102             child->repaintDuringLayoutIfMoved(oldRect);
2103     }
2104 
2105     if (!childHadLayout && child->checkForRepaintDuringLayout()) {
2106         child->repaint();
2107         child->repaintOverhangingFloats(true);
2108     }
2109 
2110     if (paginated) {
2111         // Check for an after page/column break.
2112         int newHeight = applyAfterBreak(child, logicalHeight(), marginInfo);
2113         if (newHeight != height())
2114             setLogicalHeight(newHeight);
2115     }
2116 
2117     ASSERT(oldLayoutDelta == view()->layoutDelta());
2118 }
2119 
simplifiedNormalFlowLayout()2120 void RenderBlock::simplifiedNormalFlowLayout()
2121 {
2122     if (childrenInline()) {
2123         ListHashSet<RootInlineBox*> lineBoxes;
2124         bool endOfInline = false;
2125         RenderObject* o = bidiFirst(this, 0, false);
2126         while (o) {
2127             if (!o->isPositioned() && (o->isReplaced() || o->isFloating())) {
2128                 o->layoutIfNeeded();
2129                 if (toRenderBox(o)->inlineBoxWrapper()) {
2130                     RootInlineBox* box = toRenderBox(o)->inlineBoxWrapper()->root();
2131                     lineBoxes.add(box);
2132                 }
2133             } else if (o->isText() || (o->isRenderInline() && !endOfInline))
2134                 o->setNeedsLayout(false);
2135             o = bidiNext(this, o, 0, false, &endOfInline);
2136         }
2137 
2138         // FIXME: Glyph overflow will get lost in this case, but not really a big deal.
2139         GlyphOverflowAndFallbackFontsMap textBoxDataMap;
2140         for (ListHashSet<RootInlineBox*>::const_iterator it = lineBoxes.begin(); it != lineBoxes.end(); ++it) {
2141             RootInlineBox* box = *it;
2142             box->computeOverflow(box->lineTop(), box->lineBottom(), textBoxDataMap);
2143         }
2144     } else {
2145         for (RenderBox* box = firstChildBox(); box; box = box->nextSiblingBox()) {
2146             if (!box->isPositioned())
2147                 box->layoutIfNeeded();
2148         }
2149     }
2150 }
2151 
simplifiedLayout()2152 bool RenderBlock::simplifiedLayout()
2153 {
2154     if ((!posChildNeedsLayout() && !needsSimplifiedNormalFlowLayout()) || normalChildNeedsLayout() || selfNeedsLayout())
2155         return false;
2156 
2157     LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
2158 
2159     if (needsPositionedMovementLayout() && !tryLayoutDoingPositionedMovementOnly())
2160         return false;
2161 
2162     // Lay out positioned descendants or objects that just need to recompute overflow.
2163     if (needsSimplifiedNormalFlowLayout())
2164         simplifiedNormalFlowLayout();
2165 
2166     // Lay out our positioned objects if our positioned child bit is set.
2167     if (posChildNeedsLayout())
2168         layoutPositionedObjects(false);
2169 
2170     // Recompute our overflow information.
2171     // FIXME: We could do better here by computing a temporary overflow object from layoutPositionedObjects and only
2172     // updating our overflow if we either used to have overflow or if the new temporary object has overflow.
2173     // For now just always recompute overflow.  This is no worse performance-wise than the old code that called rightmostPosition and
2174     // lowestPosition on every relayout so it's not a regression.
2175     m_overflow.clear();
2176     computeOverflow(clientLogicalBottom(), true);
2177 
2178     statePusher.pop();
2179 
2180     updateLayerTransform();
2181 
2182     updateScrollInfoAfterLayout();
2183 
2184     setNeedsLayout(false);
2185     return true;
2186 }
2187 
layoutPositionedObjects(bool relayoutChildren)2188 void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
2189 {
2190     if (!m_positionedObjects)
2191         return;
2192 
2193     if (hasColumns())
2194         view()->layoutState()->clearPaginationInformation(); // Positioned objects are not part of the column flow, so they don't paginate with the columns.
2195 
2196     RenderBox* r;
2197     Iterator end = m_positionedObjects->end();
2198     for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
2199         r = *it;
2200         // When a non-positioned block element moves, it may have positioned children that are implicitly positioned relative to the
2201         // non-positioned block.  Rather than trying to detect all of these movement cases, we just always lay out positioned
2202         // objects that are positioned implicitly like this.  Such objects are rare, and so in typical DHTML menu usage (where everything is
2203         // positioned explicitly) this should not incur a performance penalty.
2204         if (relayoutChildren || (r->style()->hasStaticBlockPosition(isHorizontalWritingMode()) && r->parent() != this && r->parent()->isBlockFlow()))
2205             r->setChildNeedsLayout(true, false);
2206 
2207         // If relayoutChildren is set and we have percentage padding, we also need to invalidate the child's pref widths.
2208         if (relayoutChildren && (r->style()->paddingStart().isPercent() || r->style()->paddingEnd().isPercent()))
2209             r->setPreferredLogicalWidthsDirty(true, false);
2210 
2211         if (!r->needsLayout())
2212             r->markForPaginationRelayoutIfNeeded();
2213 
2214         // 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
2215         // and we hit the available width constraint, the layoutIfNeeded() will catch it and do a full layout.
2216         if (r->needsPositionedMovementLayoutOnly() && r->tryLayoutDoingPositionedMovementOnly())
2217             r->setNeedsLayout(false);
2218         r->layoutIfNeeded();
2219     }
2220 
2221     if (hasColumns())
2222         view()->layoutState()->m_columnInfo = columnInfo(); // FIXME: Kind of gross. We just put this back into the layout state so that pop() will work.
2223 }
2224 
markPositionedObjectsForLayout()2225 void RenderBlock::markPositionedObjectsForLayout()
2226 {
2227     if (m_positionedObjects) {
2228         RenderBox* r;
2229         Iterator end = m_positionedObjects->end();
2230         for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
2231             r = *it;
2232             r->setChildNeedsLayout(true);
2233         }
2234     }
2235 }
2236 
markForPaginationRelayoutIfNeeded()2237 void RenderBlock::markForPaginationRelayoutIfNeeded()
2238 {
2239     ASSERT(!needsLayout());
2240     if (needsLayout())
2241         return;
2242 
2243     if (view()->layoutState()->pageLogicalHeightChanged() || (view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(logicalTop()) != pageLogicalOffset()))
2244         setChildNeedsLayout(true, false);
2245 }
2246 
repaintOverhangingFloats(bool paintAllDescendants)2247 void RenderBlock::repaintOverhangingFloats(bool paintAllDescendants)
2248 {
2249     // Repaint any overhanging floats (if we know we're the one to paint them).
2250     // Otherwise, bail out.
2251     if (!hasOverhangingFloats())
2252         return;
2253 
2254     // FIXME: Avoid disabling LayoutState. At the very least, don't disable it for floats originating
2255     // in this block. Better yet would be to push extra state for the containers of other floats.
2256     view()->disableLayoutState();
2257     FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
2258     FloatingObjectSetIterator end = floatingObjectSet.end();
2259     for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
2260         FloatingObject* r = *it;
2261         // Only repaint the object if it is overhanging, is not in its own layer, and
2262         // is our responsibility to paint (m_shouldPaint is set). When paintAllDescendants is true, the latter
2263         // condition is replaced with being a descendant of us.
2264         if (logicalBottomForFloat(r) > logicalHeight() && ((paintAllDescendants && r->m_renderer->isDescendantOf(this)) || r->m_shouldPaint) && !r->m_renderer->hasSelfPaintingLayer()) {
2265             r->m_renderer->repaint();
2266             r->m_renderer->repaintOverhangingFloats();
2267         }
2268     }
2269     view()->enableLayoutState();
2270 }
2271 
paint(PaintInfo & paintInfo,int tx,int ty)2272 void RenderBlock::paint(PaintInfo& paintInfo, int tx, int ty)
2273 {
2274     tx += x();
2275     ty += y();
2276 
2277     PaintPhase phase = paintInfo.phase;
2278 
2279     // Check if we need to do anything at all.
2280     // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
2281     // paints the root's background.
2282     if (!isRoot()) {
2283         IntRect overflowBox = visualOverflowRect();
2284         flipForWritingMode(overflowBox);
2285         overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
2286         overflowBox.move(tx, ty);
2287         if (!overflowBox.intersects(paintInfo.rect))
2288             return;
2289     }
2290 
2291     bool pushedClip = pushContentsClip(paintInfo, tx, ty);
2292     paintObject(paintInfo, tx, ty);
2293     if (pushedClip)
2294         popContentsClip(paintInfo, phase, tx, ty);
2295 
2296     // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
2297     // z-index.  We paint after we painted the background/border, so that the scrollbars will
2298     // sit above the background/border.
2299     if (hasOverflowClip() && style()->visibility() == VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground) && paintInfo.shouldPaintWithinRoot(this))
2300         layer()->paintOverflowControls(paintInfo.context, tx, ty, paintInfo.rect);
2301 }
2302 
paintColumnRules(PaintInfo & paintInfo,int tx,int ty)2303 void RenderBlock::paintColumnRules(PaintInfo& paintInfo, int tx, int ty)
2304 {
2305     const Color& ruleColor = style()->visitedDependentColor(CSSPropertyWebkitColumnRuleColor);
2306     bool ruleTransparent = style()->columnRuleIsTransparent();
2307     EBorderStyle ruleStyle = style()->columnRuleStyle();
2308     int ruleWidth = style()->columnRuleWidth();
2309     int colGap = columnGap();
2310     bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent && ruleWidth <= colGap;
2311     if (!renderRule)
2312         return;
2313 
2314     // We need to do multiple passes, breaking up our child painting into strips.
2315     ColumnInfo* colInfo = columnInfo();
2316     unsigned colCount = columnCount(colInfo);
2317     int currLogicalLeftOffset = style()->isLeftToRightDirection() ? 0 : contentLogicalWidth();
2318     int ruleAdd = logicalLeftOffsetForContent();
2319     int ruleLogicalLeft = style()->isLeftToRightDirection() ? 0 : contentLogicalWidth();
2320     for (unsigned i = 0; i < colCount; i++) {
2321         IntRect colRect = columnRectAt(colInfo, i);
2322 
2323         int inlineDirectionSize = isHorizontalWritingMode() ? colRect.width() : colRect.height();
2324 
2325         // Move to the next position.
2326         if (style()->isLeftToRightDirection()) {
2327             ruleLogicalLeft += inlineDirectionSize + colGap / 2;
2328             currLogicalLeftOffset += inlineDirectionSize + colGap;
2329         } else {
2330             ruleLogicalLeft -= (inlineDirectionSize + colGap / 2);
2331             currLogicalLeftOffset -= (inlineDirectionSize + colGap);
2332         }
2333 
2334         // Now paint the column rule.
2335         if (i < colCount - 1) {
2336             int ruleLeft = isHorizontalWritingMode() ? tx + ruleLogicalLeft - ruleWidth / 2 + ruleAdd : tx + borderBefore() + paddingBefore();
2337             int ruleRight = isHorizontalWritingMode() ? ruleLeft + ruleWidth : ruleLeft + contentWidth();
2338             int ruleTop = isHorizontalWritingMode() ? ty + borderTop() + paddingTop() : ty + ruleLogicalLeft - ruleWidth / 2 + ruleAdd;
2339             int ruleBottom = isHorizontalWritingMode() ? ruleTop + contentHeight() : ruleTop + ruleWidth;
2340             drawLineForBoxSide(paintInfo.context, ruleLeft, ruleTop, ruleRight, ruleBottom,
2341                                style()->isLeftToRightDirection() ? BSLeft : BSRight, ruleColor, ruleStyle, 0, 0);
2342         }
2343 
2344         ruleLogicalLeft = currLogicalLeftOffset;
2345     }
2346 }
2347 
paintColumnContents(PaintInfo & paintInfo,int tx,int ty,bool paintingFloats)2348 void RenderBlock::paintColumnContents(PaintInfo& paintInfo, int tx, int ty, bool paintingFloats)
2349 {
2350     // We need to do multiple passes, breaking up our child painting into strips.
2351     GraphicsContext* context = paintInfo.context;
2352     ColumnInfo* colInfo = columnInfo();
2353     unsigned colCount = columnCount(colInfo);
2354     if (!colCount)
2355         return;
2356     int currLogicalTopOffset = 0;
2357     for (unsigned i = 0; i < colCount; i++) {
2358         // For each rect, we clip to the rect, and then we adjust our coords.
2359         IntRect colRect = columnRectAt(colInfo, i);
2360         flipForWritingMode(colRect);
2361         int logicalLeftOffset = (isHorizontalWritingMode() ? colRect.x() : colRect.y()) - logicalLeftOffsetForContent();
2362         IntSize offset = isHorizontalWritingMode() ? IntSize(logicalLeftOffset, currLogicalTopOffset) : IntSize(currLogicalTopOffset, logicalLeftOffset);
2363         colRect.move(tx, ty);
2364         PaintInfo info(paintInfo);
2365         info.rect.intersect(colRect);
2366 
2367         if (!info.rect.isEmpty()) {
2368             context->save();
2369 
2370             // Each strip pushes a clip, since column boxes are specified as being
2371             // like overflow:hidden.
2372             context->clip(colRect);
2373 
2374             // Adjust our x and y when painting.
2375             int finalX = tx + offset.width();
2376             int finalY = ty + offset.height();
2377             if (paintingFloats)
2378                 paintFloats(info, finalX, finalY, paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip);
2379             else
2380                 paintContents(info, finalX, finalY);
2381 
2382             context->restore();
2383         }
2384 
2385         int blockDelta = (isHorizontalWritingMode() ? colRect.height() : colRect.width());
2386         if (style()->isFlippedBlocksWritingMode())
2387             currLogicalTopOffset += blockDelta;
2388         else
2389             currLogicalTopOffset -= blockDelta;
2390     }
2391 }
2392 
paintContents(PaintInfo & paintInfo,int tx,int ty)2393 void RenderBlock::paintContents(PaintInfo& paintInfo, int tx, int ty)
2394 {
2395     // Avoid painting descendants of the root element when stylesheets haven't loaded.  This eliminates FOUC.
2396     // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
2397     // will do a full repaint().
2398     if (document()->didLayoutWithPendingStylesheets() && !isRenderView())
2399         return;
2400 
2401     if (childrenInline())
2402         m_lineBoxes.paint(this, paintInfo, tx, ty);
2403     else
2404         paintChildren(paintInfo, tx, ty);
2405 }
2406 
paintChildren(PaintInfo & paintInfo,int tx,int ty)2407 void RenderBlock::paintChildren(PaintInfo& paintInfo, int tx, int ty)
2408 {
2409     PaintPhase newPhase = (paintInfo.phase == PaintPhaseChildOutlines) ? PaintPhaseOutline : paintInfo.phase;
2410     newPhase = (newPhase == PaintPhaseChildBlockBackgrounds) ? PaintPhaseChildBlockBackground : newPhase;
2411 
2412     // We don't paint our own background, but we do let the kids paint their backgrounds.
2413     PaintInfo info(paintInfo);
2414     info.phase = newPhase;
2415     info.updatePaintingRootForChildren(this);
2416 
2417     // FIXME: Paint-time pagination is obsolete and is now only used by embedded WebViews inside AppKit
2418     // NSViews.  Do not add any more code for this.
2419     RenderView* renderView = view();
2420     bool usePrintRect = !renderView->printRect().isEmpty();
2421 
2422     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
2423         // Check for page-break-before: always, and if it's set, break and bail.
2424         bool checkBeforeAlways = !childrenInline() && (usePrintRect && child->style()->pageBreakBefore() == PBALWAYS);
2425         if (checkBeforeAlways
2426             && (ty + child->y()) > paintInfo.rect.y()
2427             && (ty + child->y()) < paintInfo.rect.maxY()) {
2428             view()->setBestTruncatedAt(ty + child->y(), this, true);
2429             return;
2430         }
2431 
2432         if (!child->isFloating() && child->isReplaced() && usePrintRect && child->height() <= renderView->printRect().height()) {
2433             // Paginate block-level replaced elements.
2434             if (ty + child->y() + child->height() > renderView->printRect().maxY()) {
2435                 if (ty + child->y() < renderView->truncatedAt())
2436                     renderView->setBestTruncatedAt(ty + child->y(), child);
2437                 // If we were able to truncate, don't paint.
2438                 if (ty + child->y() >= renderView->truncatedAt())
2439                     break;
2440             }
2441         }
2442 
2443         IntPoint childPoint = flipForWritingMode(child, IntPoint(tx, ty), ParentToChildFlippingAdjustment);
2444         if (!child->hasSelfPaintingLayer() && !child->isFloating())
2445             child->paint(info, childPoint.x(), childPoint.y());
2446 
2447         // Check for page-break-after: always, and if it's set, break and bail.
2448         bool checkAfterAlways = !childrenInline() && (usePrintRect && child->style()->pageBreakAfter() == PBALWAYS);
2449         if (checkAfterAlways
2450             && (ty + child->y() + child->height()) > paintInfo.rect.y()
2451             && (ty + child->y() + child->height()) < paintInfo.rect.maxY()) {
2452             view()->setBestTruncatedAt(ty + child->y() + child->height() + max(0, child->collapsedMarginAfter()), this, true);
2453             return;
2454         }
2455     }
2456 }
2457 
paintCaret(PaintInfo & paintInfo,int tx,int ty,CaretType type)2458 void RenderBlock::paintCaret(PaintInfo& paintInfo, int tx, int ty, CaretType type)
2459 {
2460     SelectionController* selection = type == CursorCaret ? frame()->selection() : frame()->page()->dragCaretController();
2461 
2462     // Paint the caret if the SelectionController says so or if caret browsing is enabled
2463     bool caretBrowsing = frame()->settings() && frame()->settings()->caretBrowsingEnabled();
2464     RenderObject* caretPainter = selection->caretRenderer();
2465     if (caretPainter == this && (selection->isContentEditable() || caretBrowsing)) {
2466         // Convert the painting offset into the local coordinate system of this renderer,
2467         // to match the localCaretRect computed by the SelectionController
2468         offsetForContents(tx, ty);
2469 
2470         if (type == CursorCaret)
2471             frame()->selection()->paintCaret(paintInfo.context, tx, ty, paintInfo.rect);
2472         else
2473             frame()->selection()->paintDragCaret(paintInfo.context, tx, ty, paintInfo.rect);
2474     }
2475 }
2476 
paintObject(PaintInfo & paintInfo,int tx,int ty)2477 void RenderBlock::paintObject(PaintInfo& paintInfo, int tx, int ty)
2478 {
2479     PaintPhase paintPhase = paintInfo.phase;
2480 
2481     // 1. paint background, borders etc
2482     if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && style()->visibility() == VISIBLE) {
2483         if (hasBoxDecorations())
2484             paintBoxDecorations(paintInfo, tx, ty);
2485         if (hasColumns())
2486             paintColumnRules(paintInfo, tx, ty);
2487     }
2488 
2489     if (paintPhase == PaintPhaseMask && style()->visibility() == VISIBLE) {
2490         paintMask(paintInfo, tx, ty);
2491         return;
2492     }
2493 
2494     // We're done.  We don't bother painting any children.
2495     if (paintPhase == PaintPhaseBlockBackground)
2496         return;
2497 
2498     // Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div).
2499     int scrolledX = tx;
2500     int scrolledY = ty;
2501     if (hasOverflowClip()) {
2502         IntSize offset = layer()->scrolledContentOffset();
2503         scrolledX -= offset.width();
2504         scrolledY -= offset.height();
2505     }
2506 
2507     // 2. paint contents
2508     if (paintPhase != PaintPhaseSelfOutline) {
2509         if (hasColumns())
2510             paintColumnContents(paintInfo, scrolledX, scrolledY);
2511         else
2512             paintContents(paintInfo, scrolledX, scrolledY);
2513     }
2514 
2515     // 3. paint selection
2516     // FIXME: Make this work with multi column layouts.  For now don't fill gaps.
2517     bool isPrinting = document()->printing();
2518     if (!isPrinting && !hasColumns())
2519         paintSelection(paintInfo, scrolledX, scrolledY); // Fill in gaps in selection on lines and between blocks.
2520 
2521     // 4. paint floats.
2522     if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip) {
2523         if (hasColumns())
2524             paintColumnContents(paintInfo, scrolledX, scrolledY, true);
2525         else
2526             paintFloats(paintInfo, scrolledX, scrolledY, paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip);
2527     }
2528 
2529     // 5. paint outline.
2530     if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style()->visibility() == VISIBLE)
2531         paintOutline(paintInfo.context, tx, ty, width(), height());
2532 
2533     // 6. paint continuation outlines.
2534     if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)) {
2535         RenderInline* inlineCont = inlineElementContinuation();
2536         if (inlineCont && inlineCont->hasOutline() && inlineCont->style()->visibility() == VISIBLE) {
2537             RenderInline* inlineRenderer = toRenderInline(inlineCont->node()->renderer());
2538             RenderBlock* cb = containingBlock();
2539 
2540             bool inlineEnclosedInSelfPaintingLayer = false;
2541             for (RenderBoxModelObject* box = inlineRenderer; box != cb; box = box->parent()->enclosingBoxModelObject()) {
2542                 if (box->hasSelfPaintingLayer()) {
2543                     inlineEnclosedInSelfPaintingLayer = true;
2544                     break;
2545                 }
2546             }
2547 
2548             if (!inlineEnclosedInSelfPaintingLayer)
2549                 cb->addContinuationWithOutline(inlineRenderer);
2550             else if (!inlineRenderer->firstLineBox())
2551                 inlineRenderer->paintOutline(paintInfo.context, tx - x() + inlineRenderer->containingBlock()->x(),
2552                                              ty - y() + inlineRenderer->containingBlock()->y());
2553         }
2554         paintContinuationOutlines(paintInfo, tx, ty);
2555     }
2556 
2557     // 7. paint caret.
2558     // If the caret's node's render object's containing block is this block, and the paint action is PaintPhaseForeground,
2559     // then paint the caret.
2560     if (paintPhase == PaintPhaseForeground) {
2561         paintCaret(paintInfo, scrolledX, scrolledY, CursorCaret);
2562         paintCaret(paintInfo, scrolledX, scrolledY, DragCaret);
2563     }
2564 }
2565 
flipFloatForWritingMode(const FloatingObject * child,const IntPoint & point) const2566 IntPoint RenderBlock::flipFloatForWritingMode(const FloatingObject* child, const IntPoint& point) const
2567 {
2568     if (!style()->isFlippedBlocksWritingMode())
2569         return point;
2570 
2571     // This is similar to the ParentToChildFlippingAdjustment in RenderBox::flipForWritingMode.  We have to subtract out our left/top offsets twice, since
2572     // it's going to get added back in.  We hide this complication here so that the calling code looks normal for the unflipped
2573     // case.
2574     if (isHorizontalWritingMode())
2575         return IntPoint(point.x(), point.y() + height() - child->renderer()->height() - 2 * yPositionForFloatIncludingMargin(child));
2576     return IntPoint(point.x() + width() - child->width() - 2 * xPositionForFloatIncludingMargin(child), point.y());
2577 }
2578 
paintFloats(PaintInfo & paintInfo,int tx,int ty,bool preservePhase)2579 void RenderBlock::paintFloats(PaintInfo& paintInfo, int tx, int ty, bool preservePhase)
2580 {
2581     if (!m_floatingObjects)
2582         return;
2583 
2584     FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
2585     FloatingObjectSetIterator end = floatingObjectSet.end();
2586     for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
2587         FloatingObject* r = *it;
2588         // Only paint the object if our m_shouldPaint flag is set.
2589         if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) {
2590             PaintInfo currentPaintInfo(paintInfo);
2591             currentPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
2592             IntPoint childPoint = flipFloatForWritingMode(r, IntPoint(tx + xPositionForFloatIncludingMargin(r) - r->m_renderer->x(), ty + yPositionForFloatIncludingMargin(r) - r->m_renderer->y()));
2593             r->m_renderer->paint(currentPaintInfo, childPoint.x(), childPoint.y());
2594             if (!preservePhase) {
2595                 currentPaintInfo.phase = PaintPhaseChildBlockBackgrounds;
2596                 r->m_renderer->paint(currentPaintInfo, childPoint.x(), childPoint.y());
2597                 currentPaintInfo.phase = PaintPhaseFloat;
2598                 r->m_renderer->paint(currentPaintInfo, childPoint.x(), childPoint.y());
2599                 currentPaintInfo.phase = PaintPhaseForeground;
2600                 r->m_renderer->paint(currentPaintInfo, childPoint.x(), childPoint.y());
2601                 currentPaintInfo.phase = PaintPhaseOutline;
2602                 r->m_renderer->paint(currentPaintInfo, childPoint.x(), childPoint.y());
2603             }
2604         }
2605     }
2606 }
2607 
paintEllipsisBoxes(PaintInfo & paintInfo,int tx,int ty)2608 void RenderBlock::paintEllipsisBoxes(PaintInfo& paintInfo, int tx, int ty)
2609 {
2610     if (!paintInfo.shouldPaintWithinRoot(this) || !firstLineBox())
2611         return;
2612 
2613     if (style()->visibility() == VISIBLE && paintInfo.phase == PaintPhaseForeground) {
2614         // We can check the first box and last box and avoid painting if we don't
2615         // intersect.
2616         int yPos = ty + firstLineBox()->y();
2617         int h = lastLineBox()->y() + lastLineBox()->logicalHeight() - firstLineBox()->y();
2618         if (yPos >= paintInfo.rect.maxY() || yPos + h <= paintInfo.rect.y())
2619             return;
2620 
2621         // See if our boxes intersect with the dirty rect.  If so, then we paint
2622         // them.  Note that boxes can easily overlap, so we can't make any assumptions
2623         // based off positions of our first line box or our last line box.
2624         for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
2625             yPos = ty + curr->y();
2626             h = curr->logicalHeight();
2627             if (curr->ellipsisBox() && yPos < paintInfo.rect.maxY() && yPos + h > paintInfo.rect.y())
2628                 curr->paintEllipsisBox(paintInfo, tx, ty, curr->lineTop(), curr->lineBottom());
2629         }
2630     }
2631 }
2632 
inlineElementContinuation() const2633 RenderInline* RenderBlock::inlineElementContinuation() const
2634 {
2635     RenderBoxModelObject* continuation = this->continuation();
2636     return continuation && continuation->isInline() ? toRenderInline(continuation) : 0;
2637 }
2638 
blockElementContinuation() const2639 RenderBlock* RenderBlock::blockElementContinuation() const
2640 {
2641     RenderBoxModelObject* currentContinuation = continuation();
2642     if (!currentContinuation || currentContinuation->isInline())
2643         return 0;
2644     RenderBlock* nextContinuation = toRenderBlock(currentContinuation);
2645     if (nextContinuation->isAnonymousBlock())
2646         return nextContinuation->blockElementContinuation();
2647     return nextContinuation;
2648 }
2649 
continuationOutlineTable()2650 static ContinuationOutlineTableMap* continuationOutlineTable()
2651 {
2652     DEFINE_STATIC_LOCAL(ContinuationOutlineTableMap, table, ());
2653     return &table;
2654 }
2655 
addContinuationWithOutline(RenderInline * flow)2656 void RenderBlock::addContinuationWithOutline(RenderInline* flow)
2657 {
2658     // We can't make this work if the inline is in a layer.  We'll just rely on the broken
2659     // way of painting.
2660     ASSERT(!flow->layer() && !flow->isInlineElementContinuation());
2661 
2662     ContinuationOutlineTableMap* table = continuationOutlineTable();
2663     ListHashSet<RenderInline*>* continuations = table->get(this);
2664     if (!continuations) {
2665         continuations = new ListHashSet<RenderInline*>;
2666         table->set(this, continuations);
2667     }
2668 
2669     continuations->add(flow);
2670 }
2671 
paintsContinuationOutline(RenderInline * flow)2672 bool RenderBlock::paintsContinuationOutline(RenderInline* flow)
2673 {
2674     ContinuationOutlineTableMap* table = continuationOutlineTable();
2675     if (table->isEmpty())
2676         return false;
2677 
2678     ListHashSet<RenderInline*>* continuations = table->get(this);
2679     if (!continuations)
2680         return false;
2681 
2682     return continuations->contains(flow);
2683 }
2684 
paintContinuationOutlines(PaintInfo & info,int tx,int ty)2685 void RenderBlock::paintContinuationOutlines(PaintInfo& info, int tx, int ty)
2686 {
2687     ContinuationOutlineTableMap* table = continuationOutlineTable();
2688     if (table->isEmpty())
2689         return;
2690 
2691     ListHashSet<RenderInline*>* continuations = table->get(this);
2692     if (!continuations)
2693         return;
2694 
2695     // Paint each continuation outline.
2696     ListHashSet<RenderInline*>::iterator end = continuations->end();
2697     for (ListHashSet<RenderInline*>::iterator it = continuations->begin(); it != end; ++it) {
2698         // Need to add in the coordinates of the intervening blocks.
2699         RenderInline* flow = *it;
2700         RenderBlock* block = flow->containingBlock();
2701         for ( ; block && block != this; block = block->containingBlock()) {
2702             tx += block->x();
2703             ty += block->y();
2704         }
2705         ASSERT(block);
2706         flow->paintOutline(info.context, tx, ty);
2707     }
2708 
2709     // Delete
2710     delete continuations;
2711     table->remove(this);
2712 }
2713 
shouldPaintSelectionGaps() const2714 bool RenderBlock::shouldPaintSelectionGaps() const
2715 {
2716     return selectionState() != SelectionNone && style()->visibility() == VISIBLE && isSelectionRoot();
2717 }
2718 
isSelectionRoot() const2719 bool RenderBlock::isSelectionRoot() const
2720 {
2721     if (!node())
2722         return false;
2723 
2724     // FIXME: Eventually tables should have to learn how to fill gaps between cells, at least in simple non-spanning cases.
2725     if (isTable())
2726         return false;
2727 
2728     if (isBody() || isRoot() || hasOverflowClip() || isRelPositioned() ||
2729         isFloatingOrPositioned() || isTableCell() || isInlineBlockOrInlineTable() || hasTransform() ||
2730         hasReflection() || hasMask() || isWritingModeRoot())
2731         return true;
2732 
2733     if (view() && view()->selectionStart()) {
2734         Node* startElement = view()->selectionStart()->node();
2735         if (startElement && startElement->rootEditableElement() == node())
2736             return true;
2737     }
2738 
2739     return false;
2740 }
2741 
selectionGapRectsForRepaint(RenderBoxModelObject * repaintContainer)2742 GapRects RenderBlock::selectionGapRectsForRepaint(RenderBoxModelObject* repaintContainer)
2743 {
2744     ASSERT(!needsLayout());
2745 
2746     if (!shouldPaintSelectionGaps())
2747         return GapRects();
2748 
2749     // FIXME: this is broken with transforms
2750     TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint());
2751     mapLocalToContainer(repaintContainer, false, false, transformState);
2752     IntPoint offsetFromRepaintContainer = roundedIntPoint(transformState.mappedPoint());
2753 
2754     if (hasOverflowClip())
2755         offsetFromRepaintContainer -= layer()->scrolledContentOffset();
2756 
2757     int lastTop = 0;
2758     int lastLeft = logicalLeftSelectionOffset(this, lastTop);
2759     int lastRight = logicalRightSelectionOffset(this, lastTop);
2760 
2761     return selectionGaps(this, offsetFromRepaintContainer, IntSize(), lastTop, lastLeft, lastRight);
2762 }
2763 
paintSelection(PaintInfo & paintInfo,int tx,int ty)2764 void RenderBlock::paintSelection(PaintInfo& paintInfo, int tx, int ty)
2765 {
2766     if (shouldPaintSelectionGaps() && paintInfo.phase == PaintPhaseForeground) {
2767         int lastTop = 0;
2768         int lastLeft = logicalLeftSelectionOffset(this, lastTop);
2769         int lastRight = logicalRightSelectionOffset(this, lastTop);
2770         paintInfo.context->save();
2771         IntRect gapRectsBounds = selectionGaps(this, IntPoint(tx, ty), IntSize(), lastTop, lastLeft, lastRight, &paintInfo);
2772         if (!gapRectsBounds.isEmpty()) {
2773             if (RenderLayer* layer = enclosingLayer()) {
2774                 gapRectsBounds.move(IntSize(-tx, -ty));
2775                 if (!hasLayer()) {
2776                     IntRect localBounds(gapRectsBounds);
2777                     flipForWritingMode(localBounds);
2778                     gapRectsBounds = localToContainerQuad(FloatRect(localBounds), layer->renderer()).enclosingBoundingBox();
2779                     gapRectsBounds.move(layer->scrolledContentOffset());
2780                 }
2781                 layer->addBlockSelectionGapsBounds(gapRectsBounds);
2782             }
2783         }
2784         paintInfo.context->restore();
2785     }
2786 }
2787 
clipOutPositionedObjects(const PaintInfo * paintInfo,const IntPoint & offset,RenderBlock::PositionedObjectsListHashSet * positionedObjects)2788 static void clipOutPositionedObjects(const PaintInfo* paintInfo, const IntPoint& offset, RenderBlock::PositionedObjectsListHashSet* positionedObjects)
2789 {
2790     if (!positionedObjects)
2791         return;
2792 
2793     RenderBlock::PositionedObjectsListHashSet::const_iterator end = positionedObjects->end();
2794     for (RenderBlock::PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
2795         RenderBox* r = *it;
2796         paintInfo->context->clipOut(IntRect(offset.x() + r->x(), offset.y() + r->y(), r->width(), r->height()));
2797     }
2798 }
2799 
blockDirectionOffset(RenderBlock * rootBlock,const IntSize & offsetFromRootBlock)2800 static int blockDirectionOffset(RenderBlock* rootBlock, const IntSize& offsetFromRootBlock)
2801 {
2802     return rootBlock->isHorizontalWritingMode() ? offsetFromRootBlock.height() : offsetFromRootBlock.width();
2803 }
2804 
inlineDirectionOffset(RenderBlock * rootBlock,const IntSize & offsetFromRootBlock)2805 static int inlineDirectionOffset(RenderBlock* rootBlock, const IntSize& offsetFromRootBlock)
2806 {
2807     return rootBlock->isHorizontalWritingMode() ? offsetFromRootBlock.width() : offsetFromRootBlock.height();
2808 }
2809 
logicalRectToPhysicalRect(const IntPoint & rootBlockPhysicalPosition,const IntRect & logicalRect)2810 IntRect RenderBlock::logicalRectToPhysicalRect(const IntPoint& rootBlockPhysicalPosition, const IntRect& logicalRect)
2811 {
2812     IntRect result;
2813     if (isHorizontalWritingMode())
2814         result = logicalRect;
2815     else
2816         result = IntRect(logicalRect.y(), logicalRect.x(), logicalRect.height(), logicalRect.width());
2817     flipForWritingMode(result);
2818     result.move(rootBlockPhysicalPosition.x(), rootBlockPhysicalPosition.y());
2819     return result;
2820 }
2821 
selectionGaps(RenderBlock * rootBlock,const IntPoint & rootBlockPhysicalPosition,const IntSize & offsetFromRootBlock,int & lastLogicalTop,int & lastLogicalLeft,int & lastLogicalRight,const PaintInfo * paintInfo)2822 GapRects RenderBlock::selectionGaps(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock,
2823                                     int& lastLogicalTop, int& lastLogicalLeft, int& lastLogicalRight, const PaintInfo* paintInfo)
2824 {
2825     // IMPORTANT: Callers of this method that intend for painting to happen need to do a save/restore.
2826     // Clip out floating and positioned objects when painting selection gaps.
2827     if (paintInfo) {
2828         // Note that we don't clip out overflow for positioned objects.  We just stick to the border box.
2829         IntRect flippedBlockRect = IntRect(offsetFromRootBlock.width(), offsetFromRootBlock.height(), width(), height());
2830         rootBlock->flipForWritingMode(flippedBlockRect);
2831         flippedBlockRect.move(rootBlockPhysicalPosition.x(), rootBlockPhysicalPosition.y());
2832         clipOutPositionedObjects(paintInfo, flippedBlockRect.location(), m_positionedObjects.get());
2833         if (isBody() || isRoot()) // The <body> must make sure to examine its containingBlock's positioned objects.
2834             for (RenderBlock* cb = containingBlock(); cb && !cb->isRenderView(); cb = cb->containingBlock())
2835                 clipOutPositionedObjects(paintInfo, IntPoint(cb->x(), cb->y()), cb->m_positionedObjects.get()); // FIXME: Not right for flipped writing modes.
2836         if (m_floatingObjects) {
2837             FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
2838             FloatingObjectSetIterator end = floatingObjectSet.end();
2839             for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
2840                 FloatingObject* r = *it;
2841                 IntRect floatBox = IntRect(offsetFromRootBlock.width() + xPositionForFloatIncludingMargin(r),
2842                                            offsetFromRootBlock.height() + yPositionForFloatIncludingMargin(r),
2843                                            r->m_renderer->width(), r->m_renderer->height());
2844                 rootBlock->flipForWritingMode(floatBox);
2845                 floatBox.move(rootBlockPhysicalPosition.x(), rootBlockPhysicalPosition.y());
2846                 paintInfo->context->clipOut(floatBox);
2847             }
2848         }
2849     }
2850 
2851     // 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
2852     // fixed).
2853     GapRects result;
2854     if (!isBlockFlow()) // FIXME: Make multi-column selection gap filling work someday.
2855         return result;
2856 
2857     if (hasColumns() || hasTransform() || style()->columnSpan()) {
2858         // FIXME: We should learn how to gap fill multiple columns and transforms eventually.
2859         lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalHeight();
2860         lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight());
2861         lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight());
2862         return result;
2863     }
2864 
2865     if (childrenInline())
2866         result = inlineSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo);
2867     else
2868         result = blockSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo);
2869 
2870     // Go ahead and fill the vertical gap all the way to the bottom of our block if the selection extends past our block.
2871     if (rootBlock == this && (selectionState() != SelectionBoth && selectionState() != SelectionEnd))
2872         result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight,
2873                                              logicalHeight(), paintInfo));
2874     return result;
2875 }
2876 
inlineSelectionGaps(RenderBlock * rootBlock,const IntPoint & rootBlockPhysicalPosition,const IntSize & offsetFromRootBlock,int & lastLogicalTop,int & lastLogicalLeft,int & lastLogicalRight,const PaintInfo * paintInfo)2877 GapRects RenderBlock::inlineSelectionGaps(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock,
2878                                           int& lastLogicalTop, int& lastLogicalLeft, int& lastLogicalRight, const PaintInfo* paintInfo)
2879 {
2880     GapRects result;
2881 
2882     bool containsStart = selectionState() == SelectionStart || selectionState() == SelectionBoth;
2883 
2884     if (!firstLineBox()) {
2885         if (containsStart) {
2886             // Go ahead and update our lastLogicalTop to be the bottom of the block.  <hr>s or empty blocks with height can trip this
2887             // case.
2888             lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalHeight();
2889             lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight());
2890             lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight());
2891         }
2892         return result;
2893     }
2894 
2895     RootInlineBox* lastSelectedLine = 0;
2896     RootInlineBox* curr;
2897     for (curr = firstRootBox(); curr && !curr->hasSelectedChildren(); curr = curr->nextRootBox()) { }
2898 
2899     // Now paint the gaps for the lines.
2900     for (; curr && curr->hasSelectedChildren(); curr = curr->nextRootBox()) {
2901         int selTop =  curr->selectionTop();
2902         int selHeight = curr->selectionHeight();
2903 
2904         if (!containsStart && !lastSelectedLine &&
2905             selectionState() != SelectionStart && selectionState() != SelectionBoth)
2906             result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight,
2907                                                  selTop, paintInfo));
2908 
2909         IntRect logicalRect(curr->logicalLeft(), selTop, curr->logicalWidth(), selTop + selHeight);
2910         logicalRect.move(isHorizontalWritingMode() ? offsetFromRootBlock : IntSize(offsetFromRootBlock.height(), offsetFromRootBlock.width()));
2911         IntRect physicalRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, logicalRect);
2912         if (!paintInfo || (isHorizontalWritingMode() && physicalRect.y() < paintInfo->rect.maxY() && physicalRect.maxY() > paintInfo->rect.y())
2913             || (!isHorizontalWritingMode() && physicalRect.x() < paintInfo->rect.maxX() && physicalRect.maxX() > paintInfo->rect.x()))
2914             result.unite(curr->lineSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, selTop, selHeight, paintInfo));
2915 
2916         lastSelectedLine = curr;
2917     }
2918 
2919     if (containsStart && !lastSelectedLine)
2920         // VisibleSelection must start just after our last line.
2921         lastSelectedLine = lastRootBox();
2922 
2923     if (lastSelectedLine && selectionState() != SelectionEnd && selectionState() != SelectionBoth) {
2924         // Go ahead and update our lastY to be the bottom of the last selected line.
2925         lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + lastSelectedLine->selectionBottom();
2926         lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, lastSelectedLine->selectionBottom());
2927         lastLogicalRight = logicalRightSelectionOffset(rootBlock, lastSelectedLine->selectionBottom());
2928     }
2929     return result;
2930 }
2931 
blockSelectionGaps(RenderBlock * rootBlock,const IntPoint & rootBlockPhysicalPosition,const IntSize & offsetFromRootBlock,int & lastLogicalTop,int & lastLogicalLeft,int & lastLogicalRight,const PaintInfo * paintInfo)2932 GapRects RenderBlock::blockSelectionGaps(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock,
2933                                          int& lastLogicalTop, int& lastLogicalLeft, int& lastLogicalRight, const PaintInfo* paintInfo)
2934 {
2935     GapRects result;
2936 
2937     // Go ahead and jump right to the first block child that contains some selected objects.
2938     RenderBox* curr;
2939     for (curr = firstChildBox(); curr && curr->selectionState() == SelectionNone; curr = curr->nextSiblingBox()) { }
2940 
2941     for (bool sawSelectionEnd = false; curr && !sawSelectionEnd; curr = curr->nextSiblingBox()) {
2942         SelectionState childState = curr->selectionState();
2943         if (childState == SelectionBoth || childState == SelectionEnd)
2944             sawSelectionEnd = true;
2945 
2946         if (curr->isFloatingOrPositioned())
2947             continue; // We must be a normal flow object in order to even be considered.
2948 
2949         if (curr->isRelPositioned() && curr->hasLayer()) {
2950             // If the relposition offset is anything other than 0, then treat this just like an absolute positioned element.
2951             // Just disregard it completely.
2952             IntSize relOffset = curr->layer()->relativePositionOffset();
2953             if (relOffset.width() || relOffset.height())
2954                 continue;
2955         }
2956 
2957         bool paintsOwnSelection = curr->shouldPaintSelectionGaps() || curr->isTable(); // FIXME: Eventually we won't special-case table like this.
2958         bool fillBlockGaps = paintsOwnSelection || (curr->canBeSelectionLeaf() && childState != SelectionNone);
2959         if (fillBlockGaps) {
2960             // We need to fill the vertical gap above this object.
2961             if (childState == SelectionEnd || childState == SelectionInside)
2962                 // Fill the gap above the object.
2963                 result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight,
2964                                                      curr->logicalTop(), paintInfo));
2965 
2966             // 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*
2967             // our object.  We know this if the selection did not end inside our object.
2968             if (paintsOwnSelection && (childState == SelectionStart || sawSelectionEnd))
2969                 childState = SelectionNone;
2970 
2971             // Fill side gaps on this object based off its state.
2972             bool leftGap, rightGap;
2973             getSelectionGapInfo(childState, leftGap, rightGap);
2974 
2975             if (leftGap)
2976                 result.uniteLeft(logicalLeftSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalLeft(), curr->logicalTop(), curr->logicalHeight(), paintInfo));
2977             if (rightGap)
2978                 result.uniteRight(logicalRightSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalRight(), curr->logicalTop(), curr->logicalHeight(), paintInfo));
2979 
2980             // Update lastLogicalTop to be just underneath the object.  lastLogicalLeft and lastLogicalRight extend as far as
2981             // they can without bumping into floating or positioned objects.  Ideally they will go right up
2982             // to the border of the root selection block.
2983             lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + curr->logicalBottom();
2984             lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, curr->logicalBottom());
2985             lastLogicalRight = logicalRightSelectionOffset(rootBlock, curr->logicalBottom());
2986         } else if (childState != SelectionNone)
2987             // We must be a block that has some selected object inside it.  Go ahead and recur.
2988             result.unite(toRenderBlock(curr)->selectionGaps(rootBlock, rootBlockPhysicalPosition, IntSize(offsetFromRootBlock.width() + curr->x(), offsetFromRootBlock.height() + curr->y()),
2989                                                             lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo));
2990     }
2991     return result;
2992 }
2993 
blockSelectionGap(RenderBlock * rootBlock,const IntPoint & rootBlockPhysicalPosition,const IntSize & offsetFromRootBlock,int lastLogicalTop,int lastLogicalLeft,int lastLogicalRight,int logicalBottom,const PaintInfo * paintInfo)2994 IntRect RenderBlock::blockSelectionGap(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock,
2995                                        int lastLogicalTop, int lastLogicalLeft, int lastLogicalRight, int logicalBottom, const PaintInfo* paintInfo)
2996 {
2997     int logicalTop = lastLogicalTop;
2998     int logicalHeight = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalBottom - logicalTop;
2999     if (logicalHeight <= 0)
3000         return IntRect();
3001 
3002     // Get the selection offsets for the bottom of the gap
3003     int logicalLeft = max(lastLogicalLeft, logicalLeftSelectionOffset(rootBlock, logicalBottom));
3004     int logicalRight = min(lastLogicalRight, logicalRightSelectionOffset(rootBlock, logicalBottom));
3005     int logicalWidth = logicalRight - logicalLeft;
3006     if (logicalWidth <= 0)
3007         return IntRect();
3008 
3009     IntRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, IntRect(logicalLeft, logicalTop, logicalWidth, logicalHeight));
3010     if (paintInfo)
3011         paintInfo->context->fillRect(gapRect, selectionBackgroundColor(), style()->colorSpace());
3012     return gapRect;
3013 }
3014 
logicalLeftSelectionGap(RenderBlock * rootBlock,const IntPoint & rootBlockPhysicalPosition,const IntSize & offsetFromRootBlock,RenderObject * selObj,int logicalLeft,int logicalTop,int logicalHeight,const PaintInfo * paintInfo)3015 IntRect RenderBlock::logicalLeftSelectionGap(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock,
3016                                              RenderObject* selObj, int logicalLeft, int logicalTop, int logicalHeight, const PaintInfo* paintInfo)
3017 {
3018     int rootBlockLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalTop;
3019     int rootBlockLogicalLeft = max(logicalLeftSelectionOffset(rootBlock, logicalTop), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight));
3020     int rootBlockLogicalRight = min(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + logicalLeft, min(logicalRightSelectionOffset(rootBlock, logicalTop), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight)));
3021     int rootBlockLogicalWidth = rootBlockLogicalRight - rootBlockLogicalLeft;
3022     if (rootBlockLogicalWidth <= 0)
3023         return IntRect();
3024 
3025     IntRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, IntRect(rootBlockLogicalLeft, rootBlockLogicalTop, rootBlockLogicalWidth, logicalHeight));
3026     if (paintInfo)
3027         paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor(), selObj->style()->colorSpace());
3028     return gapRect;
3029 }
3030 
logicalRightSelectionGap(RenderBlock * rootBlock,const IntPoint & rootBlockPhysicalPosition,const IntSize & offsetFromRootBlock,RenderObject * selObj,int logicalRight,int logicalTop,int logicalHeight,const PaintInfo * paintInfo)3031 IntRect RenderBlock::logicalRightSelectionGap(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock,
3032                                               RenderObject* selObj, int logicalRight, int logicalTop, int logicalHeight, const PaintInfo* paintInfo)
3033 {
3034     int rootBlockLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalTop;
3035     int rootBlockLogicalLeft = max(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + logicalRight, max(logicalLeftSelectionOffset(rootBlock, logicalTop), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight)));
3036     int rootBlockLogicalRight = min(logicalRightSelectionOffset(rootBlock, logicalTop), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight));
3037     int rootBlockLogicalWidth = rootBlockLogicalRight - rootBlockLogicalLeft;
3038     if (rootBlockLogicalWidth <= 0)
3039         return IntRect();
3040 
3041     IntRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, IntRect(rootBlockLogicalLeft, rootBlockLogicalTop, rootBlockLogicalWidth, logicalHeight));
3042     if (paintInfo)
3043         paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor(), selObj->style()->colorSpace());
3044     return gapRect;
3045 }
3046 
getSelectionGapInfo(SelectionState state,bool & leftGap,bool & rightGap)3047 void RenderBlock::getSelectionGapInfo(SelectionState state, bool& leftGap, bool& rightGap)
3048 {
3049     bool ltr = style()->isLeftToRightDirection();
3050     leftGap = (state == RenderObject::SelectionInside) ||
3051               (state == RenderObject::SelectionEnd && ltr) ||
3052               (state == RenderObject::SelectionStart && !ltr);
3053     rightGap = (state == RenderObject::SelectionInside) ||
3054                (state == RenderObject::SelectionStart && ltr) ||
3055                (state == RenderObject::SelectionEnd && !ltr);
3056 }
3057 
logicalLeftSelectionOffset(RenderBlock * rootBlock,int position)3058 int RenderBlock::logicalLeftSelectionOffset(RenderBlock* rootBlock, int position)
3059 {
3060     int logicalLeft = logicalLeftOffsetForLine(position, false);
3061     if (logicalLeft == logicalLeftOffsetForContent()) {
3062         if (rootBlock != this)
3063             // The border can potentially be further extended by our containingBlock().
3064             return containingBlock()->logicalLeftSelectionOffset(rootBlock, position + logicalTop());
3065         return logicalLeft;
3066     } else {
3067         RenderBlock* cb = this;
3068         while (cb != rootBlock) {
3069             logicalLeft += cb->logicalLeft();
3070             cb = cb->containingBlock();
3071         }
3072     }
3073     return logicalLeft;
3074 }
3075 
logicalRightSelectionOffset(RenderBlock * rootBlock,int position)3076 int RenderBlock::logicalRightSelectionOffset(RenderBlock* rootBlock, int position)
3077 {
3078     int logicalRight = logicalRightOffsetForLine(position, false);
3079     if (logicalRight == logicalRightOffsetForContent()) {
3080         if (rootBlock != this)
3081             // The border can potentially be further extended by our containingBlock().
3082             return containingBlock()->logicalRightSelectionOffset(rootBlock, position + logicalTop());
3083         return logicalRight;
3084     } else {
3085         RenderBlock* cb = this;
3086         while (cb != rootBlock) {
3087             logicalRight += cb->logicalLeft();
3088             cb = cb->containingBlock();
3089         }
3090     }
3091     return logicalRight;
3092 }
3093 
insertPositionedObject(RenderBox * o)3094 void RenderBlock::insertPositionedObject(RenderBox* o)
3095 {
3096     // Create the list of special objects if we don't aleady have one
3097     if (!m_positionedObjects)
3098         m_positionedObjects = adoptPtr(new PositionedObjectsListHashSet);
3099 
3100     m_positionedObjects->add(o);
3101 }
3102 
removePositionedObject(RenderBox * o)3103 void RenderBlock::removePositionedObject(RenderBox* o)
3104 {
3105     if (m_positionedObjects)
3106         m_positionedObjects->remove(o);
3107 }
3108 
removePositionedObjects(RenderBlock * o)3109 void RenderBlock::removePositionedObjects(RenderBlock* o)
3110 {
3111     if (!m_positionedObjects)
3112         return;
3113 
3114     RenderBox* r;
3115 
3116     Iterator end = m_positionedObjects->end();
3117 
3118     Vector<RenderBox*, 16> deadObjects;
3119 
3120     for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
3121         r = *it;
3122         if (!o || r->isDescendantOf(o)) {
3123             if (o)
3124                 r->setChildNeedsLayout(true, false);
3125 
3126             // It is parent blocks job to add positioned child to positioned objects list of its containing block
3127             // Parent layout needs to be invalidated to ensure this happens.
3128             RenderObject* p = r->parent();
3129             while (p && !p->isRenderBlock())
3130                 p = p->parent();
3131             if (p)
3132                 p->setChildNeedsLayout(true);
3133 
3134             deadObjects.append(r);
3135         }
3136     }
3137 
3138     for (unsigned i = 0; i < deadObjects.size(); i++)
3139         m_positionedObjects->remove(deadObjects.at(i));
3140 }
3141 
insertFloatingObject(RenderBox * o)3142 RenderBlock::FloatingObject* RenderBlock::insertFloatingObject(RenderBox* o)
3143 {
3144     ASSERT(o->isFloating());
3145 
3146     // Create the list of special objects if we don't aleady have one
3147     if (!m_floatingObjects)
3148         m_floatingObjects = adoptPtr(new FloatingObjects);
3149     else {
3150         // Don't insert the object again if it's already in the list
3151         FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3152         FloatingObjectSetIterator it = floatingObjectSet.find<RenderBox*, FloatingObjectHashTranslator>(o);
3153         if (it != floatingObjectSet.end())
3154             return *it;
3155     }
3156 
3157     // Create the special object entry & append it to the list
3158 
3159     FloatingObject* newObj = new FloatingObject(o->style()->floating() == FLEFT ? FloatingObject::FloatLeft : FloatingObject::FloatRight);
3160 
3161     // Our location is irrelevant if we're unsplittable or no pagination is in effect.
3162     // Just go ahead and lay out the float.
3163     bool isChildRenderBlock = o->isRenderBlock();
3164     if (isChildRenderBlock && !o->needsLayout() && view()->layoutState()->pageLogicalHeightChanged())
3165         o->setChildNeedsLayout(true, false);
3166 
3167     bool affectedByPagination = isChildRenderBlock && view()->layoutState()->m_pageLogicalHeight;
3168     if (!affectedByPagination || isWritingModeRoot()) // We are unsplittable if we're a block flow root.
3169         o->layoutIfNeeded();
3170     else {
3171         o->computeLogicalWidth();
3172         o->computeBlockDirectionMargins(this);
3173     }
3174     setLogicalWidthForFloat(newObj, logicalWidthForChild(o) + marginStartForChild(o) + marginEndForChild(o));
3175 
3176     newObj->m_shouldPaint = !o->hasSelfPaintingLayer(); // If a layer exists, the float will paint itself.  Otherwise someone else will.
3177     newObj->m_isDescendant = true;
3178     newObj->m_renderer = o;
3179 
3180     m_floatingObjects->increaseObjectsCount(newObj->type());
3181     m_floatingObjects->set().add(newObj);
3182 
3183     return newObj;
3184 }
3185 
removeFloatingObject(RenderBox * o)3186 void RenderBlock::removeFloatingObject(RenderBox* o)
3187 {
3188     if (m_floatingObjects) {
3189         FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3190         FloatingObjectSet::iterator it = floatingObjectSet.find<RenderBox*, FloatingObjectHashTranslator>(o);
3191         if (it != floatingObjectSet.end()) {
3192             FloatingObject* r = *it;
3193             if (childrenInline()) {
3194                 int logicalTop = logicalTopForFloat(r);
3195                 int logicalBottom = logicalBottomForFloat(r);
3196 
3197                 // Fix for https://bugs.webkit.org/show_bug.cgi?id=54995.
3198                 if (logicalBottom < 0 || logicalBottom < logicalTop || logicalTop == numeric_limits<int>::max())
3199                     logicalBottom = numeric_limits<int>::max();
3200                 else {
3201                     // Special-case zero- and less-than-zero-height floats: those don't touch
3202                     // the line that they're on, but it still needs to be dirtied. This is
3203                     // accomplished by pretending they have a height of 1.
3204                     logicalBottom = max(logicalBottom, logicalTop + 1);
3205                 }
3206                 if (r->m_originatingLine) {
3207                     ASSERT(r->m_originatingLine->renderer() == this);
3208                     r->m_originatingLine->markDirty();
3209 #if !ASSERT_DISABLED
3210                     r->m_originatingLine = 0;
3211 #endif
3212                 }
3213                 markLinesDirtyInBlockRange(0, logicalBottom);
3214             }
3215             m_floatingObjects->decreaseObjectsCount(r->type());
3216             floatingObjectSet.remove(it);
3217             ASSERT(!r->m_originatingLine);
3218             delete r;
3219         }
3220     }
3221 }
3222 
removeFloatingObjectsBelow(FloatingObject * lastFloat,int logicalOffset)3223 void RenderBlock::removeFloatingObjectsBelow(FloatingObject* lastFloat, int logicalOffset)
3224 {
3225     if (!m_floatingObjects)
3226         return;
3227 
3228     FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3229     FloatingObject* curr = floatingObjectSet.last();
3230     while (curr != lastFloat && (!curr->isPlaced() || logicalTopForFloat(curr) >= logicalOffset)) {
3231         m_floatingObjects->decreaseObjectsCount(curr->type());
3232         floatingObjectSet.removeLast();
3233         ASSERT(!curr->m_originatingLine);
3234         delete curr;
3235         curr = floatingObjectSet.last();
3236     }
3237 }
3238 
positionNewFloats()3239 bool RenderBlock::positionNewFloats()
3240 {
3241     if (!m_floatingObjects)
3242         return false;
3243 
3244     FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3245     if (floatingObjectSet.isEmpty())
3246         return false;
3247 
3248     // If all floats have already been positioned, then we have no work to do.
3249     if (floatingObjectSet.last()->isPlaced())
3250         return false;
3251 
3252     // Move backwards through our floating object list until we find a float that has
3253     // already been positioned.  Then we'll be able to move forward, positioning all of
3254     // the new floats that need it.
3255     FloatingObjectSetIterator it = floatingObjectSet.end();
3256     --it; // Go to last item.
3257     FloatingObjectSetIterator begin = floatingObjectSet.begin();
3258     FloatingObject* lastPlacedFloatingObject = 0;
3259     while (it != begin) {
3260         --it;
3261         if ((*it)->isPlaced()) {
3262             lastPlacedFloatingObject = *it;
3263             ++it;
3264             break;
3265         }
3266     }
3267 
3268     int logicalTop = logicalHeight();
3269 
3270     // The float cannot start above the top position of the last positioned float.
3271     if (lastPlacedFloatingObject)
3272         logicalTop = max(logicalTopForFloat(lastPlacedFloatingObject), logicalTop);
3273 
3274     FloatingObjectSetIterator end = floatingObjectSet.end();
3275     // Now walk through the set of unpositioned floats and place them.
3276     for (; it != end; ++it) {
3277          FloatingObject* floatingObject = *it;
3278         // The containing block is responsible for positioning floats, so if we have floats in our
3279         // list that come from somewhere else, do not attempt to position them.
3280         if (floatingObject->renderer()->containingBlock() != this)
3281             continue;
3282 
3283         RenderBox* childBox = floatingObject->renderer();
3284         int childLogicalLeftMargin = style()->isLeftToRightDirection() ? marginStartForChild(childBox) : marginEndForChild(childBox);
3285 
3286         int rightOffset = logicalRightOffsetForContent(); // Constant part of right offset.
3287         int leftOffset = logicalLeftOffsetForContent(); // Constant part of left offset.
3288         int floatLogicalWidth = logicalWidthForFloat(floatingObject); // The width we look for.
3289         if (rightOffset - leftOffset < floatLogicalWidth)
3290             floatLogicalWidth = rightOffset - leftOffset; // Never look for more than what will be available.
3291 
3292         IntRect oldRect(childBox->x(), childBox->y() , childBox->width(), childBox->height());
3293 
3294         if (childBox->style()->clear() & CLEFT)
3295             logicalTop = max(lowestFloatLogicalBottom(FloatingObject::FloatLeft), logicalTop);
3296         if (childBox->style()->clear() & CRIGHT)
3297             logicalTop = max(lowestFloatLogicalBottom(FloatingObject::FloatRight), logicalTop);
3298 
3299         int floatLogicalLeft;
3300         if (childBox->style()->floating() == FLEFT) {
3301             int heightRemainingLeft = 1;
3302             int heightRemainingRight = 1;
3303             floatLogicalLeft = logicalLeftOffsetForLine(logicalTop, leftOffset, false, &heightRemainingLeft);
3304             while (logicalRightOffsetForLine(logicalTop, rightOffset, false, &heightRemainingRight) - floatLogicalLeft < floatLogicalWidth) {
3305                 logicalTop += min(heightRemainingLeft, heightRemainingRight);
3306                 floatLogicalLeft = logicalLeftOffsetForLine(logicalTop, leftOffset, false, &heightRemainingLeft);
3307             }
3308             floatLogicalLeft = max(0, floatLogicalLeft);
3309         } else {
3310             int heightRemainingLeft = 1;
3311             int heightRemainingRight = 1;
3312             floatLogicalLeft = logicalRightOffsetForLine(logicalTop, rightOffset, false, &heightRemainingRight);
3313             while (floatLogicalLeft - logicalLeftOffsetForLine(logicalTop, leftOffset, false, &heightRemainingLeft) < floatLogicalWidth) {
3314                 logicalTop += min(heightRemainingLeft, heightRemainingRight);
3315                 floatLogicalLeft = logicalRightOffsetForLine(logicalTop, rightOffset, false, &heightRemainingRight);
3316             }
3317             floatLogicalLeft -= logicalWidthForFloat(floatingObject); // Use the original width of the float here, since the local variable
3318                                                                       // |floatLogicalWidth| was capped to the available line width.
3319                                                                       // See fast/block/float/clamped-right-float.html.
3320         }
3321 
3322         setLogicalLeftForFloat(floatingObject, floatLogicalLeft);
3323         setLogicalLeftForChild(childBox, floatLogicalLeft + childLogicalLeftMargin);
3324         setLogicalTopForChild(childBox, logicalTop + marginBeforeForChild(childBox));
3325 
3326         if (view()->layoutState()->isPaginated()) {
3327             RenderBlock* childBlock = childBox->isRenderBlock() ? toRenderBlock(childBox) : 0;
3328 
3329             if (!childBox->needsLayout())
3330                 childBox->markForPaginationRelayoutIfNeeded();;
3331             childBox->layoutIfNeeded();
3332 
3333             // If we are unsplittable and don't fit, then we need to move down.
3334             // We include our margins as part of the unsplittable area.
3335             int newLogicalTop = adjustForUnsplittableChild(childBox, logicalTop, true);
3336 
3337             // See if we have a pagination strut that is making us move down further.
3338             // Note that an unsplittable child can't also have a pagination strut, so this is
3339             // exclusive with the case above.
3340             if (childBlock && childBlock->paginationStrut()) {
3341                 newLogicalTop += childBlock->paginationStrut();
3342                 childBlock->setPaginationStrut(0);
3343             }
3344 
3345             if (newLogicalTop != logicalTop) {
3346                 floatingObject->m_paginationStrut = newLogicalTop - logicalTop;
3347                 logicalTop = newLogicalTop;
3348                 setLogicalTopForChild(childBox, logicalTop + marginBeforeForChild(childBox));
3349                 if (childBlock)
3350                     childBlock->setChildNeedsLayout(true, false);
3351                 childBox->layoutIfNeeded();
3352             }
3353         }
3354 
3355         setLogicalTopForFloat(floatingObject, logicalTop);
3356         setLogicalHeightForFloat(floatingObject, logicalHeightForChild(childBox) + marginBeforeForChild(childBox) + marginAfterForChild(childBox));
3357 
3358         floatingObject->setIsPlaced();
3359 
3360         // If the child moved, we have to repaint it.
3361         if (childBox->checkForRepaintDuringLayout())
3362             childBox->repaintDuringLayoutIfMoved(oldRect);
3363     }
3364     return true;
3365 }
3366 
newLine(EClear clear)3367 void RenderBlock::newLine(EClear clear)
3368 {
3369     positionNewFloats();
3370     // set y position
3371     int newY = 0;
3372     switch (clear)
3373     {
3374         case CLEFT:
3375             newY = lowestFloatLogicalBottom(FloatingObject::FloatLeft);
3376             break;
3377         case CRIGHT:
3378             newY = lowestFloatLogicalBottom(FloatingObject::FloatRight);
3379             break;
3380         case CBOTH:
3381             newY = lowestFloatLogicalBottom();
3382         default:
3383             break;
3384     }
3385     if (height() < newY)
3386         setLogicalHeight(newY);
3387 }
3388 
addPercentHeightDescendant(RenderBox * descendant)3389 void RenderBlock::addPercentHeightDescendant(RenderBox* descendant)
3390 {
3391     if (!gPercentHeightDescendantsMap) {
3392         gPercentHeightDescendantsMap = new PercentHeightDescendantsMap;
3393         gPercentHeightContainerMap = new PercentHeightContainerMap;
3394     }
3395 
3396     HashSet<RenderBox*>* descendantSet = gPercentHeightDescendantsMap->get(this);
3397     if (!descendantSet) {
3398         descendantSet = new HashSet<RenderBox*>;
3399         gPercentHeightDescendantsMap->set(this, descendantSet);
3400     }
3401     bool added = descendantSet->add(descendant).second;
3402     if (!added) {
3403         ASSERT(gPercentHeightContainerMap->get(descendant));
3404         ASSERT(gPercentHeightContainerMap->get(descendant)->contains(this));
3405         return;
3406     }
3407 
3408     HashSet<RenderBlock*>* containerSet = gPercentHeightContainerMap->get(descendant);
3409     if (!containerSet) {
3410         containerSet = new HashSet<RenderBlock*>;
3411         gPercentHeightContainerMap->set(descendant, containerSet);
3412     }
3413     ASSERT(!containerSet->contains(this));
3414     containerSet->add(this);
3415 }
3416 
removePercentHeightDescendant(RenderBox * descendant)3417 void RenderBlock::removePercentHeightDescendant(RenderBox* descendant)
3418 {
3419     if (!gPercentHeightContainerMap)
3420         return;
3421 
3422     HashSet<RenderBlock*>* containerSet = gPercentHeightContainerMap->take(descendant);
3423     if (!containerSet)
3424         return;
3425 
3426     HashSet<RenderBlock*>::iterator end = containerSet->end();
3427     for (HashSet<RenderBlock*>::iterator it = containerSet->begin(); it != end; ++it) {
3428         RenderBlock* container = *it;
3429         HashSet<RenderBox*>* descendantSet = gPercentHeightDescendantsMap->get(container);
3430         ASSERT(descendantSet);
3431         if (!descendantSet)
3432             continue;
3433         ASSERT(descendantSet->contains(descendant));
3434         descendantSet->remove(descendant);
3435         if (descendantSet->isEmpty()) {
3436             gPercentHeightDescendantsMap->remove(container);
3437             delete descendantSet;
3438         }
3439     }
3440 
3441     delete containerSet;
3442 }
3443 
percentHeightDescendants() const3444 HashSet<RenderBox*>* RenderBlock::percentHeightDescendants() const
3445 {
3446     return gPercentHeightDescendantsMap ? gPercentHeightDescendantsMap->get(this) : 0;
3447 }
3448 
3449 // FIXME: The logicalLeftOffsetForLine/logicalRightOffsetForLine functions are very slow if there are many floats
3450 // present. We need to add a structure to floating objects to represent "lines" of floats.  Then instead of checking
3451 // each float individually, we'd just walk backwards through the "lines" and stop when we hit a line that is fully above
3452 // the vertical offset that we'd like to check.  Computing the "lines" would be rather complicated, but could replace the left
3453 // objects and right objects count hack that is currently used here.
logicalLeftOffsetForLine(int logicalTop,int fixedOffset,bool applyTextIndent,int * heightRemaining) const3454 int RenderBlock::logicalLeftOffsetForLine(int logicalTop, int fixedOffset, bool applyTextIndent, int* heightRemaining) const
3455 {
3456     int left = fixedOffset;
3457     if (m_floatingObjects && m_floatingObjects->hasLeftObjects()) {
3458         if (heightRemaining)
3459             *heightRemaining = 1;
3460 
3461         // We know the list is non-empty, since we have "left" objects to search for.
3462         // Therefore we can assume that begin != end, and that we can do at least one
3463         // decrement.
3464         FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3465         FloatingObjectSetIterator begin = floatingObjectSet.begin();
3466         FloatingObjectSetIterator it = floatingObjectSet.end();
3467         do {
3468             --it;
3469             FloatingObject* r = *it;
3470             if (r->isPlaced() && logicalTopForFloat(r) <= logicalTop && logicalBottomForFloat(r) > logicalTop
3471                 && r->type() == FloatingObject::FloatLeft
3472                 && logicalRightForFloat(r) > left) {
3473                 left = max(left, logicalRightForFloat(r));
3474                 if (heightRemaining)
3475                     *heightRemaining = logicalBottomForFloat(r) - logicalTop;
3476             }
3477         } while (it != begin);
3478     }
3479 
3480     if (applyTextIndent && style()->isLeftToRightDirection()) {
3481         int cw = 0;
3482         if (style()->textIndent().isPercent())
3483             cw = containingBlock()->availableLogicalWidth();
3484         left += style()->textIndent().calcMinValue(cw);
3485     }
3486 
3487     return left;
3488 }
3489 
logicalRightOffsetForLine(int logicalTop,int fixedOffset,bool applyTextIndent,int * heightRemaining) const3490 int RenderBlock::logicalRightOffsetForLine(int logicalTop, int fixedOffset, bool applyTextIndent, int* heightRemaining) const
3491 {
3492     int right = fixedOffset;
3493 
3494     if (m_floatingObjects && m_floatingObjects->hasRightObjects()) {
3495         if (heightRemaining)
3496             *heightRemaining = 1;
3497 
3498         // We know the list is non-empty, since we have "right" objects to search for.
3499         // Therefore we can assume that begin != end, and that we can do at least one
3500         // decrement.
3501         FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3502         FloatingObjectSetIterator begin = floatingObjectSet.begin();
3503         FloatingObjectSetIterator it = floatingObjectSet.end();
3504         do {
3505             --it;
3506             FloatingObject* r = *it;
3507             if (r->isPlaced() && logicalTopForFloat(r) <= logicalTop && logicalBottomForFloat(r) > logicalTop
3508                 && r->type() == FloatingObject::FloatRight
3509                 && logicalLeftForFloat(r) < right) {
3510                 right = min(right, logicalLeftForFloat(r));
3511                 if (heightRemaining)
3512                     *heightRemaining = logicalBottomForFloat(r) - logicalTop;
3513             }
3514         } while (it != begin);
3515     }
3516 
3517     if (applyTextIndent && !style()->isLeftToRightDirection()) {
3518         int cw = 0;
3519         if (style()->textIndent().isPercent())
3520             cw = containingBlock()->availableLogicalWidth();
3521         right -= style()->textIndent().calcMinValue(cw);
3522     }
3523 
3524     return right;
3525 }
3526 
availableLogicalWidthForLine(int position,bool firstLine) const3527 int RenderBlock::availableLogicalWidthForLine(int position, bool firstLine) const
3528 {
3529     int result = logicalRightOffsetForLine(position, firstLine) - logicalLeftOffsetForLine(position, firstLine);
3530     return (result < 0) ? 0 : result;
3531 }
3532 
nextFloatLogicalBottomBelow(int logicalHeight) const3533 int RenderBlock::nextFloatLogicalBottomBelow(int logicalHeight) const
3534 {
3535     if (!m_floatingObjects)
3536         return 0;
3537 
3538     int bottom = INT_MAX;
3539     FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3540     FloatingObjectSetIterator end = floatingObjectSet.end();
3541     for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
3542         FloatingObject* r = *it;
3543         int floatBottom = logicalBottomForFloat(r);
3544         if (floatBottom > logicalHeight)
3545             bottom = min(floatBottom, bottom);
3546     }
3547 
3548     return bottom == INT_MAX ? 0 : bottom;
3549 }
3550 
lowestFloatLogicalBottom(FloatingObject::Type floatType) const3551 int RenderBlock::lowestFloatLogicalBottom(FloatingObject::Type floatType) const
3552 {
3553     if (!m_floatingObjects)
3554         return 0;
3555     int lowestFloatBottom = 0;
3556     FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3557     FloatingObjectSetIterator end = floatingObjectSet.end();
3558     for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
3559         FloatingObject* r = *it;
3560         if (r->isPlaced() && r->type() & floatType)
3561             lowestFloatBottom = max(lowestFloatBottom, logicalBottomForFloat(r));
3562     }
3563     return lowestFloatBottom;
3564 }
3565 
markLinesDirtyInBlockRange(int logicalTop,int logicalBottom,RootInlineBox * highest)3566 void RenderBlock::markLinesDirtyInBlockRange(int logicalTop, int logicalBottom, RootInlineBox* highest)
3567 {
3568     if (logicalTop >= logicalBottom)
3569         return;
3570 
3571     RootInlineBox* lowestDirtyLine = lastRootBox();
3572     RootInlineBox* afterLowest = lowestDirtyLine;
3573     while (lowestDirtyLine && lowestDirtyLine->blockLogicalHeight() >= logicalBottom && logicalBottom < numeric_limits<int>::max()) {
3574         afterLowest = lowestDirtyLine;
3575         lowestDirtyLine = lowestDirtyLine->prevRootBox();
3576     }
3577 
3578     while (afterLowest && afterLowest != highest && (afterLowest->blockLogicalHeight() >= logicalTop || afterLowest->blockLogicalHeight() < 0)) {
3579         afterLowest->markDirty();
3580         afterLowest = afterLowest->prevRootBox();
3581     }
3582 }
3583 
clearFloats()3584 void RenderBlock::clearFloats()
3585 {
3586     // Inline blocks are covered by the isReplaced() check in the avoidFloats method.
3587     if (avoidsFloats() || isRoot() || isRenderView() || isFloatingOrPositioned() || isTableCell()) {
3588         if (m_floatingObjects) {
3589             deleteAllValues(m_floatingObjects->set());
3590             m_floatingObjects->clear();
3591         }
3592         return;
3593     }
3594 
3595     typedef HashMap<RenderObject*, FloatingObject*> RendererToFloatInfoMap;
3596     RendererToFloatInfoMap floatMap;
3597 
3598     if (m_floatingObjects) {
3599         FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3600         if (childrenInline()) {
3601             FloatingObjectSet::iterator end = floatingObjectSet.end();
3602             for (FloatingObjectSet::iterator it = floatingObjectSet.begin(); it != end; ++it) {
3603                 FloatingObject* f = *it;
3604                 floatMap.add(f->m_renderer, f);
3605             }
3606         } else
3607             deleteAllValues(floatingObjectSet);
3608         m_floatingObjects->clear();
3609     }
3610 
3611     // We should not process floats if the parent node is not a RenderBlock. Otherwise, we will add
3612     // floats in an invalid context. This will cause a crash arising from a bad cast on the parent.
3613     // See <rdar://problem/8049753>, where float property is applied on a text node in a SVG.
3614     if (!parent() || !parent()->isRenderBlock())
3615         return;
3616 
3617     // Attempt to locate a previous sibling with overhanging floats.  We skip any elements that are
3618     // out of flow (like floating/positioned elements), and we also skip over any objects that may have shifted
3619     // to avoid floats.
3620     bool parentHasFloats = false;
3621     RenderBlock* parentBlock = toRenderBlock(parent());
3622     RenderObject* prev = previousSibling();
3623     while (prev && (prev->isFloatingOrPositioned() || !prev->isBox() || !prev->isRenderBlock() || toRenderBlock(prev)->avoidsFloats())) {
3624         if (prev->isFloating())
3625             parentHasFloats = true;
3626          prev = prev->previousSibling();
3627     }
3628 
3629     // First add in floats from the parent.
3630     int logicalTopOffset = logicalTop();
3631     if (parentHasFloats)
3632         addIntrudingFloats(parentBlock, parentBlock->logicalLeftOffsetForContent(), logicalTopOffset);
3633 
3634     int logicalLeftOffset = 0;
3635     if (prev)
3636         logicalTopOffset -= toRenderBox(prev)->logicalTop();
3637     else {
3638         prev = parentBlock;
3639         logicalLeftOffset += parentBlock->logicalLeftOffsetForContent();
3640     }
3641 
3642     // Add overhanging floats from the previous RenderBlock, but only if it has a float that intrudes into our space.
3643     if (!prev || !prev->isRenderBlock())
3644         return;
3645 
3646     RenderBlock* block = toRenderBlock(prev);
3647     if (block->m_floatingObjects && block->lowestFloatLogicalBottom() > logicalTopOffset)
3648         addIntrudingFloats(block, logicalLeftOffset, logicalTopOffset);
3649 
3650     if (childrenInline()) {
3651         int changeLogicalTop = numeric_limits<int>::max();
3652         int changeLogicalBottom = numeric_limits<int>::min();
3653         if (m_floatingObjects) {
3654             FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3655             FloatingObjectSetIterator end = floatingObjectSet.end();
3656             for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
3657                 FloatingObject* f = *it;
3658                 FloatingObject* oldFloatingObject = floatMap.get(f->m_renderer);
3659                 int logicalBottom = logicalBottomForFloat(f);
3660                 if (oldFloatingObject) {
3661                     int oldLogicalBottom = logicalBottomForFloat(oldFloatingObject);
3662                     if (logicalWidthForFloat(f) != logicalWidthForFloat(oldFloatingObject) || logicalLeftForFloat(f) != logicalLeftForFloat(oldFloatingObject)) {
3663                         changeLogicalTop = 0;
3664                         changeLogicalBottom = max(changeLogicalBottom, max(logicalBottom, oldLogicalBottom));
3665                     } else if (logicalBottom != oldLogicalBottom) {
3666                         changeLogicalTop = min(changeLogicalTop, min(logicalBottom, oldLogicalBottom));
3667                         changeLogicalBottom = max(changeLogicalBottom, max(logicalBottom, oldLogicalBottom));
3668                     }
3669 
3670                     floatMap.remove(f->m_renderer);
3671                     if (oldFloatingObject->m_originatingLine) {
3672                         ASSERT(oldFloatingObject->m_originatingLine->renderer() == this);
3673                         oldFloatingObject->m_originatingLine->markDirty();
3674                     }
3675                     delete oldFloatingObject;
3676                 } else {
3677                     changeLogicalTop = 0;
3678                     changeLogicalBottom = max(changeLogicalBottom, logicalBottom);
3679                 }
3680             }
3681         }
3682 
3683         RendererToFloatInfoMap::iterator end = floatMap.end();
3684         for (RendererToFloatInfoMap::iterator it = floatMap.begin(); it != end; ++it) {
3685             FloatingObject* floatingObject = (*it).second;
3686             if (!floatingObject->m_isDescendant) {
3687                 changeLogicalTop = 0;
3688                 changeLogicalBottom = max(changeLogicalBottom, logicalBottomForFloat(floatingObject));
3689             }
3690         }
3691         deleteAllValues(floatMap);
3692 
3693         markLinesDirtyInBlockRange(changeLogicalTop, changeLogicalBottom);
3694     }
3695 }
3696 
addOverhangingFloats(RenderBlock * child,int logicalLeftOffset,int logicalTopOffset,bool makeChildPaintOtherFloats)3697 int RenderBlock::addOverhangingFloats(RenderBlock* child, int logicalLeftOffset, int logicalTopOffset, bool makeChildPaintOtherFloats)
3698 {
3699     // Prevent floats from being added to the canvas by the root element, e.g., <html>.
3700     if (child->hasOverflowClip() || !child->containsFloats() || child->isRoot() || child->hasColumns() || child->isWritingModeRoot())
3701         return 0;
3702 
3703     int childLogicalTop = child->logicalTop();
3704     int lowestFloatLogicalBottom = 0;
3705 
3706     // Floats that will remain the child's responsibility to paint should factor into its
3707     // overflow.
3708     FloatingObjectSetIterator childEnd = child->m_floatingObjects->set().end();
3709     for (FloatingObjectSetIterator childIt = child->m_floatingObjects->set().begin(); childIt != childEnd; ++childIt) {
3710         FloatingObject* r = *childIt;
3711         int logicalBottomForFloat = min(this->logicalBottomForFloat(r), numeric_limits<int>::max() - childLogicalTop);
3712         int logicalBottom = childLogicalTop + logicalBottomForFloat;
3713         lowestFloatLogicalBottom = max(lowestFloatLogicalBottom, logicalBottom);
3714 
3715         if (logicalBottom > logicalHeight()) {
3716             // If the object is not in the list, we add it now.
3717             if (!containsFloat(r->m_renderer)) {
3718                 int leftOffset = isHorizontalWritingMode() ? logicalLeftOffset : logicalTopOffset;
3719                 int topOffset = isHorizontalWritingMode() ? logicalTopOffset : logicalLeftOffset;
3720                 FloatingObject* floatingObj = new FloatingObject(r->type(), IntRect(r->x() - leftOffset, r->y() - topOffset, r->width(), r->height()));
3721                 floatingObj->m_renderer = r->m_renderer;
3722 
3723                 // The nearest enclosing layer always paints the float (so that zindex and stacking
3724                 // behaves properly).  We always want to propagate the desire to paint the float as
3725                 // far out as we can, to the outermost block that overlaps the float, stopping only
3726                 // if we hit a self-painting layer boundary.
3727                 if (r->m_renderer->enclosingFloatPaintingLayer() == enclosingFloatPaintingLayer())
3728                     r->m_shouldPaint = false;
3729                 else
3730                     floatingObj->m_shouldPaint = false;
3731 
3732                 floatingObj->m_isDescendant = true;
3733 
3734                 // We create the floating object list lazily.
3735                 if (!m_floatingObjects)
3736                     m_floatingObjects = adoptPtr(new FloatingObjects);
3737 
3738                 m_floatingObjects->increaseObjectsCount(floatingObj->type());
3739                 m_floatingObjects->set().add(floatingObj);
3740             }
3741         } else {
3742             if (makeChildPaintOtherFloats && !r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer() &&
3743                 r->m_renderer->isDescendantOf(child) && r->m_renderer->enclosingFloatPaintingLayer() == child->enclosingFloatPaintingLayer()) {
3744                 // The float is not overhanging from this block, so if it is a descendant of the child, the child should
3745                 // paint it (the other case is that it is intruding into the child), unless it has its own layer or enclosing
3746                 // layer.
3747                 // If makeChildPaintOtherFloats is false, it means that the child must already know about all the floats
3748                 // it should paint.
3749                 r->m_shouldPaint = true;
3750             }
3751 
3752             // Since the float doesn't overhang, it didn't get put into our list.  We need to go ahead and add its overflow in to the
3753             // child now.
3754             if (r->m_isDescendant)
3755                 child->addOverflowFromChild(r->m_renderer, IntSize(xPositionForFloatIncludingMargin(r), yPositionForFloatIncludingMargin(r)));
3756         }
3757     }
3758     return lowestFloatLogicalBottom;
3759 }
3760 
hasOverhangingFloat(RenderBox * renderer)3761 bool RenderBlock::hasOverhangingFloat(RenderBox* renderer)
3762 {
3763     if (!m_floatingObjects || hasColumns() || !parent())
3764         return false;
3765 
3766     FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3767     FloatingObjectSetIterator it = floatingObjectSet.find<RenderBox*, FloatingObjectHashTranslator>(renderer);
3768     if (it == floatingObjectSet.end())
3769         return false;
3770 
3771     return logicalBottomForFloat(*it) > logicalHeight();
3772 }
3773 
addIntrudingFloats(RenderBlock * prev,int logicalLeftOffset,int logicalTopOffset)3774 void RenderBlock::addIntrudingFloats(RenderBlock* prev, int logicalLeftOffset, int logicalTopOffset)
3775 {
3776     // If the parent or previous sibling doesn't have any floats to add, don't bother.
3777     if (!prev->m_floatingObjects)
3778         return;
3779 
3780     logicalLeftOffset += (isHorizontalWritingMode() ? marginLeft() : marginTop());
3781 
3782     FloatingObjectSet& prevSet = prev->m_floatingObjects->set();
3783     FloatingObjectSetIterator prevEnd = prevSet.end();
3784     for (FloatingObjectSetIterator prevIt = prevSet.begin(); prevIt != prevEnd; ++prevIt) {
3785         FloatingObject* r = *prevIt;
3786         if (logicalBottomForFloat(r) > logicalTopOffset) {
3787             if (!m_floatingObjects || !m_floatingObjects->set().contains(r)) {
3788                 int leftOffset = isHorizontalWritingMode() ? logicalLeftOffset : logicalTopOffset;
3789                 int topOffset = isHorizontalWritingMode() ? logicalTopOffset : logicalLeftOffset;
3790 
3791                 FloatingObject* floatingObj = new FloatingObject(r->type(), IntRect(r->x() - leftOffset, r->y() - topOffset, r->width(), r->height()));
3792 
3793                 // Applying the child's margin makes no sense in the case where the child was passed in.
3794                 // since this margin was added already through the modification of the |logicalLeftOffset| variable
3795                 // above.  |logicalLeftOffset| will equal the margin in this case, so it's already been taken
3796                 // into account.  Only apply this code if prev is the parent, since otherwise the left margin
3797                 // will get applied twice.
3798                 if (prev != parent()) {
3799                     if (isHorizontalWritingMode())
3800                         floatingObj->setX(floatingObj->x() + prev->marginLeft());
3801                     else
3802                         floatingObj->setY(floatingObj->y() + prev->marginTop());
3803                 }
3804 
3805                 floatingObj->m_shouldPaint = false;  // We are not in the direct inheritance chain for this float. We will never paint it.
3806                 floatingObj->m_renderer = r->m_renderer;
3807 
3808                 // We create the floating object list lazily.
3809                 if (!m_floatingObjects)
3810                     m_floatingObjects = adoptPtr(new FloatingObjects);
3811                 m_floatingObjects->increaseObjectsCount(floatingObj->type());
3812                 m_floatingObjects->set().add(floatingObj);
3813             }
3814         }
3815     }
3816 }
3817 
avoidsFloats() const3818 bool RenderBlock::avoidsFloats() const
3819 {
3820     // Floats can't intrude into our box if we have a non-auto column count or width.
3821     return RenderBox::avoidsFloats() || !style()->hasAutoColumnCount() || !style()->hasAutoColumnWidth();
3822 }
3823 
containsFloat(RenderBox * renderer)3824 bool RenderBlock::containsFloat(RenderBox* renderer)
3825 {
3826     return m_floatingObjects && m_floatingObjects->set().contains<RenderBox*, FloatingObjectHashTranslator>(renderer);
3827 }
3828 
markAllDescendantsWithFloatsForLayout(RenderBox * floatToRemove,bool inLayout)3829 void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove, bool inLayout)
3830 {
3831     if (!m_everHadLayout)
3832         return;
3833 
3834     setChildNeedsLayout(true, !inLayout);
3835 
3836     if (floatToRemove)
3837         removeFloatingObject(floatToRemove);
3838 
3839     // Iterate over our children and mark them as needed.
3840     if (!childrenInline()) {
3841         for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
3842             if ((!floatToRemove && child->isFloatingOrPositioned()) || !child->isRenderBlock())
3843                 continue;
3844             RenderBlock* childBlock = toRenderBlock(child);
3845             if ((floatToRemove ? childBlock->containsFloat(floatToRemove) : childBlock->containsFloats()) || childBlock->shrinkToAvoidFloats())
3846                 childBlock->markAllDescendantsWithFloatsForLayout(floatToRemove, inLayout);
3847         }
3848     }
3849 }
3850 
markSiblingsWithFloatsForLayout()3851 void RenderBlock::markSiblingsWithFloatsForLayout()
3852 {
3853     FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
3854     FloatingObjectSetIterator end = floatingObjectSet.end();
3855     for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
3856         if (logicalBottomForFloat(*it) > logicalHeight()) {
3857             RenderBox* floatingBox = (*it)->renderer();
3858 
3859             RenderObject* next = nextSibling();
3860             while (next) {
3861                 if (next->isRenderBlock() && !next->isFloatingOrPositioned() && !toRenderBlock(next)->avoidsFloats()) {
3862                     RenderBlock* nextBlock = toRenderBlock(next);
3863                     if (nextBlock->containsFloat(floatingBox))
3864                         nextBlock->markAllDescendantsWithFloatsForLayout(floatingBox);
3865                     else
3866                         break;
3867                 }
3868 
3869                 next = next->nextSibling();
3870             }
3871         }
3872     }
3873 }
3874 
getClearDelta(RenderBox * child,int yPos)3875 int RenderBlock::getClearDelta(RenderBox* child, int yPos)
3876 {
3877     // There is no need to compute clearance if we have no floats.
3878     if (!containsFloats())
3879         return 0;
3880 
3881     // At least one float is present.  We need to perform the clearance computation.
3882     bool clearSet = child->style()->clear() != CNONE;
3883     int bottom = 0;
3884     switch (child->style()->clear()) {
3885         case CNONE:
3886             break;
3887         case CLEFT:
3888             bottom = lowestFloatLogicalBottom(FloatingObject::FloatLeft);
3889             break;
3890         case CRIGHT:
3891             bottom = lowestFloatLogicalBottom(FloatingObject::FloatRight);
3892             break;
3893         case CBOTH:
3894             bottom = lowestFloatLogicalBottom();
3895             break;
3896     }
3897 
3898     // We also clear floats if we are too big to sit on the same line as a float (and wish to avoid floats by default).
3899     int result = clearSet ? max(0, bottom - yPos) : 0;
3900     if (!result && child->avoidsFloats()) {
3901         int y = yPos;
3902         while (true) {
3903             int widthAtY = availableLogicalWidthForLine(y, false);
3904             if (widthAtY == availableLogicalWidth())
3905                 return y - yPos;
3906 
3907             int oldChildY = child->y();
3908             int oldChildWidth = child->width();
3909             child->setY(y);
3910             child->computeLogicalWidth();
3911             int childWidthAtY = child->width();
3912             child->setY(oldChildY);
3913             child->setWidth(oldChildWidth);
3914 
3915             if (childWidthAtY <= widthAtY)
3916                 return y - yPos;
3917 
3918             y = nextFloatLogicalBottomBelow(y);
3919             ASSERT(y >= yPos);
3920             if (y < yPos)
3921                 break;
3922         }
3923         ASSERT_NOT_REACHED();
3924     }
3925     return result;
3926 }
3927 
isPointInOverflowControl(HitTestResult & result,int _x,int _y,int _tx,int _ty)3928 bool RenderBlock::isPointInOverflowControl(HitTestResult& result, int _x, int _y, int _tx, int _ty)
3929 {
3930     if (!scrollsOverflow())
3931         return false;
3932 
3933     return layer()->hitTestOverflowControls(result, IntPoint(_x - _tx, _y - _ty));
3934 }
3935 
nodeAtPoint(const HitTestRequest & request,HitTestResult & result,int _x,int _y,int _tx,int _ty,HitTestAction hitTestAction)3936 bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
3937 {
3938     int tx = _tx + x();
3939     int ty = _ty + y();
3940 
3941     if (!isRenderView()) {
3942         // Check if we need to do anything at all.
3943         IntRect overflowBox = visualOverflowRect();
3944         overflowBox.move(tx, ty);
3945         if (!overflowBox.intersects(result.rectForPoint(_x, _y)))
3946             return false;
3947     }
3948 
3949     if ((hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) && isPointInOverflowControl(result, _x, _y, tx, ty)) {
3950         updateHitTestResult(result, IntPoint(_x - tx, _y - ty));
3951         // FIXME: isPointInOverflowControl() doesn't handle rect-based tests yet.
3952         if (!result.addNodeToRectBasedTestResult(node(), _x, _y))
3953            return true;
3954     }
3955 
3956     // If we have clipping, then we can't have any spillout.
3957     bool useOverflowClip = hasOverflowClip() && !hasSelfPaintingLayer();
3958     bool useClip = (hasControlClip() || useOverflowClip);
3959     IntRect hitTestArea(result.rectForPoint(_x, _y));
3960     bool checkChildren = !useClip || (hasControlClip() ? controlClipRect(tx, ty).intersects(hitTestArea) : overflowClipRect(tx, ty, IncludeOverlayScrollbarSize).intersects(hitTestArea));
3961     if (checkChildren) {
3962         // Hit test descendants first.
3963         int scrolledX = tx;
3964         int scrolledY = ty;
3965         if (hasOverflowClip()) {
3966             IntSize offset = layer()->scrolledContentOffset();
3967             scrolledX -= offset.width();
3968             scrolledY -= offset.height();
3969         }
3970 
3971         // Hit test contents if we don't have columns.
3972         if (!hasColumns()) {
3973             if (hitTestContents(request, result, _x, _y, scrolledX, scrolledY, hitTestAction)) {
3974                 updateHitTestResult(result, IntPoint(_x - tx, _y - ty));
3975                 return true;
3976             }
3977             if (hitTestAction == HitTestFloat && hitTestFloats(request, result, _x, _y, scrolledX, scrolledY))
3978                 return true;
3979         } else if (hitTestColumns(request, result, _x, _y, scrolledX, scrolledY, hitTestAction)) {
3980             updateHitTestResult(result, IntPoint(_x - tx, _y - ty));
3981             return true;
3982         }
3983     }
3984 
3985     // Now hit test our background
3986     if (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) {
3987         IntRect boundsRect(tx, ty, width(), height());
3988         if (visibleToHitTesting() && boundsRect.intersects(result.rectForPoint(_x, _y))) {
3989             updateHitTestResult(result, flipForWritingMode(IntPoint(_x - tx, _y - ty)));
3990             if (!result.addNodeToRectBasedTestResult(node(), _x, _y, boundsRect))
3991                 return true;
3992         }
3993     }
3994 
3995     return false;
3996 }
3997 
hitTestFloats(const HitTestRequest & request,HitTestResult & result,int x,int y,int tx,int ty)3998 bool RenderBlock::hitTestFloats(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty)
3999 {
4000     if (!m_floatingObjects)
4001         return false;
4002 
4003     if (isRenderView()) {
4004         tx += toRenderView(this)->frameView()->scrollX();
4005         ty += toRenderView(this)->frameView()->scrollY();
4006     }
4007 
4008     FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
4009     FloatingObjectSetIterator begin = floatingObjectSet.begin();
4010     for (FloatingObjectSetIterator it = floatingObjectSet.end(); it != begin;) {
4011         --it;
4012         FloatingObject* floatingObject = *it;
4013         if (floatingObject->m_shouldPaint && !floatingObject->m_renderer->hasSelfPaintingLayer()) {
4014             int xOffset = xPositionForFloatIncludingMargin(floatingObject) - floatingObject->m_renderer->x();
4015             int yOffset = yPositionForFloatIncludingMargin(floatingObject) - floatingObject->m_renderer->y();
4016             IntPoint childPoint = flipFloatForWritingMode(floatingObject, IntPoint(tx + xOffset, ty + yOffset));
4017             if (floatingObject->m_renderer->hitTest(request, result, IntPoint(x, y), childPoint.x(), childPoint.y())) {
4018                 updateHitTestResult(result, IntPoint(x - childPoint.x(), y - childPoint.y()));
4019                 return true;
4020             }
4021         }
4022     }
4023 
4024     return false;
4025 }
4026 
hitTestColumns(const HitTestRequest & request,HitTestResult & result,int x,int y,int tx,int ty,HitTestAction hitTestAction)4027 bool RenderBlock::hitTestColumns(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
4028 {
4029     // We need to do multiple passes, breaking up our hit testing into strips.
4030     ColumnInfo* colInfo = columnInfo();
4031     int colCount = columnCount(colInfo);
4032     if (!colCount)
4033         return false;
4034     int logicalLeft = logicalLeftOffsetForContent();
4035     int currLogicalTopOffset = 0;
4036     int i;
4037     bool isHorizontal = isHorizontalWritingMode();
4038     for (i = 0; i < colCount; i++) {
4039         IntRect colRect = columnRectAt(colInfo, i);
4040         int blockDelta =  (isHorizontal ? colRect.height() : colRect.width());
4041         if (style()->isFlippedBlocksWritingMode())
4042             currLogicalTopOffset += blockDelta;
4043         else
4044             currLogicalTopOffset -= blockDelta;
4045     }
4046     for (i = colCount - 1; i >= 0; i--) {
4047         IntRect colRect = columnRectAt(colInfo, i);
4048         flipForWritingMode(colRect);
4049         int currLogicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - logicalLeft;
4050         int blockDelta =  (isHorizontal ? colRect.height() : colRect.width());
4051         if (style()->isFlippedBlocksWritingMode())
4052             currLogicalTopOffset -= blockDelta;
4053         else
4054             currLogicalTopOffset += blockDelta;
4055         colRect.move(tx, ty);
4056 
4057         if (colRect.intersects(result.rectForPoint(x, y))) {
4058             // The point is inside this column.
4059             // Adjust tx and ty to change where we hit test.
4060 
4061             IntSize offset = isHorizontal ? IntSize(currLogicalLeftOffset, currLogicalTopOffset) : IntSize(currLogicalTopOffset, currLogicalLeftOffset);
4062             int finalX = tx + offset.width();
4063             int finalY = ty + offset.height();
4064             if (result.isRectBasedTest() && !colRect.contains(result.rectForPoint(x, y)))
4065                 hitTestContents(request, result, x, y, finalX, finalY, hitTestAction);
4066             else
4067                 return hitTestContents(request, result, x, y, finalX, finalY, hitTestAction) || (hitTestAction == HitTestFloat && hitTestFloats(request, result, x, y, finalX, finalY));
4068         }
4069     }
4070 
4071     return false;
4072 }
4073 
hitTestContents(const HitTestRequest & request,HitTestResult & result,int x,int y,int tx,int ty,HitTestAction hitTestAction)4074 bool RenderBlock::hitTestContents(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
4075 {
4076     if (childrenInline() && !isTable()) {
4077         // We have to hit-test our line boxes.
4078         if (m_lineBoxes.hitTest(this, request, result, x, y, tx, ty, hitTestAction))
4079             return true;
4080     } else {
4081         // Hit test our children.
4082         HitTestAction childHitTest = hitTestAction;
4083         if (hitTestAction == HitTestChildBlockBackgrounds)
4084             childHitTest = HitTestChildBlockBackground;
4085         for (RenderBox* child = lastChildBox(); child; child = child->previousSiblingBox()) {
4086             IntPoint childPoint = flipForWritingMode(child, IntPoint(tx, ty), ParentToChildFlippingAdjustment);
4087             if (!child->hasSelfPaintingLayer() && !child->isFloating() && child->nodeAtPoint(request, result, x, y, childPoint.x(), childPoint.y(), childHitTest))
4088                 return true;
4089         }
4090     }
4091 
4092     return false;
4093 }
4094 
positionForBox(InlineBox * box,bool start) const4095 Position RenderBlock::positionForBox(InlineBox *box, bool start) const
4096 {
4097     if (!box)
4098         return Position();
4099 
4100     if (!box->renderer()->node())
4101         return Position(node(), start ? caretMinOffset() : caretMaxOffset());
4102 
4103     if (!box->isInlineTextBox())
4104         return Position(box->renderer()->node(), start ? box->renderer()->caretMinOffset() : box->renderer()->caretMaxOffset());
4105 
4106     InlineTextBox *textBox = static_cast<InlineTextBox *>(box);
4107     return Position(box->renderer()->node(), start ? textBox->start() : textBox->start() + textBox->len());
4108 }
4109 
4110 // FIXME: This function should go on RenderObject as an instance method. Then
4111 // all cases in which positionForPoint recurs could call this instead to
4112 // prevent crossing editable boundaries. This would require many tests.
positionForPointRespectingEditingBoundaries(RenderBlock * parent,RenderBox * child,const IntPoint & pointInParentCoordinates)4113 static VisiblePosition positionForPointRespectingEditingBoundaries(RenderBlock* parent, RenderBox* child, const IntPoint& pointInParentCoordinates)
4114 {
4115     // FIXME: This is wrong if the child's writing-mode is different from the parent's.
4116     IntPoint pointInChildCoordinates(pointInParentCoordinates - child->location());
4117 
4118     // If this is an anonymous renderer, we just recur normally
4119     Node* childNode = child->node();
4120     if (!childNode)
4121         return child->positionForPoint(pointInChildCoordinates);
4122 
4123     // Otherwise, first make sure that the editability of the parent and child agree.
4124     // If they don't agree, then we return a visible position just before or after the child
4125     RenderObject* ancestor = parent;
4126     while (ancestor && !ancestor->node())
4127         ancestor = ancestor->parent();
4128 
4129     // If we can't find an ancestor to check editability on, or editability is unchanged, we recur like normal
4130     if (!ancestor || ancestor->node()->rendererIsEditable() == childNode->rendererIsEditable())
4131         return child->positionForPoint(pointInChildCoordinates);
4132 
4133     // Otherwise return before or after the child, depending on if the click was to the logical left or logical right of the child
4134     int childMiddle = parent->logicalWidthForChild(child) / 2;
4135     int logicalLeft = parent->isHorizontalWritingMode() ? pointInChildCoordinates.x() : pointInChildCoordinates.y();
4136     if (logicalLeft < childMiddle)
4137         return ancestor->createVisiblePosition(childNode->nodeIndex(), DOWNSTREAM);
4138     return ancestor->createVisiblePosition(childNode->nodeIndex() + 1, UPSTREAM);
4139 }
4140 
positionForPointWithInlineChildren(const IntPoint & pointInLogicalContents)4141 VisiblePosition RenderBlock::positionForPointWithInlineChildren(const IntPoint& pointInLogicalContents)
4142 {
4143     ASSERT(childrenInline());
4144 
4145     if (!firstRootBox())
4146         return createVisiblePosition(0, DOWNSTREAM);
4147 
4148     // look for the closest line box in the root box which is at the passed-in y coordinate
4149     InlineBox* closestBox = 0;
4150     RootInlineBox* firstRootBoxWithChildren = 0;
4151     RootInlineBox* lastRootBoxWithChildren = 0;
4152     for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) {
4153         if (!root->firstLeafChild())
4154             continue;
4155         if (!firstRootBoxWithChildren)
4156             firstRootBoxWithChildren = root;
4157         lastRootBoxWithChildren = root;
4158 
4159         // check if this root line box is located at this y coordinate
4160         if (pointInLogicalContents.y() < root->selectionBottom()) {
4161             closestBox = root->closestLeafChildForLogicalLeftPosition(pointInLogicalContents.x());
4162             if (closestBox)
4163                 break;
4164         }
4165     }
4166 
4167     bool moveCaretToBoundary = document()->frame()->editor()->behavior().shouldMoveCaretToHorizontalBoundaryWhenPastTopOrBottom();
4168 
4169     if (!moveCaretToBoundary && !closestBox && lastRootBoxWithChildren) {
4170         // y coordinate is below last root line box, pretend we hit it
4171         closestBox = lastRootBoxWithChildren->closestLeafChildForLogicalLeftPosition(pointInLogicalContents.x());
4172     }
4173 
4174     if (closestBox) {
4175         if (moveCaretToBoundary && pointInLogicalContents.y() < firstRootBoxWithChildren->selectionTop()) {
4176             // y coordinate is above first root line box, so return the start of the first
4177             return VisiblePosition(positionForBox(firstRootBoxWithChildren->firstLeafChild(), true), DOWNSTREAM);
4178         }
4179 
4180         // pass the box a top position that is inside it
4181         IntPoint point(pointInLogicalContents.x(), closestBox->logicalTop());
4182         if (!isHorizontalWritingMode())
4183             point = point.transposedPoint();
4184         if (closestBox->renderer()->isReplaced())
4185             return positionForPointRespectingEditingBoundaries(this, toRenderBox(closestBox->renderer()), point);
4186         return closestBox->renderer()->positionForPoint(point);
4187     }
4188 
4189     if (lastRootBoxWithChildren) {
4190         // We hit this case for Mac behavior when the Y coordinate is below the last box.
4191         ASSERT(moveCaretToBoundary);
4192         InlineBox* logicallyLastBox;
4193         if (lastRootBoxWithChildren->getLogicalEndBoxWithNode(logicallyLastBox))
4194             return VisiblePosition(positionForBox(logicallyLastBox, false), DOWNSTREAM);
4195     }
4196 
4197     // Can't reach this. We have a root line box, but it has no kids.
4198     // FIXME: This should ASSERT_NOT_REACHED(), but clicking on placeholder text
4199     // seems to hit this code path.
4200     return createVisiblePosition(0, DOWNSTREAM);
4201 }
4202 
isChildHitTestCandidate(RenderBox * box)4203 static inline bool isChildHitTestCandidate(RenderBox* box)
4204 {
4205     return box->height() && box->style()->visibility() == VISIBLE && !box->isFloatingOrPositioned();
4206 }
4207 
positionForPoint(const IntPoint & point)4208 VisiblePosition RenderBlock::positionForPoint(const IntPoint& point)
4209 {
4210     if (isTable())
4211         return RenderBox::positionForPoint(point);
4212 
4213     if (isReplaced()) {
4214         // FIXME: This seems wrong when the object's writing-mode doesn't match the line's writing-mode.
4215         int pointLogicalLeft = isHorizontalWritingMode() ? point.x() : point.y();
4216         int pointLogicalTop = isHorizontalWritingMode() ? point.y() : point.x();
4217 
4218         if (pointLogicalTop < 0 || (pointLogicalTop < logicalHeight() && pointLogicalLeft < 0))
4219             return createVisiblePosition(caretMinOffset(), DOWNSTREAM);
4220         if (pointLogicalTop >= logicalHeight() || (pointLogicalTop >= 0 && pointLogicalLeft >= logicalWidth()))
4221             return createVisiblePosition(caretMaxOffset(), DOWNSTREAM);
4222     }
4223 
4224     int contentsX = point.x();
4225     int contentsY = point.y();
4226     offsetForContents(contentsX, contentsY);
4227     IntPoint pointInContents(contentsX, contentsY);
4228     IntPoint pointInLogicalContents(pointInContents);
4229     if (!isHorizontalWritingMode())
4230         pointInLogicalContents = pointInLogicalContents.transposedPoint();
4231 
4232     if (childrenInline())
4233         return positionForPointWithInlineChildren(pointInLogicalContents);
4234 
4235     if (lastChildBox() && pointInContents.y() > lastChildBox()->logicalTop()) {
4236         for (RenderBox* childBox = lastChildBox(); childBox; childBox = childBox->previousSiblingBox()) {
4237             if (isChildHitTestCandidate(childBox))
4238                 return positionForPointRespectingEditingBoundaries(this, childBox, pointInContents);
4239         }
4240     } else {
4241         for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) {
4242             // We hit child if our click is above the bottom of its padding box (like IE6/7 and FF3).
4243             if (isChildHitTestCandidate(childBox) && pointInContents.y() < childBox->logicalBottom())
4244                 return positionForPointRespectingEditingBoundaries(this, childBox, pointInContents);
4245         }
4246     }
4247 
4248     // We only get here if there are no hit test candidate children below the click.
4249     return RenderBox::positionForPoint(point);
4250 }
4251 
offsetForContents(int & tx,int & ty) const4252 void RenderBlock::offsetForContents(int& tx, int& ty) const
4253 {
4254     IntPoint contentsPoint(tx, ty);
4255 
4256     if (hasOverflowClip())
4257         contentsPoint += layer()->scrolledContentOffset();
4258 
4259     if (hasColumns())
4260         adjustPointToColumnContents(contentsPoint);
4261 
4262     tx = contentsPoint.x();
4263     ty = contentsPoint.y();
4264 }
4265 
availableLogicalWidth() const4266 int RenderBlock::availableLogicalWidth() const
4267 {
4268     // If we have multiple columns, then the available logical width is reduced to our column width.
4269     if (hasColumns())
4270         return desiredColumnWidth();
4271     return RenderBox::availableLogicalWidth();
4272 }
4273 
columnGap() const4274 int RenderBlock::columnGap() const
4275 {
4276     if (style()->hasNormalColumnGap())
4277         return style()->fontDescription().computedPixelSize(); // "1em" is recommended as the normal gap setting. Matches <p> margins.
4278     return static_cast<int>(style()->columnGap());
4279 }
4280 
calcColumnWidth()4281 void RenderBlock::calcColumnWidth()
4282 {
4283     // Calculate our column width and column count.
4284     unsigned desiredColumnCount = 1;
4285     int desiredColumnWidth = contentLogicalWidth();
4286 
4287     // For now, we don't support multi-column layouts when printing, since we have to do a lot of work for proper pagination.
4288     if (document()->paginated() || (style()->hasAutoColumnCount() && style()->hasAutoColumnWidth())) {
4289         setDesiredColumnCountAndWidth(desiredColumnCount, desiredColumnWidth);
4290         return;
4291     }
4292 
4293     int availWidth = desiredColumnWidth;
4294     int colGap = columnGap();
4295     int colWidth = max(1, static_cast<int>(style()->columnWidth()));
4296     int colCount = max(1, static_cast<int>(style()->columnCount()));
4297 
4298     if (style()->hasAutoColumnWidth() && !style()->hasAutoColumnCount()) {
4299         desiredColumnCount = colCount;
4300         desiredColumnWidth = max<int>(0, (availWidth - ((desiredColumnCount - 1) * colGap)) / desiredColumnCount);
4301     } else if (!style()->hasAutoColumnWidth() && style()->hasAutoColumnCount()) {
4302         desiredColumnCount = max<int>(1, (float)(availWidth + colGap) / (colWidth + colGap));
4303         desiredColumnWidth = ((availWidth + colGap) / desiredColumnCount) - colGap;
4304     } else {
4305         desiredColumnCount = max(min<int>(colCount, (float)(availWidth + colGap) / (colWidth + colGap)), 1);
4306         desiredColumnWidth = ((availWidth + colGap) / desiredColumnCount) - colGap;
4307     }
4308     setDesiredColumnCountAndWidth(desiredColumnCount, desiredColumnWidth);
4309 }
4310 
setDesiredColumnCountAndWidth(int count,int width)4311 void RenderBlock::setDesiredColumnCountAndWidth(int count, int width)
4312 {
4313     bool destroyColumns = !firstChild()
4314                           || (count == 1 && style()->hasAutoColumnWidth())
4315                           || firstChild()->isAnonymousColumnsBlock()
4316                           || firstChild()->isAnonymousColumnSpanBlock();
4317     if (destroyColumns) {
4318         if (hasColumns()) {
4319             delete gColumnInfoMap->take(this);
4320             setHasColumns(false);
4321         }
4322     } else {
4323         ColumnInfo* info;
4324         if (hasColumns())
4325             info = gColumnInfoMap->get(this);
4326         else {
4327             if (!gColumnInfoMap)
4328                 gColumnInfoMap = new ColumnInfoMap;
4329             info = new ColumnInfo;
4330             gColumnInfoMap->add(this, info);
4331             setHasColumns(true);
4332         }
4333         info->setDesiredColumnCount(count);
4334         info->setDesiredColumnWidth(width);
4335     }
4336 }
4337 
desiredColumnWidth() const4338 int RenderBlock::desiredColumnWidth() const
4339 {
4340     if (!hasColumns())
4341         return contentLogicalWidth();
4342     return gColumnInfoMap->get(this)->desiredColumnWidth();
4343 }
4344 
desiredColumnCount() const4345 unsigned RenderBlock::desiredColumnCount() const
4346 {
4347     if (!hasColumns())
4348         return 1;
4349     return gColumnInfoMap->get(this)->desiredColumnCount();
4350 }
4351 
columnInfo() const4352 ColumnInfo* RenderBlock::columnInfo() const
4353 {
4354     if (!hasColumns())
4355         return 0;
4356     return gColumnInfoMap->get(this);
4357 }
4358 
columnCount(ColumnInfo * colInfo) const4359 unsigned RenderBlock::columnCount(ColumnInfo* colInfo) const
4360 {
4361     ASSERT(hasColumns() && gColumnInfoMap->get(this) == colInfo);
4362     return colInfo->columnCount();
4363 }
4364 
columnRectAt(ColumnInfo * colInfo,unsigned index) const4365 IntRect RenderBlock::columnRectAt(ColumnInfo* colInfo, unsigned index) const
4366 {
4367     ASSERT(hasColumns() && gColumnInfoMap->get(this) == colInfo);
4368 
4369     // Compute the appropriate rect based off our information.
4370     int colLogicalWidth = colInfo->desiredColumnWidth();
4371     int colLogicalHeight = colInfo->columnHeight();
4372     int colLogicalTop = borderBefore() + paddingBefore();
4373     int colGap = columnGap();
4374     int colLogicalLeft = style()->isLeftToRightDirection() ?
4375                           logicalLeftOffsetForContent() + (index * (colLogicalWidth + colGap))
4376                         : logicalLeftOffsetForContent() + contentLogicalWidth() - colLogicalWidth - (index * (colLogicalWidth + colGap));
4377     IntRect rect(colLogicalLeft, colLogicalTop, colLogicalWidth, colLogicalHeight);
4378     if (isHorizontalWritingMode())
4379         return IntRect(colLogicalLeft, colLogicalTop, colLogicalWidth, colLogicalHeight);
4380     return IntRect(colLogicalTop, colLogicalLeft, colLogicalHeight, colLogicalWidth);
4381 }
4382 
layoutColumns(bool hasSpecifiedPageLogicalHeight,int pageLogicalHeight,LayoutStateMaintainer & statePusher)4383 bool RenderBlock::layoutColumns(bool hasSpecifiedPageLogicalHeight, int pageLogicalHeight, LayoutStateMaintainer& statePusher)
4384 {
4385     if (!hasColumns())
4386         return false;
4387 
4388     // FIXME: We don't balance properly at all in the presence of forced page breaks.  We need to understand what
4389     // the distance between forced page breaks is so that we can avoid making the minimum column height too tall.
4390     ColumnInfo* colInfo = columnInfo();
4391     int desiredColumnCount = colInfo->desiredColumnCount();
4392     if (!hasSpecifiedPageLogicalHeight) {
4393         int columnHeight = pageLogicalHeight;
4394         int minColumnCount = colInfo->forcedBreaks() + 1;
4395         if (minColumnCount >= desiredColumnCount) {
4396             // The forced page breaks are in control of the balancing.  Just set the column height to the
4397             // maximum page break distance.
4398             if (!pageLogicalHeight) {
4399                 int distanceBetweenBreaks = max(colInfo->maximumDistanceBetweenForcedBreaks(),
4400                                                 view()->layoutState()->pageLogicalOffset(borderBefore() + paddingBefore() + contentLogicalHeight()) - colInfo->forcedBreakOffset());
4401                 columnHeight = max(colInfo->minimumColumnHeight(), distanceBetweenBreaks);
4402             }
4403         } else if (contentLogicalHeight() > pageLogicalHeight * desiredColumnCount) {
4404             // Now that we know the intrinsic height of the columns, we have to rebalance them.
4405             columnHeight = max(colInfo->minimumColumnHeight(), (int)ceilf((float)contentLogicalHeight() / desiredColumnCount));
4406         }
4407 
4408         if (columnHeight && columnHeight != pageLogicalHeight) {
4409             statePusher.pop();
4410             m_everHadLayout = true;
4411             layoutBlock(false, columnHeight);
4412             return true;
4413         }
4414     }
4415 
4416     if (pageLogicalHeight)
4417         colInfo->setColumnCountAndHeight(ceilf((float)contentLogicalHeight() / pageLogicalHeight), pageLogicalHeight);
4418 
4419     if (columnCount(colInfo)) {
4420         setLogicalHeight(borderBefore() + paddingBefore() + colInfo->columnHeight() + borderAfter() + paddingAfter() + scrollbarLogicalHeight());
4421         m_overflow.clear();
4422     }
4423 
4424     return false;
4425 }
4426 
adjustPointToColumnContents(IntPoint & point) const4427 void RenderBlock::adjustPointToColumnContents(IntPoint& point) const
4428 {
4429     // Just bail if we have no columns.
4430     if (!hasColumns())
4431         return;
4432 
4433     ColumnInfo* colInfo = columnInfo();
4434     if (!columnCount(colInfo))
4435         return;
4436 
4437     // Determine which columns we intersect.
4438     int colGap = columnGap();
4439     int halfColGap = colGap / 2;
4440     IntPoint columnPoint(columnRectAt(colInfo, 0).location());
4441     int logicalOffset = 0;
4442     for (unsigned i = 0; i < colInfo->columnCount(); i++) {
4443         // Add in half the column gap to the left and right of the rect.
4444         IntRect colRect = columnRectAt(colInfo, i);
4445         if (isHorizontalWritingMode()) {
4446             IntRect gapAndColumnRect(colRect.x() - halfColGap, colRect.y(), colRect.width() + colGap, colRect.height());
4447             if (point.x() >= gapAndColumnRect.x() && point.x() < gapAndColumnRect.maxX()) {
4448                 // FIXME: The clamping that follows is not completely right for right-to-left
4449                 // content.
4450                 // Clamp everything above the column to its top left.
4451                 if (point.y() < gapAndColumnRect.y())
4452                     point = gapAndColumnRect.location();
4453                 // Clamp everything below the column to the next column's top left. If there is
4454                 // no next column, this still maps to just after this column.
4455                 else if (point.y() >= gapAndColumnRect.maxY()) {
4456                     point = gapAndColumnRect.location();
4457                     point.move(0, gapAndColumnRect.height());
4458                 }
4459 
4460                 // We're inside the column.  Translate the x and y into our column coordinate space.
4461                 point.move(columnPoint.x() - colRect.x(), logicalOffset);
4462                 return;
4463             }
4464 
4465             // Move to the next position.
4466             logicalOffset += colRect.height();
4467         } else {
4468             IntRect gapAndColumnRect(colRect.x(), colRect.y() - halfColGap, colRect.width(), colRect.height() + colGap);
4469             if (point.y() >= gapAndColumnRect.y() && point.y() < gapAndColumnRect.maxY()) {
4470                 // FIXME: The clamping that follows is not completely right for right-to-left
4471                 // content.
4472                 // Clamp everything above the column to its top left.
4473                 if (point.x() < gapAndColumnRect.x())
4474                     point = gapAndColumnRect.location();
4475                 // Clamp everything below the column to the next column's top left. If there is
4476                 // no next column, this still maps to just after this column.
4477                 else if (point.x() >= gapAndColumnRect.maxX()) {
4478                     point = gapAndColumnRect.location();
4479                     point.move(gapAndColumnRect.width(), 0);
4480                 }
4481 
4482                 // We're inside the column.  Translate the x and y into our column coordinate space.
4483                 point.move(logicalOffset, columnPoint.y() - colRect.y());
4484                 return;
4485             }
4486 
4487             // Move to the next position.
4488             logicalOffset += colRect.width();
4489         }
4490     }
4491 }
4492 
adjustRectForColumns(IntRect & r) const4493 void RenderBlock::adjustRectForColumns(IntRect& r) const
4494 {
4495     // Just bail if we have no columns.
4496     if (!hasColumns())
4497         return;
4498 
4499     ColumnInfo* colInfo = columnInfo();
4500 
4501     // Begin with a result rect that is empty.
4502     IntRect result;
4503 
4504     // Determine which columns we intersect.
4505     unsigned colCount = columnCount(colInfo);
4506     if (!colCount)
4507         return;
4508 
4509     int logicalLeft = logicalLeftOffsetForContent();
4510     int currLogicalOffset = 0;
4511 
4512     for (unsigned i = 0; i < colCount; i++) {
4513         IntRect colRect = columnRectAt(colInfo, i);
4514         IntRect repaintRect = r;
4515         if (isHorizontalWritingMode()) {
4516             int currXOffset = colRect.x() - logicalLeft;
4517             repaintRect.move(currXOffset, currLogicalOffset);
4518             currLogicalOffset -= colRect.height();
4519         } else {
4520             int currYOffset = colRect.y() - logicalLeft;
4521             repaintRect.move(currLogicalOffset, currYOffset);
4522             currLogicalOffset -= colRect.width();
4523         }
4524         repaintRect.intersect(colRect);
4525         result.unite(repaintRect);
4526     }
4527 
4528     r = result;
4529 }
4530 
flipForWritingModeIncludingColumns(const IntPoint & point) const4531 IntPoint RenderBlock::flipForWritingModeIncludingColumns(const IntPoint& point) const
4532 {
4533     ASSERT(hasColumns());
4534     if (!hasColumns() || !style()->isFlippedBlocksWritingMode())
4535         return point;
4536     ColumnInfo* colInfo = columnInfo();
4537     int columnLogicalHeight = colInfo->columnHeight();
4538     int expandedLogicalHeight = borderBefore() + paddingBefore() + columnCount(colInfo) * columnLogicalHeight + borderAfter() + paddingAfter() + scrollbarLogicalHeight();
4539     if (isHorizontalWritingMode())
4540         return IntPoint(point.x(), expandedLogicalHeight - point.y());
4541     return IntPoint(expandedLogicalHeight - point.x(), point.y());
4542 }
4543 
flipForWritingModeIncludingColumns(IntRect & rect) const4544 void RenderBlock::flipForWritingModeIncludingColumns(IntRect& rect) const
4545 {
4546     ASSERT(hasColumns());
4547     if (!hasColumns() || !style()->isFlippedBlocksWritingMode())
4548         return;
4549 
4550     ColumnInfo* colInfo = columnInfo();
4551     int columnLogicalHeight = colInfo->columnHeight();
4552     int expandedLogicalHeight = borderBefore() + paddingBefore() + columnCount(colInfo) * columnLogicalHeight + borderAfter() + paddingAfter() + scrollbarLogicalHeight();
4553     if (isHorizontalWritingMode())
4554         rect.setY(expandedLogicalHeight - rect.maxY());
4555     else
4556         rect.setX(expandedLogicalHeight - rect.maxX());
4557 }
4558 
adjustForColumns(IntSize & offset,const IntPoint & point) const4559 void RenderBlock::adjustForColumns(IntSize& offset, const IntPoint& point) const
4560 {
4561     if (!hasColumns())
4562         return;
4563 
4564     ColumnInfo* colInfo = columnInfo();
4565 
4566     int logicalLeft = logicalLeftOffsetForContent();
4567     size_t colCount = columnCount(colInfo);
4568     int colLogicalWidth = colInfo->desiredColumnWidth();
4569     int colLogicalHeight = colInfo->columnHeight();
4570 
4571     for (size_t i = 0; i < colCount; ++i) {
4572         // Compute the edges for a given column in the block progression direction.
4573         IntRect sliceRect = IntRect(logicalLeft, borderBefore() + paddingBefore() + i * colLogicalHeight, colLogicalWidth, colLogicalHeight);
4574         if (!isHorizontalWritingMode())
4575             sliceRect = sliceRect.transposedRect();
4576 
4577         // If we have a flipped blocks writing mode, then convert the column so that it's coming from the after edge (either top or left edge).
4578         flipForWritingModeIncludingColumns(sliceRect);
4579 
4580         int logicalOffset = style()->isFlippedBlocksWritingMode() ? (colCount - 1 - i) * colLogicalHeight : i * colLogicalHeight;
4581 
4582         // Now we're in the same coordinate space as the point.  See if it is inside the rectangle.
4583         if (isHorizontalWritingMode()) {
4584             if (point.y() >= sliceRect.y() && point.y() < sliceRect.maxY()) {
4585                 offset.expand(columnRectAt(colInfo, i).x() - logicalLeft, -logicalOffset);
4586                 return;
4587             }
4588         } else {
4589             if (point.x() >= sliceRect.x() && point.x() < sliceRect.maxX()) {
4590                 offset.expand(-logicalOffset, columnRectAt(colInfo, i).y() - logicalLeft);
4591                 return;
4592             }
4593         }
4594     }
4595 }
4596 
computePreferredLogicalWidths()4597 void RenderBlock::computePreferredLogicalWidths()
4598 {
4599     ASSERT(preferredLogicalWidthsDirty());
4600 
4601     updateFirstLetter();
4602 
4603     if (!isTableCell() && style()->logicalWidth().isFixed() && style()->logicalWidth().value() > 0)
4604         m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = computeContentBoxLogicalWidth(style()->logicalWidth().value());
4605     else {
4606         m_minPreferredLogicalWidth = 0;
4607         m_maxPreferredLogicalWidth = 0;
4608 
4609         if (childrenInline())
4610             computeInlinePreferredLogicalWidths();
4611         else
4612             computeBlockPreferredLogicalWidths();
4613 
4614         m_maxPreferredLogicalWidth = max(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
4615 
4616         if (!style()->autoWrap() && childrenInline()) {
4617             m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth;
4618 
4619             // A horizontal marquee with inline children has no minimum width.
4620             if (layer() && layer()->marquee() && layer()->marquee()->isHorizontal())
4621                 m_minPreferredLogicalWidth = 0;
4622         }
4623 
4624         int scrollbarWidth = 0;
4625         if (hasOverflowClip() && style()->overflowY() == OSCROLL) {
4626             layer()->setHasVerticalScrollbar(true);
4627             scrollbarWidth = verticalScrollbarWidth();
4628             m_maxPreferredLogicalWidth += scrollbarWidth;
4629         }
4630 
4631         if (isTableCell()) {
4632             Length w = toRenderTableCell(this)->styleOrColLogicalWidth();
4633             if (w.isFixed() && w.value() > 0) {
4634                 m_maxPreferredLogicalWidth = max(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(w.value()));
4635                 scrollbarWidth = 0;
4636             }
4637         }
4638 
4639         m_minPreferredLogicalWidth += scrollbarWidth;
4640     }
4641 
4642     if (style()->logicalMinWidth().isFixed() && style()->logicalMinWidth().value() > 0) {
4643         m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->logicalMinWidth().value()));
4644         m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->logicalMinWidth().value()));
4645     }
4646 
4647     if (style()->logicalMaxWidth().isFixed() && style()->logicalMaxWidth().value() != undefinedLength) {
4648         m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->logicalMaxWidth().value()));
4649         m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->logicalMaxWidth().value()));
4650     }
4651 
4652     int borderAndPadding = borderAndPaddingLogicalWidth();
4653     m_minPreferredLogicalWidth += borderAndPadding;
4654     m_maxPreferredLogicalWidth += borderAndPadding;
4655 
4656     setPreferredLogicalWidthsDirty(false);
4657 }
4658 
4659 struct InlineMinMaxIterator {
4660 /* InlineMinMaxIterator is a class that will iterate over all render objects that contribute to
4661    inline min/max width calculations.  Note the following about the way it walks:
4662    (1) Positioned content is skipped (since it does not contribute to min/max width of a block)
4663    (2) We do not drill into the children of floats or replaced elements, since you can't break
4664        in the middle of such an element.
4665    (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side can have
4666        distinct borders/margin/padding that contribute to the min/max width.
4667 */
4668     RenderObject* parent;
4669     RenderObject* current;
4670     bool endOfInline;
4671 
InlineMinMaxIteratorWebCore::InlineMinMaxIterator4672     InlineMinMaxIterator(RenderObject* p, bool end = false)
4673         :parent(p), current(p), endOfInline(end) {}
4674 
4675     RenderObject* next();
4676 };
4677 
next()4678 RenderObject* InlineMinMaxIterator::next()
4679 {
4680     RenderObject* result = 0;
4681     bool oldEndOfInline = endOfInline;
4682     endOfInline = false;
4683     while (current || current == parent) {
4684         if (!oldEndOfInline &&
4685             (current == parent ||
4686              (!current->isFloating() && !current->isReplaced() && !current->isPositioned())))
4687             result = current->firstChild();
4688         if (!result) {
4689             // We hit the end of our inline. (It was empty, e.g., <span></span>.)
4690             if (!oldEndOfInline && current->isRenderInline()) {
4691                 result = current;
4692                 endOfInline = true;
4693                 break;
4694             }
4695 
4696             while (current && current != parent) {
4697                 result = current->nextSibling();
4698                 if (result) break;
4699                 current = current->parent();
4700                 if (current && current != parent && current->isRenderInline()) {
4701                     result = current;
4702                     endOfInline = true;
4703                     break;
4704                 }
4705             }
4706         }
4707 
4708         if (!result)
4709             break;
4710 
4711         if (!result->isPositioned() && (result->isText() || result->isFloating() || result->isReplaced() || result->isRenderInline()))
4712              break;
4713 
4714         current = result;
4715         result = 0;
4716     }
4717 
4718     // Update our position.
4719     current = result;
4720     return current;
4721 }
4722 
getBPMWidth(int childValue,Length cssUnit)4723 static int getBPMWidth(int childValue, Length cssUnit)
4724 {
4725     if (cssUnit.type() != Auto)
4726         return (cssUnit.isFixed() ? cssUnit.value() : childValue);
4727     return 0;
4728 }
4729 
getBorderPaddingMargin(const RenderBoxModelObject * child,bool endOfInline)4730 static int getBorderPaddingMargin(const RenderBoxModelObject* child, bool endOfInline)
4731 {
4732     RenderStyle* cstyle = child->style();
4733     if (endOfInline)
4734         return getBPMWidth(child->marginEnd(), cstyle->marginEnd()) +
4735                getBPMWidth(child->paddingEnd(), cstyle->paddingEnd()) +
4736                child->borderEnd();
4737     return getBPMWidth(child->marginStart(), cstyle->marginStart()) +
4738                getBPMWidth(child->paddingStart(), cstyle->paddingStart()) +
4739                child->borderStart();
4740 }
4741 
stripTrailingSpace(float & inlineMax,float & inlineMin,RenderObject * trailingSpaceChild)4742 static inline void stripTrailingSpace(float& inlineMax, float& inlineMin,
4743                                       RenderObject* trailingSpaceChild)
4744 {
4745     if (trailingSpaceChild && trailingSpaceChild->isText()) {
4746         // Collapse away the trailing space at the end of a block.
4747         RenderText* t = toRenderText(trailingSpaceChild);
4748         const UChar space = ' ';
4749         const Font& font = t->style()->font(); // FIXME: This ignores first-line.
4750         float spaceWidth = font.width(TextRun(&space, 1));
4751         inlineMax -= spaceWidth + font.wordSpacing();
4752         if (inlineMin > inlineMax)
4753             inlineMin = inlineMax;
4754     }
4755 }
4756 
updatePreferredWidth(int & preferredWidth,float & result)4757 static inline void updatePreferredWidth(int& preferredWidth, float& result)
4758 {
4759     int snappedResult = ceilf(result);
4760     preferredWidth = max(snappedResult, preferredWidth);
4761 }
4762 
computeInlinePreferredLogicalWidths()4763 void RenderBlock::computeInlinePreferredLogicalWidths()
4764 {
4765     float inlineMax = 0;
4766     float inlineMin = 0;
4767 
4768     int cw = containingBlock()->contentLogicalWidth();
4769 
4770     // If we are at the start of a line, we want to ignore all white-space.
4771     // Also strip spaces if we previously had text that ended in a trailing space.
4772     bool stripFrontSpaces = true;
4773     RenderObject* trailingSpaceChild = 0;
4774 
4775     // Firefox and Opera will allow a table cell to grow to fit an image inside it under
4776     // very specific cirucumstances (in order to match common WinIE renderings).
4777     // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.)
4778     bool allowImagesToBreak = !document()->inQuirksMode() || !isTableCell() || !style()->logicalWidth().isIntrinsicOrAuto();
4779 
4780     bool autoWrap, oldAutoWrap;
4781     autoWrap = oldAutoWrap = style()->autoWrap();
4782 
4783     InlineMinMaxIterator childIterator(this);
4784     bool addedTextIndent = false; // Only gets added in once.
4785     RenderObject* prevFloat = 0;
4786     while (RenderObject* child = childIterator.next()) {
4787         autoWrap = child->isReplaced() ? child->parent()->style()->autoWrap() :
4788             child->style()->autoWrap();
4789 
4790         if (!child->isBR()) {
4791             // Step One: determine whether or not we need to go ahead and
4792             // terminate our current line.  Each discrete chunk can become
4793             // the new min-width, if it is the widest chunk seen so far, and
4794             // it can also become the max-width.
4795 
4796             // Children fall into three categories:
4797             // (1) An inline flow object.  These objects always have a min/max of 0,
4798             // and are included in the iteration solely so that their margins can
4799             // be added in.
4800             //
4801             // (2) An inline non-text non-flow object, e.g., an inline replaced element.
4802             // These objects can always be on a line by themselves, so in this situation
4803             // we need to go ahead and break the current line, and then add in our own
4804             // margins and min/max width on its own line, and then terminate the line.
4805             //
4806             // (3) A text object.  Text runs can have breakable characters at the start,
4807             // the middle or the end.  They may also lose whitespace off the front if
4808             // we're already ignoring whitespace.  In order to compute accurate min-width
4809             // information, we need three pieces of information.
4810             // (a) the min-width of the first non-breakable run.  Should be 0 if the text string
4811             // starts with whitespace.
4812             // (b) the min-width of the last non-breakable run. Should be 0 if the text string
4813             // ends with whitespace.
4814             // (c) the min/max width of the string (trimmed for whitespace).
4815             //
4816             // If the text string starts with whitespace, then we need to go ahead and
4817             // terminate our current line (unless we're already in a whitespace stripping
4818             // mode.
4819             //
4820             // If the text string has a breakable character in the middle, but didn't start
4821             // with whitespace, then we add the width of the first non-breakable run and
4822             // then end the current line.  We then need to use the intermediate min/max width
4823             // values (if any of them are larger than our current min/max).  We then look at
4824             // the width of the last non-breakable run and use that to start a new line
4825             // (unless we end in whitespace).
4826             RenderStyle* cstyle = child->style();
4827             float childMin = 0;
4828             float childMax = 0;
4829 
4830             if (!child->isText()) {
4831                 // Case (1) and (2).  Inline replaced and inline flow elements.
4832                 if (child->isRenderInline()) {
4833                     // Add in padding/border/margin from the appropriate side of
4834                     // the element.
4835                     float bpm = getBorderPaddingMargin(toRenderInline(child), childIterator.endOfInline);
4836                     childMin += bpm;
4837                     childMax += bpm;
4838 
4839                     inlineMin += childMin;
4840                     inlineMax += childMax;
4841 
4842                     child->setPreferredLogicalWidthsDirty(false);
4843                 } else {
4844                     // Inline replaced elts add in their margins to their min/max values.
4845                     float margins = 0;
4846                     Length startMargin = cstyle->marginStart();
4847                     Length endMargin = cstyle->marginEnd();
4848                     if (startMargin.isFixed())
4849                         margins += startMargin.value();
4850                     if (endMargin.isFixed())
4851                         margins += endMargin.value();
4852                     childMin += margins;
4853                     childMax += margins;
4854                 }
4855             }
4856 
4857             if (!child->isRenderInline() && !child->isText()) {
4858                 // Case (2). Inline replaced elements and floats.
4859                 // Go ahead and terminate the current line as far as
4860                 // minwidth is concerned.
4861                 childMin += child->minPreferredLogicalWidth();
4862                 childMax += child->maxPreferredLogicalWidth();
4863 
4864                 bool clearPreviousFloat;
4865                 if (child->isFloating()) {
4866                     clearPreviousFloat = (prevFloat
4867                         && ((prevFloat->style()->floating() == FLEFT && (child->style()->clear() & CLEFT))
4868                             || (prevFloat->style()->floating() == FRIGHT && (child->style()->clear() & CRIGHT))));
4869                     prevFloat = child;
4870                 } else
4871                     clearPreviousFloat = false;
4872 
4873                 bool canBreakReplacedElement = !child->isImage() || allowImagesToBreak;
4874                 if ((canBreakReplacedElement && (autoWrap || oldAutoWrap)) || clearPreviousFloat) {
4875                     updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
4876                     inlineMin = 0;
4877                 }
4878 
4879                 // If we're supposed to clear the previous float, then terminate maxwidth as well.
4880                 if (clearPreviousFloat) {
4881                     updatePreferredWidth(m_maxPreferredLogicalWidth, inlineMax);
4882                     inlineMax = 0;
4883                 }
4884 
4885                 // Add in text-indent.  This is added in only once.
4886                 int ti = 0;
4887                 if (!addedTextIndent) {
4888                     addedTextIndent = true;
4889                     ti = style()->textIndent().calcMinValue(cw);
4890                     childMin += ti;
4891                     childMax += ti;
4892                 }
4893 
4894                 // Add our width to the max.
4895                 inlineMax += childMax;
4896 
4897                 if (!autoWrap || !canBreakReplacedElement) {
4898                     if (child->isFloating())
4899                         updatePreferredWidth(m_minPreferredLogicalWidth, childMin);
4900                     else
4901                         inlineMin += childMin;
4902                 } else {
4903                     // Now check our line.
4904                     updatePreferredWidth(m_minPreferredLogicalWidth, childMin);
4905 
4906                     // Now start a new line.
4907                     inlineMin = 0;
4908                 }
4909 
4910                 // We are no longer stripping whitespace at the start of
4911                 // a line.
4912                 if (!child->isFloating()) {
4913                     stripFrontSpaces = false;
4914                     trailingSpaceChild = 0;
4915                 }
4916             } else if (child->isText()) {
4917                 // Case (3). Text.
4918                 RenderText* t = toRenderText(child);
4919 
4920                 if (t->isWordBreak()) {
4921                     updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
4922                     inlineMin = 0;
4923                     continue;
4924                 }
4925 
4926                 if (t->style()->hasTextCombine() && t->isCombineText())
4927                     toRenderCombineText(t)->combineText();
4928 
4929                 // Determine if we have a breakable character.  Pass in
4930                 // whether or not we should ignore any spaces at the front
4931                 // of the string.  If those are going to be stripped out,
4932                 // then they shouldn't be considered in the breakable char
4933                 // check.
4934                 bool hasBreakableChar, hasBreak;
4935                 float beginMin, endMin;
4936                 bool beginWS, endWS;
4937                 float beginMax, endMax;
4938                 t->trimmedPrefWidths(inlineMax, beginMin, beginWS, endMin, endWS,
4939                                      hasBreakableChar, hasBreak, beginMax, endMax,
4940                                      childMin, childMax, stripFrontSpaces);
4941 
4942                 // This text object will not be rendered, but it may still provide a breaking opportunity.
4943                 if (!hasBreak && childMax == 0) {
4944                     if (autoWrap && (beginWS || endWS)) {
4945                         updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
4946                         inlineMin = 0;
4947                     }
4948                     continue;
4949                 }
4950 
4951                 if (stripFrontSpaces)
4952                     trailingSpaceChild = child;
4953                 else
4954                     trailingSpaceChild = 0;
4955 
4956                 // Add in text-indent.  This is added in only once.
4957                 int ti = 0;
4958                 if (!addedTextIndent) {
4959                     addedTextIndent = true;
4960                     ti = style()->textIndent().calcMinValue(cw);
4961                     childMin+=ti; beginMin += ti;
4962                     childMax+=ti; beginMax += ti;
4963                 }
4964 
4965                 // If we have no breakable characters at all,
4966                 // then this is the easy case. We add ourselves to the current
4967                 // min and max and continue.
4968                 if (!hasBreakableChar) {
4969                     inlineMin += childMin;
4970                 } else {
4971                     // We have a breakable character.  Now we need to know if
4972                     // we start and end with whitespace.
4973                     if (beginWS)
4974                         // Go ahead and end the current line.
4975                         updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
4976                     else {
4977                         inlineMin += beginMin;
4978                         updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
4979                         childMin -= ti;
4980                     }
4981 
4982                     inlineMin = childMin;
4983 
4984                     if (endWS) {
4985                         // We end in whitespace, which means we can go ahead
4986                         // and end our current line.
4987                         updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
4988                         inlineMin = 0;
4989                     } else {
4990                         updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
4991                         inlineMin = endMin;
4992                     }
4993                 }
4994 
4995                 if (hasBreak) {
4996                     inlineMax += beginMax;
4997                     updatePreferredWidth(m_maxPreferredLogicalWidth, inlineMax);
4998                     updatePreferredWidth(m_maxPreferredLogicalWidth, childMax);
4999                     inlineMax = endMax;
5000                 } else
5001                     inlineMax += childMax;
5002             }
5003 
5004             // Ignore spaces after a list marker.
5005             if (child->isListMarker())
5006                 stripFrontSpaces = true;
5007         } else {
5008             updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
5009             updatePreferredWidth(m_maxPreferredLogicalWidth, inlineMax);
5010             inlineMin = inlineMax = 0;
5011             stripFrontSpaces = true;
5012             trailingSpaceChild = 0;
5013         }
5014 
5015         oldAutoWrap = autoWrap;
5016     }
5017 
5018     if (style()->collapseWhiteSpace())
5019         stripTrailingSpace(inlineMax, inlineMin, trailingSpaceChild);
5020 
5021     updatePreferredWidth(m_minPreferredLogicalWidth, inlineMin);
5022     updatePreferredWidth(m_maxPreferredLogicalWidth, inlineMax);
5023 }
5024 
5025 // Use a very large value (in effect infinite).
5026 #define BLOCK_MAX_WIDTH 15000
5027 
computeBlockPreferredLogicalWidths()5028 void RenderBlock::computeBlockPreferredLogicalWidths()
5029 {
5030     bool nowrap = style()->whiteSpace() == NOWRAP;
5031 
5032     RenderObject *child = firstChild();
5033     int floatLeftWidth = 0, floatRightWidth = 0;
5034     while (child) {
5035         // Positioned children don't affect the min/max width
5036         if (child->isPositioned()) {
5037             child = child->nextSibling();
5038             continue;
5039         }
5040 
5041         if (child->isFloating() || (child->isBox() && toRenderBox(child)->avoidsFloats())) {
5042             int floatTotalWidth = floatLeftWidth + floatRightWidth;
5043             if (child->style()->clear() & CLEFT) {
5044                 m_maxPreferredLogicalWidth = max(floatTotalWidth, m_maxPreferredLogicalWidth);
5045                 floatLeftWidth = 0;
5046             }
5047             if (child->style()->clear() & CRIGHT) {
5048                 m_maxPreferredLogicalWidth = max(floatTotalWidth, m_maxPreferredLogicalWidth);
5049                 floatRightWidth = 0;
5050             }
5051         }
5052 
5053         // A margin basically has three types: fixed, percentage, and auto (variable).
5054         // Auto and percentage margins simply become 0 when computing min/max width.
5055         // Fixed margins can be added in as is.
5056         Length startMarginLength = child->style()->marginStart();
5057         Length endMarginLength = child->style()->marginEnd();
5058         int margin = 0;
5059         int marginStart = 0;
5060         int marginEnd = 0;
5061         if (startMarginLength.isFixed())
5062             marginStart += startMarginLength.value();
5063         if (endMarginLength.isFixed())
5064             marginEnd += endMarginLength.value();
5065         margin = marginStart + marginEnd;
5066 
5067         int w = child->minPreferredLogicalWidth() + margin;
5068         m_minPreferredLogicalWidth = max(w, m_minPreferredLogicalWidth);
5069 
5070         // IE ignores tables for calculation of nowrap. Makes some sense.
5071         if (nowrap && !child->isTable())
5072             m_maxPreferredLogicalWidth = max(w, m_maxPreferredLogicalWidth);
5073 
5074         w = child->maxPreferredLogicalWidth() + margin;
5075 
5076         if (!child->isFloating()) {
5077             if (child->isBox() && toRenderBox(child)->avoidsFloats()) {
5078                 // Determine a left and right max value based off whether or not the floats can fit in the
5079                 // margins of the object.  For negative margins, we will attempt to overlap the float if the negative margin
5080                 // is smaller than the float width.
5081                 bool ltr = containingBlock()->style()->isLeftToRightDirection();
5082                 int marginLogicalLeft = ltr ? marginStart : marginEnd;
5083                 int marginLogicalRight = ltr ? marginEnd : marginStart;
5084                 int maxLeft = marginLogicalLeft > 0 ? max(floatLeftWidth, marginLogicalLeft) : floatLeftWidth + marginLogicalLeft;
5085                 int maxRight = marginLogicalRight > 0 ? max(floatRightWidth, marginLogicalRight) : floatRightWidth + marginLogicalRight;
5086                 w = child->maxPreferredLogicalWidth() + maxLeft + maxRight;
5087                 w = max(w, floatLeftWidth + floatRightWidth);
5088             }
5089             else
5090                 m_maxPreferredLogicalWidth = max(floatLeftWidth + floatRightWidth, m_maxPreferredLogicalWidth);
5091             floatLeftWidth = floatRightWidth = 0;
5092         }
5093 
5094         if (child->isFloating()) {
5095             if (style()->floating() == FLEFT)
5096                 floatLeftWidth += w;
5097             else
5098                 floatRightWidth += w;
5099         } else
5100             m_maxPreferredLogicalWidth = max(w, m_maxPreferredLogicalWidth);
5101 
5102         // A very specific WinIE quirk.
5103         // Example:
5104         /*
5105            <div style="position:absolute; width:100px; top:50px;">
5106               <div style="position:absolute;left:0px;top:50px;height:50px;background-color:green">
5107                 <table style="width:100%"><tr><td></table>
5108               </div>
5109            </div>
5110         */
5111         // In the above example, the inner absolute positioned block should have a computed width
5112         // of 100px because of the table.
5113         // We can achieve this effect by making the maxwidth of blocks that contain tables
5114         // with percentage widths be infinite (as long as they are not inside a table cell).
5115         if (document()->inQuirksMode() && child->style()->logicalWidth().isPercent() &&
5116             !isTableCell() && child->isTable() && m_maxPreferredLogicalWidth < BLOCK_MAX_WIDTH) {
5117             RenderBlock* cb = containingBlock();
5118             while (!cb->isRenderView() && !cb->isTableCell())
5119                 cb = cb->containingBlock();
5120             if (!cb->isTableCell())
5121                 m_maxPreferredLogicalWidth = BLOCK_MAX_WIDTH;
5122         }
5123 
5124         child = child->nextSibling();
5125     }
5126 
5127     // Always make sure these values are non-negative.
5128     m_minPreferredLogicalWidth = max(0, m_minPreferredLogicalWidth);
5129     m_maxPreferredLogicalWidth = max(0, m_maxPreferredLogicalWidth);
5130 
5131     m_maxPreferredLogicalWidth = max(floatLeftWidth + floatRightWidth, m_maxPreferredLogicalWidth);
5132 }
5133 
hasLineIfEmpty() const5134 bool RenderBlock::hasLineIfEmpty() const
5135 {
5136     if (!node())
5137         return false;
5138 
5139     if (node()->rendererIsEditable() && node()->rootEditableElement() == node())
5140         return true;
5141 
5142     if (node()->isShadowRoot() && (node()->shadowHost()->hasTagName(inputTag)))
5143         return true;
5144 
5145     return false;
5146 }
5147 
lineHeight(bool firstLine,LineDirectionMode direction,LinePositionMode linePositionMode) const5148 int RenderBlock::lineHeight(bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
5149 {
5150     // Inline blocks are replaced elements. Otherwise, just pass off to
5151     // the base class.  If we're being queried as though we're the root line
5152     // box, then the fact that we're an inline-block is irrelevant, and we behave
5153     // just like a block.
5154     if (isReplaced() && linePositionMode == PositionOnContainingLine)
5155         return RenderBox::lineHeight(firstLine, direction, linePositionMode);
5156 
5157     if (firstLine && document()->usesFirstLineRules()) {
5158         RenderStyle* s = style(firstLine);
5159         if (s != style())
5160             return s->computedLineHeight();
5161     }
5162 
5163     if (m_lineHeight == -1)
5164         m_lineHeight = style()->computedLineHeight();
5165 
5166     return m_lineHeight;
5167 }
5168 
baselinePosition(FontBaseline baselineType,bool firstLine,LineDirectionMode direction,LinePositionMode linePositionMode) const5169 int RenderBlock::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
5170 {
5171     // Inline blocks are replaced elements. Otherwise, just pass off to
5172     // the base class.  If we're being queried as though we're the root line
5173     // box, then the fact that we're an inline-block is irrelevant, and we behave
5174     // just like a block.
5175     if (isReplaced() && linePositionMode == PositionOnContainingLine) {
5176         // For "leaf" theme objects, let the theme decide what the baseline position is.
5177         // FIXME: Might be better to have a custom CSS property instead, so that if the theme
5178         // is turned off, checkboxes/radios will still have decent baselines.
5179         // FIXME: Need to patch form controls to deal with vertical lines.
5180         if (style()->hasAppearance() && !theme()->isControlContainer(style()->appearance()))
5181             return theme()->baselinePosition(this);
5182 
5183         // CSS2.1 states that the baseline of an inline block is the baseline of the last line box in
5184         // the normal flow.  We make an exception for marquees, since their baselines are meaningless
5185         // (the content inside them moves).  This matches WinIE as well, which just bottom-aligns them.
5186         // We also give up on finding a baseline if we have a vertical scrollbar, or if we are scrolled
5187         // vertically (e.g., an overflow:hidden block that has had scrollTop moved) or if the baseline is outside
5188         // of our content box.
5189         bool ignoreBaseline = (layer() && (layer()->marquee() || (direction == HorizontalLine ? (layer()->verticalScrollbar() || layer()->scrollYOffset() != 0)
5190             : (layer()->horizontalScrollbar() || layer()->scrollXOffset() != 0)))) || (isWritingModeRoot() && !isRubyRun());
5191 
5192         int baselinePos = ignoreBaseline ? -1 : lastLineBoxBaseline();
5193 
5194         int bottomOfContent = direction == HorizontalLine ? borderTop() + paddingTop() + contentHeight() : borderRight() + paddingRight() + contentWidth();
5195         if (baselinePos != -1 && baselinePos <= bottomOfContent)
5196             return direction == HorizontalLine ? marginTop() + baselinePos : marginRight() + baselinePos;
5197 
5198         return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
5199     }
5200 
5201     const FontMetrics& fontMetrics = style(firstLine)->fontMetrics();
5202     return fontMetrics.ascent(baselineType) + (lineHeight(firstLine, direction, linePositionMode) - fontMetrics.height()) / 2;
5203 }
5204 
firstLineBoxBaseline() const5205 int RenderBlock::firstLineBoxBaseline() const
5206 {
5207     if (!isBlockFlow() || (isWritingModeRoot() && !isRubyRun()))
5208         return -1;
5209 
5210     if (childrenInline()) {
5211         if (firstLineBox())
5212             return firstLineBox()->logicalTop() + style(true)->fontMetrics().ascent(firstRootBox()->baselineType());
5213         else
5214             return -1;
5215     }
5216     else {
5217         for (RenderBox* curr = firstChildBox(); curr; curr = curr->nextSiblingBox()) {
5218             if (!curr->isFloatingOrPositioned()) {
5219                 int result = curr->firstLineBoxBaseline();
5220                 if (result != -1)
5221                     return curr->logicalTop() + result; // Translate to our coordinate space.
5222             }
5223         }
5224     }
5225 
5226     return -1;
5227 }
5228 
lastLineBoxBaseline() const5229 int RenderBlock::lastLineBoxBaseline() const
5230 {
5231     if (!isBlockFlow() || (isWritingModeRoot() && !isRubyRun()))
5232         return -1;
5233 
5234     LineDirectionMode lineDirection = isHorizontalWritingMode() ? HorizontalLine : VerticalLine;
5235 
5236     if (childrenInline()) {
5237         if (!firstLineBox() && hasLineIfEmpty()) {
5238             const FontMetrics& fontMetrics = firstLineStyle()->fontMetrics();
5239             return fontMetrics.ascent()
5240                  + (lineHeight(true, lineDirection, PositionOfInteriorLineBoxes) - fontMetrics.height()) / 2
5241                  + (lineDirection == HorizontalLine ? borderTop() + paddingTop() : borderRight() + paddingRight());
5242         }
5243         if (lastLineBox())
5244             return lastLineBox()->logicalTop() + style(lastLineBox() == firstLineBox())->fontMetrics().ascent(lastRootBox()->baselineType());
5245         return -1;
5246     } else {
5247         bool haveNormalFlowChild = false;
5248         for (RenderBox* curr = lastChildBox(); curr; curr = curr->previousSiblingBox()) {
5249             if (!curr->isFloatingOrPositioned()) {
5250                 haveNormalFlowChild = true;
5251                 int result = curr->lastLineBoxBaseline();
5252                 if (result != -1)
5253                     return curr->logicalTop() + result; // Translate to our coordinate space.
5254             }
5255         }
5256         if (!haveNormalFlowChild && hasLineIfEmpty()) {
5257             const FontMetrics& fontMetrics = firstLineStyle()->fontMetrics();
5258             return fontMetrics.ascent()
5259                  + (lineHeight(true, lineDirection, PositionOfInteriorLineBoxes) - fontMetrics.height()) / 2
5260                  + (lineDirection == HorizontalLine ? borderTop() + paddingTop() : borderRight() + paddingRight());
5261         }
5262     }
5263 
5264     return -1;
5265 }
5266 
containsNonZeroBidiLevel() const5267 bool RenderBlock::containsNonZeroBidiLevel() const
5268 {
5269     for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) {
5270         for (InlineBox* box = root->firstLeafChild(); box; box = box->nextLeafChild()) {
5271             if (box->bidiLevel())
5272                 return true;
5273         }
5274     }
5275     return false;
5276 }
5277 
firstLineBlock() const5278 RenderBlock* RenderBlock::firstLineBlock() const
5279 {
5280     RenderBlock* firstLineBlock = const_cast<RenderBlock*>(this);
5281     bool hasPseudo = false;
5282     while (true) {
5283         hasPseudo = firstLineBlock->style()->hasPseudoStyle(FIRST_LINE);
5284         if (hasPseudo)
5285             break;
5286         RenderObject* parentBlock = firstLineBlock->parent();
5287         if (firstLineBlock->isReplaced() || firstLineBlock->isFloating() ||
5288             !parentBlock || parentBlock->firstChild() != firstLineBlock || !parentBlock->isBlockFlow())
5289             break;
5290         ASSERT(parentBlock->isRenderBlock());
5291         firstLineBlock = toRenderBlock(parentBlock);
5292     }
5293 
5294     if (!hasPseudo)
5295         return 0;
5296 
5297     return firstLineBlock;
5298 }
5299 
styleForFirstLetter(RenderObject * firstLetterBlock,RenderObject * firstLetterContainer)5300 static RenderStyle* styleForFirstLetter(RenderObject* firstLetterBlock, RenderObject* firstLetterContainer)
5301 {
5302     RenderStyle* pseudoStyle = firstLetterBlock->getCachedPseudoStyle(FIRST_LETTER, firstLetterContainer->firstLineStyle());
5303     // Force inline display (except for floating first-letters).
5304     pseudoStyle->setDisplay(pseudoStyle->isFloating() ? BLOCK : INLINE);
5305     // CSS2 says first-letter can't be positioned.
5306     pseudoStyle->setPosition(StaticPosition);
5307     return pseudoStyle;
5308 }
5309 
5310 // CSS 2.1 http://www.w3.org/TR/CSS21/selector.html#first-letter
5311 // "Punctuation (i.e, characters defined in Unicode [UNICODE] in the "open" (Ps), "close" (Pe),
5312 // "initial" (Pi). "final" (Pf) and "other" (Po) punctuation classes), that precedes or follows the first letter should be included"
isPunctuationForFirstLetter(UChar c)5313 static inline bool isPunctuationForFirstLetter(UChar c)
5314 {
5315     CharCategory charCategory = category(c);
5316     return charCategory == Punctuation_Open
5317         || charCategory == Punctuation_Close
5318         || charCategory == Punctuation_InitialQuote
5319         || charCategory == Punctuation_FinalQuote
5320         || charCategory == Punctuation_Other;
5321 }
5322 
shouldSkipForFirstLetter(UChar c)5323 static inline bool shouldSkipForFirstLetter(UChar c)
5324 {
5325     return isSpaceOrNewline(c) || c == noBreakSpace || isPunctuationForFirstLetter(c);
5326 }
5327 
updateFirstLetter()5328 void RenderBlock::updateFirstLetter()
5329 {
5330     if (!document()->usesFirstLetterRules())
5331         return;
5332     // Don't recur
5333     if (style()->styleType() == FIRST_LETTER)
5334         return;
5335 
5336     // FIXME: We need to destroy the first-letter object if it is no longer the first child.  Need to find
5337     // an efficient way to check for that situation though before implementing anything.
5338     RenderObject* firstLetterBlock = this;
5339     bool hasPseudoStyle = false;
5340     while (true) {
5341         // We only honor first-letter if the firstLetterBlock can have children in the DOM. This correctly
5342         // prevents form controls from honoring first-letter.
5343         hasPseudoStyle = firstLetterBlock->style()->hasPseudoStyle(FIRST_LETTER)
5344             && firstLetterBlock->canHaveChildren();
5345         if (hasPseudoStyle)
5346             break;
5347         RenderObject* parentBlock = firstLetterBlock->parent();
5348         if (firstLetterBlock->isReplaced() || !parentBlock || parentBlock->firstChild() != firstLetterBlock ||
5349             !parentBlock->isBlockFlow())
5350             break;
5351         firstLetterBlock = parentBlock;
5352     }
5353 
5354     if (!hasPseudoStyle)
5355         return;
5356 
5357     // Drill into inlines looking for our first text child.
5358     RenderObject* currChild = firstLetterBlock->firstChild();
5359     while (currChild && ((!currChild->isReplaced() && !currChild->isRenderButton() && !currChild->isMenuList()) || currChild->isFloatingOrPositioned()) && !currChild->isText()) {
5360         if (currChild->isFloatingOrPositioned()) {
5361             if (currChild->style()->styleType() == FIRST_LETTER) {
5362                 currChild = currChild->firstChild();
5363                 break;
5364             }
5365             currChild = currChild->nextSibling();
5366         } else
5367             currChild = currChild->firstChild();
5368     }
5369 
5370     // Get list markers out of the way.
5371     while (currChild && currChild->isListMarker())
5372         currChild = currChild->nextSibling();
5373 
5374     if (!currChild)
5375         return;
5376 
5377     // If the child already has style, then it has already been created, so we just want
5378     // to update it.
5379     if (currChild->parent()->style()->styleType() == FIRST_LETTER) {
5380         RenderObject* firstLetter = currChild->parent();
5381         RenderObject* firstLetterContainer = firstLetter->parent();
5382         RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer);
5383 
5384         if (Node::diff(firstLetter->style(), pseudoStyle) == Node::Detach) {
5385             // The first-letter renderer needs to be replaced. Create a new renderer of the right type.
5386             RenderObject* newFirstLetter;
5387             if (pseudoStyle->display() == INLINE)
5388                 newFirstLetter = new (renderArena()) RenderInline(document());
5389             else
5390                 newFirstLetter = new (renderArena()) RenderBlock(document());
5391             newFirstLetter->setStyle(pseudoStyle);
5392 
5393             // Move the first letter into the new renderer.
5394             view()->disableLayoutState();
5395             while (RenderObject* child = firstLetter->firstChild()) {
5396                 if (child->isText())
5397                     toRenderText(child)->removeAndDestroyTextBoxes();
5398                 firstLetter->removeChild(child);
5399                 newFirstLetter->addChild(child, 0);
5400             }
5401 
5402             RenderTextFragment* remainingText = 0;
5403             RenderObject* nextSibling = firstLetter->nextSibling();
5404             RenderObject* next = nextSibling;
5405             while (next) {
5406                 if (next->isText() && toRenderText(next)->isTextFragment()) {
5407                     remainingText = toRenderTextFragment(next);
5408                     break;
5409                 }
5410                 next = next->nextSibling();
5411             }
5412             if (remainingText) {
5413                 ASSERT(remainingText->node()->renderer() == remainingText);
5414                 // Replace the old renderer with the new one.
5415                 remainingText->setFirstLetter(newFirstLetter);
5416             }
5417             firstLetter->destroy();
5418             firstLetter = newFirstLetter;
5419             firstLetterContainer->addChild(firstLetter, nextSibling);
5420             view()->enableLayoutState();
5421         } else
5422             firstLetter->setStyle(pseudoStyle);
5423 
5424         for (RenderObject* genChild = firstLetter->firstChild(); genChild; genChild = genChild->nextSibling()) {
5425             if (genChild->isText())
5426                 genChild->setStyle(pseudoStyle);
5427         }
5428 
5429         return;
5430     }
5431 
5432     if (!currChild->isText() || currChild->isBR())
5433         return;
5434 
5435     // If the child does not already have style, we create it here.
5436     RenderObject* firstLetterContainer = currChild->parent();
5437 
5438     // Our layout state is not valid for the repaints we are going to trigger by
5439     // adding and removing children of firstLetterContainer.
5440     view()->disableLayoutState();
5441 
5442     RenderText* textObj = toRenderText(currChild);
5443 
5444     // Create our pseudo style now that we have our firstLetterContainer determined.
5445     RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer);
5446 
5447     RenderObject* firstLetter = 0;
5448     if (pseudoStyle->display() == INLINE)
5449         firstLetter = new (renderArena()) RenderInline(document());
5450     else
5451         firstLetter = new (renderArena()) RenderBlock(document());
5452     firstLetter->setStyle(pseudoStyle);
5453     firstLetterContainer->addChild(firstLetter, currChild);
5454 
5455     // The original string is going to be either a generated content string or a DOM node's
5456     // string.  We want the original string before it got transformed in case first-letter has
5457     // no text-transform or a different text-transform applied to it.
5458     RefPtr<StringImpl> oldText = textObj->originalText();
5459     ASSERT(oldText);
5460 
5461     if (oldText && oldText->length() > 0) {
5462         unsigned length = 0;
5463 
5464         // Account for leading spaces and punctuation.
5465         while (length < oldText->length() && shouldSkipForFirstLetter((*oldText)[length]))
5466             length++;
5467 
5468         // Account for first letter.
5469         length++;
5470 
5471         // Keep looking for whitespace and allowed punctuation, but avoid
5472         // accumulating just whitespace into the :first-letter.
5473         for (unsigned scanLength = length; scanLength < oldText->length(); ++scanLength) {
5474             UChar c = (*oldText)[scanLength];
5475 
5476             if (!shouldSkipForFirstLetter(c))
5477                 break;
5478 
5479             if (isPunctuationForFirstLetter(c))
5480                 length = scanLength + 1;
5481          }
5482 
5483         // Construct a text fragment for the text after the first letter.
5484         // This text fragment might be empty.
5485         RenderTextFragment* remainingText =
5486             new (renderArena()) RenderTextFragment(textObj->node() ? textObj->node() : textObj->document(), oldText.get(), length, oldText->length() - length);
5487         remainingText->setStyle(textObj->style());
5488         if (remainingText->node())
5489             remainingText->node()->setRenderer(remainingText);
5490 
5491         firstLetterContainer->addChild(remainingText, textObj);
5492         firstLetterContainer->removeChild(textObj);
5493         remainingText->setFirstLetter(firstLetter);
5494 
5495         // construct text fragment for the first letter
5496         RenderTextFragment* letter =
5497             new (renderArena()) RenderTextFragment(remainingText->node() ? remainingText->node() : remainingText->document(), oldText.get(), 0, length);
5498         letter->setStyle(pseudoStyle);
5499         firstLetter->addChild(letter);
5500 
5501         textObj->destroy();
5502     }
5503     view()->enableLayoutState();
5504 }
5505 
5506 // Helper methods for obtaining the last line, computing line counts and heights for line counts
5507 // (crawling into blocks).
shouldCheckLines(RenderObject * obj)5508 static bool shouldCheckLines(RenderObject* obj)
5509 {
5510     return !obj->isFloatingOrPositioned() && !obj->isRunIn() &&
5511             obj->isBlockFlow() && obj->style()->height().isAuto() &&
5512             (!obj->isFlexibleBox() || obj->style()->boxOrient() == VERTICAL);
5513 }
5514 
getLineAtIndex(RenderBlock * block,int i,int & count)5515 static RootInlineBox* getLineAtIndex(RenderBlock* block, int i, int& count)
5516 {
5517     if (block->style()->visibility() == VISIBLE) {
5518         if (block->childrenInline()) {
5519             for (RootInlineBox* box = block->firstRootBox(); box; box = box->nextRootBox()) {
5520                 if (count++ == i)
5521                     return box;
5522             }
5523         }
5524         else {
5525             for (RenderObject* obj = block->firstChild(); obj; obj = obj->nextSibling()) {
5526                 if (shouldCheckLines(obj)) {
5527                     RootInlineBox *box = getLineAtIndex(toRenderBlock(obj), i, count);
5528                     if (box)
5529                         return box;
5530                 }
5531             }
5532         }
5533     }
5534     return 0;
5535 }
5536 
getHeightForLineCount(RenderBlock * block,int l,bool includeBottom,int & count)5537 static int getHeightForLineCount(RenderBlock* block, int l, bool includeBottom, int& count)
5538 {
5539     if (block->style()->visibility() == VISIBLE) {
5540         if (block->childrenInline()) {
5541             for (RootInlineBox* box = block->firstRootBox(); box; box = box->nextRootBox()) {
5542                 if (++count == l)
5543                     return box->lineBottom() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0);
5544             }
5545         }
5546         else {
5547             RenderBox* normalFlowChildWithoutLines = 0;
5548             for (RenderBox* obj = block->firstChildBox(); obj; obj = obj->nextSiblingBox()) {
5549                 if (shouldCheckLines(obj)) {
5550                     int result = getHeightForLineCount(toRenderBlock(obj), l, false, count);
5551                     if (result != -1)
5552                         return result + obj->y() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0);
5553                 }
5554                 else if (!obj->isFloatingOrPositioned() && !obj->isRunIn())
5555                     normalFlowChildWithoutLines = obj;
5556             }
5557             if (normalFlowChildWithoutLines && l == 0)
5558                 return normalFlowChildWithoutLines->y() + normalFlowChildWithoutLines->height();
5559         }
5560     }
5561 
5562     return -1;
5563 }
5564 
lineAtIndex(int i)5565 RootInlineBox* RenderBlock::lineAtIndex(int i)
5566 {
5567     int count = 0;
5568     return getLineAtIndex(this, i, count);
5569 }
5570 
lineCount()5571 int RenderBlock::lineCount()
5572 {
5573     int count = 0;
5574     if (style()->visibility() == VISIBLE) {
5575         if (childrenInline())
5576             for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox())
5577                 count++;
5578         else
5579             for (RenderObject* obj = firstChild(); obj; obj = obj->nextSibling())
5580                 if (shouldCheckLines(obj))
5581                     count += toRenderBlock(obj)->lineCount();
5582     }
5583     return count;
5584 }
5585 
heightForLineCount(int l)5586 int RenderBlock::heightForLineCount(int l)
5587 {
5588     int count = 0;
5589     return getHeightForLineCount(this, l, true, count);
5590 }
5591 
adjustForBorderFit(int x,int & left,int & right) const5592 void RenderBlock::adjustForBorderFit(int x, int& left, int& right) const
5593 {
5594     // We don't deal with relative positioning.  Our assumption is that you shrink to fit the lines without accounting
5595     // for either overflow or translations via relative positioning.
5596     if (style()->visibility() == VISIBLE) {
5597         if (childrenInline()) {
5598             for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox()) {
5599                 if (box->firstChild())
5600                     left = min(left, x + static_cast<int>(box->firstChild()->x()));
5601                 if (box->lastChild())
5602                     right = max(right, x + static_cast<int>(ceilf(box->lastChild()->logicalRight())));
5603             }
5604         }
5605         else {
5606             for (RenderBox* obj = firstChildBox(); obj; obj = obj->nextSiblingBox()) {
5607                 if (!obj->isFloatingOrPositioned()) {
5608                     if (obj->isBlockFlow() && !obj->hasOverflowClip())
5609                         toRenderBlock(obj)->adjustForBorderFit(x + obj->x(), left, right);
5610                     else if (obj->style()->visibility() == VISIBLE) {
5611                         // We are a replaced element or some kind of non-block-flow object.
5612                         left = min(left, x + obj->x());
5613                         right = max(right, x + obj->x() + obj->width());
5614                     }
5615                 }
5616             }
5617         }
5618 
5619         if (m_floatingObjects) {
5620             FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
5621             FloatingObjectSetIterator end = floatingObjectSet.end();
5622             for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
5623                 FloatingObject* r = *it;
5624                 // Only examine the object if our m_shouldPaint flag is set.
5625                 if (r->m_shouldPaint) {
5626                     int floatLeft = xPositionForFloatIncludingMargin(r) - r->m_renderer->x();
5627                     int floatRight = floatLeft + r->m_renderer->width();
5628                     left = min(left, floatLeft);
5629                     right = max(right, floatRight);
5630                 }
5631             }
5632         }
5633     }
5634 }
5635 
borderFitAdjust(int & x,int & w) const5636 void RenderBlock::borderFitAdjust(int& x, int& w) const
5637 {
5638     if (style()->borderFit() == BorderFitBorder)
5639         return;
5640 
5641     // Walk any normal flow lines to snugly fit.
5642     int left = INT_MAX;
5643     int right = INT_MIN;
5644     int oldWidth = w;
5645     adjustForBorderFit(0, left, right);
5646     if (left != INT_MAX) {
5647         left -= (borderLeft() + paddingLeft());
5648         if (left > 0) {
5649             x += left;
5650             w -= left;
5651         }
5652     }
5653     if (right != INT_MIN) {
5654         right += (borderRight() + paddingRight());
5655         if (right < oldWidth)
5656             w -= (oldWidth - right);
5657     }
5658 }
5659 
clearTruncation()5660 void RenderBlock::clearTruncation()
5661 {
5662     if (style()->visibility() == VISIBLE) {
5663         if (childrenInline() && hasMarkupTruncation()) {
5664             setHasMarkupTruncation(false);
5665             for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox())
5666                 box->clearTruncation();
5667         }
5668         else
5669             for (RenderObject* obj = firstChild(); obj; obj = obj->nextSibling())
5670                 if (shouldCheckLines(obj))
5671                     toRenderBlock(obj)->clearTruncation();
5672     }
5673 }
5674 
setMaxMarginBeforeValues(int pos,int neg)5675 void RenderBlock::setMaxMarginBeforeValues(int pos, int neg)
5676 {
5677     if (!m_rareData) {
5678         if (pos == RenderBlockRareData::positiveMarginBeforeDefault(this) && neg == RenderBlockRareData::negativeMarginBeforeDefault(this))
5679             return;
5680         m_rareData = new RenderBlockRareData(this);
5681     }
5682     m_rareData->m_margins.setPositiveMarginBefore(pos);
5683     m_rareData->m_margins.setNegativeMarginBefore(neg);
5684 }
5685 
setMaxMarginAfterValues(int pos,int neg)5686 void RenderBlock::setMaxMarginAfterValues(int pos, int neg)
5687 {
5688     if (!m_rareData) {
5689         if (pos == RenderBlockRareData::positiveMarginAfterDefault(this) && neg == RenderBlockRareData::negativeMarginAfterDefault(this))
5690             return;
5691         m_rareData = new RenderBlockRareData(this);
5692     }
5693     m_rareData->m_margins.setPositiveMarginAfter(pos);
5694     m_rareData->m_margins.setNegativeMarginAfter(neg);
5695 }
5696 
setPaginationStrut(int strut)5697 void RenderBlock::setPaginationStrut(int strut)
5698 {
5699     if (!m_rareData) {
5700         if (!strut)
5701             return;
5702         m_rareData = new RenderBlockRareData(this);
5703     }
5704     m_rareData->m_paginationStrut = strut;
5705 }
5706 
setPageLogicalOffset(int logicalOffset)5707 void RenderBlock::setPageLogicalOffset(int logicalOffset)
5708 {
5709     if (!m_rareData) {
5710         if (!logicalOffset)
5711             return;
5712         m_rareData = new RenderBlockRareData(this);
5713     }
5714     m_rareData->m_pageLogicalOffset = logicalOffset;
5715 }
5716 
absoluteRects(Vector<IntRect> & rects,int tx,int ty)5717 void RenderBlock::absoluteRects(Vector<IntRect>& rects, int tx, int ty)
5718 {
5719     // For blocks inside inlines, we go ahead and include margins so that we run right up to the
5720     // inline boxes above and below us (thus getting merged with them to form a single irregular
5721     // shape).
5722     if (isAnonymousBlockContinuation()) {
5723         // FIXME: This is wrong for block-flows that are horizontal.
5724         // https://bugs.webkit.org/show_bug.cgi?id=46781
5725         rects.append(IntRect(tx, ty - collapsedMarginBefore(),
5726                              width(), height() + collapsedMarginBefore() + collapsedMarginAfter()));
5727         continuation()->absoluteRects(rects,
5728                                       tx - x() + inlineElementContinuation()->containingBlock()->x(),
5729                                       ty - y() + inlineElementContinuation()->containingBlock()->y());
5730     } else
5731         rects.append(IntRect(tx, ty, width(), height()));
5732 }
5733 
absoluteQuads(Vector<FloatQuad> & quads)5734 void RenderBlock::absoluteQuads(Vector<FloatQuad>& quads)
5735 {
5736     // For blocks inside inlines, we go ahead and include margins so that we run right up to the
5737     // inline boxes above and below us (thus getting merged with them to form a single irregular
5738     // shape).
5739     if (isAnonymousBlockContinuation()) {
5740         // FIXME: This is wrong for block-flows that are horizontal.
5741         // https://bugs.webkit.org/show_bug.cgi?id=46781
5742         FloatRect localRect(0, -collapsedMarginBefore(),
5743                             width(), height() + collapsedMarginBefore() + collapsedMarginAfter());
5744         quads.append(localToAbsoluteQuad(localRect));
5745         continuation()->absoluteQuads(quads);
5746     } else
5747         quads.append(RenderBox::localToAbsoluteQuad(FloatRect(0, 0, width(), height())));
5748 }
5749 
rectWithOutlineForRepaint(RenderBoxModelObject * repaintContainer,int outlineWidth)5750 IntRect RenderBlock::rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, int outlineWidth)
5751 {
5752     IntRect r(RenderBox::rectWithOutlineForRepaint(repaintContainer, outlineWidth));
5753     if (isAnonymousBlockContinuation())
5754         r.inflateY(collapsedMarginBefore()); // FIXME: This is wrong for block-flows that are horizontal.
5755     return r;
5756 }
5757 
hoverAncestor() const5758 RenderObject* RenderBlock::hoverAncestor() const
5759 {
5760     return isAnonymousBlockContinuation() ? continuation() : RenderBox::hoverAncestor();
5761 }
5762 
updateDragState(bool dragOn)5763 void RenderBlock::updateDragState(bool dragOn)
5764 {
5765     RenderBox::updateDragState(dragOn);
5766     if (continuation())
5767         continuation()->updateDragState(dragOn);
5768 }
5769 
outlineStyleForRepaint() const5770 RenderStyle* RenderBlock::outlineStyleForRepaint() const
5771 {
5772     return isAnonymousBlockContinuation() ? continuation()->style() : style();
5773 }
5774 
childBecameNonInline(RenderObject *)5775 void RenderBlock::childBecameNonInline(RenderObject*)
5776 {
5777     makeChildrenNonInline();
5778     if (isAnonymousBlock() && parent() && parent()->isRenderBlock())
5779         toRenderBlock(parent())->removeLeftoverAnonymousBlock(this);
5780     // |this| may be dead here
5781 }
5782 
updateHitTestResult(HitTestResult & result,const IntPoint & point)5783 void RenderBlock::updateHitTestResult(HitTestResult& result, const IntPoint& point)
5784 {
5785     if (result.innerNode())
5786         return;
5787 
5788     Node* n = node();
5789     if (isAnonymousBlockContinuation())
5790         // We are in the margins of block elements that are part of a continuation.  In
5791         // this case we're actually still inside the enclosing element that was
5792         // split.  Go ahead and set our inner node accordingly.
5793         n = continuation()->node();
5794 
5795     if (n) {
5796         result.setInnerNode(n);
5797         if (!result.innerNonSharedNode())
5798             result.setInnerNonSharedNode(n);
5799         result.setLocalPoint(point);
5800     }
5801 }
5802 
localCaretRect(InlineBox * inlineBox,int caretOffset,int * extraWidthToEndOfLine)5803 IntRect RenderBlock::localCaretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
5804 {
5805     // Do the normal calculation in most cases.
5806     if (firstChild())
5807         return RenderBox::localCaretRect(inlineBox, caretOffset, extraWidthToEndOfLine);
5808 
5809     // This is a special case:
5810     // The element is not an inline element, and it's empty. So we have to
5811     // calculate a fake position to indicate where objects are to be inserted.
5812 
5813     // FIXME: This does not take into account either :first-line or :first-letter
5814     // However, as soon as some content is entered, the line boxes will be
5815     // constructed and this kludge is not called any more. So only the caret size
5816     // of an empty :first-line'd block is wrong. I think we can live with that.
5817     RenderStyle* currentStyle = firstLineStyle();
5818     int height = lineHeight(true, currentStyle->isHorizontalWritingMode() ? HorizontalLine : VerticalLine);
5819 
5820     enum CaretAlignment { alignLeft, alignRight, alignCenter };
5821 
5822     CaretAlignment alignment = alignLeft;
5823 
5824     switch (currentStyle->textAlign()) {
5825         case TAAUTO:
5826         case JUSTIFY:
5827             if (!currentStyle->isLeftToRightDirection())
5828                 alignment = alignRight;
5829             break;
5830         case LEFT:
5831         case WEBKIT_LEFT:
5832             break;
5833         case CENTER:
5834         case WEBKIT_CENTER:
5835             alignment = alignCenter;
5836             break;
5837         case RIGHT:
5838         case WEBKIT_RIGHT:
5839             alignment = alignRight;
5840             break;
5841         case TASTART:
5842             if (!currentStyle->isLeftToRightDirection())
5843                 alignment = alignRight;
5844             break;
5845         case TAEND:
5846             if (currentStyle->isLeftToRightDirection())
5847                 alignment = alignRight;
5848             break;
5849     }
5850 
5851     int x = borderLeft() + paddingLeft();
5852     int w = width();
5853 
5854     switch (alignment) {
5855         case alignLeft:
5856             break;
5857         case alignCenter:
5858             x = (x + w - (borderRight() + paddingRight())) / 2;
5859             break;
5860         case alignRight:
5861             x = w - (borderRight() + paddingRight()) - caretWidth;
5862             break;
5863     }
5864 
5865     if (extraWidthToEndOfLine) {
5866         if (isRenderBlock()) {
5867             *extraWidthToEndOfLine = w - (x + caretWidth);
5868         } else {
5869             // FIXME: This code looks wrong.
5870             // myRight and containerRight are set up, but then clobbered.
5871             // So *extraWidthToEndOfLine will always be 0 here.
5872 
5873             int myRight = x + caretWidth;
5874             // FIXME: why call localToAbsoluteForContent() twice here, too?
5875             FloatPoint absRightPoint = localToAbsolute(FloatPoint(myRight, 0));
5876 
5877             int containerRight = containingBlock()->x() + containingBlockLogicalWidthForContent();
5878             FloatPoint absContainerPoint = localToAbsolute(FloatPoint(containerRight, 0));
5879 
5880             *extraWidthToEndOfLine = absContainerPoint.x() - absRightPoint.x();
5881         }
5882     }
5883 
5884     int y = paddingTop() + borderTop();
5885 
5886     return IntRect(x, y, caretWidth, height);
5887 }
5888 
addFocusRingRects(Vector<IntRect> & rects,int tx,int ty)5889 void RenderBlock::addFocusRingRects(Vector<IntRect>& rects, int tx, int ty)
5890 {
5891     // For blocks inside inlines, we go ahead and include margins so that we run right up to the
5892     // inline boxes above and below us (thus getting merged with them to form a single irregular
5893     // shape).
5894     if (inlineElementContinuation()) {
5895         // FIXME: This check really isn't accurate.
5896         bool nextInlineHasLineBox = inlineElementContinuation()->firstLineBox();
5897         // FIXME: This is wrong. The principal renderer may not be the continuation preceding this block.
5898         // FIXME: This is wrong for block-flows that are horizontal.
5899         // https://bugs.webkit.org/show_bug.cgi?id=46781
5900         bool prevInlineHasLineBox = toRenderInline(inlineElementContinuation()->node()->renderer())->firstLineBox();
5901         int topMargin = prevInlineHasLineBox ? collapsedMarginBefore() : 0;
5902         int bottomMargin = nextInlineHasLineBox ? collapsedMarginAfter() : 0;
5903         IntRect rect(tx, ty - topMargin, width(), height() + topMargin + bottomMargin);
5904         if (!rect.isEmpty())
5905             rects.append(rect);
5906     } else if (width() && height())
5907         rects.append(IntRect(tx, ty, width(), height()));
5908 
5909     if (!hasOverflowClip() && !hasControlClip()) {
5910         for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
5911             int top = max(curr->lineTop(), curr->logicalTop());
5912             int bottom = min(curr->lineBottom(), curr->logicalTop() + curr->logicalHeight());
5913             IntRect rect(tx + curr->x(), ty + top, curr->logicalWidth(), bottom - top);
5914             if (!rect.isEmpty())
5915                 rects.append(rect);
5916         }
5917 
5918         for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
5919             if (!curr->isText() && !curr->isListMarker() && curr->isBox()) {
5920                 RenderBox* box = toRenderBox(curr);
5921                 FloatPoint pos;
5922                 // FIXME: This doesn't work correctly with transforms.
5923                 if (box->layer())
5924                     pos = curr->localToAbsolute();
5925                 else
5926                     pos = FloatPoint(tx + box->x(), ty + box->y());
5927                 box->addFocusRingRects(rects, pos.x(), pos.y());
5928             }
5929         }
5930     }
5931 
5932     if (inlineElementContinuation())
5933         inlineElementContinuation()->addFocusRingRects(rects,
5934                                                        tx - x() + inlineElementContinuation()->containingBlock()->x(),
5935                                                        ty - y() + inlineElementContinuation()->containingBlock()->y());
5936 }
5937 
createAnonymousBlock(bool isFlexibleBox) const5938 RenderBlock* RenderBlock::createAnonymousBlock(bool isFlexibleBox) const
5939 {
5940     RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style());
5941 
5942     RenderBlock* newBox = 0;
5943     if (isFlexibleBox) {
5944         newStyle->setDisplay(BOX);
5945         newBox = new (renderArena()) RenderFlexibleBox(document() /* anonymous box */);
5946     } else {
5947         newStyle->setDisplay(BLOCK);
5948         newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
5949     }
5950 
5951     newBox->setStyle(newStyle.release());
5952     return newBox;
5953 }
5954 
createAnonymousBlockWithSameTypeAs(RenderBlock * otherAnonymousBlock) const5955 RenderBlock* RenderBlock::createAnonymousBlockWithSameTypeAs(RenderBlock* otherAnonymousBlock) const
5956 {
5957     if (otherAnonymousBlock->isAnonymousColumnsBlock())
5958         return createAnonymousColumnsBlock();
5959     if (otherAnonymousBlock->isAnonymousColumnSpanBlock())
5960         return createAnonymousColumnSpanBlock();
5961     return createAnonymousBlock(otherAnonymousBlock->style()->display() == BOX);
5962 }
5963 
createAnonymousColumnsBlock() const5964 RenderBlock* RenderBlock::createAnonymousColumnsBlock() const
5965 {
5966     RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style());
5967     newStyle->inheritColumnPropertiesFrom(style());
5968     newStyle->setDisplay(BLOCK);
5969 
5970     RenderBlock* newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
5971     newBox->setStyle(newStyle.release());
5972     return newBox;
5973 }
5974 
createAnonymousColumnSpanBlock() const5975 RenderBlock* RenderBlock::createAnonymousColumnSpanBlock() const
5976 {
5977     RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyle(style());
5978     newStyle->setColumnSpan(true);
5979     newStyle->setDisplay(BLOCK);
5980 
5981     RenderBlock* newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
5982     newBox->setStyle(newStyle.release());
5983     return newBox;
5984 }
5985 
nextPageLogicalTop(int logicalOffset) const5986 int RenderBlock::nextPageLogicalTop(int logicalOffset) const
5987 {
5988     LayoutState* layoutState = view()->layoutState();
5989     if (!layoutState->m_pageLogicalHeight)
5990         return logicalOffset;
5991 
5992     // The logicalOffset is in our coordinate space.  We can add in our pushed offset.
5993     int pageLogicalHeight = layoutState->m_pageLogicalHeight;
5994     IntSize delta = layoutState->m_layoutOffset - layoutState->m_pageOffset;
5995     int offset = isHorizontalWritingMode() ? delta.height() : delta.width();
5996     int remainingLogicalHeight = (pageLogicalHeight - (offset + logicalOffset) % pageLogicalHeight) % pageLogicalHeight;
5997     return logicalOffset + remainingLogicalHeight;
5998 }
5999 
inNormalFlow(RenderBox * child)6000 static bool inNormalFlow(RenderBox* child)
6001 {
6002     RenderBlock* curr = child->containingBlock();
6003     RenderBlock* initialBlock = child->view();
6004     while (curr && curr != initialBlock) {
6005         if (curr->hasColumns())
6006             return true;
6007         if (curr->isFloatingOrPositioned())
6008             return false;
6009         curr = curr->containingBlock();
6010     }
6011     return true;
6012 }
6013 
applyBeforeBreak(RenderBox * child,int logicalOffset)6014 int RenderBlock::applyBeforeBreak(RenderBox* child, int logicalOffset)
6015 {
6016     // FIXME: Add page break checking here when we support printing.
6017     bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns();
6018     bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageLogicalHeight; // FIXME: Once columns can print we have to check this.
6019     bool checkBeforeAlways = (checkColumnBreaks && child->style()->columnBreakBefore() == PBALWAYS) || (checkPageBreaks && child->style()->pageBreakBefore() == PBALWAYS);
6020     if (checkBeforeAlways && inNormalFlow(child)) {
6021         if (checkColumnBreaks)
6022             view()->layoutState()->addForcedColumnBreak(logicalOffset);
6023         return nextPageLogicalTop(logicalOffset);
6024     }
6025     return logicalOffset;
6026 }
6027 
applyAfterBreak(RenderBox * child,int logicalOffset,MarginInfo & marginInfo)6028 int RenderBlock::applyAfterBreak(RenderBox* child, int logicalOffset, MarginInfo& marginInfo)
6029 {
6030     // FIXME: Add page break checking here when we support printing.
6031     bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns();
6032     bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageLogicalHeight; // FIXME: Once columns can print we have to check this.
6033     bool checkAfterAlways = (checkColumnBreaks && child->style()->columnBreakAfter() == PBALWAYS) || (checkPageBreaks && child->style()->pageBreakAfter() == PBALWAYS);
6034     if (checkAfterAlways && inNormalFlow(child)) {
6035         marginInfo.setMarginAfterQuirk(true); // Cause margins to be discarded for any following content.
6036         if (checkColumnBreaks)
6037             view()->layoutState()->addForcedColumnBreak(logicalOffset);
6038         return nextPageLogicalTop(logicalOffset);
6039     }
6040     return logicalOffset;
6041 }
6042 
adjustForUnsplittableChild(RenderBox * child,int logicalOffset,bool includeMargins)6043 int RenderBlock::adjustForUnsplittableChild(RenderBox* child, int logicalOffset, bool includeMargins)
6044 {
6045     bool isUnsplittable = child->isReplaced() || child->scrollsOverflow();
6046     if (!isUnsplittable)
6047         return logicalOffset;
6048     int childLogicalHeight = logicalHeightForChild(child) + (includeMargins ? marginBeforeForChild(child) + marginAfterForChild(child) : 0);
6049     LayoutState* layoutState = view()->layoutState();
6050     if (layoutState->m_columnInfo)
6051         layoutState->m_columnInfo->updateMinimumColumnHeight(childLogicalHeight);
6052     int pageLogicalHeight = layoutState->m_pageLogicalHeight;
6053     if (!pageLogicalHeight || childLogicalHeight > pageLogicalHeight)
6054         return logicalOffset;
6055     IntSize delta = layoutState->m_layoutOffset - layoutState->m_pageOffset;
6056     int offset = isHorizontalWritingMode() ? delta.height() : delta.width();
6057     int remainingLogicalHeight = (pageLogicalHeight - (offset + logicalOffset) % pageLogicalHeight) % pageLogicalHeight;
6058     if (remainingLogicalHeight < childLogicalHeight)
6059         return logicalOffset + remainingLogicalHeight;
6060     return logicalOffset;
6061 }
6062 
adjustLinePositionForPagination(RootInlineBox * lineBox,int & delta)6063 void RenderBlock::adjustLinePositionForPagination(RootInlineBox* lineBox, int& delta)
6064 {
6065     // FIXME: For now we paginate using line overflow.  This ensures that lines don't overlap at all when we
6066     // put a strut between them for pagination purposes.  However, this really isn't the desired rendering, since
6067     // the line on the top of the next page will appear too far down relative to the same kind of line at the top
6068     // of the first column.
6069     //
6070     // The rendering we would like to see is one where the lineTop is at the top of the column, and any line overflow
6071     // simply spills out above the top of the column.  This effect would match what happens at the top of the first column.
6072     // We can't achieve this rendering, however, until we stop columns from clipping to the column bounds (thus allowing
6073     // for overflow to occur), and then cache visible overflow for each column rect.
6074     //
6075     // Furthermore, the paint we have to do when a column has overflow has to be special.  We need to exclude
6076     // content that paints in a previous column (and content that paints in the following column).
6077     //
6078     // FIXME: Another problem with simply moving lines is that the available line width may change (because of floats).
6079     // Technically if the location we move the line to has a different line width than our old position, then we need to dirty the
6080     // line and all following lines.
6081     LayoutState* layoutState = view()->layoutState();
6082     int pageLogicalHeight = layoutState->m_pageLogicalHeight;
6083     IntRect logicalVisualOverflow = lineBox->logicalVisualOverflowRect(lineBox->lineTop(), lineBox->lineBottom());
6084     int logicalOffset = logicalVisualOverflow.y();
6085     int lineHeight = logicalVisualOverflow.maxY() - logicalOffset;
6086     if (layoutState->m_columnInfo)
6087         layoutState->m_columnInfo->updateMinimumColumnHeight(lineHeight);
6088     logicalOffset += delta;
6089     lineBox->setPaginationStrut(0);
6090     if (!pageLogicalHeight || lineHeight > pageLogicalHeight)
6091         return;
6092     IntSize offsetDelta = layoutState->m_layoutOffset - layoutState->m_pageOffset;
6093     int offset = isHorizontalWritingMode() ? offsetDelta.height() : offsetDelta.width();
6094     int remainingLogicalHeight = pageLogicalHeight - (offset + logicalOffset) % pageLogicalHeight;
6095     if (remainingLogicalHeight < lineHeight) {
6096         int totalLogicalHeight = lineHeight + max(0, logicalOffset);
6097         if (lineBox == firstRootBox() && totalLogicalHeight < pageLogicalHeight && !isPositioned() && !isTableCell())
6098             setPaginationStrut(remainingLogicalHeight + max(0, logicalOffset));
6099         else {
6100             delta += remainingLogicalHeight;
6101             lineBox->setPaginationStrut(remainingLogicalHeight);
6102         }
6103     }
6104 }
6105 
collapsedMarginBeforeForChild(RenderBox * child) const6106 int RenderBlock::collapsedMarginBeforeForChild(RenderBox* child) const
6107 {
6108     // If the child has the same directionality as we do, then we can just return its
6109     // collapsed margin.
6110     if (!child->isWritingModeRoot())
6111         return child->collapsedMarginBefore();
6112 
6113     // The child has a different directionality.  If the child is parallel, then it's just
6114     // flipped relative to us.  We can use the collapsed margin for the opposite edge.
6115     if (child->isHorizontalWritingMode() == isHorizontalWritingMode())
6116         return child->collapsedMarginAfter();
6117 
6118     // The child is perpendicular to us, which means its margins don't collapse but are on the
6119     // "logical left/right" sides of the child box.  We can just return the raw margin in this case.
6120     return marginBeforeForChild(child);
6121 }
6122 
collapsedMarginAfterForChild(RenderBox * child) const6123 int RenderBlock::collapsedMarginAfterForChild(RenderBox* child) const
6124 {
6125     // If the child has the same directionality as we do, then we can just return its
6126     // collapsed margin.
6127     if (!child->isWritingModeRoot())
6128         return child->collapsedMarginAfter();
6129 
6130     // The child has a different directionality.  If the child is parallel, then it's just
6131     // flipped relative to us.  We can use the collapsed margin for the opposite edge.
6132     if (child->isHorizontalWritingMode() == isHorizontalWritingMode())
6133         return child->collapsedMarginBefore();
6134 
6135     // The child is perpendicular to us, which means its margins don't collapse but are on the
6136     // "logical left/right" side of the child box.  We can just return the raw margin in this case.
6137     return marginAfterForChild(child);
6138 }
6139 
marginBeforeForChild(RenderBoxModelObject * child) const6140 int RenderBlock::marginBeforeForChild(RenderBoxModelObject* child) const
6141 {
6142     switch (style()->writingMode()) {
6143     case TopToBottomWritingMode:
6144         return child->marginTop();
6145     case BottomToTopWritingMode:
6146         return child->marginBottom();
6147     case LeftToRightWritingMode:
6148         return child->marginLeft();
6149     case RightToLeftWritingMode:
6150         return child->marginRight();
6151     }
6152     ASSERT_NOT_REACHED();
6153     return child->marginTop();
6154 }
6155 
marginAfterForChild(RenderBoxModelObject * child) const6156 int RenderBlock::marginAfterForChild(RenderBoxModelObject* child) const
6157 {
6158     switch (style()->writingMode()) {
6159     case TopToBottomWritingMode:
6160         return child->marginBottom();
6161     case BottomToTopWritingMode:
6162         return child->marginTop();
6163     case LeftToRightWritingMode:
6164         return child->marginRight();
6165     case RightToLeftWritingMode:
6166         return child->marginLeft();
6167     }
6168     ASSERT_NOT_REACHED();
6169     return child->marginBottom();
6170 }
6171 
marginStartForChild(RenderBoxModelObject * child) const6172 int RenderBlock::marginStartForChild(RenderBoxModelObject* child) const
6173 {
6174     if (isHorizontalWritingMode())
6175         return style()->isLeftToRightDirection() ? child->marginLeft() : child->marginRight();
6176     return style()->isLeftToRightDirection() ? child->marginTop() : child->marginBottom();
6177 }
6178 
marginEndForChild(RenderBoxModelObject * child) const6179 int RenderBlock::marginEndForChild(RenderBoxModelObject* child) const
6180 {
6181     if (isHorizontalWritingMode())
6182         return style()->isLeftToRightDirection() ? child->marginRight() : child->marginLeft();
6183     return style()->isLeftToRightDirection() ? child->marginBottom() : child->marginTop();
6184 }
6185 
setMarginStartForChild(RenderBox * child,int margin)6186 void RenderBlock::setMarginStartForChild(RenderBox* child, int margin)
6187 {
6188     if (isHorizontalWritingMode()) {
6189         if (style()->isLeftToRightDirection())
6190             child->setMarginLeft(margin);
6191         else
6192             child->setMarginRight(margin);
6193     } else {
6194         if (style()->isLeftToRightDirection())
6195             child->setMarginTop(margin);
6196         else
6197             child->setMarginBottom(margin);
6198     }
6199 }
6200 
setMarginEndForChild(RenderBox * child,int margin)6201 void RenderBlock::setMarginEndForChild(RenderBox* child, int margin)
6202 {
6203     if (isHorizontalWritingMode()) {
6204         if (style()->isLeftToRightDirection())
6205             child->setMarginRight(margin);
6206         else
6207             child->setMarginLeft(margin);
6208     } else {
6209         if (style()->isLeftToRightDirection())
6210             child->setMarginBottom(margin);
6211         else
6212             child->setMarginTop(margin);
6213     }
6214 }
6215 
setMarginBeforeForChild(RenderBox * child,int margin)6216 void RenderBlock::setMarginBeforeForChild(RenderBox* child, int margin)
6217 {
6218     switch (style()->writingMode()) {
6219     case TopToBottomWritingMode:
6220         child->setMarginTop(margin);
6221         break;
6222     case BottomToTopWritingMode:
6223         child->setMarginBottom(margin);
6224         break;
6225     case LeftToRightWritingMode:
6226         child->setMarginLeft(margin);
6227         break;
6228     case RightToLeftWritingMode:
6229         child->setMarginRight(margin);
6230         break;
6231     }
6232 }
6233 
setMarginAfterForChild(RenderBox * child,int margin)6234 void RenderBlock::setMarginAfterForChild(RenderBox* child, int margin)
6235 {
6236     switch (style()->writingMode()) {
6237     case TopToBottomWritingMode:
6238         child->setMarginBottom(margin);
6239         break;
6240     case BottomToTopWritingMode:
6241         child->setMarginTop(margin);
6242         break;
6243     case LeftToRightWritingMode:
6244         child->setMarginRight(margin);
6245         break;
6246     case RightToLeftWritingMode:
6247         child->setMarginLeft(margin);
6248         break;
6249     }
6250 }
6251 
marginValuesForChild(RenderBox * child)6252 RenderBlock::MarginValues RenderBlock::marginValuesForChild(RenderBox* child)
6253 {
6254     int childBeforePositive = 0;
6255     int childBeforeNegative = 0;
6256     int childAfterPositive = 0;
6257     int childAfterNegative = 0;
6258 
6259     int beforeMargin = 0;
6260     int afterMargin = 0;
6261 
6262     RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
6263 
6264     // If the child has the same directionality as we do, then we can just return its
6265     // margins in the same direction.
6266     if (!child->isWritingModeRoot()) {
6267         if (childRenderBlock) {
6268             childBeforePositive = childRenderBlock->maxPositiveMarginBefore();
6269             childBeforeNegative = childRenderBlock->maxNegativeMarginBefore();
6270             childAfterPositive = childRenderBlock->maxPositiveMarginAfter();
6271             childAfterNegative = childRenderBlock->maxNegativeMarginAfter();
6272         } else {
6273             beforeMargin = child->marginBefore();
6274             afterMargin = child->marginAfter();
6275         }
6276     } else if (child->isHorizontalWritingMode() == isHorizontalWritingMode()) {
6277         // The child has a different directionality.  If the child is parallel, then it's just
6278         // flipped relative to us.  We can use the margins for the opposite edges.
6279         if (childRenderBlock) {
6280             childBeforePositive = childRenderBlock->maxPositiveMarginAfter();
6281             childBeforeNegative = childRenderBlock->maxNegativeMarginAfter();
6282             childAfterPositive = childRenderBlock->maxPositiveMarginBefore();
6283             childAfterNegative = childRenderBlock->maxNegativeMarginBefore();
6284         } else {
6285             beforeMargin = child->marginAfter();
6286             afterMargin = child->marginBefore();
6287         }
6288     } else {
6289         // The child is perpendicular to us, which means its margins don't collapse but are on the
6290         // "logical left/right" sides of the child box.  We can just return the raw margin in this case.
6291         beforeMargin = marginBeforeForChild(child);
6292         afterMargin = marginAfterForChild(child);
6293     }
6294 
6295     // Resolve uncollapsing margins into their positive/negative buckets.
6296     if (beforeMargin) {
6297         if (beforeMargin > 0)
6298             childBeforePositive = beforeMargin;
6299         else
6300             childBeforeNegative = -beforeMargin;
6301     }
6302     if (afterMargin) {
6303         if (afterMargin > 0)
6304             childAfterPositive = afterMargin;
6305         else
6306             childAfterNegative = -afterMargin;
6307     }
6308 
6309     return MarginValues(childBeforePositive, childBeforeNegative, childAfterPositive, childAfterNegative);
6310 }
6311 
renderName() const6312 const char* RenderBlock::renderName() const
6313 {
6314     if (isBody())
6315         return "RenderBody"; // FIXME: Temporary hack until we know that the regression tests pass.
6316 
6317     if (isFloating())
6318         return "RenderBlock (floating)";
6319     if (isPositioned())
6320         return "RenderBlock (positioned)";
6321     if (isAnonymousColumnsBlock())
6322         return "RenderBlock (anonymous multi-column)";
6323     if (isAnonymousColumnSpanBlock())
6324         return "RenderBlock (anonymous multi-column span)";
6325     if (isAnonymousBlock())
6326         return "RenderBlock (anonymous)";
6327     else if (isAnonymous())
6328         return "RenderBlock (generated)";
6329     if (isRelPositioned())
6330         return "RenderBlock (relative positioned)";
6331     if (isRunIn())
6332         return "RenderBlock (run-in)";
6333     return "RenderBlock";
6334 }
6335 
clear()6336 inline void RenderBlock::FloatingObjects::clear()
6337 {
6338     m_set.clear();
6339     m_leftObjectsCount = 0;
6340     m_rightObjectsCount = 0;
6341 }
6342 
increaseObjectsCount(FloatingObject::Type type)6343 inline void RenderBlock::FloatingObjects::increaseObjectsCount(FloatingObject::Type type)
6344 {
6345     if (type == FloatingObject::FloatLeft)
6346         m_leftObjectsCount++;
6347     else
6348         m_rightObjectsCount++;
6349 }
6350 
decreaseObjectsCount(FloatingObject::Type type)6351 inline void RenderBlock::FloatingObjects::decreaseObjectsCount(FloatingObject::Type type)
6352 {
6353     if (type == FloatingObject::FloatLeft)
6354         m_leftObjectsCount--;
6355     else
6356         m_rightObjectsCount--;
6357 }
6358 
6359 } // namespace WebCore
6360