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