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