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 "FloatingObjects.h"
27#include "RenderBlock.h"
28#include "RenderLineBoxList.h"
29#include "SimpleLineLayout.h"
30#include "TrailingObjects.h"
31#include <memory>
32
33namespace WebCore {
34
35class LayoutStateMaintainer;
36class LineBreaker;
37class LineInfo;
38class LineWidth;
39class RenderMultiColumnFlowThread;
40class RenderNamedFlowFragment;
41class RenderRubyRun;
42
43struct FloatWithRect;
44struct WordMeasurement;
45
46template <class Run> class BidiRunList;
47typedef Vector<WordMeasurement, 64> WordMeasurements;
48
49#if ENABLE(IOS_TEXT_AUTOSIZING)
50enum LineCount {
51    NOT_SET = 0, NO_LINE = 1, ONE_LINE = 2, MULTI_LINE = 3
52};
53#endif
54
55class RenderBlockFlow : public RenderBlock {
56public:
57    RenderBlockFlow(Element&, PassRef<RenderStyle>);
58    RenderBlockFlow(Document&, PassRef<RenderStyle>);
59    virtual ~RenderBlockFlow();
60
61    virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) override;
62
63protected:
64    virtual void insertedIntoTree() override;
65    virtual void willBeDestroyed() override;
66
67    // This method is called at the start of layout to wipe away all of the floats in our floating objects list. It also
68    // repopulates the list with any floats that intrude from previous siblings or parents. Floats that were added by
69    // descendants are gone when this call completes and will get added back later on after the children have gotten
70    // a relayout.
71    void rebuildFloatingObjectSetFromIntrudingFloats();
72
73    // RenderBlockFlow always contains either lines or paragraphs. When the children are all blocks (e.g. paragraphs), we call layoutBlockChildren.
74    // When the children are are all inline (e.g., lines), we call layoutInlineChildren.
75    void layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloatLogicalBottom);
76    void layoutInlineChildren(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom);
77
78    // RenderBlockFlows override these methods, since they are the only class that supports margin collapsing.
79    virtual LayoutUnit collapsedMarginBefore() const override final { return maxPositiveMarginBefore() - maxNegativeMarginBefore(); }
80    virtual LayoutUnit collapsedMarginAfter() const override final { return maxPositiveMarginAfter() - maxNegativeMarginAfter(); }
81
82    virtual void dirtyLinesFromChangedChild(RenderObject* child) override final { lineBoxes().dirtyLinesFromChangedChild(this, child); }
83    virtual void updateLogicalHeight() override;
84
85    virtual void paintColumnRules(PaintInfo&, const LayoutPoint&) override;
86
87public:
88    class MarginValues {
89    public:
90        MarginValues(LayoutUnit beforePos, LayoutUnit beforeNeg, LayoutUnit afterPos, LayoutUnit afterNeg)
91            : m_positiveMarginBefore(beforePos)
92            , m_negativeMarginBefore(beforeNeg)
93            , m_positiveMarginAfter(afterPos)
94            , m_negativeMarginAfter(afterNeg)
95        {
96        }
97
98        LayoutUnit positiveMarginBefore() const { return m_positiveMarginBefore; }
99        LayoutUnit negativeMarginBefore() const { return m_negativeMarginBefore; }
100        LayoutUnit positiveMarginAfter() const { return m_positiveMarginAfter; }
101        LayoutUnit negativeMarginAfter() const { return m_negativeMarginAfter; }
102
103        void setPositiveMarginBefore(LayoutUnit pos) { m_positiveMarginBefore = pos; }
104        void setNegativeMarginBefore(LayoutUnit neg) { m_negativeMarginBefore = neg; }
105        void setPositiveMarginAfter(LayoutUnit pos) { m_positiveMarginAfter = pos; }
106        void setNegativeMarginAfter(LayoutUnit neg) { m_negativeMarginAfter = neg; }
107
108    private:
109        LayoutUnit m_positiveMarginBefore;
110        LayoutUnit m_negativeMarginBefore;
111        LayoutUnit m_positiveMarginAfter;
112        LayoutUnit m_negativeMarginAfter;
113    };
114    MarginValues marginValuesForChild(RenderBox& child) const;
115
116    // Allocated only when some of these fields have non-default values
117    struct RenderBlockFlowRareData {
118        WTF_MAKE_NONCOPYABLE(RenderBlockFlowRareData); WTF_MAKE_FAST_ALLOCATED;
119    public:
120        RenderBlockFlowRareData(const RenderBlockFlow& block)
121            : m_margins(positiveMarginBeforeDefault(block), negativeMarginBeforeDefault(block), positiveMarginAfterDefault(block), negativeMarginAfterDefault(block))
122            , m_lineBreakToAvoidWidow(-1)
123            , m_renderNamedFlowFragment(nullptr)
124            , m_multiColumnFlowThread(nullptr)
125            , m_discardMarginBefore(false)
126            , m_discardMarginAfter(false)
127            , m_didBreakAtLineToAvoidWidow(false)
128        {
129        }
130
131        ~RenderBlockFlowRareData()
132        {
133        }
134
135        static LayoutUnit positiveMarginBeforeDefault(const RenderBlock& block)
136        {
137            return std::max<LayoutUnit>(block.marginBefore(), 0);
138        }
139        static LayoutUnit negativeMarginBeforeDefault(const RenderBlock& block)
140        {
141            return std::max<LayoutUnit>(-block.marginBefore(), 0);
142        }
143        static LayoutUnit positiveMarginAfterDefault(const RenderBlock& block)
144        {
145            return std::max<LayoutUnit>(block.marginAfter(), 0);
146        }
147        static LayoutUnit negativeMarginAfterDefault(const RenderBlock& block)
148        {
149            return std::max<LayoutUnit>(-block.marginAfter(), 0);
150        }
151
152        MarginValues m_margins;
153        int m_lineBreakToAvoidWidow;
154        std::unique_ptr<RootInlineBox> m_lineGridBox;
155        RenderNamedFlowFragment* m_renderNamedFlowFragment;
156
157        RenderMultiColumnFlowThread* m_multiColumnFlowThread;
158
159        bool m_discardMarginBefore : 1;
160        bool m_discardMarginAfter : 1;
161        bool m_didBreakAtLineToAvoidWidow : 1;
162    };
163
164    class MarginInfo {
165        // Collapsing flags for whether we can collapse our margins with our children's margins.
166        bool m_canCollapseWithChildren : 1;
167        bool m_canCollapseMarginBeforeWithChildren : 1;
168        bool m_canCollapseMarginAfterWithChildren : 1;
169
170        // Whether or not we are a quirky container, i.e., do we collapse away top and bottom
171        // margins in our container. Table cells and the body are the common examples. We
172        // also have a custom style property for Safari RSS to deal with TypePad blog articles.
173        bool m_quirkContainer : 1;
174
175        // This flag tracks whether we are still looking at child margins that can all collapse together at the beginning of a block.
176        // They may or may not collapse with the top margin of the block (|m_canCollapseTopWithChildren| tells us that), but they will
177        // always be collapsing with one another. This variable can remain set to true through multiple iterations
178        // as long as we keep encountering self-collapsing blocks.
179        bool m_atBeforeSideOfBlock : 1;
180
181        // This flag is set when we know we're examining bottom margins and we know we're at the bottom of the block.
182        bool m_atAfterSideOfBlock : 1;
183
184        // These variables are used to detect quirky margins that we need to collapse away (in table cells
185        // and in the body element).
186        bool m_hasMarginBeforeQuirk : 1;
187        bool m_hasMarginAfterQuirk : 1;
188        bool m_determinedMarginBeforeQuirk : 1;
189
190        bool m_discardMargin : 1;
191
192        // These flags track the previous maximal positive and negative margins.
193        LayoutUnit m_positiveMargin;
194        LayoutUnit m_negativeMargin;
195
196    public:
197        MarginInfo(RenderBlockFlow&, LayoutUnit beforeBorderPadding, LayoutUnit afterBorderPadding);
198
199        void setAtBeforeSideOfBlock(bool b) { m_atBeforeSideOfBlock = b; }
200        void setAtAfterSideOfBlock(bool b) { m_atAfterSideOfBlock = b; }
201        void clearMargin()
202        {
203            m_positiveMargin = 0;
204            m_negativeMargin = 0;
205        }
206        void setHasMarginBeforeQuirk(bool b) { m_hasMarginBeforeQuirk = b; }
207        void setHasMarginAfterQuirk(bool b) { m_hasMarginAfterQuirk = b; }
208        void setDeterminedMarginBeforeQuirk(bool b) { m_determinedMarginBeforeQuirk = b; }
209        void setPositiveMargin(LayoutUnit p) { ASSERT(!m_discardMargin); m_positiveMargin = p; }
210        void setNegativeMargin(LayoutUnit n) { ASSERT(!m_discardMargin); m_negativeMargin = n; }
211        void setPositiveMarginIfLarger(LayoutUnit p)
212        {
213            ASSERT(!m_discardMargin);
214            if (p > m_positiveMargin)
215                m_positiveMargin = p;
216        }
217        void setNegativeMarginIfLarger(LayoutUnit n)
218        {
219            ASSERT(!m_discardMargin);
220            if (n > m_negativeMargin)
221                m_negativeMargin = n;
222        }
223
224        void setMargin(LayoutUnit p, LayoutUnit n) { ASSERT(!m_discardMargin); m_positiveMargin = p; m_negativeMargin = n; }
225        void setCanCollapseMarginAfterWithChildren(bool collapse) { m_canCollapseMarginAfterWithChildren = collapse; }
226        void setDiscardMargin(bool value) { m_discardMargin = value; }
227
228        bool atBeforeSideOfBlock() const { return m_atBeforeSideOfBlock; }
229        bool canCollapseWithMarginBefore() const { return m_atBeforeSideOfBlock && m_canCollapseMarginBeforeWithChildren; }
230        bool canCollapseWithMarginAfter() const { return m_atAfterSideOfBlock && m_canCollapseMarginAfterWithChildren; }
231        bool canCollapseMarginBeforeWithChildren() const { return m_canCollapseMarginBeforeWithChildren; }
232        bool canCollapseMarginAfterWithChildren() const { return m_canCollapseMarginAfterWithChildren; }
233        bool quirkContainer() const { return m_quirkContainer; }
234        bool determinedMarginBeforeQuirk() const { return m_determinedMarginBeforeQuirk; }
235        bool hasMarginBeforeQuirk() const { return m_hasMarginBeforeQuirk; }
236        bool hasMarginAfterQuirk() const { return m_hasMarginAfterQuirk; }
237        LayoutUnit positiveMargin() const { return m_positiveMargin; }
238        LayoutUnit negativeMargin() const { return m_negativeMargin; }
239        bool discardMargin() const { return m_discardMargin; }
240        LayoutUnit margin() const { return m_positiveMargin - m_negativeMargin; }
241    };
242    LayoutUnit marginOffsetForSelfCollapsingBlock();
243
244    void layoutBlockChild(RenderBox& child, MarginInfo&, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom);
245    void adjustPositionedBlock(RenderBox& child, const MarginInfo&);
246    void adjustFloatingBlock(const MarginInfo&);
247
248    void setStaticInlinePositionForChild(RenderBox& child, LayoutUnit blockOffset, LayoutUnit inlinePosition);
249    void updateStaticInlinePositionForChild(RenderBox& child, LayoutUnit logicalTop);
250
251    LayoutUnit collapseMargins(RenderBox& child, MarginInfo&);
252    LayoutUnit clearFloatsIfNeeded(RenderBox& child, MarginInfo&, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos);
253    LayoutUnit estimateLogicalTopPosition(RenderBox& child, const MarginInfo&, LayoutUnit& estimateWithoutPagination);
254    void marginBeforeEstimateForChild(RenderBox&, LayoutUnit&, LayoutUnit&, bool&) const;
255    void handleAfterSideOfBlock(LayoutUnit top, LayoutUnit bottom, MarginInfo&);
256    void setCollapsedBottomMargin(const MarginInfo&);
257
258    bool shouldBreakAtLineToAvoidWidow() const { return hasRareBlockFlowData() && rareBlockFlowData()->m_lineBreakToAvoidWidow >= 0; }
259    void clearShouldBreakAtLineToAvoidWidow() const;
260    int lineBreakToAvoidWidow() const { return hasRareBlockFlowData() ? rareBlockFlowData()->m_lineBreakToAvoidWidow : -1; }
261    void setBreakAtLineToAvoidWidow(int);
262    void clearDidBreakAtLineToAvoidWidow();
263    void setDidBreakAtLineToAvoidWidow();
264    bool didBreakAtLineToAvoidWidow() const { return hasRareBlockFlowData() && rareBlockFlowData()->m_didBreakAtLineToAvoidWidow; }
265    bool relayoutToAvoidWidows(LayoutStateMaintainer&);
266
267    virtual bool canHaveGeneratedChildren() const override;
268
269    RootInlineBox* lineGridBox() const { return hasRareBlockFlowData() ? rareBlockFlowData()->m_lineGridBox.get() : nullptr; }
270    void setLineGridBox(std::unique_ptr<RootInlineBox> box)
271    {
272        ensureRareBlockFlowData().m_lineGridBox = WTF::move(box);
273    }
274    void layoutLineGridBox();
275
276    virtual bool canCollapseAnonymousBlockChild() const override { return !renderNamedFlowFragment(); }
277    RenderNamedFlowFragment* renderNamedFlowFragment() const { return hasRareBlockFlowData() ? rareBlockFlowData()->m_renderNamedFlowFragment : nullptr; }
278    void setRenderNamedFlowFragment(RenderNamedFlowFragment*);
279
280    RenderMultiColumnFlowThread* multiColumnFlowThread() const { return hasRareBlockFlowData() ? rareBlockFlowData()->m_multiColumnFlowThread : nullptr; }
281    void setMultiColumnFlowThread(RenderMultiColumnFlowThread*);
282
283    bool containsFloats() const override { return m_floatingObjects && !m_floatingObjects->set().isEmpty(); }
284    bool containsFloat(RenderBox&) const;
285
286    virtual void deleteLines() override;
287    virtual void computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats = false) override;
288    virtual VisiblePosition positionForPoint(const LayoutPoint&, const RenderRegion*) override;
289
290    void removeFloatingObjects();
291    void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = nullptr, bool inLayout = true);
292    void markSiblingsWithFloatsForLayout(RenderBox* floatToRemove = nullptr);
293
294    const FloatingObjectSet* floatingObjectSet() const { return m_floatingObjects ? &m_floatingObjects->set() : nullptr; }
295
296    LayoutUnit logicalTopForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->y() : floatingObject->x(); }
297    LayoutUnit logicalBottomForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->maxY() : floatingObject->maxX(); }
298    LayoutUnit logicalLeftForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->x() : floatingObject->y(); }
299    LayoutUnit logicalRightForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->maxX() : floatingObject->maxY(); }
300    LayoutUnit logicalWidthForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->width() : floatingObject->height(); }
301    LayoutUnit logicalHeightForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->height() : floatingObject->width(); }
302    LayoutSize logicalSizeForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? LayoutSize(floatingObject->width(), floatingObject->height()) : LayoutSize(floatingObject->height(), floatingObject->width()); }
303
304    int pixelSnappedLogicalTopForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->frameRect().pixelSnappedY() : floatingObject->frameRect().pixelSnappedX(); }
305    int pixelSnappedLogicalBottomForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->frameRect().pixelSnappedMaxY() : floatingObject->frameRect().pixelSnappedMaxX(); }
306    int pixelSnappedLogicalLeftForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->frameRect().pixelSnappedX() : floatingObject->frameRect().pixelSnappedY(); }
307    int pixelSnappedLogicalRightForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->frameRect().pixelSnappedMaxX() : floatingObject->frameRect().pixelSnappedMaxY(); }
308
309    void setLogicalTopForFloat(FloatingObject* floatingObject, LayoutUnit logicalTop)
310    {
311        if (isHorizontalWritingMode())
312            floatingObject->setY(logicalTop);
313        else
314            floatingObject->setX(logicalTop);
315    }
316    void setLogicalLeftForFloat(FloatingObject* floatingObject, LayoutUnit logicalLeft)
317    {
318        if (isHorizontalWritingMode())
319            floatingObject->setX(logicalLeft);
320        else
321            floatingObject->setY(logicalLeft);
322    }
323    void setLogicalHeightForFloat(FloatingObject* floatingObject, LayoutUnit logicalHeight)
324    {
325        if (isHorizontalWritingMode())
326            floatingObject->setHeight(logicalHeight);
327        else
328            floatingObject->setWidth(logicalHeight);
329    }
330    void setLogicalWidthForFloat(FloatingObject* floatingObject, LayoutUnit logicalWidth)
331    {
332        if (isHorizontalWritingMode())
333            floatingObject->setWidth(logicalWidth);
334        else
335            floatingObject->setHeight(logicalWidth);
336    }
337
338    LayoutUnit xPositionForFloatIncludingMargin(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->x() + child->renderer().marginLeft() : child->x() + marginBeforeForChild(child->renderer()); }
339    LayoutUnit yPositionForFloatIncludingMargin(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->y() + marginBeforeForChild(child->renderer()) : child->y() + child->renderer().marginTop(); }
340
341    LayoutPoint flipFloatForWritingModeForChild(const FloatingObject*, const LayoutPoint&) const;
342
343    RenderLineBoxList& lineBoxes() { return m_lineBoxes; }
344    const RenderLineBoxList& lineBoxes() const { return m_lineBoxes; }
345
346    RootInlineBox* firstRootBox() const { return toRootInlineBox(m_lineBoxes.firstLineBox()); }
347    RootInlineBox* lastRootBox() const { return toRootInlineBox(m_lineBoxes.lastLineBox()); }
348
349    virtual bool hasLines() const override final;
350    virtual void invalidateLineLayoutPath() override final;
351
352    // Helper methods for computing line counts and heights for line counts.
353    RootInlineBox* lineAtIndex(int) const;
354    int lineCount(const RootInlineBox* = nullptr, bool* = nullptr) const;
355    int heightForLineCount(int);
356    void clearTruncation();
357
358    void setHasMarkupTruncation(bool b) { m_hasMarkupTruncation = b; }
359    bool hasMarkupTruncation() const { return m_hasMarkupTruncation; }
360
361    bool containsNonZeroBidiLevel() const;
362
363    const SimpleLineLayout::Layout* simpleLineLayout() const;
364    void deleteLineBoxesBeforeSimpleLineLayout();
365    void ensureLineBoxes();
366
367#ifndef NDEBUG
368    virtual void showLineTreeAndMark(const InlineBox* = nullptr, const char* = nullptr, const InlineBox* = nullptr, const char* = nullptr, const RenderObject* = nullptr) const override;
369#endif
370
371    // Returns the logicalOffset at the top of the next page. If the offset passed in is already at the top of the current page,
372    // then nextPageLogicalTop with ExcludePageBoundary will still move to the top of the next page. nextPageLogicalTop with
373    // IncludePageBoundary set will not.
374    //
375    // 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.
376    enum PageBoundaryRule { ExcludePageBoundary, IncludePageBoundary };
377    LayoutUnit nextPageLogicalTop(LayoutUnit logicalOffset, PageBoundaryRule = ExcludePageBoundary) const;
378    LayoutUnit pageLogicalTopForOffset(LayoutUnit offset) const;
379    LayoutUnit pageLogicalHeightForOffset(LayoutUnit offset) const;
380    LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit offset, PageBoundaryRule = IncludePageBoundary) const;
381    LayoutUnit logicalHeightForChildForFragmentation(const RenderBox& child) const;
382    bool hasNextPage(LayoutUnit logicalOffset, PageBoundaryRule = ExcludePageBoundary) const;
383
384    void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) override;
385    RenderObject* removeChild(RenderObject&) override;
386
387    void createMultiColumnFlowThread();
388    void destroyMultiColumnFlowThread();
389
390    void updateColumnProgressionFromStyle(RenderStyle*);
391    void updateStylesForColumnChildren();
392
393    virtual bool needsLayoutAfterRegionRangeChange() const override;
394
395protected:
396    virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const override;
397
398    // A page break is required at some offset due to space shortage in the current fragmentainer.
399    void setPageBreak(LayoutUnit offset, LayoutUnit spaceShortage);
400
401    // Update minimum page height required to avoid fragmentation where it shouldn't occur (inside
402    // unbreakable content, between orphans and widows, etc.). This will be used as a hint to the
403    // column balancer to help set a good minimum column height.
404    void updateMinimumPageHeight(LayoutUnit offset, LayoutUnit minHeight);
405    bool pushToNextPageWithMinimumLogicalHeight(LayoutUnit& adjustment, LayoutUnit logicalOffset, LayoutUnit minimumLogicalHeight) const;
406
407    // If the child is unsplittable and can't fit on the current page, return the top of the next page/column.
408    LayoutUnit adjustForUnsplittableChild(RenderBox& child, LayoutUnit logicalOffset, bool includeMargins = false);
409    LayoutUnit adjustBlockChildForPagination(LayoutUnit logicalTopAfterClear, LayoutUnit estimateWithoutPagination, RenderBox& child, bool atBeforeSideOfBlock);
410    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.
411    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.
412
413    LayoutUnit maxPositiveMarginBefore() const { return hasRareBlockFlowData() ? rareBlockFlowData()->m_margins.positiveMarginBefore() : RenderBlockFlowRareData::positiveMarginBeforeDefault(*this); }
414    LayoutUnit maxNegativeMarginBefore() const { return hasRareBlockFlowData() ? rareBlockFlowData()->m_margins.negativeMarginBefore() : RenderBlockFlowRareData::negativeMarginBeforeDefault(*this); }
415    LayoutUnit maxPositiveMarginAfter() const { return hasRareBlockFlowData() ? rareBlockFlowData()->m_margins.positiveMarginAfter() : RenderBlockFlowRareData::positiveMarginAfterDefault(*this); }
416    LayoutUnit maxNegativeMarginAfter() const { return hasRareBlockFlowData() ? rareBlockFlowData()->m_margins.negativeMarginAfter() : RenderBlockFlowRareData::negativeMarginAfterDefault(*this); }
417
418    void initMaxMarginValues()
419    {
420        if (!hasRareBlockFlowData())
421            return;
422
423        rareBlockFlowData()->m_margins = MarginValues(RenderBlockFlowRareData::positiveMarginBeforeDefault(*this) , RenderBlockFlowRareData::negativeMarginBeforeDefault(*this),
424            RenderBlockFlowRareData::positiveMarginAfterDefault(*this), RenderBlockFlowRareData::negativeMarginAfterDefault(*this));
425        rareBlockFlowData()->m_discardMarginBefore = false;
426        rareBlockFlowData()->m_discardMarginAfter = false;
427    }
428
429    void setMaxMarginBeforeValues(LayoutUnit pos, LayoutUnit neg);
430    void setMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg);
431
432    void setMustDiscardMarginBefore(bool = true);
433    void setMustDiscardMarginAfter(bool = true);
434
435    bool mustDiscardMarginBefore() const;
436    bool mustDiscardMarginAfter() const;
437
438    bool mustDiscardMarginBeforeForChild(const RenderBox&) const;
439    bool mustDiscardMarginAfterForChild(const RenderBox&) const;
440    bool mustSeparateMarginBeforeForChild(const RenderBox&) const;
441    bool mustSeparateMarginAfterForChild(const RenderBox&) const;
442
443    virtual void styleWillChange(StyleDifference, const RenderStyle& newStyle) override;
444    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override;
445
446    void createFloatingObjects();
447
448    virtual int firstLineBaseline() const override;
449    virtual int inlineBlockBaseline(LineDirectionMode) const override;
450
451    virtual bool isMultiColumnBlockFlow() const override { return multiColumnFlowThread(); }
452
453    void setComputedColumnCountAndWidth(int, LayoutUnit);
454
455    LayoutUnit computedColumnWidth() const;
456    unsigned computedColumnCount() const;
457
458    bool isTopLayoutOverflowAllowed() const override;
459    bool isLeftLayoutOverflowAllowed() const override;
460
461    void moveFloatsTo(RenderBlockFlow* toBlock);
462
463    virtual void computeColumnCountAndWidth();
464    virtual bool requiresColumns(int) const;
465
466private:
467    bool recomputeLogicalWidthAndColumnWidth();
468    LayoutUnit columnGap() const;
469
470    // Called to lay out the legend for a fieldset or the ruby text of a ruby run. Also used by multi-column layout to handle
471    // the flow thread child.
472    virtual RenderObject* layoutSpecialExcludedChild(bool /*relayoutChildren*/);
473
474    void checkForPaginationLogicalHeightChange(bool& relayoutChildren, LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged);
475
476    virtual void paintInlineChildren(PaintInfo&, const LayoutPoint&) override;
477    virtual void paintFloats(PaintInfo&, const LayoutPoint&, bool preservePhase = false) override;
478
479    virtual void moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert) override;
480    virtual void repaintOverhangingFloats(bool paintAllDescendants) override final;
481    virtual void clipOutFloatingObjects(RenderBlock&, const PaintInfo*, const LayoutPoint&, const LayoutSize&) override;
482
483    FloatingObject* insertFloatingObject(RenderBox&);
484    void removeFloatingObject(RenderBox&);
485    void removeFloatingObjectsBelow(FloatingObject*, int logicalOffset);
486    LayoutPoint computeLogicalLocationForFloat(const FloatingObject*, LayoutUnit logicalTopOffset) const;
487
488    // Called from lineWidth, to position the floats added in the last line.
489    // Returns true if and only if it has positioned any floats.
490    bool positionNewFloats();
491
492    void clearFloats(EClear);
493
494    virtual LayoutUnit logicalRightFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit logicalHeight) const override;
495    virtual LayoutUnit logicalLeftFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit logicalHeight) const override;
496
497    LayoutUnit logicalRightOffsetForPositioningFloat(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const;
498    LayoutUnit logicalLeftOffsetForPositioningFloat(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const;
499
500    LayoutUnit lowestFloatLogicalBottom(FloatingObject::Type = FloatingObject::FloatLeftRight) const;
501    LayoutUnit nextFloatLogicalBottomBelow(LayoutUnit) const;
502    LayoutUnit nextFloatLogicalBottomBelowForBlock(LayoutUnit) const;
503
504    LayoutUnit addOverhangingFloats(RenderBlockFlow& child, bool makeChildPaintOtherFloats);
505    bool hasOverhangingFloat(RenderBox&);
506    void addIntrudingFloats(RenderBlockFlow* prev, LayoutUnit xoffset, LayoutUnit yoffset);
507    bool hasOverhangingFloats() { return parent() && containsFloats() && lowestFloatLogicalBottom() > logicalHeight(); }
508    LayoutUnit getClearDelta(RenderBox& child, LayoutUnit yPos);
509
510    void determineLogicalLeftPositionForChild(RenderBox& child, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
511
512    virtual bool hitTestFloats(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) override;
513    virtual bool hitTestInlineChildren(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
514
515    void addOverflowFromFloats();
516    virtual void addOverflowFromInlineChildren();
517
518    void fitBorderToLinesIfNeeded(); // Shrink the box in which the border paints if border-fit is set.
519    void adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const;
520
521    void markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit logicalBottom, RootInlineBox* highest = 0);
522
523    virtual GapRects inlineSelectionGaps(RenderBlock& rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
524        LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches&, const PaintInfo*) override;
525
526    Position positionForBox(InlineBox*, bool start = true) const;
527    virtual VisiblePosition positionForPointWithInlineChildren(const LayoutPoint& pointInLogicalContents, const RenderRegion*) override;
528    virtual void addFocusRingRectsForInlineChildren(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject*) override;
529
530// FIXME-BLOCKFLOW: These methods have implementations in
531// RenderBlockLineLayout. They should be moved to the proper header once the
532// line layout code is separated from RenderBlock and RenderBlockFlow.
533// START METHODS DEFINED IN RenderBlockLineLayout
534public:
535    static void appendRunsForObject(BidiRunList<BidiRun>&, int start, int end, RenderObject*, InlineBidiResolver&);
536    RootInlineBox* createAndAppendRootInlineBox();
537
538    LayoutUnit startAlignedOffsetForLine(LayoutUnit position, bool shouldIndentText);
539    virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const;
540    virtual void adjustInlineDirectionLineBounds(int /* expansionOpportunityCount */, float& /* logicalLeft */, float& /* logicalWidth */) const { }
541
542private:
543    void adjustIntrinsicLogicalWidthsForColumns(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const;
544
545    void layoutLineBoxes(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom);
546    void layoutSimpleLines(LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom);
547
548    virtual std::unique_ptr<RootInlineBox> createRootInlineBox(); // Subclassed by RenderSVGText.
549    InlineFlowBox* createLineBoxes(RenderObject*, const LineInfo&, InlineBox* childBox);
550    RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
551    void setMarginsForRubyRun(BidiRun*, RenderRubyRun&, RenderObject*, const LineInfo&);
552    void computeInlineDirectionPositionsForLine(RootInlineBox*, const LineInfo&, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&, WordMeasurements&);
553    BidiRun* computeInlineDirectionPositionsForSegment(RootInlineBox*, const LineInfo&, ETextAlign, float& logicalLeft,
554        float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache&, WordMeasurements&);
555    void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&);
556    BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>&, BidiContext*);
557    void appendFloatingObjectToLastLine(FloatingObject*);
558    // Helper function for layoutInlineChildren()
559    RootInlineBox* createLineBoxesFromBidiRuns(unsigned bidiLevel, BidiRunList<BidiRun>&, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun, WordMeasurements&);
560    void layoutRunsAndFloats(LineLayoutState&, bool hasInlineChild);
561    const InlineIterator& restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight,  FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver&,  const InlineIterator&);
562    void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines);
563    void linkToEndLineIfNeeded(LineLayoutState&);
564    static void repaintDirtyFloats(Vector<FloatWithRect>& floats);
565    void checkFloatsInCleanLine(RootInlineBox*, Vector<FloatWithRect>&, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat);
566    RootInlineBox* determineStartPosition(LineLayoutState&, InlineBidiResolver&);
567    void determineEndPosition(LineLayoutState&, RootInlineBox* startBox, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus);
568    bool checkPaginationAndFloatsAtEndLine(LineLayoutState&);
569    bool matchedEndLine(LineLayoutState&, const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus);
570    void deleteEllipsisLineBoxes();
571    void checkLinesForTextOverflow();
572    // Positions new floats and also adjust all floats encountered on the line if any of them
573    // have to move to the next page/column.
574    bool positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo&, LineWidth&);
575    // 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
576    // region/page/column that has a different available line width than the old one. Used to know when you have to dirty a
577    // line, i.e., that it can't be re-used.
578    bool lineWidthForPaginatedLineChanged(RootInlineBox*, LayoutUnit lineDelta, RenderFlowThread*) const;
579    void updateLogicalWidthForAlignment(const ETextAlign&, const RootInlineBox*, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, int expansionOpportunityCount);
580
581// END METHODS DEFINED IN RenderBlockLineLayout
582
583    bool namedFlowFragmentNeedsUpdate() const;
584    virtual bool canHaveChildren() const override;
585
586#if ENABLE(IOS_TEXT_AUTOSIZING)
587    int m_widthForTextAutosizing;
588    unsigned m_lineCountForTextAutosizing : 2;
589#endif
590
591public:
592    // FIXME-BLOCKFLOW: These can be made protected again once all callers have been moved here.
593    void adjustLinePositionForPagination(RootInlineBox*, LayoutUnit& deltaOffset, bool& overflowsRegion, 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.
594    void updateRegionForLine(RootInlineBox*) const;
595    void createRenderNamedFlowFragmentIfNeeded();
596
597    // Pagination routines.
598    bool relayoutForPagination(LayoutStateMaintainer&);
599
600    bool hasRareBlockFlowData() const { return m_rareBlockFlowData.get(); }
601    RenderBlockFlowRareData* rareBlockFlowData() const { ASSERT_WITH_SECURITY_IMPLICATION(hasRareBlockFlowData()); return m_rareBlockFlowData.get(); }
602    RenderBlockFlowRareData& ensureRareBlockFlowData();
603    void materializeRareBlockFlowData();
604
605#if ENABLE(IOS_TEXT_AUTOSIZING)
606    int lineCountForTextAutosizing();
607    void adjustComputedFontSizes(float size, float visibleWidth);
608    void resetComputedFontSize()
609    {
610        m_widthForTextAutosizing = -1;
611        m_lineCountForTextAutosizing = NOT_SET;
612    }
613#endif
614
615protected:
616    std::unique_ptr<FloatingObjects> m_floatingObjects;
617    std::unique_ptr<RenderBlockFlowRareData> m_rareBlockFlowData;
618    RenderLineBoxList m_lineBoxes;
619    std::unique_ptr<SimpleLineLayout::Layout> m_simpleLineLayout;
620
621    friend class LineBreaker;
622    friend class LineWidth; // Needs to know FloatingObject
623};
624
625RENDER_OBJECT_TYPE_CASTS(RenderBlockFlow, isRenderBlockFlow())
626
627inline bool RenderElement::isRenderNamedFlowFragmentContainer() const
628{
629    return isRenderBlockFlow() && toRenderBlockFlow(this)->renderNamedFlowFragment();
630}
631
632inline const SimpleLineLayout::Layout* RenderBlockFlow::simpleLineLayout() const
633{
634    ASSERT(m_lineLayoutPath == SimpleLinesPath || !m_simpleLineLayout);
635    return m_simpleLineLayout.get();
636}
637
638} // namespace WebCore
639
640#endif // RenderBlockFlow_h
641