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
44namespace blink {
45
46class MarginInfo;
47class LineBreaker;
48class LineWidth;
49class RenderMultiColumnFlowThread;
50
51class RenderBlockFlow : public RenderBlock {
52public:
53    explicit RenderBlockFlow(ContainerNode*);
54    virtual ~RenderBlockFlow();
55    virtual void trace(Visitor*) OVERRIDE;
56
57    static RenderBlockFlow* createAnonymous(Document*);
58
59    virtual bool isRenderBlockFlow() const OVERRIDE FINAL { return true; }
60
61    virtual void layoutBlock(bool relayoutChildren) OVERRIDE;
62
63    virtual void computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats = false) OVERRIDE;
64
65    virtual void deleteLineBoxTree() OVERRIDE FINAL;
66
67    LayoutUnit availableLogicalWidthForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
68    {
69        return max<LayoutUnit>(0, logicalRightOffsetForLine(position, shouldIndentText, logicalHeight) - logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight));
70    }
71    LayoutUnit logicalRightOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
72    {
73        return logicalRightOffsetForLine(position, logicalRightOffsetForContent(), shouldIndentText, logicalHeight);
74    }
75    LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
76    {
77        return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(), shouldIndentText, logicalHeight);
78    }
79    LayoutUnit startOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
80    {
81        return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight)
82            : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, logicalHeight);
83    }
84    LayoutUnit endOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
85    {
86        return !style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight)
87            : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, logicalHeight);
88    }
89
90    // FIXME-BLOCKFLOW: Move this into RenderBlockFlow once there are no calls
91    // in RenderBlock. http://crbug.com/393945, http://crbug.com/302024
92    using RenderBlock::lineBoxes;
93    using RenderBlock::firstLineBox;
94    using RenderBlock::lastLineBox;
95    using RenderBlock::firstRootBox;
96    using RenderBlock::lastRootBox;
97
98    virtual LayoutUnit logicalLeftSelectionOffset(const RenderBlock* rootBlock, LayoutUnit position) const OVERRIDE;
99    virtual LayoutUnit logicalRightSelectionOffset(const RenderBlock* rootBlock, LayoutUnit position) const OVERRIDE;
100
101    RootInlineBox* createAndAppendRootInlineBox();
102
103    void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true);
104    void markSiblingsWithFloatsForLayout(RenderBox* floatToRemove = 0);
105
106    bool containsFloats() const { return m_floatingObjects && !m_floatingObjects->set().isEmpty(); }
107    bool containsFloat(RenderBox*) const;
108
109    void removeFloatingObjects();
110
111    virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE;
112
113    void moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert);
114
115    bool generatesLineBoxesForInlineChild(RenderObject*);
116
117    LayoutUnit logicalTopForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->y() : floatingObject->x(); }
118    LayoutUnit logicalBottomForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->maxY() : floatingObject->maxX(); }
119    LayoutUnit logicalLeftForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->x() : floatingObject->y(); }
120    LayoutUnit logicalRightForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->maxX() : floatingObject->maxY(); }
121    LayoutUnit logicalWidthForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->width() : floatingObject->height(); }
122    LayoutUnit logicalHeightForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->height() : floatingObject->width(); }
123    LayoutSize logicalSizeForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? LayoutSize(floatingObject->width(), floatingObject->height()) : LayoutSize(floatingObject->height(), floatingObject->width()); }
124
125    int pixelSnappedLogicalTopForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->frameRect().pixelSnappedY() : floatingObject->frameRect().pixelSnappedX(); }
126    int pixelSnappedLogicalBottomForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->frameRect().pixelSnappedMaxY() : floatingObject->frameRect().pixelSnappedMaxX(); }
127    int pixelSnappedLogicalLeftForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->frameRect().pixelSnappedX() : floatingObject->frameRect().pixelSnappedY(); }
128    int pixelSnappedLogicalRightForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->frameRect().pixelSnappedMaxX() : floatingObject->frameRect().pixelSnappedMaxY(); }
129
130    void setLogicalTopForFloat(FloatingObject* floatingObject, LayoutUnit logicalTop)
131    {
132        if (isHorizontalWritingMode())
133            floatingObject->setY(logicalTop);
134        else
135            floatingObject->setX(logicalTop);
136    }
137    void setLogicalLeftForFloat(FloatingObject* floatingObject, LayoutUnit logicalLeft)
138    {
139        if (isHorizontalWritingMode())
140            floatingObject->setX(logicalLeft);
141        else
142            floatingObject->setY(logicalLeft);
143    }
144    void setLogicalHeightForFloat(FloatingObject* floatingObject, LayoutUnit logicalHeight)
145    {
146        if (isHorizontalWritingMode())
147            floatingObject->setHeight(logicalHeight);
148        else
149            floatingObject->setWidth(logicalHeight);
150    }
151    void setLogicalWidthForFloat(FloatingObject* floatingObject, LayoutUnit logicalWidth)
152    {
153        if (isHorizontalWritingMode())
154            floatingObject->setWidth(logicalWidth);
155        else
156            floatingObject->setHeight(logicalWidth);
157    }
158
159    LayoutUnit startAlignedOffsetForLine(LayoutUnit position, bool shouldIndentText);
160
161    void setStaticInlinePositionForChild(RenderBox*, LayoutUnit inlinePosition);
162    void updateStaticInlinePositionForChild(RenderBox*, LayoutUnit logicalTop);
163
164    static bool shouldSkipCreatingRunsForObject(RenderObject* obj)
165    {
166        return obj->isFloating() || (obj->isOutOfFlowPositioned() && !obj->style()->isOriginalDisplayInlineType() && !obj->container()->isRenderInline());
167    }
168
169    RenderMultiColumnFlowThread* multiColumnFlowThread() const { return m_rareData ? m_rareData->m_multiColumnFlowThread.get() : 0; }
170    void resetMultiColumnFlowThread()
171    {
172        if (m_rareData)
173            m_rareData->m_multiColumnFlowThread = nullptr;
174    }
175
176    void addOverflowFromInlineChildren();
177
178    // FIXME: This should be const to avoid a const_cast, but can modify child dirty bits and RenderCombineText
179    void computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth);
180
181    GapRects inlineSelectionGaps(const RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
182        LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo*) const;
183
184    LayoutUnit paginationStrut() const { return m_rareData ? m_rareData->m_paginationStrut : LayoutUnit(); }
185    void setPaginationStrut(LayoutUnit);
186
187    virtual bool avoidsFloats() const OVERRIDE;
188
189    LayoutUnit xPositionForFloatIncludingMargin(const FloatingObject* child) const
190    {
191        if (isHorizontalWritingMode())
192            return child->x() + child->renderer()->marginLeft();
193
194        return child->x() + marginBeforeForChild(child->renderer());
195    }
196
197    LayoutUnit yPositionForFloatIncludingMargin(const FloatingObject* child) const
198    {
199        if (isHorizontalWritingMode())
200            return child->y() + marginBeforeForChild(child->renderer());
201
202        return child->y() + child->renderer()->marginTop();
203    }
204
205    LayoutPoint flipFloatForWritingModeForChild(const FloatingObject*, const LayoutPoint&) const;
206
207protected:
208    void rebuildFloatsFromIntruding();
209    void layoutInlineChildren(bool relayoutChildren, LayoutUnit& paintInvalidationLogicalTop, LayoutUnit& paintInvalidationLogicalBottom, LayoutUnit afterEdge);
210
211    void createFloatingObjects();
212
213    virtual void styleWillChange(StyleDifference, const RenderStyle& newStyle) OVERRIDE;
214    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
215
216    void addOverflowFromFloats();
217
218    LayoutUnit logicalRightOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit logicalHeight = 0) const
219    {
220        return adjustLogicalRightOffsetForLine(logicalRightFloatOffsetForLine(logicalTop, fixedOffset, logicalHeight), applyTextIndent);
221    }
222    LayoutUnit logicalLeftOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit logicalHeight = 0) const
223    {
224        return adjustLogicalLeftOffsetForLine(logicalLeftFloatOffsetForLine(logicalTop, fixedOffset, logicalHeight), applyTextIndent);
225    }
226
227    virtual RenderObject* layoutSpecialExcludedChild(bool /*relayoutChildren*/, SubtreeLayoutScope&);
228    virtual bool updateLogicalWidthAndColumnWidth() OVERRIDE;
229
230    void setLogicalLeftForChild(RenderBox* child, LayoutUnit logicalLeft);
231    void setLogicalTopForChild(RenderBox* child, LayoutUnit logicalTop);
232    void determineLogicalLeftPositionForChild(RenderBox* child);
233
234private:
235    bool layoutBlockFlow(bool relayoutChildren, LayoutUnit& pageLogicalHeight, SubtreeLayoutScope&);
236    void layoutBlockChildren(bool relayoutChildren, SubtreeLayoutScope&, LayoutUnit beforeEdge, LayoutUnit afterEdge);
237
238    void layoutBlockChild(RenderBox* child, MarginInfo&, LayoutUnit& previousFloatLogicalBottom);
239    void adjustPositionedBlock(RenderBox* child, const MarginInfo&);
240    void adjustFloatingBlock(const MarginInfo&);
241
242    LayoutPoint computeLogicalLocationForFloat(const FloatingObject*, LayoutUnit logicalTopOffset) const;
243
244    FloatingObject* insertFloatingObject(RenderBox*);
245    void removeFloatingObject(RenderBox*);
246    void removeFloatingObjectsBelow(FloatingObject*, int logicalOffset);
247
248    // Called from lineWidth, to position the floats added in the last line.
249    // Returns true if and only if it has positioned any floats.
250    bool positionNewFloats();
251
252    LayoutUnit getClearDelta(RenderBox* child, LayoutUnit yPos);
253
254    bool hasOverhangingFloats() { return parent() && !hasColumns() && containsFloats() && lowestFloatLogicalBottom() > logicalHeight(); }
255    bool hasOverhangingFloat(RenderBox*);
256    void addIntrudingFloats(RenderBlockFlow* prev, LayoutUnit xoffset, LayoutUnit yoffset);
257    void addOverhangingFloats(RenderBlockFlow* child, bool makeChildPaintOtherFloats);
258
259    LayoutUnit lowestFloatLogicalBottom(FloatingObject::Type = FloatingObject::FloatLeftRight) const;
260    LayoutUnit nextFloatLogicalBottomBelow(LayoutUnit, ShapeOutsideFloatOffsetMode = ShapeOutsideFloatMarginBoxOffset) const;
261
262    virtual bool hitTestFloats(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) OVERRIDE FINAL;
263
264    virtual void invalidatePaintForOverhangingFloats(bool paintAllDescendants) OVERRIDE FINAL;
265    virtual void invalidatePaintForOverflow() OVERRIDE FINAL;
266    virtual void paintFloats(PaintInfo&, const LayoutPoint&, bool preservePhase = false) OVERRIDE FINAL;
267    virtual void clipOutFloatingObjects(const RenderBlock*, const PaintInfo*, const LayoutPoint&, const LayoutSize&) const OVERRIDE;
268    void clearFloats(EClear);
269
270    LayoutUnit logicalRightFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit logicalHeight) const;
271    LayoutUnit logicalLeftFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit logicalHeight) const;
272
273    LayoutUnit logicalRightOffsetForPositioningFloat(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const;
274    LayoutUnit logicalLeftOffsetForPositioningFloat(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const;
275
276    LayoutUnit adjustLogicalRightOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const;
277    LayoutUnit adjustLogicalLeftOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const;
278
279    void fitBorderToLinesIfNeeded(); // Shrink the box in which the border paints if border-fit is set.
280    void adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const; // Helper function for borderFitAdjust
281
282    virtual RootInlineBox* createRootInlineBox(); // Subclassed by SVG
283
284    bool isPagedOverflow(const RenderStyle*);
285
286    enum FlowThreadType {
287        NoFlowThread,
288        MultiColumnFlowThread,
289        PagedFlowThread
290    };
291
292    FlowThreadType flowThreadType(const RenderStyle*);
293
294    RenderMultiColumnFlowThread* createMultiColumnFlowThread(FlowThreadType);
295    void createOrDestroyMultiColumnFlowThreadIfNeeded(const RenderStyle* oldStyle);
296
297    void updateLogicalWidthForAlignment(const ETextAlign&, const RootInlineBox*, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, unsigned expansionOpportunityCount);
298    void checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight);
299    bool shouldRelayoutForPagination(LayoutUnit& pageLogicalHeight, LayoutUnit layoutOverflowLogicalBottom) const;
300    void setColumnCountAndHeight(unsigned count, LayoutUnit pageLogicalHeight);
301
302    bool shouldBreakAtLineToAvoidWidow() const { return m_rareData && m_rareData->m_lineBreakToAvoidWidow >= 0; }
303    void clearShouldBreakAtLineToAvoidWidow() const;
304    int lineBreakToAvoidWidow() const { return m_rareData ? m_rareData->m_lineBreakToAvoidWidow : -1; }
305    void setBreakAtLineToAvoidWidow(int);
306    void clearDidBreakAtLineToAvoidWidow();
307    void setDidBreakAtLineToAvoidWidow();
308    bool didBreakAtLineToAvoidWidow() const { return m_rareData && m_rareData->m_didBreakAtLineToAvoidWidow; }
309
310public:
311    struct FloatWithRect {
312        FloatWithRect(RenderBox* f)
313            : object(f)
314            , rect(LayoutRect(f->x() - f->marginLeft(), f->y() - f->marginTop(), f->width() + f->marginWidth(), f->height() + f->marginHeight()))
315            , everHadLayout(f->everHadLayout())
316        {
317        }
318
319        RenderBox* object;
320        LayoutRect rect;
321        bool everHadLayout;
322    };
323
324    class MarginValues {
325    public:
326        MarginValues(LayoutUnit beforePos, LayoutUnit beforeNeg, LayoutUnit afterPos, LayoutUnit afterNeg)
327            : m_positiveMarginBefore(beforePos)
328            , m_negativeMarginBefore(beforeNeg)
329            , m_positiveMarginAfter(afterPos)
330            , m_negativeMarginAfter(afterNeg)
331        { }
332
333        LayoutUnit positiveMarginBefore() const { return m_positiveMarginBefore; }
334        LayoutUnit negativeMarginBefore() const { return m_negativeMarginBefore; }
335        LayoutUnit positiveMarginAfter() const { return m_positiveMarginAfter; }
336        LayoutUnit negativeMarginAfter() const { return m_negativeMarginAfter; }
337
338        void setPositiveMarginBefore(LayoutUnit pos) { m_positiveMarginBefore = pos; }
339        void setNegativeMarginBefore(LayoutUnit neg) { m_negativeMarginBefore = neg; }
340        void setPositiveMarginAfter(LayoutUnit pos) { m_positiveMarginAfter = pos; }
341        void setNegativeMarginAfter(LayoutUnit neg) { m_negativeMarginAfter = neg; }
342
343    private:
344        LayoutUnit m_positiveMarginBefore;
345        LayoutUnit m_negativeMarginBefore;
346        LayoutUnit m_positiveMarginAfter;
347        LayoutUnit m_negativeMarginAfter;
348    };
349    MarginValues marginValuesForChild(RenderBox* child) const;
350
351    // Allocated only when some of these fields have non-default values
352    struct RenderBlockFlowRareData : public NoBaseWillBeGarbageCollected<RenderBlockFlowRareData> {
353        WTF_MAKE_NONCOPYABLE(RenderBlockFlowRareData); WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED;
354    public:
355        RenderBlockFlowRareData(const RenderBlockFlow* block)
356            : m_margins(positiveMarginBeforeDefault(block), negativeMarginBeforeDefault(block), positiveMarginAfterDefault(block), negativeMarginAfterDefault(block))
357            , m_paginationStrut(0)
358            , m_multiColumnFlowThread(nullptr)
359            , m_lineBreakToAvoidWidow(-1)
360            , m_didBreakAtLineToAvoidWidow(false)
361            , m_discardMarginBefore(false)
362            , m_discardMarginAfter(false)
363        {
364        }
365        void trace(Visitor*);
366
367        static LayoutUnit positiveMarginBeforeDefault(const RenderBlockFlow* block)
368        {
369            return std::max<LayoutUnit>(block->marginBefore(), 0);
370        }
371        static LayoutUnit negativeMarginBeforeDefault(const RenderBlockFlow* block)
372        {
373            return std::max<LayoutUnit>(-block->marginBefore(), 0);
374        }
375        static LayoutUnit positiveMarginAfterDefault(const RenderBlockFlow* block)
376        {
377            return std::max<LayoutUnit>(block->marginAfter(), 0);
378        }
379        static LayoutUnit negativeMarginAfterDefault(const RenderBlockFlow* block)
380        {
381            return std::max<LayoutUnit>(-block->marginAfter(), 0);
382        }
383
384        MarginValues m_margins;
385        LayoutUnit m_paginationStrut;
386
387        RawPtrWillBeMember<RenderMultiColumnFlowThread> m_multiColumnFlowThread;
388
389        int m_lineBreakToAvoidWidow;
390        bool m_didBreakAtLineToAvoidWidow : 1;
391        bool m_discardMarginBefore : 1;
392        bool m_discardMarginAfter : 1;
393    };
394    LayoutUnit marginOffsetForSelfCollapsingBlock();
395
396    FloatingObjects* floatingObjects() { return m_floatingObjects.get(); }
397
398
399protected:
400    LayoutUnit maxPositiveMarginBefore() const { return m_rareData ? m_rareData->m_margins.positiveMarginBefore() : RenderBlockFlowRareData::positiveMarginBeforeDefault(this); }
401    LayoutUnit maxNegativeMarginBefore() const { return m_rareData ? m_rareData->m_margins.negativeMarginBefore() : RenderBlockFlowRareData::negativeMarginBeforeDefault(this); }
402    LayoutUnit maxPositiveMarginAfter() const { return m_rareData ? m_rareData->m_margins.positiveMarginAfter() : RenderBlockFlowRareData::positiveMarginAfterDefault(this); }
403    LayoutUnit maxNegativeMarginAfter() const { return m_rareData ? m_rareData->m_margins.negativeMarginAfter() : RenderBlockFlowRareData::negativeMarginAfterDefault(this); }
404
405    void setMaxMarginBeforeValues(LayoutUnit pos, LayoutUnit neg);
406    void setMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg);
407
408    void setMustDiscardMarginBefore(bool = true);
409    void setMustDiscardMarginAfter(bool = true);
410
411    bool mustDiscardMarginBefore() const;
412    bool mustDiscardMarginAfter() const;
413
414    bool mustDiscardMarginBeforeForChild(const RenderBox*) const;
415    bool mustDiscardMarginAfterForChild(const RenderBox*) const;
416
417    bool mustSeparateMarginBeforeForChild(const RenderBox*) const;
418    bool mustSeparateMarginAfterForChild(const RenderBox*) const;
419
420    void initMaxMarginValues()
421    {
422        if (m_rareData) {
423            m_rareData->m_margins = MarginValues(RenderBlockFlowRareData::positiveMarginBeforeDefault(this) , RenderBlockFlowRareData::negativeMarginBeforeDefault(this),
424                RenderBlockFlowRareData::positiveMarginAfterDefault(this), RenderBlockFlowRareData::negativeMarginAfterDefault(this));
425
426            m_rareData->m_discardMarginBefore = false;
427            m_rareData->m_discardMarginAfter = false;
428        }
429    }
430
431    virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const;
432private:
433    virtual LayoutUnit collapsedMarginBefore() const OVERRIDE FINAL { return maxPositiveMarginBefore() - maxNegativeMarginBefore(); }
434    virtual LayoutUnit collapsedMarginAfter() const OVERRIDE FINAL { return maxPositiveMarginAfter() - maxNegativeMarginAfter(); }
435
436    LayoutUnit collapseMargins(RenderBox* child, MarginInfo&, bool childIsSelfCollapsing);
437    LayoutUnit clearFloatsIfNeeded(RenderBox* child, MarginInfo&, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos, bool childIsSelfCollapsing);
438    LayoutUnit estimateLogicalTopPosition(RenderBox* child, const MarginInfo&, LayoutUnit& estimateWithoutPagination);
439    void marginBeforeEstimateForChild(RenderBox*, LayoutUnit&, LayoutUnit&, bool&) const;
440    void handleAfterSideOfBlock(RenderBox* lastChild, LayoutUnit top, LayoutUnit bottom, MarginInfo&);
441    void setCollapsedBottomMargin(const MarginInfo&);
442
443    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.
444    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.
445
446    LayoutUnit adjustBlockChildForPagination(LayoutUnit logicalTopAfterClear, LayoutUnit estimateWithoutPagination, RenderBox* child, bool atBeforeSideOfBlock);
447    // Computes a deltaOffset value that put a line at the top of the next page if it doesn't fit on the current page.
448    void adjustLinePositionForPagination(RootInlineBox*, LayoutUnit& deltaOffset, RenderFlowThread*);
449    // If the child is unsplittable and can't fit on the current page, return the top of the next page/column.
450    LayoutUnit adjustForUnsplittableChild(RenderBox*, LayoutUnit logicalOffset, bool includeMargins = false);
451
452    // Used to store state between styleWillChange and styleDidChange
453    static bool s_canPropagateFloatIntoSibling;
454
455    RenderBlockFlowRareData& ensureRareData();
456
457    LayoutUnit m_paintInvalidationLogicalTop;
458    LayoutUnit m_paintInvalidationLogicalBottom;
459
460    virtual bool isSelfCollapsingBlock() const OVERRIDE;
461
462protected:
463    OwnPtrWillBeMember<RenderBlockFlowRareData> m_rareData;
464    OwnPtr<FloatingObjects> m_floatingObjects;
465
466    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
467    friend class MarginInfo;
468    friend class LineBreaker;
469    friend class LineWidth; // needs to know FloatingObject
470
471// FIXME-BLOCKFLOW: These methods have implementations in
472// RenderBlockLineLayout. They should be moved to the proper header once the
473// line layout code is separated from RenderBlock and RenderBlockFlow.
474// START METHODS DEFINED IN RenderBlockLineLayout
475private:
476    InlineFlowBox* createLineBoxes(RenderObject*, const LineInfo&, InlineBox* childBox);
477    RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
478    void setMarginsForRubyRun(BidiRun*, RenderRubyRun*, RenderObject*, const LineInfo&);
479    void computeInlineDirectionPositionsForLine(RootInlineBox*, const LineInfo&, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&, WordMeasurements&);
480    BidiRun* computeInlineDirectionPositionsForSegment(RootInlineBox*, const LineInfo&, ETextAlign, float& logicalLeft,
481        float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache&, WordMeasurements&);
482    void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&);
483    BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>&, BidiContext*);
484    void appendFloatingObjectToLastLine(FloatingObject*);
485    // Helper function for layoutInlineChildren()
486    RootInlineBox* createLineBoxesFromBidiRuns(unsigned bidiLevel, BidiRunList<BidiRun>&, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun, WordMeasurements&);
487    void layoutRunsAndFloats(LineLayoutState&);
488    const InlineIterator& restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight,  FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver&,  const InlineIterator&);
489    void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&,
490        const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus);
491    void linkToEndLineIfNeeded(LineLayoutState&);
492    static void markDirtyFloatsForPaintInvalidation(Vector<FloatWithRect>& floats);
493    void checkFloatsInCleanLine(RootInlineBox*, Vector<FloatWithRect>&, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat);
494    RootInlineBox* determineStartPosition(LineLayoutState&, InlineBidiResolver&);
495    void determineEndPosition(LineLayoutState&, RootInlineBox* startBox, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus);
496    bool checkPaginationAndFloatsAtEndLine(LineLayoutState&);
497    bool matchedEndLine(LineLayoutState&, const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus);
498    void deleteEllipsisLineBoxes();
499    void checkLinesForTextOverflow();
500    // Positions new floats and also adjust all floats encountered on the line if any of them
501    // have to move to the next page/column.
502    bool positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo&, LineWidth&);
503    void positionDialog();
504
505// END METHODS DEFINED IN RenderBlockLineLayout
506
507};
508
509DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderBlockFlow, isRenderBlockFlow());
510
511} // namespace blink
512
513#endif // RenderBlockFlow_h
514