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 * Copyright (C) Research In Motion Limited 2010. All rights reserved. 7 * Copyright (C) 2013 Google Inc. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions are 11 * met: 12 * 13 * * Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * * Redistributions in binary form must reproduce the above 16 * copyright notice, this list of conditions and the following disclaimer 17 * in the documentation and/or other materials provided with the 18 * distribution. 19 * * Neither the name of Google Inc. nor the names of its 20 * contributors may be used to endorse or promote products derived from 21 * this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 #ifndef RenderBlockFlow_h 37 #define RenderBlockFlow_h 38 39 #include "core/rendering/FloatingObjects.h" 40 #include "core/rendering/RenderBlock.h" 41 #include "core/rendering/line/TrailingObjects.h" 42 #include "core/rendering/style/RenderStyleConstants.h" 43 44 namespace blink { 45 46 class MarginInfo; 47 class LineBreaker; 48 class LineWidth; 49 class RenderMultiColumnFlowThread; 50 51 class RenderBlockFlow : public RenderBlock { 52 public: 53 explicit RenderBlockFlow(ContainerNode*); 54 virtual ~RenderBlockFlow(); 55 virtual void trace(Visitor*) OVERRIDE; 56 57 static RenderBlockFlow* createAnonymous(Document*); 58 isRenderBlockFlow()59 virtual bool isRenderBlockFlow() const OVERRIDE FINAL { return true; } 60 61 virtual void layoutBlock(bool relayoutChildren) OVERRIDE; 62 63 virtual void computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats = false) OVERRIDE; 64 65 virtual void deleteLineBoxTree() OVERRIDE FINAL; 66 67 LayoutUnit availableLogicalWidthForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const 68 { 69 return max<LayoutUnit>(0, logicalRightOffsetForLine(position, shouldIndentText, logicalHeight) - logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight)); 70 } 71 LayoutUnit logicalRightOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const 72 { 73 return logicalRightOffsetForLine(position, logicalRightOffsetForContent(), shouldIndentText, logicalHeight); 74 } 75 LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const 76 { 77 return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(), shouldIndentText, logicalHeight); 78 } 79 LayoutUnit startOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const 80 { 81 return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight) 82 : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, logicalHeight); 83 } 84 LayoutUnit endOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const 85 { 86 return !style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight) 87 : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, logicalHeight); 88 } 89 90 // FIXME-BLOCKFLOW: Move this into RenderBlockFlow once there are no calls 91 // in RenderBlock. http://crbug.com/393945, http://crbug.com/302024 92 using RenderBlock::lineBoxes; 93 using RenderBlock::firstLineBox; 94 using RenderBlock::lastLineBox; 95 using RenderBlock::firstRootBox; 96 using RenderBlock::lastRootBox; 97 98 virtual LayoutUnit logicalLeftSelectionOffset(const RenderBlock* rootBlock, LayoutUnit position) const OVERRIDE; 99 virtual LayoutUnit logicalRightSelectionOffset(const RenderBlock* rootBlock, LayoutUnit position) const OVERRIDE; 100 101 RootInlineBox* createAndAppendRootInlineBox(); 102 103 void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true); 104 void markSiblingsWithFloatsForLayout(RenderBox* floatToRemove = 0); 105 containsFloats()106 bool containsFloats() const { return m_floatingObjects && !m_floatingObjects->set().isEmpty(); } 107 bool containsFloat(RenderBox*) const; 108 109 void removeFloatingObjects(); 110 111 virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE; 112 113 void moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert); 114 115 bool generatesLineBoxesForInlineChild(RenderObject*); 116 logicalTopForFloat(const FloatingObject * floatingObject)117 LayoutUnit logicalTopForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->y() : floatingObject->x(); } logicalBottomForFloat(const FloatingObject * floatingObject)118 LayoutUnit logicalBottomForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->maxY() : floatingObject->maxX(); } logicalLeftForFloat(const FloatingObject * floatingObject)119 LayoutUnit logicalLeftForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->x() : floatingObject->y(); } logicalRightForFloat(const FloatingObject * floatingObject)120 LayoutUnit logicalRightForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->maxX() : floatingObject->maxY(); } logicalWidthForFloat(const FloatingObject * floatingObject)121 LayoutUnit logicalWidthForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->width() : floatingObject->height(); } logicalHeightForFloat(const FloatingObject * floatingObject)122 LayoutUnit logicalHeightForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->height() : floatingObject->width(); } logicalSizeForFloat(const FloatingObject * floatingObject)123 LayoutSize logicalSizeForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? LayoutSize(floatingObject->width(), floatingObject->height()) : LayoutSize(floatingObject->height(), floatingObject->width()); } 124 pixelSnappedLogicalTopForFloat(const FloatingObject * floatingObject)125 int pixelSnappedLogicalTopForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->frameRect().pixelSnappedY() : floatingObject->frameRect().pixelSnappedX(); } pixelSnappedLogicalBottomForFloat(const FloatingObject * floatingObject)126 int pixelSnappedLogicalBottomForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->frameRect().pixelSnappedMaxY() : floatingObject->frameRect().pixelSnappedMaxX(); } pixelSnappedLogicalLeftForFloat(const FloatingObject * floatingObject)127 int pixelSnappedLogicalLeftForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->frameRect().pixelSnappedX() : floatingObject->frameRect().pixelSnappedY(); } pixelSnappedLogicalRightForFloat(const FloatingObject * floatingObject)128 int pixelSnappedLogicalRightForFloat(const FloatingObject* floatingObject) const { return isHorizontalWritingMode() ? floatingObject->frameRect().pixelSnappedMaxX() : floatingObject->frameRect().pixelSnappedMaxY(); } 129 setLogicalTopForFloat(FloatingObject * floatingObject,LayoutUnit logicalTop)130 void setLogicalTopForFloat(FloatingObject* floatingObject, LayoutUnit logicalTop) 131 { 132 if (isHorizontalWritingMode()) 133 floatingObject->setY(logicalTop); 134 else 135 floatingObject->setX(logicalTop); 136 } setLogicalLeftForFloat(FloatingObject * floatingObject,LayoutUnit logicalLeft)137 void setLogicalLeftForFloat(FloatingObject* floatingObject, LayoutUnit logicalLeft) 138 { 139 if (isHorizontalWritingMode()) 140 floatingObject->setX(logicalLeft); 141 else 142 floatingObject->setY(logicalLeft); 143 } setLogicalHeightForFloat(FloatingObject * floatingObject,LayoutUnit logicalHeight)144 void setLogicalHeightForFloat(FloatingObject* floatingObject, LayoutUnit logicalHeight) 145 { 146 if (isHorizontalWritingMode()) 147 floatingObject->setHeight(logicalHeight); 148 else 149 floatingObject->setWidth(logicalHeight); 150 } setLogicalWidthForFloat(FloatingObject * floatingObject,LayoutUnit logicalWidth)151 void setLogicalWidthForFloat(FloatingObject* floatingObject, LayoutUnit logicalWidth) 152 { 153 if (isHorizontalWritingMode()) 154 floatingObject->setWidth(logicalWidth); 155 else 156 floatingObject->setHeight(logicalWidth); 157 } 158 159 LayoutUnit startAlignedOffsetForLine(LayoutUnit position, bool shouldIndentText); 160 161 void setStaticInlinePositionForChild(RenderBox*, LayoutUnit inlinePosition); 162 void updateStaticInlinePositionForChild(RenderBox*, LayoutUnit logicalTop); 163 shouldSkipCreatingRunsForObject(RenderObject * obj)164 static bool shouldSkipCreatingRunsForObject(RenderObject* obj) 165 { 166 return obj->isFloating() || (obj->isOutOfFlowPositioned() && !obj->style()->isOriginalDisplayInlineType() && !obj->container()->isRenderInline()); 167 } 168 multiColumnFlowThread()169 RenderMultiColumnFlowThread* multiColumnFlowThread() const { return m_rareData ? m_rareData->m_multiColumnFlowThread.get() : 0; } resetMultiColumnFlowThread()170 void resetMultiColumnFlowThread() 171 { 172 if (m_rareData) 173 m_rareData->m_multiColumnFlowThread = nullptr; 174 } 175 176 void addOverflowFromInlineChildren(); 177 178 // FIXME: This should be const to avoid a const_cast, but can modify child dirty bits and RenderCombineText 179 void computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth); 180 181 GapRects inlineSelectionGaps(const RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, 182 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo*) const; 183 paginationStrut()184 LayoutUnit paginationStrut() const { return m_rareData ? m_rareData->m_paginationStrut : LayoutUnit(); } 185 void setPaginationStrut(LayoutUnit); 186 187 virtual bool avoidsFloats() const OVERRIDE; 188 xPositionForFloatIncludingMargin(const FloatingObject * child)189 LayoutUnit xPositionForFloatIncludingMargin(const FloatingObject* child) const 190 { 191 if (isHorizontalWritingMode()) 192 return child->x() + child->renderer()->marginLeft(); 193 194 return child->x() + marginBeforeForChild(child->renderer()); 195 } 196 yPositionForFloatIncludingMargin(const FloatingObject * child)197 LayoutUnit yPositionForFloatIncludingMargin(const FloatingObject* child) const 198 { 199 if (isHorizontalWritingMode()) 200 return child->y() + marginBeforeForChild(child->renderer()); 201 202 return child->y() + child->renderer()->marginTop(); 203 } 204 205 LayoutPoint flipFloatForWritingModeForChild(const FloatingObject*, const LayoutPoint&) const; 206 207 protected: 208 void rebuildFloatsFromIntruding(); 209 void layoutInlineChildren(bool relayoutChildren, LayoutUnit& paintInvalidationLogicalTop, LayoutUnit& paintInvalidationLogicalBottom, LayoutUnit afterEdge); 210 211 void createFloatingObjects(); 212 213 virtual void styleWillChange(StyleDifference, const RenderStyle& newStyle) OVERRIDE; 214 virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE; 215 216 void addOverflowFromFloats(); 217 218 LayoutUnit logicalRightOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit logicalHeight = 0) const 219 { 220 return adjustLogicalRightOffsetForLine(logicalRightFloatOffsetForLine(logicalTop, fixedOffset, logicalHeight), applyTextIndent); 221 } 222 LayoutUnit logicalLeftOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit logicalHeight = 0) const 223 { 224 return adjustLogicalLeftOffsetForLine(logicalLeftFloatOffsetForLine(logicalTop, fixedOffset, logicalHeight), applyTextIndent); 225 } 226 227 virtual RenderObject* layoutSpecialExcludedChild(bool /*relayoutChildren*/, SubtreeLayoutScope&); 228 virtual bool updateLogicalWidthAndColumnWidth() OVERRIDE; 229 230 void setLogicalLeftForChild(RenderBox* child, LayoutUnit logicalLeft); 231 void setLogicalTopForChild(RenderBox* child, LayoutUnit logicalTop); 232 void determineLogicalLeftPositionForChild(RenderBox* child); 233 234 private: 235 bool layoutBlockFlow(bool relayoutChildren, LayoutUnit& pageLogicalHeight, SubtreeLayoutScope&); 236 void layoutBlockChildren(bool relayoutChildren, SubtreeLayoutScope&, LayoutUnit beforeEdge, LayoutUnit afterEdge); 237 238 void layoutBlockChild(RenderBox* child, MarginInfo&, LayoutUnit& previousFloatLogicalBottom); 239 void adjustPositionedBlock(RenderBox* child, const MarginInfo&); 240 void adjustFloatingBlock(const MarginInfo&); 241 242 LayoutPoint computeLogicalLocationForFloat(const FloatingObject*, LayoutUnit logicalTopOffset) const; 243 244 FloatingObject* insertFloatingObject(RenderBox*); 245 void removeFloatingObject(RenderBox*); 246 void removeFloatingObjectsBelow(FloatingObject*, int logicalOffset); 247 248 // Called from lineWidth, to position the floats added in the last line. 249 // Returns true if and only if it has positioned any floats. 250 bool positionNewFloats(); 251 252 LayoutUnit getClearDelta(RenderBox* child, LayoutUnit yPos); 253 hasOverhangingFloats()254 bool hasOverhangingFloats() { return parent() && !hasColumns() && containsFloats() && lowestFloatLogicalBottom() > logicalHeight(); } 255 bool hasOverhangingFloat(RenderBox*); 256 void addIntrudingFloats(RenderBlockFlow* prev, LayoutUnit xoffset, LayoutUnit yoffset); 257 void addOverhangingFloats(RenderBlockFlow* child, bool makeChildPaintOtherFloats); 258 259 LayoutUnit lowestFloatLogicalBottom(FloatingObject::Type = FloatingObject::FloatLeftRight) const; 260 LayoutUnit nextFloatLogicalBottomBelow(LayoutUnit, ShapeOutsideFloatOffsetMode = ShapeOutsideFloatMarginBoxOffset) const; 261 262 virtual bool hitTestFloats(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) OVERRIDE FINAL; 263 264 virtual void invalidatePaintForOverhangingFloats(bool paintAllDescendants) OVERRIDE FINAL; 265 virtual void invalidatePaintForOverflow() OVERRIDE FINAL; 266 virtual void paintFloats(PaintInfo&, const LayoutPoint&, bool preservePhase = false) OVERRIDE FINAL; 267 virtual void clipOutFloatingObjects(const RenderBlock*, const PaintInfo*, const LayoutPoint&, const LayoutSize&) const OVERRIDE; 268 void clearFloats(EClear); 269 270 LayoutUnit logicalRightFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit logicalHeight) const; 271 LayoutUnit logicalLeftFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit logicalHeight) const; 272 273 LayoutUnit logicalRightOffsetForPositioningFloat(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const; 274 LayoutUnit logicalLeftOffsetForPositioningFloat(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const; 275 276 LayoutUnit adjustLogicalRightOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const; 277 LayoutUnit adjustLogicalLeftOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const; 278 279 void fitBorderToLinesIfNeeded(); // Shrink the box in which the border paints if border-fit is set. 280 void adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const; // Helper function for borderFitAdjust 281 282 virtual RootInlineBox* createRootInlineBox(); // Subclassed by SVG 283 284 bool isPagedOverflow(const RenderStyle*); 285 286 enum FlowThreadType { 287 NoFlowThread, 288 MultiColumnFlowThread, 289 PagedFlowThread 290 }; 291 292 FlowThreadType flowThreadType(const RenderStyle*); 293 294 RenderMultiColumnFlowThread* createMultiColumnFlowThread(FlowThreadType); 295 void createOrDestroyMultiColumnFlowThreadIfNeeded(const RenderStyle* oldStyle); 296 297 void updateLogicalWidthForAlignment(const ETextAlign&, const RootInlineBox*, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, unsigned expansionOpportunityCount); 298 void checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight); 299 bool shouldRelayoutForPagination(LayoutUnit& pageLogicalHeight, LayoutUnit layoutOverflowLogicalBottom) const; 300 void setColumnCountAndHeight(unsigned count, LayoutUnit pageLogicalHeight); 301 shouldBreakAtLineToAvoidWidow()302 bool shouldBreakAtLineToAvoidWidow() const { return m_rareData && m_rareData->m_lineBreakToAvoidWidow >= 0; } 303 void clearShouldBreakAtLineToAvoidWidow() const; lineBreakToAvoidWidow()304 int lineBreakToAvoidWidow() const { return m_rareData ? m_rareData->m_lineBreakToAvoidWidow : -1; } 305 void setBreakAtLineToAvoidWidow(int); 306 void clearDidBreakAtLineToAvoidWidow(); 307 void setDidBreakAtLineToAvoidWidow(); didBreakAtLineToAvoidWidow()308 bool didBreakAtLineToAvoidWidow() const { return m_rareData && m_rareData->m_didBreakAtLineToAvoidWidow; } 309 310 public: 311 struct FloatWithRect { FloatWithRectFloatWithRect312 FloatWithRect(RenderBox* f) 313 : object(f) 314 , rect(LayoutRect(f->x() - f->marginLeft(), f->y() - f->marginTop(), f->width() + f->marginWidth(), f->height() + f->marginHeight())) 315 , everHadLayout(f->everHadLayout()) 316 { 317 } 318 319 RenderBox* object; 320 LayoutRect rect; 321 bool everHadLayout; 322 }; 323 324 class MarginValues { 325 public: MarginValues(LayoutUnit beforePos,LayoutUnit beforeNeg,LayoutUnit afterPos,LayoutUnit afterNeg)326 MarginValues(LayoutUnit beforePos, LayoutUnit beforeNeg, LayoutUnit afterPos, LayoutUnit afterNeg) 327 : m_positiveMarginBefore(beforePos) 328 , m_negativeMarginBefore(beforeNeg) 329 , m_positiveMarginAfter(afterPos) 330 , m_negativeMarginAfter(afterNeg) 331 { } 332 positiveMarginBefore()333 LayoutUnit positiveMarginBefore() const { return m_positiveMarginBefore; } negativeMarginBefore()334 LayoutUnit negativeMarginBefore() const { return m_negativeMarginBefore; } positiveMarginAfter()335 LayoutUnit positiveMarginAfter() const { return m_positiveMarginAfter; } negativeMarginAfter()336 LayoutUnit negativeMarginAfter() const { return m_negativeMarginAfter; } 337 setPositiveMarginBefore(LayoutUnit pos)338 void setPositiveMarginBefore(LayoutUnit pos) { m_positiveMarginBefore = pos; } setNegativeMarginBefore(LayoutUnit neg)339 void setNegativeMarginBefore(LayoutUnit neg) { m_negativeMarginBefore = neg; } setPositiveMarginAfter(LayoutUnit pos)340 void setPositiveMarginAfter(LayoutUnit pos) { m_positiveMarginAfter = pos; } setNegativeMarginAfter(LayoutUnit neg)341 void setNegativeMarginAfter(LayoutUnit neg) { m_negativeMarginAfter = neg; } 342 343 private: 344 LayoutUnit m_positiveMarginBefore; 345 LayoutUnit m_negativeMarginBefore; 346 LayoutUnit m_positiveMarginAfter; 347 LayoutUnit m_negativeMarginAfter; 348 }; 349 MarginValues marginValuesForChild(RenderBox* child) const; 350 351 // Allocated only when some of these fields have non-default values 352 struct RenderBlockFlowRareData : public NoBaseWillBeGarbageCollected<RenderBlockFlowRareData> { 353 WTF_MAKE_NONCOPYABLE(RenderBlockFlowRareData); WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; 354 public: RenderBlockFlowRareDataRenderBlockFlowRareData355 RenderBlockFlowRareData(const RenderBlockFlow* block) 356 : m_margins(positiveMarginBeforeDefault(block), negativeMarginBeforeDefault(block), positiveMarginAfterDefault(block), negativeMarginAfterDefault(block)) 357 , m_paginationStrut(0) 358 , m_multiColumnFlowThread(nullptr) 359 , m_lineBreakToAvoidWidow(-1) 360 , m_didBreakAtLineToAvoidWidow(false) 361 , m_discardMarginBefore(false) 362 , m_discardMarginAfter(false) 363 { 364 } 365 void trace(Visitor*); 366 positiveMarginBeforeDefaultRenderBlockFlowRareData367 static LayoutUnit positiveMarginBeforeDefault(const RenderBlockFlow* block) 368 { 369 return std::max<LayoutUnit>(block->marginBefore(), 0); 370 } negativeMarginBeforeDefaultRenderBlockFlowRareData371 static LayoutUnit negativeMarginBeforeDefault(const RenderBlockFlow* block) 372 { 373 return std::max<LayoutUnit>(-block->marginBefore(), 0); 374 } positiveMarginAfterDefaultRenderBlockFlowRareData375 static LayoutUnit positiveMarginAfterDefault(const RenderBlockFlow* block) 376 { 377 return std::max<LayoutUnit>(block->marginAfter(), 0); 378 } negativeMarginAfterDefaultRenderBlockFlowRareData379 static LayoutUnit negativeMarginAfterDefault(const RenderBlockFlow* block) 380 { 381 return std::max<LayoutUnit>(-block->marginAfter(), 0); 382 } 383 384 MarginValues m_margins; 385 LayoutUnit m_paginationStrut; 386 387 RawPtrWillBeMember<RenderMultiColumnFlowThread> m_multiColumnFlowThread; 388 389 int m_lineBreakToAvoidWidow; 390 bool m_didBreakAtLineToAvoidWidow : 1; 391 bool m_discardMarginBefore : 1; 392 bool m_discardMarginAfter : 1; 393 }; 394 LayoutUnit marginOffsetForSelfCollapsingBlock(); 395 floatingObjects()396 FloatingObjects* floatingObjects() { return m_floatingObjects.get(); } 397 398 399 protected: maxPositiveMarginBefore()400 LayoutUnit maxPositiveMarginBefore() const { return m_rareData ? m_rareData->m_margins.positiveMarginBefore() : RenderBlockFlowRareData::positiveMarginBeforeDefault(this); } maxNegativeMarginBefore()401 LayoutUnit maxNegativeMarginBefore() const { return m_rareData ? m_rareData->m_margins.negativeMarginBefore() : RenderBlockFlowRareData::negativeMarginBeforeDefault(this); } maxPositiveMarginAfter()402 LayoutUnit maxPositiveMarginAfter() const { return m_rareData ? m_rareData->m_margins.positiveMarginAfter() : RenderBlockFlowRareData::positiveMarginAfterDefault(this); } maxNegativeMarginAfter()403 LayoutUnit maxNegativeMarginAfter() const { return m_rareData ? m_rareData->m_margins.negativeMarginAfter() : RenderBlockFlowRareData::negativeMarginAfterDefault(this); } 404 405 void setMaxMarginBeforeValues(LayoutUnit pos, LayoutUnit neg); 406 void setMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg); 407 408 void setMustDiscardMarginBefore(bool = true); 409 void setMustDiscardMarginAfter(bool = true); 410 411 bool mustDiscardMarginBefore() const; 412 bool mustDiscardMarginAfter() const; 413 414 bool mustDiscardMarginBeforeForChild(const RenderBox*) const; 415 bool mustDiscardMarginAfterForChild(const RenderBox*) const; 416 417 bool mustSeparateMarginBeforeForChild(const RenderBox*) const; 418 bool mustSeparateMarginAfterForChild(const RenderBox*) const; 419 initMaxMarginValues()420 void initMaxMarginValues() 421 { 422 if (m_rareData) { 423 m_rareData->m_margins = MarginValues(RenderBlockFlowRareData::positiveMarginBeforeDefault(this) , RenderBlockFlowRareData::negativeMarginBeforeDefault(this), 424 RenderBlockFlowRareData::positiveMarginAfterDefault(this), RenderBlockFlowRareData::negativeMarginAfterDefault(this)); 425 426 m_rareData->m_discardMarginBefore = false; 427 m_rareData->m_discardMarginAfter = false; 428 } 429 } 430 431 virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const; 432 private: collapsedMarginBefore()433 virtual LayoutUnit collapsedMarginBefore() const OVERRIDE FINAL { return maxPositiveMarginBefore() - maxNegativeMarginBefore(); } collapsedMarginAfter()434 virtual LayoutUnit collapsedMarginAfter() const OVERRIDE FINAL { return maxPositiveMarginAfter() - maxNegativeMarginAfter(); } 435 436 LayoutUnit collapseMargins(RenderBox* child, MarginInfo&, bool childIsSelfCollapsing); 437 LayoutUnit clearFloatsIfNeeded(RenderBox* child, MarginInfo&, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos, bool childIsSelfCollapsing); 438 LayoutUnit estimateLogicalTopPosition(RenderBox* child, const MarginInfo&, LayoutUnit& estimateWithoutPagination); 439 void marginBeforeEstimateForChild(RenderBox*, LayoutUnit&, LayoutUnit&, bool&) const; 440 void handleAfterSideOfBlock(RenderBox* lastChild, LayoutUnit top, LayoutUnit bottom, MarginInfo&); 441 void setCollapsedBottomMargin(const MarginInfo&); 442 443 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. 444 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. 445 446 LayoutUnit adjustBlockChildForPagination(LayoutUnit logicalTopAfterClear, LayoutUnit estimateWithoutPagination, RenderBox* child, bool atBeforeSideOfBlock); 447 // Computes a deltaOffset value that put a line at the top of the next page if it doesn't fit on the current page. 448 void adjustLinePositionForPagination(RootInlineBox*, LayoutUnit& deltaOffset, RenderFlowThread*); 449 // If the child is unsplittable and can't fit on the current page, return the top of the next page/column. 450 LayoutUnit adjustForUnsplittableChild(RenderBox*, LayoutUnit logicalOffset, bool includeMargins = false); 451 452 // Used to store state between styleWillChange and styleDidChange 453 static bool s_canPropagateFloatIntoSibling; 454 455 RenderBlockFlowRareData& ensureRareData(); 456 457 LayoutUnit m_paintInvalidationLogicalTop; 458 LayoutUnit m_paintInvalidationLogicalBottom; 459 460 virtual bool isSelfCollapsingBlock() const OVERRIDE; 461 462 protected: 463 OwnPtrWillBeMember<RenderBlockFlowRareData> m_rareData; 464 OwnPtr<FloatingObjects> m_floatingObjects; 465 466 friend class BreakingContext; // FIXME: It uses insertFloatingObject and positionNewFloatOnLine, if we move those out from the private scope/add a helper to LineBreaker, we can remove this friend 467 friend class MarginInfo; 468 friend class LineBreaker; 469 friend class LineWidth; // needs to know FloatingObject 470 471 // FIXME-BLOCKFLOW: These methods have implementations in 472 // RenderBlockLineLayout. They should be moved to the proper header once the 473 // line layout code is separated from RenderBlock and RenderBlockFlow. 474 // START METHODS DEFINED IN RenderBlockLineLayout 475 private: 476 InlineFlowBox* createLineBoxes(RenderObject*, const LineInfo&, InlineBox* childBox); 477 RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&); 478 void setMarginsForRubyRun(BidiRun*, RenderRubyRun*, RenderObject*, const LineInfo&); 479 void computeInlineDirectionPositionsForLine(RootInlineBox*, const LineInfo&, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&, WordMeasurements&); 480 BidiRun* computeInlineDirectionPositionsForSegment(RootInlineBox*, const LineInfo&, ETextAlign, float& logicalLeft, 481 float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache&, WordMeasurements&); 482 void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&); 483 BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>&, BidiContext*); 484 void appendFloatingObjectToLastLine(FloatingObject*); 485 // Helper function for layoutInlineChildren() 486 RootInlineBox* createLineBoxesFromBidiRuns(unsigned bidiLevel, BidiRunList<BidiRun>&, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun, WordMeasurements&); 487 void layoutRunsAndFloats(LineLayoutState&); 488 const InlineIterator& restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight, FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver&, const InlineIterator&); 489 void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, 490 const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus); 491 void linkToEndLineIfNeeded(LineLayoutState&); 492 static void markDirtyFloatsForPaintInvalidation(Vector<FloatWithRect>& floats); 493 void checkFloatsInCleanLine(RootInlineBox*, Vector<FloatWithRect>&, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat); 494 RootInlineBox* determineStartPosition(LineLayoutState&, InlineBidiResolver&); 495 void determineEndPosition(LineLayoutState&, RootInlineBox* startBox, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus); 496 bool checkPaginationAndFloatsAtEndLine(LineLayoutState&); 497 bool matchedEndLine(LineLayoutState&, const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus); 498 void deleteEllipsisLineBoxes(); 499 void checkLinesForTextOverflow(); 500 // Positions new floats and also adjust all floats encountered on the line if any of them 501 // have to move to the next page/column. 502 bool positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo&, LineWidth&); 503 void positionDialog(); 504 505 // END METHODS DEFINED IN RenderBlockLineLayout 506 507 }; 508 509 DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderBlockFlow, isRenderBlockFlow()); 510 511 } // namespace blink 512 513 #endif // RenderBlockFlow_h 514