Move m_floatingObjects to RenderBlockFlow from RenderBlock
[WebKit-https.git] / Source / WebCore / rendering / RenderBlockFlow.h
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2007 David Smith (catfish.man@gmail.com)
5  * Copyright (C) 2003-2013,  Apple Inc. All rights reserved.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #ifndef RenderBlockFlow_h
24 #define RenderBlockFlow_h
25
26 #include "RenderBlock.h"
27
28 namespace WebCore {
29
30 class LineBreaker;
31
32 class RenderBlockFlow : public RenderBlock {
33 public:
34     explicit RenderBlockFlow(Element*);
35     virtual ~RenderBlockFlow();
36         
37     virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) OVERRIDE;
38
39 protected:
40     virtual void willBeDestroyed() OVERRIDE;
41     
42     // This method is called at the start of layout to wipe away all of the floats in our floating objects list. It also
43     // repopulates the list with any floats that intrude from previous siblings or parents. Floats that were added by
44     // descendants are gone when this call completes and will get added back later on after the children have gotten
45     // a relayout.
46     void clearFloats();
47
48     // RenderBlockFlow always contains either lines or paragraphs. When the children are all blocks (e.g. paragraphs), we call layoutBlockChildren.
49     // When the children are are all inline (e.g., lines), we call layoutInlineChildren.
50     void layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloatLogicalBottom);
51     void layoutInlineChildren(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom);
52     
53     // RenderBlockFlows override these methods, since they are the only class that supports margin collapsing.
54     virtual LayoutUnit collapsedMarginBefore() const OVERRIDE FINAL { return maxPositiveMarginBefore() - maxNegativeMarginBefore(); }
55     virtual LayoutUnit collapsedMarginAfter() const OVERRIDE FINAL { return maxPositiveMarginAfter() - maxNegativeMarginAfter(); }
56
57     virtual void dirtyLinesFromChangedChild(RenderObject* child) OVERRIDE FINAL { lineBoxes().dirtyLinesFromChangedChild(this, child); }
58
59 public:
60     class MarginValues {
61     public:
62         MarginValues(LayoutUnit beforePos, LayoutUnit beforeNeg, LayoutUnit afterPos, LayoutUnit afterNeg)
63             : m_positiveMarginBefore(beforePos)
64             , m_negativeMarginBefore(beforeNeg)
65             , m_positiveMarginAfter(afterPos)
66             , m_negativeMarginAfter(afterNeg)
67         { }
68         
69         LayoutUnit positiveMarginBefore() const { return m_positiveMarginBefore; }
70         LayoutUnit negativeMarginBefore() const { return m_negativeMarginBefore; }
71         LayoutUnit positiveMarginAfter() const { return m_positiveMarginAfter; }
72         LayoutUnit negativeMarginAfter() const { return m_negativeMarginAfter; }
73         
74         void setPositiveMarginBefore(LayoutUnit pos) { m_positiveMarginBefore = pos; }
75         void setNegativeMarginBefore(LayoutUnit neg) { m_negativeMarginBefore = neg; }
76         void setPositiveMarginAfter(LayoutUnit pos) { m_positiveMarginAfter = pos; }
77         void setNegativeMarginAfter(LayoutUnit neg) { m_negativeMarginAfter = neg; }
78     
79     private:
80         LayoutUnit m_positiveMarginBefore;
81         LayoutUnit m_negativeMarginBefore;
82         LayoutUnit m_positiveMarginAfter;
83         LayoutUnit m_negativeMarginAfter;
84     };
85     MarginValues marginValuesForChild(RenderBox* child) const;
86
87     // Allocated only when some of these fields have non-default values
88     struct RenderBlockFlowRareData {
89         WTF_MAKE_NONCOPYABLE(RenderBlockFlowRareData); WTF_MAKE_FAST_ALLOCATED;
90     public:
91         RenderBlockFlowRareData(const RenderBlockFlow* block)
92             : m_margins(positiveMarginBeforeDefault(block), negativeMarginBeforeDefault(block), positiveMarginAfterDefault(block), negativeMarginAfterDefault(block))
93             , m_lineBreakToAvoidWidow(-1)
94             , m_lineGridBox(0)
95             , m_discardMarginBefore(false)
96             , m_discardMarginAfter(false)
97             , m_didBreakAtLineToAvoidWidow(false)
98         { 
99         }
100
101         static LayoutUnit positiveMarginBeforeDefault(const RenderBlock* block)
102         { 
103             return std::max<LayoutUnit>(block->marginBefore(), 0);
104         }
105         static LayoutUnit negativeMarginBeforeDefault(const RenderBlock* block)
106         { 
107             return std::max<LayoutUnit>(-block->marginBefore(), 0);
108         }
109         static LayoutUnit positiveMarginAfterDefault(const RenderBlock* block)
110         {
111             return std::max<LayoutUnit>(block->marginAfter(), 0);
112         }
113         static LayoutUnit negativeMarginAfterDefault(const RenderBlock* block)
114         {
115             return std::max<LayoutUnit>(-block->marginAfter(), 0);
116         }
117         
118         MarginValues m_margins;
119         int m_lineBreakToAvoidWidow;
120         RootInlineBox* m_lineGridBox;
121
122         bool m_discardMarginBefore : 1;
123         bool m_discardMarginAfter : 1;
124         bool m_didBreakAtLineToAvoidWidow : 1;
125     };
126
127     class MarginInfo {
128         // Collapsing flags for whether we can collapse our margins with our children's margins.
129         bool m_canCollapseWithChildren : 1;
130         bool m_canCollapseMarginBeforeWithChildren : 1;
131         bool m_canCollapseMarginAfterWithChildren : 1;
132
133         // Whether or not we are a quirky container, i.e., do we collapse away top and bottom
134         // margins in our container. Table cells and the body are the common examples. We
135         // also have a custom style property for Safari RSS to deal with TypePad blog articles.
136         bool m_quirkContainer : 1;
137
138         // This flag tracks whether we are still looking at child margins that can all collapse together at the beginning of a block.  
139         // They may or may not collapse with the top margin of the block (|m_canCollapseTopWithChildren| tells us that), but they will
140         // always be collapsing with one another. This variable can remain set to true through multiple iterations 
141         // as long as we keep encountering self-collapsing blocks.
142         bool m_atBeforeSideOfBlock : 1;
143
144         // This flag is set when we know we're examining bottom margins and we know we're at the bottom of the block.
145         bool m_atAfterSideOfBlock : 1;
146
147         // These variables are used to detect quirky margins that we need to collapse away (in table cells
148         // and in the body element).
149         bool m_hasMarginBeforeQuirk : 1;
150         bool m_hasMarginAfterQuirk : 1;
151         bool m_determinedMarginBeforeQuirk : 1;
152
153         bool m_discardMargin : 1;
154
155         // These flags track the previous maximal positive and negative margins.
156         LayoutUnit m_positiveMargin;
157         LayoutUnit m_negativeMargin;
158
159     public:
160         MarginInfo(RenderBlockFlow*, LayoutUnit beforeBorderPadding, LayoutUnit afterBorderPadding);
161
162         void setAtBeforeSideOfBlock(bool b) { m_atBeforeSideOfBlock = b; }
163         void setAtAfterSideOfBlock(bool b) { m_atAfterSideOfBlock = b; }
164         void clearMargin()
165         {
166             m_positiveMargin = 0;
167             m_negativeMargin = 0;
168         }
169         void setHasMarginBeforeQuirk(bool b) { m_hasMarginBeforeQuirk = b; }
170         void setHasMarginAfterQuirk(bool b) { m_hasMarginAfterQuirk = b; }
171         void setDeterminedMarginBeforeQuirk(bool b) { m_determinedMarginBeforeQuirk = b; }
172         void setPositiveMargin(LayoutUnit p) { ASSERT(!m_discardMargin); m_positiveMargin = p; }
173         void setNegativeMargin(LayoutUnit n) { ASSERT(!m_discardMargin); m_negativeMargin = n; }
174         void setPositiveMarginIfLarger(LayoutUnit p)
175         {
176             ASSERT(!m_discardMargin);
177             if (p > m_positiveMargin)
178                 m_positiveMargin = p;
179         }
180         void setNegativeMarginIfLarger(LayoutUnit n)
181         {
182             ASSERT(!m_discardMargin);
183             if (n > m_negativeMargin)
184                 m_negativeMargin = n;
185         }
186
187         void setMargin(LayoutUnit p, LayoutUnit n) { ASSERT(!m_discardMargin); m_positiveMargin = p; m_negativeMargin = n; }
188         void setCanCollapseMarginAfterWithChildren(bool collapse) { m_canCollapseMarginAfterWithChildren = collapse; }
189         void setDiscardMargin(bool value) { m_discardMargin = value; }
190
191         bool atBeforeSideOfBlock() const { return m_atBeforeSideOfBlock; }
192         bool canCollapseWithMarginBefore() const { return m_atBeforeSideOfBlock && m_canCollapseMarginBeforeWithChildren; }
193         bool canCollapseWithMarginAfter() const { return m_atAfterSideOfBlock && m_canCollapseMarginAfterWithChildren; }
194         bool canCollapseMarginBeforeWithChildren() const { return m_canCollapseMarginBeforeWithChildren; }
195         bool canCollapseMarginAfterWithChildren() const { return m_canCollapseMarginAfterWithChildren; }
196         bool quirkContainer() const { return m_quirkContainer; }
197         bool determinedMarginBeforeQuirk() const { return m_determinedMarginBeforeQuirk; }
198         bool hasMarginBeforeQuirk() const { return m_hasMarginBeforeQuirk; }
199         bool hasMarginAfterQuirk() const { return m_hasMarginAfterQuirk; }
200         LayoutUnit positiveMargin() const { return m_positiveMargin; }
201         LayoutUnit negativeMargin() const { return m_negativeMargin; }
202         bool discardMargin() const { return m_discardMargin; }
203         LayoutUnit margin() const { return m_positiveMargin - m_negativeMargin; }
204     };
205
206     void layoutBlockChild(RenderBox* child, MarginInfo&, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom);
207     void adjustPositionedBlock(RenderBox* child, const MarginInfo&);
208     void adjustFloatingBlock(const MarginInfo&);
209
210     LayoutUnit collapseMargins(RenderBox* child, MarginInfo&);
211     LayoutUnit clearFloatsIfNeeded(RenderBox* child, MarginInfo&, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos);
212     LayoutUnit estimateLogicalTopPosition(RenderBox* child, const MarginInfo&, LayoutUnit& estimateWithoutPagination);
213     void marginBeforeEstimateForChild(RenderBox*, LayoutUnit&, LayoutUnit&, bool&) const;
214     void handleAfterSideOfBlock(LayoutUnit top, LayoutUnit bottom, MarginInfo&);
215     void setCollapsedBottomMargin(const MarginInfo&);
216
217     bool shouldBreakAtLineToAvoidWidow() const { return m_rareData && m_rareData->m_lineBreakToAvoidWidow >= 0; }
218     void clearShouldBreakAtLineToAvoidWidow() const;
219     int lineBreakToAvoidWidow() const { return m_rareData ? m_rareData->m_lineBreakToAvoidWidow : -1; }
220     void setBreakAtLineToAvoidWidow(int);
221     void clearDidBreakAtLineToAvoidWidow();
222     void setDidBreakAtLineToAvoidWidow();
223     bool didBreakAtLineToAvoidWidow() const { return m_rareData && m_rareData->m_didBreakAtLineToAvoidWidow; }
224     bool relayoutToAvoidWidows(LayoutStateMaintainer&);
225
226     RootInlineBox* lineGridBox() const { return m_rareData ? m_rareData->m_lineGridBox : 0; }
227     void setLineGridBox(RootInlineBox* box)
228     {
229         if (!m_rareData)
230             m_rareData = adoptPtr(new RenderBlockFlowRareData(this));
231         if (m_rareData->m_lineGridBox)
232             m_rareData->m_lineGridBox->destroy(renderArena());
233         m_rareData->m_lineGridBox = box;
234     }
235     void layoutLineGridBox();
236
237     bool containsFloats() const OVERRIDE { return m_floatingObjects && !m_floatingObjects->set().isEmpty(); }
238     bool containsFloat(RenderBox*) const;
239
240     virtual void deleteLineBoxTree() OVERRIDE;
241     virtual void computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats = false) OVERRIDE;
242
243     void removeFloatingObjects();
244     void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true);
245     void markSiblingsWithFloatsForLayout(RenderBox* floatToRemove = 0);
246
247 protected:
248     LayoutUnit maxPositiveMarginBefore() const { return m_rareData ? m_rareData->m_margins.positiveMarginBefore() : RenderBlockFlowRareData::positiveMarginBeforeDefault(this); }
249     LayoutUnit maxNegativeMarginBefore() const { return m_rareData ? m_rareData->m_margins.negativeMarginBefore() : RenderBlockFlowRareData::negativeMarginBeforeDefault(this); }
250     LayoutUnit maxPositiveMarginAfter() const { return m_rareData ? m_rareData->m_margins.positiveMarginAfter() : RenderBlockFlowRareData::positiveMarginAfterDefault(this); }
251     LayoutUnit maxNegativeMarginAfter() const { return m_rareData ? m_rareData->m_margins.negativeMarginAfter() : RenderBlockFlowRareData::negativeMarginAfterDefault(this); }
252
253     void initMaxMarginValues()
254     {
255         if (!m_rareData)
256             return;
257         m_rareData->m_margins = MarginValues(RenderBlockFlowRareData::positiveMarginBeforeDefault(this) , RenderBlockFlowRareData::negativeMarginBeforeDefault(this),
258             RenderBlockFlowRareData::positiveMarginAfterDefault(this), RenderBlockFlowRareData::negativeMarginAfterDefault(this));
259         m_rareData->m_discardMarginBefore = false;
260         m_rareData->m_discardMarginAfter = false;
261     }
262
263     void setMaxMarginBeforeValues(LayoutUnit pos, LayoutUnit neg);
264     void setMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg);
265
266     void setMustDiscardMarginBefore(bool = true);
267     void setMustDiscardMarginAfter(bool = true);
268
269     bool mustDiscardMarginBefore() const;
270     bool mustDiscardMarginAfter() const;
271
272     bool mustDiscardMarginBeforeForChild(const RenderBox*) const;
273     bool mustDiscardMarginAfterForChild(const RenderBox*) const;
274
275     bool mustSeparateMarginBeforeForChild(const RenderBox*) const;
276     bool mustSeparateMarginAfterForChild(const RenderBox*) const;
277
278     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.
279     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.
280     LayoutUnit adjustBlockChildForPagination(LayoutUnit logicalTopAfterClear, LayoutUnit estimateWithoutPagination, RenderBox* child, bool atBeforeSideOfBlock);
281
282     virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle) OVERRIDE;
283     virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
284
285     void createFloatingObjects();
286
287 private:
288     virtual void moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert) OVERRIDE;
289     virtual void repaintOverhangingFloats(bool paintAllDescendants) OVERRIDE FINAL;
290     virtual void paintFloats(PaintInfo&, const LayoutPoint&, bool preservePhase = false) OVERRIDE;
291     virtual void clipOutFloatingObjects(RenderBlock*, const PaintInfo*, const LayoutPoint&, const LayoutSize&) OVERRIDE;
292
293     FloatingObject* insertFloatingObject(RenderBox*);
294     void removeFloatingObject(RenderBox*);
295     void removeFloatingObjectsBelow(FloatingObject*, int logicalOffset);
296     LayoutPoint computeLogicalLocationForFloat(const FloatingObject*, LayoutUnit logicalTopOffset) const;
297
298     // Called from lineWidth, to position the floats added in the last line.
299     // Returns true if and only if it has positioned any floats.
300     bool positionNewFloats();
301
302     void newLine(EClear);
303
304     virtual LayoutUnit logicalRightFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit* heightRemaining, LayoutUnit logicalHeight, ShapeOutsideFloatOffsetMode) const OVERRIDE;
305     virtual LayoutUnit logicalLeftFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit* heightRemaining, LayoutUnit logicalHeight, ShapeOutsideFloatOffsetMode) const OVERRIDE;
306     LayoutUnit lowestFloatLogicalBottom(FloatingObject::Type = FloatingObject::FloatLeftRight) const; 
307     LayoutUnit nextFloatLogicalBottomBelow(LayoutUnit, ShapeOutsideFloatOffsetMode = ShapeOutsideFloatMarginBoxOffset) const;
308     
309     LayoutUnit addOverhangingFloats(RenderBlockFlow* child, bool makeChildPaintOtherFloats);
310     bool hasOverhangingFloat(RenderBox*);
311     void addIntrudingFloats(RenderBlockFlow* prev, LayoutUnit xoffset, LayoutUnit yoffset);
312     bool hasOverhangingFloats() { return parent() && !hasColumns() && containsFloats() && lowestFloatLogicalBottom() > logicalHeight(); }
313     LayoutUnit getClearDelta(RenderBox* child, LayoutUnit yPos);
314
315     virtual bool hitTestFloats(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) OVERRIDE;
316     void addOverflowFromFloats();
317     virtual void adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const OVERRIDE;
318
319
320 // FIXME-BLOCKFLOW: These methods have implementations in
321 // RenderBlockLineLayout. They should be moved to the proper header once the
322 // line layout code is separated from RenderBlock and RenderBlockFlow.
323 // START METHODS DEFINED IN RenderBlockLineLayout
324 public:
325     static void appendRunsForObject(BidiRunList<BidiRun>&, int start, int end, RenderObject*, InlineBidiResolver&);
326
327 private:
328     InlineFlowBox* createLineBoxes(RenderObject*, const LineInfo&, InlineBox* childBox, bool startsNewSegment);
329     RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
330     void setMarginsForRubyRun(BidiRun*, RenderRubyRun*, RenderObject*, const LineInfo&);
331     void computeInlineDirectionPositionsForLine(RootInlineBox*, const LineInfo&, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&, WordMeasurements&);
332     BidiRun* computeInlineDirectionPositionsForSegment(RootInlineBox*, const LineInfo&, ETextAlign, float& logicalLeft,
333         float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache&, WordMeasurements&);
334     void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&);
335     BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>&, BidiContext*);
336     void appendFloatingObjectToLastLine(FloatingObject*);
337     // Helper function for layoutInlineChildren()
338     RootInlineBox* createLineBoxesFromBidiRuns(BidiRunList<BidiRun>&, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun, WordMeasurements&);
339     void layoutRunsAndFloats(LineLayoutState&, bool hasInlineChild);
340     const InlineIterator& restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight,  FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver&,  const InlineIterator&);
341     void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines);
342 #if ENABLE(CSS_SHAPES)
343     void updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*&, const LayoutSize&, LineLayoutState&);
344     void updateShapeAndSegmentsForCurrentLineInFlowThread(ShapeInsideInfo*&, LineLayoutState&);
345     bool adjustLogicalLineTopAndLogicalHeightIfNeeded(ShapeInsideInfo*, LayoutUnit, LineLayoutState&, InlineBidiResolver&, FloatingObject*, InlineIterator&, WordMeasurements&);
346 #endif
347     void linkToEndLineIfNeeded(LineLayoutState&);
348     static void repaintDirtyFloats(Vector<FloatWithRect>& floats);
349     void checkFloatsInCleanLine(RootInlineBox*, Vector<FloatWithRect>&, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat);
350     RootInlineBox* determineStartPosition(LineLayoutState&, InlineBidiResolver&);
351     void determineEndPosition(LineLayoutState&, RootInlineBox* startBox, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus);
352     bool checkPaginationAndFloatsAtEndLine(LineLayoutState&);
353     bool matchedEndLine(LineLayoutState&, const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus);
354     void deleteEllipsisLineBoxes();
355     void checkLinesForTextOverflow();
356     // Positions new floats and also adjust all floats encountered on the line if any of them
357     // have to move to the next page/column.
358     bool positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo&, LineWidth&);
359
360
361 // END METHODS DEFINED IN RenderBlockLineLayout
362     
363 public:
364     // FIXME-BLOCKFLOW: These can be made protected again once all callers have been moved here.
365     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.
366     void updateRegionForLine(RootInlineBox*) const;
367
368 protected:
369     OwnPtr<FloatingObjects> m_floatingObjects;
370     OwnPtr<RenderBlockFlowRareData> m_rareData;
371
372     friend class LineBreaker;
373     friend class LineWidth; // Needs to know FloatingObject
374 };
375
376 inline RenderBlockFlow& toRenderBlockFlow(RenderObject& object)
377 {
378     ASSERT_WITH_SECURITY_IMPLICATION(object.isRenderBlockFlow());
379     return static_cast<RenderBlockFlow&>(object);
380 }
381
382 inline const RenderBlockFlow& toRenderBlockFlow(const RenderObject& object)
383 {
384     ASSERT_WITH_SECURITY_IMPLICATION(object.isRenderBlockFlow());
385     return static_cast<const RenderBlockFlow&>(object);
386 }
387
388 inline RenderBlockFlow* toRenderBlockFlow(RenderObject* object)
389
390     ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderBlockFlow());
391     return static_cast<RenderBlockFlow*>(object);
392 }
393
394 inline const RenderBlockFlow* toRenderBlockFlow(const RenderObject* object)
395
396     ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderBlockFlow());
397     return static_cast<const RenderBlockFlow*>(object);
398 }
399
400 // This will catch anyone doing an unnecessary cast.
401 void toRenderBlockFlow(const RenderBlockFlow*);
402 void toRenderBlockFlow(const RenderBlockFlow&);
403
404 } // namespace WebCore
405
406 #endif // RenderBlockFlow_h