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