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.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
26 #include "ColumnInfo.h"
28 #include "PODIntervalTree.h"
29 #include "RenderBox.h"
30 #include "RenderLineBoxList.h"
31 #include "RootInlineBox.h"
33 #include <wtf/OwnPtr.h>
34 #include <wtf/ListHashSet.h>
40 class LayoutStateMaintainer;
41 class LazyLineBreakIterator;
42 class LineLayoutState;
52 template <class Iterator, class Run> class BidiResolver;
53 template <class Run> class BidiRunList;
54 template <class Iterator> struct MidpointState;
55 typedef BidiResolver<InlineIterator, BidiRun> InlineBidiResolver;
56 typedef MidpointState<InlineIterator> LineMidpointState;
58 enum CaretType { CursorCaret, DragCaret };
61 DefaultTextRunFlags = 0,
62 RespectDirection = 1 << 0,
63 RespectDirectionOverride = 1 << 1
66 typedef unsigned TextRunFlags;
68 class RenderBlock : public RenderBox {
70 friend class LineLayoutState;
72 // Used by the PODIntervalTree for debugging the FloatingObject.
73 template <class> friend struct ValueToString;
77 virtual ~RenderBlock();
79 const RenderObjectChildList* children() const { return &m_children; }
80 RenderObjectChildList* children() { return &m_children; }
82 bool beingDestroyed() const { return m_beingDestroyed; }
84 // These two functions are overridden for inline-block.
85 virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
86 virtual LayoutUnit baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
88 RenderLineBoxList* lineBoxes() { return &m_lineBoxes; }
89 const RenderLineBoxList* lineBoxes() const { return &m_lineBoxes; }
91 InlineFlowBox* firstLineBox() const { return m_lineBoxes.firstLineBox(); }
92 InlineFlowBox* lastLineBox() const { return m_lineBoxes.lastLineBox(); }
94 void deleteLineBoxTree();
96 virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
97 virtual void removeChild(RenderObject*);
99 virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0);
101 void insertPositionedObject(RenderBox*);
102 void removePositionedObject(RenderBox*);
103 void removePositionedObjects(RenderBlock*);
105 typedef ListHashSet<RenderBox*, 4> PositionedObjectsListHashSet;
106 PositionedObjectsListHashSet* positionedObjects() const { return m_positionedObjects.get(); }
107 bool hasPositionedObjects() const { return m_positionedObjects && !m_positionedObjects->isEmpty(); }
109 void addPercentHeightDescendant(RenderBox*);
110 static void removePercentHeightDescendant(RenderBox*);
111 HashSet<RenderBox*>* percentHeightDescendants() const;
112 static bool hasPercentHeightContainerMap();
113 static bool hasPercentHeightDescendant(RenderBox*);
114 static void clearPercentHeightDescendantsFrom(RenderBox*);
115 static void removePercentHeightDescendantIfNeeded(RenderBox*);
117 void setHasMarkupTruncation(bool b) { m_hasMarkupTruncation = b; }
118 bool hasMarkupTruncation() const { return m_hasMarkupTruncation; }
120 RootInlineBox* createAndAppendRootInlineBox();
122 bool generatesLineBoxesForInlineChild(RenderObject*);
124 void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true);
125 void markSiblingsWithFloatsForLayout(RenderBox* floatToRemove = 0);
126 void markPositionedObjectsForLayout();
127 virtual void markForPaginationRelayoutIfNeeded();
129 bool containsFloats() const { return m_floatingObjects && !m_floatingObjects->set().isEmpty(); }
130 bool containsFloat(RenderBox*) const;
132 // Versions that can compute line offsets with the region and page offset passed in. Used for speed to avoid having to
133 // compute the region all over again when you already know it.
134 LayoutUnit availableLogicalWidthForLine(LayoutUnit position, bool firstLine, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, LayoutUnit logicalHeight = 0) const
136 return max(ZERO_LAYOUT_UNIT, logicalRightOffsetForLine(position, firstLine, region, offsetFromLogicalTopOfFirstPage, logicalHeight)
137 - logicalLeftOffsetForLine(position, firstLine, region, offsetFromLogicalTopOfFirstPage, logicalHeight));
139 LayoutUnit logicalRightOffsetForLine(LayoutUnit position, bool firstLine, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, LayoutUnit logicalHeight = 0) const
141 return logicalRightOffsetForLine(position, logicalRightOffsetForContent(region, offsetFromLogicalTopOfFirstPage), firstLine, 0, logicalHeight);
143 LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, bool firstLine, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, LayoutUnit logicalHeight = 0) const
145 return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(region, offsetFromLogicalTopOfFirstPage), firstLine, 0, logicalHeight);
147 LayoutUnit startOffsetForLine(LayoutUnit position, bool firstLine, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, LayoutUnit logicalHeight = 0) const
149 return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, firstLine, region, offsetFromLogicalTopOfFirstPage, logicalHeight)
150 : logicalWidth() - logicalRightOffsetForLine(position, firstLine, region, offsetFromLogicalTopOfFirstPage, logicalHeight);
152 LayoutUnit endOffsetForLine(LayoutUnit position, bool firstLine, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, LayoutUnit logicalHeight = 0) const
154 return !style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, firstLine, region, offsetFromLogicalTopOfFirstPage, logicalHeight)
155 : logicalWidth() - logicalRightOffsetForLine(position, firstLine, region, offsetFromLogicalTopOfFirstPage, logicalHeight);
158 LayoutUnit availableLogicalWidthForLine(LayoutUnit position, bool firstLine, LayoutUnit logicalHeight = 0) const
160 return availableLogicalWidthForLine(position, firstLine, regionAtBlockOffset(position), offsetFromLogicalTopOfFirstPage(), logicalHeight);
162 LayoutUnit logicalRightOffsetForLine(LayoutUnit position, bool firstLine, LayoutUnit logicalHeight = 0) const
164 return logicalRightOffsetForLine(position, logicalRightOffsetForContent(position), firstLine, 0, logicalHeight);
166 LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, bool firstLine, LayoutUnit logicalHeight = 0) const
168 return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(position), firstLine, 0, logicalHeight);
170 LayoutUnit pixelSnappedLogicalLeftOffsetForLine(LayoutUnit position, bool firstLine, LayoutUnit logicalHeight = 0) const
172 return roundToInt(logicalLeftOffsetForLine(position, firstLine, logicalHeight));
174 LayoutUnit pixelSnappedLogicalRightOffsetForLine(LayoutUnit position, bool firstLine, LayoutUnit logicalHeight = 0) const
176 // FIXME: Multicolumn layouts break carrying over subpixel values to the logical right offset because the lines may be shifted
177 // by a subpixel value for all but the first column. This can lead to the actual pixel snapped width of the column being off
178 // by one pixel when rendered versus layed out, which can result in the line being clipped. For now, we have to floor.
179 return floorToInt(logicalRightOffsetForLine(position, firstLine, logicalHeight));
181 LayoutUnit startOffsetForLine(LayoutUnit position, bool firstLine, LayoutUnit logicalHeight = 0) const
183 return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, firstLine, logicalHeight)
184 : logicalWidth() - logicalRightOffsetForLine(position, firstLine, logicalHeight);
186 LayoutUnit endOffsetForLine(LayoutUnit position, bool firstLine, LayoutUnit logicalHeight = 0) const
188 return !style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, firstLine, logicalHeight)
189 : logicalWidth() - logicalRightOffsetForLine(position, firstLine, logicalHeight);
192 LayoutUnit startAlignedOffsetForLine(LayoutUnit position, bool firstLine);
193 LayoutUnit textIndentOffset() const;
195 virtual VisiblePosition positionForPoint(const LayoutPoint&);
197 // Block flows subclass availableWidth to handle multi column layout (shrinking the width available to children when laying out.)
198 virtual LayoutUnit availableLogicalWidth() const;
200 LayoutPoint flipForWritingModeIncludingColumns(const LayoutPoint&) const;
201 void adjustStartEdgeForWritingModeIncludingColumns(LayoutRect&) const;
203 RootInlineBox* firstRootBox() const { return static_cast<RootInlineBox*>(firstLineBox()); }
204 RootInlineBox* lastRootBox() const { return static_cast<RootInlineBox*>(lastLineBox()); }
206 bool containsNonZeroBidiLevel() const;
208 GapRects selectionGapRectsForRepaint(RenderBoxModelObject* repaintContainer);
209 LayoutRect logicalLeftSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
210 RenderObject* selObj, LayoutUnit logicalLeft, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo*);
211 LayoutRect logicalRightSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
212 RenderObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo*);
213 void getSelectionGapInfo(SelectionState, bool& leftGap, bool& rightGap);
214 RenderBlock* blockBeforeWithinSelectionRoot(LayoutSize& offset) const;
216 LayoutRect logicalRectToPhysicalRect(const LayoutPoint& physicalPosition, const LayoutRect& logicalRect);
218 // Helper methods for computing line counts and heights for line counts.
219 RootInlineBox* lineAtIndex(int);
221 int heightForLineCount(int);
222 void clearTruncation();
224 void adjustRectForColumns(LayoutRect&) const;
225 virtual void adjustForColumns(LayoutSize&, const LayoutPoint&) const;
226 void adjustForColumnRect(LayoutSize& offset, const LayoutPoint& pointInContainer) const;
228 void addContinuationWithOutline(RenderInline*);
229 bool paintsContinuationOutline(RenderInline*);
231 virtual RenderBoxModelObject* virtualContinuation() const { return continuation(); }
232 bool isAnonymousBlockContinuation() const { return continuation() && isAnonymousBlock(); }
233 RenderInline* inlineElementContinuation() const;
234 RenderBlock* blockElementContinuation() const;
236 using RenderBoxModelObject::continuation;
237 using RenderBoxModelObject::setContinuation;
239 static RenderBlock* createAnonymousWithParentRendererAndDisplay(const RenderObject*, EDisplay = BLOCK);
240 static RenderBlock* createAnonymousColumnsWithParentRenderer(const RenderObject*);
241 static RenderBlock* createAnonymousColumnSpanWithParentRenderer(const RenderObject*);
242 RenderBlock* createAnonymousBlock(EDisplay display = BLOCK) const { return createAnonymousWithParentRendererAndDisplay(this, display); }
243 RenderBlock* createAnonymousColumnsBlock() const { return createAnonymousColumnsWithParentRenderer(this); }
244 RenderBlock* createAnonymousColumnSpanBlock() const { return createAnonymousColumnSpanWithParentRenderer(this); }
246 virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE;
248 static bool shouldSkipCreatingRunsForObject(RenderObject* obj)
250 return obj->isFloating() || (obj->isOutOfFlowPositioned() && !obj->style()->isOriginalDisplayInlineType() && !obj->container()->isRenderInline());
253 static void appendRunsForObject(BidiRunList<BidiRun>&, int start, int end, RenderObject*, InlineBidiResolver&);
255 static TextRun constructTextRun(RenderObject* context, const Font&, const String&, RenderStyle*,
256 TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion, TextRunFlags = DefaultTextRunFlags);
258 static TextRun constructTextRun(RenderObject* context, const Font&, const UChar*, int length, RenderStyle*,
259 TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion, TextRunFlags = DefaultTextRunFlags);
261 ColumnInfo* columnInfo() const;
262 int columnGap() const;
264 // These two functions take the ColumnInfo* to avoid repeated lookups of the info in the global HashMap.
265 unsigned columnCount(ColumnInfo*) const;
266 LayoutRect columnRectAt(ColumnInfo*, unsigned) const;
268 LayoutUnit paginationStrut() const { return m_rareData ? m_rareData->m_paginationStrut : ZERO_LAYOUT_UNIT; }
269 void setPaginationStrut(LayoutUnit);
271 // The page logical offset is the object's offset from the top of the page in the page progression
272 // direction (so an x-offset in vertical text and a y-offset for horizontal text).
273 LayoutUnit pageLogicalOffset() const { return m_rareData ? m_rareData->m_pageLogicalOffset : ZERO_LAYOUT_UNIT; }
274 void setPageLogicalOffset(LayoutUnit);
276 RootInlineBox* lineGridBox() const { return m_rareData ? m_rareData->m_lineGridBox : 0; }
277 void setLineGridBox(RootInlineBox* box)
280 m_rareData = adoptPtr(new RenderBlockRareData(this));
281 if (m_rareData->m_lineGridBox)
282 m_rareData->m_lineGridBox->destroy(renderArena());
283 m_rareData->m_lineGridBox = box;
285 void layoutLineGridBox();
287 // Accessors for logical width/height and margins in the containing block's block-flow direction.
288 enum ApplyLayoutDeltaMode { ApplyLayoutDelta, DoNotApplyLayoutDelta };
289 LayoutUnit logicalWidthForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->width() : child->height(); }
290 LayoutUnit logicalHeightForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->height() : child->width(); }
291 LayoutUnit logicalTopForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->y() : child->x(); }
292 void setLogicalLeftForChild(RenderBox* child, LayoutUnit logicalLeft, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
293 void setLogicalTopForChild(RenderBox* child, LayoutUnit logicalTop, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
294 LayoutUnit marginBeforeForChild(const RenderBoxModelObject* child) const { return child->marginBefore(style()); }
295 LayoutUnit marginAfterForChild(const RenderBoxModelObject* child) const { return child->marginAfter(style()); }
296 LayoutUnit marginStartForChild(const RenderBoxModelObject* child) const { return child->marginStart(style()); }
297 LayoutUnit marginEndForChild(const RenderBoxModelObject* child) const { return child->marginEnd(style()); }
298 void setMarginStartForChild(RenderBox* child, LayoutUnit value) const { child->setMarginStart(value, style()); }
299 void setMarginEndForChild(RenderBox* child, LayoutUnit value) const { child->setMarginEnd(value, style()); }
300 void setMarginBeforeForChild(RenderBox* child, LayoutUnit value) const { child->setMarginBefore(value, style()); }
301 void setMarginAfterForChild(RenderBox* child, LayoutUnit value) const { child->setMarginAfter(value, style()); }
302 LayoutUnit collapsedMarginBeforeForChild(const RenderBox* child) const;
303 LayoutUnit collapsedMarginAfterForChild(const RenderBox* child) const;
305 void updateLogicalWidthForAlignment(const ETextAlign&, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, int expansionOpportunityCount);
307 virtual void updateFirstLetter();
311 MarginValues(LayoutUnit beforePos, LayoutUnit beforeNeg, LayoutUnit afterPos, LayoutUnit afterNeg)
312 : m_positiveMarginBefore(beforePos)
313 , m_negativeMarginBefore(beforeNeg)
314 , m_positiveMarginAfter(afterPos)
315 , m_negativeMarginAfter(afterNeg)
318 LayoutUnit positiveMarginBefore() const { return m_positiveMarginBefore; }
319 LayoutUnit negativeMarginBefore() const { return m_negativeMarginBefore; }
320 LayoutUnit positiveMarginAfter() const { return m_positiveMarginAfter; }
321 LayoutUnit negativeMarginAfter() const { return m_negativeMarginAfter; }
323 void setPositiveMarginBefore(LayoutUnit pos) { m_positiveMarginBefore = pos; }
324 void setNegativeMarginBefore(LayoutUnit neg) { m_negativeMarginBefore = neg; }
325 void setPositiveMarginAfter(LayoutUnit pos) { m_positiveMarginAfter = pos; }
326 void setNegativeMarginAfter(LayoutUnit neg) { m_negativeMarginAfter = neg; }
329 LayoutUnit m_positiveMarginBefore;
330 LayoutUnit m_negativeMarginBefore;
331 LayoutUnit m_positiveMarginAfter;
332 LayoutUnit m_negativeMarginAfter;
334 MarginValues marginValuesForChild(RenderBox* child) const;
336 virtual void scrollbarsChanged(bool /*horizontalScrollbarChanged*/, bool /*verticalScrollbarChanged*/) { };
338 LayoutUnit logicalLeftOffsetForContent(RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage) const;
339 LayoutUnit logicalRightOffsetForContent(RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage) const;
340 LayoutUnit availableLogicalWidthForContent(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
342 return max(ZERO_LAYOUT_UNIT, logicalRightOffsetForContent(region, offsetFromLogicalTopOfFirstPage) -
343 logicalLeftOffsetForContent(region, offsetFromLogicalTopOfFirstPage)); }
344 LayoutUnit startOffsetForContent(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
346 return style()->isLeftToRightDirection() ? logicalLeftOffsetForContent(region, offsetFromLogicalTopOfFirstPage)
347 : logicalWidth() - logicalRightOffsetForContent(region, offsetFromLogicalTopOfFirstPage);
349 LayoutUnit endOffsetForContent(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
351 return !style()->isLeftToRightDirection() ? logicalLeftOffsetForContent(region, offsetFromLogicalTopOfFirstPage)
352 : logicalWidth() - logicalRightOffsetForContent(region, offsetFromLogicalTopOfFirstPage);
354 LayoutUnit logicalLeftOffsetForContent(LayoutUnit blockOffset) const
356 return logicalLeftOffsetForContent(regionAtBlockOffset(blockOffset), offsetFromLogicalTopOfFirstPage());
358 LayoutUnit logicalRightOffsetForContent(LayoutUnit blockOffset) const
360 return logicalRightOffsetForContent(regionAtBlockOffset(blockOffset), offsetFromLogicalTopOfFirstPage());
362 LayoutUnit availableLogicalWidthForContent(LayoutUnit blockOffset) const
364 return availableLogicalWidthForContent(regionAtBlockOffset(blockOffset), offsetFromLogicalTopOfFirstPage());
366 LayoutUnit startOffsetForContent(LayoutUnit blockOffset) const
368 return startOffsetForContent(regionAtBlockOffset(blockOffset), offsetFromLogicalTopOfFirstPage());
370 LayoutUnit endOffsetForContent(LayoutUnit blockOffset) const
372 return endOffsetForContent(regionAtBlockOffset(blockOffset), offsetFromLogicalTopOfFirstPage());
374 LayoutUnit logicalLeftOffsetForContent() const { return isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop(); }
375 LayoutUnit logicalRightOffsetForContent() const { return logicalLeftOffsetForContent() + availableLogicalWidth(); }
376 LayoutUnit startOffsetForContent() const { return style()->isLeftToRightDirection() ? logicalLeftOffsetForContent() : logicalWidth() - logicalRightOffsetForContent(); }
377 LayoutUnit endOffsetForContent() const { return !style()->isLeftToRightDirection() ? logicalLeftOffsetForContent() : logicalWidth() - logicalRightOffsetForContent(); }
379 void setStaticInlinePositionForChild(RenderBox*, LayoutUnit blockOffset, LayoutUnit inlinePosition);
381 LayoutUnit computeStartPositionDeltaForChildAvoidingFloats(const RenderBox* child, LayoutUnit childMarginStart, RenderRegion* = 0, LayoutUnit offsetFromLogicalTopOfFirstPage = 0);
383 void placeRunInIfNeeded(RenderObject* newChild, PlaceGeneratedRunInFlag);
384 bool runInIsPlacedIntoSiblingBlock(RenderObject* runIn);
387 void checkPositionedObjectsNeedLayout();
388 void showLineTreeAndMark(const InlineBox* = 0, const char* = 0, const InlineBox* = 0, const char* = 0, const RenderObject* = 0) const;
392 virtual void willBeDestroyed();
394 LayoutUnit maxPositiveMarginBefore() const { return m_rareData ? m_rareData->m_margins.positiveMarginBefore() : RenderBlockRareData::positiveMarginBeforeDefault(this); }
395 LayoutUnit maxNegativeMarginBefore() const { return m_rareData ? m_rareData->m_margins.negativeMarginBefore() : RenderBlockRareData::negativeMarginBeforeDefault(this); }
396 LayoutUnit maxPositiveMarginAfter() const { return m_rareData ? m_rareData->m_margins.positiveMarginAfter() : RenderBlockRareData::positiveMarginAfterDefault(this); }
397 LayoutUnit maxNegativeMarginAfter() const { return m_rareData ? m_rareData->m_margins.negativeMarginAfter() : RenderBlockRareData::negativeMarginAfterDefault(this); }
399 void setMaxMarginBeforeValues(LayoutUnit pos, LayoutUnit neg);
400 void setMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg);
402 void initMaxMarginValues()
405 m_rareData->m_margins = MarginValues(RenderBlockRareData::positiveMarginBeforeDefault(this) , RenderBlockRareData::negativeMarginBeforeDefault(this),
406 RenderBlockRareData::positiveMarginAfterDefault(this), RenderBlockRareData::negativeMarginAfterDefault(this));
407 m_rareData->m_paginationStrut = 0;
411 virtual void layout();
413 void layoutPositionedObjects(bool relayoutChildren);
415 virtual void paint(PaintInfo&, const LayoutPoint&);
416 virtual void paintObject(PaintInfo&, const LayoutPoint&);
417 virtual void paintChildren(PaintInfo& forSelf, const LayoutPoint&, PaintInfo& forChild, bool usePrintRect);
418 bool paintChild(RenderBox*, PaintInfo& forSelf, const LayoutPoint&, PaintInfo& forChild, bool usePrintRect);
420 LayoutUnit logicalRightOffsetForLine(LayoutUnit position, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* logicalHeightRemaining = 0, LayoutUnit logicalHeight = 0) const;
421 LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* logicalHeightRemaining = 0, LayoutUnit logicalHeight = 0) const;
423 virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const;
424 virtual void adjustInlineDirectionLineBounds(int /* expansionOpportunityCount */, float& /* logicalLeft */, float& /* logicalWidth */) const { }
426 virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
428 virtual void computePreferredLogicalWidths();
430 virtual LayoutUnit firstLineBoxBaseline() const;
431 virtual LayoutUnit lastLineBoxBaseline() const;
433 virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&);
435 // Delay update scrollbar until finishDelayRepaint() will be
436 // called. This function is used when a flexbox is laying out its
437 // descendant. If multiple calls are made to startDelayRepaint(),
438 // finishDelayRepaint() will do nothing until finishDelayRepaint()
439 // is called the same number of times.
440 static void startDelayUpdateScrollInfo();
441 static void finishDelayUpdateScrollInfo();
443 virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
444 virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
446 virtual bool hasLineIfEmpty() const;
448 bool simplifiedLayout();
449 void simplifiedNormalFlowLayout();
451 void setDesiredColumnCountAndWidth(int, LayoutUnit);
453 void computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats = false);
454 virtual void addOverflowFromChildren();
455 void addOverflowFromFloats();
456 void addOverflowFromPositionedObjects();
457 void addOverflowFromBlockChildren();
458 void addOverflowFromInlineChildren();
459 void addVisualOverflowFromTheme();
461 virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint&);
464 // Only used by RenderSVGText, which explicitely overrides RenderBlock::layoutBlock(), do NOT use for anything else.
465 void forceLayoutInlineChildren()
467 LayoutUnit repaintLogicalTop = 0;
468 LayoutUnit repaintLogicalBottom = 0;
470 layoutInlineChildren(true, repaintLogicalTop, repaintLogicalBottom);
474 void computeInitialRegionRangeForBlock();
475 void computeRegionRangeForBlock();
477 virtual void checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight);
480 virtual RenderObjectChildList* virtualChildren() { return children(); }
481 virtual const RenderObjectChildList* virtualChildren() const { return children(); }
483 virtual const char* renderName() const;
485 virtual bool isRenderBlock() const { return true; }
486 virtual bool isBlockFlow() const { return (!isInline() || isReplaced()) && !isTable(); }
487 virtual bool isInlineBlockOrInlineTable() const { return isInline() && isReplaced(); }
489 void makeChildrenNonInline(RenderObject* insertionPoint = 0);
490 virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
492 static void collapseAnonymousBoxChild(RenderBlock* parent, RenderObject* child);
494 virtual void dirtyLinesFromChangedChild(RenderObject* child) { m_lineBoxes.dirtyLinesFromChangedChild(this, child); }
496 void addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild);
497 void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild);
498 void addChildToAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild);
500 virtual void addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild = 0);
502 virtual bool isSelfCollapsingBlock() const;
504 virtual LayoutUnit collapsedMarginBefore() const { return maxPositiveMarginBefore() - maxNegativeMarginBefore(); }
505 virtual LayoutUnit collapsedMarginAfter() const { return maxPositiveMarginAfter() - maxNegativeMarginAfter(); }
507 virtual void repaintOverhangingFloats(bool paintAllDescendants);
509 void layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloatLogicalBottom);
510 void layoutInlineChildren(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom);
511 BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>&, BidiContext*);
513 virtual void borderFitAdjust(LayoutRect&) const; // Shrink the box in which the border paints if border-fit is set.
515 virtual void updateBeforeAfterContent(PseudoId);
517 virtual RootInlineBox* createRootInlineBox(); // Subclassed by SVG and Ruby.
519 // Called to lay out the legend for a fieldset or the ruby text of a ruby run.
520 virtual RenderObject* layoutSpecialExcludedChild(bool /*relayoutChildren*/) { return 0; }
522 void createFirstLetterRenderer(RenderObject* firstLetterBlock, RenderObject* currentChild);
523 void updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderObject* firstLetterContainer);
525 struct FloatWithRect {
526 FloatWithRect(RenderBox* f)
528 , rect(LayoutRect(f->x() - f->marginLeft(), f->y() - f->marginTop(), f->width() + f->marginWidth(), f->height() + f->marginHeight()))
529 , everHadLayout(f->everHadLayout())
538 struct FloatingObject {
539 WTF_MAKE_NONCOPYABLE(FloatingObject); WTF_MAKE_FAST_ALLOCATED;
541 // Note that Type uses bits so you can use FloatLeftRight as a mask to query for both left and right.
542 enum Type { FloatLeft = 1, FloatRight = 2, FloatLeftRight = 3 };
544 FloatingObject(EFloat type)
546 , m_originatingLine(0)
547 , m_paginationStrut(0)
548 , m_shouldPaint(true)
549 , m_isDescendant(false)
552 , m_isInPlacedTree(false)
555 ASSERT(type != NoFloat);
556 if (type == LeftFloat)
558 else if (type == RightFloat)
562 FloatingObject(Type type, const LayoutRect& frameRect)
564 , m_originatingLine(0)
565 , m_frameRect(frameRect)
566 , m_paginationStrut(0)
568 , m_shouldPaint(true)
569 , m_isDescendant(false)
572 , m_isInPlacedTree(false)
577 Type type() const { return static_cast<Type>(m_type); }
578 RenderBox* renderer() const { return m_renderer; }
580 bool isPlaced() const { return m_isPlaced; }
581 void setIsPlaced(bool placed = true) { m_isPlaced = placed; }
583 inline LayoutUnit x() const { ASSERT(isPlaced()); return m_frameRect.x(); }
584 inline LayoutUnit maxX() const { ASSERT(isPlaced()); return m_frameRect.maxX(); }
585 inline LayoutUnit y() const { ASSERT(isPlaced()); return m_frameRect.y(); }
586 inline LayoutUnit maxY() const { ASSERT(isPlaced()); return m_frameRect.maxY(); }
587 inline LayoutUnit width() const { return m_frameRect.width(); }
588 inline LayoutUnit height() const { return m_frameRect.height(); }
590 void setX(LayoutUnit x) { ASSERT(!isInPlacedTree()); m_frameRect.setX(x); }
591 void setY(LayoutUnit y) { ASSERT(!isInPlacedTree()); m_frameRect.setY(y); }
592 void setWidth(LayoutUnit width) { ASSERT(!isInPlacedTree()); m_frameRect.setWidth(width); }
593 void setHeight(LayoutUnit height) { ASSERT(!isInPlacedTree()); m_frameRect.setHeight(height); }
595 const LayoutRect& frameRect() const { ASSERT(isPlaced()); return m_frameRect; }
596 void setFrameRect(const LayoutRect& frameRect) { ASSERT(!isInPlacedTree()); m_frameRect = frameRect; }
599 bool isInPlacedTree() const { return m_isInPlacedTree; }
600 void setIsInPlacedTree(bool value) { m_isInPlacedTree = value; }
603 bool shouldPaint() const { return m_shouldPaint; }
604 void setShouldPaint(bool shouldPaint) { m_shouldPaint = shouldPaint; }
605 bool isDescendant() const { return m_isDescendant; }
606 void setIsDescendant(bool isDescendant) { m_isDescendant = isDescendant; }
608 RenderBox* m_renderer;
609 RootInlineBox* m_originatingLine;
610 LayoutRect m_frameRect;
611 int m_paginationStrut;
614 unsigned m_type : 2; // Type (left or right aligned)
615 unsigned m_shouldPaint : 1;
616 unsigned m_isDescendant : 1;
617 unsigned m_isPlaced : 1;
619 unsigned m_isInPlacedTree : 1;
623 LayoutPoint flipFloatForWritingModeForChild(const FloatingObject*, const LayoutPoint&) const;
625 LayoutUnit logicalTopForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->y() : child->x(); }
626 LayoutUnit logicalBottomForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->maxY() : child->maxX(); }
627 LayoutUnit logicalLeftForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->x() : child->y(); }
628 LayoutUnit logicalRightForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->maxX() : child->maxY(); }
629 LayoutUnit logicalWidthForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->width() : child->height(); }
631 int pixelSnappedLogicalTopForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedY() : child->frameRect().pixelSnappedX(); }
632 int pixelSnappedLogicalBottomForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedMaxY() : child->frameRect().pixelSnappedMaxX(); }
633 int pixelSnappedLogicalLeftForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedX() : child->frameRect().pixelSnappedY(); }
634 int pixelSnappedLogicalRightForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedMaxX() : child->frameRect().pixelSnappedMaxY(); }
636 void setLogicalTopForFloat(FloatingObject* child, LayoutUnit logicalTop)
638 if (isHorizontalWritingMode())
639 child->setY(logicalTop);
641 child->setX(logicalTop);
643 void setLogicalLeftForFloat(FloatingObject* child, LayoutUnit logicalLeft)
645 if (isHorizontalWritingMode())
646 child->setX(logicalLeft);
648 child->setY(logicalLeft);
650 void setLogicalHeightForFloat(FloatingObject* child, LayoutUnit logicalHeight)
652 if (isHorizontalWritingMode())
653 child->setHeight(logicalHeight);
655 child->setWidth(logicalHeight);
657 void setLogicalWidthForFloat(FloatingObject* child, LayoutUnit logicalWidth)
659 if (isHorizontalWritingMode())
660 child->setWidth(logicalWidth);
662 child->setHeight(logicalWidth);
665 LayoutUnit xPositionForFloatIncludingMargin(const FloatingObject* child) const
667 if (isHorizontalWritingMode())
668 return child->x() + child->renderer()->marginLeft();
670 return child->x() + marginBeforeForChild(child->renderer());
673 LayoutUnit yPositionForFloatIncludingMargin(const FloatingObject* child) const
675 if (isHorizontalWritingMode())
676 return child->y() + marginBeforeForChild(child->renderer());
678 return child->y() + child->renderer()->marginTop();
681 LayoutPoint computeLogicalLocationForFloat(const FloatingObject*, LayoutUnit logicalTopOffset) const;
683 // The following functions' implementations are in RenderBlockLineLayout.cpp.
684 typedef std::pair<RenderText*, LazyLineBreakIterator> LineBreakIteratorInfo;
687 LineBreaker(RenderBlock* block)
693 InlineIterator nextLineBreak(InlineBidiResolver&, LineInfo&, LineBreakIteratorInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines);
695 bool lineWasHyphenated() { return m_hyphenated; }
696 const Vector<RenderBox*>& positionedObjects() { return m_positionedObjects; }
697 EClear clear() { return m_clear; }
701 void skipTrailingWhitespace(InlineIterator&, const LineInfo&);
702 void skipLeadingWhitespace(InlineBidiResolver&, LineInfo&, FloatingObject* lastFloatFromPreviousLine, LineWidth&);
704 RenderBlock* m_block;
707 Vector<RenderBox*> m_positionedObjects;
710 void checkFloatsInCleanLine(RootInlineBox*, Vector<FloatWithRect>&, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat);
711 RootInlineBox* determineStartPosition(LineLayoutState&, InlineBidiResolver&);
712 void determineEndPosition(LineLayoutState&, RootInlineBox* startBox, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus);
713 bool matchedEndLine(LineLayoutState&, const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus);
714 bool checkPaginationAndFloatsAtEndLine(LineLayoutState&);
716 RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
717 InlineFlowBox* createLineBoxes(RenderObject*, const LineInfo&, InlineBox* childBox);
719 void setMarginsForRubyRun(BidiRun*, RenderRubyRun*, RenderObject*, const LineInfo&);
721 void computeInlineDirectionPositionsForLine(RootInlineBox*, const LineInfo&, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&);
722 void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&);
723 void deleteEllipsisLineBoxes();
724 void checkLinesForTextOverflow();
726 // Positions new floats and also adjust all floats encountered on the line if any of them
727 // have to move to the next page/column.
728 bool positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo&, LineWidth&);
729 void appendFloatingObjectToLastLine(FloatingObject*);
731 // End of functions defined in RenderBlockLineLayout.cpp.
733 void paintFloats(PaintInfo&, const LayoutPoint&, bool preservePhase = false);
734 void paintContents(PaintInfo&, const LayoutPoint&);
735 void paintColumnContents(PaintInfo&, const LayoutPoint&, bool paintFloats = false);
736 void paintColumnRules(PaintInfo&, const LayoutPoint&);
737 void paintEllipsisBoxes(PaintInfo&, const LayoutPoint&);
738 void paintSelection(PaintInfo&, const LayoutPoint&);
739 void paintCaret(PaintInfo&, const LayoutPoint&, CaretType);
741 FloatingObject* insertFloatingObject(RenderBox*);
742 void removeFloatingObject(RenderBox*);
743 void removeFloatingObjectsBelow(FloatingObject*, int logicalOffset);
745 // Called from lineWidth, to position the floats added in the last line.
746 // Returns true if and only if it has positioned any floats.
747 bool positionNewFloats();
751 LayoutUnit getClearDelta(RenderBox* child, LayoutUnit yPos);
753 virtual bool avoidsFloats() const;
755 bool hasOverhangingFloats() { return parent() && !hasColumns() && containsFloats() && lowestFloatLogicalBottom() > logicalHeight(); }
756 bool hasOverhangingFloat(RenderBox*);
757 void addIntrudingFloats(RenderBlock* prev, LayoutUnit xoffset, LayoutUnit yoffset);
758 LayoutUnit addOverhangingFloats(RenderBlock* child, bool makeChildPaintOtherFloats);
760 LayoutUnit lowestFloatLogicalBottom(FloatingObject::Type = FloatingObject::FloatLeftRight) const;
761 LayoutUnit nextFloatLogicalBottomBelow(LayoutUnit) const;
763 virtual bool hitTestColumns(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
764 virtual bool hitTestContents(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
765 bool hitTestFloats(const HitTestRequest&, HitTestResult&, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset);
767 virtual bool isPointInOverflowControl(HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset);
769 void computeInlinePreferredLogicalWidths();
770 void computeBlockPreferredLogicalWidths();
772 // Obtains the nearest enclosing block (including this block) that contributes a first-line style to our inline
774 virtual RenderBlock* firstLineBlock() const;
776 virtual LayoutRect rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, LayoutUnit outlineWidth) const;
777 virtual RenderStyle* outlineStyleForRepaint() const;
779 virtual RenderObject* hoverAncestor() const;
780 virtual void updateDragState(bool dragOn);
781 virtual void childBecameNonInline(RenderObject* child);
783 virtual LayoutRect selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool /*clipToVisibleContent*/)
785 return selectionGapRectsForRepaint(repaintContainer);
787 virtual bool shouldPaintSelectionGaps() const;
788 bool isSelectionRoot() const;
789 GapRects selectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
790 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* = 0);
791 GapRects inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
792 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo*);
793 GapRects blockSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
794 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo*);
795 LayoutRect blockSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
796 LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const PaintInfo*);
797 LayoutUnit logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position);
798 LayoutUnit logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position);
800 virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const;
801 virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
803 LayoutUnit desiredColumnWidth() const;
804 unsigned desiredColumnCount() const;
806 void paintContinuationOutlines(PaintInfo&, const LayoutPoint&);
808 virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0);
810 void adjustPointToColumnContents(LayoutPoint&) const;
811 void adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const; // Helper function for borderFitAdjust
813 void markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit logicalBottom, RootInlineBox* highest = 0);
815 void newLine(EClear);
817 Position positionForBox(InlineBox*, bool start = true) const;
818 VisiblePosition positionForPointWithInlineChildren(const LayoutPoint&);
820 virtual void calcColumnWidth();
821 void makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, RenderBlock* newBlockBox, RenderObject* newChild);
823 bool expandsToEncloseOverhangingFloats() const;
825 void updateScrollInfoAfterLayout();
827 void splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock,
828 RenderObject* beforeChild, RenderBoxModelObject* oldCont);
829 void splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
830 RenderObject* newChild, RenderBoxModelObject* oldCont);
831 RenderBlock* clone() const;
832 RenderBlock* continuationBefore(RenderObject* beforeChild);
833 RenderBlock* containingColumnsBlock(bool allowAnonymousColumnBlock = true);
834 RenderBlock* columnsBlockForSpanningElement(RenderObject* newChild);
837 // Collapsing flags for whether we can collapse our margins with our children's margins.
838 bool m_canCollapseWithChildren : 1;
839 bool m_canCollapseMarginBeforeWithChildren : 1;
840 bool m_canCollapseMarginAfterWithChildren : 1;
842 // Whether or not we are a quirky container, i.e., do we collapse away top and bottom
843 // margins in our container. Table cells and the body are the common examples. We
844 // also have a custom style property for Safari RSS to deal with TypePad blog articles.
845 bool m_quirkContainer : 1;
847 // This flag tracks whether we are still looking at child margins that can all collapse together at the beginning of a block.
848 // They may or may not collapse with the top margin of the block (|m_canCollapseTopWithChildren| tells us that), but they will
849 // always be collapsing with one another. This variable can remain set to true through multiple iterations
850 // as long as we keep encountering self-collapsing blocks.
851 bool m_atBeforeSideOfBlock : 1;
853 // This flag is set when we know we're examining bottom margins and we know we're at the bottom of the block.
854 bool m_atAfterSideOfBlock : 1;
856 // These variables are used to detect quirky margins that we need to collapse away (in table cells
857 // and in the body element).
858 bool m_marginBeforeQuirk : 1;
859 bool m_marginAfterQuirk : 1;
860 bool m_determinedMarginBeforeQuirk : 1;
862 // These flags track the previous maximal positive and negative margins.
863 LayoutUnit m_positiveMargin;
864 LayoutUnit m_negativeMargin;
867 MarginInfo(RenderBlock*, LayoutUnit beforeBorderPadding, LayoutUnit afterBorderPadding);
869 void setAtBeforeSideOfBlock(bool b) { m_atBeforeSideOfBlock = b; }
870 void setAtAfterSideOfBlock(bool b) { m_atAfterSideOfBlock = b; }
873 m_positiveMargin = 0;
874 m_negativeMargin = 0;
876 void setMarginBeforeQuirk(bool b) { m_marginBeforeQuirk = b; }
877 void setMarginAfterQuirk(bool b) { m_marginAfterQuirk = b; }
878 void setDeterminedMarginBeforeQuirk(bool b) { m_determinedMarginBeforeQuirk = b; }
879 void setPositiveMargin(LayoutUnit p) { m_positiveMargin = p; }
880 void setNegativeMargin(LayoutUnit n) { m_negativeMargin = n; }
881 void setPositiveMarginIfLarger(LayoutUnit p)
883 if (p > m_positiveMargin)
884 m_positiveMargin = p;
886 void setNegativeMarginIfLarger(LayoutUnit n)
888 if (n > m_negativeMargin)
889 m_negativeMargin = n;
892 void setMargin(LayoutUnit p, LayoutUnit n) { m_positiveMargin = p; m_negativeMargin = n; }
894 bool atBeforeSideOfBlock() const { return m_atBeforeSideOfBlock; }
895 bool canCollapseWithMarginBefore() const { return m_atBeforeSideOfBlock && m_canCollapseMarginBeforeWithChildren; }
896 bool canCollapseWithMarginAfter() const { return m_atAfterSideOfBlock && m_canCollapseMarginAfterWithChildren; }
897 bool canCollapseMarginBeforeWithChildren() const { return m_canCollapseMarginBeforeWithChildren; }
898 bool canCollapseMarginAfterWithChildren() const { return m_canCollapseMarginAfterWithChildren; }
899 bool quirkContainer() const { return m_quirkContainer; }
900 bool determinedMarginBeforeQuirk() const { return m_determinedMarginBeforeQuirk; }
901 bool marginBeforeQuirk() const { return m_marginBeforeQuirk; }
902 bool marginAfterQuirk() const { return m_marginAfterQuirk; }
903 LayoutUnit positiveMargin() const { return m_positiveMargin; }
904 LayoutUnit negativeMargin() const { return m_negativeMargin; }
905 LayoutUnit margin() const { return m_positiveMargin - m_negativeMargin; }
908 void layoutBlockChild(RenderBox* child, MarginInfo&, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom);
909 void adjustPositionedBlock(RenderBox* child, const MarginInfo&);
910 void adjustFloatingBlock(const MarginInfo&);
911 bool handleSpecialChild(RenderBox* child, const MarginInfo&);
912 bool handleFloatingChild(RenderBox* child, const MarginInfo&);
913 bool handlePositionedChild(RenderBox* child, const MarginInfo&);
915 RenderBoxModelObject* createReplacementRunIn(RenderBoxModelObject* runIn);
916 void moveRunInUnderSiblingBlockIfNeeded(RenderObject* runIn);
917 void moveRunInToOriginalPosition(RenderObject* runIn);
919 LayoutUnit collapseMargins(RenderBox* child, MarginInfo&);
920 LayoutUnit clearFloatsIfNeeded(RenderBox* child, MarginInfo&, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos);
921 LayoutUnit estimateLogicalTopPosition(RenderBox* child, const MarginInfo&, LayoutUnit& estimateWithoutPagination);
922 void marginBeforeEstimateForChild(RenderBox* child, LayoutUnit& positiveMarginBefore, LayoutUnit& negativeMarginBefore) const;
923 void determineLogicalLeftPositionForChild(RenderBox* child);
924 void handleAfterSideOfBlock(LayoutUnit top, LayoutUnit bottom, MarginInfo&);
925 void setCollapsedBottomMargin(const MarginInfo&);
926 // End helper functions and structs used by layoutBlockChildren.
928 // Helper function for layoutInlineChildren()
929 RootInlineBox* createLineBoxesFromBidiRuns(BidiRunList<BidiRun>&, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun);
930 void layoutRunsAndFloats(LineLayoutState&, bool hasInlineChild);
931 void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines);
932 void linkToEndLineIfNeeded(LineLayoutState&);
933 static void repaintDirtyFloats(Vector<FloatWithRect>& floats);
936 // Pagination routines.
937 virtual bool relayoutForPagination(bool hasSpecifiedPageLogicalHeight, LayoutUnit pageLogicalHeight, LayoutStateMaintainer&);
939 // Returns the logicalOffset at the top of the next page. If the offset passed in is already at the top of the current page,
940 // then nextPageLogicalTop with ExcludePageBoundary will still move to the top of the next page. nextPageLogicalTop with
941 // IncludePageBoundary set will not.
943 // For a page height of 800px, the first rule will return 800 if the value passed in is 0. The second rule will simply return 0.
944 enum PageBoundaryRule { ExcludePageBoundary, IncludePageBoundary };
945 LayoutUnit nextPageLogicalTop(LayoutUnit logicalOffset, PageBoundaryRule = ExcludePageBoundary) const;
946 bool hasNextPage(LayoutUnit logicalOffset, PageBoundaryRule = ExcludePageBoundary) const;
948 virtual ColumnInfo::PaginationUnit paginationUnit() const;
950 LayoutUnit applyBeforeBreak(RenderBox* child, LayoutUnit logicalOffset); // If the child has a before break, then return a new yPos that shifts to the top of the next page/column.
951 LayoutUnit applyAfterBreak(RenderBox* child, LayoutUnit logicalOffset, MarginInfo&); // If the child has an after break, then return a new offset that shifts to the top of the next page/column.
954 LayoutUnit pageLogicalTopForOffset(LayoutUnit offset) const;
955 LayoutUnit pageLogicalHeightForOffset(LayoutUnit offset) const;
956 LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit offset, PageBoundaryRule = IncludePageBoundary) const;
959 bool pushToNextPageWithMinimumLogicalHeight(LayoutUnit& adjustment, LayoutUnit logicalOffset, LayoutUnit minimumLogicalHeight) const;
961 LayoutUnit adjustForUnsplittableChild(RenderBox* child, LayoutUnit logicalOffset, bool includeMargins = false); // If the child is unsplittable and can't fit on the current page, return the top of the next page/column.
962 void adjustLinePositionForPagination(RootInlineBox*, LayoutUnit& deltaOffset); // Computes a deltaOffset value that put a line at the top of the next page if it doesn't fit on the current page.
963 LayoutUnit adjustBlockChildForPagination(LayoutUnit logicalTopAfterClear, LayoutUnit estimateWithoutPagination, RenderBox* child, bool atBeforeSideOfBlock);
965 // Adjust from painting offsets to the local coords of this renderer
966 void offsetForContents(LayoutPoint&) const;
968 // This function is called to test a line box that has moved in the block direction to see if it has ended up in a new
969 // region/page/column that has a different available line width than the old one. Used to know when you have to dirty a
970 // line, i.e., that it can't be re-used.
971 bool lineWidthForPaginatedLineChanged(RootInlineBox*, LayoutUnit lineDelta = 0) const;
973 bool logicalWidthChangedInRegions() const;
975 virtual bool requiresColumns(int desiredColumnCount) const;
977 virtual bool recomputeLogicalWidth();
980 LayoutUnit offsetFromLogicalTopOfFirstPage() const;
981 RenderRegion* regionAtBlockOffset(LayoutUnit) const;
982 RenderRegion* clampToStartAndEndRegions(RenderRegion*) const;
985 struct FloatingObjectHashFunctions {
986 static unsigned hash(FloatingObject* key) { return DefaultHash<RenderBox*>::Hash::hash(key->m_renderer); }
987 static bool equal(FloatingObject* a, FloatingObject* b) { return a->m_renderer == b->m_renderer; }
988 static const bool safeToCompareToEmptyOrDeleted = true;
990 struct FloatingObjectHashTranslator {
991 static unsigned hash(RenderBox* key) { return DefaultHash<RenderBox*>::Hash::hash(key); }
992 static bool equal(FloatingObject* a, RenderBox* b) { return a->m_renderer == b; }
994 typedef ListHashSet<FloatingObject*, 4, FloatingObjectHashFunctions> FloatingObjectSet;
995 typedef FloatingObjectSet::const_iterator FloatingObjectSetIterator;
996 typedef PODInterval<int, FloatingObject*> FloatingObjectInterval;
997 typedef PODIntervalTree<int, FloatingObject*> FloatingObjectTree;
998 typedef PODFreeListArena<PODRedBlackTree<FloatingObjectInterval>::Node> IntervalArena;
1000 template <FloatingObject::Type FloatTypeValue>
1001 class FloatIntervalSearchAdapter {
1003 typedef FloatingObjectInterval IntervalType;
1005 FloatIntervalSearchAdapter(const RenderBlock* renderer, int lowValue, int highValue, LayoutUnit& offset, LayoutUnit* heightRemaining)
1006 : m_renderer(renderer)
1007 , m_lowValue(lowValue)
1008 , m_highValue(highValue)
1010 , m_heightRemaining(heightRemaining)
1014 inline int lowValue() const { return m_lowValue; }
1015 inline int highValue() const { return m_highValue; }
1016 void collectIfNeeded(const IntervalType&) const;
1019 const RenderBlock* m_renderer;
1022 LayoutUnit& m_offset;
1023 LayoutUnit* m_heightRemaining;
1026 class FloatingObjects {
1028 FloatingObjects(const RenderBlock* renderer, bool horizontalWritingMode)
1029 : m_placedFloatsTree(UninitializedTree)
1030 , m_leftObjectsCount(0)
1031 , m_rightObjectsCount(0)
1032 , m_horizontalWritingMode(horizontalWritingMode)
1033 , m_renderer(renderer)
1038 void add(FloatingObject*);
1039 void remove(FloatingObject*);
1040 void addPlacedObject(FloatingObject*);
1041 void removePlacedObject(FloatingObject*);
1042 void setHorizontalWritingMode(bool b = true) { m_horizontalWritingMode = b; }
1044 bool hasLeftObjects() const { return m_leftObjectsCount > 0; }
1045 bool hasRightObjects() const { return m_rightObjectsCount > 0; }
1046 const FloatingObjectSet& set() const { return m_set; }
1047 const FloatingObjectTree& placedFloatsTree()
1049 computePlacedFloatsTreeIfNeeded();
1050 return m_placedFloatsTree;
1053 void computePlacedFloatsTree();
1054 inline void computePlacedFloatsTreeIfNeeded()
1056 if (!m_placedFloatsTree.isInitialized())
1057 computePlacedFloatsTree();
1059 void increaseObjectsCount(FloatingObject::Type);
1060 void decreaseObjectsCount(FloatingObject::Type);
1061 FloatingObjectInterval intervalForFloatingObject(FloatingObject*);
1063 FloatingObjectSet m_set;
1064 FloatingObjectTree m_placedFloatsTree;
1065 unsigned m_leftObjectsCount;
1066 unsigned m_rightObjectsCount;
1067 bool m_horizontalWritingMode;
1068 const RenderBlock* m_renderer;
1070 OwnPtr<FloatingObjects> m_floatingObjects;
1072 typedef PositionedObjectsListHashSet::const_iterator Iterator;
1073 OwnPtr<PositionedObjectsListHashSet> m_positionedObjects;
1075 // Allocated only when some of these fields have non-default values
1076 struct RenderBlockRareData {
1077 WTF_MAKE_NONCOPYABLE(RenderBlockRareData); WTF_MAKE_FAST_ALLOCATED;
1079 RenderBlockRareData(const RenderBlock* block)
1080 : m_margins(positiveMarginBeforeDefault(block), negativeMarginBeforeDefault(block), positiveMarginAfterDefault(block), negativeMarginAfterDefault(block))
1081 , m_paginationStrut(0)
1082 , m_pageLogicalOffset(0)
1087 static LayoutUnit positiveMarginBeforeDefault(const RenderBlock* block)
1089 return std::max(block->marginBefore(), ZERO_LAYOUT_UNIT);
1092 static LayoutUnit negativeMarginBeforeDefault(const RenderBlock* block)
1094 return std::max(-block->marginBefore(), ZERO_LAYOUT_UNIT);
1096 static LayoutUnit positiveMarginAfterDefault(const RenderBlock* block)
1098 return std::max(block->marginAfter(), ZERO_LAYOUT_UNIT);
1100 static LayoutUnit negativeMarginAfterDefault(const RenderBlock* block)
1102 return std::max(-block->marginAfter(), ZERO_LAYOUT_UNIT);
1105 MarginValues m_margins;
1106 LayoutUnit m_paginationStrut;
1107 LayoutUnit m_pageLogicalOffset;
1109 RootInlineBox* m_lineGridBox;
1112 OwnPtr<RenderBlockRareData> m_rareData;
1114 RenderObjectChildList m_children;
1115 RenderLineBoxList m_lineBoxes; // All of the root line boxes created for this block flow. For example, <div>Hello<br>world.</div> will have two total lines for the <div>.
1117 mutable signed m_lineHeight : 30;
1118 unsigned m_beingDestroyed : 1;
1119 unsigned m_hasMarkupTruncation : 1;
1121 // RenderRubyBase objects need to be able to split and merge, moving their children around
1122 // (calling moveChildTo, moveAllChildrenTo, and makeChildrenNonInline).
1123 friend class RenderRubyBase;
1124 friend class LineWidth; // Needs to know FloatingObject
1127 // Used to store state between styleWillChange and styleDidChange
1128 static bool s_canPropagateFloatIntoSibling;
1131 inline RenderBlock* toRenderBlock(RenderObject* object)
1133 ASSERT(!object || object->isRenderBlock());
1134 return static_cast<RenderBlock*>(object);
1137 inline const RenderBlock* toRenderBlock(const RenderObject* object)
1139 ASSERT(!object || object->isRenderBlock());
1140 return static_cast<const RenderBlock*>(object);
1143 // This will catch anyone doing an unnecessary cast.
1144 void toRenderBlock(const RenderBlock*);
1147 // These structures are used by PODIntervalTree for debugging purposes.
1148 template <> struct ValueToString<int> {
1149 static String string(const int value);
1151 template<> struct ValueToString<RenderBlock::FloatingObject*> {
1152 static String string(const RenderBlock::FloatingObject*);
1156 } // namespace WebCore
1158 #endif // RenderBlock_h