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