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