1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2007 David Smith (catfish.man (at) gmail.com) 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 RenderBlock_h 24 #define RenderBlock_h 25 26 #include "core/platform/PODIntervalTree.h" 27 #include "core/platform/graphics/TextRun.h" 28 #include "core/platform/text/TextBreakIterator.h" 29 #include "core/rendering/ColumnInfo.h" 30 #include "core/rendering/GapRects.h" 31 #include "core/rendering/RenderBox.h" 32 #include "core/rendering/RenderLineBoxList.h" 33 #include "core/rendering/RootInlineBox.h" 34 #include "core/rendering/shapes/ShapeInsideInfo.h" 35 #include "core/rendering/style/ShapeValue.h" 36 #include "wtf/ListHashSet.h" 37 #include "wtf/OwnPtr.h" 38 39 namespace WebCore { 40 41 class BasicShape; 42 class BidiContext; 43 class InlineIterator; 44 class LayoutStateMaintainer; 45 class LineLayoutState; 46 class LineWidth; 47 class RenderInline; 48 class RenderText; 49 50 struct BidiRun; 51 struct PaintInfo; 52 class LineInfo; 53 class RenderRubyRun; 54 class TextLayout; 55 class WordMeasurement; 56 57 template <class Iterator, class Run> class BidiResolver; 58 template <class Run> class BidiRunList; 59 template <class Iterator> struct MidpointState; 60 typedef BidiResolver<InlineIterator, BidiRun> InlineBidiResolver; 61 typedef MidpointState<InlineIterator> LineMidpointState; 62 typedef WTF::ListHashSet<RenderBox*, 16> TrackedRendererListHashSet; 63 typedef WTF::HashMap<const RenderBlock*, OwnPtr<TrackedRendererListHashSet> > TrackedDescendantsMap; 64 typedef WTF::HashMap<const RenderBox*, OwnPtr<HashSet<RenderBlock*> > > TrackedContainerMap; 65 typedef Vector<WordMeasurement, 64> WordMeasurements; 66 67 enum CaretType { CursorCaret, DragCaret }; 68 enum ContainingBlockState { NewContainingBlock, SameContainingBlock }; 69 70 enum TextRunFlag { 71 DefaultTextRunFlags = 0, 72 RespectDirection = 1 << 0, 73 RespectDirectionOverride = 1 << 1 74 }; 75 76 typedef unsigned TextRunFlags; 77 78 class RenderBlock : public RenderBox { 79 public: 80 friend class LineLayoutState; 81 #ifndef NDEBUG 82 // Used by the PODIntervalTree for debugging the FloatingObject. 83 template <class> friend struct ValueToString; 84 #endif 85 86 explicit RenderBlock(ContainerNode*); 87 virtual ~RenderBlock(); 88 89 static RenderBlock* createAnonymous(Document*); 90 91 RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); } 92 RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); } 93 94 const RenderObjectChildList* children() const { return &m_children; } 95 RenderObjectChildList* children() { return &m_children; } 96 97 bool beingDestroyed() const { return m_beingDestroyed; } 98 99 // These two functions are overridden for inline-block. 100 virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE FINAL; 101 virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; 102 103 RenderLineBoxList* lineBoxes() { return &m_lineBoxes; } 104 const RenderLineBoxList* lineBoxes() const { return &m_lineBoxes; } 105 106 InlineFlowBox* firstLineBox() const { return m_lineBoxes.firstLineBox(); } 107 InlineFlowBox* lastLineBox() const { return m_lineBoxes.lastLineBox(); } 108 109 void deleteLineBoxTree(); 110 111 virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0); 112 virtual void removeChild(RenderObject*); 113 114 virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0); 115 116 void insertPositionedObject(RenderBox*); 117 static void removePositionedObject(RenderBox*); 118 void removePositionedObjects(RenderBlock*, ContainingBlockState = SameContainingBlock); 119 120 void removeFloatingObjects(); 121 122 TrackedRendererListHashSet* positionedObjects() const; 123 bool hasPositionedObjects() const 124 { 125 TrackedRendererListHashSet* objects = positionedObjects(); 126 return objects && !objects->isEmpty(); 127 } 128 129 void addPercentHeightDescendant(RenderBox*); 130 static void removePercentHeightDescendant(RenderBox*); 131 TrackedRendererListHashSet* percentHeightDescendants() const; 132 static bool hasPercentHeightContainerMap(); 133 static bool hasPercentHeightDescendant(RenderBox*); 134 static void clearPercentHeightDescendantsFrom(RenderBox*); 135 static void removePercentHeightDescendantIfNeeded(RenderBox*); 136 137 void setHasMarkupTruncation(bool b) { m_hasMarkupTruncation = b; } 138 bool hasMarkupTruncation() const { return m_hasMarkupTruncation; } 139 140 void setHasMarginBeforeQuirk(bool b) { m_hasMarginBeforeQuirk = b; } 141 void setHasMarginAfterQuirk(bool b) { m_hasMarginAfterQuirk = b; } 142 143 bool hasMarginBeforeQuirk() const { return m_hasMarginBeforeQuirk; } 144 bool hasMarginAfterQuirk() const { return m_hasMarginAfterQuirk; } 145 146 bool hasMarginBeforeQuirk(const RenderBox* child) const; 147 bool hasMarginAfterQuirk(const RenderBox* child) const; 148 149 RootInlineBox* createAndAppendRootInlineBox(); 150 151 bool generatesLineBoxesForInlineChild(RenderObject*); 152 153 void markShapeInsideDescendantsForLayout(); 154 void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true); 155 void markSiblingsWithFloatsForLayout(RenderBox* floatToRemove = 0); 156 void markPositionedObjectsForLayout(); 157 virtual void markForPaginationRelayoutIfNeeded() OVERRIDE FINAL; 158 159 bool containsFloats() const { return m_floatingObjects && !m_floatingObjects->set().isEmpty(); } 160 bool containsFloat(RenderBox*) const; 161 162 // Versions that can compute line offsets with the region and page offset passed in. Used for speed to avoid having to 163 // compute the region all over again when you already know it. 164 LayoutUnit availableLogicalWidthForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, LayoutUnit logicalHeight = 0) const 165 { 166 return max<LayoutUnit>(0, logicalRightOffsetForLine(position, shouldIndentText, region, offsetFromLogicalTopOfFirstPage, logicalHeight) 167 - logicalLeftOffsetForLine(position, shouldIndentText, region, offsetFromLogicalTopOfFirstPage, logicalHeight)); 168 } 169 LayoutUnit logicalRightOffsetForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, LayoutUnit logicalHeight = 0) const 170 { 171 return logicalRightOffsetForLine(position, logicalRightOffsetForContent(region, offsetFromLogicalTopOfFirstPage), shouldIndentText, 0, logicalHeight); 172 } 173 LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, LayoutUnit logicalHeight = 0) const 174 { 175 return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(region, offsetFromLogicalTopOfFirstPage), shouldIndentText, 0, logicalHeight); 176 } 177 LayoutUnit startOffsetForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, LayoutUnit logicalHeight = 0) const 178 { 179 return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, region, offsetFromLogicalTopOfFirstPage, logicalHeight) 180 : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, region, offsetFromLogicalTopOfFirstPage, logicalHeight); 181 } 182 LayoutUnit endOffsetForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, LayoutUnit logicalHeight = 0) const 183 { 184 return !style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, region, offsetFromLogicalTopOfFirstPage, logicalHeight) 185 : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, region, offsetFromLogicalTopOfFirstPage, logicalHeight); 186 } 187 188 LayoutUnit availableLogicalWidthForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const 189 { 190 return availableLogicalWidthForLine(position, shouldIndentText, regionAtBlockOffset(position), offsetFromLogicalTopOfFirstPage(), logicalHeight); 191 } 192 LayoutUnit logicalRightOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const 193 { 194 return logicalRightOffsetForLine(position, logicalRightOffsetForContent(position), shouldIndentText, 0, logicalHeight); 195 } 196 LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const 197 { 198 return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(position), shouldIndentText, 0, logicalHeight); 199 } 200 LayoutUnit pixelSnappedLogicalLeftOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const 201 { 202 return roundToInt(logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight)); 203 } 204 LayoutUnit pixelSnappedLogicalRightOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const 205 { 206 // FIXME: Multicolumn layouts break carrying over subpixel values to the logical right offset because the lines may be shifted 207 // by a subpixel value for all but the first column. This can lead to the actual pixel snapped width of the column being off 208 // by one pixel when rendered versus layed out, which can result in the line being clipped. For now, we have to floor. 209 // https://bugs.webkit.org/show_bug.cgi?id=105461 210 return floorToInt(logicalRightOffsetForLine(position, shouldIndentText, logicalHeight)); 211 } 212 LayoutUnit startOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const 213 { 214 return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight) 215 : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, logicalHeight); 216 } 217 LayoutUnit endOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const 218 { 219 return !style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight) 220 : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, logicalHeight); 221 } 222 223 LayoutUnit startAlignedOffsetForLine(LayoutUnit position, bool shouldIndentText); 224 LayoutUnit textIndentOffset() const; 225 226 virtual PositionWithAffinity positionForPoint(const LayoutPoint&) OVERRIDE; 227 228 // Block flows subclass availableWidth to handle multi column layout (shrinking the width available to children when laying out.) 229 virtual LayoutUnit availableLogicalWidth() const OVERRIDE FINAL; 230 231 LayoutPoint flipForWritingModeIncludingColumns(const LayoutPoint&) const; 232 void adjustStartEdgeForWritingModeIncludingColumns(LayoutRect&) const; 233 234 RootInlineBox* firstRootBox() const { return static_cast<RootInlineBox*>(firstLineBox()); } 235 RootInlineBox* lastRootBox() const { return static_cast<RootInlineBox*>(lastLineBox()); } 236 237 GapRects selectionGapRectsForRepaint(const RenderLayerModelObject* repaintContainer); 238 LayoutRect logicalLeftSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, 239 RenderObject* selObj, LayoutUnit logicalLeft, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo*); 240 LayoutRect logicalRightSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, 241 RenderObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo*); 242 void getSelectionGapInfo(SelectionState, bool& leftGap, bool& rightGap); 243 RenderBlock* blockBeforeWithinSelectionRoot(LayoutSize& offset) const; 244 245 LayoutRect logicalRectToPhysicalRect(const LayoutPoint& physicalPosition, const LayoutRect& logicalRect); 246 247 // Helper methods for computing line counts and heights for line counts. 248 RootInlineBox* lineAtIndex(int) const; 249 int lineCount(const RootInlineBox* = 0, bool* = 0) const; 250 int heightForLineCount(int); 251 void clearTruncation(); 252 253 void adjustRectForColumns(LayoutRect&) const; 254 virtual void adjustForColumns(LayoutSize&, const LayoutPoint&) const OVERRIDE FINAL; 255 void adjustForColumnRect(LayoutSize& offset, const LayoutPoint& locationInContainer) const; 256 257 void addContinuationWithOutline(RenderInline*); 258 bool paintsContinuationOutline(RenderInline*); 259 260 virtual RenderBoxModelObject* virtualContinuation() const OVERRIDE FINAL { return continuation(); } 261 bool isAnonymousBlockContinuation() const { return continuation() && isAnonymousBlock(); } 262 RenderInline* inlineElementContinuation() const; 263 RenderBlock* blockElementContinuation() const; 264 265 using RenderBoxModelObject::continuation; 266 using RenderBoxModelObject::setContinuation; 267 268 static RenderBlock* createAnonymousWithParentRendererAndDisplay(const RenderObject*, EDisplay = BLOCK); 269 static RenderBlock* createAnonymousColumnsWithParentRenderer(const RenderObject*); 270 static RenderBlock* createAnonymousColumnSpanWithParentRenderer(const RenderObject*); 271 RenderBlock* createAnonymousBlock(EDisplay display = BLOCK) const { return createAnonymousWithParentRendererAndDisplay(this, display); } 272 RenderBlock* createAnonymousColumnsBlock() const { return createAnonymousColumnsWithParentRenderer(this); } 273 RenderBlock* createAnonymousColumnSpanBlock() const { return createAnonymousColumnSpanWithParentRenderer(this); } 274 275 virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE; 276 277 static bool shouldSkipCreatingRunsForObject(RenderObject* obj) 278 { 279 return obj->isFloating() || (obj->isOutOfFlowPositioned() && !obj->style()->isOriginalDisplayInlineType() && !obj->container()->isRenderInline()); 280 } 281 282 static void appendRunsForObject(BidiRunList<BidiRun>&, int start, int end, RenderObject*, InlineBidiResolver&); 283 284 static TextRun constructTextRun(RenderObject* context, const Font& font, const String& string, RenderStyle* style, 285 TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion, TextRunFlags = DefaultTextRunFlags); 286 287 static TextRun constructTextRun(RenderObject* context, const Font& font, const RenderText* text, RenderStyle* style, 288 TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion); 289 290 static TextRun constructTextRun(RenderObject* context, const Font& font, const RenderText* text, unsigned offset, unsigned length, RenderStyle* style, 291 TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion); 292 293 static TextRun constructTextRun(RenderObject* context, const Font& font, const RenderText* text, unsigned offset, RenderStyle* style, 294 TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion); 295 296 static TextRun constructTextRun(RenderObject* context, const Font& font, const LChar* characters, int length, RenderStyle* style, 297 TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion); 298 299 static TextRun constructTextRun(RenderObject* context, const Font& font, const UChar* characters, int length, RenderStyle* style, 300 TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion); 301 302 ColumnInfo* columnInfo() const; 303 int columnGap() const; 304 305 void updateColumnInfoFromStyle(RenderStyle*); 306 307 // These two functions take the ColumnInfo* to avoid repeated lookups of the info in the global HashMap. 308 unsigned columnCount(ColumnInfo*) const; 309 LayoutRect columnRectAt(ColumnInfo*, unsigned) const; 310 311 LayoutUnit paginationStrut() const { return m_rareData ? m_rareData->m_paginationStrut : LayoutUnit(); } 312 void setPaginationStrut(LayoutUnit); 313 314 bool shouldBreakAtLineToAvoidWidow() const { return m_rareData && m_rareData->m_shouldBreakAtLineToAvoidWidow; } 315 void clearShouldBreakAtLineToAvoidWidow() const; 316 RootInlineBox* lineBreakToAvoidWidow() const { return m_rareData ? m_rareData->m_lineBreakToAvoidWidow : 0; } 317 void setBreakAtLineToAvoidWidow(RootInlineBox*); 318 319 // The page logical offset is the object's offset from the top of the page in the page progression 320 // direction (so an x-offset in vertical text and a y-offset for horizontal text). 321 LayoutUnit pageLogicalOffset() const { return m_rareData ? m_rareData->m_pageLogicalOffset : LayoutUnit(); } 322 void setPageLogicalOffset(LayoutUnit); 323 324 RootInlineBox* lineGridBox() const { return m_rareData ? m_rareData->m_lineGridBox : 0; } 325 void setLineGridBox(RootInlineBox* box) 326 { 327 if (!m_rareData) 328 m_rareData = adoptPtr(new RenderBlockRareData(this)); 329 if (m_rareData->m_lineGridBox) 330 m_rareData->m_lineGridBox->destroy(); 331 m_rareData->m_lineGridBox = box; 332 } 333 void layoutLineGridBox(); 334 335 // Accessors for logical width/height and margins in the containing block's block-flow direction. 336 enum ApplyLayoutDeltaMode { ApplyLayoutDelta, DoNotApplyLayoutDelta }; 337 LayoutUnit logicalWidthForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->width() : child->height(); } 338 LayoutUnit logicalHeightForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->height() : child->width(); } 339 LayoutUnit logicalTopForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->y() : child->x(); } 340 void setLogicalLeftForChild(RenderBox* child, LayoutUnit logicalLeft, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta); 341 void setLogicalTopForChild(RenderBox* child, LayoutUnit logicalTop, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta); 342 LayoutUnit marginBeforeForChild(const RenderBoxModelObject* child) const { return child->marginBefore(style()); } 343 LayoutUnit marginAfterForChild(const RenderBoxModelObject* child) const { return child->marginAfter(style()); } 344 LayoutUnit marginStartForChild(const RenderBoxModelObject* child) const { return child->marginStart(style()); } 345 LayoutUnit marginEndForChild(const RenderBoxModelObject* child) const { return child->marginEnd(style()); } 346 void setMarginStartForChild(RenderBox* child, LayoutUnit value) const { child->setMarginStart(value, style()); } 347 void setMarginEndForChild(RenderBox* child, LayoutUnit value) const { child->setMarginEnd(value, style()); } 348 void setMarginBeforeForChild(RenderBox* child, LayoutUnit value) const { child->setMarginBefore(value, style()); } 349 void setMarginAfterForChild(RenderBox* child, LayoutUnit value) const { child->setMarginAfter(value, style()); } 350 LayoutUnit collapsedMarginBeforeForChild(const RenderBox* child) const; 351 LayoutUnit collapsedMarginAfterForChild(const RenderBox* child) const; 352 353 void updateLogicalWidthForAlignment(const ETextAlign&, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, int expansionOpportunityCount); 354 355 virtual void updateFirstLetter(); 356 357 class MarginValues { 358 public: 359 MarginValues(LayoutUnit beforePos, LayoutUnit beforeNeg, LayoutUnit afterPos, LayoutUnit afterNeg) 360 : m_positiveMarginBefore(beforePos) 361 , m_negativeMarginBefore(beforeNeg) 362 , m_positiveMarginAfter(afterPos) 363 , m_negativeMarginAfter(afterNeg) 364 { } 365 366 LayoutUnit positiveMarginBefore() const { return m_positiveMarginBefore; } 367 LayoutUnit negativeMarginBefore() const { return m_negativeMarginBefore; } 368 LayoutUnit positiveMarginAfter() const { return m_positiveMarginAfter; } 369 LayoutUnit negativeMarginAfter() const { return m_negativeMarginAfter; } 370 371 void setPositiveMarginBefore(LayoutUnit pos) { m_positiveMarginBefore = pos; } 372 void setNegativeMarginBefore(LayoutUnit neg) { m_negativeMarginBefore = neg; } 373 void setPositiveMarginAfter(LayoutUnit pos) { m_positiveMarginAfter = pos; } 374 void setNegativeMarginAfter(LayoutUnit neg) { m_negativeMarginAfter = neg; } 375 376 private: 377 LayoutUnit m_positiveMarginBefore; 378 LayoutUnit m_negativeMarginBefore; 379 LayoutUnit m_positiveMarginAfter; 380 LayoutUnit m_negativeMarginAfter; 381 }; 382 MarginValues marginValuesForChild(RenderBox* child) const; 383 384 virtual void scrollbarsChanged(bool /*horizontalScrollbarChanged*/, bool /*verticalScrollbarChanged*/) { }; 385 386 LayoutUnit logicalLeftOffsetForContent(RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage) const; 387 LayoutUnit logicalRightOffsetForContent(RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage) const; 388 LayoutUnit availableLogicalWidthForContent(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const 389 { 390 return max<LayoutUnit>(0, logicalRightOffsetForContent(region, offsetFromLogicalTopOfFirstPage) - 391 logicalLeftOffsetForContent(region, offsetFromLogicalTopOfFirstPage)); } 392 LayoutUnit startOffsetForContent(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const 393 { 394 return style()->isLeftToRightDirection() ? logicalLeftOffsetForContent(region, offsetFromLogicalTopOfFirstPage) 395 : logicalWidth() - logicalRightOffsetForContent(region, offsetFromLogicalTopOfFirstPage); 396 } 397 LayoutUnit endOffsetForContent(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const 398 { 399 return !style()->isLeftToRightDirection() ? logicalLeftOffsetForContent(region, offsetFromLogicalTopOfFirstPage) 400 : logicalWidth() - logicalRightOffsetForContent(region, offsetFromLogicalTopOfFirstPage); 401 } 402 LayoutUnit logicalLeftOffsetForContent(LayoutUnit blockOffset) const 403 { 404 return logicalLeftOffsetForContent(regionAtBlockOffset(blockOffset), offsetFromLogicalTopOfFirstPage()); 405 } 406 LayoutUnit logicalRightOffsetForContent(LayoutUnit blockOffset) const 407 { 408 return logicalRightOffsetForContent(regionAtBlockOffset(blockOffset), offsetFromLogicalTopOfFirstPage()); 409 } 410 LayoutUnit availableLogicalWidthForContent(LayoutUnit blockOffset) const 411 { 412 return availableLogicalWidthForContent(regionAtBlockOffset(blockOffset), offsetFromLogicalTopOfFirstPage()); 413 } 414 LayoutUnit startOffsetForContent(LayoutUnit blockOffset) const 415 { 416 return startOffsetForContent(regionAtBlockOffset(blockOffset), offsetFromLogicalTopOfFirstPage()); 417 } 418 LayoutUnit endOffsetForContent(LayoutUnit blockOffset) const 419 { 420 return endOffsetForContent(regionAtBlockOffset(blockOffset), offsetFromLogicalTopOfFirstPage()); 421 } 422 LayoutUnit logicalLeftOffsetForContent() const { return isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop(); } 423 LayoutUnit logicalRightOffsetForContent() const { return logicalLeftOffsetForContent() + availableLogicalWidth(); } 424 LayoutUnit startOffsetForContent() const { return style()->isLeftToRightDirection() ? logicalLeftOffsetForContent() : logicalWidth() - logicalRightOffsetForContent(); } 425 LayoutUnit endOffsetForContent() const { return !style()->isLeftToRightDirection() ? logicalLeftOffsetForContent() : logicalWidth() - logicalRightOffsetForContent(); } 426 427 void setStaticInlinePositionForChild(RenderBox*, LayoutUnit blockOffset, LayoutUnit inlinePosition); 428 void updateStaticInlinePositionForChild(RenderBox*, LayoutUnit logicalTop); 429 430 LayoutUnit computeStartPositionDeltaForChildAvoidingFloats(const RenderBox* child, LayoutUnit childMarginStart, RenderRegion* = 0, LayoutUnit offsetFromLogicalTopOfFirstPage = 0); 431 432 void placeRunInIfNeeded(RenderObject* newChild); 433 bool runInIsPlacedIntoSiblingBlock(RenderObject* runIn); 434 435 #ifndef NDEBUG 436 void checkPositionedObjectsNeedLayout(); 437 void showLineTreeAndMark(const InlineBox* = 0, const char* = 0, const InlineBox* = 0, const char* = 0, const RenderObject* = 0) const; 438 #endif 439 440 ShapeInsideInfo* ensureShapeInsideInfo() 441 { 442 if (!m_rareData || !m_rareData->m_shapeInsideInfo) 443 setShapeInsideInfo(ShapeInsideInfo::createInfo(this)); 444 return m_rareData->m_shapeInsideInfo.get(); 445 } 446 ShapeInsideInfo* shapeInsideInfo() const 447 { 448 return m_rareData && m_rareData->m_shapeInsideInfo && ShapeInsideInfo::isEnabledFor(this) ? m_rareData->m_shapeInsideInfo.get() : 0; 449 } 450 void setShapeInsideInfo(PassOwnPtr<ShapeInsideInfo> value) 451 { 452 if (!m_rareData) 453 m_rareData = adoptPtr(new RenderBlockRareData(this)); 454 m_rareData->m_shapeInsideInfo = value; 455 } 456 ShapeInsideInfo* layoutShapeInsideInfo() const; 457 bool allowsShapeInsideInfoSharing() const { return !isInline() && !isFloating(); } 458 459 protected: 460 virtual void willBeDestroyed(); 461 462 LayoutUnit maxPositiveMarginBefore() const { return m_rareData ? m_rareData->m_margins.positiveMarginBefore() : RenderBlockRareData::positiveMarginBeforeDefault(this); } 463 LayoutUnit maxNegativeMarginBefore() const { return m_rareData ? m_rareData->m_margins.negativeMarginBefore() : RenderBlockRareData::negativeMarginBeforeDefault(this); } 464 LayoutUnit maxPositiveMarginAfter() const { return m_rareData ? m_rareData->m_margins.positiveMarginAfter() : RenderBlockRareData::positiveMarginAfterDefault(this); } 465 LayoutUnit maxNegativeMarginAfter() const { return m_rareData ? m_rareData->m_margins.negativeMarginAfter() : RenderBlockRareData::negativeMarginAfterDefault(this); } 466 467 void setMaxMarginBeforeValues(LayoutUnit pos, LayoutUnit neg); 468 void setMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg); 469 470 void setMustDiscardMarginBefore(bool = true); 471 void setMustDiscardMarginAfter(bool = true); 472 473 bool mustDiscardMarginBefore() const; 474 bool mustDiscardMarginAfter() const; 475 476 bool mustDiscardMarginBeforeForChild(const RenderBox*) const; 477 bool mustDiscardMarginAfterForChild(const RenderBox*) const; 478 479 bool mustSeparateMarginBeforeForChild(const RenderBox*) const; 480 bool mustSeparateMarginAfterForChild(const RenderBox*) const; 481 482 void initMaxMarginValues() 483 { 484 if (m_rareData) { 485 m_rareData->m_margins = MarginValues(RenderBlockRareData::positiveMarginBeforeDefault(this) , RenderBlockRareData::negativeMarginBeforeDefault(this), 486 RenderBlockRareData::positiveMarginAfterDefault(this), RenderBlockRareData::negativeMarginAfterDefault(this)); 487 m_rareData->m_paginationStrut = 0; 488 489 m_rareData->m_discardMarginBefore = false; 490 m_rareData->m_discardMarginAfter = false; 491 } 492 } 493 494 virtual void layout(); 495 496 void layoutPositionedObjects(bool relayoutChildren, bool fixedPositionObjectsOnly = false); 497 void markFixedPositionObjectForLayoutIfNeeded(RenderObject* child); 498 499 virtual void paint(PaintInfo&, const LayoutPoint&); 500 virtual void paintObject(PaintInfo&, const LayoutPoint&); 501 virtual void paintChildren(PaintInfo&, const LayoutPoint&); 502 void paintChild(RenderBox*, PaintInfo&, const LayoutPoint&); 503 504 LayoutUnit logicalRightOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining = 0, LayoutUnit logicalHeight = 0) const 505 { 506 return adjustLogicalRightOffsetForLine(logicalRightFloatOffsetForLine(logicalTop, fixedOffset, heightRemaining, logicalHeight, ShapeOutsideFloatShapeOffset), applyTextIndent); 507 } 508 LayoutUnit logicalLeftOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining = 0, LayoutUnit logicalHeight = 0) const 509 { 510 return adjustLogicalLeftOffsetForLine(logicalLeftFloatOffsetForLine(logicalTop, fixedOffset, heightRemaining, logicalHeight, ShapeOutsideFloatShapeOffset), applyTextIndent); 511 } 512 LayoutUnit logicalRightOffsetForLineIgnoringShapeOutside(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining = 0, LayoutUnit logicalHeight = 0) const 513 { 514 return adjustLogicalRightOffsetForLine(logicalRightFloatOffsetForLine(logicalTop, fixedOffset, heightRemaining, logicalHeight, ShapeOutsideFloatMarginBoxOffset), applyTextIndent); 515 } 516 LayoutUnit logicalLeftOffsetForLineIgnoringShapeOutside(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining = 0, LayoutUnit logicalHeight = 0) const 517 { 518 return adjustLogicalLeftOffsetForLine(logicalLeftFloatOffsetForLine(logicalTop, fixedOffset, heightRemaining, logicalHeight, ShapeOutsideFloatMarginBoxOffset), applyTextIndent); 519 } 520 521 virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const; 522 virtual void adjustInlineDirectionLineBounds(int /* expansionOpportunityCount */, float& /* logicalLeft */, float& /* logicalWidth */) const { } 523 524 virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE; 525 526 virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE; 527 virtual void computePreferredLogicalWidths() OVERRIDE; 528 529 virtual int firstLineBoxBaseline() const; 530 virtual int inlineBlockBaseline(LineDirectionMode) const OVERRIDE; 531 int lastLineBoxBaseline(LineDirectionMode) const; 532 533 virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&); 534 535 // Delay update scrollbar until finishDelayRepaint() will be 536 // called. This function is used when a flexbox is laying out its 537 // descendant. If multiple calls are made to startDelayRepaint(), 538 // finishDelayRepaint() will do nothing until finishDelayRepaint() 539 // is called the same number of times. 540 static void startDelayUpdateScrollInfo(); 541 static void finishDelayUpdateScrollInfo(); 542 543 void updateScrollInfoAfterLayout(); 544 545 virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); 546 virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); 547 548 virtual bool hasLineIfEmpty() const; 549 550 bool simplifiedLayout(); 551 virtual void simplifiedNormalFlowLayout(); 552 553 void setDesiredColumnCountAndWidth(int, LayoutUnit); 554 555 public: 556 void computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats = false); 557 protected: 558 virtual void addOverflowFromChildren(); 559 void addOverflowFromFloats(); 560 void addOverflowFromPositionedObjects(); 561 void addOverflowFromBlockChildren(); 562 void addOverflowFromInlineChildren(); 563 void addVisualOverflowFromTheme(); 564 565 virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE; 566 567 virtual void computeSelfHitTestRects(Vector<LayoutRect>&, const LayoutPoint& layerOffset) const OVERRIDE; 568 569 // Only used by RenderSVGText, which explicitly overrides RenderBlock::layoutBlock(), do NOT use for anything else. 570 void forceLayoutInlineChildren() 571 { 572 LayoutUnit repaintLogicalTop = 0; 573 LayoutUnit repaintLogicalBottom = 0; 574 clearFloats(); 575 layoutInlineChildren(true, repaintLogicalTop, repaintLogicalBottom); 576 } 577 578 bool updateRegionsAndShapesLogicalSize(RenderFlowThread*); 579 void computeRegionRangeForBlock(RenderFlowThread*); 580 581 void updateBlockChildDirtyBitsBeforeLayout(bool relayoutChildren, RenderBox*); 582 583 virtual void checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight); 584 585 private: 586 enum ShapeOutsideFloatOffsetMode { ShapeOutsideFloatShapeOffset, ShapeOutsideFloatMarginBoxOffset }; 587 588 LayoutUnit logicalRightFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit* heightRemaining, LayoutUnit logicalHeight, ShapeOutsideFloatOffsetMode) const; 589 LayoutUnit logicalLeftFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit* heightRemaining, LayoutUnit logicalHeight, ShapeOutsideFloatOffsetMode) const; 590 LayoutUnit adjustLogicalRightOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const; 591 LayoutUnit adjustLogicalLeftOffsetForLine(LayoutUnit offsetFromFloats, bool applyTextIndent) const; 592 593 void computeShapeSize(); 594 void updateRegionsAndShapesAfterChildLayout(RenderFlowThread*, bool); 595 void updateShapeInsideInfoAfterStyleChange(const ShapeValue*, const ShapeValue* oldShape); 596 597 virtual RenderObjectChildList* virtualChildren() OVERRIDE FINAL { return children(); } 598 virtual const RenderObjectChildList* virtualChildren() const OVERRIDE FINAL { return children(); } 599 600 virtual const char* renderName() const; 601 602 virtual bool isRenderBlock() const OVERRIDE FINAL { return true; } 603 virtual bool isBlockFlow() const OVERRIDE FINAL { return (!isInline() || isReplaced()) && !isTable(); } 604 virtual bool isInlineBlockOrInlineTable() const OVERRIDE FINAL { return isInline() && isReplaced(); } 605 606 void makeChildrenNonInline(RenderObject* insertionPoint = 0); 607 virtual void removeLeftoverAnonymousBlock(RenderBlock* child); 608 609 static void collapseAnonymousBlockChild(RenderBlock* parent, RenderBlock* child); 610 void moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert); 611 612 virtual void dirtyLinesFromChangedChild(RenderObject* child) OVERRIDE FINAL { m_lineBoxes.dirtyLinesFromChangedChild(this, child); } 613 614 void addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild); 615 void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild); 616 void addChildToAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild); 617 618 void addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild = 0); 619 620 virtual bool isSelfCollapsingBlock() const OVERRIDE FINAL; 621 622 virtual LayoutUnit collapsedMarginBefore() const OVERRIDE FINAL { return maxPositiveMarginBefore() - maxNegativeMarginBefore(); } 623 virtual LayoutUnit collapsedMarginAfter() const OVERRIDE FINAL { return maxPositiveMarginAfter() - maxNegativeMarginAfter(); } 624 625 virtual void repaintOverhangingFloats(bool paintAllDescendants) OVERRIDE FINAL; 626 627 void layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloatLogicalBottom); 628 void layoutInlineChildren(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom); 629 BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>&, BidiContext*); 630 631 void insertIntoTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&); 632 static void removeFromTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&); 633 634 virtual RootInlineBox* createRootInlineBox(); // Subclassed by SVG and Ruby. 635 636 // Called to lay out the legend for a fieldset or the ruby text of a ruby run. 637 virtual RenderObject* layoutSpecialExcludedChild(bool /*relayoutChildren*/) { return 0; } 638 639 void createFirstLetterRenderer(RenderObject* firstLetterBlock, RenderObject* currentChild); 640 void updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderObject* firstLetterContainer); 641 642 Node* nodeForHitTest() const; 643 644 struct FloatWithRect { 645 FloatWithRect(RenderBox* f) 646 : object(f) 647 , rect(LayoutRect(f->x() - f->marginLeft(), f->y() - f->marginTop(), f->width() + f->marginWidth(), f->height() + f->marginHeight())) 648 , everHadLayout(f->everHadLayout()) 649 { 650 } 651 652 RenderBox* object; 653 LayoutRect rect; 654 bool everHadLayout; 655 }; 656 657 struct FloatingObject { 658 WTF_MAKE_NONCOPYABLE(FloatingObject); WTF_MAKE_FAST_ALLOCATED; 659 public: 660 // Note that Type uses bits so you can use FloatLeftRight as a mask to query for both left and right. 661 enum Type { FloatLeft = 1, FloatRight = 2, FloatLeftRight = 3 }; 662 663 FloatingObject(EFloat type) 664 : m_renderer(0) 665 , m_originatingLine(0) 666 , m_paginationStrut(0) 667 , m_shouldPaint(true) 668 , m_isDescendant(false) 669 , m_isPlaced(false) 670 #ifndef NDEBUG 671 , m_isInPlacedTree(false) 672 #endif 673 { 674 ASSERT(type != NoFloat); 675 if (type == LeftFloat) 676 m_type = FloatLeft; 677 else if (type == RightFloat) 678 m_type = FloatRight; 679 } 680 681 FloatingObject(Type type, const LayoutRect& frameRect) 682 : m_renderer(0) 683 , m_originatingLine(0) 684 , m_frameRect(frameRect) 685 , m_paginationStrut(0) 686 , m_type(type) 687 , m_shouldPaint(true) 688 , m_isDescendant(false) 689 , m_isPlaced(true) 690 #ifndef NDEBUG 691 , m_isInPlacedTree(false) 692 #endif 693 { 694 } 695 696 FloatingObject* clone() const 697 { 698 FloatingObject* cloneObject = new FloatingObject(type(), m_frameRect); 699 cloneObject->m_renderer = m_renderer; 700 cloneObject->m_originatingLine = m_originatingLine; 701 cloneObject->m_paginationStrut = m_paginationStrut; 702 cloneObject->m_shouldPaint = m_shouldPaint; 703 cloneObject->m_isDescendant = m_isDescendant; 704 cloneObject->m_isPlaced = m_isPlaced; 705 return cloneObject; 706 } 707 708 Type type() const { return static_cast<Type>(m_type); } 709 RenderBox* renderer() const { return m_renderer; } 710 711 bool isPlaced() const { return m_isPlaced; } 712 void setIsPlaced(bool placed = true) { m_isPlaced = placed; } 713 714 inline LayoutUnit x() const { ASSERT(isPlaced()); return m_frameRect.x(); } 715 inline LayoutUnit maxX() const { ASSERT(isPlaced()); return m_frameRect.maxX(); } 716 inline LayoutUnit y() const { ASSERT(isPlaced()); return m_frameRect.y(); } 717 inline LayoutUnit maxY() const { ASSERT(isPlaced()); return m_frameRect.maxY(); } 718 inline LayoutUnit width() const { return m_frameRect.width(); } 719 inline LayoutUnit height() const { return m_frameRect.height(); } 720 721 void setX(LayoutUnit x) { ASSERT(!isInPlacedTree()); m_frameRect.setX(x); } 722 void setY(LayoutUnit y) { ASSERT(!isInPlacedTree()); m_frameRect.setY(y); } 723 void setWidth(LayoutUnit width) { ASSERT(!isInPlacedTree()); m_frameRect.setWidth(width); } 724 void setHeight(LayoutUnit height) { ASSERT(!isInPlacedTree()); m_frameRect.setHeight(height); } 725 726 const LayoutRect& frameRect() const { ASSERT(isPlaced()); return m_frameRect; } 727 void setFrameRect(const LayoutRect& frameRect) { ASSERT(!isInPlacedTree()); m_frameRect = frameRect; } 728 729 #ifndef NDEBUG 730 bool isInPlacedTree() const { return m_isInPlacedTree; } 731 void setIsInPlacedTree(bool value) { m_isInPlacedTree = value; } 732 #endif 733 734 bool shouldPaint() const { return m_shouldPaint; } 735 void setShouldPaint(bool shouldPaint) { m_shouldPaint = shouldPaint; } 736 bool isDescendant() const { return m_isDescendant; } 737 void setIsDescendant(bool isDescendant) { m_isDescendant = isDescendant; } 738 739 RenderBox* m_renderer; 740 RootInlineBox* m_originatingLine; 741 LayoutRect m_frameRect; 742 int m_paginationStrut; 743 744 private: 745 unsigned m_type : 2; // Type (left or right aligned) 746 unsigned m_shouldPaint : 1; 747 unsigned m_isDescendant : 1; 748 unsigned m_isPlaced : 1; 749 #ifndef NDEBUG 750 unsigned m_isInPlacedTree : 1; 751 #endif 752 }; 753 754 LayoutPoint flipFloatForWritingModeForChild(const FloatingObject*, const LayoutPoint&) const; 755 756 LayoutUnit logicalTopForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->y() : child->x(); } 757 LayoutUnit logicalBottomForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->maxY() : child->maxX(); } 758 LayoutUnit logicalLeftForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->x() : child->y(); } 759 LayoutUnit logicalRightForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->maxX() : child->maxY(); } 760 LayoutUnit logicalWidthForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->width() : child->height(); } 761 762 int pixelSnappedLogicalTopForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedY() : child->frameRect().pixelSnappedX(); } 763 int pixelSnappedLogicalBottomForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedMaxY() : child->frameRect().pixelSnappedMaxX(); } 764 int pixelSnappedLogicalLeftForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedX() : child->frameRect().pixelSnappedY(); } 765 int pixelSnappedLogicalRightForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedMaxX() : child->frameRect().pixelSnappedMaxY(); } 766 767 void setLogicalTopForFloat(FloatingObject* child, LayoutUnit logicalTop) 768 { 769 if (isHorizontalWritingMode()) 770 child->setY(logicalTop); 771 else 772 child->setX(logicalTop); 773 } 774 void setLogicalLeftForFloat(FloatingObject* child, LayoutUnit logicalLeft) 775 { 776 if (isHorizontalWritingMode()) 777 child->setX(logicalLeft); 778 else 779 child->setY(logicalLeft); 780 } 781 void setLogicalHeightForFloat(FloatingObject* child, LayoutUnit logicalHeight) 782 { 783 if (isHorizontalWritingMode()) 784 child->setHeight(logicalHeight); 785 else 786 child->setWidth(logicalHeight); 787 } 788 void setLogicalWidthForFloat(FloatingObject* child, LayoutUnit logicalWidth) 789 { 790 if (isHorizontalWritingMode()) 791 child->setWidth(logicalWidth); 792 else 793 child->setHeight(logicalWidth); 794 } 795 796 LayoutUnit xPositionForFloatIncludingMargin(const FloatingObject* child) const 797 { 798 if (isHorizontalWritingMode()) 799 return child->x() + child->renderer()->marginLeft(); 800 else 801 return child->x() + marginBeforeForChild(child->renderer()); 802 } 803 804 LayoutUnit yPositionForFloatIncludingMargin(const FloatingObject* child) const 805 { 806 if (isHorizontalWritingMode()) 807 return child->y() + marginBeforeForChild(child->renderer()); 808 else 809 return child->y() + child->renderer()->marginTop(); 810 } 811 812 LayoutPoint computeLogicalLocationForFloat(const FloatingObject*, LayoutUnit logicalTopOffset) const; 813 814 // The following functions' implementations are in RenderBlockLineLayout.cpp. 815 struct RenderTextInfo { 816 // Destruction of m_layout requires TextLayout to be a complete type, so the constructor and destructor are made non-inline to avoid compilation errors. 817 RenderTextInfo(); 818 ~RenderTextInfo(); 819 820 RenderText* m_text; 821 OwnPtr<TextLayout> m_layout; 822 LazyLineBreakIterator m_lineBreakIterator; 823 const Font* m_font; 824 }; 825 826 class LineBreaker { 827 public: 828 LineBreaker(RenderBlock* block) 829 : m_block(block) 830 { 831 reset(); 832 } 833 834 InlineIterator nextLineBreak(InlineBidiResolver&, LineInfo&, RenderTextInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements&); 835 836 bool lineWasHyphenated() { return m_hyphenated; } 837 const Vector<RenderBox*>& positionedObjects() { return m_positionedObjects; } 838 EClear clear() { return m_clear; } 839 private: 840 void reset(); 841 842 InlineIterator nextSegmentBreak(InlineBidiResolver&, LineInfo&, RenderTextInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements&); 843 void skipTrailingWhitespace(InlineIterator&, const LineInfo&); 844 void skipLeadingWhitespace(InlineBidiResolver&, LineInfo&, FloatingObject* lastFloatFromPreviousLine, LineWidth&); 845 846 RenderBlock* m_block; 847 bool m_hyphenated; 848 EClear m_clear; 849 Vector<RenderBox*> m_positionedObjects; 850 }; 851 852 void checkFloatsInCleanLine(RootInlineBox*, Vector<FloatWithRect>&, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat); 853 RootInlineBox* determineStartPosition(LineLayoutState&, InlineBidiResolver&); 854 void determineEndPosition(LineLayoutState&, RootInlineBox* startBox, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus); 855 bool matchedEndLine(LineLayoutState&, const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus); 856 bool checkPaginationAndFloatsAtEndLine(LineLayoutState&); 857 858 RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&); 859 InlineFlowBox* createLineBoxes(RenderObject*, const LineInfo&, InlineBox* childBox, bool startsNewSegment); 860 861 void setMarginsForRubyRun(BidiRun*, RenderRubyRun*, RenderObject*, const LineInfo&); 862 863 BidiRun* computeInlineDirectionPositionsForSegment(RootInlineBox*, const LineInfo&, ETextAlign, float& logicalLeft, 864 float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache&, WordMeasurements&); 865 void computeInlineDirectionPositionsForLine(RootInlineBox*, const LineInfo&, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&, WordMeasurements&); 866 void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&); 867 void deleteEllipsisLineBoxes(); 868 void checkLinesForTextOverflow(); 869 870 // Positions new floats and also adjust all floats encountered on the line if any of them 871 // have to move to the next page/column. 872 bool positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo&, LineWidth&); 873 void appendFloatingObjectToLastLine(FloatingObject*); 874 875 // End of functions defined in RenderBlockLineLayout.cpp. 876 877 void paintFloats(PaintInfo&, const LayoutPoint&, bool preservePhase = false); 878 void paintContents(PaintInfo&, const LayoutPoint&); 879 void paintColumnContents(PaintInfo&, const LayoutPoint&, bool paintFloats = false); 880 void paintColumnRules(PaintInfo&, const LayoutPoint&); 881 void paintSelection(PaintInfo&, const LayoutPoint&); 882 void paintCaret(PaintInfo&, const LayoutPoint&, CaretType); 883 884 bool hasCaret() const { return hasCaret(CursorCaret) || hasCaret(DragCaret); } 885 bool hasCaret(CaretType) const; 886 887 FloatingObject* insertFloatingObject(RenderBox*); 888 void removeFloatingObject(RenderBox*); 889 void removeFloatingObjectsBelow(FloatingObject*, int logicalOffset); 890 891 // Called from lineWidth, to position the floats added in the last line. 892 // Returns true if and only if it has positioned any floats. 893 bool positionNewFloats(); 894 895 void clearFloats(); 896 897 LayoutUnit getClearDelta(RenderBox* child, LayoutUnit yPos); 898 899 virtual bool avoidsFloats() const; 900 901 bool hasOverhangingFloats() { return parent() && !hasColumns() && containsFloats() && lowestFloatLogicalBottom() > logicalHeight(); } 902 bool hasOverhangingFloat(RenderBox*); 903 void addIntrudingFloats(RenderBlock* prev, LayoutUnit xoffset, LayoutUnit yoffset); 904 LayoutUnit addOverhangingFloats(RenderBlock* child, bool makeChildPaintOtherFloats); 905 906 LayoutUnit lowestFloatLogicalBottom(FloatingObject::Type = FloatingObject::FloatLeftRight) const; 907 LayoutUnit nextFloatLogicalBottomBelow(LayoutUnit) const; 908 909 bool hitTestColumns(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction); 910 bool hitTestContents(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction); 911 bool hitTestFloats(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset); 912 913 virtual bool isPointInOverflowControl(HitTestResult&, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset); 914 915 // FIXME: Make this method const so we can remove the const_cast in computeIntrinsicLogicalWidths. 916 void computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth); 917 void computeBlockPreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const; 918 919 // Obtains the nearest enclosing block (including this block) that contributes a first-line style to our inline 920 // children. 921 virtual RenderBlock* firstLineBlock() const; 922 923 virtual LayoutRect rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const OVERRIDE FINAL; 924 virtual RenderStyle* outlineStyleForRepaint() const OVERRIDE FINAL; 925 926 virtual RenderObject* hoverAncestor() const OVERRIDE FINAL; 927 virtual void updateDragState(bool dragOn) OVERRIDE FINAL; 928 virtual void childBecameNonInline(RenderObject* child) OVERRIDE FINAL; 929 930 virtual LayoutRect selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool /*clipToVisibleContent*/) OVERRIDE FINAL 931 { 932 return selectionGapRectsForRepaint(repaintContainer); 933 } 934 virtual bool shouldPaintSelectionGaps() const OVERRIDE FINAL; 935 bool isSelectionRoot() const; 936 GapRects selectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, 937 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* = 0); 938 GapRects inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, 939 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo*); 940 GapRects blockSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, 941 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo*); 942 LayoutRect blockSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, 943 LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const PaintInfo*); 944 LayoutUnit logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position); 945 LayoutUnit logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position); 946 947 virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const; 948 virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const; 949 950 LayoutUnit desiredColumnWidth() const; 951 unsigned desiredColumnCount() const; 952 953 void paintContinuationOutlines(PaintInfo&, const LayoutPoint&); 954 955 virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0) OVERRIDE FINAL; 956 957 void adjustPointToColumnContents(LayoutPoint&) const; 958 959 void fitBorderToLinesIfNeeded(); // Shrink the box in which the border paints if border-fit is set. 960 void adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const; // Helper function for borderFitAdjust 961 962 void markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit logicalBottom, RootInlineBox* highest = 0); 963 964 void newLine(EClear); 965 966 Position positionForBox(InlineBox*, bool start = true) const; 967 PositionWithAffinity positionForPointWithInlineChildren(const LayoutPoint&); 968 969 virtual void calcColumnWidth(); 970 void makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, RenderBlock* newBlockBox, RenderObject* newChild); 971 972 bool expandsToEncloseOverhangingFloats() const; 973 974 void splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock, 975 RenderObject* beforeChild, RenderBoxModelObject* oldCont); 976 void splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox, 977 RenderObject* newChild, RenderBoxModelObject* oldCont); 978 RenderBlock* clone() const; 979 RenderBlock* continuationBefore(RenderObject* beforeChild); 980 RenderBlock* containingColumnsBlock(bool allowAnonymousColumnBlock = true); 981 RenderBlock* columnsBlockForSpanningElement(RenderObject* newChild); 982 983 class MarginInfo { 984 // Collapsing flags for whether we can collapse our margins with our children's margins. 985 bool m_canCollapseWithChildren : 1; 986 bool m_canCollapseMarginBeforeWithChildren : 1; 987 bool m_canCollapseMarginAfterWithChildren : 1; 988 989 // Whether or not we are a quirky container, i.e., do we collapse away top and bottom 990 // margins in our container. Table cells and the body are the common examples. We 991 // also have a custom style property for Safari RSS to deal with TypePad blog articles. 992 bool m_quirkContainer : 1; 993 994 // This flag tracks whether we are still looking at child margins that can all collapse together at the beginning of a block. 995 // They may or may not collapse with the top margin of the block (|m_canCollapseTopWithChildren| tells us that), but they will 996 // always be collapsing with one another. This variable can remain set to true through multiple iterations 997 // as long as we keep encountering self-collapsing blocks. 998 bool m_atBeforeSideOfBlock : 1; 999 1000 // This flag is set when we know we're examining bottom margins and we know we're at the bottom of the block. 1001 bool m_atAfterSideOfBlock : 1; 1002 1003 // These variables are used to detect quirky margins that we need to collapse away (in table cells 1004 // and in the body element). 1005 bool m_hasMarginBeforeQuirk : 1; 1006 bool m_hasMarginAfterQuirk : 1; 1007 bool m_determinedMarginBeforeQuirk : 1; 1008 1009 bool m_discardMargin : 1; 1010 1011 // These flags track the previous maximal positive and negative margins. 1012 LayoutUnit m_positiveMargin; 1013 LayoutUnit m_negativeMargin; 1014 1015 public: 1016 MarginInfo(RenderBlock*, LayoutUnit beforeBorderPadding, LayoutUnit afterBorderPadding); 1017 1018 void setAtBeforeSideOfBlock(bool b) { m_atBeforeSideOfBlock = b; } 1019 void setAtAfterSideOfBlock(bool b) { m_atAfterSideOfBlock = b; } 1020 void clearMargin() 1021 { 1022 m_positiveMargin = 0; 1023 m_negativeMargin = 0; 1024 } 1025 void setHasMarginBeforeQuirk(bool b) { m_hasMarginBeforeQuirk = b; } 1026 void setHasMarginAfterQuirk(bool b) { m_hasMarginAfterQuirk = b; } 1027 void setDeterminedMarginBeforeQuirk(bool b) { m_determinedMarginBeforeQuirk = b; } 1028 void setPositiveMargin(LayoutUnit p) { ASSERT(!m_discardMargin); m_positiveMargin = p; } 1029 void setNegativeMargin(LayoutUnit n) { ASSERT(!m_discardMargin); m_negativeMargin = n; } 1030 void setPositiveMarginIfLarger(LayoutUnit p) 1031 { 1032 ASSERT(!m_discardMargin); 1033 if (p > m_positiveMargin) 1034 m_positiveMargin = p; 1035 } 1036 void setNegativeMarginIfLarger(LayoutUnit n) 1037 { 1038 ASSERT(!m_discardMargin); 1039 if (n > m_negativeMargin) 1040 m_negativeMargin = n; 1041 } 1042 1043 void setMargin(LayoutUnit p, LayoutUnit n) { ASSERT(!m_discardMargin); m_positiveMargin = p; m_negativeMargin = n; } 1044 void setCanCollapseMarginAfterWithChildren(bool collapse) { m_canCollapseMarginAfterWithChildren = collapse; } 1045 void setDiscardMargin(bool value) { m_discardMargin = value; } 1046 1047 bool atBeforeSideOfBlock() const { return m_atBeforeSideOfBlock; } 1048 bool canCollapseWithMarginBefore() const { return m_atBeforeSideOfBlock && m_canCollapseMarginBeforeWithChildren; } 1049 bool canCollapseWithMarginAfter() const { return m_atAfterSideOfBlock && m_canCollapseMarginAfterWithChildren; } 1050 bool canCollapseMarginBeforeWithChildren() const { return m_canCollapseMarginBeforeWithChildren; } 1051 bool canCollapseMarginAfterWithChildren() const { return m_canCollapseMarginAfterWithChildren; } 1052 bool quirkContainer() const { return m_quirkContainer; } 1053 bool determinedMarginBeforeQuirk() const { return m_determinedMarginBeforeQuirk; } 1054 bool hasMarginBeforeQuirk() const { return m_hasMarginBeforeQuirk; } 1055 bool hasMarginAfterQuirk() const { return m_hasMarginAfterQuirk; } 1056 LayoutUnit positiveMargin() const { return m_positiveMargin; } 1057 LayoutUnit negativeMargin() const { return m_negativeMargin; } 1058 bool discardMargin() const { return m_discardMargin; } 1059 LayoutUnit margin() const { return m_positiveMargin - m_negativeMargin; } 1060 }; 1061 1062 void layoutBlockChild(RenderBox* child, MarginInfo&, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom); 1063 void adjustPositionedBlock(RenderBox* child, const MarginInfo&); 1064 void adjustFloatingBlock(const MarginInfo&); 1065 1066 RenderBoxModelObject* createReplacementRunIn(RenderBoxModelObject* runIn); 1067 void moveRunInUnderSiblingBlockIfNeeded(RenderObject* runIn); 1068 void moveRunInToOriginalPosition(RenderObject* runIn); 1069 1070 LayoutUnit collapseMargins(RenderBox* child, MarginInfo&); 1071 LayoutUnit clearFloatsIfNeeded(RenderBox* child, MarginInfo&, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos); 1072 LayoutUnit estimateLogicalTopPosition(RenderBox* child, const MarginInfo&, LayoutUnit& estimateWithoutPagination); 1073 void marginBeforeEstimateForChild(RenderBox*, LayoutUnit&, LayoutUnit&, bool&) const; 1074 void handleAfterSideOfBlock(LayoutUnit top, LayoutUnit bottom, MarginInfo&); 1075 void setCollapsedBottomMargin(const MarginInfo&); 1076 // End helper functions and structs used by layoutBlockChildren. 1077 1078 // Helper function for layoutInlineChildren() 1079 RootInlineBox* createLineBoxesFromBidiRuns(BidiRunList<BidiRun>&, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun, WordMeasurements&); 1080 void layoutRunsAndFloats(LineLayoutState&, bool hasInlineChild); 1081 void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines); 1082 void updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*&, LayoutUnit&, LineLayoutState&); 1083 void updateShapeAndSegmentsForCurrentLineInFlowThread(ShapeInsideInfo*&, LineLayoutState&); 1084 bool adjustLogicalLineTopAndLogicalHeightIfNeeded(ShapeInsideInfo*, LayoutUnit, LineLayoutState&, InlineBidiResolver&, FloatingObject*, InlineIterator&, WordMeasurements&); 1085 const InlineIterator& restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight, FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver&, const InlineIterator&); 1086 void linkToEndLineIfNeeded(LineLayoutState&); 1087 static void repaintDirtyFloats(Vector<FloatWithRect>& floats); 1088 1089 protected: 1090 void determineLogicalLeftPositionForChild(RenderBox* child, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta); 1091 1092 // Pagination routines. 1093 virtual bool relayoutForPagination(bool hasSpecifiedPageLogicalHeight, LayoutUnit pageLogicalHeight, LayoutStateMaintainer&); 1094 1095 // Returns the logicalOffset at the top of the next page. If the offset passed in is already at the top of the current page, 1096 // then nextPageLogicalTop with ExcludePageBoundary will still move to the top of the next page. nextPageLogicalTop with 1097 // IncludePageBoundary set will not. 1098 // 1099 // 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. 1100 enum PageBoundaryRule { ExcludePageBoundary, IncludePageBoundary }; 1101 LayoutUnit nextPageLogicalTop(LayoutUnit logicalOffset, PageBoundaryRule = ExcludePageBoundary) const; 1102 bool hasNextPage(LayoutUnit logicalOffset, PageBoundaryRule = ExcludePageBoundary) const; 1103 1104 virtual ColumnInfo::PaginationUnit paginationUnit() const; 1105 1106 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. 1107 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. 1108 1109 public: 1110 LayoutUnit pageLogicalTopForOffset(LayoutUnit offset) const; 1111 LayoutUnit pageLogicalHeightForOffset(LayoutUnit offset) const; 1112 LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit offset, PageBoundaryRule = IncludePageBoundary) const; 1113 1114 protected: 1115 bool pushToNextPageWithMinimumLogicalHeight(LayoutUnit& adjustment, LayoutUnit logicalOffset, LayoutUnit minimumLogicalHeight) const; 1116 1117 // A page break is required at some offset due to space shortage in the current fragmentainer. 1118 void setPageBreak(LayoutUnit offset, LayoutUnit spaceShortage); 1119 1120 // Update minimum page height required to avoid fragmentation where it shouldn't occur (inside 1121 // unbreakable content, between orphans and widows, etc.). This will be used as a hint to the 1122 // column balancer to help set a good minimum column height. 1123 void updateMinimumPageHeight(LayoutUnit offset, LayoutUnit minHeight); 1124 1125 LayoutUnit adjustForUnsplittableChild(RenderBox* child, LayoutUnit logicalOffset, bool includeMargins = false); // If the child is unsplittable and can't fit on the current page, return the top of the next page/column. 1126 void adjustLinePositionForPagination(RootInlineBox*, LayoutUnit& deltaOffset, RenderFlowThread*); // Computes a deltaOffset value that put a line at the top of the next page if it doesn't fit on the current page. 1127 LayoutUnit adjustBlockChildForPagination(LayoutUnit logicalTopAfterClear, LayoutUnit estimateWithoutPagination, RenderBox* child, bool atBeforeSideOfBlock); 1128 1129 // Adjust from painting offsets to the local coords of this renderer 1130 void offsetForContents(LayoutPoint&) const; 1131 1132 // 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 1133 // region/page/column that has a different available line width than the old one. Used to know when you have to dirty a 1134 // line, i.e., that it can't be re-used. 1135 bool lineWidthForPaginatedLineChanged(RootInlineBox*, LayoutUnit lineDelta, RenderFlowThread*) const; 1136 1137 bool logicalWidthChangedInRegions(RenderFlowThread*) const; 1138 1139 virtual bool requiresColumns(int desiredColumnCount) const; 1140 1141 virtual bool updateLogicalWidthAndColumnWidth(); 1142 1143 virtual bool canCollapseAnonymousBlockChild() const { return true; } 1144 1145 public: 1146 LayoutUnit offsetFromLogicalTopOfFirstPage() const; 1147 RenderRegion* regionAtBlockOffset(LayoutUnit) const; 1148 RenderRegion* clampToStartAndEndRegions(RenderRegion*) const; 1149 1150 protected: 1151 struct FloatingObjectHashFunctions { 1152 static unsigned hash(FloatingObject* key) { return DefaultHash<RenderBox*>::Hash::hash(key->m_renderer); } 1153 static bool equal(FloatingObject* a, FloatingObject* b) { return a->m_renderer == b->m_renderer; } 1154 static const bool safeToCompareToEmptyOrDeleted = true; 1155 }; 1156 struct FloatingObjectHashTranslator { 1157 static unsigned hash(RenderBox* key) { return DefaultHash<RenderBox*>::Hash::hash(key); } 1158 static bool equal(FloatingObject* a, RenderBox* b) { return a->m_renderer == b; } 1159 }; 1160 typedef ListHashSet<FloatingObject*, 4, FloatingObjectHashFunctions> FloatingObjectSet; 1161 typedef FloatingObjectSet::const_iterator FloatingObjectSetIterator; 1162 typedef PODInterval<int, FloatingObject*> FloatingObjectInterval; 1163 typedef PODIntervalTree<int, FloatingObject*> FloatingObjectTree; 1164 typedef PODFreeListArena<PODRedBlackTree<FloatingObjectInterval>::Node> IntervalArena; 1165 1166 template <FloatingObject::Type FloatTypeValue> 1167 class FloatIntervalSearchAdapter { 1168 public: 1169 typedef FloatingObjectInterval IntervalType; 1170 1171 FloatIntervalSearchAdapter(const RenderBlock* renderer, int lowValue, int highValue, LayoutUnit& offset, LayoutUnit* heightRemaining) 1172 : m_renderer(renderer) 1173 , m_lowValue(lowValue) 1174 , m_highValue(highValue) 1175 , m_offset(offset) 1176 , m_heightRemaining(heightRemaining) 1177 , m_last(0) 1178 { 1179 } 1180 1181 inline int lowValue() const { return m_lowValue; } 1182 inline int highValue() const { return m_highValue; } 1183 void collectIfNeeded(const IntervalType&) const; 1184 1185 // When computing the offset caused by the floats on a given line, if 1186 // the outermost float on that line has a shape-outside, the inline 1187 // content that butts up against that float must be positioned using 1188 // the contours of the shape, not the margin box of the float. 1189 // We save the last float encountered so that the offset can be 1190 // computed correctly by the code using this adapter. 1191 const FloatingObject* lastFloat() const { return m_last; } 1192 1193 private: 1194 bool updateOffsetIfNeeded(const FloatingObject*) const; 1195 1196 const RenderBlock* m_renderer; 1197 int m_lowValue; 1198 int m_highValue; 1199 LayoutUnit& m_offset; 1200 LayoutUnit* m_heightRemaining; 1201 // This member variable is mutable because the collectIfNeeded method 1202 // is declared as const, even though it doesn't actually respect that 1203 // contract. It modifies other member variables via loopholes in the 1204 // const behavior. Instead of using loopholes, I decided it was better 1205 // to make the fact that this is modified in a const method explicit. 1206 mutable const FloatingObject* m_last; 1207 }; 1208 1209 void createFloatingObjects(); 1210 1211 public: 1212 1213 class FloatingObjects { 1214 WTF_MAKE_NONCOPYABLE(FloatingObjects); WTF_MAKE_FAST_ALLOCATED; 1215 public: 1216 void clear(); 1217 void add(FloatingObject*); 1218 void remove(FloatingObject*); 1219 void addPlacedObject(FloatingObject*); 1220 void removePlacedObject(FloatingObject*); 1221 void setHorizontalWritingMode(bool b = true) { m_horizontalWritingMode = b; } 1222 1223 bool hasLeftObjects() const { return m_leftObjectsCount > 0; } 1224 bool hasRightObjects() const { return m_rightObjectsCount > 0; } 1225 const FloatingObjectSet& set() const { return m_set; } 1226 const FloatingObjectTree& placedFloatsTree() 1227 { 1228 computePlacedFloatsTreeIfNeeded(); 1229 return m_placedFloatsTree; 1230 } 1231 private: 1232 FloatingObjects(const RenderBlock*, bool horizontalWritingMode); 1233 void computePlacedFloatsTree(); 1234 inline void computePlacedFloatsTreeIfNeeded() 1235 { 1236 if (!m_placedFloatsTree.isInitialized()) 1237 computePlacedFloatsTree(); 1238 } 1239 void increaseObjectsCount(FloatingObject::Type); 1240 void decreaseObjectsCount(FloatingObject::Type); 1241 FloatingObjectInterval intervalForFloatingObject(FloatingObject*); 1242 1243 FloatingObjectSet m_set; 1244 FloatingObjectTree m_placedFloatsTree; 1245 unsigned m_leftObjectsCount; 1246 unsigned m_rightObjectsCount; 1247 bool m_horizontalWritingMode; 1248 const RenderBlock* m_renderer; 1249 1250 friend void RenderBlock::createFloatingObjects(); 1251 }; 1252 1253 // Allocated only when some of these fields have non-default values 1254 struct RenderBlockRareData { 1255 WTF_MAKE_NONCOPYABLE(RenderBlockRareData); WTF_MAKE_FAST_ALLOCATED; 1256 public: 1257 RenderBlockRareData(const RenderBlock* block) 1258 : m_margins(positiveMarginBeforeDefault(block), negativeMarginBeforeDefault(block), positiveMarginAfterDefault(block), negativeMarginAfterDefault(block)) 1259 , m_paginationStrut(0) 1260 , m_pageLogicalOffset(0) 1261 , m_lineGridBox(0) 1262 , m_lineBreakToAvoidWidow(0) 1263 , m_shouldBreakAtLineToAvoidWidow(false) 1264 , m_discardMarginBefore(false) 1265 , m_discardMarginAfter(false) 1266 { 1267 } 1268 1269 static LayoutUnit positiveMarginBeforeDefault(const RenderBlock* block) 1270 { 1271 return std::max<LayoutUnit>(block->marginBefore(), 0); 1272 } 1273 static LayoutUnit negativeMarginBeforeDefault(const RenderBlock* block) 1274 { 1275 return std::max<LayoutUnit>(-block->marginBefore(), 0); 1276 } 1277 static LayoutUnit positiveMarginAfterDefault(const RenderBlock* block) 1278 { 1279 return std::max<LayoutUnit>(block->marginAfter(), 0); 1280 } 1281 static LayoutUnit negativeMarginAfterDefault(const RenderBlock* block) 1282 { 1283 return std::max<LayoutUnit>(-block->marginAfter(), 0); 1284 } 1285 1286 MarginValues m_margins; 1287 LayoutUnit m_paginationStrut; 1288 LayoutUnit m_pageLogicalOffset; 1289 1290 RootInlineBox* m_lineGridBox; 1291 1292 RootInlineBox* m_lineBreakToAvoidWidow; 1293 OwnPtr<ShapeInsideInfo> m_shapeInsideInfo; 1294 bool m_shouldBreakAtLineToAvoidWidow : 1; 1295 bool m_discardMarginBefore : 1; 1296 bool m_discardMarginAfter : 1; 1297 }; 1298 1299 protected: 1300 1301 OwnPtr<FloatingObjects> m_floatingObjects; 1302 OwnPtr<RenderBlockRareData> m_rareData; 1303 1304 RenderObjectChildList m_children; 1305 RenderLineBoxList m_lineBoxes; // All of the root line boxes created for this block flow. For example, <div>Hello<br>world.</div> will have two total lines for the <div>. 1306 1307 mutable signed m_lineHeight : 27; 1308 unsigned m_hasMarginBeforeQuirk : 1; // Note these quirk values can't be put in RenderBlockRareData since they are set too frequently. 1309 unsigned m_hasMarginAfterQuirk : 1; 1310 unsigned m_beingDestroyed : 1; 1311 unsigned m_hasMarkupTruncation : 1; 1312 unsigned m_hasBorderOrPaddingLogicalWidthChanged : 1; 1313 1314 // RenderRubyBase objects need to be able to split and merge, moving their children around 1315 // (calling moveChildTo, moveAllChildrenTo, and makeChildrenNonInline). 1316 friend class RenderRubyBase; 1317 friend class LineWidth; // Needs to know FloatingObject 1318 1319 private: 1320 // Used to store state between styleWillChange and styleDidChange 1321 static bool s_canPropagateFloatIntoSibling; 1322 }; 1323 1324 inline RenderBlock* toRenderBlock(RenderObject* object) 1325 { 1326 ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderBlock()); 1327 return static_cast<RenderBlock*>(object); 1328 } 1329 1330 inline const RenderBlock* toRenderBlock(const RenderObject* object) 1331 { 1332 ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderBlock()); 1333 return static_cast<const RenderBlock*>(object); 1334 } 1335 1336 // This will catch anyone doing an unnecessary cast. 1337 void toRenderBlock(const RenderBlock*); 1338 1339 #ifndef NDEBUG 1340 // These structures are used by PODIntervalTree for debugging purposes. 1341 template <> struct ValueToString<int> { 1342 static String string(const int value); 1343 }; 1344 template<> struct ValueToString<RenderBlock::FloatingObject*> { 1345 static String string(const RenderBlock::FloatingObject*); 1346 }; 1347 #endif 1348 1349 } // namespace WebCore 1350 1351 #endif // RenderBlock_h 1352