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 "GapRects.h" 27 #include "RenderBox.h" 28 #include "RenderLineBoxList.h" 29 #include "RootInlineBox.h" 30 #include <wtf/OwnPtr.h> 31 #include <wtf/ListHashSet.h> 32 33 namespace WebCore { 34 35 class BidiContext; 36 class ColumnInfo; 37 class InlineIterator; 38 class LayoutStateMaintainer; 39 class LazyLineBreakIterator; 40 class LineWidth; 41 class RenderInline; 42 43 struct BidiRun; 44 struct PaintInfo; 45 46 template <class Iterator, class Run> class BidiResolver; 47 template <class Run> class BidiRunList; 48 template <class Iterator> struct MidpointState; 49 typedef BidiResolver<InlineIterator, BidiRun> InlineBidiResolver; 50 typedef MidpointState<InlineIterator> LineMidpointState; 51 52 enum CaretType { CursorCaret, DragCaret }; 53 54 class RenderBlock : public RenderBox { 55 public: 56 RenderBlock(Node*); 57 virtual ~RenderBlock(); 58 59 const RenderObjectChildList* children() const { return &m_children; } 60 RenderObjectChildList* children() { return &m_children; } 61 62 virtual void destroy(); 63 bool beingDestroyed() const { return m_beingDestroyed; } 64 65 // These two functions are overridden for inline-block. 66 virtual int lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; 67 virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const; 68 69 RenderLineBoxList* lineBoxes() { return &m_lineBoxes; } 70 const RenderLineBoxList* lineBoxes() const { return &m_lineBoxes; } 71 72 InlineFlowBox* firstLineBox() const { return m_lineBoxes.firstLineBox(); } 73 InlineFlowBox* lastLineBox() const { return m_lineBoxes.lastLineBox(); } 74 75 void deleteLineBoxTree(); 76 77 virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0); 78 virtual void removeChild(RenderObject*); 79 80 virtual void layoutBlock(bool relayoutChildren, int pageLogicalHeight = 0); 81 82 void insertPositionedObject(RenderBox*); 83 void removePositionedObject(RenderBox*); 84 void removePositionedObjects(RenderBlock*); 85 86 typedef ListHashSet<RenderBox*, 4> PositionedObjectsListHashSet; 87 PositionedObjectsListHashSet* positionedObjects() const { return m_positionedObjects.get(); } 88 89 void addPercentHeightDescendant(RenderBox*); 90 static void removePercentHeightDescendant(RenderBox*); 91 HashSet<RenderBox*>* percentHeightDescendants() const; 92 93 RootInlineBox* createAndAppendRootInlineBox(); 94 95 bool generatesLineBoxesForInlineChild(RenderObject*, bool isLineEmpty = true, bool previousLineBrokeCleanly = true); 96 97 void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true); 98 void markSiblingsWithFloatsForLayout(); 99 void markPositionedObjectsForLayout(); 100 virtual void markForPaginationRelayoutIfNeeded(); 101 102 bool containsFloats() { return m_floatingObjects && !m_floatingObjects->set().isEmpty(); } 103 bool containsFloat(RenderBox*); 104 105 int availableLogicalWidthForLine(int position, bool firstLine) const; 106 int logicalRightOffsetForLine(int position, bool firstLine) const { return logicalRightOffsetForLine(position, logicalRightOffsetForContent(), firstLine); } 107 int logicalLeftOffsetForLine(int position, bool firstLine) const { return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(), firstLine); } 108 int startOffsetForLine(int position, bool firstLine) const { return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, firstLine) : logicalRightOffsetForLine(position, firstLine); } 109 110 virtual VisiblePosition positionForPoint(const IntPoint&); 111 112 // Block flows subclass availableWidth to handle multi column layout (shrinking the width available to children when laying out.) 113 virtual int availableLogicalWidth() const; 114 115 IntPoint flipForWritingModeIncludingColumns(const IntPoint&) const; 116 void flipForWritingModeIncludingColumns(IntRect&) const; 117 118 RootInlineBox* firstRootBox() const { return static_cast<RootInlineBox*>(firstLineBox()); } 119 RootInlineBox* lastRootBox() const { return static_cast<RootInlineBox*>(lastLineBox()); } 120 121 bool containsNonZeroBidiLevel() const; 122 123 GapRects selectionGapRectsForRepaint(RenderBoxModelObject* repaintContainer); 124 IntRect logicalLeftSelectionGap(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock, 125 RenderObject* selObj, int logicalLeft, int logicalTop, int logicalHeight, const PaintInfo*); 126 IntRect logicalRightSelectionGap(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock, 127 RenderObject* selObj, int logicalRight, int logicalTop, int logicalHeight, const PaintInfo*); 128 void getSelectionGapInfo(SelectionState, bool& leftGap, bool& rightGap); 129 IntRect logicalRectToPhysicalRect(const IntPoint& physicalPosition, const IntRect& logicalRect); 130 131 // Helper methods for computing line counts and heights for line counts. 132 RootInlineBox* lineAtIndex(int); 133 int lineCount(); 134 int heightForLineCount(int); 135 void clearTruncation(); 136 137 void adjustRectForColumns(IntRect&) const; 138 virtual void adjustForColumns(IntSize&, const IntPoint&) const; 139 140 void addContinuationWithOutline(RenderInline*); 141 bool paintsContinuationOutline(RenderInline*); 142 143 virtual RenderBoxModelObject* virtualContinuation() const { return continuation(); } 144 bool isAnonymousBlockContinuation() const { return continuation() && isAnonymousBlock(); } 145 RenderInline* inlineElementContinuation() const; 146 RenderBlock* blockElementContinuation() const; 147 148 using RenderBoxModelObject::continuation; 149 using RenderBoxModelObject::setContinuation; 150 151 // This function is a convenience helper for creating an anonymous block that inherits its 152 // style from this RenderBlock. 153 RenderBlock* createAnonymousBlock(bool isFlexibleBox = false) const; 154 RenderBlock* createAnonymousColumnsBlock() const; 155 RenderBlock* createAnonymousColumnSpanBlock() const; 156 RenderBlock* createAnonymousBlockWithSameTypeAs(RenderBlock* otherAnonymousBlock) const; 157 158 static void appendRunsForObject(BidiRunList<BidiRun>&, int start, int end, RenderObject*, InlineBidiResolver&); 159 static bool requiresLineBox(const InlineIterator&, bool isLineEmpty = true, bool previousLineBrokeCleanly = true); 160 161 ColumnInfo* columnInfo() const; 162 int columnGap() const; 163 164 // These two functions take the ColumnInfo* to avoid repeated lookups of the info in the global HashMap. 165 unsigned columnCount(ColumnInfo*) const; 166 IntRect columnRectAt(ColumnInfo*, unsigned) const; 167 168 int paginationStrut() const { return m_rareData ? m_rareData->m_paginationStrut : 0; } 169 void setPaginationStrut(int); 170 171 // The page logical offset is the object's offset from the top of the page in the page progression 172 // direction (so an x-offset in vertical text and a y-offset for horizontal text). 173 int pageLogicalOffset() const { return m_rareData ? m_rareData->m_pageLogicalOffset : 0; } 174 void setPageLogicalOffset(int); 175 176 // Accessors for logical width/height and margins in the containing block's block-flow direction. 177 enum ApplyLayoutDeltaMode { ApplyLayoutDelta, DoNotApplyLayoutDelta }; 178 int logicalWidthForChild(RenderBox* child) { return isHorizontalWritingMode() ? child->width() : child->height(); } 179 int logicalHeightForChild(RenderBox* child) { return isHorizontalWritingMode() ? child->height() : child->width(); } 180 int logicalTopForChild(RenderBox* child) { return isHorizontalWritingMode() ? child->y() : child->x(); } 181 void setLogicalLeftForChild(RenderBox* child, int logicalLeft, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta); 182 void setLogicalTopForChild(RenderBox* child, int logicalTop, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta); 183 int marginBeforeForChild(RenderBoxModelObject* child) const; 184 int marginAfterForChild(RenderBoxModelObject* child) const; 185 int marginStartForChild(RenderBoxModelObject* child) const; 186 int marginEndForChild(RenderBoxModelObject* child) const; 187 void setMarginStartForChild(RenderBox* child, int); 188 void setMarginEndForChild(RenderBox* child, int); 189 void setMarginBeforeForChild(RenderBox* child, int); 190 void setMarginAfterForChild(RenderBox* child, int); 191 int collapsedMarginBeforeForChild(RenderBox* child) const; 192 int collapsedMarginAfterForChild(RenderBox* child) const; 193 194 virtual void updateFirstLetter(); 195 196 class MarginValues { 197 public: 198 MarginValues(int beforePos, int beforeNeg, int afterPos, int afterNeg) 199 : m_positiveMarginBefore(beforePos) 200 , m_negativeMarginBefore(beforeNeg) 201 , m_positiveMarginAfter(afterPos) 202 , m_negativeMarginAfter(afterNeg) 203 { } 204 205 int positiveMarginBefore() const { return m_positiveMarginBefore; } 206 int negativeMarginBefore() const { return m_negativeMarginBefore; } 207 int positiveMarginAfter() const { return m_positiveMarginAfter; } 208 int negativeMarginAfter() const { return m_negativeMarginAfter; } 209 210 void setPositiveMarginBefore(int pos) { m_positiveMarginBefore = pos; } 211 void setNegativeMarginBefore(int neg) { m_negativeMarginBefore = neg; } 212 void setPositiveMarginAfter(int pos) { m_positiveMarginAfter = pos; } 213 void setNegativeMarginAfter(int neg) { m_negativeMarginAfter = neg; } 214 215 private: 216 int m_positiveMarginBefore; 217 int m_negativeMarginBefore; 218 int m_positiveMarginAfter; 219 int m_negativeMarginAfter; 220 }; 221 MarginValues marginValuesForChild(RenderBox* child); 222 223 virtual void scrollbarsChanged(bool /*horizontalScrollbarChanged*/, bool /*verticalScrollbarChanged*/) { }; 224 225 int logicalRightOffsetForContent() const { return isHorizontalWritingMode() ? borderLeft() + paddingLeft() + availableLogicalWidth() : borderTop() + paddingTop() + availableLogicalWidth(); } 226 int logicalLeftOffsetForContent() const { return isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop(); } 227 228 protected: 229 // These functions are only used internally to manipulate the render tree structure via remove/insert/appendChildNode. 230 // Since they are typically called only to move objects around within anonymous blocks (which only have layers in 231 // the case of column spans), the default for fullRemoveInsert is false rather than true. 232 void moveChildTo(RenderBlock* to, RenderObject* child, bool fullRemoveInsert = false) 233 { 234 return moveChildTo(to, child, 0, fullRemoveInsert); 235 } 236 void moveChildTo(RenderBlock* to, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert = false); 237 void moveAllChildrenTo(RenderBlock* to, bool fullRemoveInsert = false) 238 { 239 return moveAllChildrenTo(to, 0, fullRemoveInsert); 240 } 241 void moveAllChildrenTo(RenderBlock* to, RenderObject* beforeChild, bool fullRemoveInsert = false) 242 { 243 return moveChildrenTo(to, firstChild(), 0, beforeChild, fullRemoveInsert); 244 } 245 // Move all of the kids from |startChild| up to but excluding |endChild|. 0 can be passed as the endChild to denote 246 // that all the kids from |startChild| onwards should be added. 247 void moveChildrenTo(RenderBlock* to, RenderObject* startChild, RenderObject* endChild, bool fullRemoveInsert = false) 248 { 249 return moveChildrenTo(to, startChild, endChild, 0, fullRemoveInsert); 250 } 251 void moveChildrenTo(RenderBlock* to, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert = false); 252 253 int maxPositiveMarginBefore() const { return m_rareData ? m_rareData->m_margins.positiveMarginBefore() : RenderBlockRareData::positiveMarginBeforeDefault(this); } 254 int maxNegativeMarginBefore() const { return m_rareData ? m_rareData->m_margins.negativeMarginBefore() : RenderBlockRareData::negativeMarginBeforeDefault(this); } 255 int maxPositiveMarginAfter() const { return m_rareData ? m_rareData->m_margins.positiveMarginAfter() : RenderBlockRareData::positiveMarginAfterDefault(this); } 256 int maxNegativeMarginAfter() const { return m_rareData ? m_rareData->m_margins.negativeMarginAfter() : RenderBlockRareData::negativeMarginAfterDefault(this); } 257 258 void setMaxMarginBeforeValues(int pos, int neg); 259 void setMaxMarginAfterValues(int pos, int neg); 260 261 void initMaxMarginValues() 262 { 263 if (m_rareData) { 264 m_rareData->m_margins = MarginValues(RenderBlockRareData::positiveMarginBeforeDefault(this) , RenderBlockRareData::negativeMarginBeforeDefault(this), 265 RenderBlockRareData::positiveMarginAfterDefault(this), RenderBlockRareData::negativeMarginAfterDefault(this)); 266 m_rareData->m_paginationStrut = 0; 267 } 268 } 269 270 virtual void layout(); 271 272 void layoutPositionedObjects(bool relayoutChildren); 273 274 virtual void paint(PaintInfo&, int tx, int ty); 275 virtual void paintObject(PaintInfo&, int tx, int ty); 276 277 int logicalRightOffsetForLine(int position, int fixedOffset, bool applyTextIndent = true, int* logicalHeightRemaining = 0) const; 278 int logicalLeftOffsetForLine(int position, int fixedOffset, bool applyTextIndent = true, int* logicalHeightRemaining = 0) const; 279 280 virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const; 281 virtual void adjustInlineDirectionLineBounds(int /* expansionOpportunityCount */, float& /* logicalLeft */, float& /* logicalWidth */) const { } 282 283 virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); 284 285 virtual void computePreferredLogicalWidths(); 286 287 virtual int firstLineBoxBaseline() const; 288 virtual int lastLineBoxBaseline() const; 289 290 virtual void updateHitTestResult(HitTestResult&, const IntPoint&); 291 292 // Delay update scrollbar until finishDelayRepaint() will be 293 // called. This function is used when a flexbox is laying out its 294 // descendant. If multiple calls are made to startDelayRepaint(), 295 // finishDelayRepaint() will do nothing until finishDelayRepaint() 296 // is called the same number of times. 297 static void startDelayUpdateScrollInfo(); 298 static void finishDelayUpdateScrollInfo(); 299 300 virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle); 301 virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); 302 303 virtual bool hasLineIfEmpty() const; 304 305 bool simplifiedLayout(); 306 void simplifiedNormalFlowLayout(); 307 308 void computeOverflow(int oldClientAfterEdge, bool recomputeFloats = false); 309 virtual void addOverflowFromChildren(); 310 void addOverflowFromFloats(); 311 void addOverflowFromPositionedObjects(); 312 void addOverflowFromBlockChildren(); 313 void addOverflowFromInlineChildren(); 314 315 virtual void addFocusRingRects(Vector<IntRect>&, int tx, int ty); 316 317 #if ENABLE(SVG) 318 // Only used by RenderSVGText, which explicitely overrides RenderBlock::layoutBlock(), do NOT use for anything else. 319 void forceLayoutInlineChildren() 320 { 321 int repaintLogicalTop = 0; 322 int repaintLogicalBottom = 0; 323 layoutInlineChildren(true, repaintLogicalTop, repaintLogicalBottom); 324 } 325 #endif 326 327 private: 328 virtual RenderObjectChildList* virtualChildren() { return children(); } 329 virtual const RenderObjectChildList* virtualChildren() const { return children(); } 330 331 virtual const char* renderName() const; 332 333 virtual bool isRenderBlock() const { return true; } 334 virtual bool isBlockFlow() const { return (!isInline() || isReplaced()) && !isTable(); } 335 virtual bool isInlineBlockOrInlineTable() const { return isInline() && isReplaced(); } 336 337 void makeChildrenNonInline(RenderObject* insertionPoint = 0); 338 virtual void removeLeftoverAnonymousBlock(RenderBlock* child); 339 340 virtual void dirtyLinesFromChangedChild(RenderObject* child) { m_lineBoxes.dirtyLinesFromChangedChild(this, child); } 341 342 void addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild); 343 void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild); 344 void addChildToAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild); 345 virtual void addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild = 0); 346 347 virtual bool isSelfCollapsingBlock() const; 348 349 virtual int collapsedMarginBefore() const { return maxPositiveMarginBefore() - maxNegativeMarginBefore(); } 350 virtual int collapsedMarginAfter() const { return maxPositiveMarginAfter() - maxNegativeMarginAfter(); } 351 352 virtual void repaintOverhangingFloats(bool paintAllDescendants); 353 354 void layoutBlockChildren(bool relayoutChildren, int& maxFloatLogicalBottom); 355 void layoutInlineChildren(bool relayoutChildren, int& repaintLogicalTop, int& repaintLogicalBottom); 356 BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>&, BidiContext*); 357 358 virtual void borderFitAdjust(int& x, int& w) const; // Shrink the box in which the border paints if border-fit is set. 359 360 virtual void updateBeforeAfterContent(PseudoId); 361 362 virtual RootInlineBox* createRootInlineBox(); // Subclassed by SVG and Ruby. 363 364 // Called to lay out the legend for a fieldset or the ruby text of a ruby run. 365 virtual RenderObject* layoutSpecialExcludedChild(bool /*relayoutChildren*/) { return 0; } 366 367 struct FloatWithRect { 368 FloatWithRect(RenderBox* f) 369 : object(f) 370 , rect(IntRect(f->x() - f->marginLeft(), f->y() - f->marginTop(), f->width() + f->marginLeft() + f->marginRight(), f->height() + f->marginTop() + f->marginBottom())) 371 , everHadLayout(f->m_everHadLayout) 372 { 373 } 374 375 RenderBox* object; 376 IntRect rect; 377 bool everHadLayout; 378 }; 379 380 struct FloatingObject { 381 WTF_MAKE_NONCOPYABLE(FloatingObject); WTF_MAKE_FAST_ALLOCATED; 382 public: 383 // Note that Type uses bits so you can use FloatBoth as a mask to query for both left and right. 384 enum Type { FloatLeft = 1, FloatRight = 2, FloatBoth = 3 }; 385 386 FloatingObject(Type type) 387 : m_renderer(0) 388 , m_originatingLine(0) 389 , m_paginationStrut(0) 390 , m_type(type) 391 , m_shouldPaint(true) 392 , m_isDescendant(false) 393 , m_isPlaced(false) 394 { 395 } 396 397 FloatingObject(Type type, const IntRect& frameRect) 398 : m_renderer(0) 399 , m_originatingLine(0) 400 , m_frameRect(frameRect) 401 , m_paginationStrut(0) 402 , m_type(type) 403 , m_shouldPaint(true) 404 , m_isDescendant(false) 405 , m_isPlaced(true) 406 { 407 } 408 409 Type type() const { return static_cast<Type>(m_type); } 410 RenderBox* renderer() const { return m_renderer; } 411 412 bool isPlaced() const { return m_isPlaced; } 413 void setIsPlaced(bool placed = true) { m_isPlaced = placed; } 414 415 int x() const { ASSERT(isPlaced()); return m_frameRect.x(); } 416 int maxX() const { ASSERT(isPlaced()); return m_frameRect.maxX(); } 417 int y() const { ASSERT(isPlaced()); return m_frameRect.y(); } 418 int maxY() const { ASSERT(isPlaced()); return m_frameRect.maxY(); } 419 int width() const { return m_frameRect.width(); } 420 int height() const { return m_frameRect.height(); } 421 422 void setX(int x) { m_frameRect.setX(x); } 423 void setY(int y) { m_frameRect.setY(y); } 424 void setWidth(int width) { m_frameRect.setWidth(width); } 425 void setHeight(int height) { m_frameRect.setHeight(height); } 426 427 const IntRect& frameRect() const { ASSERT(isPlaced()); return m_frameRect; } 428 void setFrameRect(const IntRect& frameRect) { m_frameRect = frameRect; } 429 430 RenderBox* m_renderer; 431 RootInlineBox* m_originatingLine; 432 IntRect m_frameRect; 433 int m_paginationStrut; 434 unsigned m_type : 2; // Type (left or right aligned) 435 bool m_shouldPaint : 1; 436 bool m_isDescendant : 1; 437 bool m_isPlaced : 1; 438 }; 439 440 IntPoint flipFloatForWritingMode(const FloatingObject*, const IntPoint&) const; 441 442 int logicalTopForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->y() : child->x(); } 443 int logicalBottomForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->maxY() : child->maxX(); } 444 int logicalLeftForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->x() : child->y(); } 445 int logicalRightForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->maxX() : child->maxY(); } 446 int logicalWidthForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->width() : child->height(); } 447 void setLogicalTopForFloat(FloatingObject* child, int logicalTop) 448 { 449 if (isHorizontalWritingMode()) 450 child->setY(logicalTop); 451 else 452 child->setX(logicalTop); 453 } 454 void setLogicalLeftForFloat(FloatingObject* child, int logicalLeft) 455 { 456 if (isHorizontalWritingMode()) 457 child->setX(logicalLeft); 458 else 459 child->setY(logicalLeft); 460 } 461 void setLogicalHeightForFloat(FloatingObject* child, int logicalHeight) 462 { 463 if (isHorizontalWritingMode()) 464 child->setHeight(logicalHeight); 465 else 466 child->setWidth(logicalHeight); 467 } 468 void setLogicalWidthForFloat(FloatingObject* child, int logicalWidth) 469 { 470 if (isHorizontalWritingMode()) 471 child->setWidth(logicalWidth); 472 else 473 child->setHeight(logicalWidth); 474 } 475 476 int xPositionForFloatIncludingMargin(const FloatingObject* child) const 477 { 478 if (isHorizontalWritingMode()) 479 return child->x() + child->renderer()->marginLeft(); 480 else 481 return child->x() + marginBeforeForChild(child->renderer()); 482 } 483 484 int yPositionForFloatIncludingMargin(const FloatingObject* child) const 485 { 486 if (isHorizontalWritingMode()) 487 return child->y() + marginBeforeForChild(child->renderer()); 488 else 489 return child->y() + child->renderer()->marginTop(); 490 } 491 492 // The following functions' implementations are in RenderBlockLineLayout.cpp. 493 void checkFloatsInCleanLine(RootInlineBox*, Vector<FloatWithRect>&, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat); 494 RootInlineBox* determineStartPosition(bool& firstLine, bool& fullLayout, bool& previousLineBrokeCleanly, 495 InlineBidiResolver&, Vector<FloatWithRect>& floats, unsigned& numCleanFloats, 496 bool& useRepaintBounds, int& repaintTop, int& repaintBottom); 497 RootInlineBox* determineEndPosition(RootInlineBox* startBox, Vector<FloatWithRect>& floats, size_t floatIndex, InlineIterator& cleanLineStart, 498 BidiStatus& cleanLineBidiStatus, int& yPos); 499 bool matchedEndLine(const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus, 500 RootInlineBox*& endLine, int& endYPos, int& repaintBottom, int& repaintTop); 501 502 void skipTrailingWhitespace(InlineIterator&, bool isLineEmpty, bool previousLineBrokeCleanly); 503 void skipLeadingWhitespace(InlineBidiResolver&, bool isLineEmpty, bool previousLineBrokeCleanly, FloatingObject* lastFloatFromPreviousLine, LineWidth&); 504 typedef std::pair<RenderText*, LazyLineBreakIterator> LineBreakIteratorInfo; 505 InlineIterator findNextLineBreak(InlineBidiResolver&, bool firstLine, bool& isLineEmpty, LineBreakIteratorInfo&, bool& previousLineBrokeCleanly, bool& hyphenated, 506 EClear*, FloatingObject* lastFloatFromPreviousLine, Vector<RenderBox*>& positionedObjects); 507 RootInlineBox* constructLine(BidiRunList<BidiRun>&, bool firstLine, bool lastLine); 508 InlineFlowBox* createLineBoxes(RenderObject*, bool firstLine, InlineBox* childBox); 509 510 void computeInlineDirectionPositionsForLine(RootInlineBox*, bool firstLine, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&); 511 void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&); 512 void deleteEllipsisLineBoxes(); 513 void checkLinesForTextOverflow(); 514 515 // Positions new floats and also adjust all floats encountered on the line if any of them 516 // have to move to the next page/column. 517 bool positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineWidth&); 518 void appendFloatingObjectToLastLine(FloatingObject*); 519 520 // End of functions defined in RenderBlockLineLayout.cpp. 521 522 void paintFloats(PaintInfo&, int tx, int ty, bool preservePhase = false); 523 void paintContents(PaintInfo&, int tx, int ty); 524 void paintColumnContents(PaintInfo&, int tx, int ty, bool paintFloats = false); 525 void paintColumnRules(PaintInfo&, int tx, int ty); 526 void paintChildren(PaintInfo&, int tx, int ty); 527 void paintEllipsisBoxes(PaintInfo&, int tx, int ty); 528 void paintSelection(PaintInfo&, int tx, int ty); 529 void paintCaret(PaintInfo&, int tx, int ty, CaretType); 530 531 FloatingObject* insertFloatingObject(RenderBox*); 532 void removeFloatingObject(RenderBox*); 533 void removeFloatingObjectsBelow(FloatingObject*, int logicalOffset); 534 535 // Called from lineWidth, to position the floats added in the last line. 536 // Returns true if and only if it has positioned any floats. 537 bool positionNewFloats(); 538 539 void clearFloats(); 540 int getClearDelta(RenderBox* child, int yPos); 541 542 virtual bool avoidsFloats() const; 543 544 bool hasOverhangingFloats() { return parent() && !hasColumns() && containsFloats() && lowestFloatLogicalBottom() > logicalHeight(); } 545 bool hasOverhangingFloat(RenderBox*); 546 void addIntrudingFloats(RenderBlock* prev, int xoffset, int yoffset); 547 int addOverhangingFloats(RenderBlock* child, int xoffset, int yoffset, bool makeChildPaintOtherFloats); 548 549 int lowestFloatLogicalBottom(FloatingObject::Type = FloatingObject::FloatBoth) const; 550 int nextFloatLogicalBottomBelow(int) const; 551 552 virtual bool hitTestColumns(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); 553 virtual bool hitTestContents(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); 554 bool hitTestFloats(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty); 555 556 virtual bool isPointInOverflowControl(HitTestResult&, int x, int y, int tx, int ty); 557 558 void computeInlinePreferredLogicalWidths(); 559 void computeBlockPreferredLogicalWidths(); 560 561 // Obtains the nearest enclosing block (including this block) that contributes a first-line style to our inline 562 // children. 563 virtual RenderBlock* firstLineBlock() const; 564 565 virtual IntRect rectWithOutlineForRepaint(RenderBoxModelObject* repaintContainer, int outlineWidth); 566 virtual RenderStyle* outlineStyleForRepaint() const; 567 568 virtual RenderObject* hoverAncestor() const; 569 virtual void updateDragState(bool dragOn); 570 virtual void childBecameNonInline(RenderObject* child); 571 572 virtual IntRect selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool /*clipToVisibleContent*/) 573 { 574 return selectionGapRectsForRepaint(repaintContainer); 575 } 576 virtual bool shouldPaintSelectionGaps() const; 577 bool isSelectionRoot() const; 578 GapRects selectionGaps(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock, 579 int& lastLogicalTop, int& lastLogicalLeft, int& lastLogicalRight, const PaintInfo* = 0); 580 GapRects inlineSelectionGaps(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock, 581 int& lastLogicalTop, int& lastLogicalLeft, int& lastLogicalRight, const PaintInfo*); 582 GapRects blockSelectionGaps(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock, 583 int& lastLogicalTop, int& lastLogicalLeft, int& lastLogicalRight, const PaintInfo*); 584 IntRect blockSelectionGap(RenderBlock* rootBlock, const IntPoint& rootBlockPhysicalPosition, const IntSize& offsetFromRootBlock, 585 int lastLogicalTop, int lastLogicalLeft, int lastLogicalRight, int logicalBottom, const PaintInfo*); 586 int logicalLeftSelectionOffset(RenderBlock* rootBlock, int position); 587 int logicalRightSelectionOffset(RenderBlock* rootBlock, int position); 588 589 virtual void absoluteRects(Vector<IntRect>&, int tx, int ty); 590 virtual void absoluteQuads(Vector<FloatQuad>&); 591 592 int desiredColumnWidth() const; 593 unsigned desiredColumnCount() const; 594 void setDesiredColumnCountAndWidth(int count, int width); 595 596 void paintContinuationOutlines(PaintInfo&, int tx, int ty); 597 598 virtual IntRect localCaretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0); 599 600 void adjustPointToColumnContents(IntPoint&) const; 601 void adjustForBorderFit(int x, int& left, int& right) const; // Helper function for borderFitAdjust 602 603 void markLinesDirtyInBlockRange(int logicalTop, int logicalBottom, RootInlineBox* highest = 0); 604 605 void newLine(EClear); 606 607 Position positionForBox(InlineBox*, bool start = true) const; 608 VisiblePosition positionForPointWithInlineChildren(const IntPoint&); 609 610 // Adjust tx and ty from painting offsets to the local coords of this renderer 611 void offsetForContents(int& tx, int& ty) const; 612 613 void calcColumnWidth(); 614 bool layoutColumns(bool hasSpecifiedPageLogicalHeight, int pageLogicalHeight, LayoutStateMaintainer&); 615 void makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, RenderBlock* newBlockBox, RenderObject* newChild); 616 617 bool expandsToEncloseOverhangingFloats() const; 618 619 void updateScrollInfoAfterLayout(); 620 621 RenderObject* splitAnonymousBlocksAroundChild(RenderObject* beforeChild); 622 void splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock, 623 RenderObject* beforeChild, RenderBoxModelObject* oldCont); 624 void splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox, 625 RenderObject* newChild, RenderBoxModelObject* oldCont); 626 RenderBlock* clone() const; 627 RenderBlock* continuationBefore(RenderObject* beforeChild); 628 RenderBlock* containingColumnsBlock(bool allowAnonymousColumnBlock = true); 629 RenderBlock* columnsBlockForSpanningElement(RenderObject* newChild); 630 631 class MarginInfo { 632 // Collapsing flags for whether we can collapse our margins with our children's margins. 633 bool m_canCollapseWithChildren : 1; 634 bool m_canCollapseMarginBeforeWithChildren : 1; 635 bool m_canCollapseMarginAfterWithChildren : 1; 636 637 // Whether or not we are a quirky container, i.e., do we collapse away top and bottom 638 // margins in our container. Table cells and the body are the common examples. We 639 // also have a custom style property for Safari RSS to deal with TypePad blog articles. 640 bool m_quirkContainer : 1; 641 642 // This flag tracks whether we are still looking at child margins that can all collapse together at the beginning of a block. 643 // They may or may not collapse with the top margin of the block (|m_canCollapseTopWithChildren| tells us that), but they will 644 // always be collapsing with one another. This variable can remain set to true through multiple iterations 645 // as long as we keep encountering self-collapsing blocks. 646 bool m_atBeforeSideOfBlock : 1; 647 648 // This flag is set when we know we're examining bottom margins and we know we're at the bottom of the block. 649 bool m_atAfterSideOfBlock : 1; 650 651 // These variables are used to detect quirky margins that we need to collapse away (in table cells 652 // and in the body element). 653 bool m_marginBeforeQuirk : 1; 654 bool m_marginAfterQuirk : 1; 655 bool m_determinedMarginBeforeQuirk : 1; 656 657 // These flags track the previous maximal positive and negative margins. 658 int m_positiveMargin; 659 int m_negativeMargin; 660 661 public: 662 MarginInfo(RenderBlock* b, int beforeBorderPadding, int afterBorderPadding); 663 664 void setAtBeforeSideOfBlock(bool b) { m_atBeforeSideOfBlock = b; } 665 void setAtAfterSideOfBlock(bool b) { m_atAfterSideOfBlock = b; } 666 void clearMargin() { m_positiveMargin = m_negativeMargin = 0; } 667 void setMarginBeforeQuirk(bool b) { m_marginBeforeQuirk = b; } 668 void setMarginAfterQuirk(bool b) { m_marginAfterQuirk = b; } 669 void setDeterminedMarginBeforeQuirk(bool b) { m_determinedMarginBeforeQuirk = b; } 670 void setPositiveMargin(int p) { m_positiveMargin = p; } 671 void setNegativeMargin(int n) { m_negativeMargin = n; } 672 void setPositiveMarginIfLarger(int p) { if (p > m_positiveMargin) m_positiveMargin = p; } 673 void setNegativeMarginIfLarger(int n) { if (n > m_negativeMargin) m_negativeMargin = n; } 674 675 void setMargin(int p, int n) { m_positiveMargin = p; m_negativeMargin = n; } 676 677 bool atBeforeSideOfBlock() const { return m_atBeforeSideOfBlock; } 678 bool canCollapseWithMarginBefore() const { return m_atBeforeSideOfBlock && m_canCollapseMarginBeforeWithChildren; } 679 bool canCollapseWithMarginAfter() const { return m_atAfterSideOfBlock && m_canCollapseMarginAfterWithChildren; } 680 bool canCollapseMarginBeforeWithChildren() const { return m_canCollapseMarginBeforeWithChildren; } 681 bool canCollapseMarginAfterWithChildren() const { return m_canCollapseMarginAfterWithChildren; } 682 bool quirkContainer() const { return m_quirkContainer; } 683 bool determinedMarginBeforeQuirk() const { return m_determinedMarginBeforeQuirk; } 684 bool marginBeforeQuirk() const { return m_marginBeforeQuirk; } 685 bool marginAfterQuirk() const { return m_marginAfterQuirk; } 686 int positiveMargin() const { return m_positiveMargin; } 687 int negativeMargin() const { return m_negativeMargin; } 688 int margin() const { return m_positiveMargin - m_negativeMargin; } 689 }; 690 691 void layoutBlockChild(RenderBox* child, MarginInfo&, int& previousFloatLogicalBottom, int& maxFloatLogicalBottom); 692 void adjustPositionedBlock(RenderBox* child, const MarginInfo&); 693 void adjustFloatingBlock(const MarginInfo&); 694 bool handleSpecialChild(RenderBox* child, const MarginInfo&); 695 bool handleFloatingChild(RenderBox* child, const MarginInfo&); 696 bool handlePositionedChild(RenderBox* child, const MarginInfo&); 697 bool handleRunInChild(RenderBox* child); 698 int collapseMargins(RenderBox* child, MarginInfo&); 699 int clearFloatsIfNeeded(RenderBox* child, MarginInfo&, int oldTopPosMargin, int oldTopNegMargin, int yPos); 700 int estimateLogicalTopPosition(RenderBox* child, const MarginInfo&); 701 void determineLogicalLeftPositionForChild(RenderBox* child); 702 void handleAfterSideOfBlock(int top, int bottom, MarginInfo&); 703 void setCollapsedBottomMargin(const MarginInfo&); 704 // End helper functions and structs used by layoutBlockChildren. 705 706 // Pagination routines. 707 int nextPageLogicalTop(int logicalOffset) const; // Returns the top of the next page following logicalOffset. 708 int applyBeforeBreak(RenderBox* child, int logicalOffset); // If the child has a before break, then return a new yPos that shifts to the top of the next page/column. 709 int applyAfterBreak(RenderBox* child, int logicalOffset, MarginInfo& marginInfo); // If the child has an after break, then return a new offset that shifts to the top of the next page/column. 710 int adjustForUnsplittableChild(RenderBox* child, int 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. 711 void adjustLinePositionForPagination(RootInlineBox*, int& deltaOffset); // Computes a deltaOffset value that put a line at the top of the next page if it doesn't fit on the current page. 712 713 struct FloatingObjectHashFunctions { 714 static unsigned hash(FloatingObject* key) { return DefaultHash<RenderBox*>::Hash::hash(key->m_renderer); } 715 static bool equal(FloatingObject* a, FloatingObject* b) { return a->m_renderer == b->m_renderer; } 716 static const bool safeToCompareToEmptyOrDeleted = true; 717 }; 718 struct FloatingObjectHashTranslator { 719 static unsigned hash(RenderBox* key) { return DefaultHash<RenderBox*>::Hash::hash(key); } 720 static bool equal(FloatingObject* a, RenderBox* b) { return a->m_renderer == b; } 721 }; 722 typedef ListHashSet<FloatingObject*, 4, FloatingObjectHashFunctions> FloatingObjectSet; 723 typedef FloatingObjectSet::const_iterator FloatingObjectSetIterator; 724 class FloatingObjects { 725 public: 726 FloatingObjects() 727 : m_leftObjectsCount(0) 728 , m_rightObjectsCount(0) 729 { 730 } 731 732 void clear(); 733 void increaseObjectsCount(FloatingObject::Type); 734 void decreaseObjectsCount(FloatingObject::Type); 735 bool hasLeftObjects() const { return m_leftObjectsCount > 0; } 736 bool hasRightObjects() const { return m_rightObjectsCount > 0; } 737 FloatingObjectSet& set() { return m_set; } 738 739 private: 740 FloatingObjectSet m_set; 741 unsigned m_leftObjectsCount; 742 unsigned m_rightObjectsCount; 743 }; 744 OwnPtr<FloatingObjects> m_floatingObjects; 745 746 typedef PositionedObjectsListHashSet::const_iterator Iterator; 747 OwnPtr<PositionedObjectsListHashSet> m_positionedObjects; 748 749 // Allocated only when some of these fields have non-default values 750 struct RenderBlockRareData { 751 WTF_MAKE_NONCOPYABLE(RenderBlockRareData); WTF_MAKE_FAST_ALLOCATED; 752 public: 753 RenderBlockRareData(const RenderBlock* block) 754 : m_margins(positiveMarginBeforeDefault(block), negativeMarginBeforeDefault(block), positiveMarginAfterDefault(block), negativeMarginAfterDefault(block)) 755 , m_paginationStrut(0) 756 , m_pageLogicalOffset(0) 757 { 758 } 759 760 static int positiveMarginBeforeDefault(const RenderBlock* block) 761 { 762 return std::max(block->marginBefore(), 0); 763 } 764 765 static int negativeMarginBeforeDefault(const RenderBlock* block) 766 { 767 return std::max(-block->marginBefore(), 0); 768 } 769 static int positiveMarginAfterDefault(const RenderBlock* block) 770 { 771 return std::max(block->marginAfter(), 0); 772 } 773 static int negativeMarginAfterDefault(const RenderBlock* block) 774 { 775 return std::max(-block->marginAfter(), 0); 776 } 777 778 MarginValues m_margins; 779 int m_paginationStrut; 780 int m_pageLogicalOffset; 781 }; 782 783 OwnPtr<RenderBlockRareData> m_rareData; 784 785 RenderObjectChildList m_children; 786 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>. 787 788 mutable int m_lineHeight : 31; 789 bool m_beingDestroyed : 1; 790 791 // RenderRubyBase objects need to be able to split and merge, moving their children around 792 // (calling moveChildTo, moveAllChildrenTo, and makeChildrenNonInline). 793 friend class RenderRubyBase; 794 friend class LineWidth; // Needs to know FloatingObject 795 796 private: 797 // Used to store state between styleWillChange and styleDidChange 798 static bool s_canPropagateFloatIntoSibling; 799 }; 800 801 inline RenderBlock* toRenderBlock(RenderObject* object) 802 { 803 ASSERT(!object || object->isRenderBlock()); 804 return static_cast<RenderBlock*>(object); 805 } 806 807 inline const RenderBlock* toRenderBlock(const RenderObject* object) 808 { 809 ASSERT(!object || object->isRenderBlock()); 810 return static_cast<const RenderBlock*>(object); 811 } 812 813 // This will catch anyone doing an unnecessary cast. 814 void toRenderBlock(const RenderBlock*); 815 816 } // namespace WebCore 817 818 #endif // RenderBlock_h 819