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"
32 #include "TextBreakIterator.h"
34 #include <wtf/OwnPtr.h>
35 #include <wtf/ListHashSet.h>
37 #if ENABLE(CSS_SHAPES)
38 #include "ExclusionShapeInsideInfo.h"
39 #include "ExclusionShapeValue.h"
46 class LayoutStateMaintainer;
47 class LineLayoutState;
49 class LogicalSelectionOffsetCaches;
57 #if ENABLE(CSS_SHAPES)
61 class WordMeasurement;
63 template <class Iterator, class Run> class BidiResolver;
64 template <class Run> class BidiRunList;
65 template <class Iterator> struct MidpointState;
66 typedef BidiResolver<InlineIterator, BidiRun> InlineBidiResolver;
67 typedef MidpointState<InlineIterator> LineMidpointState;
68 typedef WTF::ListHashSet<RenderBox*, 16> TrackedRendererListHashSet;
69 typedef WTF::HashMap<const RenderBlock*, OwnPtr<TrackedRendererListHashSet> > TrackedDescendantsMap;
70 typedef WTF::HashMap<const RenderBox*, OwnPtr<HashSet<RenderBlock*> > > TrackedContainerMap;
71 typedef Vector<WordMeasurement, 64> WordMeasurements;
73 enum CaretType { CursorCaret, DragCaret };
74 enum ContainingBlockState { NewContainingBlock, SameContainingBlock };
75 enum ShapeOutsideFloatOffsetMode { ShapeOutsideFloatShapeOffset, ShapeOutsideFloatBoundingBoxOffset };
78 DefaultTextRunFlags = 0,
79 RespectDirection = 1 << 0,
80 RespectDirectionOverride = 1 << 1
83 typedef unsigned TextRunFlags;
85 class RenderBlock : public RenderBox {
87 friend class LineLayoutState;
89 // Used by the PODIntervalTree for debugging the FloatingObject.
90 template <class> friend struct ValueToString;
93 explicit RenderBlock(ContainerNode*);
94 virtual ~RenderBlock();
96 static RenderBlock* createAnonymous(Document*);
98 RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
99 RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
101 const RenderObjectChildList* children() const { return &m_children; }
102 RenderObjectChildList* children() { return &m_children; }
104 bool beingDestroyed() const { return m_beingDestroyed; }
106 // These two functions are overridden for inline-block.
107 virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
108 virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
110 RenderLineBoxList* lineBoxes() { return &m_lineBoxes; }
111 const RenderLineBoxList* lineBoxes() const { return &m_lineBoxes; }
113 InlineFlowBox* firstLineBox() const { return m_lineBoxes.firstLineBox(); }
114 InlineFlowBox* lastLineBox() const { return m_lineBoxes.lastLineBox(); }
116 void deleteLineBoxTree();
118 virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
119 virtual void removeChild(RenderObject*);
121 virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0);
123 void insertPositionedObject(RenderBox*);
124 static void removePositionedObject(RenderBox*);
125 void removePositionedObjects(RenderBlock*, ContainingBlockState = SameContainingBlock);
127 void removeFloatingObjects();
129 TrackedRendererListHashSet* positionedObjects() const;
130 bool hasPositionedObjects() const
132 TrackedRendererListHashSet* objects = positionedObjects();
133 return objects && !objects->isEmpty();
136 void addPercentHeightDescendant(RenderBox*);
137 static void removePercentHeightDescendant(RenderBox*);
138 TrackedRendererListHashSet* percentHeightDescendants() const;
139 static bool hasPercentHeightContainerMap();
140 static bool hasPercentHeightDescendant(RenderBox*);
141 static void clearPercentHeightDescendantsFrom(RenderBox*);
142 static void removePercentHeightDescendantIfNeeded(RenderBox*);
144 void setHasMarkupTruncation(bool b) { m_hasMarkupTruncation = b; }
145 bool hasMarkupTruncation() const { return m_hasMarkupTruncation; }
147 void setHasMarginBeforeQuirk(bool b) { m_hasMarginBeforeQuirk = b; }
148 void setHasMarginAfterQuirk(bool b) { m_hasMarginAfterQuirk = b; }
150 bool hasMarginBeforeQuirk() const { return m_hasMarginBeforeQuirk; }
151 bool hasMarginAfterQuirk() const { return m_hasMarginAfterQuirk; }
153 bool hasMarginBeforeQuirk(const RenderBox* child) const;
154 bool hasMarginAfterQuirk(const RenderBox* child) const;
156 RootInlineBox* createAndAppendRootInlineBox();
158 bool generatesLineBoxesForInlineChild(RenderObject*);
160 void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true);
161 void markSiblingsWithFloatsForLayout(RenderBox* floatToRemove = 0);
162 void markPositionedObjectsForLayout();
163 virtual void markForPaginationRelayoutIfNeeded();
165 bool containsFloats() const { return m_floatingObjects && !m_floatingObjects->set().isEmpty(); }
166 bool containsFloat(RenderBox*) const;
168 // Versions that can compute line offsets with the region and page offset passed in. Used for speed to avoid having to
169 // compute the region all over again when you already know it.
170 LayoutUnit availableLogicalWidthForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit logicalHeight = 0) const
172 return max<LayoutUnit>(0, logicalRightOffsetForLine(position, shouldIndentText, region, logicalHeight)
173 - logicalLeftOffsetForLine(position, shouldIndentText, region, logicalHeight));
175 LayoutUnit logicalRightOffsetForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit logicalHeight = 0, ShapeOutsideFloatOffsetMode offsetMode = ShapeOutsideFloatShapeOffset) const
177 return logicalRightOffsetForLine(position, logicalRightOffsetForContent(region), shouldIndentText, 0, logicalHeight, offsetMode);
179 LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit logicalHeight = 0, ShapeOutsideFloatOffsetMode offsetMode = ShapeOutsideFloatShapeOffset) const
181 return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(region), shouldIndentText, 0, logicalHeight, offsetMode);
183 LayoutUnit startOffsetForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit logicalHeight = 0) const
185 return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, region, logicalHeight)
186 : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, region, logicalHeight);
188 LayoutUnit endOffsetForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit logicalHeight = 0) const
190 return !style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, region, logicalHeight)
191 : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, region, logicalHeight);
194 LayoutUnit availableLogicalWidthForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
196 return availableLogicalWidthForLine(position, shouldIndentText, regionAtBlockOffset(position), logicalHeight);
198 LayoutUnit logicalRightOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0, ShapeOutsideFloatOffsetMode offsetMode = ShapeOutsideFloatShapeOffset) const
200 return logicalRightOffsetForLine(position, logicalRightOffsetForContent(position), shouldIndentText, 0, logicalHeight, offsetMode);
202 LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0, ShapeOutsideFloatOffsetMode offsetMode = ShapeOutsideFloatShapeOffset) const
204 return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(position), shouldIndentText, 0, logicalHeight, offsetMode);
206 LayoutUnit pixelSnappedLogicalLeftOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
208 return roundToInt(logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight));
210 LayoutUnit pixelSnappedLogicalRightOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
212 // FIXME: Multicolumn layouts break carrying over subpixel values to the logical right offset because the lines may be shifted
213 // by a subpixel value for all but the first column. This can lead to the actual pixel snapped width of the column being off
214 // by one pixel when rendered versus layed out, which can result in the line being clipped. For now, we have to floor.
215 // https://bugs.webkit.org/show_bug.cgi?id=105461
216 return floorToInt(logicalRightOffsetForLine(position, shouldIndentText, logicalHeight));
218 LayoutUnit startOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
220 return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight)
221 : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, logicalHeight);
223 LayoutUnit endOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
225 return !style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight)
226 : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, logicalHeight);
229 LayoutUnit startAlignedOffsetForLine(LayoutUnit position, bool shouldIndentText);
230 LayoutUnit textIndentOffset() const;
232 virtual VisiblePosition positionForPoint(const LayoutPoint&);
234 // Block flows subclass availableWidth to handle multi column layout (shrinking the width available to children when laying out.)
235 virtual LayoutUnit availableLogicalWidth() const;
237 LayoutPoint flipForWritingModeIncludingColumns(const LayoutPoint&) const;
238 void adjustStartEdgeForWritingModeIncludingColumns(LayoutRect&) const;
240 RootInlineBox* firstRootBox() const { return static_cast<RootInlineBox*>(firstLineBox()); }
241 RootInlineBox* lastRootBox() const { return static_cast<RootInlineBox*>(lastLineBox()); }
243 bool containsNonZeroBidiLevel() const;
245 GapRects selectionGapRectsForRepaint(const RenderLayerModelObject* repaintContainer);
246 LayoutRect logicalLeftSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
247 RenderObject* selObj, LayoutUnit logicalLeft, LayoutUnit logicalTop, LayoutUnit logicalHeight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
248 LayoutRect logicalRightSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
249 RenderObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
250 void getSelectionGapInfo(SelectionState, bool& leftGap, bool& rightGap);
251 RenderBlock* blockBeforeWithinSelectionRoot(LayoutSize& offset) const;
253 LayoutRect logicalRectToPhysicalRect(const LayoutPoint& physicalPosition, const LayoutRect& logicalRect);
255 // Helper methods for computing line counts and heights for line counts.
256 RootInlineBox* lineAtIndex(int) const;
257 int lineCount(const RootInlineBox* = 0, bool* = 0) const;
258 int heightForLineCount(int);
259 void clearTruncation();
261 void adjustRectForColumns(LayoutRect&) const;
262 virtual void adjustForColumns(LayoutSize&, const LayoutPoint&) const;
263 void adjustForColumnRect(LayoutSize& offset, const LayoutPoint& locationInContainer) const;
265 void addContinuationWithOutline(RenderInline*);
266 bool paintsContinuationOutline(RenderInline*);
268 virtual RenderBoxModelObject* virtualContinuation() const { return continuation(); }
269 bool isAnonymousBlockContinuation() const { return continuation() && isAnonymousBlock(); }
270 RenderInline* inlineElementContinuation() const;
271 RenderBlock* blockElementContinuation() const;
273 using RenderBoxModelObject::continuation;
274 using RenderBoxModelObject::setContinuation;
276 static RenderBlock* createAnonymousWithParentRendererAndDisplay(const RenderObject*, EDisplay = BLOCK);
277 static RenderBlock* createAnonymousColumnsWithParentRenderer(const RenderObject*);
278 static RenderBlock* createAnonymousColumnSpanWithParentRenderer(const RenderObject*);
279 RenderBlock* createAnonymousBlock(EDisplay display = BLOCK) const { return createAnonymousWithParentRendererAndDisplay(this, display); }
280 RenderBlock* createAnonymousColumnsBlock() const { return createAnonymousColumnsWithParentRenderer(this); }
281 RenderBlock* createAnonymousColumnSpanBlock() const { return createAnonymousColumnSpanWithParentRenderer(this); }
282 static void collapseAnonymousBoxChild(RenderBlock* parent, RenderObject* child);
284 virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE;
286 static bool shouldSkipCreatingRunsForObject(RenderObject* obj)
288 return obj->isFloating() || (obj->isOutOfFlowPositioned() && !obj->style()->isOriginalDisplayInlineType() && !obj->container()->isRenderInline());
291 static void appendRunsForObject(BidiRunList<BidiRun>&, int start, int end, RenderObject*, InlineBidiResolver&);
293 static TextRun constructTextRun(RenderObject* context, const Font& font, const String& string, RenderStyle* style,
294 TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion, TextRunFlags = DefaultTextRunFlags);
296 static TextRun constructTextRun(RenderObject* context, const Font& font, const RenderText* text, RenderStyle* style,
297 TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
299 static TextRun constructTextRun(RenderObject* context, const Font& font, const RenderText* text, unsigned offset, unsigned length, RenderStyle* style,
300 TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
302 static TextRun constructTextRun(RenderObject* context, const Font& font, const RenderText* text, unsigned offset, RenderStyle* style,
303 TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
305 #if ENABLE(8BIT_TEXTRUN)
306 static TextRun constructTextRun(RenderObject* context, const Font& font, const LChar* characters, int length, RenderStyle* style,
307 TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
310 static TextRun constructTextRun(RenderObject* context, const Font& font, const UChar* characters, int length, RenderStyle* style,
311 TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
313 ColumnInfo* columnInfo() const;
314 int columnGap() const;
316 void updateColumnInfoFromStyle(RenderStyle*);
318 // These two functions take the ColumnInfo* to avoid repeated lookups of the info in the global HashMap.
319 unsigned columnCount(ColumnInfo*) const;
320 LayoutRect columnRectAt(ColumnInfo*, unsigned) const;
322 LayoutUnit paginationStrut() const { return m_rareData ? m_rareData->m_paginationStrut : LayoutUnit(); }
323 void setPaginationStrut(LayoutUnit);
325 bool shouldBreakAtLineToAvoidWidow() const { return m_rareData && m_rareData->m_shouldBreakAtLineToAvoidWidow; }
326 void clearShouldBreakAtLineToAvoidWidow() const;
327 RootInlineBox* lineBreakToAvoidWidow() const { return m_rareData ? m_rareData->m_lineBreakToAvoidWidow : 0; }
328 void setBreakAtLineToAvoidWidow(RootInlineBox*);
330 // The page logical offset is the object's offset from the top of the page in the page progression
331 // direction (so an x-offset in vertical text and a y-offset for horizontal text).
332 LayoutUnit pageLogicalOffset() const { return m_rareData ? m_rareData->m_pageLogicalOffset : LayoutUnit(); }
333 void setPageLogicalOffset(LayoutUnit);
335 RootInlineBox* lineGridBox() const { return m_rareData ? m_rareData->m_lineGridBox : 0; }
336 void setLineGridBox(RootInlineBox* box)
339 m_rareData = adoptPtr(new RenderBlockRareData(this));
340 if (m_rareData->m_lineGridBox)
341 m_rareData->m_lineGridBox->destroy(renderArena());
342 m_rareData->m_lineGridBox = box;
344 void layoutLineGridBox();
346 // Accessors for logical width/height and margins in the containing block's block-flow direction.
347 enum ApplyLayoutDeltaMode { ApplyLayoutDelta, DoNotApplyLayoutDelta };
348 LayoutUnit logicalWidthForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->width() : child->height(); }
349 LayoutUnit logicalHeightForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->height() : child->width(); }
350 LayoutUnit logicalTopForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->y() : child->x(); }
351 void setLogicalLeftForChild(RenderBox* child, LayoutUnit logicalLeft, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
352 void setLogicalTopForChild(RenderBox* child, LayoutUnit logicalTop, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
353 LayoutUnit marginBeforeForChild(const RenderBoxModelObject* child) const { return child->marginBefore(style()); }
354 LayoutUnit marginAfterForChild(const RenderBoxModelObject* child) const { return child->marginAfter(style()); }
355 LayoutUnit marginStartForChild(const RenderBoxModelObject* child) const { return child->marginStart(style()); }
356 LayoutUnit marginEndForChild(const RenderBoxModelObject* child) const { return child->marginEnd(style()); }
357 void setMarginStartForChild(RenderBox* child, LayoutUnit value) const { child->setMarginStart(value, style()); }
358 void setMarginEndForChild(RenderBox* child, LayoutUnit value) const { child->setMarginEnd(value, style()); }
359 void setMarginBeforeForChild(RenderBox* child, LayoutUnit value) const { child->setMarginBefore(value, style()); }
360 void setMarginAfterForChild(RenderBox* child, LayoutUnit value) const { child->setMarginAfter(value, style()); }
361 LayoutUnit collapsedMarginBeforeForChild(const RenderBox* child) const;
362 LayoutUnit collapsedMarginAfterForChild(const RenderBox* child) const;
364 void updateLogicalWidthForAlignment(const ETextAlign&, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, int expansionOpportunityCount);
366 virtual void updateFirstLetter();
370 MarginValues(LayoutUnit beforePos, LayoutUnit beforeNeg, LayoutUnit afterPos, LayoutUnit afterNeg)
371 : m_positiveMarginBefore(beforePos)
372 , m_negativeMarginBefore(beforeNeg)
373 , m_positiveMarginAfter(afterPos)
374 , m_negativeMarginAfter(afterNeg)
377 LayoutUnit positiveMarginBefore() const { return m_positiveMarginBefore; }
378 LayoutUnit negativeMarginBefore() const { return m_negativeMarginBefore; }
379 LayoutUnit positiveMarginAfter() const { return m_positiveMarginAfter; }
380 LayoutUnit negativeMarginAfter() const { return m_negativeMarginAfter; }
382 void setPositiveMarginBefore(LayoutUnit pos) { m_positiveMarginBefore = pos; }
383 void setNegativeMarginBefore(LayoutUnit neg) { m_negativeMarginBefore = neg; }
384 void setPositiveMarginAfter(LayoutUnit pos) { m_positiveMarginAfter = pos; }
385 void setNegativeMarginAfter(LayoutUnit neg) { m_negativeMarginAfter = neg; }
388 LayoutUnit m_positiveMarginBefore;
389 LayoutUnit m_negativeMarginBefore;
390 LayoutUnit m_positiveMarginAfter;
391 LayoutUnit m_negativeMarginAfter;
393 MarginValues marginValuesForChild(RenderBox* child) const;
395 virtual void scrollbarsChanged(bool /*horizontalScrollbarChanged*/, bool /*verticalScrollbarChanged*/) { };
397 LayoutUnit logicalLeftOffsetForContent(RenderRegion*) const;
398 LayoutUnit logicalRightOffsetForContent(RenderRegion*) const;
399 LayoutUnit availableLogicalWidthForContent(RenderRegion* region) const
401 return max<LayoutUnit>(0, logicalRightOffsetForContent(region) - logicalLeftOffsetForContent(region)); }
402 LayoutUnit startOffsetForContent(RenderRegion* region) const
404 return style()->isLeftToRightDirection() ? logicalLeftOffsetForContent(region) : logicalWidth() - logicalRightOffsetForContent(region);
406 LayoutUnit endOffsetForContent(RenderRegion* region) const
408 return !style()->isLeftToRightDirection() ? logicalLeftOffsetForContent(region) : logicalWidth() - logicalRightOffsetForContent(region);
410 LayoutUnit logicalLeftOffsetForContent(LayoutUnit blockOffset) const
412 return logicalLeftOffsetForContent(regionAtBlockOffset(blockOffset));
414 LayoutUnit logicalRightOffsetForContent(LayoutUnit blockOffset) const
416 return logicalRightOffsetForContent(regionAtBlockOffset(blockOffset));
418 LayoutUnit availableLogicalWidthForContent(LayoutUnit blockOffset) const
420 return availableLogicalWidthForContent(regionAtBlockOffset(blockOffset));
422 LayoutUnit startOffsetForContent(LayoutUnit blockOffset) const
424 return startOffsetForContent(regionAtBlockOffset(blockOffset));
426 LayoutUnit endOffsetForContent(LayoutUnit blockOffset) const
428 return endOffsetForContent(regionAtBlockOffset(blockOffset));
430 LayoutUnit logicalLeftOffsetForContent() const { return isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop(); }
431 LayoutUnit logicalRightOffsetForContent() const { return logicalLeftOffsetForContent() + availableLogicalWidth(); }
432 LayoutUnit startOffsetForContent() const { return style()->isLeftToRightDirection() ? logicalLeftOffsetForContent() : logicalWidth() - logicalRightOffsetForContent(); }
433 LayoutUnit endOffsetForContent() const { return !style()->isLeftToRightDirection() ? logicalLeftOffsetForContent() : logicalWidth() - logicalRightOffsetForContent(); }
435 void setStaticInlinePositionForChild(RenderBox*, LayoutUnit blockOffset, LayoutUnit inlinePosition);
436 void updateStaticInlinePositionForChild(RenderBox*, LayoutUnit logicalTop);
438 LayoutUnit computeStartPositionDeltaForChildAvoidingFloats(const RenderBox* child, LayoutUnit childMarginStart, RenderRegion* = 0);
440 void placeRunInIfNeeded(RenderObject* newChild);
441 bool runInIsPlacedIntoSiblingBlock(RenderObject* runIn);
444 void checkPositionedObjectsNeedLayout();
445 void showLineTreeAndMark(const InlineBox* = 0, const char* = 0, const InlineBox* = 0, const char* = 0, const RenderObject* = 0) const;
448 #if ENABLE(CSS_SHAPES)
449 ExclusionShapeInsideInfo* ensureExclusionShapeInsideInfo()
451 if (!m_rareData || !m_rareData->m_shapeInsideInfo)
452 setExclusionShapeInsideInfo(ExclusionShapeInsideInfo::createInfo(this));
453 return m_rareData->m_shapeInsideInfo.get();
456 ExclusionShapeInsideInfo* exclusionShapeInsideInfo() const
458 if (!m_rareData || !m_rareData->m_shapeInsideInfo)
460 return ExclusionShapeInsideInfo::isEnabledFor(this) ? m_rareData->m_shapeInsideInfo.get() : 0;
462 void setExclusionShapeInsideInfo(PassOwnPtr<ExclusionShapeInsideInfo> value)
465 m_rareData = adoptPtr(new RenderBlockRareData(this));
466 m_rareData->m_shapeInsideInfo = value;
468 void markShapeInsideDescendantsForLayout();
469 ExclusionShapeInsideInfo* layoutExclusionShapeInsideInfo() const;
470 bool allowsExclusionShapeInsideInfoSharing() const { return !isInline() && !isFloating(); }
474 virtual void willBeDestroyed();
476 LayoutUnit maxPositiveMarginBefore() const { return m_rareData ? m_rareData->m_margins.positiveMarginBefore() : RenderBlockRareData::positiveMarginBeforeDefault(this); }
477 LayoutUnit maxNegativeMarginBefore() const { return m_rareData ? m_rareData->m_margins.negativeMarginBefore() : RenderBlockRareData::negativeMarginBeforeDefault(this); }
478 LayoutUnit maxPositiveMarginAfter() const { return m_rareData ? m_rareData->m_margins.positiveMarginAfter() : RenderBlockRareData::positiveMarginAfterDefault(this); }
479 LayoutUnit maxNegativeMarginAfter() const { return m_rareData ? m_rareData->m_margins.negativeMarginAfter() : RenderBlockRareData::negativeMarginAfterDefault(this); }
481 void setMaxMarginBeforeValues(LayoutUnit pos, LayoutUnit neg);
482 void setMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg);
484 void setMustDiscardMarginBefore(bool = true);
485 void setMustDiscardMarginAfter(bool = true);
487 bool mustDiscardMarginBefore() const;
488 bool mustDiscardMarginAfter() const;
490 bool mustDiscardMarginBeforeForChild(const RenderBox*) const;
491 bool mustDiscardMarginAfterForChild(const RenderBox*) const;
493 bool mustSeparateMarginBeforeForChild(const RenderBox*) const;
494 bool mustSeparateMarginAfterForChild(const RenderBox*) const;
496 void initMaxMarginValues()
499 m_rareData->m_margins = MarginValues(RenderBlockRareData::positiveMarginBeforeDefault(this) , RenderBlockRareData::negativeMarginBeforeDefault(this),
500 RenderBlockRareData::positiveMarginAfterDefault(this), RenderBlockRareData::negativeMarginAfterDefault(this));
501 m_rareData->m_paginationStrut = 0;
503 m_rareData->m_discardMarginBefore = false;
504 m_rareData->m_discardMarginAfter = false;
508 virtual void layout();
510 void layoutPositionedObjects(bool relayoutChildren, bool fixedPositionObjectsOnly = false);
511 void markFixedPositionObjectForLayoutIfNeeded(RenderObject* child);
513 virtual void paint(PaintInfo&, const LayoutPoint&);
514 virtual void paintObject(PaintInfo&, const LayoutPoint&);
515 virtual void paintChildren(PaintInfo& forSelf, const LayoutPoint&, PaintInfo& forChild, bool usePrintRect);
516 bool paintChild(RenderBox*, PaintInfo& forSelf, const LayoutPoint&, PaintInfo& forChild, bool usePrintRect);
518 LayoutUnit logicalRightOffsetForLine(LayoutUnit position, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* logicalHeightRemaining = 0, LayoutUnit logicalHeight = 0, ShapeOutsideFloatOffsetMode = ShapeOutsideFloatShapeOffset) const;
519 LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* logicalHeightRemaining = 0, LayoutUnit logicalHeight = 0, ShapeOutsideFloatOffsetMode = ShapeOutsideFloatShapeOffset) const;
521 virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const;
522 virtual void adjustInlineDirectionLineBounds(int /* expansionOpportunityCount */, float& /* logicalLeft */, float& /* logicalWidth */) const { }
524 virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
526 virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
527 virtual void computePreferredLogicalWidths() OVERRIDE;
529 virtual int firstLineBoxBaseline() const;
530 virtual int inlineBlockBaseline(LineDirectionMode) const OVERRIDE;
531 int lastLineBoxBaseline(LineDirectionMode) const;
533 virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&);
535 // Delay update scrollbar until finishDelayRepaint() will be
536 // called. This function is used when a flexbox is laying out its
537 // descendant. If multiple calls are made to startDelayRepaint(),
538 // finishDelayRepaint() will do nothing until finishDelayRepaint()
539 // is called the same number of times.
540 static void startDelayUpdateScrollInfo();
541 static void finishDelayUpdateScrollInfo();
543 void updateScrollInfoAfterLayout();
545 virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
546 virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
548 virtual bool hasLineIfEmpty() const;
550 bool simplifiedLayout();
551 virtual void simplifiedNormalFlowLayout();
553 void setDesiredColumnCountAndWidth(int, LayoutUnit);
556 void computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats = false);
557 void clearLayoutOverflow();
559 virtual void addOverflowFromChildren();
560 void addOverflowFromFloats();
561 void addOverflowFromPositionedObjects();
562 void addOverflowFromBlockChildren();
563 void addOverflowFromInlineChildren();
564 void addVisualOverflowFromTheme();
566 virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE;
569 // Only used by RenderSVGText, which explicitely overrides RenderBlock::layoutBlock(), do NOT use for anything else.
570 void forceLayoutInlineChildren()
572 LayoutUnit repaintLogicalTop = 0;
573 LayoutUnit repaintLogicalBottom = 0;
575 layoutInlineChildren(true, repaintLogicalTop, repaintLogicalBottom);
579 bool updateRegionsAndExclusionsBeforeChildLayout(RenderFlowThread*);
580 void updateRegionsAndExclusionsAfterChildLayout(RenderFlowThread*, bool heightChanged = false);
581 void computeRegionRangeForBlock(RenderFlowThread*);
583 void updateBlockChildDirtyBitsBeforeLayout(bool relayoutChildren, RenderBox*);
585 virtual void checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight);
588 #if ENABLE(CSS_SHAPES)
589 void computeExclusionShapeSize();
590 void updateExclusionShapeInsideInfoAfterStyleChange(const ExclusionShapeValue*, const ExclusionShapeValue* oldExclusionShape);
592 virtual RenderObjectChildList* virtualChildren() { return children(); }
593 virtual const RenderObjectChildList* virtualChildren() const { return children(); }
595 virtual const char* renderName() const;
597 virtual bool isRenderBlock() const { return true; }
598 virtual bool isBlockFlow() const { return (!isInline() || isReplaced()) && !isTable(); }
599 virtual bool isInlineBlockOrInlineTable() const { return isInline() && isReplaced(); }
601 void makeChildrenNonInline(RenderObject* insertionPoint = 0);
602 virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
604 void moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert);
606 virtual void dirtyLinesFromChangedChild(RenderObject* child) { m_lineBoxes.dirtyLinesFromChangedChild(this, child); }
608 void addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild);
609 void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild);
610 void addChildToAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild);
612 virtual void addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild = 0);
614 virtual bool isSelfCollapsingBlock() const;
616 virtual LayoutUnit collapsedMarginBefore() const { return maxPositiveMarginBefore() - maxNegativeMarginBefore(); }
617 virtual LayoutUnit collapsedMarginAfter() const { return maxPositiveMarginAfter() - maxNegativeMarginAfter(); }
619 virtual void repaintOverhangingFloats(bool paintAllDescendants) OVERRIDE;
621 void layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloatLogicalBottom);
622 void layoutInlineChildren(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom);
623 BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>&, BidiContext*);
625 void insertIntoTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&);
626 static void removeFromTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&);
628 virtual RootInlineBox* createRootInlineBox(); // Subclassed by SVG and Ruby.
630 // Called to lay out the legend for a fieldset or the ruby text of a ruby run.
631 virtual RenderObject* layoutSpecialExcludedChild(bool /*relayoutChildren*/) { return 0; }
633 void createFirstLetterRenderer(RenderObject* firstLetterBlock, RenderObject* currentChild);
634 void updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderObject* firstLetterContainer);
636 Node* nodeForHitTest() const;
638 struct FloatWithRect {
639 FloatWithRect(RenderBox* f)
641 , rect(LayoutRect(f->x() - f->marginLeft(), f->y() - f->marginTop(), f->width() + f->marginWidth(), f->height() + f->marginHeight()))
642 , everHadLayout(f->everHadLayout())
651 struct FloatingObject {
652 WTF_MAKE_NONCOPYABLE(FloatingObject); WTF_MAKE_FAST_ALLOCATED;
654 // Note that Type uses bits so you can use FloatLeftRight as a mask to query for both left and right.
655 enum Type { FloatLeft = 1, FloatRight = 2, FloatLeftRight = 3 };
657 FloatingObject(EFloat type)
659 , m_originatingLine(0)
660 , m_paginationStrut(0)
661 , m_shouldPaint(true)
662 , m_isDescendant(false)
665 , m_isInPlacedTree(false)
668 ASSERT(type != NoFloat);
669 if (type == LeftFloat)
671 else if (type == RightFloat)
675 FloatingObject(Type type, const LayoutRect& frameRect)
677 , m_originatingLine(0)
678 , m_frameRect(frameRect)
679 , m_paginationStrut(0)
681 , m_shouldPaint(true)
682 , m_isDescendant(false)
685 , m_isInPlacedTree(false)
690 FloatingObject* clone() const
692 FloatingObject* cloneObject = new FloatingObject(type(), m_frameRect);
693 cloneObject->m_renderer = m_renderer;
694 cloneObject->m_originatingLine = m_originatingLine;
695 cloneObject->m_paginationStrut = m_paginationStrut;
696 cloneObject->m_shouldPaint = m_shouldPaint;
697 cloneObject->m_isDescendant = m_isDescendant;
698 cloneObject->m_isPlaced = m_isPlaced;
702 Type type() const { return static_cast<Type>(m_type); }
703 RenderBox* renderer() const { return m_renderer; }
705 bool isPlaced() const { return m_isPlaced; }
706 void setIsPlaced(bool placed = true) { m_isPlaced = placed; }
708 inline LayoutUnit x() const { ASSERT(isPlaced()); return m_frameRect.x(); }
709 inline LayoutUnit maxX() const { ASSERT(isPlaced()); return m_frameRect.maxX(); }
710 inline LayoutUnit y() const { ASSERT(isPlaced()); return m_frameRect.y(); }
711 inline LayoutUnit maxY() const { ASSERT(isPlaced()); return m_frameRect.maxY(); }
712 inline LayoutUnit width() const { return m_frameRect.width(); }
713 inline LayoutUnit height() const { return m_frameRect.height(); }
715 void setX(LayoutUnit x) { ASSERT(!isInPlacedTree()); m_frameRect.setX(x); }
716 void setY(LayoutUnit y) { ASSERT(!isInPlacedTree()); m_frameRect.setY(y); }
717 void setWidth(LayoutUnit width) { ASSERT(!isInPlacedTree()); m_frameRect.setWidth(width); }
718 void setHeight(LayoutUnit height) { ASSERT(!isInPlacedTree()); m_frameRect.setHeight(height); }
720 const LayoutRect& frameRect() const { ASSERT(isPlaced()); return m_frameRect; }
721 void setFrameRect(const LayoutRect& frameRect) { ASSERT(!isInPlacedTree()); m_frameRect = frameRect; }
724 bool isInPlacedTree() const { return m_isInPlacedTree; }
725 void setIsInPlacedTree(bool value) { m_isInPlacedTree = value; }
728 bool shouldPaint() const { return m_shouldPaint; }
729 void setShouldPaint(bool shouldPaint) { m_shouldPaint = shouldPaint; }
730 bool isDescendant() const { return m_isDescendant; }
731 void setIsDescendant(bool isDescendant) { m_isDescendant = isDescendant; }
733 RenderBox* m_renderer;
734 RootInlineBox* m_originatingLine;
735 LayoutRect m_frameRect;
736 int m_paginationStrut;
739 unsigned m_type : 2; // Type (left or right aligned)
740 unsigned m_shouldPaint : 1;
741 unsigned m_isDescendant : 1;
742 unsigned m_isPlaced : 1;
744 unsigned m_isInPlacedTree : 1;
748 LayoutPoint flipFloatForWritingModeForChild(const FloatingObject*, const LayoutPoint&) const;
750 LayoutUnit logicalTopForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->y() : child->x(); }
751 LayoutUnit logicalBottomForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->maxY() : child->maxX(); }
752 LayoutUnit logicalLeftForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->x() : child->y(); }
753 LayoutUnit logicalRightForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->maxX() : child->maxY(); }
754 LayoutUnit logicalWidthForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->width() : child->height(); }
756 int pixelSnappedLogicalTopForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedY() : child->frameRect().pixelSnappedX(); }
757 int pixelSnappedLogicalBottomForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedMaxY() : child->frameRect().pixelSnappedMaxX(); }
758 int pixelSnappedLogicalLeftForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedX() : child->frameRect().pixelSnappedY(); }
759 int pixelSnappedLogicalRightForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedMaxX() : child->frameRect().pixelSnappedMaxY(); }
761 void setLogicalTopForFloat(FloatingObject* child, LayoutUnit logicalTop)
763 if (isHorizontalWritingMode())
764 child->setY(logicalTop);
766 child->setX(logicalTop);
768 void setLogicalLeftForFloat(FloatingObject* child, LayoutUnit logicalLeft)
770 if (isHorizontalWritingMode())
771 child->setX(logicalLeft);
773 child->setY(logicalLeft);
775 void setLogicalHeightForFloat(FloatingObject* child, LayoutUnit logicalHeight)
777 if (isHorizontalWritingMode())
778 child->setHeight(logicalHeight);
780 child->setWidth(logicalHeight);
782 void setLogicalWidthForFloat(FloatingObject* child, LayoutUnit logicalWidth)
784 if (isHorizontalWritingMode())
785 child->setWidth(logicalWidth);
787 child->setHeight(logicalWidth);
790 LayoutUnit xPositionForFloatIncludingMargin(const FloatingObject* child) const
792 #if ENABLE(CSS_SHAPES)
793 ExclusionShapeOutsideInfo *shapeOutside = child->renderer()->exclusionShapeOutsideInfo();
798 if (isHorizontalWritingMode())
799 return child->x() + child->renderer()->marginLeft();
801 return child->x() + marginBeforeForChild(child->renderer());
804 LayoutUnit yPositionForFloatIncludingMargin(const FloatingObject* child) const
806 #if ENABLE(CSS_SHAPES)
807 ExclusionShapeOutsideInfo *shapeOutside = child->renderer()->exclusionShapeOutsideInfo();
812 if (isHorizontalWritingMode())
813 return child->y() + marginBeforeForChild(child->renderer());
815 return child->y() + child->renderer()->marginTop();
818 LayoutPoint computeLogicalLocationForFloat(const FloatingObject*, LayoutUnit logicalTopOffset) const;
820 // The following functions' implementations are in RenderBlockLineLayout.cpp.
821 struct RenderTextInfo {
822 // Destruction of m_layout requires TextLayout to be a complete type, so the constructor and destructor are made non-inline to avoid compilation errors.
827 OwnPtr<TextLayout> m_layout;
828 LazyLineBreakIterator m_lineBreakIterator;
834 LineBreaker(RenderBlock* block)
840 InlineIterator nextLineBreak(InlineBidiResolver&, LineInfo&, RenderTextInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements&);
842 bool lineWasHyphenated() { return m_hyphenated; }
843 const Vector<RenderBox*>& positionedObjects() { return m_positionedObjects; }
844 EClear clear() { return m_clear; }
848 InlineIterator nextSegmentBreak(InlineBidiResolver&, LineInfo&, RenderTextInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements&);
849 void skipTrailingWhitespace(InlineIterator&, const LineInfo&);
850 void skipLeadingWhitespace(InlineBidiResolver&, LineInfo&, FloatingObject* lastFloatFromPreviousLine, LineWidth&);
852 RenderBlock* m_block;
855 Vector<RenderBox*> m_positionedObjects;
858 void checkFloatsInCleanLine(RootInlineBox*, Vector<FloatWithRect>&, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat);
859 RootInlineBox* determineStartPosition(LineLayoutState&, InlineBidiResolver&);
860 void determineEndPosition(LineLayoutState&, RootInlineBox* startBox, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus);
861 bool matchedEndLine(LineLayoutState&, const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus);
862 bool checkPaginationAndFloatsAtEndLine(LineLayoutState&);
864 RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
865 InlineFlowBox* createLineBoxes(RenderObject*, const LineInfo&, InlineBox* childBox, bool startsNewSegment);
867 void setMarginsForRubyRun(BidiRun*, RenderRubyRun*, RenderObject*, const LineInfo&);
869 BidiRun* computeInlineDirectionPositionsForSegment(RootInlineBox*, const LineInfo&, ETextAlign, float& logicalLeft,
870 float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache&, WordMeasurements&);
871 void computeInlineDirectionPositionsForLine(RootInlineBox*, const LineInfo&, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&, WordMeasurements&);
872 void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&);
873 void deleteEllipsisLineBoxes();
874 void checkLinesForTextOverflow();
876 // Positions new floats and also adjust all floats encountered on the line if any of them
877 // have to move to the next page/column.
878 bool positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo&, LineWidth&);
879 void appendFloatingObjectToLastLine(FloatingObject*);
881 // End of functions defined in RenderBlockLineLayout.cpp.
883 void paintFloats(PaintInfo&, const LayoutPoint&, bool preservePhase = false);
884 void paintContents(PaintInfo&, const LayoutPoint&);
885 void paintColumnContents(PaintInfo&, const LayoutPoint&, bool paintFloats = false);
886 void paintColumnRules(PaintInfo&, const LayoutPoint&);
887 void paintSelection(PaintInfo&, const LayoutPoint&);
888 void paintCaret(PaintInfo&, const LayoutPoint&, CaretType);
890 FloatingObject* insertFloatingObject(RenderBox*);
891 void removeFloatingObject(RenderBox*);
892 void removeFloatingObjectsBelow(FloatingObject*, int logicalOffset);
894 // Called from lineWidth, to position the floats added in the last line.
895 // Returns true if and only if it has positioned any floats.
896 bool positionNewFloats();
900 LayoutUnit getClearDelta(RenderBox* child, LayoutUnit yPos);
902 virtual bool avoidsFloats() const;
904 bool hasOverhangingFloats() { return parent() && !hasColumns() && containsFloats() && lowestFloatLogicalBottom() > logicalHeight(); }
905 bool hasOverhangingFloat(RenderBox*);
906 void addIntrudingFloats(RenderBlock* prev, LayoutUnit xoffset, LayoutUnit yoffset);
907 LayoutUnit addOverhangingFloats(RenderBlock* child, bool makeChildPaintOtherFloats);
909 LayoutUnit lowestFloatLogicalBottom(FloatingObject::Type = FloatingObject::FloatLeftRight) const;
910 LayoutUnit nextFloatLogicalBottomBelow(LayoutUnit) const;
912 virtual bool hitTestColumns(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
913 virtual bool hitTestContents(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
914 bool hitTestFloats(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset);
916 virtual bool isPointInOverflowControl(HitTestResult&, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset);
918 // FIXME: Make this method const so we can remove the const_cast in computeIntrinsicLogicalWidths.
919 void computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth);
920 void computeBlockPreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const;
922 // Obtains the nearest enclosing block (including this block) that contributes a first-line style to our inline
924 virtual RenderBlock* firstLineBlock() const;
926 virtual LayoutRect rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const OVERRIDE;
927 virtual RenderStyle* outlineStyleForRepaint() const;
929 virtual RenderObject* hoverAncestor() const;
930 virtual void updateDragState(bool dragOn);
931 virtual void childBecameNonInline(RenderObject* child);
933 virtual LayoutRect selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool /*clipToVisibleContent*/) OVERRIDE
935 return selectionGapRectsForRepaint(repaintContainer);
937 virtual bool shouldPaintSelectionGaps() const;
938 bool isSelectionRoot() const;
939 GapRects selectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
940 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches&, const PaintInfo* = 0);
941 GapRects inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
942 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
943 GapRects blockSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
944 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches&, const PaintInfo*);
945 LayoutRect blockSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
946 LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const LogicalSelectionOffsetCaches&, const PaintInfo*);
947 LayoutUnit logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches&);
948 LayoutUnit logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position, const LogicalSelectionOffsetCaches&);
950 friend class LogicalSelectionOffsetCaches;
952 virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const;
953 virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
955 LayoutUnit desiredColumnWidth() const;
956 unsigned desiredColumnCount() const;
958 void paintContinuationOutlines(PaintInfo&, const LayoutPoint&);
960 virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0);
962 void adjustPointToColumnContents(LayoutPoint&) const;
964 void fitBorderToLinesIfNeeded(); // Shrink the box in which the border paints if border-fit is set.
965 void adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const; // Helper function for borderFitAdjust
967 void markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit logicalBottom, RootInlineBox* highest = 0);
969 void newLine(EClear);
971 Position positionForBox(InlineBox*, bool start = true) const;
972 VisiblePosition positionForPointWithInlineChildren(const LayoutPoint&);
974 virtual void calcColumnWidth();
975 void makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, RenderBlock* newBlockBox, RenderObject* newChild);
977 bool expandsToEncloseOverhangingFloats() const;
979 void splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock,
980 RenderObject* beforeChild, RenderBoxModelObject* oldCont);
981 void splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
982 RenderObject* newChild, RenderBoxModelObject* oldCont);
983 RenderBlock* clone() const;
984 RenderBlock* continuationBefore(RenderObject* beforeChild);
985 RenderBlock* containingColumnsBlock(bool allowAnonymousColumnBlock = true);
986 RenderBlock* columnsBlockForSpanningElement(RenderObject* newChild);
989 // Collapsing flags for whether we can collapse our margins with our children's margins.
990 bool m_canCollapseWithChildren : 1;
991 bool m_canCollapseMarginBeforeWithChildren : 1;
992 bool m_canCollapseMarginAfterWithChildren : 1;
994 // Whether or not we are a quirky container, i.e., do we collapse away top and bottom
995 // margins in our container. Table cells and the body are the common examples. We
996 // also have a custom style property for Safari RSS to deal with TypePad blog articles.
997 bool m_quirkContainer : 1;
999 // This flag tracks whether we are still looking at child margins that can all collapse together at the beginning of a block.
1000 // They may or may not collapse with the top margin of the block (|m_canCollapseTopWithChildren| tells us that), but they will
1001 // always be collapsing with one another. This variable can remain set to true through multiple iterations
1002 // as long as we keep encountering self-collapsing blocks.
1003 bool m_atBeforeSideOfBlock : 1;
1005 // This flag is set when we know we're examining bottom margins and we know we're at the bottom of the block.
1006 bool m_atAfterSideOfBlock : 1;
1008 // These variables are used to detect quirky margins that we need to collapse away (in table cells
1009 // and in the body element).
1010 bool m_hasMarginBeforeQuirk : 1;
1011 bool m_hasMarginAfterQuirk : 1;
1012 bool m_determinedMarginBeforeQuirk : 1;
1014 bool m_discardMargin : 1;
1016 // These flags track the previous maximal positive and negative margins.
1017 LayoutUnit m_positiveMargin;
1018 LayoutUnit m_negativeMargin;
1021 MarginInfo(RenderBlock*, LayoutUnit beforeBorderPadding, LayoutUnit afterBorderPadding);
1023 void setAtBeforeSideOfBlock(bool b) { m_atBeforeSideOfBlock = b; }
1024 void setAtAfterSideOfBlock(bool b) { m_atAfterSideOfBlock = b; }
1027 m_positiveMargin = 0;
1028 m_negativeMargin = 0;
1030 void setHasMarginBeforeQuirk(bool b) { m_hasMarginBeforeQuirk = b; }
1031 void setHasMarginAfterQuirk(bool b) { m_hasMarginAfterQuirk = b; }
1032 void setDeterminedMarginBeforeQuirk(bool b) { m_determinedMarginBeforeQuirk = b; }
1033 void setPositiveMargin(LayoutUnit p) { ASSERT(!m_discardMargin); m_positiveMargin = p; }
1034 void setNegativeMargin(LayoutUnit n) { ASSERT(!m_discardMargin); m_negativeMargin = n; }
1035 void setPositiveMarginIfLarger(LayoutUnit p)
1037 ASSERT(!m_discardMargin);
1038 if (p > m_positiveMargin)
1039 m_positiveMargin = p;
1041 void setNegativeMarginIfLarger(LayoutUnit n)
1043 ASSERT(!m_discardMargin);
1044 if (n > m_negativeMargin)
1045 m_negativeMargin = n;
1048 void setMargin(LayoutUnit p, LayoutUnit n) { ASSERT(!m_discardMargin); m_positiveMargin = p; m_negativeMargin = n; }
1049 void setCanCollapseMarginAfterWithChildren(bool collapse) { m_canCollapseMarginAfterWithChildren = collapse; }
1050 void setDiscardMargin(bool value) { m_discardMargin = value; }
1052 bool atBeforeSideOfBlock() const { return m_atBeforeSideOfBlock; }
1053 bool canCollapseWithMarginBefore() const { return m_atBeforeSideOfBlock && m_canCollapseMarginBeforeWithChildren; }
1054 bool canCollapseWithMarginAfter() const { return m_atAfterSideOfBlock && m_canCollapseMarginAfterWithChildren; }
1055 bool canCollapseMarginBeforeWithChildren() const { return m_canCollapseMarginBeforeWithChildren; }
1056 bool canCollapseMarginAfterWithChildren() const { return m_canCollapseMarginAfterWithChildren; }
1057 bool quirkContainer() const { return m_quirkContainer; }
1058 bool determinedMarginBeforeQuirk() const { return m_determinedMarginBeforeQuirk; }
1059 bool hasMarginBeforeQuirk() const { return m_hasMarginBeforeQuirk; }
1060 bool hasMarginAfterQuirk() const { return m_hasMarginAfterQuirk; }
1061 LayoutUnit positiveMargin() const { return m_positiveMargin; }
1062 LayoutUnit negativeMargin() const { return m_negativeMargin; }
1063 bool discardMargin() const { return m_discardMargin; }
1064 LayoutUnit margin() const { return m_positiveMargin - m_negativeMargin; }
1067 void layoutBlockChild(RenderBox* child, MarginInfo&, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom);
1068 void adjustPositionedBlock(RenderBox* child, const MarginInfo&);
1069 void adjustFloatingBlock(const MarginInfo&);
1071 RenderBoxModelObject* createReplacementRunIn(RenderBoxModelObject* runIn);
1072 void moveRunInUnderSiblingBlockIfNeeded(RenderObject* runIn);
1073 void moveRunInToOriginalPosition(RenderObject* runIn);
1075 LayoutUnit collapseMargins(RenderBox* child, MarginInfo&);
1076 LayoutUnit clearFloatsIfNeeded(RenderBox* child, MarginInfo&, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos);
1077 LayoutUnit estimateLogicalTopPosition(RenderBox* child, const MarginInfo&, LayoutUnit& estimateWithoutPagination);
1078 void marginBeforeEstimateForChild(RenderBox*, LayoutUnit&, LayoutUnit&, bool&) const;
1079 void handleAfterSideOfBlock(LayoutUnit top, LayoutUnit bottom, MarginInfo&);
1080 void setCollapsedBottomMargin(const MarginInfo&);
1081 // End helper functions and structs used by layoutBlockChildren.
1083 // Helper function for layoutInlineChildren()
1084 RootInlineBox* createLineBoxesFromBidiRuns(BidiRunList<BidiRun>&, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun, WordMeasurements&);
1085 void layoutRunsAndFloats(LineLayoutState&, bool hasInlineChild);
1086 void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines);
1087 #if ENABLE(CSS_SHAPES)
1088 void updateShapeAndSegmentsForCurrentLine(ExclusionShapeInsideInfo*, LayoutUnit&, LineLayoutState&, bool&);
1089 bool adjustLogicalLineTopAndLogicalHeightIfNeeded(ExclusionShapeInsideInfo*, LayoutUnit, LineLayoutState&, InlineBidiResolver&, FloatingObject*, InlineIterator&, WordMeasurements&);
1091 const InlineIterator& restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight, FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver&, const InlineIterator&);
1092 void linkToEndLineIfNeeded(LineLayoutState&);
1093 static void repaintDirtyFloats(Vector<FloatWithRect>& floats);
1096 void determineLogicalLeftPositionForChild(RenderBox* child, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
1098 // Pagination routines.
1099 virtual bool relayoutForPagination(bool hasSpecifiedPageLogicalHeight, LayoutUnit pageLogicalHeight, LayoutStateMaintainer&);
1101 // Returns the logicalOffset at the top of the next page. If the offset passed in is already at the top of the current page,
1102 // then nextPageLogicalTop with ExcludePageBoundary will still move to the top of the next page. nextPageLogicalTop with
1103 // IncludePageBoundary set will not.
1105 // 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.
1106 enum PageBoundaryRule { ExcludePageBoundary, IncludePageBoundary };
1107 LayoutUnit nextPageLogicalTop(LayoutUnit logicalOffset, PageBoundaryRule = ExcludePageBoundary) const;
1108 bool hasNextPage(LayoutUnit logicalOffset, PageBoundaryRule = ExcludePageBoundary) const;
1110 virtual ColumnInfo::PaginationUnit paginationUnit() const;
1112 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.
1113 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.
1116 LayoutUnit pageLogicalTopForOffset(LayoutUnit offset) const;
1117 LayoutUnit pageLogicalHeightForOffset(LayoutUnit offset) const;
1118 LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit offset, PageBoundaryRule = IncludePageBoundary) const;
1121 bool pushToNextPageWithMinimumLogicalHeight(LayoutUnit& adjustment, LayoutUnit logicalOffset, LayoutUnit minimumLogicalHeight) const;
1123 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.
1124 void adjustLinePositionForPagination(RootInlineBox*, LayoutUnit& deltaOffset, RenderFlowThread*); // Computes a deltaOffset value that put a line at the top of the next page if it doesn't fit on the current page.
1125 LayoutUnit adjustBlockChildForPagination(LayoutUnit logicalTopAfterClear, LayoutUnit estimateWithoutPagination, RenderBox* child, bool atBeforeSideOfBlock);
1127 // Adjust from painting offsets to the local coords of this renderer
1128 void offsetForContents(LayoutPoint&) const;
1130 // 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
1131 // region/page/column that has a different available line width than the old one. Used to know when you have to dirty a
1132 // line, i.e., that it can't be re-used.
1133 bool lineWidthForPaginatedLineChanged(RootInlineBox*, LayoutUnit lineDelta, RenderFlowThread*) const;
1135 bool logicalWidthChangedInRegions(RenderFlowThread*) const;
1137 virtual bool requiresColumns(int desiredColumnCount) const;
1139 virtual bool updateLogicalWidthAndColumnWidth();
1141 virtual bool canCollapseAnonymousBlockChild() const { return true; }
1144 virtual LayoutUnit offsetFromLogicalTopOfFirstPage() const;
1145 RenderRegion* regionAtBlockOffset(LayoutUnit) const;
1146 RenderRegion* clampToStartAndEndRegions(RenderRegion*) const;
1149 struct FloatingObjectHashFunctions {
1150 static unsigned hash(FloatingObject* key) { return DefaultHash<RenderBox*>::Hash::hash(key->m_renderer); }
1151 static bool equal(FloatingObject* a, FloatingObject* b) { return a->m_renderer == b->m_renderer; }
1152 static const bool safeToCompareToEmptyOrDeleted = true;
1154 struct FloatingObjectHashTranslator {
1155 static unsigned hash(RenderBox* key) { return DefaultHash<RenderBox*>::Hash::hash(key); }
1156 static bool equal(FloatingObject* a, RenderBox* b) { return a->m_renderer == b; }
1158 typedef ListHashSet<FloatingObject*, 4, FloatingObjectHashFunctions> FloatingObjectSet;
1159 typedef FloatingObjectSet::const_iterator FloatingObjectSetIterator;
1160 typedef PODInterval<int, FloatingObject*> FloatingObjectInterval;
1161 typedef PODIntervalTree<int, FloatingObject*> FloatingObjectTree;
1162 typedef PODFreeListArena<PODRedBlackTree<FloatingObjectInterval>::Node> IntervalArena;
1164 template <FloatingObject::Type FloatTypeValue>
1165 class FloatIntervalSearchAdapter {
1167 typedef FloatingObjectInterval IntervalType;
1169 FloatIntervalSearchAdapter(const RenderBlock* renderer, int lowValue, int highValue, LayoutUnit& offset, LayoutUnit* heightRemaining)
1170 : m_renderer(renderer)
1171 , m_lowValue(lowValue)
1172 , m_highValue(highValue)
1174 , m_heightRemaining(heightRemaining)
1175 #if ENABLE(CSS_SHAPES)
1181 inline int lowValue() const { return m_lowValue; }
1182 inline int highValue() const { return m_highValue; }
1183 void collectIfNeeded(const IntervalType&) const;
1185 #if ENABLE(CSS_SHAPES)
1186 // When computing the offset caused by the floats on a given line, if
1187 // the outermost float on that line has a shape-outside, the inline
1188 // content that butts up against that float must be positioned using
1189 // the contours of the shape, not the shape's bounding box. We save the
1190 // last float encountered so that the offset can be computed correctly
1191 // by the code using this adapter.
1192 const FloatingObject* lastFloat() const { return m_last; }
1196 const RenderBlock* m_renderer;
1199 LayoutUnit& m_offset;
1200 LayoutUnit* m_heightRemaining;
1201 #if ENABLE(CSS_SHAPES)
1202 // This member variable is mutable because the collectIfNeeded method
1203 // is declared as const, even though it doesn't actually respect that
1204 // contract. It modifies other member variables via loopholes in the
1205 // const behavior. Instead of using loopholes, I decided it was better
1206 // to make the fact that this is modified in a const method explicit.
1207 mutable const FloatingObject* m_last;
1211 void createFloatingObjects();
1215 class FloatingObjects {
1216 WTF_MAKE_NONCOPYABLE(FloatingObjects); WTF_MAKE_FAST_ALLOCATED;
1219 void add(FloatingObject*);
1220 void remove(FloatingObject*);
1221 void addPlacedObject(FloatingObject*);
1222 void removePlacedObject(FloatingObject*);
1223 void setHorizontalWritingMode(bool b = true) { m_horizontalWritingMode = b; }
1225 bool hasLeftObjects() const { return m_leftObjectsCount > 0; }
1226 bool hasRightObjects() const { return m_rightObjectsCount > 0; }
1227 const FloatingObjectSet& set() const { return m_set; }
1228 const FloatingObjectTree& placedFloatsTree()
1230 computePlacedFloatsTreeIfNeeded();
1231 return m_placedFloatsTree;
1234 FloatingObjects(const RenderBlock*, bool horizontalWritingMode);
1235 void computePlacedFloatsTree();
1236 inline void computePlacedFloatsTreeIfNeeded()
1238 if (!m_placedFloatsTree.isInitialized())
1239 computePlacedFloatsTree();
1241 void increaseObjectsCount(FloatingObject::Type);
1242 void decreaseObjectsCount(FloatingObject::Type);
1243 FloatingObjectInterval intervalForFloatingObject(FloatingObject*);
1245 FloatingObjectSet m_set;
1246 FloatingObjectTree m_placedFloatsTree;
1247 unsigned m_leftObjectsCount;
1248 unsigned m_rightObjectsCount;
1249 bool m_horizontalWritingMode;
1250 const RenderBlock* m_renderer;
1252 friend void RenderBlock::createFloatingObjects();
1255 // Allocated only when some of these fields have non-default values
1256 struct RenderBlockRareData {
1257 WTF_MAKE_NONCOPYABLE(RenderBlockRareData); WTF_MAKE_FAST_ALLOCATED;
1259 RenderBlockRareData(const RenderBlock* block)
1260 : m_margins(positiveMarginBeforeDefault(block), negativeMarginBeforeDefault(block), positiveMarginAfterDefault(block), negativeMarginAfterDefault(block))
1261 , m_paginationStrut(0)
1262 , m_pageLogicalOffset(0)
1264 , m_lineBreakToAvoidWidow(0)
1265 , m_shouldBreakAtLineToAvoidWidow(false)
1266 , m_discardMarginBefore(false)
1267 , m_discardMarginAfter(false)
1271 static LayoutUnit positiveMarginBeforeDefault(const RenderBlock* block)
1273 return std::max<LayoutUnit>(block->marginBefore(), 0);
1275 static LayoutUnit negativeMarginBeforeDefault(const RenderBlock* block)
1277 return std::max<LayoutUnit>(-block->marginBefore(), 0);
1279 static LayoutUnit positiveMarginAfterDefault(const RenderBlock* block)
1281 return std::max<LayoutUnit>(block->marginAfter(), 0);
1283 static LayoutUnit negativeMarginAfterDefault(const RenderBlock* block)
1285 return std::max<LayoutUnit>(-block->marginAfter(), 0);
1288 MarginValues m_margins;
1289 LayoutUnit m_paginationStrut;
1290 LayoutUnit m_pageLogicalOffset;
1292 RootInlineBox* m_lineGridBox;
1294 RootInlineBox* m_lineBreakToAvoidWidow;
1295 #if ENABLE(CSS_SHAPES)
1296 OwnPtr<ExclusionShapeInsideInfo> m_shapeInsideInfo;
1298 bool m_shouldBreakAtLineToAvoidWidow : 1;
1299 bool m_discardMarginBefore : 1;
1300 bool m_discardMarginAfter : 1;
1305 OwnPtr<FloatingObjects> m_floatingObjects;
1306 OwnPtr<RenderBlockRareData> m_rareData;
1308 RenderObjectChildList m_children;
1309 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>.
1311 mutable signed m_lineHeight : 27;
1312 unsigned m_hasMarginBeforeQuirk : 1; // Note these quirk values can't be put in RenderBlockRareData since they are set too frequently.
1313 unsigned m_hasMarginAfterQuirk : 1;
1314 unsigned m_beingDestroyed : 1;
1315 unsigned m_hasMarkupTruncation : 1;
1316 unsigned m_hasBorderOrPaddingLogicalWidthChanged : 1;
1318 // RenderRubyBase objects need to be able to split and merge, moving their children around
1319 // (calling moveChildTo, moveAllChildrenTo, and makeChildrenNonInline).
1320 friend class RenderRubyBase;
1321 friend class LineWidth; // Needs to know FloatingObject
1324 // Used to store state between styleWillChange and styleDidChange
1325 static bool s_canPropagateFloatIntoSibling;
1328 inline RenderBlock* toRenderBlock(RenderObject* object)
1330 ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderBlock());
1331 return static_cast<RenderBlock*>(object);
1334 inline const RenderBlock* toRenderBlock(const RenderObject* object)
1336 ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderBlock());
1337 return static_cast<const RenderBlock*>(object);
1340 // This will catch anyone doing an unnecessary cast.
1341 void toRenderBlock(const RenderBlock*);
1344 // These structures are used by PODIntervalTree for debugging purposes.
1345 template <> struct ValueToString<int> {
1346 static String string(const int value);
1348 template<> struct ValueToString<RenderBlock::FloatingObject*> {
1349 static String string(const RenderBlock::FloatingObject*);
1353 } // namespace WebCore
1355 #endif // RenderBlock_h