• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2007 David Smith (catfish.man@gmail.com)
5  * Copyright (C) 2003-2013 Apple Inc. All rights reserved.
6  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
7  * Copyright (C) 2013 Google Inc. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are
11  * met:
12  *
13  *     * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *     * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following disclaimer
17  * in the documentation and/or other materials provided with the
18  * distribution.
19  *     * Neither the name of Google Inc. nor the names of its
20  * contributors may be used to endorse or promote products derived from
21  * this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #ifndef RenderBlockFlow_h
37 #define RenderBlockFlow_h
38 
39 #include "core/rendering/FloatingObjects.h"
40 #include "core/rendering/RenderBlock.h"
41 #include "core/rendering/line/TrailingObjects.h"
42 #include "core/rendering/style/RenderStyleConstants.h"
43 
44 namespace WebCore {
45 
46 class MarginInfo;
47 class LineBreaker;
48 class LineWidth;
49 class RenderMultiColumnFlowThread;
50 
51 class RenderBlockFlow : public RenderBlock {
52 public:
53     explicit RenderBlockFlow(ContainerNode*);
54     virtual ~RenderBlockFlow();
55 
56     static RenderBlockFlow* createAnonymous(Document*);
57 
isRenderBlockFlow()58     virtual bool isRenderBlockFlow() const OVERRIDE FINAL { return true; }
59 
60     virtual void layoutBlock(bool relayoutChildren) OVERRIDE;
61 
62     virtual void computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats = false) OVERRIDE;
63     virtual void deleteLineBoxTree() OVERRIDE FINAL;
64 
65     LayoutUnit availableLogicalWidthForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
66     {
67         return max<LayoutUnit>(0, logicalRightOffsetForLine(position, shouldIndentText, logicalHeight) - logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight));
68     }
69     LayoutUnit logicalRightOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
70     {
71         return logicalRightOffsetForLine(position, logicalRightOffsetForContent(), shouldIndentText, logicalHeight);
72     }
73     LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
74     {
75         return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(), shouldIndentText, logicalHeight);
76     }
77     LayoutUnit startOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
78     {
79         return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight)
80             : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, logicalHeight);
81     }
82     LayoutUnit endOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
83     {
84         return !style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight)
85             : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, logicalHeight);
86     }
87 
88     virtual LayoutUnit logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position) OVERRIDE;
89     virtual LayoutUnit logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position) OVERRIDE;
90 
91     LayoutUnit computeStartPositionDeltaForChildAvoidingFloats(const RenderBox* child, LayoutUnit childMarginStart);
92 
93     RootInlineBox* createAndAppendRootInlineBox();
94 
95     void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true);
96     void markSiblingsWithFloatsForLayout(RenderBox* floatToRemove = 0);
97 
containsFloats()98     virtual bool containsFloats() const OVERRIDE FINAL { return m_floatingObjects && !m_floatingObjects->set().isEmpty(); }
99     bool containsFloat(RenderBox*) const;
100 
101     void removeFloatingObjects();
102 
103     virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE;
104 
105     void moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert);
106 
107     bool generatesLineBoxesForInlineChild(RenderObject*);
108 
logicalTopForFloat(const FloatingObject * floatingObject)109     LayoutUnit logicalTopForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->y() : floatingObject->x(); }
logicalBottomForFloat(const FloatingObject * floatingObject)110     LayoutUnit logicalBottomForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->maxY() : floatingObject->maxX(); }
logicalLeftForFloat(const FloatingObject * floatingObject)111     LayoutUnit logicalLeftForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->x() : floatingObject->y(); }
logicalRightForFloat(const FloatingObject * floatingObject)112     LayoutUnit logicalRightForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->maxX() : floatingObject->maxY(); }
logicalWidthForFloat(const FloatingObject * floatingObject)113     LayoutUnit logicalWidthForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->width() : floatingObject->height(); }
logicalHeightForFloat(const FloatingObject * floatingObject)114     LayoutUnit logicalHeightForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->height() : floatingObject->width(); }
logicalSizeForFloat(const FloatingObject * floatingObject)115     LayoutSize logicalSizeForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? LayoutSize(floatingObject->width(), floatingObject->height()) : LayoutSize(floatingObject->height(), floatingObject->width()); }
116 
pixelSnappedLogicalTopForFloat(const FloatingObject * floatingObject)117     int pixelSnappedLogicalTopForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->frameRect().pixelSnappedY() : floatingObject->frameRect().pixelSnappedX(); }
pixelSnappedLogicalBottomForFloat(const FloatingObject * floatingObject)118     int pixelSnappedLogicalBottomForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->frameRect().pixelSnappedMaxY() : floatingObject->frameRect().pixelSnappedMaxX(); }
pixelSnappedLogicalLeftForFloat(const FloatingObject * floatingObject)119     int pixelSnappedLogicalLeftForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->frameRect().pixelSnappedX() : floatingObject->frameRect().pixelSnappedY(); }
pixelSnappedLogicalRightForFloat(const FloatingObject * floatingObject)120     int pixelSnappedLogicalRightForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->frameRect().pixelSnappedMaxX() : floatingObject->frameRect().pixelSnappedMaxY(); }
121 
setLogicalTopForFloat(FloatingObject * floatingObject,LayoutUnit logicalTop)122     void setLogicalTopForFloat(FloatingObject* floatingObject, LayoutUnit logicalTop)
123     {
124         if (isHorizontalWritingMode())
125             floatingObject->setY(logicalTop);
126         else
127             floatingObject->setX(logicalTop);
128     }
setLogicalLeftForFloat(FloatingObject * floatingObject,LayoutUnit logicalLeft)129     void setLogicalLeftForFloat(FloatingObject* floatingObject, LayoutUnit logicalLeft)
130     {
131         if (isHorizontalWritingMode())
132             floatingObject->setX(logicalLeft);
133         else
134             floatingObject->setY(logicalLeft);
135     }
setLogicalHeightForFloat(FloatingObject * floatingObject,LayoutUnit logicalHeight)136     void setLogicalHeightForFloat(FloatingObject* floatingObject, LayoutUnit logicalHeight)
137     {
138         if (isHorizontalWritingMode())
139             floatingObject->setHeight(logicalHeight);
140         else
141             floatingObject->setWidth(logicalHeight);
142     }
setLogicalWidthForFloat(FloatingObject * floatingObject,LayoutUnit logicalWidth)143     void setLogicalWidthForFloat(FloatingObject* floatingObject, LayoutUnit logicalWidth)
144     {
145         if (isHorizontalWritingMode())
146             floatingObject->setWidth(logicalWidth);
147         else
148             floatingObject->setHeight(logicalWidth);
149     }
150 
151     LayoutUnit startAlignedOffsetForLine(LayoutUnit position, bool shouldIndentText);
152 
153     void setStaticInlinePositionForChild(RenderBox*, LayoutUnit blockOffset, LayoutUnit inlinePosition);
154     void updateStaticInlinePositionForChild(RenderBox*, LayoutUnit logicalTop);
155 
shouldSkipCreatingRunsForObject(RenderObject * obj)156     static bool shouldSkipCreatingRunsForObject(RenderObject* obj)
157     {
158         return obj->isFloating() || (obj->isOutOfFlowPositioned() && !obj->style()->isOriginalDisplayInlineType() && !obj->container()->isRenderInline());
159     }
160 
161     // Direction resolved from string value.
162     static TextRun constructTextRun(RenderObject* context, const Font&, const String&, RenderStyle*,
163         TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion, TextRunFlags = DefaultTextRunFlags);
164     static TextRun constructTextRun(RenderObject* context, const Font&, const RenderText*, unsigned offset, unsigned length, RenderStyle*,
165         TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
166 
167     // Explicit direction.
168     static TextRun constructTextRun(RenderObject* context, const Font&, const String&, RenderStyle*, TextDirection,
169         TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion, TextRunFlags = DefaultTextRunFlags);
170 
171     static TextRun constructTextRun(RenderObject* context, const Font&, const RenderText*, RenderStyle*, TextDirection,
172         TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
173 
174     static TextRun constructTextRun(RenderObject* context, const Font&, const RenderText*, unsigned offset, unsigned length, RenderStyle*, TextDirection,
175         TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
176 
177     static TextRun constructTextRun(RenderObject* context, const Font&, const RenderText*, unsigned offset, RenderStyle*,
178         TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
179 
180     static TextRun constructTextRun(RenderObject* context, const Font&, const LChar* characters, int length, RenderStyle*, TextDirection,
181         TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
182 
183     static TextRun constructTextRun(RenderObject* context, const Font&, const UChar* characters, int length, RenderStyle*, TextDirection,
184         TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
185 
multiColumnFlowThread()186     RenderMultiColumnFlowThread* multiColumnFlowThread() const { return m_rareData ? m_rareData->m_multiColumnFlowThread : 0; }
resetMultiColumnFlowThread()187     void resetMultiColumnFlowThread()
188     {
189         if (m_rareData)
190             m_rareData->m_multiColumnFlowThread = 0;
191     }
192 
193     void addOverflowFromInlineChildren();
194 
195     // FIXME: This should be const to avoid a const_cast, but can modify child dirty bits and RenderCombineText
196     void computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth);
197 
198     GapRects inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
199         LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo*);
200 protected:
201     void rebuildFloatsFromIntruding();
202     void layoutInlineChildren(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom, LayoutUnit afterEdge);
203 
204     void createFloatingObjects();
205 
206     virtual void styleWillChange(StyleDifference, const RenderStyle& newStyle) OVERRIDE;
207     virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
208 
209     void addOverflowFromFloats();
210 
211     LayoutUnit logicalRightOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit logicalHeight = 0) const
212     {
213         return adjustLogicalRightOffsetForLine(logicalRightFloatOffsetForLine(logicalTop, fixedOffset, logicalHeight), applyTextIndent);
214     }
215     LayoutUnit logicalLeftOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit logicalHeight = 0) const
216     {
217         return adjustLogicalLeftOffsetForLine(logicalLeftFloatOffsetForLine(logicalTop, fixedOffset, logicalHeight), applyTextIndent);
218     }
219 
220     virtual RenderObject* layoutSpecialExcludedChild(bool /*relayoutChildren*/, SubtreeLayoutScope&);
221     virtual bool updateLogicalWidthAndColumnWidth() OVERRIDE;
222 
223     // These functions optionally update LayoutState's layoutDelta, which is used to ensure they're repainted correctly when moved
224     enum ApplyLayoutDeltaMode { ApplyLayoutDelta, DoNotApplyLayoutDelta };
225     void setLogicalLeftForChild(RenderBox* child, LayoutUnit logicalLeft, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
226     void setLogicalTopForChild(RenderBox* child, LayoutUnit logicalTop, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
227     void determineLogicalLeftPositionForChild(RenderBox* child, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
228 
229 private:
230     bool layoutBlockFlow(bool relayoutChildren, LayoutUnit& pageLogicalHeight, SubtreeLayoutScope&);
231     void layoutBlockChildren(bool relayoutChildren, SubtreeLayoutScope&, LayoutUnit beforeEdge, LayoutUnit afterEdge);
232 
233     void layoutBlockChild(RenderBox* child, MarginInfo&, LayoutUnit& previousFloatLogicalBottom);
234     void adjustPositionedBlock(RenderBox* child, const MarginInfo&);
235     void adjustFloatingBlock(const MarginInfo&);
236 
237     LayoutPoint flipFloatForWritingModeForChild(const FloatingObject*, const LayoutPoint&) const;
238 
xPositionForFloatIncludingMargin(const FloatingObject * child)239     LayoutUnit xPositionForFloatIncludingMargin(const FloatingObject* child) const
240     {
241         if (isHorizontalWritingMode())
242             return child->x() + child->renderer()->marginLeft();
243 
244         return child->x() + marginBeforeForChild(child->renderer());
245     }
246 
yPositionForFloatIncludingMargin(const FloatingObject * child)247     LayoutUnit yPositionForFloatIncludingMargin(const FloatingObject* child) const
248     {
249         if (isHorizontalWritingMode())
250             return child->y() + marginBeforeForChild(child->renderer());
251 
252         return child->y() + child->renderer()->marginTop();
253     }
254 
255     LayoutPoint computeLogicalLocationForFloat(const FloatingObject*, LayoutUnit logicalTopOffset) const;
256 
257     FloatingObject* insertFloatingObject(RenderBox*);
258     void removeFloatingObject(RenderBox*);
259     void removeFloatingObjectsBelow(FloatingObject*, int logicalOffset);
260 
261     // Called from lineWidth, to position the floats added in the last line.
262     // Returns true if and only if it has positioned any floats.
263     bool positionNewFloats();
264 
265     LayoutUnit getClearDelta(RenderBox* child, LayoutUnit yPos);
266 
hasOverhangingFloats()267     bool hasOverhangingFloats() { return parent() && !hasColumns() && containsFloats() && lowestFloatLogicalBottom() > logicalHeight(); }
268     bool hasOverhangingFloat(RenderBox*);
269     void addIntrudingFloats(RenderBlockFlow* prev, LayoutUnit xoffset, LayoutUnit yoffset);
270     void addOverhangingFloats(RenderBlockFlow* child, bool makeChildPaintOtherFloats);
271 
272     LayoutUnit lowestFloatLogicalBottom(FloatingObject::Type = FloatingObject::FloatLeftRight) const;
273     LayoutUnit nextFloatLogicalBottomBelow(LayoutUnit, ShapeOutsideFloatOffsetMode = ShapeOutsideFloatMarginBoxOffset) const;
274 
275     virtual bool hitTestFloats(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) OVERRIDE FINAL;
276 
277     virtual void repaintOverhangingFloats(bool paintAllDescendants) OVERRIDE FINAL;
278     virtual void invalidatePaintForOverflow() OVERRIDE FINAL;
279     virtual void paintFloats(PaintInfo&, const LayoutPoint&, bool preservePhase = false) OVERRIDE FINAL;
280     virtual void clipOutFloatingObjects(RenderBlock*, const PaintInfo*, const LayoutPoint&, const LayoutSize&) OVERRIDE;
281     void clearFloats(EClear);
282 
283     LayoutUnit logicalRightFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit logicalHeight) const;
284     LayoutUnit logicalLeftFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit logicalHeight) const;
285 
286     LayoutUnit logicalRightOffsetForPositioningFloat(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const;
287     LayoutUnit logicalLeftOffsetForPositioningFloat(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const;
288 
289     LayoutUnit adjustLogicalRightOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const;
290     LayoutUnit adjustLogicalLeftOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const;
291 
292     virtual void adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const OVERRIDE; // Helper function for borderFitAdjust
293 
294     virtual RootInlineBox* createRootInlineBox(); // Subclassed by SVG
295 
296     void createOrDestroyMultiColumnFlowThreadIfNeeded();
297 
298     void updateLogicalWidthForAlignment(const ETextAlign&, const RootInlineBox*, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, unsigned expansionOpportunityCount);
299     void checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight);
300     bool shouldRelayoutForPagination(LayoutUnit& pageLogicalHeight, LayoutUnit layoutOverflowLogicalBottom) const;
301     void setColumnCountAndHeight(unsigned count, LayoutUnit pageLogicalHeight);
302 
303 public:
304     struct FloatWithRect {
FloatWithRectFloatWithRect305         FloatWithRect(RenderBox* f)
306             : object(f)
307             , rect(LayoutRect(f->x() - f->marginLeft(), f->y() - f->marginTop(), f->width() + f->marginWidth(), f->height() + f->marginHeight()))
308             , everHadLayout(f->everHadLayout())
309         {
310         }
311 
312         RenderBox* object;
313         LayoutRect rect;
314         bool everHadLayout;
315     };
316 
317     class MarginValues {
318     public:
MarginValues(LayoutUnit beforePos,LayoutUnit beforeNeg,LayoutUnit afterPos,LayoutUnit afterNeg)319         MarginValues(LayoutUnit beforePos, LayoutUnit beforeNeg, LayoutUnit afterPos, LayoutUnit afterNeg)
320             : m_positiveMarginBefore(beforePos)
321             , m_negativeMarginBefore(beforeNeg)
322             , m_positiveMarginAfter(afterPos)
323             , m_negativeMarginAfter(afterNeg)
324         { }
325 
positiveMarginBefore()326         LayoutUnit positiveMarginBefore() const { return m_positiveMarginBefore; }
negativeMarginBefore()327         LayoutUnit negativeMarginBefore() const { return m_negativeMarginBefore; }
positiveMarginAfter()328         LayoutUnit positiveMarginAfter() const { return m_positiveMarginAfter; }
negativeMarginAfter()329         LayoutUnit negativeMarginAfter() const { return m_negativeMarginAfter; }
330 
setPositiveMarginBefore(LayoutUnit pos)331         void setPositiveMarginBefore(LayoutUnit pos) { m_positiveMarginBefore = pos; }
setNegativeMarginBefore(LayoutUnit neg)332         void setNegativeMarginBefore(LayoutUnit neg) { m_negativeMarginBefore = neg; }
setPositiveMarginAfter(LayoutUnit pos)333         void setPositiveMarginAfter(LayoutUnit pos) { m_positiveMarginAfter = pos; }
setNegativeMarginAfter(LayoutUnit neg)334         void setNegativeMarginAfter(LayoutUnit neg) { m_negativeMarginAfter = neg; }
335 
336     private:
337         LayoutUnit m_positiveMarginBefore;
338         LayoutUnit m_negativeMarginBefore;
339         LayoutUnit m_positiveMarginAfter;
340         LayoutUnit m_negativeMarginAfter;
341     };
342     MarginValues marginValuesForChild(RenderBox* child) const;
343 
344     // Allocated only when some of these fields have non-default values
345     struct RenderBlockFlowRareData {
346         WTF_MAKE_NONCOPYABLE(RenderBlockFlowRareData); WTF_MAKE_FAST_ALLOCATED;
347     public:
RenderBlockFlowRareDataRenderBlockFlowRareData348         RenderBlockFlowRareData(const RenderBlockFlow* block)
349             : m_margins(positiveMarginBeforeDefault(block), negativeMarginBeforeDefault(block), positiveMarginAfterDefault(block), negativeMarginAfterDefault(block))
350             , m_multiColumnFlowThread(0)
351             , m_discardMarginBefore(false)
352             , m_discardMarginAfter(false)
353         {
354         }
355 
positiveMarginBeforeDefaultRenderBlockFlowRareData356         static LayoutUnit positiveMarginBeforeDefault(const RenderBlockFlow* block)
357         {
358             return std::max<LayoutUnit>(block->marginBefore(), 0);
359         }
negativeMarginBeforeDefaultRenderBlockFlowRareData360         static LayoutUnit negativeMarginBeforeDefault(const RenderBlockFlow* block)
361         {
362             return std::max<LayoutUnit>(-block->marginBefore(), 0);
363         }
positiveMarginAfterDefaultRenderBlockFlowRareData364         static LayoutUnit positiveMarginAfterDefault(const RenderBlockFlow* block)
365         {
366             return std::max<LayoutUnit>(block->marginAfter(), 0);
367         }
negativeMarginAfterDefaultRenderBlockFlowRareData368         static LayoutUnit negativeMarginAfterDefault(const RenderBlockFlow* block)
369         {
370             return std::max<LayoutUnit>(-block->marginAfter(), 0);
371         }
372 
373         MarginValues m_margins;
374 
375         RenderMultiColumnFlowThread* m_multiColumnFlowThread;
376 
377         bool m_discardMarginBefore : 1;
378         bool m_discardMarginAfter : 1;
379     };
380     LayoutUnit marginOffsetForSelfCollapsingBlock();
381 
382 protected:
maxPositiveMarginBefore()383     LayoutUnit maxPositiveMarginBefore() const { return m_rareData ? m_rareData->m_margins.positiveMarginBefore() : RenderBlockFlowRareData::positiveMarginBeforeDefault(this); }
maxNegativeMarginBefore()384     LayoutUnit maxNegativeMarginBefore() const { return m_rareData ? m_rareData->m_margins.negativeMarginBefore() : RenderBlockFlowRareData::negativeMarginBeforeDefault(this); }
maxPositiveMarginAfter()385     LayoutUnit maxPositiveMarginAfter() const { return m_rareData ? m_rareData->m_margins.positiveMarginAfter() : RenderBlockFlowRareData::positiveMarginAfterDefault(this); }
maxNegativeMarginAfter()386     LayoutUnit maxNegativeMarginAfter() const { return m_rareData ? m_rareData->m_margins.negativeMarginAfter() : RenderBlockFlowRareData::negativeMarginAfterDefault(this); }
387 
388     void setMaxMarginBeforeValues(LayoutUnit pos, LayoutUnit neg);
389     void setMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg);
390 
391     void setMustDiscardMarginBefore(bool = true);
392     void setMustDiscardMarginAfter(bool = true);
393 
394     bool mustDiscardMarginBefore() const;
395     bool mustDiscardMarginAfter() const;
396 
397     bool mustDiscardMarginBeforeForChild(const RenderBox*) const;
398     bool mustDiscardMarginAfterForChild(const RenderBox*) const;
399 
400     bool mustSeparateMarginBeforeForChild(const RenderBox*) const;
401     bool mustSeparateMarginAfterForChild(const RenderBox*) const;
402 
initMaxMarginValues()403     void initMaxMarginValues()
404     {
405         if (m_rareData) {
406             m_rareData->m_margins = MarginValues(RenderBlockFlowRareData::positiveMarginBeforeDefault(this) , RenderBlockFlowRareData::negativeMarginBeforeDefault(this),
407                 RenderBlockFlowRareData::positiveMarginAfterDefault(this), RenderBlockFlowRareData::negativeMarginAfterDefault(this));
408 
409             m_rareData->m_discardMarginBefore = false;
410             m_rareData->m_discardMarginAfter = false;
411         }
412     }
413 
414     virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const;
415 private:
collapsedMarginBefore()416     virtual LayoutUnit collapsedMarginBefore() const OVERRIDE FINAL { return maxPositiveMarginBefore() - maxNegativeMarginBefore(); }
collapsedMarginAfter()417     virtual LayoutUnit collapsedMarginAfter() const OVERRIDE FINAL { return maxPositiveMarginAfter() - maxNegativeMarginAfter(); }
418 
419     LayoutUnit collapseMargins(RenderBox* child, MarginInfo&, bool childIsSelfCollapsing);
420     LayoutUnit clearFloatsIfNeeded(RenderBox* child, MarginInfo&, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos, bool childIsSelfCollapsing);
421     LayoutUnit estimateLogicalTopPosition(RenderBox* child, const MarginInfo&, LayoutUnit& estimateWithoutPagination);
422     void marginBeforeEstimateForChild(RenderBox*, LayoutUnit&, LayoutUnit&, bool&) const;
423     void handleAfterSideOfBlock(RenderBox* lastChild, LayoutUnit top, LayoutUnit bottom, MarginInfo&);
424     void setCollapsedBottomMargin(const MarginInfo&);
425 
426     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.
427     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.
428 
429     LayoutUnit adjustBlockChildForPagination(LayoutUnit logicalTopAfterClear, LayoutUnit estimateWithoutPagination, RenderBox* child, bool atBeforeSideOfBlock);
430 
431     // Used to store state between styleWillChange and styleDidChange
432     static bool s_canPropagateFloatIntoSibling;
433 
434     RenderBlockFlowRareData& ensureRareData();
435 
436     LayoutUnit m_repaintLogicalTop;
437     LayoutUnit m_repaintLogicalBottom;
438 
439     virtual bool isSelfCollapsingBlock() const OVERRIDE;
440 protected:
441     OwnPtr<RenderBlockFlowRareData> m_rareData;
442     OwnPtr<FloatingObjects> m_floatingObjects;
443 
444     friend class BreakingContext; // FIXME: It uses insertFloatingObject and positionNewFloatOnLine, if we move those out from the private scope/add a helper to LineBreaker, we can remove this friend
445     friend class MarginInfo;
446     friend class LineBreaker;
447     friend class LineWidth; // needs to know FloatingObject
448 
449 // FIXME-BLOCKFLOW: These methods have implementations in
450 // RenderBlockLineLayout. They should be moved to the proper header once the
451 // line layout code is separated from RenderBlock and RenderBlockFlow.
452 // START METHODS DEFINED IN RenderBlockLineLayout
453 private:
454     InlineFlowBox* createLineBoxes(RenderObject*, const LineInfo&, InlineBox* childBox);
455     RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
456     void setMarginsForRubyRun(BidiRun*, RenderRubyRun*, RenderObject*, const LineInfo&);
457     void computeInlineDirectionPositionsForLine(RootInlineBox*, const LineInfo&, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&, WordMeasurements&);
458     BidiRun* computeInlineDirectionPositionsForSegment(RootInlineBox*, const LineInfo&, ETextAlign, float& logicalLeft,
459         float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache&, WordMeasurements&);
460     void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&);
461     BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>&, BidiContext*);
462     void appendFloatingObjectToLastLine(FloatingObject*);
463     // Helper function for layoutInlineChildren()
464     RootInlineBox* createLineBoxesFromBidiRuns(unsigned bidiLevel, BidiRunList<BidiRun>&, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun, WordMeasurements&);
465     void layoutRunsAndFloats(LineLayoutState&);
466     const InlineIterator& restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight,  FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver&,  const InlineIterator&);
467     void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines);
468     void linkToEndLineIfNeeded(LineLayoutState&);
469     static void repaintDirtyFloats(Vector<FloatWithRect>& floats);
470     void checkFloatsInCleanLine(RootInlineBox*, Vector<FloatWithRect>&, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat);
471     RootInlineBox* determineStartPosition(LineLayoutState&, InlineBidiResolver&);
472     void determineEndPosition(LineLayoutState&, RootInlineBox* startBox, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus);
473     bool checkPaginationAndFloatsAtEndLine(LineLayoutState&);
474     bool matchedEndLine(LineLayoutState&, const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus);
475     void deleteEllipsisLineBoxes();
476     void checkLinesForTextOverflow();
477     // Positions new floats and also adjust all floats encountered on the line if any of them
478     // have to move to the next page/column.
479     bool positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo&, LineWidth&);
480 
481 
482 // END METHODS DEFINED IN RenderBlockLineLayout
483 
484 };
485 
486 DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderBlockFlow, isRenderBlockFlow());
487 
488 } // namespace WebCore
489 
490 #endif // RenderBlockFlow_h
491