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 "FloatingObjects.h"
27 #include "RenderBlock.h"
28 #include "RenderLineBoxList.h"
29 #include "SimpleLineLayout.h"
30 #include "TrailingObjects.h"
35 class LayoutStateMaintainer;
39 class RenderMultiColumnFlowThread;
40 class RenderNamedFlowFragment;
44 struct WordMeasurement;
46 template <class Run> class BidiRunList;
47 typedef Vector<WordMeasurement, 64> WordMeasurements;
49 #if ENABLE(IOS_TEXT_AUTOSIZING)
51 NOT_SET = 0, NO_LINE = 1, ONE_LINE = 2, MULTI_LINE = 3
55 class RenderBlockFlow : public RenderBlock {
57 RenderBlockFlow(Element&, Ref<RenderStyle>&&);
58 RenderBlockFlow(Document&, Ref<RenderStyle>&&);
59 virtual ~RenderBlockFlow();
61 virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) override;
64 virtual void insertedIntoTree() override;
65 virtual void willBeDestroyed() override;
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
71 void rebuildFloatingObjectSetFromIntrudingFloats();
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);
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(); }
82 virtual void dirtyLinesFromChangedChild(RenderObject& child) override final { lineBoxes().dirtyLinesFromChangedChild(*this, child); }
83 virtual void updateLogicalHeight() override;
85 virtual void paintColumnRules(PaintInfo&, const LayoutPoint&) override;
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)
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; }
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; }
109 LayoutUnit m_positiveMarginBefore;
110 LayoutUnit m_negativeMarginBefore;
111 LayoutUnit m_positiveMarginAfter;
112 LayoutUnit m_negativeMarginAfter;
114 MarginValues marginValuesForChild(RenderBox& child) const;
116 // Allocated only when some of these fields have non-default values
117 struct RenderBlockFlowRareData {
118 WTF_MAKE_NONCOPYABLE(RenderBlockFlowRareData); WTF_MAKE_FAST_ALLOCATED;
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)
131 ~RenderBlockFlowRareData()
135 static LayoutUnit positiveMarginBeforeDefault(const RenderBlock& block)
137 return std::max<LayoutUnit>(block.marginBefore(), 0);
139 static LayoutUnit negativeMarginBeforeDefault(const RenderBlock& block)
141 return std::max<LayoutUnit>(-block.marginBefore(), 0);
143 static LayoutUnit positiveMarginAfterDefault(const RenderBlock& block)
145 return std::max<LayoutUnit>(block.marginAfter(), 0);
147 static LayoutUnit negativeMarginAfterDefault(const RenderBlock& block)
149 return std::max<LayoutUnit>(-block.marginAfter(), 0);
152 MarginValues m_margins;
153 int m_lineBreakToAvoidWidow;
154 std::unique_ptr<RootInlineBox> m_lineGridBox;
155 RenderNamedFlowFragment* m_renderNamedFlowFragment;
157 RenderMultiColumnFlowThread* m_multiColumnFlowThread;
159 bool m_discardMarginBefore : 1;
160 bool m_discardMarginAfter : 1;
161 bool m_didBreakAtLineToAvoidWidow : 1;
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;
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;
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;
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;
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;
190 bool m_discardMargin : 1;
192 // These flags track the previous maximal positive and negative margins.
193 LayoutUnit m_positiveMargin;
194 LayoutUnit m_negativeMargin;
197 MarginInfo(RenderBlockFlow&, LayoutUnit beforeBorderPadding, LayoutUnit afterBorderPadding);
199 void setAtBeforeSideOfBlock(bool b) { m_atBeforeSideOfBlock = b; }
200 void setAtAfterSideOfBlock(bool b) { m_atAfterSideOfBlock = b; }
203 m_positiveMargin = 0;
204 m_negativeMargin = 0;
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)
213 ASSERT(!m_discardMargin);
214 if (p > m_positiveMargin)
215 m_positiveMargin = p;
217 void setNegativeMarginIfLarger(LayoutUnit n)
219 ASSERT(!m_discardMargin);
220 if (n > m_negativeMargin)
221 m_negativeMargin = n;
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; }
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; }
242 LayoutUnit marginOffsetForSelfCollapsingBlock();
244 void layoutBlockChild(RenderBox& child, MarginInfo&, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom);
245 void adjustPositionedBlock(RenderBox& child, const MarginInfo&);
246 void adjustFloatingBlock(const MarginInfo&);
248 void setStaticInlinePositionForChild(RenderBox& child, LayoutUnit blockOffset, LayoutUnit inlinePosition);
249 void updateStaticInlinePositionForChild(RenderBox& child, LayoutUnit logicalTop);
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&);
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&);
267 virtual bool canHaveGeneratedChildren() const override;
269 RootInlineBox* lineGridBox() const { return hasRareBlockFlowData() ? rareBlockFlowData()->m_lineGridBox.get() : nullptr; }
270 void setLineGridBox(std::unique_ptr<RootInlineBox> box)
272 ensureRareBlockFlowData().m_lineGridBox = WTF::move(box);
274 void layoutLineGridBox();
276 virtual bool canCollapseAnonymousBlockChild() const override { return !renderNamedFlowFragment(); }
277 RenderNamedFlowFragment* renderNamedFlowFragment() const { return hasRareBlockFlowData() ? rareBlockFlowData()->m_renderNamedFlowFragment : nullptr; }
278 void setRenderNamedFlowFragment(RenderNamedFlowFragment*);
280 RenderMultiColumnFlowThread* multiColumnFlowThread() const { return hasRareBlockFlowData() ? rareBlockFlowData()->m_multiColumnFlowThread : nullptr; }
281 void setMultiColumnFlowThread(RenderMultiColumnFlowThread*);
283 virtual bool containsFloats() const override { return m_floatingObjects && !m_floatingObjects->set().isEmpty(); }
284 bool containsFloat(RenderBox&) const;
286 virtual void deleteLines() override;
287 virtual void computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats = false) override;
288 virtual VisiblePosition positionForPoint(const LayoutPoint&, const RenderRegion*) override;
290 void removeFloatingObjects();
291 void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = nullptr, bool inLayout = true);
292 void markSiblingsWithFloatsForLayout(RenderBox* floatToRemove = nullptr);
294 const FloatingObjectSet* floatingObjectSet() const { return m_floatingObjects ? &m_floatingObjects->set() : nullptr; }
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()); }
304 void setLogicalTopForFloat(FloatingObject* floatingObject, LayoutUnit logicalTop)
306 if (isHorizontalWritingMode())
307 floatingObject->setY(logicalTop);
309 floatingObject->setX(logicalTop);
311 void setLogicalLeftForFloat(FloatingObject* floatingObject, LayoutUnit logicalLeft)
313 if (isHorizontalWritingMode())
314 floatingObject->setX(logicalLeft);
316 floatingObject->setY(logicalLeft);
318 void setLogicalHeightForFloat(FloatingObject* floatingObject, LayoutUnit logicalHeight)
320 if (isHorizontalWritingMode())
321 floatingObject->setHeight(logicalHeight);
323 floatingObject->setWidth(logicalHeight);
325 void setLogicalWidthForFloat(FloatingObject* floatingObject, LayoutUnit logicalWidth)
327 if (isHorizontalWritingMode())
328 floatingObject->setWidth(logicalWidth);
330 floatingObject->setHeight(logicalWidth);
333 LayoutUnit xPositionForFloatIncludingMargin(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->x() + child->renderer().marginLeft() : child->x() + marginBeforeForChild(child->renderer()); }
334 LayoutUnit yPositionForFloatIncludingMargin(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->y() + marginBeforeForChild(child->renderer()) : child->y() + child->renderer().marginTop(); }
336 LayoutPoint flipFloatForWritingModeForChild(const FloatingObject*, const LayoutPoint&) const;
338 RenderLineBoxList& lineBoxes() { return m_lineBoxes; }
339 const RenderLineBoxList& lineBoxes() const { return m_lineBoxes; }
341 RootInlineBox* firstRootBox() const { return downcast<RootInlineBox>(m_lineBoxes.firstLineBox()); }
342 RootInlineBox* lastRootBox() const { return downcast<RootInlineBox>(m_lineBoxes.lastLineBox()); }
344 virtual bool hasLines() const override final;
345 virtual void invalidateLineLayoutPath() override final;
347 enum LineLayoutPath { UndeterminedPath = 0, SimpleLinesPath, LineBoxesPath, ForceLineBoxesPath };
348 LineLayoutPath lineLayoutPath() const { return static_cast<LineLayoutPath>(renderBlockFlowLineLayoutPath()); }
349 void setLineLayoutPath(LineLayoutPath path) { setRenderBlockFlowLineLayoutPath(path); }
351 // Helper methods for computing line counts and heights for line counts.
352 RootInlineBox* lineAtIndex(int) const;
353 int lineCount(const RootInlineBox* = nullptr, bool* = nullptr) const;
354 int heightForLineCount(int);
355 void clearTruncation();
357 void setHasMarkupTruncation(bool b) { setRenderBlockFlowHasMarkupTruncation(b); }
358 bool hasMarkupTruncation() const { return renderBlockFlowHasMarkupTruncation(); }
360 bool containsNonZeroBidiLevel() const;
362 const SimpleLineLayout::Layout* simpleLineLayout() const;
363 void deleteLineBoxesBeforeSimpleLineLayout();
364 void ensureLineBoxes();
366 #if ENABLE(TREE_DEBUGGING)
367 void showLineTreeAndMark(const InlineBox* markedBox, int depth) const;
370 // Returns the logicalOffset at the top of the next page. If the offset passed in is already at the top of the current page,
371 // then nextPageLogicalTop with ExcludePageBoundary will still move to the top of the next page. nextPageLogicalTop with
372 // IncludePageBoundary set will not.
374 // 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.
375 enum PageBoundaryRule { ExcludePageBoundary, IncludePageBoundary };
376 LayoutUnit nextPageLogicalTop(LayoutUnit logicalOffset, PageBoundaryRule = ExcludePageBoundary) const;
377 LayoutUnit pageLogicalTopForOffset(LayoutUnit offset) const;
378 LayoutUnit pageLogicalHeightForOffset(LayoutUnit offset) const;
379 LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit offset, PageBoundaryRule = IncludePageBoundary) const;
380 LayoutUnit logicalHeightForChildForFragmentation(const RenderBox& child) const;
381 bool hasNextPage(LayoutUnit logicalOffset, PageBoundaryRule = ExcludePageBoundary) const;
383 virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) override;
384 virtual void removeChild(RenderObject&) override;
386 void createMultiColumnFlowThread();
387 void destroyMultiColumnFlowThread();
389 void updateColumnProgressionFromStyle(RenderStyle&);
390 void updateStylesForColumnChildren();
392 virtual bool needsLayoutAfterRegionRangeChange() const override;
395 virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const override;
397 // A page break is required at some offset due to space shortage in the current fragmentainer.
398 void setPageBreak(LayoutUnit offset, LayoutUnit spaceShortage);
400 // Update minimum page height required to avoid fragmentation where it shouldn't occur (inside
401 // unbreakable content, between orphans and widows, etc.). This will be used as a hint to the
402 // column balancer to help set a good minimum column height.
403 void updateMinimumPageHeight(LayoutUnit offset, LayoutUnit minHeight);
404 bool pushToNextPageWithMinimumLogicalHeight(LayoutUnit& adjustment, LayoutUnit logicalOffset, LayoutUnit minimumLogicalHeight) const;
406 // If the child is unsplittable and can't fit on the current page, return the top of the next page/column.
407 LayoutUnit adjustForUnsplittableChild(RenderBox& child, LayoutUnit logicalOffset, bool includeMargins = false);
408 LayoutUnit adjustBlockChildForPagination(LayoutUnit logicalTopAfterClear, LayoutUnit estimateWithoutPagination, RenderBox& child, bool atBeforeSideOfBlock);
409 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.
410 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 LayoutUnit maxPositiveMarginBefore() const { return hasRareBlockFlowData() ? rareBlockFlowData()->m_margins.positiveMarginBefore() : RenderBlockFlowRareData::positiveMarginBeforeDefault(*this); }
413 LayoutUnit maxNegativeMarginBefore() const { return hasRareBlockFlowData() ? rareBlockFlowData()->m_margins.negativeMarginBefore() : RenderBlockFlowRareData::negativeMarginBeforeDefault(*this); }
414 LayoutUnit maxPositiveMarginAfter() const { return hasRareBlockFlowData() ? rareBlockFlowData()->m_margins.positiveMarginAfter() : RenderBlockFlowRareData::positiveMarginAfterDefault(*this); }
415 LayoutUnit maxNegativeMarginAfter() const { return hasRareBlockFlowData() ? rareBlockFlowData()->m_margins.negativeMarginAfter() : RenderBlockFlowRareData::negativeMarginAfterDefault(*this); }
417 void initMaxMarginValues()
419 if (!hasRareBlockFlowData())
422 rareBlockFlowData()->m_margins = MarginValues(RenderBlockFlowRareData::positiveMarginBeforeDefault(*this) , RenderBlockFlowRareData::negativeMarginBeforeDefault(*this),
423 RenderBlockFlowRareData::positiveMarginAfterDefault(*this), RenderBlockFlowRareData::negativeMarginAfterDefault(*this));
424 rareBlockFlowData()->m_discardMarginBefore = false;
425 rareBlockFlowData()->m_discardMarginAfter = false;
428 void setMaxMarginBeforeValues(LayoutUnit pos, LayoutUnit neg);
429 void setMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg);
431 void setMustDiscardMarginBefore(bool = true);
432 void setMustDiscardMarginAfter(bool = true);
434 bool mustDiscardMarginBefore() const;
435 bool mustDiscardMarginAfter() const;
437 bool mustDiscardMarginBeforeForChild(const RenderBox&) const;
438 bool mustDiscardMarginAfterForChild(const RenderBox&) const;
439 bool mustSeparateMarginBeforeForChild(const RenderBox&) const;
440 bool mustSeparateMarginAfterForChild(const RenderBox&) const;
442 virtual void styleWillChange(StyleDifference, const RenderStyle& newStyle) override;
443 virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override;
445 void createFloatingObjects();
447 virtual Optional<int> firstLineBaseline() const override;
448 virtual Optional<int> inlineBlockBaseline(LineDirectionMode) const override;
450 virtual bool isMultiColumnBlockFlow() const override { return multiColumnFlowThread(); }
452 void setComputedColumnCountAndWidth(int, LayoutUnit);
454 LayoutUnit computedColumnWidth() const;
455 unsigned computedColumnCount() const;
457 virtual bool isTopLayoutOverflowAllowed() const override;
458 virtual bool isLeftLayoutOverflowAllowed() const override;
460 void moveFloatsTo(RenderBlockFlow* toBlock);
462 virtual void computeColumnCountAndWidth();
463 virtual bool requiresColumns(int) const;
465 virtual void cachePriorCharactersIfNeeded(const LazyLineBreakIterator&) {};
468 bool recomputeLogicalWidthAndColumnWidth();
469 LayoutUnit columnGap() const;
471 RenderBlockFlow* previousSiblingWithOverhangingFloats(bool& parentHasFloats) const;
473 // 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
474 // the flow thread child.
475 virtual RenderObject* layoutSpecialExcludedChild(bool /*relayoutChildren*/);
477 void checkForPaginationLogicalHeightChange(bool& relayoutChildren, LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged);
479 virtual void paintInlineChildren(PaintInfo&, const LayoutPoint&) override;
480 virtual void paintFloats(PaintInfo&, const LayoutPoint&, bool preservePhase = false) override;
482 virtual void moveAllChildrenIncludingFloatsTo(RenderBlock& toBlock, bool fullRemoveInsert) override;
483 virtual void repaintOverhangingFloats(bool paintAllDescendants) override final;
484 virtual void clipOutFloatingObjects(RenderBlock&, const PaintInfo*, const LayoutPoint&, const LayoutSize&) override;
486 FloatingObject* insertFloatingObject(RenderBox&);
487 void removeFloatingObject(RenderBox&);
488 void removeFloatingObjectsBelow(FloatingObject*, int logicalOffset);
489 LayoutPoint computeLogicalLocationForFloat(const FloatingObject*, LayoutUnit logicalTopOffset);
491 // Called from lineWidth, to position the floats added in the last line.
492 // Returns true if and only if it has positioned any floats.
493 bool positionNewFloats();
495 void clearFloats(EClear);
497 virtual LayoutUnit logicalRightFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit logicalHeight) const override;
498 virtual LayoutUnit logicalLeftFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit logicalHeight) const override;
500 LayoutUnit logicalRightOffsetForPositioningFloat(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const;
501 LayoutUnit logicalLeftOffsetForPositioningFloat(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const;
503 LayoutUnit lowestInitialLetterLogicalBottom() const;
505 LayoutUnit lowestFloatLogicalBottom(FloatingObject::Type = FloatingObject::FloatLeftRight) const;
506 LayoutUnit nextFloatLogicalBottomBelow(LayoutUnit) const;
507 LayoutUnit nextFloatLogicalBottomBelowForBlock(LayoutUnit) const;
509 LayoutUnit addOverhangingFloats(RenderBlockFlow& child, bool makeChildPaintOtherFloats);
510 bool hasOverhangingFloat(RenderBox&);
511 void addIntrudingFloats(RenderBlockFlow* prev, RenderBlockFlow* container, LayoutUnit xoffset, LayoutUnit yoffset);
512 bool hasOverhangingFloats() { return parent() && containsFloats() && lowestFloatLogicalBottom() > logicalHeight(); }
513 LayoutUnit getClearDelta(RenderBox& child, LayoutUnit yPos);
515 void determineLogicalLeftPositionForChild(RenderBox& child, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
517 virtual bool hitTestFloats(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) override;
518 virtual bool hitTestInlineChildren(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
520 void addOverflowFromFloats();
521 virtual void addOverflowFromInlineChildren() override;
523 void fitBorderToLinesIfNeeded(); // Shrink the box in which the border paints if border-fit is set.
524 void adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const;
526 void markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit logicalBottom, RootInlineBox* highest = 0);
528 virtual GapRects inlineSelectionGaps(RenderBlock& rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
529 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const LogicalSelectionOffsetCaches&, const PaintInfo*) override;
531 Position positionForBox(InlineBox*, bool start = true) const;
532 virtual VisiblePosition positionForPointWithInlineChildren(const LayoutPoint& pointInLogicalContents, const RenderRegion*) override;
533 virtual void addFocusRingRectsForInlineChildren(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject*) override;
535 // FIXME-BLOCKFLOW: These methods have implementations in
536 // RenderBlockLineLayout. They should be moved to the proper header once the
537 // line layout code is separated from RenderBlock and RenderBlockFlow.
538 // START METHODS DEFINED IN RenderBlockLineLayout
540 static void appendRunsForObject(BidiRunList<BidiRun>*, int start, int end, RenderObject&, InlineBidiResolver&);
541 RootInlineBox* createAndAppendRootInlineBox();
543 LayoutUnit startAlignedOffsetForLine(LayoutUnit position, bool shouldIndentText);
544 virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const;
545 virtual void adjustInlineDirectionLineBounds(int /* expansionOpportunityCount */, float& /* logicalLeft */, float& /* logicalWidth */) const { }
548 void adjustIntrinsicLogicalWidthsForColumns(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const;
550 void layoutLineBoxes(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom);
551 void layoutSimpleLines(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom);
553 virtual std::unique_ptr<RootInlineBox> createRootInlineBox(); // Subclassed by RenderSVGText.
554 InlineFlowBox* createLineBoxes(RenderObject*, const LineInfo&, InlineBox* childBox);
555 RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
556 void setMarginsForRubyRun(BidiRun*, RenderRubyRun&, RenderObject*, const LineInfo&);
557 void computeInlineDirectionPositionsForLine(RootInlineBox*, const LineInfo&, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&, WordMeasurements&);
558 void updateRubyForJustifiedText(RenderRubyRun&, BidiRun&, const Vector<unsigned, 16>& expansionOpportunities, unsigned& expansionOpportunityCount, float& totalLogicalWidth, float availableLogicalWidth, size_t& expansionIndex);
559 void computeExpansionForJustifiedText(BidiRun* firstRun, BidiRun* trailingSpaceRun, const Vector<unsigned, 16>& expansionOpportunities, unsigned expansionOpportunityCount, float totalLogicalWidth, float availableLogicalWidth);
560 BidiRun* computeInlineDirectionPositionsForSegment(RootInlineBox*, const LineInfo&, ETextAlign, float& logicalLeft,
561 float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache&, WordMeasurements&);
562 void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&);
563 BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>&, BidiContext*);
564 void appendFloatingObjectToLastLine(FloatingObject*);
565 // Helper function for layoutInlineChildren()
566 RootInlineBox* createLineBoxesFromBidiRuns(unsigned bidiLevel, BidiRunList<BidiRun>&, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun, WordMeasurements&);
567 void layoutRunsAndFloats(LineLayoutState&, bool hasInlineChild);
568 const InlineIterator& restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight, FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver&, const InlineIterator&);
569 void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines);
570 void linkToEndLineIfNeeded(LineLayoutState&);
571 static void repaintDirtyFloats(Vector<FloatWithRect>& floats);
572 void checkFloatsInCleanLine(RootInlineBox*, Vector<FloatWithRect>&, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat);
573 RootInlineBox* determineStartPosition(LineLayoutState&, InlineBidiResolver&);
574 void determineEndPosition(LineLayoutState&, RootInlineBox* startBox, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus);
575 bool checkPaginationAndFloatsAtEndLine(LineLayoutState&);
576 bool matchedEndLine(LineLayoutState&, const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus);
577 void deleteEllipsisLineBoxes();
578 void checkLinesForTextOverflow();
579 // Positions new floats and also adjust all floats encountered on the line if any of them
580 // have to move to the next page/column.
581 bool positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo&, LineWidth&);
582 // 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
583 // region/page/column that has a different available line width than the old one. Used to know when you have to dirty a
584 // line, i.e., that it can't be re-used.
585 bool lineWidthForPaginatedLineChanged(RootInlineBox*, LayoutUnit lineDelta, RenderFlowThread*) const;
586 void updateLogicalWidthForAlignment(const ETextAlign&, const RootInlineBox*, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, int expansionOpportunityCount);
588 // END METHODS DEFINED IN RenderBlockLineLayout
590 bool namedFlowFragmentNeedsUpdate() const;
591 virtual bool canHaveChildren() const override;
593 void computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const;
595 #if ENABLE(IOS_TEXT_AUTOSIZING)
596 int m_widthForTextAutosizing;
597 unsigned m_lineCountForTextAutosizing : 2;
599 virtual void setSelectionState(SelectionState) override final;
602 // FIXME-BLOCKFLOW: These can be made protected again once all callers have been moved here.
603 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.
604 void updateRegionForLine(RootInlineBox*) const;
605 void createRenderNamedFlowFragmentIfNeeded();
607 // Pagination routines.
608 bool relayoutForPagination(LayoutStateMaintainer&);
610 bool hasRareBlockFlowData() const { return m_rareBlockFlowData.get(); }
611 RenderBlockFlowRareData* rareBlockFlowData() const { ASSERT_WITH_SECURITY_IMPLICATION(hasRareBlockFlowData()); return m_rareBlockFlowData.get(); }
612 RenderBlockFlowRareData& ensureRareBlockFlowData();
613 void materializeRareBlockFlowData();
615 #if ENABLE(IOS_TEXT_AUTOSIZING)
616 int lineCountForTextAutosizing();
617 void adjustComputedFontSizes(float size, float visibleWidth);
618 void resetComputedFontSize()
620 m_widthForTextAutosizing = -1;
621 m_lineCountForTextAutosizing = NOT_SET;
626 std::unique_ptr<FloatingObjects> m_floatingObjects;
627 std::unique_ptr<RenderBlockFlowRareData> m_rareBlockFlowData;
628 RenderLineBoxList m_lineBoxes;
629 std::unique_ptr<SimpleLineLayout::Layout> m_simpleLineLayout;
631 friend class LineBreaker;
632 friend class LineWidth; // Needs to know FloatingObject
635 inline bool RenderElement::isRenderNamedFlowFragmentContainer() const
637 return is<RenderBlockFlow>(*this) && downcast<RenderBlockFlow>(*this).renderNamedFlowFragment();
640 inline const SimpleLineLayout::Layout* RenderBlockFlow::simpleLineLayout() const
642 ASSERT(lineLayoutPath() == SimpleLinesPath || !m_simpleLineLayout);
643 return m_simpleLineLayout.get();
646 } // namespace WebCore
648 SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderBlockFlow, isRenderBlockFlow())
650 #endif // RenderBlockFlow_h