• 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 Apple Inc. All rights reserved.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #include "config.h"
24 #include "RenderBlock.h"
25 
26 #include "Document.h"
27 #include "Element.h"
28 #include "FloatQuad.h"
29 #include "Frame.h"
30 #include "FrameView.h"
31 #include "GraphicsContext.h"
32 #include "HTMLFormElement.h"
33 #include "HTMLNames.h"
34 #include "HitTestResult.h"
35 #include "InlineTextBox.h"
36 #include "RenderImage.h"
37 #include "RenderInline.h"
38 #include "RenderMarquee.h"
39 #include "RenderReplica.h"
40 #include "RenderTableCell.h"
41 #include "RenderTextFragment.h"
42 #include "RenderTheme.h"
43 #include "RenderView.h"
44 #include "SelectionController.h"
45 #include "Settings.h"
46 #include <wtf/StdLibExtras.h>
47 
48 #ifdef ANDROID_LAYOUT
49 #include "Settings.h"
50 #endif
51 
52 using namespace std;
53 using namespace WTF;
54 using namespace Unicode;
55 
56 namespace WebCore {
57 
58 // Number of pixels to allow as a fudge factor when clicking above or below a line.
59 // clicking up to verticalLineClickFudgeFactor pixels above a line will correspond to the closest point on the line.
60 static const int verticalLineClickFudgeFactor = 3;
61 
62 using namespace HTMLNames;
63 
moveChild(RenderObject * to,RenderObjectChildList * toChildList,RenderObject * from,RenderObjectChildList * fromChildList,RenderObject * child)64 static void moveChild(RenderObject* to, RenderObjectChildList* toChildList, RenderObject* from, RenderObjectChildList* fromChildList, RenderObject* child)
65 {
66     ASSERT(from == child->parent());
67     toChildList->appendChildNode(to, fromChildList->removeChildNode(from, child, false), false);
68 }
69 
70 struct ColumnInfo {
ColumnInfoWebCore::ColumnInfo71     ColumnInfo()
72         : m_desiredColumnWidth(0)
73         , m_desiredColumnCount(1)
74         { }
75     int m_desiredColumnWidth;
76     unsigned m_desiredColumnCount;
77     Vector<IntRect> m_columnRects;
78 };
79 
80 typedef WTF::HashMap<const RenderBox*, ColumnInfo*> ColumnInfoMap;
81 static ColumnInfoMap* gColumnInfoMap = 0;
82 
83 typedef WTF::HashMap<const RenderBlock*, HashSet<RenderBox*>*> PercentHeightDescendantsMap;
84 static PercentHeightDescendantsMap* gPercentHeightDescendantsMap = 0;
85 
86 typedef WTF::HashMap<const RenderBox*, HashSet<RenderBlock*>*> PercentHeightContainerMap;
87 static PercentHeightContainerMap* gPercentHeightContainerMap = 0;
88 
89 typedef WTF::HashMap<RenderBlock*, ListHashSet<RenderInline*>*> ContinuationOutlineTableMap;
90 
91 typedef WTF::HashSet<RenderBlock*> DelayedUpdateScrollInfoSet;
92 static int gDelayUpdateScrollInfo = 0;
93 static DelayedUpdateScrollInfoSet* gDelayedUpdateScrollInfoSet = 0;
94 
95 // Our MarginInfo state used when laying out block children.
MarginInfo(RenderBlock * block,int top,int bottom)96 RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, int top, int bottom)
97 {
98     // Whether or not we can collapse our own margins with our children.  We don't do this
99     // if we had any border/padding (obviously), if we're the root or HTML elements, or if
100     // we're positioned, floating, a table cell.
101     m_canCollapseWithChildren = !block->isRenderView() && !block->isRoot() && !block->isPositioned() &&
102         !block->isFloating() && !block->isTableCell() && !block->hasOverflowClip() && !block->isInlineBlockOrInlineTable();
103 
104     m_canCollapseTopWithChildren = m_canCollapseWithChildren && (top == 0) && block->style()->marginTopCollapse() != MSEPARATE;
105 
106     // If any height other than auto is specified in CSS, then we don't collapse our bottom
107     // margins with our children's margins.  To do otherwise would be to risk odd visual
108     // effects when the children overflow out of the parent block and yet still collapse
109     // with it.  We also don't collapse if we have any bottom border/padding.
110     m_canCollapseBottomWithChildren = m_canCollapseWithChildren && (bottom == 0) &&
111         (block->style()->height().isAuto() && block->style()->height().value() == 0) && block->style()->marginBottomCollapse() != MSEPARATE;
112 
113     m_quirkContainer = block->isTableCell() || block->isBody() || block->style()->marginTopCollapse() == MDISCARD ||
114         block->style()->marginBottomCollapse() == MDISCARD;
115 
116     m_atTopOfBlock = true;
117     m_atBottomOfBlock = false;
118 
119     m_posMargin = m_canCollapseTopWithChildren ? block->maxTopMargin(true) : 0;
120     m_negMargin = m_canCollapseTopWithChildren ? block->maxTopMargin(false) : 0;
121 
122     m_selfCollapsingBlockClearedFloat = false;
123 
124     m_topQuirk = m_bottomQuirk = m_determinedTopQuirk = false;
125 }
126 
127 // -------------------------------------------------------------------------------------------------------
128 
RenderBlock(Node * node)129 RenderBlock::RenderBlock(Node* node)
130       : RenderBox(node)
131       , m_floatingObjects(0)
132       , m_positionedObjects(0)
133       , m_inlineContinuation(0)
134       , m_maxMargin(0)
135       , m_overflowHeight(0)
136       , m_overflowWidth(0)
137       , m_overflowLeft(0)
138       , m_overflowTop(0)
139       , m_lineHeight(-1)
140 {
141     setChildrenInline(true);
142 }
143 
~RenderBlock()144 RenderBlock::~RenderBlock()
145 {
146     delete m_floatingObjects;
147     delete m_positionedObjects;
148     delete m_maxMargin;
149 
150     if (hasColumns())
151         delete gColumnInfoMap->take(this);
152 
153     if (gPercentHeightDescendantsMap) {
154         if (HashSet<RenderBox*>* descendantSet = gPercentHeightDescendantsMap->take(this)) {
155             HashSet<RenderBox*>::iterator end = descendantSet->end();
156             for (HashSet<RenderBox*>::iterator descendant = descendantSet->begin(); descendant != end; ++descendant) {
157                 HashSet<RenderBlock*>* containerSet = gPercentHeightContainerMap->get(*descendant);
158                 ASSERT(containerSet);
159                 if (!containerSet)
160                     continue;
161                 ASSERT(containerSet->contains(this));
162                 containerSet->remove(this);
163                 if (containerSet->isEmpty()) {
164                     gPercentHeightContainerMap->remove(*descendant);
165                     delete containerSet;
166                 }
167             }
168             delete descendantSet;
169         }
170     }
171 }
172 
destroy()173 void RenderBlock::destroy()
174 {
175     // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will
176     // properly dirty line boxes that they are removed from. Effects that do :before/:after only on hover could crash otherwise.
177     children()->destroyLeftoverChildren();
178 
179     // Destroy our continuation before anything other than anonymous children.
180     // The reason we don't destroy it before anonymous children is that they may
181     // have continuations of their own that are anonymous children of our continuation.
182     if (m_inlineContinuation) {
183         m_inlineContinuation->destroy();
184         m_inlineContinuation = 0;
185     }
186 
187     if (!documentBeingDestroyed()) {
188         if (firstLineBox()) {
189             // We can't wait for RenderBox::destroy to clear the selection,
190             // because by then we will have nuked the line boxes.
191             // FIXME: The SelectionController should be responsible for this when it
192             // is notified of DOM mutations.
193             if (isSelectionBorder())
194                 view()->clearSelection();
195 
196             // If we are an anonymous block, then our line boxes might have children
197             // that will outlast this block. In the non-anonymous block case those
198             // children will be destroyed by the time we return from this function.
199             if (isAnonymousBlock()) {
200                 for (InlineFlowBox* box = firstLineBox(); box; box = box->nextFlowBox()) {
201                     while (InlineBox* childBox = box->firstChild())
202                         childBox->remove();
203                 }
204             }
205         } else if (isInline() && parent())
206             parent()->dirtyLinesFromChangedChild(this);
207     }
208 
209     m_lineBoxes.deleteLineBoxes(renderArena());
210 
211     RenderBox::destroy();
212 }
213 
styleWillChange(StyleDifference diff,const RenderStyle * newStyle)214 void RenderBlock::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
215 {
216     setReplaced(newStyle->isDisplayReplacedType());
217 
218     if (style() && parent() && diff == StyleDifferenceLayout && style()->position() != newStyle->position()) {
219         if (newStyle->position() == StaticPosition)
220             // Clear our positioned objects list. Our absolutely positioned descendants will be
221             // inserted into our containing block's positioned objects list during layout.
222             removePositionedObjects(0);
223         else if (style()->position() == StaticPosition) {
224             // Remove our absolutely positioned descendants from their current containing block.
225             // They will be inserted into our positioned objects list during layout.
226             RenderObject* cb = parent();
227             while (cb && (cb->style()->position() == StaticPosition || (cb->isInline() && !cb->isReplaced())) && !cb->isRenderView()) {
228                 if (cb->style()->position() == RelativePosition && cb->isInline() && !cb->isReplaced()) {
229                     cb = cb->containingBlock();
230                     break;
231                 }
232                 cb = cb->parent();
233             }
234 
235             if (cb->isRenderBlock())
236                 toRenderBlock(cb)->removePositionedObjects(this);
237         }
238     }
239 
240     RenderBox::styleWillChange(diff, newStyle);
241 }
242 
styleDidChange(StyleDifference diff,const RenderStyle * oldStyle)243 void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
244 {
245     RenderBox::styleDidChange(diff, oldStyle);
246 
247     // FIXME: We could save this call when the change only affected non-inherited properties
248     for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
249         if (child->isAnonymousBlock()) {
250             RefPtr<RenderStyle> newStyle = RenderStyle::create();
251             newStyle->inheritFrom(style());
252             newStyle->setDisplay(BLOCK);
253             child->setStyle(newStyle.release());
254         }
255     }
256 
257     m_lineHeight = -1;
258 
259     // Update pseudos for :before and :after now.
260     if (!isAnonymous() && document()->usesBeforeAfterRules() && canHaveChildren()) {
261         updateBeforeAfterContent(BEFORE);
262         updateBeforeAfterContent(AFTER);
263     }
264     updateFirstLetter();
265 }
266 
updateBeforeAfterContent(PseudoId pseudoId)267 void RenderBlock::updateBeforeAfterContent(PseudoId pseudoId)
268 {
269     // If this is an anonymous wrapper, then the parent applies its own pseudo-element style to it.
270     if (parent() && parent()->createsAnonymousWrapper())
271         return;
272     return children()->updateBeforeAfterContent(this, pseudoId);
273 }
274 
addChild(RenderObject * newChild,RenderObject * beforeChild)275 void RenderBlock::addChild(RenderObject* newChild, RenderObject* beforeChild)
276 {
277     // Make sure we don't append things after :after-generated content if we have it.
278     if (!beforeChild && isAfterContent(lastChild()))
279         beforeChild = lastChild();
280 
281     bool madeBoxesNonInline = false;
282 
283     // If the requested beforeChild is not one of our children, then this is because
284     // there is an anonymous container within this object that contains the beforeChild.
285     if (beforeChild && beforeChild->parent() != this) {
286         RenderObject* anonymousChild = beforeChild->parent();
287         ASSERT(anonymousChild);
288 
289         while (anonymousChild->parent() != this)
290             anonymousChild = anonymousChild->parent();
291 
292         ASSERT(anonymousChild->isAnonymous());
293 
294         if (anonymousChild->isAnonymousBlock()) {
295             // Insert the child into the anonymous block box instead of here.
296             if (newChild->isInline() || beforeChild->parent()->firstChild() != beforeChild)
297                 beforeChild->parent()->addChild(newChild, beforeChild);
298             else
299                 addChild(newChild, beforeChild->parent());
300             return;
301         }
302 
303         ASSERT(anonymousChild->isTable());
304         if ((newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP)
305                 || (newChild->isRenderBlock() && newChild->style()->display() == TABLE_CAPTION)
306                 || newChild->isTableSection()
307                 || newChild->isTableRow()
308                 || newChild->isTableCell()) {
309             // Insert into the anonymous table.
310             anonymousChild->addChild(newChild, beforeChild);
311             return;
312         }
313 
314         // Go on to insert before the anonymous table.
315         beforeChild = anonymousChild;
316     }
317 
318     // A block has to either have all of its children inline, or all of its children as blocks.
319     // So, if our children are currently inline and a block child has to be inserted, we move all our
320     // inline children into anonymous block boxes.
321     if (childrenInline() && !newChild->isInline() && !newChild->isFloatingOrPositioned()) {
322         // This is a block with inline content. Wrap the inline content in anonymous blocks.
323         makeChildrenNonInline(beforeChild);
324         madeBoxesNonInline = true;
325 
326         if (beforeChild && beforeChild->parent() != this) {
327             beforeChild = beforeChild->parent();
328             ASSERT(beforeChild->isAnonymousBlock());
329             ASSERT(beforeChild->parent() == this);
330         }
331     } else if (!childrenInline() && (newChild->isFloatingOrPositioned() || newChild->isInline())) {
332         // If we're inserting an inline child but all of our children are blocks, then we have to make sure
333         // it is put into an anomyous block box. We try to use an existing anonymous box if possible, otherwise
334         // a new one is created and inserted into our list of children in the appropriate position.
335         RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : lastChild();
336 
337         if (afterChild && afterChild->isAnonymousBlock()) {
338             afterChild->addChild(newChild);
339             return;
340         }
341 
342         if (newChild->isInline()) {
343             // No suitable existing anonymous box - create a new one.
344             RenderBlock* newBox = createAnonymousBlock();
345             RenderBox::addChild(newBox, beforeChild);
346             newBox->addChild(newChild);
347             return;
348         }
349     }
350 
351     RenderBox::addChild(newChild, beforeChild);
352 
353     if (madeBoxesNonInline && parent() && isAnonymousBlock() && parent()->isRenderBlock())
354         toRenderBlock(parent())->removeLeftoverAnonymousBlock(this);
355     // this object may be dead here
356 }
357 
getInlineRun(RenderObject * start,RenderObject * boundary,RenderObject * & inlineRunStart,RenderObject * & inlineRunEnd)358 static void getInlineRun(RenderObject* start, RenderObject* boundary,
359                          RenderObject*& inlineRunStart,
360                          RenderObject*& inlineRunEnd)
361 {
362     // Beginning at |start| we find the largest contiguous run of inlines that
363     // we can.  We denote the run with start and end points, |inlineRunStart|
364     // and |inlineRunEnd|.  Note that these two values may be the same if
365     // we encounter only one inline.
366     //
367     // We skip any non-inlines we encounter as long as we haven't found any
368     // inlines yet.
369     //
370     // |boundary| indicates a non-inclusive boundary point.  Regardless of whether |boundary|
371     // is inline or not, we will not include it in a run with inlines before it.  It's as though we encountered
372     // a non-inline.
373 
374     // Start by skipping as many non-inlines as we can.
375     RenderObject * curr = start;
376     bool sawInline;
377     do {
378         while (curr && !(curr->isInline() || curr->isFloatingOrPositioned()))
379             curr = curr->nextSibling();
380 
381         inlineRunStart = inlineRunEnd = curr;
382 
383         if (!curr)
384             return; // No more inline children to be found.
385 
386         sawInline = curr->isInline();
387 
388         curr = curr->nextSibling();
389         while (curr && (curr->isInline() || curr->isFloatingOrPositioned()) && (curr != boundary)) {
390             inlineRunEnd = curr;
391             if (curr->isInline())
392                 sawInline = true;
393             curr = curr->nextSibling();
394         }
395     } while (!sawInline);
396 }
397 
deleteLineBoxTree()398 void RenderBlock::deleteLineBoxTree()
399 {
400     m_lineBoxes.deleteLineBoxTree(renderArena());
401 }
402 
createRootInlineBox()403 RootInlineBox* RenderBlock::createRootInlineBox()
404 {
405     return new (renderArena()) RootInlineBox(this);
406 }
407 
createAndAppendRootInlineBox()408 RootInlineBox* RenderBlock::createAndAppendRootInlineBox()
409 {
410     RootInlineBox* rootBox = createRootInlineBox();
411     m_lineBoxes.appendLineBox(rootBox);
412     return rootBox;
413 }
414 
makeChildrenNonInline(RenderObject * insertionPoint)415 void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
416 {
417     // makeChildrenNonInline takes a block whose children are *all* inline and it
418     // makes sure that inline children are coalesced under anonymous
419     // blocks.  If |insertionPoint| is defined, then it represents the insertion point for
420     // the new block child that is causing us to have to wrap all the inlines.  This
421     // means that we cannot coalesce inlines before |insertionPoint| with inlines following
422     // |insertionPoint|, because the new child is going to be inserted in between the inlines,
423     // splitting them.
424     ASSERT(isInlineBlockOrInlineTable() || !isInline());
425     ASSERT(!insertionPoint || insertionPoint->parent() == this);
426 
427     setChildrenInline(false);
428 
429     RenderObject *child = firstChild();
430     if (!child)
431         return;
432 
433     deleteLineBoxTree();
434 
435     while (child) {
436         RenderObject *inlineRunStart, *inlineRunEnd;
437         getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd);
438 
439         if (!inlineRunStart)
440             break;
441 
442         child = inlineRunEnd->nextSibling();
443 
444         RenderBlock* block = createAnonymousBlock();
445         children()->insertChildNode(this, block, inlineRunStart);
446         RenderObject* o = inlineRunStart;
447         while (o != inlineRunEnd) {
448             RenderObject* no = o;
449             o = no->nextSibling();
450 
451             moveChild(block, block->children(), this, children(), no);
452         }
453         moveChild(block, block->children(), this, children(), inlineRunEnd);
454     }
455 
456 #ifndef NDEBUG
457     for (RenderObject *c = firstChild(); c; c = c->nextSibling())
458         ASSERT(!c->isInline());
459 #endif
460 
461     repaint();
462 }
463 
removeLeftoverAnonymousBlock(RenderBlock * child)464 void RenderBlock::removeLeftoverAnonymousBlock(RenderBlock* child)
465 {
466     ASSERT(child->isAnonymousBlock());
467     ASSERT(!child->childrenInline());
468 
469     if (child->inlineContinuation())
470         return;
471 
472     RenderObject* firstAnChild = child->m_children.firstChild();
473     RenderObject* lastAnChild = child->m_children.lastChild();
474     if (firstAnChild) {
475         RenderObject* o = firstAnChild;
476         while (o) {
477             o->setParent(this);
478             o = o->nextSibling();
479         }
480         firstAnChild->setPreviousSibling(child->previousSibling());
481         lastAnChild->setNextSibling(child->nextSibling());
482         if (child->previousSibling())
483             child->previousSibling()->setNextSibling(firstAnChild);
484         if (child->nextSibling())
485             child->nextSibling()->setPreviousSibling(lastAnChild);
486     } else {
487         if (child->previousSibling())
488             child->previousSibling()->setNextSibling(child->nextSibling());
489         if (child->nextSibling())
490             child->nextSibling()->setPreviousSibling(child->previousSibling());
491     }
492     if (child == m_children.firstChild())
493         m_children.setFirstChild(firstAnChild);
494     if (child == m_children.lastChild())
495         m_children.setLastChild(lastAnChild);
496     child->setParent(0);
497     child->setPreviousSibling(0);
498     child->setNextSibling(0);
499 
500     child->children()->setFirstChild(0);
501     child->m_next = 0;
502 
503     child->destroy();
504 }
505 
removeChild(RenderObject * oldChild)506 void RenderBlock::removeChild(RenderObject* oldChild)
507 {
508     // If this child is a block, and if our previous and next siblings are
509     // both anonymous blocks with inline content, then we can go ahead and
510     // fold the inline content back together.
511     RenderObject* prev = oldChild->previousSibling();
512     RenderObject* next = oldChild->nextSibling();
513     bool canDeleteAnonymousBlocks = !documentBeingDestroyed() && !isInline() && !oldChild->isInline() &&
514                                     (!oldChild->isRenderBlock() || !toRenderBlock(oldChild)->inlineContinuation()) &&
515                                     (!prev || (prev->isAnonymousBlock() && prev->childrenInline())) &&
516                                     (!next || (next->isAnonymousBlock() && next->childrenInline()));
517     if (canDeleteAnonymousBlocks && prev && next) {
518         // Take all the children out of the |next| block and put them in
519         // the |prev| block.
520         prev->setNeedsLayoutAndPrefWidthsRecalc();
521         RenderObject* o = next->firstChild();
522 
523         RenderBlock* nextBlock = toRenderBlock(next);
524         RenderBlock* prevBlock = toRenderBlock(prev);
525         while (o) {
526             RenderObject* no = o;
527             o = no->nextSibling();
528             moveChild(prevBlock, prevBlock->children(), nextBlock, nextBlock->children(), no);
529         }
530 
531         nextBlock->deleteLineBoxTree();
532 
533         // Nuke the now-empty block.
534         next->destroy();
535     }
536 
537     RenderBox::removeChild(oldChild);
538 
539     RenderObject* child = prev ? prev : next;
540     if (canDeleteAnonymousBlocks && child && !child->previousSibling() && !child->nextSibling() && !isFlexibleBox()) {
541         // The removal has knocked us down to containing only a single anonymous
542         // box.  We can go ahead and pull the content right back up into our
543         // box.
544         setNeedsLayoutAndPrefWidthsRecalc();
545         RenderBlock* anonBlock = toRenderBlock(children()->removeChildNode(this, child, false));
546         setChildrenInline(true);
547         RenderObject* o = anonBlock->firstChild();
548         while (o) {
549             RenderObject* no = o;
550             o = no->nextSibling();
551             moveChild(this, children(), anonBlock, anonBlock->children(), no);
552         }
553 
554         // Delete the now-empty block's lines and nuke it.
555         anonBlock->deleteLineBoxTree();
556         anonBlock->destroy();
557     }
558 }
559 
overflowHeight(bool includeInterior) const560 int RenderBlock::overflowHeight(bool includeInterior) const
561 {
562     if (!includeInterior && hasOverflowClip()) {
563         int shadowTop;
564         int shadowBottom;
565         style()->getBoxShadowVerticalExtent(shadowTop, shadowBottom);
566 
567         int inflatedHeight = height() + shadowBottom;
568         if (hasReflection())
569             inflatedHeight = max(inflatedHeight, reflectionBox().bottom());
570         return inflatedHeight;
571     }
572     return m_overflowHeight;
573 }
574 
overflowWidth(bool includeInterior) const575 int RenderBlock::overflowWidth(bool includeInterior) const
576 {
577     if (!includeInterior && hasOverflowClip()) {
578         int shadowLeft;
579         int shadowRight;
580         style()->getBoxShadowHorizontalExtent(shadowLeft, shadowRight);
581 
582         int inflatedWidth = width() + shadowRight;
583         if (hasReflection())
584             inflatedWidth = max(inflatedWidth, reflectionBox().right());
585         return inflatedWidth;
586     }
587     return m_overflowWidth;
588 }
589 
overflowLeft(bool includeInterior) const590 int RenderBlock::overflowLeft(bool includeInterior) const
591 {
592     if (!includeInterior && hasOverflowClip()) {
593         int shadowLeft;
594         int shadowRight;
595         style()->getBoxShadowHorizontalExtent(shadowLeft, shadowRight);
596 
597         int left = shadowLeft;
598         if (hasReflection())
599             left = min(left, reflectionBox().x());
600         return left;
601     }
602     return m_overflowLeft;
603 }
604 
overflowTop(bool includeInterior) const605 int RenderBlock::overflowTop(bool includeInterior) const
606 {
607     if (!includeInterior && hasOverflowClip()) {
608         int shadowTop;
609         int shadowBottom;
610         style()->getBoxShadowVerticalExtent(shadowTop, shadowBottom);
611 
612         int top = shadowTop;
613         if (hasReflection())
614             top = min(top, reflectionBox().y());
615         return top;
616     }
617     return m_overflowTop;
618 }
619 
overflowRect(bool includeInterior) const620 IntRect RenderBlock::overflowRect(bool includeInterior) const
621 {
622     if (!includeInterior && hasOverflowClip()) {
623         IntRect box = borderBoxRect();
624 
625         int shadowLeft;
626         int shadowRight;
627         int shadowTop;
628         int shadowBottom;
629         style()->getBoxShadowExtent(shadowTop, shadowRight, shadowBottom, shadowLeft);
630 
631         box.move(shadowLeft, shadowTop);
632         box.setWidth(box.width() - shadowLeft + shadowRight);
633         box.setHeight(box.height() - shadowTop + shadowBottom);
634 
635         if (hasReflection()) {
636             IntRect reflection(reflectionBox());
637             int reflectTop = min(box.y(), reflection.y());
638             int reflectBottom = max(box.bottom(), reflection.bottom());
639             box.setHeight(reflectBottom - reflectTop);
640             box.setY(reflectTop);
641 
642             int reflectLeft = min(box.x(), reflection.x());
643             int reflectRight = max(box.right(), reflection.right());
644             box.setWidth(reflectRight - reflectLeft);
645             box.setX(reflectLeft);
646         }
647         return box;
648     }
649 
650     if (!includeInterior && hasOverflowClip())
651         return borderBoxRect();
652     int l = overflowLeft(includeInterior);
653     int t = overflowTop(includeInterior);
654     return IntRect(l, t, overflowWidth(includeInterior) - l, max(overflowHeight(includeInterior), height()) - t);
655 }
656 
isSelfCollapsingBlock() const657 bool RenderBlock::isSelfCollapsingBlock() const
658 {
659     // We are not self-collapsing if we
660     // (a) have a non-zero height according to layout (an optimization to avoid wasting time)
661     // (b) are a table,
662     // (c) have border/padding,
663     // (d) have a min-height
664     // (e) have specified that one of our margins can't collapse using a CSS extension
665     if (height() > 0 ||
666         isTable() || (borderBottom() + paddingBottom() + borderTop() + paddingTop()) != 0 ||
667         style()->minHeight().isPositive() ||
668         style()->marginTopCollapse() == MSEPARATE || style()->marginBottomCollapse() == MSEPARATE)
669         return false;
670 
671     bool hasAutoHeight = style()->height().isAuto();
672     if (style()->height().isPercent() && !style()->htmlHacks()) {
673         hasAutoHeight = true;
674         for (RenderBlock* cb = containingBlock(); !cb->isRenderView(); cb = cb->containingBlock()) {
675             if (cb->style()->height().isFixed() || cb->isTableCell())
676                 hasAutoHeight = false;
677         }
678     }
679 
680     // If the height is 0 or auto, then whether or not we are a self-collapsing block depends
681     // on whether we have content that is all self-collapsing or not.
682     if (hasAutoHeight || ((style()->height().isFixed() || style()->height().isPercent()) && style()->height().isZero())) {
683         // If the block has inline children, see if we generated any line boxes.  If we have any
684         // line boxes, then we can't be self-collapsing, since we have content.
685         if (childrenInline())
686             return !firstLineBox();
687 
688         // Whether or not we collapse is dependent on whether all our normal flow children
689         // are also self-collapsing.
690         for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
691             if (child->isFloatingOrPositioned())
692                 continue;
693             if (!child->isSelfCollapsingBlock())
694                 return false;
695         }
696         return true;
697     }
698     return false;
699 }
700 
startDelayUpdateScrollInfo()701 void RenderBlock::startDelayUpdateScrollInfo()
702 {
703     if (gDelayUpdateScrollInfo == 0) {
704         ASSERT(!gDelayedUpdateScrollInfoSet);
705         gDelayedUpdateScrollInfoSet = new DelayedUpdateScrollInfoSet;
706     }
707     ASSERT(gDelayedUpdateScrollInfoSet);
708     ++gDelayUpdateScrollInfo;
709 }
710 
finishDelayUpdateScrollInfo()711 void RenderBlock::finishDelayUpdateScrollInfo()
712 {
713     --gDelayUpdateScrollInfo;
714     ASSERT(gDelayUpdateScrollInfo >= 0);
715     if (gDelayUpdateScrollInfo == 0) {
716         ASSERT(gDelayedUpdateScrollInfoSet);
717 
718         for (DelayedUpdateScrollInfoSet::iterator it = gDelayedUpdateScrollInfoSet->begin(); it != gDelayedUpdateScrollInfoSet->end(); ++it) {
719             RenderBlock* block = *it;
720             if (block->hasOverflowClip()) {
721                 block->layer()->updateScrollInfoAfterLayout();
722             }
723         }
724 
725         delete gDelayedUpdateScrollInfoSet;
726         gDelayedUpdateScrollInfoSet = 0;
727     }
728 }
729 
updateScrollInfoAfterLayout()730 void RenderBlock::updateScrollInfoAfterLayout()
731 {
732     if (hasOverflowClip()) {
733         if (gDelayUpdateScrollInfo)
734             gDelayedUpdateScrollInfoSet->add(this);
735         else
736             layer()->updateScrollInfoAfterLayout();
737     }
738 }
739 
layout()740 void RenderBlock::layout()
741 {
742     // Update our first letter info now.
743     updateFirstLetter();
744 
745     // Table cells call layoutBlock directly, so don't add any logic here.  Put code into
746     // layoutBlock().
747     layoutBlock(false);
748 
749     // It's safe to check for control clip here, since controls can never be table cells.
750     if (hasControlClip()) {
751         // Because of the lightweight clip, there can never be any overflow from children.
752         m_overflowWidth = width();
753         m_overflowHeight = height();
754         m_overflowLeft = 0;
755         m_overflowTop = 0;
756     }
757 }
758 
layoutBlock(bool relayoutChildren)759 void RenderBlock::layoutBlock(bool relayoutChildren)
760 {
761     ASSERT(needsLayout());
762 
763     if (isInline() && !isInlineBlockOrInlineTable()) // Inline <form>s inside various table elements can
764         return;                                      // cause us to come in here.  Just bail.
765 
766     if (!relayoutChildren && layoutOnlyPositionedObjects())
767         return;
768 
769     LayoutRepainter repainter(*this, m_everHadLayout && checkForRepaintDuringLayout());
770     LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection());
771 
772     int oldWidth = width();
773     int oldColumnWidth = desiredColumnWidth();
774 
775 #ifdef ANDROID_LAYOUT
776     int oldVisibleWidth = m_visibleWidth;
777 #endif
778 
779     calcWidth();
780     calcColumnWidth();
781 
782     m_overflowWidth = width();
783     m_overflowLeft = 0;
784 
785     if (oldWidth != width() || oldColumnWidth != desiredColumnWidth())
786         relayoutChildren = true;
787 
788 #ifdef ANDROID_LAYOUT
789     const Settings* settings = document()->settings();
790     ASSERT(settings);
791     if (oldVisibleWidth != m_visibleWidth
792             && settings->layoutAlgorithm() == Settings::kLayoutFitColumnToScreen)
793         relayoutChildren = true;
794 #endif
795 
796     clearFloats();
797 
798     int previousHeight = height();
799     setHeight(0);
800 
801     m_overflowHeight = 0;
802 
803     // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, to track
804     // our current maximal positive and negative margins.  These values are used when we
805     // are collapsed with adjacent blocks, so for example, if you have block A and B
806     // collapsing together, then you'd take the maximal positive margin from both A and B
807     // and subtract it from the maximal negative margin from both A and B to get the
808     // true collapsed margin.  This algorithm is recursive, so when we finish layout()
809     // our block knows its current maximal positive/negative values.
810     //
811     // Start out by setting our margin values to our current margins.  Table cells have
812     // no margins, so we don't fill in the values for table cells.
813     bool isCell = isTableCell();
814     if (!isCell) {
815         initMaxMarginValues();
816 
817         setTopMarginQuirk(style()->marginTop().quirk());
818         setBottomMarginQuirk(style()->marginBottom().quirk());
819 
820         Node* n = node();
821         if (n && n->hasTagName(formTag) && static_cast<HTMLFormElement*>(n)->isMalformed()) {
822             // See if this form is malformed (i.e., unclosed). If so, don't give the form
823             // a bottom margin.
824             setMaxBottomMargins(0, 0);
825         }
826     }
827 
828     // For overflow:scroll blocks, ensure we have both scrollbars in place always.
829     if (scrollsOverflow()) {
830         if (style()->overflowX() == OSCROLL)
831             layer()->setHasHorizontalScrollbar(true);
832         if (style()->overflowY() == OSCROLL)
833             layer()->setHasVerticalScrollbar(true);
834     }
835 
836     int repaintTop = 0;
837     int repaintBottom = 0;
838     int maxFloatBottom = 0;
839     if (childrenInline())
840         layoutInlineChildren(relayoutChildren, repaintTop, repaintBottom);
841     else
842         layoutBlockChildren(relayoutChildren, maxFloatBottom);
843 
844     // Expand our intrinsic height to encompass floats.
845     int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
846     if (floatBottom() > (height() - toAdd) && expandsToEncloseOverhangingFloats())
847         setHeight(floatBottom() + toAdd);
848 
849     // Now lay out our columns within this intrinsic height, since they can slightly affect the intrinsic height as
850     // we adjust for clean column breaks.
851     int singleColumnBottom = layoutColumns();
852 
853     // Calculate our new height.
854     int oldHeight = height();
855     calcHeight();
856     if (oldHeight != height()) {
857         if (oldHeight > height() && maxFloatBottom > height() && !childrenInline()) {
858             // One of our children's floats may have become an overhanging float for us. We need to look for it.
859             for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
860                 if (child->isBlockFlow() && !child->isFloatingOrPositioned()) {
861                     RenderBlock* block = toRenderBlock(child);
862                     if (block->floatBottom() + block->y() > height())
863                         addOverhangingFloats(block, -block->x(), -block->y(), false);
864                 }
865             }
866         }
867         // We have to rebalance columns to the new height.
868         layoutColumns(singleColumnBottom);
869 
870         // If the block got expanded in size, then increase our overflowheight to match.
871         if (m_overflowHeight > height())
872             m_overflowHeight -= toAdd;
873         if (m_overflowHeight < height())
874             m_overflowHeight = height();
875     }
876     if (previousHeight != height())
877         relayoutChildren = true;
878 
879     if ((isCell || isInline() || isFloatingOrPositioned() || isRoot()) && !hasOverflowClip() && !hasControlClip())
880         addVisualOverflow(floatRect());
881 
882     layoutPositionedObjects(relayoutChildren || isRoot());
883 
884     positionListMarker();
885 
886     // Always ensure our overflow width/height are at least as large as our width/height.
887     m_overflowWidth = max(m_overflowWidth, width());
888     m_overflowHeight = max(m_overflowHeight, height());
889 
890     if (!hasOverflowClip()) {
891         int shadowLeft;
892         int shadowRight;
893         int shadowTop;
894         int shadowBottom;
895         style()->getBoxShadowExtent(shadowTop, shadowRight, shadowBottom, shadowLeft);
896 
897         m_overflowLeft = min(m_overflowLeft, shadowLeft);
898         m_overflowWidth = max(m_overflowWidth, width() + shadowRight);
899         m_overflowTop = min(m_overflowTop, shadowTop);
900         m_overflowHeight = max(m_overflowHeight, height() + shadowBottom);
901 
902         if (hasReflection()) {
903             IntRect reflection(reflectionBox());
904             m_overflowLeft = min(m_overflowLeft, reflection.x());
905             m_overflowWidth = max(m_overflowWidth, reflection.right());
906             m_overflowTop = min(m_overflowTop, reflection.y());
907             m_overflowHeight = max(m_overflowHeight, reflection.bottom());
908         }
909     }
910 
911     statePusher.pop();
912 
913     // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
914     // we overflow or not.
915     updateScrollInfoAfterLayout();
916 
917     // Repaint with our new bounds if they are different from our old bounds.
918     bool didFullRepaint = repainter.repaintAfterLayout();
919     if (!didFullRepaint && repaintTop != repaintBottom && (style()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) {
920         IntRect repaintRect(m_overflowLeft, repaintTop, m_overflowWidth - m_overflowLeft, repaintBottom - repaintTop);
921 
922         // FIXME: Deal with multiple column repainting.  We have to split the repaint
923         // rect up into multiple rects if it spans columns.
924 
925         repaintRect.inflate(maximalOutlineSize(PaintPhaseOutline));
926 
927         if (hasOverflowClip()) {
928             // Adjust repaint rect for scroll offset
929             int x = repaintRect.x();
930             int y = repaintRect.y();
931             layer()->subtractScrolledContentOffset(x, y);
932             repaintRect.setX(x);
933             repaintRect.setY(y);
934 
935             // Don't allow this rect to spill out of our overflow box.
936             repaintRect.intersect(IntRect(0, 0, width(), height()));
937         }
938 
939         // Make sure the rect is still non-empty after intersecting for overflow above
940         if (!repaintRect.isEmpty()) {
941             repaintRectangle(repaintRect); // We need to do a partial repaint of our content.
942             if (hasReflection())
943                 repaintRectangle(reflectedRect(repaintRect));
944         }
945     }
946     setNeedsLayout(false);
947 }
948 
expandsToEncloseOverhangingFloats() const949 bool RenderBlock::expandsToEncloseOverhangingFloats() const
950 {
951     return isInlineBlockOrInlineTable() || isFloatingOrPositioned() || hasOverflowClip() || (parent() && parent()->isFlexibleBox()) || hasColumns() || isTableCell() || isFieldset();
952 }
953 
adjustPositionedBlock(RenderBox * child,const MarginInfo & marginInfo)954 void RenderBlock::adjustPositionedBlock(RenderBox* child, const MarginInfo& marginInfo)
955 {
956     if (child->style()->hasStaticX()) {
957         if (style()->direction() == LTR)
958             child->layer()->setStaticX(borderLeft() + paddingLeft());
959         else
960             child->layer()->setStaticX(borderRight() + paddingRight());
961     }
962 
963     if (child->style()->hasStaticY()) {
964         int y = height();
965         if (!marginInfo.canCollapseWithTop()) {
966             child->calcVerticalMargins();
967             int marginTop = child->marginTop();
968             int collapsedTopPos = marginInfo.posMargin();
969             int collapsedTopNeg = marginInfo.negMargin();
970             if (marginTop > 0) {
971                 if (marginTop > collapsedTopPos)
972                     collapsedTopPos = marginTop;
973             } else {
974                 if (-marginTop > collapsedTopNeg)
975                     collapsedTopNeg = -marginTop;
976             }
977             y += (collapsedTopPos - collapsedTopNeg) - marginTop;
978         }
979         child->layer()->setStaticY(y);
980     }
981 }
982 
adjustFloatingBlock(const MarginInfo & marginInfo)983 void RenderBlock::adjustFloatingBlock(const MarginInfo& marginInfo)
984 {
985     // The float should be positioned taking into account the bottom margin
986     // of the previous flow.  We add that margin into the height, get the
987     // float positioned properly, and then subtract the margin out of the
988     // height again.  In the case of self-collapsing blocks, we always just
989     // use the top margins, since the self-collapsing block collapsed its
990     // own bottom margin into its top margin.
991     //
992     // Note also that the previous flow may collapse its margin into the top of
993     // our block.  If this is the case, then we do not add the margin in to our
994     // height when computing the position of the float.   This condition can be tested
995     // for by simply calling canCollapseWithTop.  See
996     // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for
997     // an example of this scenario.
998     int marginOffset = marginInfo.canCollapseWithTop() ? 0 : marginInfo.margin();
999     setHeight(height() + marginOffset);
1000     positionNewFloats();
1001     setHeight(height() - marginOffset);
1002 }
1003 
handleSpecialChild(RenderBox * child,const MarginInfo & marginInfo)1004 bool RenderBlock::handleSpecialChild(RenderBox* child, const MarginInfo& marginInfo)
1005 {
1006     // Handle in the given order
1007     return handlePositionedChild(child, marginInfo)
1008         || handleFloatingChild(child, marginInfo)
1009         || handleRunInChild(child);
1010 }
1011 
1012 
handlePositionedChild(RenderBox * child,const MarginInfo & marginInfo)1013 bool RenderBlock::handlePositionedChild(RenderBox* child, const MarginInfo& marginInfo)
1014 {
1015     if (child->isPositioned()) {
1016         child->containingBlock()->insertPositionedObject(child);
1017         adjustPositionedBlock(child, marginInfo);
1018         return true;
1019     }
1020     return false;
1021 }
1022 
handleFloatingChild(RenderBox * child,const MarginInfo & marginInfo)1023 bool RenderBlock::handleFloatingChild(RenderBox* child, const MarginInfo& marginInfo)
1024 {
1025     if (child->isFloating()) {
1026         insertFloatingObject(child);
1027         adjustFloatingBlock(marginInfo);
1028         return true;
1029     }
1030     return false;
1031 }
1032 
handleRunInChild(RenderBox * child)1033 bool RenderBlock::handleRunInChild(RenderBox* child)
1034 {
1035     // See if we have a run-in element with inline children.  If the
1036     // children aren't inline, then just treat the run-in as a normal
1037     // block.
1038     if (!child->isRunIn() || !child->childrenInline() && !child->isReplaced())
1039         return false;
1040 
1041     // Get the next non-positioned/non-floating RenderBlock.
1042     RenderBlock* blockRunIn = toRenderBlock(child);
1043     RenderObject* curr = blockRunIn->nextSibling();
1044     while (curr && curr->isFloatingOrPositioned())
1045         curr = curr->nextSibling();
1046 
1047     if (!curr || !curr->isRenderBlock() || !curr->childrenInline() || curr->isRunIn() || curr->isAnonymous())
1048         return false;
1049 
1050     RenderBlock* currBlock = toRenderBlock(curr);
1051 
1052     // Remove the old child.
1053     children()->removeChildNode(this, blockRunIn);
1054 
1055     // Create an inline.
1056     Node* runInNode = blockRunIn->node();
1057     RenderInline* inlineRunIn = new (renderArena()) RenderInline(runInNode ? runInNode : document());
1058     inlineRunIn->setStyle(blockRunIn->style());
1059 
1060     bool runInIsGenerated = child->style()->styleType() == BEFORE || child->style()->styleType() == AFTER;
1061 
1062     // Move the nodes from the old child to the new child, but skip any :before/:after content.  It has already
1063     // been regenerated by the new inline.
1064     for (RenderObject* runInChild = blockRunIn->firstChild(); runInChild; runInChild = runInChild->nextSibling()) {
1065         if (runInIsGenerated || runInChild->style()->styleType() != BEFORE && runInChild->style()->styleType() != AFTER) {
1066             blockRunIn->children()->removeChildNode(blockRunIn, runInChild, false);
1067             inlineRunIn->addChild(runInChild); // Use addChild instead of appendChildNode since it handles correct placement of the children relative to :after-generated content.
1068         }
1069     }
1070 
1071     // Now insert the new child under |currBlock|.
1072     currBlock->children()->insertChildNode(currBlock, inlineRunIn, currBlock->firstChild());
1073 
1074     // If the run-in had an element, we need to set the new renderer.
1075     if (runInNode)
1076         runInNode->setRenderer(inlineRunIn);
1077 
1078     // Destroy the block run-in.
1079     blockRunIn->destroy();
1080 
1081     // The block acts like an inline, so just null out its
1082     // position.
1083 
1084     return true;
1085 }
1086 
collapseMargins(RenderBox * child,MarginInfo & marginInfo)1087 int RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
1088 {
1089     // Get our max pos and neg top margins.
1090     int posTop = child->maxTopMargin(true);
1091     int negTop = child->maxTopMargin(false);
1092 
1093     // For self-collapsing blocks, collapse our bottom margins into our
1094     // top to get new posTop and negTop values.
1095     if (child->isSelfCollapsingBlock()) {
1096         posTop = max(posTop, child->maxBottomMargin(true));
1097         negTop = max(negTop, child->maxBottomMargin(false));
1098     }
1099 
1100     // See if the top margin is quirky. We only care if this child has
1101     // margins that will collapse with us.
1102     bool topQuirk = child->isTopMarginQuirk() || style()->marginTopCollapse() == MDISCARD;
1103 
1104     if (marginInfo.canCollapseWithTop()) {
1105         // This child is collapsing with the top of the
1106         // block.  If it has larger margin values, then we need to update
1107         // our own maximal values.
1108         if (!style()->htmlHacks() || !marginInfo.quirkContainer() || !topQuirk)
1109             setMaxTopMargins(max(posTop, maxTopPosMargin()), max(negTop, maxTopNegMargin()));
1110 
1111         // The minute any of the margins involved isn't a quirk, don't
1112         // collapse it away, even if the margin is smaller (www.webreference.com
1113         // has an example of this, a <dt> with 0.8em author-specified inside
1114         // a <dl> inside a <td>.
1115         if (!marginInfo.determinedTopQuirk() && !topQuirk && (posTop-negTop)) {
1116             setTopMarginQuirk(false);
1117             marginInfo.setDeterminedTopQuirk(true);
1118         }
1119 
1120         if (!marginInfo.determinedTopQuirk() && topQuirk && marginTop() == 0)
1121             // We have no top margin and our top child has a quirky margin.
1122             // We will pick up this quirky margin and pass it through.
1123             // This deals with the <td><div><p> case.
1124             // Don't do this for a block that split two inlines though.  You do
1125             // still apply margins in this case.
1126             setTopMarginQuirk(true);
1127     }
1128 
1129     if (marginInfo.quirkContainer() && marginInfo.atTopOfBlock() && (posTop - negTop))
1130         marginInfo.setTopQuirk(topQuirk);
1131 
1132     int ypos = height();
1133     if (child->isSelfCollapsingBlock()) {
1134         // This child has no height.  We need to compute our
1135         // position before we collapse the child's margins together,
1136         // so that we can get an accurate position for the zero-height block.
1137         int collapsedTopPos = max(marginInfo.posMargin(), child->maxTopMargin(true));
1138         int collapsedTopNeg = max(marginInfo.negMargin(), child->maxTopMargin(false));
1139         marginInfo.setMargin(collapsedTopPos, collapsedTopNeg);
1140 
1141         // Now collapse the child's margins together, which means examining our
1142         // bottom margin values as well.
1143         marginInfo.setPosMarginIfLarger(child->maxBottomMargin(true));
1144         marginInfo.setNegMarginIfLarger(child->maxBottomMargin(false));
1145 
1146         if (!marginInfo.canCollapseWithTop())
1147             // We need to make sure that the position of the self-collapsing block
1148             // is correct, since it could have overflowing content
1149             // that needs to be positioned correctly (e.g., a block that
1150             // had a specified height of 0 but that actually had subcontent).
1151             ypos = height() + collapsedTopPos - collapsedTopNeg;
1152     }
1153     else {
1154         if (child->style()->marginTopCollapse() == MSEPARATE) {
1155             setHeight(height() + marginInfo.margin() + child->marginTop());
1156             ypos = height();
1157         }
1158         else if (!marginInfo.atTopOfBlock() ||
1159             (!marginInfo.canCollapseTopWithChildren()
1160              && (!style()->htmlHacks() || !marginInfo.quirkContainer() || !marginInfo.topQuirk()))) {
1161             // We're collapsing with a previous sibling's margins and not
1162             // with the top of the block.
1163             setHeight(height() + max(marginInfo.posMargin(), posTop) - max(marginInfo.negMargin(), negTop));
1164             ypos = height();
1165         }
1166 
1167         marginInfo.setPosMargin(child->maxBottomMargin(true));
1168         marginInfo.setNegMargin(child->maxBottomMargin(false));
1169 
1170         if (marginInfo.margin())
1171             marginInfo.setBottomQuirk(child->isBottomMarginQuirk() || style()->marginBottomCollapse() == MDISCARD);
1172 
1173         marginInfo.setSelfCollapsingBlockClearedFloat(false);
1174     }
1175 
1176     return ypos;
1177 }
1178 
clearFloatsIfNeeded(RenderBox * child,MarginInfo & marginInfo,int oldTopPosMargin,int oldTopNegMargin,int yPos)1179 int RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, int oldTopPosMargin, int oldTopNegMargin, int yPos)
1180 {
1181     int heightIncrease = getClearDelta(child, yPos);
1182     if (!heightIncrease)
1183         return yPos;
1184 
1185     if (child->isSelfCollapsingBlock()) {
1186         // For self-collapsing blocks that clear, they can still collapse their
1187         // margins with following siblings.  Reset the current margins to represent
1188         // the self-collapsing block's margins only.
1189         marginInfo.setPosMargin(max(child->maxTopMargin(true), child->maxBottomMargin(true)));
1190         marginInfo.setNegMargin(max(child->maxTopMargin(false), child->maxBottomMargin(false)));
1191 
1192         // Adjust our height such that we are ready to be collapsed with subsequent siblings.
1193         setHeight(child->y() - max(0, marginInfo.margin()));
1194 
1195         // Set a flag that we cleared a float so that we know both to increase the height of the block
1196         // to compensate for the clear and to avoid collapsing our margins with the parent block's
1197         // bottom margin.
1198         marginInfo.setSelfCollapsingBlockClearedFloat(true);
1199     } else
1200         // Increase our height by the amount we had to clear.
1201         setHeight(height() + heightIncrease);
1202 
1203     if (marginInfo.canCollapseWithTop()) {
1204         // We can no longer collapse with the top of the block since a clear
1205         // occurred.  The empty blocks collapse into the cleared block.
1206         // FIXME: This isn't quite correct.  Need clarification for what to do
1207         // if the height the cleared block is offset by is smaller than the
1208         // margins involved.
1209         setMaxTopMargins(oldTopPosMargin, oldTopNegMargin);
1210         marginInfo.setAtTopOfBlock(false);
1211     }
1212 
1213     return yPos + heightIncrease;
1214 }
1215 
estimateVerticalPosition(RenderBox * child,const MarginInfo & marginInfo)1216 int RenderBlock::estimateVerticalPosition(RenderBox* child, const MarginInfo& marginInfo)
1217 {
1218     // FIXME: We need to eliminate the estimation of vertical position, because when it's wrong we sometimes trigger a pathological
1219     // relayout if there are intruding floats.
1220     int yPosEstimate = height();
1221     if (!marginInfo.canCollapseWithTop()) {
1222         int childMarginTop = child->selfNeedsLayout() ? child->marginTop() : child->collapsedMarginTop();
1223         yPosEstimate += max(marginInfo.margin(), childMarginTop);
1224     }
1225     yPosEstimate += getClearDelta(child, yPosEstimate);
1226     return yPosEstimate;
1227 }
1228 
determineHorizontalPosition(RenderBox * child)1229 void RenderBlock::determineHorizontalPosition(RenderBox* child)
1230 {
1231     if (style()->direction() == LTR) {
1232         int xPos = borderLeft() + paddingLeft();
1233 
1234         // Add in our left margin.
1235         int chPos = xPos + child->marginLeft();
1236 
1237         // Some objects (e.g., tables, horizontal rules, overflow:auto blocks) avoid floats.  They need
1238         // to shift over as necessary to dodge any floats that might get in the way.
1239         if (child->avoidsFloats()) {
1240             int leftOff = leftOffset(height(), false);
1241             if (style()->textAlign() != WEBKIT_CENTER && child->style()->marginLeft().type() != Auto) {
1242                 if (child->marginLeft() < 0)
1243                     leftOff += child->marginLeft();
1244                 chPos = max(chPos, leftOff); // Let the float sit in the child's margin if it can fit.
1245             }
1246             else if (leftOff != xPos) {
1247                 // The object is shifting right. The object might be centered, so we need to
1248                 // recalculate our horizontal margins. Note that the containing block content
1249                 // width computation will take into account the delta between |leftOff| and |xPos|
1250                 // so that we can just pass the content width in directly to the |calcHorizontalMargins|
1251                 // function.
1252                 child->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->y(), false));
1253                 chPos = leftOff + child->marginLeft();
1254             }
1255         }
1256         view()->addLayoutDelta(IntSize(child->x() - chPos, 0));
1257         child->setLocation(chPos, child->y());
1258     } else {
1259         int xPos = width() - borderRight() - paddingRight() - verticalScrollbarWidth();
1260         int chPos = xPos - (child->width() + child->marginRight());
1261         if (child->avoidsFloats()) {
1262             int rightOff = rightOffset(height(), false);
1263             if (style()->textAlign() != WEBKIT_CENTER && child->style()->marginRight().type() != Auto) {
1264                 if (child->marginRight() < 0)
1265                     rightOff -= child->marginRight();
1266                 chPos = min(chPos, rightOff - child->width()); // Let the float sit in the child's margin if it can fit.
1267             } else if (rightOff != xPos) {
1268                 // The object is shifting left. The object might be centered, so we need to
1269                 // recalculate our horizontal margins. Note that the containing block content
1270                 // width computation will take into account the delta between |rightOff| and |xPos|
1271                 // so that we can just pass the content width in directly to the |calcHorizontalMargins|
1272                 // function.
1273                 child->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->y(), false));
1274                 chPos = rightOff - child->marginRight() - child->width();
1275             }
1276         }
1277         view()->addLayoutDelta(IntSize(child->x() - chPos, 0));
1278         child->setLocation(chPos, child->y());
1279     }
1280 }
1281 
setCollapsedBottomMargin(const MarginInfo & marginInfo)1282 void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo)
1283 {
1284     if (marginInfo.canCollapseWithBottom() && !marginInfo.canCollapseWithTop()) {
1285         // Update our max pos/neg bottom margins, since we collapsed our bottom margins
1286         // with our children.
1287         setMaxBottomMargins(max(maxBottomPosMargin(), marginInfo.posMargin()), max(maxBottomNegMargin(), marginInfo.negMargin()));
1288 
1289         if (!marginInfo.bottomQuirk())
1290             setBottomMarginQuirk(false);
1291 
1292         if (marginInfo.bottomQuirk() && marginBottom() == 0)
1293             // We have no bottom margin and our last child has a quirky margin.
1294             // We will pick up this quirky margin and pass it through.
1295             // This deals with the <td><div><p> case.
1296             setBottomMarginQuirk(true);
1297     }
1298 }
1299 
handleBottomOfBlock(int top,int bottom,MarginInfo & marginInfo)1300 void RenderBlock::handleBottomOfBlock(int top, int bottom, MarginInfo& marginInfo)
1301 {
1302     // If our last flow was a self-collapsing block that cleared a float, then we don't
1303     // collapse it with the bottom of the block.
1304     if (!marginInfo.selfCollapsingBlockClearedFloat())
1305         marginInfo.setAtBottomOfBlock(true);
1306     else {
1307         // We have to special case the negative margin situation (where the collapsed
1308         // margin of the self-collapsing block is negative), since there's no need
1309         // to make an adjustment in that case.
1310         if (marginInfo.margin() < 0)
1311             marginInfo.clearMargin();
1312     }
1313 
1314     // If we can't collapse with children then go ahead and add in the bottom margin.
1315     if (!marginInfo.canCollapseWithBottom() && !marginInfo.canCollapseWithTop()
1316         && (!style()->htmlHacks() || !marginInfo.quirkContainer() || !marginInfo.bottomQuirk()))
1317         setHeight(height() + marginInfo.margin());
1318 
1319     // Now add in our bottom border/padding.
1320     setHeight(height() + bottom);
1321 
1322     // Negative margins can cause our height to shrink below our minimal height (border/padding).
1323     // If this happens, ensure that the computed height is increased to the minimal height.
1324     setHeight(max(height(), top + bottom));
1325 
1326     // Always make sure our overflow height is at least our height.
1327     m_overflowHeight = max(height(), m_overflowHeight);
1328 
1329     // Update our bottom collapsed margin info.
1330     setCollapsedBottomMargin(marginInfo);
1331 }
1332 
layoutBlockChildren(bool relayoutChildren,int & maxFloatBottom)1333 void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom)
1334 {
1335     if (gPercentHeightDescendantsMap) {
1336         if (HashSet<RenderBox*>* descendants = gPercentHeightDescendantsMap->get(this)) {
1337             HashSet<RenderBox*>::iterator end = descendants->end();
1338             for (HashSet<RenderBox*>::iterator it = descendants->begin(); it != end; ++it) {
1339                 RenderBox* box = *it;
1340                 while (box != this) {
1341                     if (box->normalChildNeedsLayout())
1342                         break;
1343                     box->setChildNeedsLayout(true, false);
1344                     box = box->containingBlock();
1345                     ASSERT(box);
1346                     if (!box)
1347                         break;
1348                 }
1349             }
1350         }
1351     }
1352 
1353     int top = borderTop() + paddingTop();
1354     int bottom = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
1355 
1356     m_overflowHeight = top;
1357     setHeight(m_overflowHeight);
1358 
1359     // The margin struct caches all our current margin collapsing state.  The compact struct caches state when we encounter compacts,
1360     MarginInfo marginInfo(this, top, bottom);
1361 
1362     // Fieldsets need to find their legend and position it inside the border of the object.
1363     // The legend then gets skipped during normal layout.
1364     RenderObject* legend = layoutLegend(relayoutChildren);
1365 
1366     int previousFloatBottom = 0;
1367     maxFloatBottom = 0;
1368 
1369     RenderBox* next = firstChildBox();
1370 
1371     while (next) {
1372         RenderBox* child = next;
1373         next = child->nextSiblingBox();
1374 
1375         if (legend == child)
1376             continue; // Skip the legend, since it has already been positioned up in the fieldset's border.
1377 
1378         int oldTopPosMargin = maxTopPosMargin();
1379         int oldTopNegMargin = maxTopNegMargin();
1380 
1381         // Make sure we layout children if they need it.
1382         // FIXME: Technically percentage height objects only need a relayout if their percentage isn't going to be turned into
1383         // an auto value.  Add a method to determine this, so that we can avoid the relayout.
1384         if (relayoutChildren || ((child->style()->height().isPercent() || child->style()->minHeight().isPercent() || child->style()->maxHeight().isPercent()) && !isRenderView()))
1385             child->setChildNeedsLayout(true, false);
1386 
1387         // If relayoutChildren is set and we have percentage padding, we also need to invalidate the child's pref widths.
1388         if (relayoutChildren && (child->style()->paddingLeft().isPercent() || child->style()->paddingRight().isPercent()))
1389             child->setPrefWidthsDirty(true, false);
1390 
1391         // Handle the four types of special elements first.  These include positioned content, floating content, compacts and
1392         // run-ins.  When we encounter these four types of objects, we don't actually lay them out as normal flow blocks.
1393         if (handleSpecialChild(child, marginInfo))
1394             continue;
1395 
1396         // The child is a normal flow object.  Compute its vertical margins now.
1397         child->calcVerticalMargins();
1398 
1399         // Do not allow a collapse if the margin top collapse style is set to SEPARATE.
1400         if (child->style()->marginTopCollapse() == MSEPARATE) {
1401             marginInfo.setAtTopOfBlock(false);
1402             marginInfo.clearMargin();
1403         }
1404 
1405         // Try to guess our correct y position.  In most cases this guess will
1406         // be correct.  Only if we're wrong (when we compute the real y position)
1407         // will we have to potentially relayout.
1408         int yPosEstimate = estimateVerticalPosition(child, marginInfo);
1409 
1410         // Cache our old rect so that we can dirty the proper repaint rects if the child moves.
1411         IntRect oldRect(child->x(), child->y() , child->width(), child->height());
1412 #ifndef NDEBUG
1413         IntSize oldLayoutDelta = view()->layoutDelta();
1414 #endif
1415         // Go ahead and position the child as though it didn't collapse with the top.
1416         view()->addLayoutDelta(IntSize(0, child->y() - yPosEstimate));
1417         child->setLocation(child->x(), yPosEstimate);
1418 
1419         bool markDescendantsWithFloats = false;
1420         if (yPosEstimate != oldRect.y() && !child->avoidsFloats() && child->isBlockFlow() && toRenderBlock(child)->containsFloats())
1421             markDescendantsWithFloats = true;
1422         else if (!child->avoidsFloats() || child->shrinkToAvoidFloats()) {
1423             // If an element might be affected by the presence of floats, then always mark it for
1424             // layout.
1425             int fb = max(previousFloatBottom, floatBottom());
1426             if (fb > yPosEstimate)
1427                 markDescendantsWithFloats = true;
1428         }
1429 
1430         if (child->isRenderBlock()) {
1431             if (markDescendantsWithFloats)
1432                 toRenderBlock(child)->markAllDescendantsWithFloatsForLayout();
1433 
1434             previousFloatBottom = max(previousFloatBottom, oldRect.y() + toRenderBlock(child)->floatBottom());
1435         }
1436 
1437         bool childHadLayout = child->m_everHadLayout;
1438         bool childNeededLayout = child->needsLayout();
1439         if (childNeededLayout)
1440             child->layout();
1441 
1442         // Now determine the correct ypos based off examination of collapsing margin
1443         // values.
1444         int yBeforeClear = collapseMargins(child, marginInfo);
1445 
1446         // Now check for clear.
1447         int yAfterClear = clearFloatsIfNeeded(child, marginInfo, oldTopPosMargin, oldTopNegMargin, yBeforeClear);
1448 
1449         view()->addLayoutDelta(IntSize(0, yPosEstimate - yAfterClear));
1450         child->setLocation(child->x(), yAfterClear);
1451 
1452         // Now we have a final y position.  See if it really does end up being different from our estimate.
1453         if (yAfterClear != yPosEstimate) {
1454             if (child->shrinkToAvoidFloats()) {
1455                 // The child's width depends on the line width.
1456                 // When the child shifts to clear an item, its width can
1457                 // change (because it has more available line width).
1458                 // So go ahead and mark the item as dirty.
1459                 child->setChildNeedsLayout(true, false);
1460             }
1461             if (!child->avoidsFloats() && child->isBlockFlow() && toRenderBlock(child)->containsFloats())
1462                 toRenderBlock(child)->markAllDescendantsWithFloatsForLayout();
1463             // Our guess was wrong. Make the child lay itself out again.
1464             child->layoutIfNeeded();
1465         }
1466 
1467         // We are no longer at the top of the block if we encounter a non-empty child.
1468         // This has to be done after checking for clear, so that margins can be reset if a clear occurred.
1469         if (marginInfo.atTopOfBlock() && !child->isSelfCollapsingBlock())
1470             marginInfo.setAtTopOfBlock(false);
1471 
1472         // Now place the child in the correct horizontal position
1473         determineHorizontalPosition(child);
1474 
1475         // Update our height now that the child has been placed in the correct position.
1476         setHeight(height() + child->height());
1477         if (child->style()->marginBottomCollapse() == MSEPARATE) {
1478             setHeight(height() + child->marginBottom());
1479             marginInfo.clearMargin();
1480         }
1481         // If the child has overhanging floats that intrude into following siblings (or possibly out
1482         // of this block), then the parent gets notified of the floats now.
1483         if (child->isBlockFlow() && toRenderBlock(child)->containsFloats())
1484             maxFloatBottom = max(maxFloatBottom, addOverhangingFloats(toRenderBlock(child), -child->x(), -child->y(), !childNeededLayout));
1485 
1486         // Update our visual overflow in case the child spills out the block, but only if we were going to paint
1487         // the child block ourselves.
1488         if (!child->hasSelfPaintingLayer()) {
1489             m_overflowTop = min(m_overflowTop, child->y() + child->overflowTop(false));
1490             m_overflowHeight = max(m_overflowHeight, height() + child->overflowHeight(false) - child->height());
1491             m_overflowWidth = max(child->x() + child->overflowWidth(false), m_overflowWidth);
1492             m_overflowLeft = min(child->x() + child->overflowLeft(false), m_overflowLeft);
1493         }
1494 
1495         IntSize childOffset(child->x() - oldRect.x(), child->y() - oldRect.y());
1496         if (childOffset.width() || childOffset.height()) {
1497             view()->addLayoutDelta(childOffset);
1498 
1499             // If the child moved, we have to repaint it as well as any floating/positioned
1500             // descendants.  An exception is if we need a layout.  In this case, we know we're going to
1501             // repaint ourselves (and the child) anyway.
1502             if (childHadLayout && !selfNeedsLayout() && child->checkForRepaintDuringLayout())
1503                 child->repaintDuringLayoutIfMoved(oldRect);
1504         }
1505 
1506         if (!childHadLayout && child->checkForRepaintDuringLayout()) {
1507             child->repaint();
1508             child->repaintOverhangingFloats(true);
1509         }
1510 
1511         ASSERT(oldLayoutDelta == view()->layoutDelta());
1512     }
1513 
1514     // Now do the handling of the bottom of the block, adding in our bottom border/padding and
1515     // determining the correct collapsed bottom margin information.
1516     handleBottomOfBlock(top, bottom, marginInfo);
1517 }
1518 
layoutOnlyPositionedObjects()1519 bool RenderBlock::layoutOnlyPositionedObjects()
1520 {
1521     if (!posChildNeedsLayout() || normalChildNeedsLayout() || selfNeedsLayout())
1522         return false;
1523 
1524     LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection());
1525 
1526     if (needsPositionedMovementLayout()) {
1527         tryLayoutDoingPositionedMovementOnly();
1528         if (needsLayout())
1529             return false;
1530     }
1531 
1532     // All we have to is lay out our positioned objects.
1533     layoutPositionedObjects(false);
1534 
1535     statePusher.pop();
1536 
1537     updateScrollInfoAfterLayout();
1538 
1539 #ifdef ANDROID_FIX
1540     // iframe flatten will call FrameView::layout() which calls performPostLayoutTasks,
1541     // which may make us need to layout again
1542     if (!posChildNeedsLayout() || normalChildNeedsLayout() || selfNeedsLayout())
1543         return false;
1544 #endif
1545 
1546     setNeedsLayout(false);
1547     return true;
1548 }
1549 
layoutPositionedObjects(bool relayoutChildren)1550 void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
1551 {
1552     if (m_positionedObjects) {
1553         RenderBox* r;
1554         Iterator end = m_positionedObjects->end();
1555         for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
1556             r = *it;
1557             // When a non-positioned block element moves, it may have positioned children that are implicitly positioned relative to the
1558             // non-positioned block.  Rather than trying to detect all of these movement cases, we just always lay out positioned
1559             // objects that are positioned implicitly like this.  Such objects are rare, and so in typical DHTML menu usage (where everything is
1560             // positioned explicitly) this should not incur a performance penalty.
1561             if (relayoutChildren || (r->style()->hasStaticY() && r->parent() != this && r->parent()->isBlockFlow()))
1562                 r->setChildNeedsLayout(true, false);
1563 
1564             // If relayoutChildren is set and we have percentage padding, we also need to invalidate the child's pref widths.
1565             //if (relayoutChildren && (r->style()->paddingLeft().isPercent() || r->style()->paddingRight().isPercent()))
1566                 r->setPrefWidthsDirty(true, false);
1567 
1568             // 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
1569             // and we hit the available width constraint, the layoutIfNeeded() will catch it and do a full layout.
1570             if (r->needsPositionedMovementLayoutOnly())
1571                 r->tryLayoutDoingPositionedMovementOnly();
1572             r->layoutIfNeeded();
1573         }
1574     }
1575 }
1576 
markPositionedObjectsForLayout()1577 void RenderBlock::markPositionedObjectsForLayout()
1578 {
1579     if (m_positionedObjects) {
1580         RenderBox* r;
1581         Iterator end = m_positionedObjects->end();
1582         for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
1583             r = *it;
1584             r->setChildNeedsLayout(true);
1585         }
1586     }
1587 }
1588 
repaintOverhangingFloats(bool paintAllDescendants)1589 void RenderBlock::repaintOverhangingFloats(bool paintAllDescendants)
1590 {
1591     // Repaint any overhanging floats (if we know we're the one to paint them).
1592     if (hasOverhangingFloats()) {
1593         // We think that we must be in a bad state if m_floatingObjects is nil at this point, so
1594         // we assert on Debug builds and nil-check Release builds.
1595         ASSERT(m_floatingObjects);
1596         if (!m_floatingObjects)
1597             return;
1598 
1599         FloatingObject* r;
1600         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
1601 
1602         // FIXME: Avoid disabling LayoutState. At the very least, don't disable it for floats originating
1603         // in this block. Better yet would be to push extra state for the containers of other floats.
1604         view()->disableLayoutState();
1605         for ( ; (r = it.current()); ++it) {
1606             // Only repaint the object if it is overhanging, is not in its own layer, and
1607             // is our responsibility to paint (m_shouldPaint is set). When paintAllDescendants is true, the latter
1608             // condition is replaced with being a descendant of us.
1609             if (r->m_bottom > height() && ((paintAllDescendants && r->m_renderer->isDescendantOf(this)) || r->m_shouldPaint) && !r->m_renderer->hasSelfPaintingLayer()) {
1610                 r->m_renderer->repaint();
1611                 r->m_renderer->repaintOverhangingFloats();
1612             }
1613         }
1614         view()->enableLayoutState();
1615     }
1616 }
1617 
paint(PaintInfo & paintInfo,int tx,int ty)1618 void RenderBlock::paint(PaintInfo& paintInfo, int tx, int ty)
1619 {
1620     tx += x();
1621     ty += y();
1622 
1623     PaintPhase phase = paintInfo.phase;
1624 
1625     // Check if we need to do anything at all.
1626     // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
1627     // paints the root's background.
1628     if (!isRoot()) {
1629         IntRect overflowBox = overflowRect(false);
1630         overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
1631         overflowBox.move(tx, ty);
1632         if (!overflowBox.intersects(paintInfo.rect))
1633             return;
1634     }
1635 
1636     bool pushedClip = pushContentsClip(paintInfo, tx, ty);
1637     paintObject(paintInfo, tx, ty);
1638     if (pushedClip)
1639         popContentsClip(paintInfo, phase, tx, ty);
1640 
1641     // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
1642     // z-index.  We paint after we painted the background/border, so that the scrollbars will
1643     // sit above the background/border.
1644     if (hasOverflowClip() && style()->visibility() == VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground))
1645         layer()->paintOverflowControls(paintInfo.context, tx, ty, paintInfo.rect);
1646 }
1647 
paintColumnRules(PaintInfo & paintInfo,int tx,int ty)1648 void RenderBlock::paintColumnRules(PaintInfo& paintInfo, int tx, int ty)
1649 {
1650     const Color& ruleColor = style()->columnRuleColor();
1651     bool ruleTransparent = style()->columnRuleIsTransparent();
1652     EBorderStyle ruleStyle = style()->columnRuleStyle();
1653     int ruleWidth = style()->columnRuleWidth();
1654     int colGap = columnGap();
1655     bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent && ruleWidth <= colGap;
1656     if (!renderRule)
1657         return;
1658 
1659     // We need to do multiple passes, breaking up our child painting into strips.
1660     int currXOffset = 0;
1661     int ruleAdd = borderLeft() + paddingLeft();
1662     int ruleX = 0;
1663     Vector<IntRect>* colRects = columnRects();
1664     unsigned colCount = colRects->size();
1665     for (unsigned i = 0; i < colCount; i++) {
1666         // For each rect, we clip to the rect, and then we adjust our coords.
1667         IntRect colRect = colRects->at(i);
1668 
1669         // Move to the next position.
1670         if (style()->direction() == LTR) {
1671             ruleX += colRect.width() + colGap / 2;
1672             currXOffset += colRect.width() + colGap;
1673         } else {
1674             ruleX -= (colRect.width() + colGap / 2);
1675             currXOffset -= (colRect.width() + colGap);
1676         }
1677 
1678         // Now paint the column rule.
1679         if (i < colCount - 1) {
1680             int ruleStart = tx + ruleX - ruleWidth / 2 + ruleAdd;
1681             int ruleEnd = ruleStart + ruleWidth;
1682             int ruleTop = ty + borderTop() + paddingTop();
1683             int ruleBottom = ruleTop + contentHeight();
1684             drawLineForBoxSide(paintInfo.context, ruleStart, ruleTop, ruleEnd, ruleBottom,
1685                                style()->direction() == LTR ? BSLeft : BSRight, ruleColor, style()->color(), ruleStyle, 0, 0);
1686         }
1687 
1688         ruleX = currXOffset;
1689     }
1690 }
1691 
paintColumnContents(PaintInfo & paintInfo,int tx,int ty,bool paintingFloats)1692 void RenderBlock::paintColumnContents(PaintInfo& paintInfo, int tx, int ty, bool paintingFloats)
1693 {
1694     // We need to do multiple passes, breaking up our child painting into strips.
1695     GraphicsContext* context = paintInfo.context;
1696     int currXOffset = 0;
1697     int currYOffset = 0;
1698     int colGap = columnGap();
1699     Vector<IntRect>* colRects = columnRects();
1700     unsigned colCount = colRects->size();
1701     for (unsigned i = 0; i < colCount; i++) {
1702         // For each rect, we clip to the rect, and then we adjust our coords.
1703         IntRect colRect = colRects->at(i);
1704         colRect.move(tx, ty);
1705         context->save();
1706 
1707         // Each strip pushes a clip, since column boxes are specified as being
1708         // like overflow:hidden.
1709         context->clip(colRect);
1710 
1711         // Adjust tx and ty to change where we paint.
1712         PaintInfo info(paintInfo);
1713         info.rect.intersect(colRect);
1714 
1715         // Adjust our x and y when painting.
1716         int finalX = tx + currXOffset;
1717         int finalY = ty + currYOffset;
1718         if (paintingFloats)
1719             paintFloats(info, finalX, finalY, paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip);
1720         else
1721             paintContents(info, finalX, finalY);
1722 
1723         // Move to the next position.
1724         if (style()->direction() == LTR)
1725             currXOffset += colRect.width() + colGap;
1726         else
1727             currXOffset -= (colRect.width() + colGap);
1728 
1729         currYOffset -= colRect.height();
1730 
1731         context->restore();
1732     }
1733 }
1734 
paintContents(PaintInfo & paintInfo,int tx,int ty)1735 void RenderBlock::paintContents(PaintInfo& paintInfo, int tx, int ty)
1736 {
1737     // Avoid painting descendants of the root element when stylesheets haven't loaded.  This eliminates FOUC.
1738     // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
1739     // will do a full repaint().
1740     if (document()->didLayoutWithPendingStylesheets() && !isRenderView())
1741         return;
1742 
1743     if (childrenInline())
1744         m_lineBoxes.paint(this, paintInfo, tx, ty);
1745     else
1746         paintChildren(paintInfo, tx, ty);
1747 }
1748 
paintChildren(PaintInfo & paintInfo,int tx,int ty)1749 void RenderBlock::paintChildren(PaintInfo& paintInfo, int tx, int ty)
1750 {
1751     PaintPhase newPhase = (paintInfo.phase == PaintPhaseChildOutlines) ? PaintPhaseOutline : paintInfo.phase;
1752     newPhase = (newPhase == PaintPhaseChildBlockBackgrounds) ? PaintPhaseChildBlockBackground : newPhase;
1753 
1754     // We don't paint our own background, but we do let the kids paint their backgrounds.
1755     PaintInfo info(paintInfo);
1756     info.phase = newPhase;
1757     info.paintingRoot = paintingRootForChildren(paintInfo);
1758     bool isPrinting = document()->printing();
1759 
1760     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
1761         // Check for page-break-before: always, and if it's set, break and bail.
1762         if (isPrinting && !childrenInline() && child->style()->pageBreakBefore() == PBALWAYS &&
1763             inRootBlockContext() && (ty + child->y()) > paintInfo.rect.y() &&
1764             (ty + child->y()) < paintInfo.rect.bottom()) {
1765             view()->setBestTruncatedAt(ty + child->y(), this, true);
1766             return;
1767         }
1768 
1769         if (!child->hasSelfPaintingLayer() && !child->isFloating())
1770             child->paint(info, tx, ty);
1771 
1772         // Check for page-break-after: always, and if it's set, break and bail.
1773         if (isPrinting && !childrenInline() && child->style()->pageBreakAfter() == PBALWAYS &&
1774             inRootBlockContext() && (ty + child->y() + child->height()) > paintInfo.rect.y() &&
1775             (ty + child->y() + child->height()) < paintInfo.rect.bottom()) {
1776             view()->setBestTruncatedAt(ty + child->y() + child->height() + max(0, child->collapsedMarginBottom()), this, true);
1777             return;
1778         }
1779     }
1780 }
1781 
paintCaret(PaintInfo & paintInfo,int tx,int ty,CaretType type)1782 void RenderBlock::paintCaret(PaintInfo& paintInfo, int tx, int ty, CaretType type)
1783 {
1784     SelectionController* selection = type == CursorCaret ? document()->frame()->selection() : document()->frame()->dragCaretController();
1785 
1786     // Paint the caret if the SelectionController says so or if caret browsing is enabled
1787     bool caretBrowsing = document()->frame()->settings() && document()->frame()->settings()->caretBrowsingEnabled();
1788     RenderObject* caretPainter = selection->caretRenderer();
1789     if (caretPainter == this && (selection->isContentEditable() || caretBrowsing)) {
1790         // Convert the painting offset into the local coordinate system of this renderer,
1791         // to match the localCaretRect computed by the SelectionController
1792         offsetForContents(tx, ty);
1793 
1794         if (type == CursorCaret)
1795             document()->frame()->paintCaret(paintInfo.context, tx, ty, paintInfo.rect);
1796         else
1797             document()->frame()->paintDragCaret(paintInfo.context, tx, ty, paintInfo.rect);
1798     }
1799 }
1800 
paintObject(PaintInfo & paintInfo,int tx,int ty)1801 void RenderBlock::paintObject(PaintInfo& paintInfo, int tx, int ty)
1802 {
1803     PaintPhase paintPhase = paintInfo.phase;
1804 
1805     // 1. paint background, borders etc
1806     if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && style()->visibility() == VISIBLE) {
1807         if (hasBoxDecorations())
1808             paintBoxDecorations(paintInfo, tx, ty);
1809         if (hasColumns())
1810             paintColumnRules(paintInfo, tx, ty);
1811     }
1812 
1813     if (paintPhase == PaintPhaseMask && style()->visibility() == VISIBLE) {
1814         paintMask(paintInfo, tx, ty);
1815         return;
1816     }
1817 
1818     // We're done.  We don't bother painting any children.
1819     if (paintPhase == PaintPhaseBlockBackground)
1820         return;
1821 
1822     // Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div).s
1823     int scrolledX = tx;
1824     int scrolledY = ty;
1825     if (hasOverflowClip())
1826         layer()->subtractScrolledContentOffset(scrolledX, scrolledY);
1827 
1828     // 2. paint contents
1829     if (paintPhase != PaintPhaseSelfOutline) {
1830         if (hasColumns())
1831             paintColumnContents(paintInfo, scrolledX, scrolledY);
1832         else
1833             paintContents(paintInfo, scrolledX, scrolledY);
1834     }
1835 
1836     // 3. paint selection
1837     // FIXME: Make this work with multi column layouts.  For now don't fill gaps.
1838     bool isPrinting = document()->printing();
1839     if (!isPrinting && !hasColumns())
1840         paintSelection(paintInfo, scrolledX, scrolledY); // Fill in gaps in selection on lines and between blocks.
1841 
1842     // 4. paint floats.
1843     if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip) {
1844         if (hasColumns())
1845             paintColumnContents(paintInfo, scrolledX, scrolledY, true);
1846         else
1847             paintFloats(paintInfo, scrolledX, scrolledY, paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip);
1848     }
1849 
1850     // 5. paint outline.
1851     if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style()->visibility() == VISIBLE)
1852         paintOutline(paintInfo.context, tx, ty, width(), height(), style());
1853 
1854     // 6. paint continuation outlines.
1855     if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)) {
1856         if (inlineContinuation() && inlineContinuation()->hasOutline() && inlineContinuation()->style()->visibility() == VISIBLE) {
1857             RenderInline* inlineRenderer = toRenderInline(inlineContinuation()->node()->renderer());
1858             if (!inlineRenderer->hasSelfPaintingLayer())
1859                 containingBlock()->addContinuationWithOutline(inlineRenderer);
1860             else if (!inlineRenderer->firstLineBox())
1861                 inlineRenderer->paintOutline(paintInfo.context, tx - x() + inlineRenderer->containingBlock()->x(),
1862                                              ty - y() + inlineRenderer->containingBlock()->y());
1863         }
1864         paintContinuationOutlines(paintInfo, tx, ty);
1865     }
1866 
1867     // 7. paint caret.
1868     // If the caret's node's render object's containing block is this block, and the paint action is PaintPhaseForeground,
1869     // then paint the caret.
1870     if (paintPhase == PaintPhaseForeground) {
1871         paintCaret(paintInfo, scrolledX, scrolledY, CursorCaret);
1872         paintCaret(paintInfo, scrolledX, scrolledY, DragCaret);
1873     }
1874 }
1875 
paintFloats(PaintInfo & paintInfo,int tx,int ty,bool preservePhase)1876 void RenderBlock::paintFloats(PaintInfo& paintInfo, int tx, int ty, bool preservePhase)
1877 {
1878     if (!m_floatingObjects)
1879         return;
1880 
1881     FloatingObject* r;
1882     DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
1883     for (; (r = it.current()); ++it) {
1884         // Only paint the object if our m_shouldPaint flag is set.
1885         if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) {
1886             PaintInfo currentPaintInfo(paintInfo);
1887             currentPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
1888             int currentTX = tx + r->m_left - r->m_renderer->x() + r->m_renderer->marginLeft();
1889             int currentTY = ty + r->m_top - r->m_renderer->y() + r->m_renderer->marginTop();
1890             r->m_renderer->paint(currentPaintInfo, currentTX, currentTY);
1891             if (!preservePhase) {
1892                 currentPaintInfo.phase = PaintPhaseChildBlockBackgrounds;
1893                 r->m_renderer->paint(currentPaintInfo, currentTX, currentTY);
1894                 currentPaintInfo.phase = PaintPhaseFloat;
1895                 r->m_renderer->paint(currentPaintInfo, currentTX, currentTY);
1896                 currentPaintInfo.phase = PaintPhaseForeground;
1897                 r->m_renderer->paint(currentPaintInfo, currentTX, currentTY);
1898                 currentPaintInfo.phase = PaintPhaseOutline;
1899                 r->m_renderer->paint(currentPaintInfo, currentTX, currentTY);
1900             }
1901         }
1902     }
1903 }
1904 
paintEllipsisBoxes(PaintInfo & paintInfo,int tx,int ty)1905 void RenderBlock::paintEllipsisBoxes(PaintInfo& paintInfo, int tx, int ty)
1906 {
1907     if (!shouldPaintWithinRoot(paintInfo) || !firstLineBox())
1908         return;
1909 
1910     if (style()->visibility() == VISIBLE && paintInfo.phase == PaintPhaseForeground) {
1911         // We can check the first box and last box and avoid painting if we don't
1912         // intersect.
1913         int yPos = ty + firstLineBox()->y();
1914         int h = lastLineBox()->y() + lastLineBox()->height() - firstLineBox()->y();
1915         if (yPos >= paintInfo.rect.bottom() || yPos + h <= paintInfo.rect.y())
1916             return;
1917 
1918         // See if our boxes intersect with the dirty rect.  If so, then we paint
1919         // them.  Note that boxes can easily overlap, so we can't make any assumptions
1920         // based off positions of our first line box or our last line box.
1921         for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
1922             yPos = ty + curr->y();
1923             h = curr->height();
1924             if (curr->ellipsisBox() && yPos < paintInfo.rect.bottom() && yPos + h > paintInfo.rect.y())
1925                 curr->paintEllipsisBox(paintInfo, tx, ty);
1926         }
1927     }
1928 }
1929 
continuationOutlineTable()1930 static ContinuationOutlineTableMap* continuationOutlineTable()
1931 {
1932     DEFINE_STATIC_LOCAL(ContinuationOutlineTableMap, table, ());
1933     return &table;
1934 }
1935 
addContinuationWithOutline(RenderInline * flow)1936 void RenderBlock::addContinuationWithOutline(RenderInline* flow)
1937 {
1938     // We can't make this work if the inline is in a layer.  We'll just rely on the broken
1939     // way of painting.
1940     ASSERT(!flow->layer() && !flow->isInlineContinuation());
1941 
1942     ContinuationOutlineTableMap* table = continuationOutlineTable();
1943     ListHashSet<RenderInline*>* continuations = table->get(this);
1944     if (!continuations) {
1945         continuations = new ListHashSet<RenderInline*>;
1946         table->set(this, continuations);
1947     }
1948 
1949     continuations->add(flow);
1950 }
1951 
paintContinuationOutlines(PaintInfo & info,int tx,int ty)1952 void RenderBlock::paintContinuationOutlines(PaintInfo& info, int tx, int ty)
1953 {
1954     ContinuationOutlineTableMap* table = continuationOutlineTable();
1955     if (table->isEmpty())
1956         return;
1957 
1958     ListHashSet<RenderInline*>* continuations = table->get(this);
1959     if (!continuations)
1960         return;
1961 
1962     // Paint each continuation outline.
1963     ListHashSet<RenderInline*>::iterator end = continuations->end();
1964     for (ListHashSet<RenderInline*>::iterator it = continuations->begin(); it != end; ++it) {
1965         // Need to add in the coordinates of the intervening blocks.
1966         RenderInline* flow = *it;
1967         RenderBlock* block = flow->containingBlock();
1968         for ( ; block && block != this; block = block->containingBlock()) {
1969             tx += block->x();
1970             ty += block->y();
1971         }
1972         ASSERT(block);
1973         flow->paintOutline(info.context, tx, ty);
1974     }
1975 
1976     // Delete
1977     delete continuations;
1978     table->remove(this);
1979 }
1980 
setSelectionState(SelectionState s)1981 void RenderBlock::setSelectionState(SelectionState s)
1982 {
1983     if (selectionState() == s)
1984         return;
1985 
1986     if (s == SelectionInside && selectionState() != SelectionNone)
1987         return;
1988 
1989     if ((s == SelectionStart && selectionState() == SelectionEnd) ||
1990         (s == SelectionEnd && selectionState() == SelectionStart))
1991         RenderBox::setSelectionState(SelectionBoth);
1992     else
1993         RenderBox::setSelectionState(s);
1994 
1995     RenderBlock* cb = containingBlock();
1996     if (cb && !cb->isRenderView())
1997         cb->setSelectionState(s);
1998 }
1999 
shouldPaintSelectionGaps() const2000 bool RenderBlock::shouldPaintSelectionGaps() const
2001 {
2002     return selectionState() != SelectionNone && style()->visibility() == VISIBLE && isSelectionRoot();
2003 }
2004 
isSelectionRoot() const2005 bool RenderBlock::isSelectionRoot() const
2006 {
2007     if (!node())
2008         return false;
2009 
2010     // FIXME: Eventually tables should have to learn how to fill gaps between cells, at least in simple non-spanning cases.
2011     if (isTable())
2012         return false;
2013 
2014     if (isBody() || isRoot() || hasOverflowClip() || isRelPositioned() ||
2015         isFloatingOrPositioned() || isTableCell() || isInlineBlockOrInlineTable() || hasTransform() ||
2016         hasReflection() || hasMask())
2017         return true;
2018 
2019     if (view() && view()->selectionStart()) {
2020         Node* startElement = view()->selectionStart()->node();
2021         if (startElement && startElement->rootEditableElement() == node())
2022             return true;
2023     }
2024 
2025     return false;
2026 }
2027 
selectionGapRectsForRepaint(RenderBoxModelObject *)2028 GapRects RenderBlock::selectionGapRectsForRepaint(RenderBoxModelObject* /*repaintContainer*/)
2029 {
2030     ASSERT(!needsLayout());
2031 
2032     if (!shouldPaintSelectionGaps())
2033         return GapRects();
2034 
2035     // FIXME: this is broken with transforms and a non-null repaintContainer
2036     FloatPoint absContentPoint = localToAbsolute(FloatPoint());
2037     if (hasOverflowClip())
2038         absContentPoint -= layer()->scrolledContentOffset();
2039 
2040     int lastTop = 0;
2041     int lastLeft = leftSelectionOffset(this, lastTop);
2042     int lastRight = rightSelectionOffset(this, lastTop);
2043 
2044     return fillSelectionGaps(this, absContentPoint.x(), absContentPoint.y(), absContentPoint.x(), absContentPoint.y(), lastTop, lastLeft, lastRight);
2045 }
2046 
paintSelection(PaintInfo & paintInfo,int tx,int ty)2047 void RenderBlock::paintSelection(PaintInfo& paintInfo, int tx, int ty)
2048 {
2049     if (shouldPaintSelectionGaps() && paintInfo.phase == PaintPhaseForeground) {
2050         int lastTop = 0;
2051         int lastLeft = leftSelectionOffset(this, lastTop);
2052         int lastRight = rightSelectionOffset(this, lastTop);
2053         paintInfo.context->save();
2054         fillSelectionGaps(this, tx, ty, tx, ty, lastTop, lastLeft, lastRight, &paintInfo);
2055         paintInfo.context->restore();
2056     }
2057 }
2058 
2059 #ifndef BUILDING_ON_TIGER
clipOutPositionedObjects(const RenderObject::PaintInfo * paintInfo,int tx,int ty,ListHashSet<RenderBox * > * positionedObjects)2060 static void clipOutPositionedObjects(const RenderObject::PaintInfo* paintInfo, int tx, int ty, ListHashSet<RenderBox*>* positionedObjects)
2061 {
2062     if (!positionedObjects)
2063         return;
2064 
2065     ListHashSet<RenderBox*>::const_iterator end = positionedObjects->end();
2066     for (ListHashSet<RenderBox*>::const_iterator it = positionedObjects->begin(); it != end; ++it) {
2067         RenderBox* r = *it;
2068         paintInfo->context->clipOut(IntRect(tx + r->x(), ty + r->y(), r->width(), r->height()));
2069     }
2070 }
2071 #endif
2072 
fillSelectionGaps(RenderBlock * rootBlock,int blockX,int blockY,int tx,int ty,int & lastTop,int & lastLeft,int & lastRight,const PaintInfo * paintInfo)2073 GapRects RenderBlock::fillSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
2074                                         int& lastTop, int& lastLeft, int& lastRight, const PaintInfo* paintInfo)
2075 {
2076 #ifndef BUILDING_ON_TIGER
2077     // IMPORTANT: Callers of this method that intend for painting to happen need to do a save/restore.
2078     // Clip out floating and positioned objects when painting selection gaps.
2079     if (paintInfo) {
2080         // Note that we don't clip out overflow for positioned objects.  We just stick to the border box.
2081         clipOutPositionedObjects(paintInfo, tx, ty, m_positionedObjects);
2082         if (isBody() || isRoot()) // The <body> must make sure to examine its containingBlock's positioned objects.
2083             for (RenderBlock* cb = containingBlock(); cb && !cb->isRenderView(); cb = cb->containingBlock())
2084                 clipOutPositionedObjects(paintInfo, cb->x(), cb->y(), cb->m_positionedObjects);
2085         if (m_floatingObjects) {
2086             for (DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); it.current(); ++it) {
2087                 FloatingObject* r = it.current();
2088                 paintInfo->context->clipOut(IntRect(tx + r->m_left + r->m_renderer->marginLeft(),
2089                                                     ty + r->m_top + r->m_renderer->marginTop(),
2090                                                     r->m_renderer->width(), r->m_renderer->height()));
2091             }
2092         }
2093     }
2094 #endif
2095 
2096     // 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
2097     // fixed).
2098     GapRects result;
2099     if (!isBlockFlow()) // FIXME: Make multi-column selection gap filling work someday.
2100         return result;
2101 
2102     if (hasColumns() || hasTransform()) {
2103         // FIXME: We should learn how to gap fill multiple columns and transforms eventually.
2104         lastTop = (ty - blockY) + height();
2105         lastLeft = leftSelectionOffset(rootBlock, height());
2106         lastRight = rightSelectionOffset(rootBlock, height());
2107         return result;
2108     }
2109 
2110     if (childrenInline())
2111         result = fillInlineSelectionGaps(rootBlock, blockX, blockY, tx, ty, lastTop, lastLeft, lastRight, paintInfo);
2112     else
2113         result = fillBlockSelectionGaps(rootBlock, blockX, blockY, tx, ty, lastTop, lastLeft, lastRight, paintInfo);
2114 
2115     // Go ahead and fill the vertical gap all the way to the bottom of our block if the selection extends past our block.
2116     if (rootBlock == this && (selectionState() != SelectionBoth && selectionState() != SelectionEnd))
2117         result.uniteCenter(fillVerticalSelectionGap(lastTop, lastLeft, lastRight, ty + height(),
2118                                                     rootBlock, blockX, blockY, paintInfo));
2119     return result;
2120 }
2121 
fillInlineSelectionGaps(RenderBlock * rootBlock,int blockX,int blockY,int tx,int ty,int & lastTop,int & lastLeft,int & lastRight,const PaintInfo * paintInfo)2122 GapRects RenderBlock::fillInlineSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
2123                                               int& lastTop, int& lastLeft, int& lastRight, const PaintInfo* paintInfo)
2124 {
2125     GapRects result;
2126 
2127     bool containsStart = selectionState() == SelectionStart || selectionState() == SelectionBoth;
2128 
2129     if (!firstLineBox()) {
2130         if (containsStart) {
2131             // Go ahead and update our lastY to be the bottom of the block.  <hr>s or empty blocks with height can trip this
2132             // case.
2133             lastTop = (ty - blockY) + height();
2134             lastLeft = leftSelectionOffset(rootBlock, height());
2135             lastRight = rightSelectionOffset(rootBlock, height());
2136         }
2137         return result;
2138     }
2139 
2140     RootInlineBox* lastSelectedLine = 0;
2141     RootInlineBox* curr;
2142     for (curr = firstRootBox(); curr && !curr->hasSelectedChildren(); curr = curr->nextRootBox()) { }
2143 
2144     // Now paint the gaps for the lines.
2145     for (; curr && curr->hasSelectedChildren(); curr = curr->nextRootBox()) {
2146         int selTop =  curr->selectionTop();
2147         int selHeight = curr->selectionHeight();
2148 
2149         if (!containsStart && !lastSelectedLine &&
2150             selectionState() != SelectionStart && selectionState() != SelectionBoth)
2151             result.uniteCenter(fillVerticalSelectionGap(lastTop, lastLeft, lastRight, ty + selTop,
2152                                                         rootBlock, blockX, blockY, paintInfo));
2153 
2154         if (!paintInfo || (ty + selTop < paintInfo->rect.bottom() && ty + selTop + selHeight > paintInfo->rect.y()))
2155             result.unite(curr->fillLineSelectionGap(selTop, selHeight, rootBlock, blockX, blockY, tx, ty, paintInfo));
2156 
2157         lastSelectedLine = curr;
2158     }
2159 
2160     if (containsStart && !lastSelectedLine)
2161         // VisibleSelection must start just after our last line.
2162         lastSelectedLine = lastRootBox();
2163 
2164     if (lastSelectedLine && selectionState() != SelectionEnd && selectionState() != SelectionBoth) {
2165         // Go ahead and update our lastY to be the bottom of the last selected line.
2166         lastTop = (ty - blockY) + lastSelectedLine->bottomOverflow();
2167         lastLeft = leftSelectionOffset(rootBlock, lastSelectedLine->bottomOverflow());
2168         lastRight = rightSelectionOffset(rootBlock, lastSelectedLine->bottomOverflow());
2169     }
2170     return result;
2171 }
2172 
fillBlockSelectionGaps(RenderBlock * rootBlock,int blockX,int blockY,int tx,int ty,int & lastTop,int & lastLeft,int & lastRight,const PaintInfo * paintInfo)2173 GapRects RenderBlock::fillBlockSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty,
2174                                              int& lastTop, int& lastLeft, int& lastRight, const PaintInfo* paintInfo)
2175 {
2176     GapRects result;
2177 
2178     // Go ahead and jump right to the first block child that contains some selected objects.
2179     RenderBox* curr;
2180     for (curr = firstChildBox(); curr && curr->selectionState() == SelectionNone; curr = curr->nextSiblingBox()) { }
2181 
2182     for (bool sawSelectionEnd = false; curr && !sawSelectionEnd; curr = curr->nextSiblingBox()) {
2183         SelectionState childState = curr->selectionState();
2184         if (childState == SelectionBoth || childState == SelectionEnd)
2185             sawSelectionEnd = true;
2186 
2187         if (curr->isFloatingOrPositioned())
2188             continue; // We must be a normal flow object in order to even be considered.
2189 
2190         if (curr->isRelPositioned() && curr->hasLayer()) {
2191             // If the relposition offset is anything other than 0, then treat this just like an absolute positioned element.
2192             // Just disregard it completely.
2193             IntSize relOffset = curr->layer()->relativePositionOffset();
2194             if (relOffset.width() || relOffset.height())
2195                 continue;
2196         }
2197 
2198         bool paintsOwnSelection = curr->shouldPaintSelectionGaps() || curr->isTable(); // FIXME: Eventually we won't special-case table like this.
2199         bool fillBlockGaps = paintsOwnSelection || (curr->canBeSelectionLeaf() && childState != SelectionNone);
2200         if (fillBlockGaps) {
2201             // We need to fill the vertical gap above this object.
2202             if (childState == SelectionEnd || childState == SelectionInside)
2203                 // Fill the gap above the object.
2204                 result.uniteCenter(fillVerticalSelectionGap(lastTop, lastLeft, lastRight,
2205                                                             ty + curr->y(), rootBlock, blockX, blockY, paintInfo));
2206 
2207             // 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*
2208             // our object.  We know this if the selection did not end inside our object.
2209             if (paintsOwnSelection && (childState == SelectionStart || sawSelectionEnd))
2210                 childState = SelectionNone;
2211 
2212             // Fill side gaps on this object based off its state.
2213             bool leftGap, rightGap;
2214             getHorizontalSelectionGapInfo(childState, leftGap, rightGap);
2215 
2216             if (leftGap)
2217                 result.uniteLeft(fillLeftSelectionGap(this, curr->x(), curr->y(), curr->height(), rootBlock, blockX, blockY, tx, ty, paintInfo));
2218             if (rightGap)
2219                 result.uniteRight(fillRightSelectionGap(this, curr->x() + curr->width(), curr->y(), curr->height(), rootBlock, blockX, blockY, tx, ty, paintInfo));
2220 
2221             // Update lastTop to be just underneath the object.  lastLeft and lastRight extend as far as
2222             // they can without bumping into floating or positioned objects.  Ideally they will go right up
2223             // to the border of the root selection block.
2224             lastTop = (ty - blockY) + (curr->y() + curr->height());
2225             lastLeft = leftSelectionOffset(rootBlock, curr->y() + curr->height());
2226             lastRight = rightSelectionOffset(rootBlock, curr->y() + curr->height());
2227         } else if (childState != SelectionNone)
2228             // We must be a block that has some selected object inside it.  Go ahead and recur.
2229             result.unite(toRenderBlock(curr)->fillSelectionGaps(rootBlock, blockX, blockY, tx + curr->x(), ty + curr->y(),
2230                                                                             lastTop, lastLeft, lastRight, paintInfo));
2231     }
2232     return result;
2233 }
2234 
fillHorizontalSelectionGap(RenderObject * selObj,int xPos,int yPos,int width,int height,const PaintInfo * paintInfo)2235 IntRect RenderBlock::fillHorizontalSelectionGap(RenderObject* selObj, int xPos, int yPos, int width, int height, const PaintInfo* paintInfo)
2236 {
2237     if (width <= 0 || height <= 0)
2238         return IntRect();
2239     IntRect gapRect(xPos, yPos, width, height);
2240     if (paintInfo && selObj->style()->visibility() == VISIBLE)
2241         paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor());
2242     return gapRect;
2243 }
2244 
fillVerticalSelectionGap(int lastTop,int lastLeft,int lastRight,int bottomY,RenderBlock * rootBlock,int blockX,int blockY,const PaintInfo * paintInfo)2245 IntRect RenderBlock::fillVerticalSelectionGap(int lastTop, int lastLeft, int lastRight, int bottomY, RenderBlock* rootBlock,
2246                                               int blockX, int blockY, const PaintInfo* paintInfo)
2247 {
2248     int top = blockY + lastTop;
2249     int height = bottomY - top;
2250     if (height <= 0)
2251         return IntRect();
2252 
2253     // Get the selection offsets for the bottom of the gap
2254     int left = blockX + max(lastLeft, leftSelectionOffset(rootBlock, bottomY));
2255     int right = blockX + min(lastRight, rightSelectionOffset(rootBlock, bottomY));
2256     int width = right - left;
2257     if (width <= 0)
2258         return IntRect();
2259 
2260     IntRect gapRect(left, top, width, height);
2261     if (paintInfo)
2262         paintInfo->context->fillRect(gapRect, selectionBackgroundColor());
2263     return gapRect;
2264 }
2265 
fillLeftSelectionGap(RenderObject * selObj,int xPos,int yPos,int height,RenderBlock * rootBlock,int blockX,int,int tx,int ty,const PaintInfo * paintInfo)2266 IntRect RenderBlock::fillLeftSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock,
2267                                           int blockX, int /*blockY*/, int tx, int ty, const PaintInfo* paintInfo)
2268 {
2269     int top = yPos + ty;
2270     int left = blockX + max(leftSelectionOffset(rootBlock, yPos), leftSelectionOffset(rootBlock, yPos + height));
2271     int right = min(xPos + tx, blockX + min(rightSelectionOffset(rootBlock, yPos), rightSelectionOffset(rootBlock, yPos + height)));
2272     int width = right - left;
2273     if (width <= 0)
2274         return IntRect();
2275 
2276     IntRect gapRect(left, top, width, height);
2277     if (paintInfo)
2278         paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor());
2279     return gapRect;
2280 }
2281 
fillRightSelectionGap(RenderObject * selObj,int xPos,int yPos,int height,RenderBlock * rootBlock,int blockX,int,int tx,int ty,const PaintInfo * paintInfo)2282 IntRect RenderBlock::fillRightSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock,
2283                                            int blockX, int /*blockY*/, int tx, int ty, const PaintInfo* paintInfo)
2284 {
2285     int left = max(xPos + tx, blockX + max(leftSelectionOffset(rootBlock, yPos), leftSelectionOffset(rootBlock, yPos + height)));
2286     int top = yPos + ty;
2287     int right = blockX + min(rightSelectionOffset(rootBlock, yPos), rightSelectionOffset(rootBlock, yPos + height));
2288     int width = right - left;
2289     if (width <= 0)
2290         return IntRect();
2291 
2292     IntRect gapRect(left, top, width, height);
2293     if (paintInfo)
2294         paintInfo->context->fillRect(gapRect, selObj->selectionBackgroundColor());
2295     return gapRect;
2296 }
2297 
getHorizontalSelectionGapInfo(SelectionState state,bool & leftGap,bool & rightGap)2298 void RenderBlock::getHorizontalSelectionGapInfo(SelectionState state, bool& leftGap, bool& rightGap)
2299 {
2300     bool ltr = style()->direction() == LTR;
2301     leftGap = (state == RenderObject::SelectionInside) ||
2302               (state == RenderObject::SelectionEnd && ltr) ||
2303               (state == RenderObject::SelectionStart && !ltr);
2304     rightGap = (state == RenderObject::SelectionInside) ||
2305                (state == RenderObject::SelectionStart && ltr) ||
2306                (state == RenderObject::SelectionEnd && !ltr);
2307 }
2308 
leftSelectionOffset(RenderBlock * rootBlock,int yPos)2309 int RenderBlock::leftSelectionOffset(RenderBlock* rootBlock, int yPos)
2310 {
2311     int left = leftOffset(yPos, false);
2312     if (left == borderLeft() + paddingLeft()) {
2313         if (rootBlock != this)
2314             // The border can potentially be further extended by our containingBlock().
2315             return containingBlock()->leftSelectionOffset(rootBlock, yPos + y());
2316         return left;
2317     }
2318     else {
2319         RenderBlock* cb = this;
2320         while (cb != rootBlock) {
2321             left += cb->x();
2322             cb = cb->containingBlock();
2323         }
2324     }
2325 
2326     return left;
2327 }
2328 
rightSelectionOffset(RenderBlock * rootBlock,int yPos)2329 int RenderBlock::rightSelectionOffset(RenderBlock* rootBlock, int yPos)
2330 {
2331     int right = rightOffset(yPos, false);
2332     if (right == (contentWidth() + (borderLeft() + paddingLeft()))) {
2333         if (rootBlock != this)
2334             // The border can potentially be further extended by our containingBlock().
2335             return containingBlock()->rightSelectionOffset(rootBlock, yPos + y());
2336         return right;
2337     }
2338     else {
2339         RenderBlock* cb = this;
2340         while (cb != rootBlock) {
2341             right += cb->x();
2342             cb = cb->containingBlock();
2343         }
2344     }
2345     return right;
2346 }
2347 
insertPositionedObject(RenderBox * o)2348 void RenderBlock::insertPositionedObject(RenderBox* o)
2349 {
2350     // Create the list of special objects if we don't aleady have one
2351     if (!m_positionedObjects)
2352         m_positionedObjects = new ListHashSet<RenderBox*>;
2353 
2354     m_positionedObjects->add(o);
2355 }
2356 
removePositionedObject(RenderBox * o)2357 void RenderBlock::removePositionedObject(RenderBox* o)
2358 {
2359     if (m_positionedObjects)
2360         m_positionedObjects->remove(o);
2361 }
2362 
removePositionedObjects(RenderBlock * o)2363 void RenderBlock::removePositionedObjects(RenderBlock* o)
2364 {
2365     if (!m_positionedObjects)
2366         return;
2367 
2368     RenderBox* r;
2369 
2370     Iterator end = m_positionedObjects->end();
2371 
2372     Vector<RenderBox*, 16> deadObjects;
2373 
2374     for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
2375         r = *it;
2376         if (!o || r->isDescendantOf(o)) {
2377             if (o)
2378                 r->setChildNeedsLayout(true, false);
2379 
2380             // It is parent blocks job to add positioned child to positioned objects list of its containing block
2381             // Parent layout needs to be invalidated to ensure this happens.
2382             RenderObject* p = r->parent();
2383             while (p && !p->isRenderBlock())
2384                 p = p->parent();
2385             if (p)
2386                 p->setChildNeedsLayout(true);
2387 
2388             deadObjects.append(r);
2389         }
2390     }
2391 
2392     for (unsigned i = 0; i < deadObjects.size(); i++)
2393         m_positionedObjects->remove(deadObjects.at(i));
2394 }
2395 
insertFloatingObject(RenderBox * o)2396 void RenderBlock::insertFloatingObject(RenderBox* o)
2397 {
2398     ASSERT(o->isFloating());
2399 
2400     // Create the list of special objects if we don't aleady have one
2401     if (!m_floatingObjects) {
2402         m_floatingObjects = new DeprecatedPtrList<FloatingObject>;
2403         m_floatingObjects->setAutoDelete(true);
2404     } else {
2405         // Don't insert the object again if it's already in the list
2406         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2407         FloatingObject* f;
2408         while ( (f = it.current()) ) {
2409             if (f->m_renderer == o) return;
2410             ++it;
2411         }
2412     }
2413 
2414     // Create the special object entry & append it to the list
2415 
2416     o->layoutIfNeeded();
2417 
2418     FloatingObject* newObj = new FloatingObject(o->style()->floating() == FLEFT ? FloatingObject::FloatLeft : FloatingObject::FloatRight);
2419 
2420     newObj->m_top = -1;
2421     newObj->m_bottom = -1;
2422     newObj->m_width = o->width() + o->marginLeft() + o->marginRight();
2423     newObj->m_shouldPaint = !o->hasSelfPaintingLayer(); // If a layer exists, the float will paint itself.  Otherwise someone else will.
2424     newObj->m_isDescendant = true;
2425     newObj->m_renderer = o;
2426 
2427     m_floatingObjects->append(newObj);
2428 }
2429 
removeFloatingObject(RenderBox * o)2430 void RenderBlock::removeFloatingObject(RenderBox* o)
2431 {
2432     if (m_floatingObjects) {
2433         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2434         while (it.current()) {
2435             if (it.current()->m_renderer == o) {
2436                 if (childrenInline())
2437                     markLinesDirtyInVerticalRange(0, it.current()->m_bottom);
2438                 m_floatingObjects->removeRef(it.current());
2439             }
2440             ++it;
2441         }
2442     }
2443 }
2444 
positionNewFloats()2445 bool RenderBlock::positionNewFloats()
2446 {
2447     if (!m_floatingObjects)
2448         return false;
2449 
2450     FloatingObject* f = m_floatingObjects->last();
2451 
2452     // If all floats have already been positioned, then we have no work to do.
2453     if (!f || f->m_top != -1)
2454         return false;
2455 
2456     // Move backwards through our floating object list until we find a float that has
2457     // already been positioned.  Then we'll be able to move forward, positioning all of
2458     // the new floats that need it.
2459     FloatingObject* lastFloat = m_floatingObjects->getPrev();
2460     while (lastFloat && lastFloat->m_top == -1) {
2461         f = m_floatingObjects->prev();
2462         lastFloat = m_floatingObjects->getPrev();
2463     }
2464 
2465     int y = height();
2466 
2467     // The float cannot start above the y position of the last positioned float.
2468     if (lastFloat)
2469         y = max(lastFloat->m_top, y);
2470 
2471     // Now walk through the set of unpositioned floats and place them.
2472     while (f) {
2473         // The containing block is responsible for positioning floats, so if we have floats in our
2474         // list that come from somewhere else, do not attempt to position them.
2475         if (f->m_renderer->containingBlock() != this) {
2476             f = m_floatingObjects->next();
2477             continue;
2478         }
2479 
2480         RenderBox* o = f->m_renderer;
2481         int _height = o->height() + o->marginTop() + o->marginBottom();
2482 
2483         int ro = rightOffset(); // Constant part of right offset.
2484         int lo = leftOffset(); // Constat part of left offset.
2485         int fwidth = f->m_width; // The width we look for.
2486         if (ro - lo < fwidth)
2487             fwidth = ro - lo; // Never look for more than what will be available.
2488 
2489         IntRect oldRect(o->x(), o->y() , o->width(), o->height());
2490 
2491         if (o->style()->clear() & CLEFT)
2492             y = max(leftBottom(), y);
2493         if (o->style()->clear() & CRIGHT)
2494             y = max(rightBottom(), y);
2495 
2496         if (o->style()->floating() == FLEFT) {
2497             int heightRemainingLeft = 1;
2498             int heightRemainingRight = 1;
2499             int fx = leftRelOffset(y, lo, false, &heightRemainingLeft);
2500             while (rightRelOffset(y, ro, false, &heightRemainingRight)-fx < fwidth) {
2501                 y += min(heightRemainingLeft, heightRemainingRight);
2502                 fx = leftRelOffset(y, lo, false, &heightRemainingLeft);
2503             }
2504             fx = max(0, fx);
2505             f->m_left = fx;
2506             o->setLocation(fx + o->marginLeft(), y + o->marginTop());
2507         } else {
2508             int heightRemainingLeft = 1;
2509             int heightRemainingRight = 1;
2510             int fx = rightRelOffset(y, ro, false, &heightRemainingRight);
2511             while (fx - leftRelOffset(y, lo, false, &heightRemainingLeft) < fwidth) {
2512                 y += min(heightRemainingLeft, heightRemainingRight);
2513                 fx = rightRelOffset(y, ro, false, &heightRemainingRight);
2514             }
2515             f->m_left = fx - f->m_width;
2516             o->setLocation(fx - o->marginRight() - o->width(), y + o->marginTop());
2517         }
2518 
2519         f->m_top = y;
2520         f->m_bottom = f->m_top + _height;
2521 
2522         // If the child moved, we have to repaint it.
2523         if (o->checkForRepaintDuringLayout())
2524             o->repaintDuringLayoutIfMoved(oldRect);
2525 
2526         f = m_floatingObjects->next();
2527     }
2528     return true;
2529 }
2530 
newLine(EClear clear)2531 void RenderBlock::newLine(EClear clear)
2532 {
2533     positionNewFloats();
2534     // set y position
2535     int newY = 0;
2536     switch (clear)
2537     {
2538         case CLEFT:
2539             newY = leftBottom();
2540             break;
2541         case CRIGHT:
2542             newY = rightBottom();
2543             break;
2544         case CBOTH:
2545             newY = floatBottom();
2546         default:
2547             break;
2548     }
2549     if (height() < newY)
2550         setHeight(newY);
2551 }
2552 
addPercentHeightDescendant(RenderBox * descendant)2553 void RenderBlock::addPercentHeightDescendant(RenderBox* descendant)
2554 {
2555     if (!gPercentHeightDescendantsMap) {
2556         gPercentHeightDescendantsMap = new PercentHeightDescendantsMap;
2557         gPercentHeightContainerMap = new PercentHeightContainerMap;
2558     }
2559 
2560     HashSet<RenderBox*>* descendantSet = gPercentHeightDescendantsMap->get(this);
2561     if (!descendantSet) {
2562         descendantSet = new HashSet<RenderBox*>;
2563         gPercentHeightDescendantsMap->set(this, descendantSet);
2564     }
2565     bool added = descendantSet->add(descendant).second;
2566     if (!added) {
2567         ASSERT(gPercentHeightContainerMap->get(descendant));
2568         ASSERT(gPercentHeightContainerMap->get(descendant)->contains(this));
2569         return;
2570     }
2571 
2572     HashSet<RenderBlock*>* containerSet = gPercentHeightContainerMap->get(descendant);
2573     if (!containerSet) {
2574         containerSet = new HashSet<RenderBlock*>;
2575         gPercentHeightContainerMap->set(descendant, containerSet);
2576     }
2577     ASSERT(!containerSet->contains(this));
2578     containerSet->add(this);
2579 }
2580 
removePercentHeightDescendant(RenderBox * descendant)2581 void RenderBlock::removePercentHeightDescendant(RenderBox* descendant)
2582 {
2583     if (!gPercentHeightContainerMap)
2584         return;
2585 
2586     HashSet<RenderBlock*>* containerSet = gPercentHeightContainerMap->take(descendant);
2587     if (!containerSet)
2588         return;
2589 
2590     HashSet<RenderBlock*>::iterator end = containerSet->end();
2591     for (HashSet<RenderBlock*>::iterator it = containerSet->begin(); it != end; ++it) {
2592         RenderBlock* container = *it;
2593         HashSet<RenderBox*>* descendantSet = gPercentHeightDescendantsMap->get(container);
2594         ASSERT(descendantSet);
2595         if (!descendantSet)
2596             continue;
2597         ASSERT(descendantSet->contains(descendant));
2598         descendantSet->remove(descendant);
2599         if (descendantSet->isEmpty()) {
2600             gPercentHeightDescendantsMap->remove(container);
2601             delete descendantSet;
2602         }
2603     }
2604 
2605     delete containerSet;
2606 }
2607 
percentHeightDescendants() const2608 HashSet<RenderBox*>* RenderBlock::percentHeightDescendants() const
2609 {
2610     return gPercentHeightDescendantsMap ? gPercentHeightDescendantsMap->get(this) : 0;
2611 }
2612 
leftOffset() const2613 int RenderBlock::leftOffset() const
2614 {
2615     return borderLeft() + paddingLeft();
2616 }
2617 
leftRelOffset(int y,int fixedOffset,bool applyTextIndent,int * heightRemaining) const2618 int RenderBlock::leftRelOffset(int y, int fixedOffset, bool applyTextIndent, int* heightRemaining) const
2619 {
2620     int left = fixedOffset;
2621     if (m_floatingObjects) {
2622         if ( heightRemaining ) *heightRemaining = 1;
2623         FloatingObject* r;
2624         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2625         for ( ; (r = it.current()); ++it )
2626         {
2627             if (r->m_top <= y && r->m_bottom > y &&
2628                 r->type() == FloatingObject::FloatLeft &&
2629                 r->m_left + r->m_width > left) {
2630                 left = r->m_left + r->m_width;
2631                 if ( heightRemaining ) *heightRemaining = r->m_bottom - y;
2632             }
2633         }
2634     }
2635 
2636     if (applyTextIndent && style()->direction() == LTR) {
2637         int cw = 0;
2638         if (style()->textIndent().isPercent())
2639             cw = containingBlock()->availableWidth();
2640         left += style()->textIndent().calcMinValue(cw);
2641     }
2642 
2643     return left;
2644 }
2645 
rightOffset() const2646 int RenderBlock::rightOffset() const
2647 {
2648     return borderLeft() + paddingLeft() + availableWidth();
2649 }
2650 
rightRelOffset(int y,int fixedOffset,bool applyTextIndent,int * heightRemaining) const2651 int RenderBlock::rightRelOffset(int y, int fixedOffset, bool applyTextIndent, int* heightRemaining) const
2652 {
2653     int right = fixedOffset;
2654 
2655     if (m_floatingObjects) {
2656         if (heightRemaining) *heightRemaining = 1;
2657         FloatingObject* r;
2658         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2659         for ( ; (r = it.current()); ++it )
2660         {
2661             if (r->m_top <= y && r->m_bottom > y &&
2662                 r->type() == FloatingObject::FloatRight &&
2663                 r->m_left < right) {
2664                 right = r->m_left;
2665                 if ( heightRemaining ) *heightRemaining = r->m_bottom - y;
2666             }
2667         }
2668     }
2669 
2670     if (applyTextIndent && style()->direction() == RTL) {
2671         int cw = 0;
2672         if (style()->textIndent().isPercent())
2673             cw = containingBlock()->availableWidth();
2674         right -= style()->textIndent().calcMinValue(cw);
2675     }
2676 
2677     return right;
2678 }
2679 
2680 int
lineWidth(int y,bool firstLine) const2681 RenderBlock::lineWidth(int y, bool firstLine) const
2682 {
2683     int result = rightOffset(y, firstLine) - leftOffset(y, firstLine);
2684     return (result < 0) ? 0 : result;
2685 }
2686 
nextFloatBottomBelow(int height) const2687 int RenderBlock::nextFloatBottomBelow(int height) const
2688 {
2689     if (!m_floatingObjects)
2690         return 0;
2691 
2692     int bottom = INT_MAX;
2693     FloatingObject* r;
2694     DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2695     for ( ; (r = it.current()); ++it) {
2696         if (r->m_bottom > height)
2697             bottom = min(r->m_bottom, bottom);
2698     }
2699 
2700     return bottom == INT_MAX ? 0 : bottom;
2701 }
2702 
2703 int
floatBottom() const2704 RenderBlock::floatBottom() const
2705 {
2706     if (!m_floatingObjects) return 0;
2707     int bottom = 0;
2708     FloatingObject* r;
2709     DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2710     for ( ; (r = it.current()); ++it )
2711         if (r->m_bottom>bottom)
2712             bottom = r->m_bottom;
2713     return bottom;
2714 }
2715 
floatRect() const2716 IntRect RenderBlock::floatRect() const
2717 {
2718     IntRect result;
2719     if (!m_floatingObjects || hasOverflowClip())
2720         return result;
2721     FloatingObject* r;
2722     DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2723     for (; (r = it.current()); ++it) {
2724         if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) {
2725             IntRect childRect = r->m_renderer->overflowRect(false);
2726             childRect.move(r->m_left + r->m_renderer->marginLeft(), r->m_top + r->m_renderer->marginTop());
2727             result.unite(childRect);
2728         }
2729     }
2730 
2731     return result;
2732 }
2733 
lowestPosition(bool includeOverflowInterior,bool includeSelf) const2734 int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
2735 {
2736     if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
2737         return includeSelf && width() > 0 ? overflowHeight(false) : 0;
2738 
2739     int bottom = includeSelf && width() > 0 ? height() : 0;
2740     if (!hasColumns()) {
2741         // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
2742         // For now, we have to descend into all the children, since we may have a huge abs div inside
2743         // a tiny rel div buried somewhere deep in our child tree.  In this case we have to get to
2744         // the abs div.
2745         // See the last test case in https://bugs.webkit.org/show_bug.cgi?id=9314 for why this is a problem.
2746         // For inline children, we miss relative positioned boxes that might be buried inside <span>s.
2747         for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
2748             if (!c->isFloatingOrPositioned() && c->isBox()) {
2749                 RenderBox* childBox = toRenderBox(c);
2750                 bottom = max(bottom, childBox->y() + childBox->lowestPosition(false));
2751             }
2752         }
2753     }
2754 
2755     if (includeSelf && isRelPositioned())
2756         bottom += relativePositionOffsetY();
2757     if (!includeOverflowInterior && hasOverflowClip())
2758         return bottom;
2759 
2760     int relativeOffset = includeSelf && isRelPositioned() ? relativePositionOffsetY() : 0;
2761 
2762     if (includeSelf)
2763         bottom = max(bottom, m_overflowHeight + relativeOffset);
2764 
2765     if (m_positionedObjects) {
2766         RenderBox* r;
2767         Iterator end = m_positionedObjects->end();
2768         for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
2769             r = *it;
2770             // Fixed positioned objects do not scroll and thus should not constitute
2771             // part of the lowest position.
2772             if (r->style()->position() != FixedPosition) {
2773                 // FIXME: Should work for overflow sections too.
2774                 // If a positioned object lies completely to the left of the root it will be unreachable via scrolling.
2775                 // Therefore we should not allow it to contribute to the lowest position.
2776                 if (!isRenderView() || r->x() + r->width() > 0 || r->x() + r->rightmostPosition(false) > 0) {
2777                     int lp = r->y() + r->lowestPosition(false);
2778                     bottom = max(bottom, lp + relativeOffset);
2779                 }
2780             }
2781         }
2782     }
2783 
2784     if (hasColumns()) {
2785         Vector<IntRect>* colRects = columnRects();
2786         for (unsigned i = 0; i < colRects->size(); i++)
2787             bottom = max(bottom, colRects->at(i).bottom() + relativeOffset);
2788         return bottom;
2789     }
2790 
2791     if (m_floatingObjects) {
2792         FloatingObject* r;
2793         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2794         for ( ; (r = it.current()); ++it ) {
2795             if (r->m_shouldPaint || r->m_renderer->hasSelfPaintingLayer()) {
2796                 int lp = r->m_top + r->m_renderer->marginTop() + r->m_renderer->lowestPosition(false);
2797                 bottom = max(bottom, lp + relativeOffset);
2798             }
2799         }
2800     }
2801 
2802     if (!includeSelf) {
2803         bottom = max(bottom, borderTop() + paddingTop() + paddingBottom() + relativeOffset);
2804         if (childrenInline()) {
2805             if (lastLineBox()) {
2806                 int childBottomEdge = lastLineBox()->y() + lastLineBox()->height();
2807                 bottom = max(bottom, childBottomEdge + paddingBottom() + relativeOffset);
2808             }
2809         } else {
2810             // Find the last normal flow child.
2811             RenderBox* currBox = lastChildBox();
2812             while (currBox && currBox->isFloatingOrPositioned())
2813                 currBox = currBox->previousSiblingBox();
2814             if (currBox) {
2815                 int childBottomEdge = currBox->y() + currBox->height() + currBox->collapsedMarginBottom();
2816                 bottom = max(bottom, childBottomEdge + paddingBottom() + relativeOffset);
2817             }
2818         }
2819     }
2820 
2821     return bottom;
2822 }
2823 
rightmostPosition(bool includeOverflowInterior,bool includeSelf) const2824 int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
2825 {
2826     if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
2827         return includeSelf && height() > 0 ? overflowWidth(false) : 0;
2828 
2829     int right = includeSelf && height() > 0 ? width() : 0;
2830 
2831     if (!hasColumns()) {
2832         // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
2833         // For now, we have to descend into all the children, since we may have a huge abs div inside
2834         // a tiny rel div buried somewhere deep in our child tree.  In this case we have to get to
2835         // the abs div.
2836         for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
2837             if (!c->isFloatingOrPositioned() && c->isBox()) {
2838                 RenderBox* childBox = toRenderBox(c);
2839                 right = max(right, childBox->x() + childBox->rightmostPosition(false));
2840             }
2841         }
2842     }
2843 
2844     if (includeSelf && isRelPositioned())
2845         right += relativePositionOffsetX();
2846 
2847     if (!includeOverflowInterior && hasOverflowClip())
2848         return right;
2849 
2850     int relativeOffset = includeSelf && isRelPositioned() ? relativePositionOffsetX() : 0;
2851 
2852     if (includeSelf)
2853         right = max(right, m_overflowWidth + relativeOffset);
2854 
2855     if (m_positionedObjects) {
2856         RenderBox* r;
2857         Iterator end = m_positionedObjects->end();
2858         for (Iterator it = m_positionedObjects->begin() ; it != end; ++it) {
2859             r = *it;
2860             // Fixed positioned objects do not scroll and thus should not constitute
2861             // part of the rightmost position.
2862             if (r->style()->position() != FixedPosition) {
2863                 // FIXME: Should work for overflow sections too.
2864                 // If a positioned object lies completely above the root it will be unreachable via scrolling.
2865                 // Therefore we should not allow it to contribute to the rightmost position.
2866                 if (!isRenderView() || r->y() + r->height() > 0 || r->y() + r->lowestPosition(false) > 0) {
2867                     int rp = r->x() + r->rightmostPosition(false);
2868                     right = max(right, rp + relativeOffset);
2869                 }
2870             }
2871         }
2872     }
2873 
2874     if (hasColumns()) {
2875         // This only matters for LTR
2876         if (style()->direction() == LTR)
2877             right = max(columnRects()->last().right() + relativeOffset, right);
2878         return right;
2879     }
2880 
2881     if (m_floatingObjects) {
2882         FloatingObject* r;
2883         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2884         for ( ; (r = it.current()); ++it ) {
2885             if (r->m_shouldPaint || r->m_renderer->hasSelfPaintingLayer()) {
2886                 int rp = r->m_left + r->m_renderer->marginLeft() + r->m_renderer->rightmostPosition(false);
2887                 right = max(right, rp + relativeOffset);
2888             }
2889         }
2890     }
2891 
2892     if (!includeSelf) {
2893         right = max(right, borderLeft() + paddingLeft() + paddingRight() + relativeOffset);
2894         if (childrenInline()) {
2895             for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) {
2896                 int childRightEdge = currBox->x() + currBox->width();
2897 
2898                 // If this node is a root editable element, then the rightmostPosition should account for a caret at the end.
2899                 // FIXME: Need to find another way to do this, since scrollbars could show when we don't want them to.
2900                 if (node() && node()->isContentEditable() && node() == node()->rootEditableElement() && style()->direction() == LTR && !paddingRight())
2901                     childRightEdge += 1;
2902                 right = max(right, childRightEdge + paddingRight() + relativeOffset);
2903             }
2904         } else {
2905             // Walk all normal flow children.
2906             for (RenderBox* currBox = firstChildBox(); currBox; currBox = currBox->nextSiblingBox()) {
2907                 if (currBox->isFloatingOrPositioned())
2908                     continue;
2909                 int childRightEdge = currBox->x() + currBox->width() + currBox->marginRight();
2910                 right = max(right, childRightEdge + paddingRight() + relativeOffset);
2911             }
2912         }
2913     }
2914 
2915     return right;
2916 }
2917 
leftmostPosition(bool includeOverflowInterior,bool includeSelf) const2918 int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
2919 {
2920     if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
2921         return includeSelf && height() > 0 ? overflowLeft(false) : width();
2922 
2923     int left = includeSelf && height() > 0 ? 0 : width();
2924     if (!hasColumns()) {
2925         // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
2926         // For now, we have to descend into all the children, since we may have a huge abs div inside
2927         // a tiny rel div buried somewhere deep in our child tree.  In this case we have to get to
2928         // the abs div.
2929         for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
2930             if (!c->isFloatingOrPositioned() && c->isBox()) {
2931                 RenderBox* childBox = toRenderBox(c);
2932                 left = min(left, childBox->x() + childBox->leftmostPosition(false));
2933             }
2934         }
2935     }
2936 
2937     if (includeSelf && isRelPositioned())
2938         left += relativePositionOffsetX();
2939 
2940     if (!includeOverflowInterior && hasOverflowClip())
2941         return left;
2942 
2943     int relativeOffset = includeSelf && isRelPositioned() ? relativePositionOffsetX() : 0;
2944 
2945     if (includeSelf)
2946         left = min(left, m_overflowLeft + relativeOffset);
2947 
2948     if (m_positionedObjects) {
2949         RenderBox* r;
2950         Iterator end = m_positionedObjects->end();
2951         for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
2952             r = *it;
2953             // Fixed positioned objects do not scroll and thus should not constitute
2954             // part of the leftmost position.
2955             if (r->style()->position() != FixedPosition) {
2956                 // FIXME: Should work for overflow sections too.
2957                 // If a positioned object lies completely above the root it will be unreachable via scrolling.
2958                 // Therefore we should not allow it to contribute to the leftmost position.
2959                 if (!isRenderView() || r->y() + r->height() > 0 || r->y() + r->lowestPosition(false) > 0) {
2960                     int lp = r->x() + r->leftmostPosition(false);
2961                     left = min(left, lp + relativeOffset);
2962                 }
2963             }
2964         }
2965     }
2966 
2967     if (hasColumns()) {
2968         // This only matters for RTL
2969         if (style()->direction() == RTL)
2970             left = min(columnRects()->last().x() + relativeOffset, left);
2971         return left;
2972     }
2973 
2974     if (m_floatingObjects) {
2975         FloatingObject* r;
2976         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2977         for ( ; (r = it.current()); ++it ) {
2978             if (r->m_shouldPaint || r->m_renderer->hasSelfPaintingLayer()) {
2979                 int lp = r->m_left + r->m_renderer->marginLeft() + r->m_renderer->leftmostPosition(false);
2980                 left = min(left, lp + relativeOffset);
2981             }
2982         }
2983     }
2984 
2985     if (!includeSelf && firstLineBox()) {
2986         for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox())
2987             left = min(left, (int)currBox->x() + relativeOffset);
2988     }
2989 
2990     return left;
2991 }
2992 
2993 int
leftBottom()2994 RenderBlock::leftBottom()
2995 {
2996     if (!m_floatingObjects) return 0;
2997     int bottom = 0;
2998     FloatingObject* r;
2999     DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
3000     for ( ; (r = it.current()); ++it )
3001         if (r->m_bottom > bottom && r->type() == FloatingObject::FloatLeft)
3002             bottom = r->m_bottom;
3003 
3004     return bottom;
3005 }
3006 
3007 int
rightBottom()3008 RenderBlock::rightBottom()
3009 {
3010     if (!m_floatingObjects) return 0;
3011     int bottom = 0;
3012     FloatingObject* r;
3013     DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
3014     for ( ; (r = it.current()); ++it )
3015         if (r->m_bottom>bottom && r->type() == FloatingObject::FloatRight)
3016             bottom = r->m_bottom;
3017 
3018     return bottom;
3019 }
3020 
markLinesDirtyInVerticalRange(int top,int bottom)3021 void RenderBlock::markLinesDirtyInVerticalRange(int top, int bottom)
3022 {
3023     if (top >= bottom)
3024         return;
3025 
3026     RootInlineBox* lowestDirtyLine = lastRootBox();
3027     RootInlineBox* afterLowest = lowestDirtyLine;
3028     while (lowestDirtyLine && lowestDirtyLine->blockHeight() >= bottom) {
3029         afterLowest = lowestDirtyLine;
3030         lowestDirtyLine = lowestDirtyLine->prevRootBox();
3031     }
3032 
3033     while (afterLowest && afterLowest->blockHeight() >= top) {
3034         afterLowest->markDirty();
3035         afterLowest = afterLowest->prevRootBox();
3036     }
3037 }
3038 
clearFloats()3039 void RenderBlock::clearFloats()
3040 {
3041     // Inline blocks are covered by the isReplaced() check in the avoidFloats method.
3042     if (avoidsFloats() || isRoot() || isRenderView() || isFloatingOrPositioned() || isTableCell()) {
3043         if (m_floatingObjects)
3044             m_floatingObjects->clear();
3045         return;
3046     }
3047 
3048     typedef HashMap<RenderObject*, FloatingObject*> RendererToFloatInfoMap;
3049     RendererToFloatInfoMap floatMap;
3050 
3051     if (m_floatingObjects) {
3052         if (childrenInline()) {
3053             m_floatingObjects->first();
3054             while (FloatingObject* f = m_floatingObjects->take())
3055                 floatMap.add(f->m_renderer, f);
3056         } else
3057             m_floatingObjects->clear();
3058     }
3059 
3060     // Attempt to locate a previous sibling with overhanging floats.  We skip any elements that are
3061     // out of flow (like floating/positioned elements), and we also skip over any objects that may have shifted
3062     // to avoid floats.
3063     bool parentHasFloats = false;
3064     RenderObject* prev = previousSibling();
3065     while (prev && (prev->isFloatingOrPositioned() || !prev->isBox() || !prev->isRenderBlock() || toRenderBlock(prev)->avoidsFloats())) {
3066         if (prev->isFloating())
3067             parentHasFloats = true;
3068          prev = prev->previousSibling();
3069     }
3070 
3071     // First add in floats from the parent.
3072     int offset = y();
3073     if (parentHasFloats) {
3074         RenderBlock* parentBlock = toRenderBlock(parent());
3075         addIntrudingFloats(parentBlock, parentBlock->borderLeft() + parentBlock->paddingLeft(), offset);
3076     }
3077 
3078     int xoffset = 0;
3079     if (prev)
3080         offset -= toRenderBox(prev)->y();
3081     else if (parent()->isBox()) {
3082         prev = parent();
3083         xoffset += toRenderBox(prev)->borderLeft() + toRenderBox(prev)->paddingLeft();
3084     }
3085 
3086     // Add overhanging floats from the previous RenderBlock, but only if it has a float that intrudes into our space.
3087     if (!prev || !prev->isRenderBlock())
3088         return;
3089 
3090     RenderBlock* block = toRenderBlock(prev);
3091     if (block->m_floatingObjects && block->floatBottom() > offset)
3092         addIntrudingFloats(block, xoffset, offset);
3093 
3094     if (childrenInline()) {
3095         int changeTop = INT_MAX;
3096         int changeBottom = INT_MIN;
3097         if (m_floatingObjects) {
3098             for (FloatingObject* f = m_floatingObjects->first(); f; f = m_floatingObjects->next()) {
3099                 FloatingObject* oldFloatingObject = floatMap.get(f->m_renderer);
3100                 if (oldFloatingObject) {
3101                     if (f->m_width != oldFloatingObject->m_width || f->m_left != oldFloatingObject->m_left) {
3102                         changeTop = 0;
3103                         changeBottom = max(changeBottom, max(f->m_bottom, oldFloatingObject->m_bottom));
3104                     } else if (f->m_bottom != oldFloatingObject->m_bottom) {
3105                         changeTop = min(changeTop, min(f->m_bottom, oldFloatingObject->m_bottom));
3106                         changeBottom = max(changeBottom, max(f->m_bottom, oldFloatingObject->m_bottom));
3107                     }
3108 
3109                     floatMap.remove(f->m_renderer);
3110                     delete oldFloatingObject;
3111                 } else {
3112                     changeTop = 0;
3113                     changeBottom = max(changeBottom, f->m_bottom);
3114                 }
3115             }
3116         }
3117 
3118         RendererToFloatInfoMap::iterator end = floatMap.end();
3119         for (RendererToFloatInfoMap::iterator it = floatMap.begin(); it != end; ++it) {
3120             FloatingObject* floatingObject = (*it).second;
3121             if (!floatingObject->m_isDescendant) {
3122                 changeTop = 0;
3123                 changeBottom = max(changeBottom, floatingObject->m_bottom);
3124             }
3125         }
3126         deleteAllValues(floatMap);
3127 
3128         markLinesDirtyInVerticalRange(changeTop, changeBottom);
3129     }
3130 }
3131 
addOverhangingFloats(RenderBlock * child,int xoff,int yoff,bool makeChildPaintOtherFloats)3132 int RenderBlock::addOverhangingFloats(RenderBlock* child, int xoff, int yoff, bool makeChildPaintOtherFloats)
3133 {
3134     // Prevent floats from being added to the canvas by the root element, e.g., <html>.
3135     if (child->hasOverflowClip() || !child->containsFloats() || child->isRoot())
3136         return 0;
3137 
3138     int lowestFloatBottom = 0;
3139 
3140     // Floats that will remain the child's responsiblity to paint should factor into its
3141     // visual overflow.
3142     IntRect floatsOverflowRect;
3143     DeprecatedPtrListIterator<FloatingObject> it(*child->m_floatingObjects);
3144     for (FloatingObject* r; (r = it.current()); ++it) {
3145         int bottom = child->y() + r->m_bottom;
3146         lowestFloatBottom = max(lowestFloatBottom, bottom);
3147 
3148         if (bottom > height()) {
3149             // If the object is not in the list, we add it now.
3150             if (!containsFloat(r->m_renderer)) {
3151                 FloatingObject *floatingObj = new FloatingObject(r->type());
3152                 floatingObj->m_top = r->m_top - yoff;
3153                 floatingObj->m_bottom = r->m_bottom - yoff;
3154                 floatingObj->m_left = r->m_left - xoff;
3155                 floatingObj->m_width = r->m_width;
3156                 floatingObj->m_renderer = r->m_renderer;
3157 
3158                 // The nearest enclosing layer always paints the float (so that zindex and stacking
3159                 // behaves properly).  We always want to propagate the desire to paint the float as
3160                 // far out as we can, to the outermost block that overlaps the float, stopping only
3161                 // if we hit a self-painting layer boundary.
3162                 if (r->m_renderer->enclosingSelfPaintingLayer() == enclosingSelfPaintingLayer())
3163                     r->m_shouldPaint = false;
3164                 else
3165                     floatingObj->m_shouldPaint = false;
3166 
3167                 // We create the floating object list lazily.
3168                 if (!m_floatingObjects) {
3169                     m_floatingObjects = new DeprecatedPtrList<FloatingObject>;
3170                     m_floatingObjects->setAutoDelete(true);
3171                 }
3172                 m_floatingObjects->append(floatingObj);
3173             }
3174         } else if (makeChildPaintOtherFloats && !r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer() &&
3175                    r->m_renderer->isDescendantOf(child) && r->m_renderer->enclosingLayer() == child->enclosingLayer())
3176             // The float is not overhanging from this block, so if it is a descendant of the child, the child should
3177             // paint it (the other case is that it is intruding into the child), unless it has its own layer or enclosing
3178             // layer.
3179             // If makeChildPaintOtherFloats is false, it means that the child must already know about all the floats
3180             // it should paint.
3181             r->m_shouldPaint = true;
3182 
3183         if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) {
3184             IntRect floatOverflowRect = r->m_renderer->overflowRect(false);
3185             floatOverflowRect.move(r->m_left + r->m_renderer->marginLeft(), r->m_top + r->m_renderer->marginTop());
3186             floatsOverflowRect.unite(floatOverflowRect);
3187         }
3188     }
3189     child->addVisualOverflow(floatsOverflowRect);
3190     return lowestFloatBottom;
3191 }
3192 
addIntrudingFloats(RenderBlock * prev,int xoff,int yoff)3193 void RenderBlock::addIntrudingFloats(RenderBlock* prev, int xoff, int yoff)
3194 {
3195     // If the parent or previous sibling doesn't have any floats to add, don't bother.
3196     if (!prev->m_floatingObjects)
3197         return;
3198 
3199     DeprecatedPtrListIterator<FloatingObject> it(*prev->m_floatingObjects);
3200     for (FloatingObject *r; (r = it.current()); ++it) {
3201         if (r->m_bottom > yoff) {
3202             // The object may already be in our list. Check for it up front to avoid
3203             // creating duplicate entries.
3204             FloatingObject* f = 0;
3205             if (m_floatingObjects) {
3206                 DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
3207                 while ((f = it.current())) {
3208                     if (f->m_renderer == r->m_renderer) break;
3209                     ++it;
3210                 }
3211             }
3212             if (!f) {
3213                 FloatingObject *floatingObj = new FloatingObject(r->type());
3214                 floatingObj->m_top = r->m_top - yoff;
3215                 floatingObj->m_bottom = r->m_bottom - yoff;
3216                 floatingObj->m_left = r->m_left - xoff;
3217                 // Applying the child's margin makes no sense in the case where the child was passed in.
3218                 // since his own margin was added already through the subtraction of the |xoff| variable
3219                 // above.  |xoff| will equal -flow->marginLeft() in this case, so it's already been taken
3220                 // into account.  Only apply this code if |child| is false, since otherwise the left margin
3221                 // will get applied twice.
3222                 if (prev != parent())
3223                     floatingObj->m_left += prev->marginLeft();
3224                 floatingObj->m_left -= marginLeft();
3225                 floatingObj->m_shouldPaint = false;  // We are not in the direct inheritance chain for this float. We will never paint it.
3226                 floatingObj->m_width = r->m_width;
3227                 floatingObj->m_renderer = r->m_renderer;
3228 
3229                 // We create the floating object list lazily.
3230                 if (!m_floatingObjects) {
3231                     m_floatingObjects = new DeprecatedPtrList<FloatingObject>;
3232                     m_floatingObjects->setAutoDelete(true);
3233                 }
3234                 m_floatingObjects->append(floatingObj);
3235             }
3236         }
3237     }
3238 }
3239 
avoidsFloats() const3240 bool RenderBlock::avoidsFloats() const
3241 {
3242     // Floats can't intrude into our box if we have a non-auto column count or width.
3243     return RenderBox::avoidsFloats() || !style()->hasAutoColumnCount() || !style()->hasAutoColumnWidth();
3244 }
3245 
containsFloat(RenderObject * o)3246 bool RenderBlock::containsFloat(RenderObject* o)
3247 {
3248     if (m_floatingObjects) {
3249         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
3250         while (it.current()) {
3251             if (it.current()->m_renderer == o)
3252                 return true;
3253             ++it;
3254         }
3255     }
3256     return false;
3257 }
3258 
markAllDescendantsWithFloatsForLayout(RenderBox * floatToRemove,bool inLayout)3259 void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove, bool inLayout)
3260 {
3261     setChildNeedsLayout(true, !inLayout);
3262 
3263     if (floatToRemove)
3264         removeFloatingObject(floatToRemove);
3265 
3266     // Iterate over our children and mark them as needed.
3267     if (!childrenInline()) {
3268         for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
3269             if ((!floatToRemove && child->isFloatingOrPositioned()) || !child->isRenderBlock())
3270                 continue;
3271             RenderBlock* childBlock = toRenderBlock(child);
3272             if ((floatToRemove ? childBlock->containsFloat(floatToRemove) : childBlock->containsFloats()) || childBlock->shrinkToAvoidFloats())
3273                 childBlock->markAllDescendantsWithFloatsForLayout(floatToRemove, inLayout);
3274         }
3275     }
3276 }
3277 
getClearDelta(RenderBox * child,int yPos)3278 int RenderBlock::getClearDelta(RenderBox* child, int yPos)
3279 {
3280     // There is no need to compute clearance if we have no floats.
3281     if (!containsFloats())
3282         return 0;
3283 
3284     // At least one float is present.  We need to perform the clearance computation.
3285     bool clearSet = child->style()->clear() != CNONE;
3286     int bottom = 0;
3287     switch (child->style()->clear()) {
3288         case CNONE:
3289             break;
3290         case CLEFT:
3291             bottom = leftBottom();
3292             break;
3293         case CRIGHT:
3294             bottom = rightBottom();
3295             break;
3296         case CBOTH:
3297             bottom = floatBottom();
3298             break;
3299     }
3300 
3301     // 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).
3302     // FIXME: Note that the remaining space checks aren't quite accurate, since you should be able to clear only some floats (the minimum # needed
3303     // to fit) and not all (we should be using nextFloatBottomBelow and looping).
3304     // Do not allow tables to wrap in quirks or even in almost strict mode
3305     // (ebay on the PLT, finance.yahoo.com in the real world, versiontracker.com forces even almost strict mode not to work)
3306     int result = clearSet ? max(0, bottom - yPos) : 0;
3307     if (!result && child->avoidsFloats() && child->style()->width().isFixed() &&
3308         child->minPrefWidth() > lineWidth(yPos, false) && child->minPrefWidth() <= availableWidth() &&
3309         document()->inStrictMode())
3310         result = max(0, floatBottom() - yPos);
3311     return result;
3312 }
3313 
addVisualOverflow(const IntRect & r)3314 void RenderBlock::addVisualOverflow(const IntRect& r)
3315 {
3316     if (r.isEmpty())
3317         return;
3318     m_overflowLeft = min(m_overflowLeft, r.x());
3319     m_overflowWidth = max(m_overflowWidth, r.right());
3320     m_overflowTop = min(m_overflowTop, r.y());
3321     m_overflowHeight = max(m_overflowHeight, r.bottom());
3322 }
3323 
isPointInOverflowControl(HitTestResult & result,int _x,int _y,int _tx,int _ty)3324 bool RenderBlock::isPointInOverflowControl(HitTestResult& result, int _x, int _y, int _tx, int _ty)
3325 {
3326     if (!scrollsOverflow())
3327         return false;
3328 
3329     return layer()->hitTestOverflowControls(result, IntPoint(_x - _tx, _y - _ty));
3330 }
3331 
nodeAtPoint(const HitTestRequest & request,HitTestResult & result,int _x,int _y,int _tx,int _ty,HitTestAction hitTestAction)3332 bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
3333 {
3334     int tx = _tx + x();
3335     int ty = _ty + y();
3336 
3337     if (!isRenderView()) {
3338         // Check if we need to do anything at all.
3339         IntRect overflowBox = overflowRect(false);
3340         overflowBox.move(tx, ty);
3341         if (!overflowBox.contains(_x, _y))
3342             return false;
3343     }
3344 
3345     if ((hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) && isPointInOverflowControl(result, _x, _y, tx, ty)) {
3346         updateHitTestResult(result, IntPoint(_x - tx, _y - ty));
3347         return true;
3348     }
3349 
3350     // If we have clipping, then we can't have any spillout.
3351     bool useOverflowClip = hasOverflowClip() && !hasSelfPaintingLayer();
3352     bool useClip = (hasControlClip() || useOverflowClip);
3353     bool checkChildren = !useClip || (hasControlClip() ? controlClipRect(tx, ty).contains(_x, _y) : overflowClipRect(tx, ty).contains(_x, _y));
3354     if (checkChildren) {
3355         // Hit test descendants first.
3356         int scrolledX = tx;
3357         int scrolledY = ty;
3358         if (hasOverflowClip())
3359             layer()->subtractScrolledContentOffset(scrolledX, scrolledY);
3360 
3361         // Hit test contents if we don't have columns.
3362         if (!hasColumns() && hitTestContents(request, result, _x, _y, scrolledX, scrolledY, hitTestAction))
3363             return true;
3364 
3365         // Hit test our columns if we do have them.
3366         if (hasColumns() && hitTestColumns(request, result, _x, _y, scrolledX, scrolledY, hitTestAction))
3367             return true;
3368 
3369         // Hit test floats.
3370         if (hitTestAction == HitTestFloat && m_floatingObjects) {
3371             if (isRenderView()) {
3372                 scrolledX += toRenderView(this)->frameView()->scrollX();
3373                 scrolledY += toRenderView(this)->frameView()->scrollY();
3374             }
3375 
3376             FloatingObject* o;
3377             DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
3378             for (it.toLast(); (o = it.current()); --it) {
3379                 if (o->m_shouldPaint && !o->m_renderer->hasSelfPaintingLayer()) {
3380                     int xoffset = scrolledX + o->m_left + o->m_renderer->marginLeft() - o->m_renderer->x();
3381                     int yoffset =  scrolledY + o->m_top + o->m_renderer->marginTop() - o->m_renderer->y();
3382                     if (o->m_renderer->hitTest(request, result, IntPoint(_x, _y), xoffset, yoffset)) {
3383                         updateHitTestResult(result, IntPoint(_x - xoffset, _y - yoffset));
3384                         return true;
3385                     }
3386                 }
3387             }
3388         }
3389     }
3390 
3391     // Now hit test our background
3392     if (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) {
3393         IntRect boundsRect(tx, ty, width(), height());
3394         if (visibleToHitTesting() && boundsRect.contains(_x, _y)) {
3395             updateHitTestResult(result, IntPoint(_x - tx, _y - ty));
3396             return true;
3397         }
3398     }
3399 
3400     return false;
3401 }
3402 
hitTestColumns(const HitTestRequest & request,HitTestResult & result,int x,int y,int tx,int ty,HitTestAction hitTestAction)3403 bool RenderBlock::hitTestColumns(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
3404 {
3405     // We need to do multiple passes, breaking up our hit testing into strips.
3406     // We can always go left to right, since column contents are clipped (meaning that there
3407     // can't be any overlap).
3408     int currXOffset = 0;
3409     int currYOffset = 0;
3410     int colGap = columnGap();
3411     Vector<IntRect>* colRects = columnRects();
3412     for (unsigned i = 0; i < colRects->size(); i++) {
3413         IntRect colRect = colRects->at(i);
3414         colRect.move(tx, ty);
3415 
3416         if (colRect.contains(x, y)) {
3417             // The point is inside this column.
3418             // Adjust tx and ty to change where we hit test.
3419 
3420             int finalX = tx + currXOffset;
3421             int finalY = ty + currYOffset;
3422             return hitTestContents(request, result, x, y, finalX, finalY, hitTestAction);
3423         }
3424 
3425         // Move to the next position.
3426         if (style()->direction() == LTR)
3427             currXOffset += colRect.width() + colGap;
3428         else
3429             currXOffset -= (colRect.width() + colGap);
3430 
3431         currYOffset -= colRect.height();
3432     }
3433 
3434     return false;
3435 }
3436 
hitTestContents(const HitTestRequest & request,HitTestResult & result,int x,int y,int tx,int ty,HitTestAction hitTestAction)3437 bool RenderBlock::hitTestContents(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
3438 {
3439     if (childrenInline() && !isTable()) {
3440         // We have to hit-test our line boxes.
3441         if (m_lineBoxes.hitTest(this, request, result, x, y, tx, ty, hitTestAction)) {
3442             updateHitTestResult(result, IntPoint(x - tx, y - ty));
3443             return true;
3444         }
3445     } else {
3446         // Hit test our children.
3447         HitTestAction childHitTest = hitTestAction;
3448         if (hitTestAction == HitTestChildBlockBackgrounds)
3449             childHitTest = HitTestChildBlockBackground;
3450         for (RenderBox* child = lastChildBox(); child; child = child->previousSiblingBox()) {
3451             if (!child->hasSelfPaintingLayer() && !child->isFloating() && child->nodeAtPoint(request, result, x, y, tx, ty, childHitTest)) {
3452                 updateHitTestResult(result, IntPoint(x - tx, y - ty));
3453                 return true;
3454             }
3455         }
3456     }
3457 
3458     return false;
3459 }
3460 
positionForBox(InlineBox * box,bool start) const3461 Position RenderBlock::positionForBox(InlineBox *box, bool start) const
3462 {
3463     if (!box)
3464         return Position();
3465 
3466     if (!box->renderer()->node())
3467         return Position(node(), start ? caretMinOffset() : caretMaxOffset());
3468 
3469     if (!box->isInlineTextBox())
3470         return Position(box->renderer()->node(), start ? box->renderer()->caretMinOffset() : box->renderer()->caretMaxOffset());
3471 
3472     InlineTextBox *textBox = static_cast<InlineTextBox *>(box);
3473     return Position(box->renderer()->node(), start ? textBox->start() : textBox->start() + textBox->len());
3474 }
3475 
positionForRenderer(RenderObject * renderer,bool start) const3476 Position RenderBlock::positionForRenderer(RenderObject* renderer, bool start) const
3477 {
3478     if (!renderer)
3479         return Position(node(), 0);
3480 
3481     Node* n = renderer->node() ? renderer->node() : node();
3482     if (!n)
3483         return Position();
3484 
3485     ASSERT(renderer == n->renderer());
3486 
3487     int offset = start ? renderer->caretMinOffset() : renderer->caretMaxOffset();
3488 
3489     // FIXME: This was a runtime check that seemingly couldn't fail; changed it to an assertion for now.
3490     ASSERT(!n->isCharacterDataNode() || renderer->isText());
3491 
3492     return Position(n, offset);
3493 }
3494 
3495 // FIXME: This function should go on RenderObject as an instance method. Then
3496 // all cases in which positionForPoint recurs could call this instead to
3497 // prevent crossing editable boundaries. This would require many tests.
positionForPointRespectingEditingBoundaries(RenderBox * parent,RenderBox * child,const IntPoint & pointInParentCoordinates)3498 static VisiblePosition positionForPointRespectingEditingBoundaries(RenderBox* parent, RenderBox* child, const IntPoint& pointInParentCoordinates)
3499 {
3500     IntPoint pointInChildCoordinates(pointInParentCoordinates - child->location());
3501 
3502     // If this is an anonymous renderer, we just recur normally
3503     Node* childNode = child->node();
3504     if (!childNode)
3505         return child->positionForPoint(pointInChildCoordinates);
3506 
3507     // Otherwise, first make sure that the editability of the parent and child agree.
3508     // If they don't agree, then we return a visible position just before or after the child
3509     RenderObject* ancestor = parent;
3510     while (ancestor && !ancestor->node())
3511         ancestor = ancestor->parent();
3512 
3513     // If we can't find an ancestor to check editability on, or editability is unchanged, we recur like normal
3514     if (!ancestor || ancestor->node()->isContentEditable() == childNode->isContentEditable())
3515         return child->positionForPoint(pointInChildCoordinates);
3516 
3517     // Otherwise return before or after the child, depending on if the click was left or right of the child
3518     int childMidX = child->width() / 2;
3519     if (pointInChildCoordinates.x() < childMidX)
3520         return ancestor->createVisiblePosition(childNode->nodeIndex(), DOWNSTREAM);
3521     return ancestor->createVisiblePosition(childNode->nodeIndex() + 1, UPSTREAM);
3522 }
3523 
positionForPointWithInlineChildren(const IntPoint & pointInContents)3524 VisiblePosition RenderBlock::positionForPointWithInlineChildren(const IntPoint& pointInContents)
3525 {
3526     ASSERT(childrenInline());
3527 
3528     if (!firstRootBox())
3529         return createVisiblePosition(0, DOWNSTREAM);
3530 
3531     // look for the closest line box in the root box which is at the passed-in y coordinate
3532     InlineBox* closestBox = 0;
3533     RootInlineBox* firstRootBoxWithChildren = 0;
3534     RootInlineBox* lastRootBoxWithChildren = 0;
3535     for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) {
3536         if (!root->firstChild())
3537             continue;
3538         if (!firstRootBoxWithChildren)
3539             firstRootBoxWithChildren = root;
3540         lastRootBoxWithChildren = root;
3541 
3542         // set the bottom based on whether there is a next root box
3543         // FIXME: This will consider nextRootBox even if it has no children, and maybe it shouldn't.
3544         int bottom;
3545         if (root->nextRootBox()) {
3546             // FIXME: We would prefer to make the break point halfway between the bottom
3547             // of the previous root box and the top of the next root box.
3548             bottom = root->nextRootBox()->topOverflow();
3549         } else
3550             bottom = root->bottomOverflow() + verticalLineClickFudgeFactor;
3551 
3552         // check if this root line box is located at this y coordinate
3553         if (pointInContents.y() < bottom) {
3554             closestBox = root->closestLeafChildForXPos(pointInContents.x());
3555             if (closestBox)
3556                 break;
3557         }
3558     }
3559 
3560     Settings* settings = document()->settings();
3561     bool useWindowsBehavior = settings && settings->editingBehavior() == EditingWindowsBehavior;
3562 
3563     if (useWindowsBehavior && !closestBox && lastRootBoxWithChildren) {
3564         // y coordinate is below last root line box, pretend we hit it
3565         closestBox = lastRootBoxWithChildren->closestLeafChildForXPos(pointInContents.x());
3566     }
3567 
3568     if (closestBox) {
3569         if (!useWindowsBehavior && pointInContents.y() < firstRootBoxWithChildren->topOverflow() - verticalLineClickFudgeFactor) {
3570             // y coordinate is above first root line box, so return the start of the first
3571             return VisiblePosition(positionForBox(firstRootBoxWithChildren->firstLeafChild(), true), DOWNSTREAM);
3572         }
3573 
3574         // pass the box a y position that is inside it
3575         return closestBox->renderer()->positionForPoint(IntPoint(pointInContents.x(), closestBox->m_y));
3576     }
3577 
3578     if (lastRootBoxWithChildren) {
3579         // We hit this case for Mac behavior when the Y coordinate is below the last box.
3580         ASSERT(!useWindowsBehavior);
3581         return VisiblePosition(positionForBox(lastRootBoxWithChildren->lastLeafChild(), false), DOWNSTREAM);
3582     }
3583 
3584     // Can't reach this. We have a root line box, but it has no kids.
3585     // FIXME: This should ASSERT_NOT_REACHED(), but clicking on placeholder text
3586     // seems to hit this code path.
3587     return createVisiblePosition(0, DOWNSTREAM);
3588 }
3589 
isChildHitTestCandidate(RenderBox * box)3590 static inline bool isChildHitTestCandidate(RenderBox* box)
3591 {
3592     return box->height() && box->style()->visibility() == VISIBLE && !box->isFloatingOrPositioned();
3593 }
3594 
positionForPoint(const IntPoint & point)3595 VisiblePosition RenderBlock::positionForPoint(const IntPoint& point)
3596 {
3597     if (isTable())
3598         return RenderBox::positionForPoint(point);
3599 
3600     if (isReplaced()) {
3601         if (point.y() < 0 || (point.y() < height() && point.x() < 0))
3602             return createVisiblePosition(caretMinOffset(), DOWNSTREAM);
3603         if (point.y() >= height() || (point.y() >= 0 && point.x() >= width()))
3604             return createVisiblePosition(caretMaxOffset(), DOWNSTREAM);
3605     }
3606 
3607     int contentsX = point.x();
3608     int contentsY = point.y();
3609     offsetForContents(contentsX, contentsY);
3610     IntPoint pointInContents(contentsX, contentsY);
3611 
3612     if (childrenInline())
3613         return positionForPointWithInlineChildren(pointInContents);
3614 
3615     if (lastChildBox() && contentsY > lastChildBox()->y()) {
3616         for (RenderBox* childBox = lastChildBox(); childBox; childBox = childBox->previousSiblingBox()) {
3617             if (isChildHitTestCandidate(childBox))
3618                 return positionForPointRespectingEditingBoundaries(this, childBox, pointInContents);
3619         }
3620     } else {
3621         for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) {
3622             // We hit child if our click is above the bottom of its padding box (like IE6/7 and FF3).
3623             if (isChildHitTestCandidate(childBox) && contentsY < childBox->frameRect().bottom())
3624                 return positionForPointRespectingEditingBoundaries(this, childBox, pointInContents);
3625         }
3626     }
3627 
3628     // We only get here if there are no hit test candidate children below the click.
3629     return RenderBox::positionForPoint(point);
3630 }
3631 
offsetForContents(int & tx,int & ty) const3632 void RenderBlock::offsetForContents(int& tx, int& ty) const
3633 {
3634     if (hasOverflowClip())
3635         layer()->addScrolledContentOffset(tx, ty);
3636 
3637     if (hasColumns()) {
3638         IntPoint contentsPoint(tx, ty);
3639         adjustPointToColumnContents(contentsPoint);
3640         tx = contentsPoint.x();
3641         ty = contentsPoint.y();
3642     }
3643 }
3644 
availableWidth() const3645 int RenderBlock::availableWidth() const
3646 {
3647     // If we have multiple columns, then the available width is reduced to our column width.
3648     if (hasColumns())
3649         return desiredColumnWidth();
3650     return contentWidth();
3651 }
3652 
columnGap() const3653 int RenderBlock::columnGap() const
3654 {
3655     if (style()->hasNormalColumnGap())
3656         return style()->fontDescription().computedPixelSize(); // "1em" is recommended as the normal gap setting. Matches <p> margins.
3657     return static_cast<int>(style()->columnGap());
3658 }
3659 
calcColumnWidth()3660 void RenderBlock::calcColumnWidth()
3661 {
3662     // Calculate our column width and column count.
3663     unsigned desiredColumnCount = 1;
3664     int desiredColumnWidth = contentWidth();
3665 
3666     // For now, we don't support multi-column layouts when printing, since we have to do a lot of work for proper pagination.
3667     if (document()->printing() || (style()->hasAutoColumnCount() && style()->hasAutoColumnWidth())) {
3668         setDesiredColumnCountAndWidth(desiredColumnCount, desiredColumnWidth);
3669         return;
3670     }
3671 
3672     int availWidth = desiredColumnWidth;
3673     int colGap = columnGap();
3674     int colWidth = max(1, static_cast<int>(style()->columnWidth()));
3675     int colCount = max(1, static_cast<int>(style()->columnCount()));
3676 
3677     if (style()->hasAutoColumnWidth()) {
3678         if ((colCount - 1) * colGap < availWidth) {
3679             desiredColumnCount = colCount;
3680             desiredColumnWidth = (availWidth - (desiredColumnCount - 1) * colGap) / desiredColumnCount;
3681         } else if (colGap < availWidth) {
3682             desiredColumnCount = availWidth / colGap;
3683             desiredColumnWidth = (availWidth - (desiredColumnCount - 1) * colGap) / desiredColumnCount;
3684         }
3685     } else if (style()->hasAutoColumnCount()) {
3686         if (colWidth < availWidth) {
3687             desiredColumnCount = (availWidth + colGap) / (colWidth + colGap);
3688             desiredColumnWidth = (availWidth - (desiredColumnCount - 1) * colGap) / desiredColumnCount;
3689         }
3690     } else {
3691         // Both are set.
3692         if (colCount * colWidth + (colCount - 1) * colGap <= availWidth) {
3693             desiredColumnCount = colCount;
3694             desiredColumnWidth = colWidth;
3695         } else if (colWidth < availWidth) {
3696             desiredColumnCount = (availWidth + colGap) / (colWidth + colGap);
3697             desiredColumnWidth = (availWidth - (desiredColumnCount - 1) * colGap) / desiredColumnCount;
3698         }
3699     }
3700     setDesiredColumnCountAndWidth(desiredColumnCount, desiredColumnWidth);
3701 }
3702 
setDesiredColumnCountAndWidth(int count,int width)3703 void RenderBlock::setDesiredColumnCountAndWidth(int count, int width)
3704 {
3705     if (count == 1) {
3706         if (hasColumns()) {
3707             delete gColumnInfoMap->take(this);
3708             setHasColumns(false);
3709         }
3710     } else {
3711         ColumnInfo* info;
3712         if (hasColumns())
3713             info = gColumnInfoMap->get(this);
3714         else {
3715             if (!gColumnInfoMap)
3716                 gColumnInfoMap = new ColumnInfoMap;
3717             info = new ColumnInfo;
3718             gColumnInfoMap->add(this, info);
3719             setHasColumns(true);
3720         }
3721         info->m_desiredColumnCount = count;
3722         info->m_desiredColumnWidth = width;
3723     }
3724 }
3725 
desiredColumnWidth() const3726 int RenderBlock::desiredColumnWidth() const
3727 {
3728     if (!hasColumns())
3729         return contentWidth();
3730     return gColumnInfoMap->get(this)->m_desiredColumnWidth;
3731 }
3732 
desiredColumnCount() const3733 unsigned RenderBlock::desiredColumnCount() const
3734 {
3735     if (!hasColumns())
3736         return 1;
3737     return gColumnInfoMap->get(this)->m_desiredColumnCount;
3738 }
3739 
columnRects() const3740 Vector<IntRect>* RenderBlock::columnRects() const
3741 {
3742     if (!hasColumns())
3743         return 0;
3744     return &gColumnInfoMap->get(this)->m_columnRects;
3745 }
3746 
layoutColumns(int endOfContent)3747 int RenderBlock::layoutColumns(int endOfContent)
3748 {
3749     // Don't do anything if we have no columns
3750     if (!hasColumns())
3751         return -1;
3752 
3753     ColumnInfo* info = gColumnInfoMap->get(this);
3754     int desiredColumnWidth = info->m_desiredColumnWidth;
3755     int desiredColumnCount = info->m_desiredColumnCount;
3756     Vector<IntRect>* columnRects = &info->m_columnRects;
3757 
3758     bool computeIntrinsicHeight = (endOfContent == -1);
3759 
3760     // Fill the columns in to the available height.  Attempt to balance the height of the columns
3761     int availableHeight = contentHeight();
3762     int colHeight = computeIntrinsicHeight ? availableHeight / desiredColumnCount : availableHeight;
3763 
3764     // Add in half our line-height to help with best-guess initial balancing.
3765     int columnSlop = lineHeight(false) / 2;
3766     int remainingSlopSpace = columnSlop * desiredColumnCount;
3767 
3768     if (computeIntrinsicHeight)
3769         colHeight += columnSlop;
3770 
3771     int colGap = columnGap();
3772 
3773     // Compute a collection of column rects.
3774     columnRects->clear();
3775 
3776     // Then we do a simulated "paint" into the column slices and allow the content to slightly adjust our individual column rects.
3777     // FIXME: We need to take into account layers that are affected by the columns as well here so that they can have an opportunity
3778     // to adjust column rects also.
3779     RenderView* v = view();
3780     int left = borderLeft() + paddingLeft();
3781     int top = borderTop() + paddingTop();
3782     int currX = style()->direction() == LTR ? borderLeft() + paddingLeft() : borderLeft() + paddingLeft() + contentWidth() - desiredColumnWidth;
3783     int currY = top;
3784     unsigned colCount = desiredColumnCount;
3785     int maxColBottom = borderTop() + paddingTop();
3786     int contentBottom = top + availableHeight;
3787     for (unsigned i = 0; i < colCount; i++) {
3788         // If we aren't constrained, then the last column can just get all the remaining space.
3789         if (computeIntrinsicHeight && i == colCount - 1)
3790             colHeight = availableHeight;
3791 
3792         // This represents the real column position.
3793         IntRect colRect(currX, top, desiredColumnWidth, colHeight);
3794 
3795         // For the simulated paint, we pretend like everything is in one long strip.
3796         IntRect pageRect(left, currY, desiredColumnWidth, colHeight);
3797         v->setPrintRect(pageRect);
3798         v->setTruncatedAt(currY + colHeight);
3799         GraphicsContext context((PlatformGraphicsContext*)0);
3800         RenderObject::PaintInfo paintInfo(&context, pageRect, PaintPhaseForeground, false, 0, 0);
3801 
3802         setHasColumns(false);
3803         paintObject(paintInfo, 0, 0);
3804         setHasColumns(true);
3805 
3806         int adjustedBottom = v->bestTruncatedAt();
3807         if (adjustedBottom <= currY)
3808             adjustedBottom = currY + colHeight;
3809 
3810         colRect.setHeight(adjustedBottom - currY);
3811 
3812         // Add in the lost space to the subsequent columns.
3813         // FIXME: This will create a "staircase" effect if there are enough columns, but the effect should be pretty subtle.
3814         if (computeIntrinsicHeight) {
3815             int lostSpace = colHeight - colRect.height();
3816             if (lostSpace > remainingSlopSpace) {
3817                 // Redestribute the space among the remaining columns.
3818                 int spaceToRedistribute = lostSpace - remainingSlopSpace;
3819                 int remainingColumns = colCount - i + 1;
3820                 colHeight += spaceToRedistribute / remainingColumns;
3821             }
3822             remainingSlopSpace = max(0, remainingSlopSpace - lostSpace);
3823         }
3824 
3825         if (style()->direction() == LTR)
3826             currX += desiredColumnWidth + colGap;
3827         else
3828             currX -= (desiredColumnWidth + colGap);
3829 
3830         currY += colRect.height();
3831         availableHeight -= colRect.height();
3832 
3833         maxColBottom = max(colRect.bottom(), maxColBottom);
3834 
3835         columnRects->append(colRect);
3836 
3837         // Start adding in more columns as long as there's still content left.
3838         if (currY < endOfContent && i == colCount - 1 && (computeIntrinsicHeight || contentHeight()))
3839             colCount++;
3840     }
3841 
3842     m_overflowWidth = max(width(), currX - colGap);
3843     m_overflowLeft = min(0, currX + desiredColumnWidth + colGap);
3844 
3845     m_overflowHeight = maxColBottom;
3846     int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
3847 
3848     if (computeIntrinsicHeight)
3849         setHeight(m_overflowHeight + toAdd);
3850 
3851     v->setPrintRect(IntRect());
3852     v->setTruncatedAt(0);
3853 
3854     ASSERT(colCount == columnRects->size());
3855 
3856     return contentBottom;
3857 }
3858 
adjustPointToColumnContents(IntPoint & point) const3859 void RenderBlock::adjustPointToColumnContents(IntPoint& point) const
3860 {
3861     // Just bail if we have no columns.
3862     if (!hasColumns())
3863         return;
3864 
3865     Vector<IntRect>* colRects = columnRects();
3866 
3867     // Determine which columns we intersect.
3868     int colGap = columnGap();
3869     int leftGap = colGap / 2;
3870     IntPoint columnPoint(colRects->at(0).location());
3871     int yOffset = 0;
3872     for (unsigned i = 0; i < colRects->size(); i++) {
3873         // Add in half the column gap to the left and right of the rect.
3874         IntRect colRect = colRects->at(i);
3875         IntRect gapAndColumnRect(colRect.x() - leftGap, colRect.y(), colRect.width() + colGap, colRect.height());
3876 
3877         if (gapAndColumnRect.contains(point)) {
3878             // We're inside the column.  Translate the x and y into our column coordinate space.
3879             point.move(columnPoint.x() - colRect.x(), yOffset);
3880             return;
3881         }
3882 
3883         // Move to the next position.
3884         yOffset += colRect.height();
3885     }
3886 }
3887 
adjustRectForColumns(IntRect & r) const3888 void RenderBlock::adjustRectForColumns(IntRect& r) const
3889 {
3890     // Just bail if we have no columns.
3891     if (!hasColumns())
3892         return;
3893 
3894     Vector<IntRect>* colRects = columnRects();
3895 
3896     // Begin with a result rect that is empty.
3897     IntRect result;
3898 
3899     // Determine which columns we intersect.
3900     int currXOffset = 0;
3901     int currYOffset = 0;
3902     int colGap = columnGap();
3903     for (unsigned i = 0; i < colRects->size(); i++) {
3904         IntRect colRect = colRects->at(i);
3905 
3906         IntRect repaintRect = r;
3907         repaintRect.move(currXOffset, currYOffset);
3908 
3909         repaintRect.intersect(colRect);
3910 
3911         result.unite(repaintRect);
3912 
3913         // Move to the next position.
3914         if (style()->direction() == LTR)
3915             currXOffset += colRect.width() + colGap;
3916         else
3917             currXOffset -= (colRect.width() + colGap);
3918 
3919         currYOffset -= colRect.height();
3920     }
3921 
3922     r = result;
3923 }
3924 
calcPrefWidths()3925 void RenderBlock::calcPrefWidths()
3926 {
3927     ASSERT(prefWidthsDirty());
3928 
3929     updateFirstLetter();
3930 
3931     if (!isTableCell() && style()->width().isFixed() && style()->width().value() > 0)
3932         m_minPrefWidth = m_maxPrefWidth = calcContentBoxWidth(style()->width().value());
3933     else {
3934         m_minPrefWidth = 0;
3935         m_maxPrefWidth = 0;
3936 
3937         if (childrenInline())
3938             calcInlinePrefWidths();
3939         else
3940             calcBlockPrefWidths();
3941 
3942         m_maxPrefWidth = max(m_minPrefWidth, m_maxPrefWidth);
3943 
3944         if (!style()->autoWrap() && childrenInline()) {
3945             m_minPrefWidth = m_maxPrefWidth;
3946 
3947             // A horizontal marquee with inline children has no minimum width.
3948             if (layer() && layer()->marquee() && layer()->marquee()->isHorizontal())
3949                 m_minPrefWidth = 0;
3950         }
3951 
3952         if (isTableCell()) {
3953             Length w = toRenderTableCell(this)->styleOrColWidth();
3954             if (w.isFixed() && w.value() > 0)
3955                 m_maxPrefWidth = max(m_minPrefWidth, calcContentBoxWidth(w.value()));
3956         }
3957     }
3958 
3959     if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
3960         m_maxPrefWidth = max(m_maxPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
3961         m_minPrefWidth = max(m_minPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
3962     }
3963 
3964     if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
3965         m_maxPrefWidth = min(m_maxPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
3966         m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
3967     }
3968 
3969     int toAdd = 0;
3970     toAdd = borderLeft() + borderRight() + paddingLeft() + paddingRight();
3971 
3972     if (hasOverflowClip() && style()->overflowY() == OSCROLL)
3973         toAdd += verticalScrollbarWidth();
3974 
3975     m_minPrefWidth += toAdd;
3976     m_maxPrefWidth += toAdd;
3977 
3978     setPrefWidthsDirty(false);
3979 }
3980 
3981 struct InlineMinMaxIterator {
3982 /* InlineMinMaxIterator is a class that will iterate over all render objects that contribute to
3983    inline min/max width calculations.  Note the following about the way it walks:
3984    (1) Positioned content is skipped (since it does not contribute to min/max width of a block)
3985    (2) We do not drill into the children of floats or replaced elements, since you can't break
3986        in the middle of such an element.
3987    (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side can have
3988        distinct borders/margin/padding that contribute to the min/max width.
3989 */
3990     RenderObject* parent;
3991     RenderObject* current;
3992     bool endOfInline;
3993 
InlineMinMaxIteratorWebCore::InlineMinMaxIterator3994     InlineMinMaxIterator(RenderObject* p, bool end = false)
3995         :parent(p), current(p), endOfInline(end) {}
3996 
3997     RenderObject* next();
3998 };
3999 
next()4000 RenderObject* InlineMinMaxIterator::next()
4001 {
4002     RenderObject* result = 0;
4003     bool oldEndOfInline = endOfInline;
4004     endOfInline = false;
4005     while (current || current == parent) {
4006         if (!oldEndOfInline &&
4007             (current == parent ||
4008              (!current->isFloating() && !current->isReplaced() && !current->isPositioned())))
4009             result = current->firstChild();
4010         if (!result) {
4011             // We hit the end of our inline. (It was empty, e.g., <span></span>.)
4012             if (!oldEndOfInline && current->isRenderInline()) {
4013                 result = current;
4014                 endOfInline = true;
4015                 break;
4016             }
4017 
4018             while (current && current != parent) {
4019                 result = current->nextSibling();
4020                 if (result) break;
4021                 current = current->parent();
4022                 if (current && current != parent && current->isRenderInline()) {
4023                     result = current;
4024                     endOfInline = true;
4025                     break;
4026                 }
4027             }
4028         }
4029 
4030         if (!result)
4031             break;
4032 
4033         if (!result->isPositioned() && (result->isText() || result->isFloating() || result->isReplaced() || result->isRenderInline()))
4034              break;
4035 
4036         current = result;
4037         result = 0;
4038     }
4039 
4040     // Update our position.
4041     current = result;
4042     return current;
4043 }
4044 
getBPMWidth(int childValue,Length cssUnit)4045 static int getBPMWidth(int childValue, Length cssUnit)
4046 {
4047     if (cssUnit.type() != Auto)
4048         return (cssUnit.isFixed() ? cssUnit.value() : childValue);
4049     return 0;
4050 }
4051 
getBorderPaddingMargin(const RenderBoxModelObject * child,bool endOfInline)4052 static int getBorderPaddingMargin(const RenderBoxModelObject* child, bool endOfInline)
4053 {
4054     RenderStyle* cstyle = child->style();
4055     int result = 0;
4056     bool leftSide = (cstyle->direction() == LTR) ? !endOfInline : endOfInline;
4057     result += getBPMWidth((leftSide ? child->marginLeft() : child->marginRight()),
4058                           (leftSide ? cstyle->marginLeft() :
4059                                       cstyle->marginRight()));
4060     result += getBPMWidth((leftSide ? child->paddingLeft() : child->paddingRight()),
4061                           (leftSide ? cstyle->paddingLeft() :
4062                                       cstyle->paddingRight()));
4063     result += leftSide ? child->borderLeft() : child->borderRight();
4064     return result;
4065 }
4066 
stripTrailingSpace(int & inlineMax,int & inlineMin,RenderObject * trailingSpaceChild)4067 static inline void stripTrailingSpace(int& inlineMax, int& inlineMin,
4068                                       RenderObject* trailingSpaceChild)
4069 {
4070     if (trailingSpaceChild && trailingSpaceChild->isText()) {
4071         // Collapse away the trailing space at the end of a block.
4072         RenderText* t = toRenderText(trailingSpaceChild);
4073         const UChar space = ' ';
4074         const Font& font = t->style()->font(); // FIXME: This ignores first-line.
4075         int spaceWidth = font.width(TextRun(&space, 1));
4076         inlineMax -= spaceWidth + font.wordSpacing();
4077         if (inlineMin > inlineMax)
4078             inlineMin = inlineMax;
4079     }
4080 }
4081 
calcInlinePrefWidths()4082 void RenderBlock::calcInlinePrefWidths()
4083 {
4084     int inlineMax = 0;
4085     int inlineMin = 0;
4086 
4087     int cw = containingBlock()->contentWidth();
4088 
4089     // If we are at the start of a line, we want to ignore all white-space.
4090     // Also strip spaces if we previously had text that ended in a trailing space.
4091     bool stripFrontSpaces = true;
4092     RenderObject* trailingSpaceChild = 0;
4093 
4094     // Firefox and Opera will allow a table cell to grow to fit an image inside it under
4095     // very specific cirucumstances (in order to match common WinIE renderings).
4096     // Not supporting the quirk has caused us to mis-render some real sites. (See Bugzilla 10517.)
4097     bool allowImagesToBreak = !style()->htmlHacks() || !isTableCell() || !style()->width().isIntrinsicOrAuto();
4098 
4099     bool autoWrap, oldAutoWrap;
4100     autoWrap = oldAutoWrap = style()->autoWrap();
4101 
4102     InlineMinMaxIterator childIterator(this);
4103     bool addedTextIndent = false; // Only gets added in once.
4104     RenderObject* prevFloat = 0;
4105     RenderObject* previousLeaf = 0;
4106     while (RenderObject* child = childIterator.next()) {
4107         autoWrap = child->isReplaced() ? child->parent()->style()->autoWrap() :
4108             child->style()->autoWrap();
4109 
4110         if (!child->isBR()) {
4111             // Step One: determine whether or not we need to go ahead and
4112             // terminate our current line.  Each discrete chunk can become
4113             // the new min-width, if it is the widest chunk seen so far, and
4114             // it can also become the max-width.
4115 
4116             // Children fall into three categories:
4117             // (1) An inline flow object.  These objects always have a min/max of 0,
4118             // and are included in the iteration solely so that their margins can
4119             // be added in.
4120             //
4121             // (2) An inline non-text non-flow object, e.g., an inline replaced element.
4122             // These objects can always be on a line by themselves, so in this situation
4123             // we need to go ahead and break the current line, and then add in our own
4124             // margins and min/max width on its own line, and then terminate the line.
4125             //
4126             // (3) A text object.  Text runs can have breakable characters at the start,
4127             // the middle or the end.  They may also lose whitespace off the front if
4128             // we're already ignoring whitespace.  In order to compute accurate min-width
4129             // information, we need three pieces of information.
4130             // (a) the min-width of the first non-breakable run.  Should be 0 if the text string
4131             // starts with whitespace.
4132             // (b) the min-width of the last non-breakable run. Should be 0 if the text string
4133             // ends with whitespace.
4134             // (c) the min/max width of the string (trimmed for whitespace).
4135             //
4136             // If the text string starts with whitespace, then we need to go ahead and
4137             // terminate our current line (unless we're already in a whitespace stripping
4138             // mode.
4139             //
4140             // If the text string has a breakable character in the middle, but didn't start
4141             // with whitespace, then we add the width of the first non-breakable run and
4142             // then end the current line.  We then need to use the intermediate min/max width
4143             // values (if any of them are larger than our current min/max).  We then look at
4144             // the width of the last non-breakable run and use that to start a new line
4145             // (unless we end in whitespace).
4146             RenderStyle* cstyle = child->style();
4147             int childMin = 0;
4148             int childMax = 0;
4149 
4150             if (!child->isText()) {
4151                 // Case (1) and (2).  Inline replaced and inline flow elements.
4152                 if (child->isRenderInline()) {
4153                     // Add in padding/border/margin from the appropriate side of
4154                     // the element.
4155                     int bpm = getBorderPaddingMargin(toRenderInline(child), childIterator.endOfInline);
4156                     childMin += bpm;
4157                     childMax += bpm;
4158 
4159                     inlineMin += childMin;
4160                     inlineMax += childMax;
4161 
4162                     child->setPrefWidthsDirty(false);
4163                 } else {
4164                     // Inline replaced elts add in their margins to their min/max values.
4165                     int margins = 0;
4166                     Length leftMargin = cstyle->marginLeft();
4167                     Length rightMargin = cstyle->marginRight();
4168                     if (leftMargin.isFixed())
4169                         margins += leftMargin.value();
4170                     if (rightMargin.isFixed())
4171                         margins += rightMargin.value();
4172                     childMin += margins;
4173                     childMax += margins;
4174                 }
4175             }
4176 
4177             if (!child->isRenderInline() && !child->isText()) {
4178                 // Case (2). Inline replaced elements and floats.
4179                 // Go ahead and terminate the current line as far as
4180                 // minwidth is concerned.
4181                 childMin += child->minPrefWidth();
4182                 childMax += child->maxPrefWidth();
4183 
4184                 bool clearPreviousFloat;
4185                 if (child->isFloating()) {
4186                     clearPreviousFloat = (prevFloat
4187                         && ((prevFloat->style()->floating() == FLEFT && (child->style()->clear() & CLEFT))
4188                             || (prevFloat->style()->floating() == FRIGHT && (child->style()->clear() & CRIGHT))));
4189                     prevFloat = child;
4190                 } else
4191                     clearPreviousFloat = false;
4192 
4193                 bool canBreakReplacedElement = !child->isImage() || allowImagesToBreak;
4194                 if ((canBreakReplacedElement && (autoWrap || oldAutoWrap)) || clearPreviousFloat) {
4195                     m_minPrefWidth = max(inlineMin, m_minPrefWidth);
4196                     inlineMin = 0;
4197                 }
4198 
4199                 // If we're supposed to clear the previous float, then terminate maxwidth as well.
4200                 if (clearPreviousFloat) {
4201                     m_maxPrefWidth = max(inlineMax, m_maxPrefWidth);
4202                     inlineMax = 0;
4203                 }
4204 
4205                 // Add in text-indent.  This is added in only once.
4206                 int ti = 0;
4207                 if (!addedTextIndent) {
4208                     addedTextIndent = true;
4209                     ti = style()->textIndent().calcMinValue(cw);
4210                     childMin+=ti;
4211                     childMax+=ti;
4212                 }
4213 
4214                 // Add our width to the max.
4215                 inlineMax += childMax;
4216 
4217                 if (!autoWrap || !canBreakReplacedElement) {
4218                     if (child->isFloating())
4219                         m_minPrefWidth = max(childMin, m_minPrefWidth);
4220                     else
4221                         inlineMin += childMin;
4222                 } else {
4223                     // Now check our line.
4224                     m_minPrefWidth = max(childMin, m_minPrefWidth);
4225 
4226                     // Now start a new line.
4227                     inlineMin = 0;
4228                 }
4229 
4230                 // We are no longer stripping whitespace at the start of
4231                 // a line.
4232                 if (!child->isFloating()) {
4233                     stripFrontSpaces = false;
4234                     trailingSpaceChild = 0;
4235                 }
4236             } else if (child->isText()) {
4237                 // Case (3). Text.
4238                 RenderText* t = toRenderText(child);
4239 
4240                 if (t->isWordBreak()) {
4241                     m_minPrefWidth = max(inlineMin, m_minPrefWidth);
4242                     inlineMin = 0;
4243                     continue;
4244                 }
4245 
4246                 // Determine if we have a breakable character.  Pass in
4247                 // whether or not we should ignore any spaces at the front
4248                 // of the string.  If those are going to be stripped out,
4249                 // then they shouldn't be considered in the breakable char
4250                 // check.
4251                 bool hasBreakableChar, hasBreak;
4252                 int beginMin, endMin;
4253 #ifdef ANDROID_FIX // bug found by valgrind
4254                 bool beginWS = false, endWS = false;
4255 #else
4256                 bool beginWS, endWS;
4257 #endif
4258                 int beginMax, endMax;
4259                 t->trimmedPrefWidths(inlineMax, beginMin, beginWS, endMin, endWS,
4260                                      hasBreakableChar, hasBreak, beginMax, endMax,
4261                                      childMin, childMax, stripFrontSpaces);
4262 
4263                 // This text object will not be rendered, but it may still provide a breaking opportunity.
4264                 if (!hasBreak && childMax == 0) {
4265                     if (autoWrap && (beginWS || endWS)) {
4266                         m_minPrefWidth = max(inlineMin, m_minPrefWidth);
4267                         inlineMin = 0;
4268                     }
4269                     continue;
4270                 }
4271 
4272                 if (stripFrontSpaces)
4273                     trailingSpaceChild = child;
4274                 else
4275                     trailingSpaceChild = 0;
4276 
4277                 // Add in text-indent.  This is added in only once.
4278                 int ti = 0;
4279                 if (!addedTextIndent) {
4280                     addedTextIndent = true;
4281                     ti = style()->textIndent().calcMinValue(cw);
4282                     childMin+=ti; beginMin += ti;
4283                     childMax+=ti; beginMax += ti;
4284                 }
4285 
4286                 // If we have no breakable characters at all,
4287                 // then this is the easy case. We add ourselves to the current
4288                 // min and max and continue.
4289                 if (!hasBreakableChar) {
4290                     inlineMin += childMin;
4291                 } else {
4292                     // We have a breakable character.  Now we need to know if
4293                     // we start and end with whitespace.
4294                     if (beginWS)
4295                         // Go ahead and end the current line.
4296                         m_minPrefWidth = max(inlineMin, m_minPrefWidth);
4297                     else {
4298                         inlineMin += beginMin;
4299                         m_minPrefWidth = max(inlineMin, m_minPrefWidth);
4300                         childMin -= ti;
4301                     }
4302 
4303                     inlineMin = childMin;
4304 
4305                     if (endWS) {
4306                         // We end in whitespace, which means we can go ahead
4307                         // and end our current line.
4308                         m_minPrefWidth = max(inlineMin, m_minPrefWidth);
4309                         inlineMin = 0;
4310                     } else {
4311                         m_minPrefWidth = max(inlineMin, m_minPrefWidth);
4312                         inlineMin = endMin;
4313                     }
4314                 }
4315 
4316                 if (hasBreak) {
4317                     inlineMax += beginMax;
4318                     m_maxPrefWidth = max(inlineMax, m_maxPrefWidth);
4319                     m_maxPrefWidth = max(childMax, m_maxPrefWidth);
4320                     inlineMax = endMax;
4321                 } else
4322                     inlineMax += childMax;
4323             }
4324         } else {
4325             m_minPrefWidth = max(inlineMin, m_minPrefWidth);
4326             m_maxPrefWidth = max(inlineMax, m_maxPrefWidth);
4327             inlineMin = inlineMax = 0;
4328             stripFrontSpaces = true;
4329             trailingSpaceChild = 0;
4330         }
4331 
4332         oldAutoWrap = autoWrap;
4333         if (!child->isRenderInline())
4334             previousLeaf = child;
4335     }
4336 
4337     if (style()->collapseWhiteSpace())
4338         stripTrailingSpace(inlineMax, inlineMin, trailingSpaceChild);
4339 
4340     m_minPrefWidth = max(inlineMin, m_minPrefWidth);
4341     m_maxPrefWidth = max(inlineMax, m_maxPrefWidth);
4342 }
4343 
4344 // Use a very large value (in effect infinite).
4345 #define BLOCK_MAX_WIDTH 15000
4346 
calcBlockPrefWidths()4347 void RenderBlock::calcBlockPrefWidths()
4348 {
4349     bool nowrap = style()->whiteSpace() == NOWRAP;
4350 
4351     RenderObject *child = firstChild();
4352     int floatLeftWidth = 0, floatRightWidth = 0;
4353     while (child) {
4354         // Positioned children don't affect the min/max width
4355         if (child->isPositioned()) {
4356             child = child->nextSibling();
4357             continue;
4358         }
4359 
4360         if (child->isFloating() || (child->isBox() && toRenderBox(child)->avoidsFloats())) {
4361             int floatTotalWidth = floatLeftWidth + floatRightWidth;
4362             if (child->style()->clear() & CLEFT) {
4363                 m_maxPrefWidth = max(floatTotalWidth, m_maxPrefWidth);
4364                 floatLeftWidth = 0;
4365             }
4366             if (child->style()->clear() & CRIGHT) {
4367                 m_maxPrefWidth = max(floatTotalWidth, m_maxPrefWidth);
4368                 floatRightWidth = 0;
4369             }
4370         }
4371 
4372         // A margin basically has three types: fixed, percentage, and auto (variable).
4373         // Auto and percentage margins simply become 0 when computing min/max width.
4374         // Fixed margins can be added in as is.
4375         Length ml = child->style()->marginLeft();
4376         Length mr = child->style()->marginRight();
4377         int margin = 0, marginLeft = 0, marginRight = 0;
4378         if (ml.isFixed())
4379             marginLeft += ml.value();
4380         if (mr.isFixed())
4381             marginRight += mr.value();
4382         margin = marginLeft + marginRight;
4383 
4384         int w = child->minPrefWidth() + margin;
4385         m_minPrefWidth = max(w, m_minPrefWidth);
4386 
4387         // IE ignores tables for calculation of nowrap. Makes some sense.
4388         if (nowrap && !child->isTable())
4389             m_maxPrefWidth = max(w, m_maxPrefWidth);
4390 
4391         w = child->maxPrefWidth() + margin;
4392 
4393         if (!child->isFloating()) {
4394             if (child->isBox() && toRenderBox(child)->avoidsFloats()) {
4395                 // Determine a left and right max value based off whether or not the floats can fit in the
4396                 // margins of the object.  For negative margins, we will attempt to overlap the float if the negative margin
4397                 // is smaller than the float width.
4398                 int maxLeft = marginLeft > 0 ? max(floatLeftWidth, marginLeft) : floatLeftWidth + marginLeft;
4399                 int maxRight = marginRight > 0 ? max(floatRightWidth, marginRight) : floatRightWidth + marginRight;
4400                 w = child->maxPrefWidth() + maxLeft + maxRight;
4401                 w = max(w, floatLeftWidth + floatRightWidth);
4402             }
4403             else
4404                 m_maxPrefWidth = max(floatLeftWidth + floatRightWidth, m_maxPrefWidth);
4405             floatLeftWidth = floatRightWidth = 0;
4406         }
4407 
4408         if (child->isFloating()) {
4409             if (style()->floating() == FLEFT)
4410                 floatLeftWidth += w;
4411             else
4412                 floatRightWidth += w;
4413         } else
4414             m_maxPrefWidth = max(w, m_maxPrefWidth);
4415 
4416         // A very specific WinIE quirk.
4417         // Example:
4418         /*
4419            <div style="position:absolute; width:100px; top:50px;">
4420               <div style="position:absolute;left:0px;top:50px;height:50px;background-color:green">
4421                 <table style="width:100%"><tr><td></table>
4422               </div>
4423            </div>
4424         */
4425         // In the above example, the inner absolute positioned block should have a computed width
4426         // of 100px because of the table.
4427         // We can achieve this effect by making the maxwidth of blocks that contain tables
4428         // with percentage widths be infinite (as long as they are not inside a table cell).
4429         if (style()->htmlHacks() && child->style()->width().isPercent() &&
4430             !isTableCell() && child->isTable() && m_maxPrefWidth < BLOCK_MAX_WIDTH) {
4431             RenderBlock* cb = containingBlock();
4432             while (!cb->isRenderView() && !cb->isTableCell())
4433                 cb = cb->containingBlock();
4434             if (!cb->isTableCell())
4435                 m_maxPrefWidth = BLOCK_MAX_WIDTH;
4436         }
4437 
4438         child = child->nextSibling();
4439     }
4440 
4441     // Always make sure these values are non-negative.
4442     m_minPrefWidth = max(0, m_minPrefWidth);
4443     m_maxPrefWidth = max(0, m_maxPrefWidth);
4444 
4445     m_maxPrefWidth = max(floatLeftWidth + floatRightWidth, m_maxPrefWidth);
4446 }
4447 
hasLineIfEmpty() const4448 bool RenderBlock::hasLineIfEmpty() const
4449 {
4450     if (!node())
4451         return false;
4452 
4453     if (node()->isContentEditable() && node()->rootEditableElement() == node())
4454         return true;
4455 
4456     if (node()->isShadowNode() && (node()->shadowParentNode()->hasTagName(inputTag) || node()->shadowParentNode()->hasTagName(textareaTag)))
4457         return true;
4458 
4459     return false;
4460 }
4461 
lineHeight(bool firstLine,bool isRootLineBox) const4462 int RenderBlock::lineHeight(bool firstLine, bool isRootLineBox) const
4463 {
4464     // Inline blocks are replaced elements. Otherwise, just pass off to
4465     // the base class.  If we're being queried as though we're the root line
4466     // box, then the fact that we're an inline-block is irrelevant, and we behave
4467     // just like a block.
4468     if (isReplaced() && !isRootLineBox)
4469         return height() + marginTop() + marginBottom();
4470 
4471     if (firstLine && document()->usesFirstLineRules()) {
4472         RenderStyle* s = style(firstLine);
4473         if (s != style())
4474             return s->computedLineHeight();
4475     }
4476 
4477     if (m_lineHeight == -1)
4478         m_lineHeight = style()->computedLineHeight();
4479 
4480     return m_lineHeight;
4481 }
4482 
baselinePosition(bool b,bool isRootLineBox) const4483 int RenderBlock::baselinePosition(bool b, bool isRootLineBox) const
4484 {
4485     // Inline blocks are replaced elements. Otherwise, just pass off to
4486     // the base class.  If we're being queried as though we're the root line
4487     // box, then the fact that we're an inline-block is irrelevant, and we behave
4488     // just like a block.
4489     if (isReplaced() && !isRootLineBox) {
4490         // For "leaf" theme objects, let the theme decide what the baseline position is.
4491         // FIXME: Might be better to have a custom CSS property instead, so that if the theme
4492         // is turned off, checkboxes/radios will still have decent baselines.
4493         if (style()->hasAppearance() && !theme()->isControlContainer(style()->appearance()))
4494             return theme()->baselinePosition(this);
4495 
4496         // CSS2.1 states that the baseline of an inline block is the baseline of the last line box in
4497         // the normal flow.  We make an exception for marquees, since their baselines are meaningless
4498         // (the content inside them moves).  This matches WinIE as well, which just bottom-aligns them.
4499         // We also give up on finding a baseline if we have a vertical scrollbar, or if we are scrolled
4500         // vertically (e.g., an overflow:hidden block that has had scrollTop moved) or if the baseline is outside
4501         // of our content box.
4502         int baselinePos = (layer() && (layer()->marquee() || layer()->verticalScrollbar() || layer()->scrollYOffset() != 0)) ? -1 : lastLineBoxBaseline();
4503         if (baselinePos != -1 && baselinePos <= borderTop() + paddingTop() + contentHeight())
4504             return marginTop() + baselinePos;
4505         return height() + marginTop() + marginBottom();
4506     }
4507     return RenderBox::baselinePosition(b, isRootLineBox);
4508 }
4509 
firstLineBoxBaseline() const4510 int RenderBlock::firstLineBoxBaseline() const
4511 {
4512     if (!isBlockFlow())
4513         return -1;
4514 
4515     if (childrenInline()) {
4516         if (firstLineBox())
4517             return firstLineBox()->y() + style(true)->font().ascent();
4518         else
4519             return -1;
4520     }
4521     else {
4522         for (RenderBox* curr = firstChildBox(); curr; curr = curr->nextSiblingBox()) {
4523             if (!curr->isFloatingOrPositioned()) {
4524                 int result = curr->firstLineBoxBaseline();
4525                 if (result != -1)
4526                     return curr->y() + result; // Translate to our coordinate space.
4527             }
4528         }
4529     }
4530 
4531     return -1;
4532 }
4533 
lastLineBoxBaseline() const4534 int RenderBlock::lastLineBoxBaseline() const
4535 {
4536     if (!isBlockFlow())
4537         return -1;
4538 
4539     if (childrenInline()) {
4540         if (!firstLineBox() && hasLineIfEmpty())
4541             return RenderBox::baselinePosition(true, true) + borderTop() + paddingTop();
4542         if (lastLineBox())
4543             return lastLineBox()->y() + style(lastLineBox() == firstLineBox())->font().ascent();
4544         return -1;
4545     }
4546     else {
4547         bool haveNormalFlowChild = false;
4548         for (RenderBox* curr = lastChildBox(); curr; curr = curr->previousSiblingBox()) {
4549             if (!curr->isFloatingOrPositioned()) {
4550                 haveNormalFlowChild = true;
4551                 int result = curr->lastLineBoxBaseline();
4552                 if (result != -1)
4553                     return curr->y() + result; // Translate to our coordinate space.
4554             }
4555         }
4556         if (!haveNormalFlowChild && hasLineIfEmpty())
4557             return RenderBox::baselinePosition(true, true) + borderTop() + paddingTop();
4558     }
4559 
4560     return -1;
4561 }
4562 
containsNonZeroBidiLevel() const4563 bool RenderBlock::containsNonZeroBidiLevel() const
4564 {
4565     for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) {
4566         for (InlineBox* box = root->firstLeafChild(); box; box = box->nextLeafChild()) {
4567             if (box->bidiLevel())
4568                 return true;
4569         }
4570     }
4571     return false;
4572 }
4573 
firstLineBlock() const4574 RenderBlock* RenderBlock::firstLineBlock() const
4575 {
4576     RenderBlock* firstLineBlock = const_cast<RenderBlock*>(this);
4577     bool hasPseudo = false;
4578     while (true) {
4579         hasPseudo = firstLineBlock->style()->hasPseudoStyle(FIRST_LINE);
4580         if (hasPseudo)
4581             break;
4582         RenderObject* parentBlock = firstLineBlock->parent();
4583         if (firstLineBlock->isReplaced() || firstLineBlock->isFloating() ||
4584             !parentBlock || parentBlock->firstChild() != firstLineBlock || !parentBlock->isBlockFlow())
4585             break;
4586         ASSERT(parentBlock->isRenderBlock());
4587         firstLineBlock = toRenderBlock(parentBlock);
4588     }
4589 
4590     if (!hasPseudo)
4591         return 0;
4592 
4593     return firstLineBlock;
4594 }
4595 
updateFirstLetter()4596 void RenderBlock::updateFirstLetter()
4597 {
4598     if (!document()->usesFirstLetterRules())
4599         return;
4600     // Don't recur
4601     if (style()->styleType() == FIRST_LETTER)
4602         return;
4603 
4604     // FIXME: We need to destroy the first-letter object if it is no longer the first child.  Need to find
4605     // an efficient way to check for that situation though before implementing anything.
4606     RenderObject* firstLetterBlock = this;
4607     bool hasPseudoStyle = false;
4608     while (true) {
4609         // We only honor first-letter if the firstLetterBlock can have children in the DOM. This correctly
4610         // prevents form controls from honoring first-letter.
4611         hasPseudoStyle = firstLetterBlock->style()->hasPseudoStyle(FIRST_LETTER)
4612             && firstLetterBlock->canHaveChildren();
4613         if (hasPseudoStyle)
4614             break;
4615         RenderObject* parentBlock = firstLetterBlock->parent();
4616         if (firstLetterBlock->isReplaced() || !parentBlock || parentBlock->firstChild() != firstLetterBlock ||
4617             !parentBlock->isBlockFlow())
4618             break;
4619         firstLetterBlock = parentBlock;
4620     }
4621 
4622     if (!hasPseudoStyle)
4623         return;
4624 
4625     // Drill into inlines looking for our first text child.
4626     RenderObject* currChild = firstLetterBlock->firstChild();
4627     while (currChild && currChild->needsLayout() && (!currChild->isReplaced() || currChild->isFloatingOrPositioned()) && !currChild->isText()) {
4628         if (currChild->isFloatingOrPositioned()) {
4629             if (currChild->style()->styleType() == FIRST_LETTER)
4630                 break;
4631             currChild = currChild->nextSibling();
4632         } else
4633             currChild = currChild->firstChild();
4634     }
4635 
4636     // Get list markers out of the way.
4637     while (currChild && currChild->isListMarker())
4638         currChild = currChild->nextSibling();
4639 
4640     if (!currChild)
4641         return;
4642 
4643     RenderObject* firstLetterContainer = currChild->parent();
4644 
4645     // If the child already has style, then it has already been created, so we just want
4646     // to update it.
4647     if (currChild->style()->styleType() == FIRST_LETTER) {
4648         RenderStyle* pseudo = firstLetterBlock->getCachedPseudoStyle(FIRST_LETTER,
4649                                                                      firstLetterContainer->firstLineStyle());
4650         currChild->setStyle(pseudo);
4651         for (RenderObject* genChild = currChild->firstChild(); genChild; genChild = genChild->nextSibling()) {
4652             if (genChild->isText())
4653                 genChild->setStyle(pseudo);
4654         }
4655         return;
4656     }
4657 
4658     // If the child does not already have style, we create it here.
4659     if (currChild->isText() && !currChild->isBR() && currChild->parent()->style()->styleType() != FIRST_LETTER) {
4660         // Our layout state is not valid for the repaints we are going to trigger by
4661         // adding and removing children of firstLetterContainer.
4662         view()->disableLayoutState();
4663 
4664         RenderText* textObj = toRenderText(currChild);
4665 
4666         // Create our pseudo style now that we have our firstLetterContainer determined.
4667         RenderStyle* pseudoStyle = firstLetterBlock->getCachedPseudoStyle(FIRST_LETTER,
4668                                                                           firstLetterContainer->firstLineStyle());
4669 
4670         // Force inline display (except for floating first-letters)
4671         pseudoStyle->setDisplay(pseudoStyle->isFloating() ? BLOCK : INLINE);
4672         pseudoStyle->setPosition(StaticPosition); // CSS2 says first-letter can't be positioned.
4673 
4674         RenderObject* firstLetter = 0;
4675         if (pseudoStyle->display() == INLINE)
4676             firstLetter = new (renderArena()) RenderInline(document());
4677         else
4678             firstLetter = new (renderArena()) RenderBlock(document());
4679         firstLetter->setStyle(pseudoStyle);
4680         firstLetterContainer->addChild(firstLetter, currChild);
4681 
4682         // The original string is going to be either a generated content string or a DOM node's
4683         // string.  We want the original string before it got transformed in case first-letter has
4684         // no text-transform or a different text-transform applied to it.
4685         RefPtr<StringImpl> oldText = textObj->originalText();
4686         ASSERT(oldText);
4687 
4688         if (oldText && oldText->length() > 0) {
4689             unsigned int length = 0;
4690 
4691             // account for leading spaces and punctuation
4692             while (length < oldText->length() && (isSpaceOrNewline((*oldText)[length]) || Unicode::isPunct((*oldText)[length])))
4693                 length++;
4694 
4695             // account for first letter
4696             length++;
4697 
4698             // construct text fragment for the text after the first letter
4699             // NOTE: this might empty
4700             RenderTextFragment* remainingText =
4701                 new (renderArena()) RenderTextFragment(textObj->node() ? textObj->node() : textObj->document(), oldText.get(), length, oldText->length() - length);
4702             remainingText->setStyle(textObj->style());
4703             if (remainingText->node())
4704                 remainingText->node()->setRenderer(remainingText);
4705 
4706             RenderObject* nextObj = textObj->nextSibling();
4707             firstLetterContainer->removeChild(textObj);
4708             firstLetterContainer->addChild(remainingText, nextObj);
4709             remainingText->setFirstLetter(firstLetter);
4710 
4711             // construct text fragment for the first letter
4712             RenderTextFragment* letter =
4713                 new (renderArena()) RenderTextFragment(remainingText->node() ? remainingText->node() : remainingText->document(), oldText.get(), 0, length);
4714             RefPtr<RenderStyle> newStyle = RenderStyle::create();
4715             newStyle->inheritFrom(pseudoStyle);
4716             letter->setStyle(newStyle.release());
4717             firstLetter->addChild(letter);
4718 
4719             textObj->destroy();
4720         }
4721         view()->enableLayoutState();
4722     }
4723 }
4724 
inRootBlockContext() const4725 bool RenderBlock::inRootBlockContext() const
4726 {
4727     if (isTableCell() || isFloatingOrPositioned() || hasOverflowClip())
4728         return false;
4729 
4730     if (isRoot() || isRenderView())
4731         return true;
4732 
4733     return containingBlock()->inRootBlockContext();
4734 }
4735 
4736 // Helper methods for obtaining the last line, computing line counts and heights for line counts
4737 // (crawling into blocks).
shouldCheckLines(RenderObject * obj)4738 static bool shouldCheckLines(RenderObject* obj)
4739 {
4740     return !obj->isFloatingOrPositioned() && !obj->isRunIn() &&
4741             obj->isBlockFlow() && obj->style()->height().isAuto() &&
4742             (!obj->isFlexibleBox() || obj->style()->boxOrient() == VERTICAL);
4743 }
4744 
getLineAtIndex(RenderBlock * block,int i,int & count)4745 static RootInlineBox* getLineAtIndex(RenderBlock* block, int i, int& count)
4746 {
4747     if (block->style()->visibility() == VISIBLE) {
4748         if (block->childrenInline()) {
4749             for (RootInlineBox* box = block->firstRootBox(); box; box = box->nextRootBox()) {
4750                 if (count++ == i)
4751                     return box;
4752             }
4753         }
4754         else {
4755             for (RenderObject* obj = block->firstChild(); obj; obj = obj->nextSibling()) {
4756                 if (shouldCheckLines(obj)) {
4757                     RootInlineBox *box = getLineAtIndex(toRenderBlock(obj), i, count);
4758                     if (box)
4759                         return box;
4760                 }
4761             }
4762         }
4763     }
4764     return 0;
4765 }
4766 
getHeightForLineCount(RenderBlock * block,int l,bool includeBottom,int & count)4767 static int getHeightForLineCount(RenderBlock* block, int l, bool includeBottom, int& count)
4768 {
4769     if (block->style()->visibility() == VISIBLE) {
4770         if (block->childrenInline()) {
4771             for (RootInlineBox* box = block->firstRootBox(); box; box = box->nextRootBox()) {
4772                 if (++count == l)
4773                     return box->bottomOverflow() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0);
4774             }
4775         }
4776         else {
4777             RenderBox* normalFlowChildWithoutLines = 0;
4778             for (RenderBox* obj = block->firstChildBox(); obj; obj = obj->nextSiblingBox()) {
4779                 if (shouldCheckLines(obj)) {
4780                     int result = getHeightForLineCount(toRenderBlock(obj), l, false, count);
4781                     if (result != -1)
4782                         return result + obj->y() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0);
4783                 }
4784                 else if (!obj->isFloatingOrPositioned() && !obj->isRunIn())
4785                     normalFlowChildWithoutLines = obj;
4786             }
4787             if (normalFlowChildWithoutLines && l == 0)
4788                 return normalFlowChildWithoutLines->y() + normalFlowChildWithoutLines->height();
4789         }
4790     }
4791 
4792     return -1;
4793 }
4794 
lineAtIndex(int i)4795 RootInlineBox* RenderBlock::lineAtIndex(int i)
4796 {
4797     int count = 0;
4798     return getLineAtIndex(this, i, count);
4799 }
4800 
lineCount()4801 int RenderBlock::lineCount()
4802 {
4803     int count = 0;
4804     if (style()->visibility() == VISIBLE) {
4805         if (childrenInline())
4806             for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox())
4807                 count++;
4808         else
4809             for (RenderObject* obj = firstChild(); obj; obj = obj->nextSibling())
4810                 if (shouldCheckLines(obj))
4811                     count += toRenderBlock(obj)->lineCount();
4812     }
4813     return count;
4814 }
4815 
heightForLineCount(int l)4816 int RenderBlock::heightForLineCount(int l)
4817 {
4818     int count = 0;
4819     return getHeightForLineCount(this, l, true, count);
4820 }
4821 
adjustForBorderFit(int x,int & left,int & right) const4822 void RenderBlock::adjustForBorderFit(int x, int& left, int& right) const
4823 {
4824     // We don't deal with relative positioning.  Our assumption is that you shrink to fit the lines without accounting
4825     // for either overflow or translations via relative positioning.
4826     if (style()->visibility() == VISIBLE) {
4827         if (childrenInline()) {
4828             for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox()) {
4829                 if (box->firstChild())
4830                     left = min(left, x + box->firstChild()->x());
4831                 if (box->lastChild())
4832                     right = max(right, x + box->lastChild()->x() + box->lastChild()->width());
4833             }
4834         }
4835         else {
4836             for (RenderBox* obj = firstChildBox(); obj; obj = obj->nextSiblingBox()) {
4837                 if (!obj->isFloatingOrPositioned()) {
4838                     if (obj->isBlockFlow() && !obj->hasOverflowClip())
4839                         toRenderBlock(obj)->adjustForBorderFit(x + obj->x(), left, right);
4840                     else if (obj->style()->visibility() == VISIBLE) {
4841                         // We are a replaced element or some kind of non-block-flow object.
4842                         left = min(left, x + obj->x());
4843                         right = max(right, x + obj->x() + obj->width());
4844                     }
4845                 }
4846             }
4847         }
4848 
4849         if (m_floatingObjects) {
4850             FloatingObject* r;
4851             DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
4852             for (; (r = it.current()); ++it) {
4853                 // Only examine the object if our m_shouldPaint flag is set.
4854                 if (r->m_shouldPaint) {
4855                     int floatLeft = r->m_left - r->m_renderer->x() + r->m_renderer->marginLeft();
4856                     int floatRight = floatLeft + r->m_renderer->width();
4857                     left = min(left, floatLeft);
4858                     right = max(right, floatRight);
4859                 }
4860             }
4861         }
4862     }
4863 }
4864 
borderFitAdjust(int & x,int & w) const4865 void RenderBlock::borderFitAdjust(int& x, int& w) const
4866 {
4867     if (style()->borderFit() == BorderFitBorder)
4868         return;
4869 
4870     // Walk any normal flow lines to snugly fit.
4871     int left = INT_MAX;
4872     int right = INT_MIN;
4873     int oldWidth = w;
4874     adjustForBorderFit(0, left, right);
4875     if (left != INT_MAX) {
4876         left -= (borderLeft() + paddingLeft());
4877         if (left > 0) {
4878             x += left;
4879             w -= left;
4880         }
4881     }
4882     if (right != INT_MIN) {
4883         right += (borderRight() + paddingRight());
4884         if (right < oldWidth)
4885             w -= (oldWidth - right);
4886     }
4887 }
4888 
clearTruncation()4889 void RenderBlock::clearTruncation()
4890 {
4891     if (style()->visibility() == VISIBLE) {
4892         if (childrenInline() && hasMarkupTruncation()) {
4893             setHasMarkupTruncation(false);
4894             for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox())
4895                 box->clearTruncation();
4896         }
4897         else
4898             for (RenderObject* obj = firstChild(); obj; obj = obj->nextSibling())
4899                 if (shouldCheckLines(obj))
4900                     toRenderBlock(obj)->clearTruncation();
4901     }
4902 }
4903 
setMaxTopMargins(int pos,int neg)4904 void RenderBlock::setMaxTopMargins(int pos, int neg)
4905 {
4906     if (!m_maxMargin) {
4907         if (pos == MaxMargin::topPosDefault(this) && neg == MaxMargin::topNegDefault(this))
4908             return;
4909         m_maxMargin = new MaxMargin(this);
4910     }
4911     m_maxMargin->m_topPos = pos;
4912     m_maxMargin->m_topNeg = neg;
4913 }
4914 
setMaxBottomMargins(int pos,int neg)4915 void RenderBlock::setMaxBottomMargins(int pos, int neg)
4916 {
4917     if (!m_maxMargin) {
4918         if (pos == MaxMargin::bottomPosDefault(this) && neg == MaxMargin::bottomNegDefault(this))
4919             return;
4920         m_maxMargin = new MaxMargin(this);
4921     }
4922     m_maxMargin->m_bottomPos = pos;
4923     m_maxMargin->m_bottomNeg = neg;
4924 }
4925 
absoluteRects(Vector<IntRect> & rects,int tx,int ty)4926 void RenderBlock::absoluteRects(Vector<IntRect>& rects, int tx, int ty)
4927 {
4928     // For blocks inside inlines, we go ahead and include margins so that we run right up to the
4929     // inline boxes above and below us (thus getting merged with them to form a single irregular
4930     // shape).
4931     if (inlineContinuation()) {
4932         rects.append(IntRect(tx, ty - collapsedMarginTop(),
4933                              width(), height() + collapsedMarginTop() + collapsedMarginBottom()));
4934         inlineContinuation()->absoluteRects(rects,
4935                                             tx - x() + inlineContinuation()->containingBlock()->x(),
4936                                             ty - y() + inlineContinuation()->containingBlock()->y());
4937     } else
4938         rects.append(IntRect(tx, ty, width(), height()));
4939 }
4940 
absoluteQuads(Vector<FloatQuad> & quads)4941 void RenderBlock::absoluteQuads(Vector<FloatQuad>& quads)
4942 {
4943     // For blocks inside inlines, we go ahead and include margins so that we run right up to the
4944     // inline boxes above and below us (thus getting merged with them to form a single irregular
4945     // shape).
4946     if (inlineContinuation()) {
4947         FloatRect localRect(0, -collapsedMarginTop(),
4948                             width(), height() + collapsedMarginTop() + collapsedMarginBottom());
4949         quads.append(localToAbsoluteQuad(localRect));
4950         inlineContinuation()->absoluteQuads(quads);
4951     } else
4952         quads.append(RenderBox::localToAbsoluteQuad(FloatRect(0, 0, width(), height())));
4953 }
4954 
rectWithOutlineForRepaint(RenderBoxModelObject * repaintContainer,int outlineWidth)4955 IntRect RenderBlock::rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, int outlineWidth)
4956 {
4957     IntRect r(RenderBox::rectWithOutlineForRepaint(repaintContainer, outlineWidth));
4958     if (inlineContinuation())
4959         r.inflateY(collapsedMarginTop());
4960     return r;
4961 }
4962 
hoverAncestor() const4963 RenderObject* RenderBlock::hoverAncestor() const
4964 {
4965     return inlineContinuation() ? inlineContinuation() : RenderBox::hoverAncestor();
4966 }
4967 
updateDragState(bool dragOn)4968 void RenderBlock::updateDragState(bool dragOn)
4969 {
4970     RenderBox::updateDragState(dragOn);
4971     if (inlineContinuation())
4972         inlineContinuation()->updateDragState(dragOn);
4973 }
4974 
outlineStyleForRepaint() const4975 RenderStyle* RenderBlock::outlineStyleForRepaint() const
4976 {
4977     return inlineContinuation() ? inlineContinuation()->style() : style();
4978 }
4979 
childBecameNonInline(RenderObject *)4980 void RenderBlock::childBecameNonInline(RenderObject*)
4981 {
4982     makeChildrenNonInline();
4983     if (isAnonymousBlock() && parent() && parent()->isRenderBlock())
4984         toRenderBlock(parent())->removeLeftoverAnonymousBlock(this);
4985     // |this| may be dead here
4986 }
4987 
updateHitTestResult(HitTestResult & result,const IntPoint & point)4988 void RenderBlock::updateHitTestResult(HitTestResult& result, const IntPoint& point)
4989 {
4990     if (result.innerNode())
4991         return;
4992 
4993     Node* n = node();
4994     if (inlineContinuation())
4995         // We are in the margins of block elements that are part of a continuation.  In
4996         // this case we're actually still inside the enclosing inline element that was
4997         // split.  Go ahead and set our inner node accordingly.
4998         n = inlineContinuation()->node();
4999 
5000     if (n) {
5001         result.setInnerNode(n);
5002         if (!result.innerNonSharedNode())
5003             result.setInnerNonSharedNode(n);
5004         result.setLocalPoint(point);
5005     }
5006 }
5007 
localCaretRect(InlineBox * inlineBox,int caretOffset,int * extraWidthToEndOfLine)5008 IntRect RenderBlock::localCaretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
5009 {
5010     // Do the normal calculation in most cases.
5011     if (firstChild())
5012         return RenderBox::localCaretRect(inlineBox, caretOffset, extraWidthToEndOfLine);
5013 
5014     // This is a special case:
5015     // The element is not an inline element, and it's empty. So we have to
5016     // calculate a fake position to indicate where objects are to be inserted.
5017 
5018     // FIXME: This does not take into account either :first-line or :first-letter
5019     // However, as soon as some content is entered, the line boxes will be
5020     // constructed and this kludge is not called any more. So only the caret size
5021     // of an empty :first-line'd block is wrong. I think we can live with that.
5022     RenderStyle* currentStyle = firstLineStyle();
5023     int height = lineHeight(true);
5024 
5025     enum CaretAlignment { alignLeft, alignRight, alignCenter };
5026 
5027     CaretAlignment alignment = alignLeft;
5028 
5029     switch (currentStyle->textAlign()) {
5030         case TAAUTO:
5031         case JUSTIFY:
5032             if (currentStyle->direction() == RTL)
5033                 alignment = alignRight;
5034             break;
5035         case LEFT:
5036         case WEBKIT_LEFT:
5037             break;
5038         case CENTER:
5039         case WEBKIT_CENTER:
5040             alignment = alignCenter;
5041             break;
5042         case RIGHT:
5043         case WEBKIT_RIGHT:
5044             alignment = alignRight;
5045             break;
5046     }
5047 
5048     int x = borderLeft() + paddingLeft();
5049     int w = width();
5050 
5051     switch (alignment) {
5052         case alignLeft:
5053             break;
5054         case alignCenter:
5055             x = (x + w - (borderRight() + paddingRight())) / 2;
5056             break;
5057         case alignRight:
5058             x = w - (borderRight() + paddingRight()) - caretWidth;
5059             break;
5060     }
5061 
5062     if (extraWidthToEndOfLine) {
5063         if (isRenderBlock()) {
5064             *extraWidthToEndOfLine = w - (x + caretWidth);
5065         } else {
5066             // FIXME: This code looks wrong.
5067             // myRight and containerRight are set up, but then clobbered.
5068             // So *extraWidthToEndOfLine will always be 0 here.
5069 
5070             int myRight = x + caretWidth;
5071             // FIXME: why call localToAbsoluteForContent() twice here, too?
5072             FloatPoint absRightPoint = localToAbsolute(FloatPoint(myRight, 0));
5073 
5074             int containerRight = containingBlock()->x() + containingBlockWidthForContent();
5075             FloatPoint absContainerPoint = localToAbsolute(FloatPoint(containerRight, 0));
5076 
5077             *extraWidthToEndOfLine = absContainerPoint.x() - absRightPoint.x();
5078         }
5079     }
5080 
5081     int y = paddingTop() + borderTop();
5082 
5083     return IntRect(x, y, caretWidth, height);
5084 }
5085 
addFocusRingRects(GraphicsContext * graphicsContext,int tx,int ty)5086 void RenderBlock::addFocusRingRects(GraphicsContext* graphicsContext, int tx, int ty)
5087 {
5088     // For blocks inside inlines, we go ahead and include margins so that we run right up to the
5089     // inline boxes above and below us (thus getting merged with them to form a single irregular
5090     // shape).
5091     if (inlineContinuation()) {
5092         // FIXME: This check really isn't accurate.
5093         bool nextInlineHasLineBox = inlineContinuation()->firstLineBox();
5094         // FIXME: This is wrong. The principal renderer may not be the continuation preceding this block.
5095         bool prevInlineHasLineBox = toRenderInline(inlineContinuation()->node()->renderer())->firstLineBox();
5096         int topMargin = prevInlineHasLineBox ? collapsedMarginTop() : 0;
5097         int bottomMargin = nextInlineHasLineBox ? collapsedMarginBottom() : 0;
5098         graphicsContext->addFocusRingRect(IntRect(tx, ty - topMargin,
5099                                                   width(), height() + topMargin + bottomMargin));
5100     } else
5101         graphicsContext->addFocusRingRect(IntRect(tx, ty, width(), height()));
5102 
5103     if (!hasOverflowClip() && !hasControlClip()) {
5104         for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
5105             graphicsContext->addFocusRingRect(IntRect(tx + curr->x(), ty + curr->y(), curr->width(), curr->height()));
5106 
5107         for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
5108             if (!curr->isText() && !curr->isListMarker() && curr->isBox()) {
5109                 RenderBox* box = toRenderBox(curr);
5110                 FloatPoint pos;
5111                 // FIXME: This doesn't work correctly with transforms.
5112                 if (box->layer())
5113                     pos = curr->localToAbsolute();
5114                 else
5115                     pos = FloatPoint(tx + box->x(), ty + box->y());
5116                 box->addFocusRingRects(graphicsContext, pos.x(), pos.y());
5117             }
5118         }
5119     }
5120 
5121     if (inlineContinuation())
5122         inlineContinuation()->addFocusRingRects(graphicsContext,
5123                                                 tx - x() + inlineContinuation()->containingBlock()->x(),
5124                                                 ty - y() + inlineContinuation()->containingBlock()->y());
5125 }
5126 
createAnonymousBlock() const5127 RenderBlock* RenderBlock::createAnonymousBlock() const
5128 {
5129     RefPtr<RenderStyle> newStyle = RenderStyle::create();
5130     newStyle->inheritFrom(style());
5131     newStyle->setDisplay(BLOCK);
5132 
5133     RenderBlock* newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
5134     newBox->setStyle(newStyle.release());
5135     return newBox;
5136 }
5137 
renderName() const5138 const char* RenderBlock::renderName() const
5139 {
5140     if (isBody())
5141         return "RenderBody"; // FIXME: Temporary hack until we know that the regression tests pass.
5142 
5143     if (isFloating())
5144         return "RenderBlock (floating)";
5145     if (isPositioned())
5146         return "RenderBlock (positioned)";
5147     if (isAnonymousBlock())
5148         return "RenderBlock (anonymous)";
5149     else if (isAnonymous())
5150         return "RenderBlock (generated)";
5151     if (isRelPositioned())
5152         return "RenderBlock (relative positioned)";
5153     if (isRunIn())
5154         return "RenderBlock (run-in)";
5155     return "RenderBlock";
5156 }
5157 
5158 } // namespace WebCore
5159