1 /* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "core/rendering/RenderBlockFlow.h" 33 34 #include "core/frame/FrameView.h" 35 #include "core/rendering/HitTestLocation.h" 36 #include "core/rendering/LayoutRectRecorder.h" 37 #include "core/rendering/LayoutRepainter.h" 38 #include "core/rendering/LineWidth.h" 39 #include "core/rendering/RenderLayer.h" 40 #include "core/rendering/RenderNamedFlowFragment.h" 41 #include "core/rendering/RenderNamedFlowThread.h" 42 #include "core/rendering/RenderText.h" 43 #include "core/rendering/RenderView.h" 44 #include "core/rendering/svg/SVGTextRunRenderingContext.h" 45 #include "platform/text/BidiResolver.h" 46 #include "platform/text/TextRunIterator.h" 47 48 using namespace std; 49 50 namespace WebCore { 51 52 bool RenderBlockFlow::s_canPropagateFloatIntoSibling = false; 53 54 struct SameSizeAsMarginInfo { 55 uint16_t bitfields; 56 LayoutUnit margins[2]; 57 }; 58 59 COMPILE_ASSERT(sizeof(RenderBlockFlow::MarginValues) == sizeof(LayoutUnit[4]), MarginValues_should_stay_small); 60 61 class MarginInfo { 62 // Collapsing flags for whether we can collapse our margins with our children's margins. 63 bool m_canCollapseWithChildren : 1; 64 bool m_canCollapseMarginBeforeWithChildren : 1; 65 bool m_canCollapseMarginAfterWithChildren : 1; 66 67 // Whether or not we are a quirky container, i.e., do we collapse away top and bottom 68 // margins in our container. Table cells and the body are the common examples. We 69 // also have a custom style property for Safari RSS to deal with TypePad blog articles. 70 bool m_quirkContainer : 1; 71 72 // This flag tracks whether we are still looking at child margins that can all collapse together at the beginning of a block. 73 // They may or may not collapse with the top margin of the block (|m_canCollapseTopWithChildren| tells us that), but they will 74 // always be collapsing with one another. This variable can remain set to true through multiple iterations 75 // as long as we keep encountering self-collapsing blocks. 76 bool m_atBeforeSideOfBlock : 1; 77 78 // This flag is set when we know we're examining bottom margins and we know we're at the bottom of the block. 79 bool m_atAfterSideOfBlock : 1; 80 81 // These variables are used to detect quirky margins that we need to collapse away (in table cells 82 // and in the body element). 83 bool m_hasMarginBeforeQuirk : 1; 84 bool m_hasMarginAfterQuirk : 1; 85 bool m_determinedMarginBeforeQuirk : 1; 86 87 bool m_discardMargin : 1; 88 89 // These flags track the previous maximal positive and negative margins. 90 LayoutUnit m_positiveMargin; 91 LayoutUnit m_negativeMargin; 92 93 public: 94 MarginInfo(RenderBlockFlow*, LayoutUnit beforeBorderPadding, LayoutUnit afterBorderPadding); 95 96 void setAtBeforeSideOfBlock(bool b) { m_atBeforeSideOfBlock = b; } 97 void setAtAfterSideOfBlock(bool b) { m_atAfterSideOfBlock = b; } 98 void clearMargin() 99 { 100 m_positiveMargin = 0; 101 m_negativeMargin = 0; 102 } 103 void setHasMarginBeforeQuirk(bool b) { m_hasMarginBeforeQuirk = b; } 104 void setHasMarginAfterQuirk(bool b) { m_hasMarginAfterQuirk = b; } 105 void setDeterminedMarginBeforeQuirk(bool b) { m_determinedMarginBeforeQuirk = b; } 106 void setPositiveMargin(LayoutUnit p) { ASSERT(!m_discardMargin); m_positiveMargin = p; } 107 void setNegativeMargin(LayoutUnit n) { ASSERT(!m_discardMargin); m_negativeMargin = n; } 108 void setPositiveMarginIfLarger(LayoutUnit p) 109 { 110 ASSERT(!m_discardMargin); 111 if (p > m_positiveMargin) 112 m_positiveMargin = p; 113 } 114 void setNegativeMarginIfLarger(LayoutUnit n) 115 { 116 ASSERT(!m_discardMargin); 117 if (n > m_negativeMargin) 118 m_negativeMargin = n; 119 } 120 121 void setMargin(LayoutUnit p, LayoutUnit n) { ASSERT(!m_discardMargin); m_positiveMargin = p; m_negativeMargin = n; } 122 void setCanCollapseMarginAfterWithChildren(bool collapse) { m_canCollapseMarginAfterWithChildren = collapse; } 123 void setDiscardMargin(bool value) { m_discardMargin = value; } 124 125 bool atBeforeSideOfBlock() const { return m_atBeforeSideOfBlock; } 126 bool canCollapseWithMarginBefore() const { return m_atBeforeSideOfBlock && m_canCollapseMarginBeforeWithChildren; } 127 bool canCollapseWithMarginAfter() const { return m_atAfterSideOfBlock && m_canCollapseMarginAfterWithChildren; } 128 bool canCollapseMarginBeforeWithChildren() const { return m_canCollapseMarginBeforeWithChildren; } 129 bool canCollapseMarginAfterWithChildren() const { return m_canCollapseMarginAfterWithChildren; } 130 bool quirkContainer() const { return m_quirkContainer; } 131 bool determinedMarginBeforeQuirk() const { return m_determinedMarginBeforeQuirk; } 132 bool hasMarginBeforeQuirk() const { return m_hasMarginBeforeQuirk; } 133 bool hasMarginAfterQuirk() const { return m_hasMarginAfterQuirk; } 134 LayoutUnit positiveMargin() const { return m_positiveMargin; } 135 LayoutUnit negativeMargin() const { return m_negativeMargin; } 136 bool discardMargin() const { return m_discardMargin; } 137 LayoutUnit margin() const { return m_positiveMargin - m_negativeMargin; } 138 }; 139 140 static bool inNormalFlow(RenderBox* child) 141 { 142 RenderBlock* curr = child->containingBlock(); 143 RenderView* renderView = child->view(); 144 while (curr && curr != renderView) { 145 if (curr->hasColumns() || curr->isRenderFlowThread()) 146 return true; 147 if (curr->isFloatingOrOutOfFlowPositioned()) 148 return false; 149 curr = curr->containingBlock(); 150 } 151 return true; 152 } 153 154 RenderBlockFlow::RenderBlockFlow(ContainerNode* node) 155 : RenderBlock(node) 156 { 157 COMPILE_ASSERT(sizeof(MarginInfo) == sizeof(SameSizeAsMarginInfo), MarginInfo_should_stay_small); 158 } 159 160 RenderBlockFlow::~RenderBlockFlow() 161 { 162 } 163 164 RenderBlockFlow* RenderBlockFlow::createAnonymous(Document* document) 165 { 166 RenderBlockFlow* renderer = new RenderBlockFlow(0); 167 renderer->setDocumentForAnonymous(document); 168 return renderer; 169 } 170 171 RenderBlockFlow* RenderBlockFlow::createAnonymousBlockFlow() const 172 { 173 return toRenderBlockFlow(createAnonymousWithParentRendererAndDisplay(this, BLOCK)); 174 } 175 176 void RenderBlockFlow::willBeDestroyed() 177 { 178 if (lineGridBox()) 179 lineGridBox()->destroy(); 180 181 if (renderNamedFlowFragment()) 182 setRenderNamedFlowFragment(0); 183 184 RenderBlock::willBeDestroyed(); 185 } 186 187 bool RenderBlockFlow::relayoutForPagination(bool hasSpecifiedPageLogicalHeight, LayoutUnit pageLogicalHeight, LayoutStateMaintainer& statePusher) 188 { 189 if (!hasColumns()) 190 return false; 191 192 OwnPtr<RenderOverflow> savedOverflow = m_overflow.release(); 193 if (childrenInline()) 194 addOverflowFromInlineChildren(); 195 else 196 addOverflowFromBlockChildren(); 197 LayoutUnit layoutOverflowLogicalBottom = (isHorizontalWritingMode() ? layoutOverflowRect().maxY() : layoutOverflowRect().maxX()) - borderBefore() - paddingBefore(); 198 199 // FIXME: We don't balance properly at all in the presence of forced page breaks. We need to understand what 200 // the distance between forced page breaks is so that we can avoid making the minimum column height too tall. 201 ColumnInfo* colInfo = columnInfo(); 202 if (!hasSpecifiedPageLogicalHeight) { 203 LayoutUnit columnHeight = pageLogicalHeight; 204 int minColumnCount = colInfo->forcedBreaks() + 1; 205 int desiredColumnCount = colInfo->desiredColumnCount(); 206 if (minColumnCount >= desiredColumnCount) { 207 // The forced page breaks are in control of the balancing. Just set the column height to the 208 // maximum page break distance. 209 if (!pageLogicalHeight) { 210 LayoutUnit distanceBetweenBreaks = max<LayoutUnit>(colInfo->maximumDistanceBetweenForcedBreaks(), 211 view()->layoutState()->pageLogicalOffset(this, borderBefore() + paddingBefore() + layoutOverflowLogicalBottom) - colInfo->forcedBreakOffset()); 212 columnHeight = max(colInfo->minimumColumnHeight(), distanceBetweenBreaks); 213 } 214 } else if (layoutOverflowLogicalBottom > boundedMultiply(pageLogicalHeight, desiredColumnCount)) { 215 // Now that we know the intrinsic height of the columns, we have to rebalance them. 216 columnHeight = max<LayoutUnit>(colInfo->minimumColumnHeight(), ceilf((float)layoutOverflowLogicalBottom / desiredColumnCount)); 217 } 218 219 if (columnHeight && columnHeight != pageLogicalHeight) { 220 statePusher.pop(); 221 setEverHadLayout(true); 222 layoutBlock(false, columnHeight); 223 return true; 224 } 225 } 226 227 if (pageLogicalHeight) 228 colInfo->setColumnCountAndHeight(ceilf((float)layoutOverflowLogicalBottom / pageLogicalHeight), pageLogicalHeight); 229 230 if (columnCount(colInfo)) { 231 setLogicalHeight(borderBefore() + paddingBefore() + colInfo->columnHeight() + borderAfter() + paddingAfter() + scrollbarLogicalHeight()); 232 m_overflow.clear(); 233 } else { 234 m_overflow = savedOverflow.release(); 235 } 236 237 return false; 238 } 239 240 void RenderBlockFlow::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight) 241 { 242 ASSERT(needsLayout()); 243 244 if (isInline() && !isInlineBlockOrInlineTable()) // Inline <form>s inside various table elements can cause us to come in here. Bail. 245 return; 246 247 if (!relayoutChildren && simplifiedLayout()) 248 return; 249 250 LayoutRepainter repainter(*this, checkForRepaintDuringLayout()); 251 252 if (updateLogicalWidthAndColumnWidth()) 253 relayoutChildren = true; 254 255 rebuildFloatsFromIntruding(); 256 257 LayoutUnit previousHeight = logicalHeight(); 258 // FIXME: should this start out as borderAndPaddingLogicalHeight() + scrollbarLogicalHeight(), 259 // for consistency with other render classes? 260 setLogicalHeight(0); 261 262 bool pageLogicalHeightChanged = false; 263 bool hasSpecifiedPageLogicalHeight = false; 264 checkForPaginationLogicalHeightChange(pageLogicalHeight, pageLogicalHeightChanged, hasSpecifiedPageLogicalHeight); 265 266 RenderView* renderView = view(); 267 LayoutStateMaintainer statePusher(renderView, this, locationOffset(), hasColumns() || hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode(), pageLogicalHeight, pageLogicalHeightChanged, columnInfo()); 268 269 // Regions changing widths can force us to relayout our children. 270 RenderFlowThread* flowThread = flowThreadContainingBlock(); 271 if (logicalWidthChangedInRegions(flowThread)) 272 relayoutChildren = true; 273 if (updateRegionsAndShapesLogicalSize(flowThread)) 274 relayoutChildren = true; 275 if (!relayoutChildren && isRenderNamedFlowFragmentContainer()) 276 relayoutChildren = true; 277 278 // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, to track 279 // our current maximal positive and negative margins. These values are used when we 280 // are collapsed with adjacent blocks, so for example, if you have block A and B 281 // collapsing together, then you'd take the maximal positive margin from both A and B 282 // and subtract it from the maximal negative margin from both A and B to get the 283 // true collapsed margin. This algorithm is recursive, so when we finish layout() 284 // our block knows its current maximal positive/negative values. 285 // 286 // Start out by setting our margin values to our current margins. Table cells have 287 // no margins, so we don't fill in the values for table cells. 288 bool isCell = isTableCell(); 289 if (!isCell) { 290 initMaxMarginValues(); 291 292 setHasMarginBeforeQuirk(style()->hasMarginBeforeQuirk()); 293 setHasMarginAfterQuirk(style()->hasMarginAfterQuirk()); 294 setPaginationStrut(0); 295 } 296 297 SubtreeLayoutScope layoutScope(this); 298 299 m_repaintLogicalTop = 0; 300 m_repaintLogicalBottom = 0; 301 LayoutUnit maxFloatLogicalBottom = 0; 302 if (!firstChild() && !isAnonymousBlock()) 303 setChildrenInline(true); 304 if (childrenInline()) 305 layoutInlineChildren(relayoutChildren, m_repaintLogicalTop, m_repaintLogicalBottom); 306 else 307 layoutBlockChildren(relayoutChildren, maxFloatLogicalBottom, layoutScope); 308 309 if (frameView()->partialLayout().isStopping()) { 310 statePusher.pop(); 311 return; 312 } 313 314 // Expand our intrinsic height to encompass floats. 315 LayoutUnit toAdd = borderAfter() + paddingAfter() + scrollbarLogicalHeight(); 316 if (lowestFloatLogicalBottom() > (logicalHeight() - toAdd) && expandsToEncloseOverhangingFloats()) 317 setLogicalHeight(lowestFloatLogicalBottom() + toAdd); 318 319 if (relayoutForPagination(hasSpecifiedPageLogicalHeight, pageLogicalHeight, statePusher) || relayoutToAvoidWidows(statePusher)) { 320 ASSERT(!shouldBreakAtLineToAvoidWidow()); 321 return; 322 } 323 324 // Calculate our new height. 325 LayoutUnit oldHeight = logicalHeight(); 326 LayoutUnit oldClientAfterEdge = clientLogicalBottom(); 327 328 // Before updating the final size of the flow thread make sure a forced break is applied after the content. 329 // This ensures the size information is correctly computed for the last auto-height region receiving content. 330 if (isRenderFlowThread()) 331 toRenderFlowThread(this)->applyBreakAfterContent(oldClientAfterEdge); 332 333 updateLogicalHeight(); 334 LayoutUnit newHeight = logicalHeight(); 335 if (oldHeight != newHeight) { 336 if (oldHeight > newHeight && maxFloatLogicalBottom > newHeight && !childrenInline()) { 337 // One of our children's floats may have become an overhanging float for us. We need to look for it. 338 for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { 339 if (child->isRenderBlockFlow() && !child->isFloatingOrOutOfFlowPositioned()) { 340 RenderBlockFlow* block = toRenderBlockFlow(child); 341 if (block->lowestFloatLogicalBottom() + block->logicalTop() > newHeight) 342 addOverhangingFloats(block, false); 343 } 344 } 345 } 346 } 347 348 bool heightChanged = (previousHeight != newHeight); 349 if (heightChanged) 350 relayoutChildren = true; 351 352 layoutPositionedObjects(relayoutChildren || isRoot()); 353 354 updateRegionsAndShapesAfterChildLayout(flowThread, heightChanged); 355 356 // Add overflow from children (unless we're multi-column, since in that case all our child overflow is clipped anyway). 357 computeOverflow(oldClientAfterEdge); 358 359 statePusher.pop(); 360 361 fitBorderToLinesIfNeeded(); 362 363 if (frameView()->partialLayout().isStopping()) 364 return; 365 366 if (renderView->layoutState()->m_pageLogicalHeight) 367 setPageLogicalOffset(renderView->layoutState()->pageLogicalOffset(this, logicalTop())); 368 369 updateLayerTransform(); 370 371 // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if 372 // we overflow or not. 373 updateScrollInfoAfterLayout(); 374 375 // Repaint with our new bounds if they are different from our old bounds. 376 bool didFullRepaint = repainter.repaintAfterLayout(); 377 if (!didFullRepaint && m_repaintLogicalTop != m_repaintLogicalBottom && (style()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) { 378 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) 379 setShouldRepaintOverflowIfNeeded(true); 380 else 381 repaintOverflow(); 382 } 383 384 clearNeedsLayout(); 385 } 386 387 void RenderBlockFlow::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom) 388 { 389 LayoutUnit oldPosMarginBefore = maxPositiveMarginBefore(); 390 LayoutUnit oldNegMarginBefore = maxNegativeMarginBefore(); 391 392 // The child is a normal flow object. Compute the margins we will use for collapsing now. 393 child->computeAndSetBlockDirectionMargins(this); 394 395 // Try to guess our correct logical top position. In most cases this guess will 396 // be correct. Only if we're wrong (when we compute the real logical top position) 397 // will we have to potentially relayout. 398 LayoutUnit estimateWithoutPagination; 399 LayoutUnit logicalTopEstimate = estimateLogicalTopPosition(child, marginInfo, estimateWithoutPagination); 400 401 // Cache our old rect so that we can dirty the proper repaint rects if the child moves. 402 LayoutRect oldRect = child->frameRect(); 403 LayoutUnit oldLogicalTop = logicalTopForChild(child); 404 405 #if !ASSERT_DISABLED 406 LayoutSize oldLayoutDelta = view()->layoutDelta(); 407 #endif 408 // Go ahead and position the child as though it didn't collapse with the top. 409 setLogicalTopForChild(child, logicalTopEstimate, ApplyLayoutDelta); 410 411 RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0; 412 RenderBlockFlow* childRenderBlockFlow = (childRenderBlock && child->isRenderBlockFlow()) ? toRenderBlockFlow(child) : 0; 413 bool markDescendantsWithFloats = false; 414 if (logicalTopEstimate != oldLogicalTop && !child->avoidsFloats() && childRenderBlock && childRenderBlock->containsFloats()) { 415 markDescendantsWithFloats = true; 416 } else if (UNLIKELY(logicalTopEstimate.mightBeSaturated())) { 417 // logicalTopEstimate, returned by estimateLogicalTopPosition, might be saturated for 418 // very large elements. If it does the comparison with oldLogicalTop might yield a 419 // false negative as adding and removing margins, borders etc from a saturated number 420 // might yield incorrect results. If this is the case always mark for layout. 421 markDescendantsWithFloats = true; 422 } else if (!child->avoidsFloats() || child->shrinkToAvoidFloats()) { 423 // If an element might be affected by the presence of floats, then always mark it for 424 // layout. 425 LayoutUnit fb = max(previousFloatLogicalBottom, lowestFloatLogicalBottom()); 426 if (fb > logicalTopEstimate) 427 markDescendantsWithFloats = true; 428 } 429 430 if (childRenderBlockFlow) { 431 if (markDescendantsWithFloats) 432 childRenderBlockFlow->markAllDescendantsWithFloatsForLayout(); 433 if (!child->isWritingModeRoot()) 434 previousFloatLogicalBottom = max(previousFloatLogicalBottom, oldLogicalTop + childRenderBlockFlow->lowestFloatLogicalBottom()); 435 } 436 437 SubtreeLayoutScope layoutScope(child); 438 if (!child->needsLayout()) 439 child->markForPaginationRelayoutIfNeeded(layoutScope); 440 441 bool childHadLayout = child->everHadLayout(); 442 bool childNeededLayout = child->needsLayout(); 443 if (childNeededLayout) 444 child->layout(); 445 446 if (frameView()->partialLayout().isStopping()) 447 return; 448 449 // Cache if we are at the top of the block right now. 450 bool atBeforeSideOfBlock = marginInfo.atBeforeSideOfBlock(); 451 452 // Now determine the correct ypos based off examination of collapsing margin 453 // values. 454 LayoutUnit logicalTopBeforeClear = collapseMargins(child, marginInfo); 455 456 // Now check for clear. 457 LayoutUnit logicalTopAfterClear = clearFloatsIfNeeded(child, marginInfo, oldPosMarginBefore, oldNegMarginBefore, logicalTopBeforeClear); 458 459 bool paginated = view()->layoutState()->isPaginated(); 460 if (paginated) { 461 logicalTopAfterClear = adjustBlockChildForPagination(logicalTopAfterClear, estimateWithoutPagination, child, 462 atBeforeSideOfBlock && logicalTopBeforeClear == logicalTopAfterClear); 463 } 464 465 setLogicalTopForChild(child, logicalTopAfterClear, ApplyLayoutDelta); 466 467 // Now we have a final top position. See if it really does end up being different from our estimate. 468 // clearFloatsIfNeeded can also mark the child as needing a layout even though we didn't move. This happens 469 // when collapseMargins dynamically adds overhanging floats because of a child with negative margins. 470 if (logicalTopAfterClear != logicalTopEstimate || child->needsLayout() || (paginated && childRenderBlock && childRenderBlock->shouldBreakAtLineToAvoidWidow())) { 471 SubtreeLayoutScope layoutScope(child); 472 if (child->shrinkToAvoidFloats()) { 473 // The child's width depends on the line width. 474 // When the child shifts to clear an item, its width can 475 // change (because it has more available line width). 476 // So go ahead and mark the item as dirty. 477 layoutScope.setChildNeedsLayout(child); 478 } 479 480 if (childRenderBlock) { 481 if (!child->avoidsFloats() && childRenderBlock->containsFloats()) 482 childRenderBlockFlow->markAllDescendantsWithFloatsForLayout(); 483 if (!child->needsLayout()) 484 child->markForPaginationRelayoutIfNeeded(layoutScope); 485 } 486 487 // Our guess was wrong. Make the child lay itself out again. 488 child->layoutIfNeeded(); 489 } 490 491 // We are no longer at the top of the block if we encounter a non-empty child. 492 // This has to be done after checking for clear, so that margins can be reset if a clear occurred. 493 if (marginInfo.atBeforeSideOfBlock() && !child->isSelfCollapsingBlock()) 494 marginInfo.setAtBeforeSideOfBlock(false); 495 496 // Now place the child in the correct left position 497 determineLogicalLeftPositionForChild(child, ApplyLayoutDelta); 498 499 LayoutSize childOffset = child->location() - oldRect.location(); 500 relayoutShapeDescendantIfMoved(childRenderBlock, childOffset); 501 502 // Update our height now that the child has been placed in the correct position. 503 setLogicalHeight(logicalHeight() + logicalHeightForChild(child)); 504 if (mustSeparateMarginAfterForChild(child)) { 505 setLogicalHeight(logicalHeight() + marginAfterForChild(child)); 506 marginInfo.clearMargin(); 507 } 508 // If the child has overhanging floats that intrude into following siblings (or possibly out 509 // of this block), then the parent gets notified of the floats now. 510 if (childRenderBlockFlow && childRenderBlockFlow->containsFloats()) 511 maxFloatLogicalBottom = max(maxFloatLogicalBottom, addOverhangingFloats(childRenderBlockFlow, !childNeededLayout)); 512 513 if (childOffset.width() || childOffset.height()) { 514 view()->addLayoutDelta(childOffset); 515 516 // If the child moved, we have to repaint it as well as any floating/positioned 517 // descendants. An exception is if we need a layout. In this case, we know we're going to 518 // repaint ourselves (and the child) anyway. 519 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && childHadLayout && !selfNeedsLayout()) 520 child->repaintOverhangingFloats(true); 521 else if (childHadLayout && !selfNeedsLayout() && child->checkForRepaintDuringLayout()) 522 child->repaintDuringLayoutIfMoved(oldRect); 523 } 524 525 if (!childHadLayout && child->checkForRepaintDuringLayout()) { 526 if (!RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) 527 child->repaint(); 528 child->repaintOverhangingFloats(true); 529 } 530 531 if (paginated) { 532 // Check for an after page/column break. 533 LayoutUnit newHeight = applyAfterBreak(child, logicalHeight(), marginInfo); 534 if (newHeight != height()) 535 setLogicalHeight(newHeight); 536 } 537 538 ASSERT(view()->layoutDeltaMatches(oldLayoutDelta)); 539 } 540 541 LayoutUnit RenderBlockFlow::adjustBlockChildForPagination(LayoutUnit logicalTopAfterClear, LayoutUnit estimateWithoutPagination, RenderBox* child, bool atBeforeSideOfBlock) 542 { 543 RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0; 544 545 if (estimateWithoutPagination != logicalTopAfterClear) { 546 // Our guess prior to pagination movement was wrong. Before we attempt to paginate, let's try again at the new 547 // position. 548 setLogicalHeight(logicalTopAfterClear); 549 setLogicalTopForChild(child, logicalTopAfterClear, ApplyLayoutDelta); 550 551 if (child->shrinkToAvoidFloats()) { 552 // The child's width depends on the line width. 553 // When the child shifts to clear an item, its width can 554 // change (because it has more available line width). 555 // So go ahead and mark the item as dirty. 556 child->setChildNeedsLayout(MarkOnlyThis); 557 } 558 559 SubtreeLayoutScope layoutScope(child); 560 561 if (childRenderBlock) { 562 if (!child->avoidsFloats() && childRenderBlock->containsFloats()) 563 toRenderBlockFlow(childRenderBlock)->markAllDescendantsWithFloatsForLayout(); 564 if (!child->needsLayout()) 565 child->markForPaginationRelayoutIfNeeded(layoutScope); 566 } 567 568 // Our guess was wrong. Make the child lay itself out again. 569 child->layoutIfNeeded(); 570 } 571 572 LayoutUnit oldTop = logicalTopAfterClear; 573 574 // If the object has a page or column break value of "before", then we should shift to the top of the next page. 575 LayoutUnit result = applyBeforeBreak(child, logicalTopAfterClear); 576 577 if (pageLogicalHeightForOffset(result)) { 578 LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset(result, ExcludePageBoundary); 579 LayoutUnit spaceShortage = child->logicalHeight() - remainingLogicalHeight; 580 if (spaceShortage > 0) { 581 // If the child crosses a column boundary, report a break, in case nothing inside it has already 582 // done so. The column balancer needs to know how much it has to stretch the columns to make more 583 // content fit. If no breaks are reported (but do occur), the balancer will have no clue. FIXME: 584 // This should be improved, though, because here we just pretend that the child is 585 // unsplittable. A splittable child, on the other hand, has break opportunities at every position 586 // where there's no child content, border or padding. In other words, we risk stretching more 587 // than necessary. 588 setPageBreak(result, spaceShortage); 589 } 590 } 591 592 // For replaced elements and scrolled elements, we want to shift them to the next page if they don't fit on the current one. 593 LayoutUnit logicalTopBeforeUnsplittableAdjustment = result; 594 LayoutUnit logicalTopAfterUnsplittableAdjustment = adjustForUnsplittableChild(child, result); 595 596 LayoutUnit paginationStrut = 0; 597 LayoutUnit unsplittableAdjustmentDelta = logicalTopAfterUnsplittableAdjustment - logicalTopBeforeUnsplittableAdjustment; 598 if (unsplittableAdjustmentDelta) 599 paginationStrut = unsplittableAdjustmentDelta; 600 else if (childRenderBlock && childRenderBlock->paginationStrut()) 601 paginationStrut = childRenderBlock->paginationStrut(); 602 603 if (paginationStrut) { 604 // We are willing to propagate out to our parent block as long as we were at the top of the block prior 605 // to collapsing our margins, and as long as we didn't clear or move as a result of other pagination. 606 if (atBeforeSideOfBlock && oldTop == result && !isOutOfFlowPositioned() && !isTableCell()) { 607 // FIXME: Should really check if we're exceeding the page height before propagating the strut, but we don't 608 // have all the information to do so (the strut only has the remaining amount to push). Gecko gets this wrong too 609 // and pushes to the next page anyway, so not too concerned about it. 610 setPaginationStrut(result + paginationStrut); 611 if (childRenderBlock) 612 childRenderBlock->setPaginationStrut(0); 613 } else { 614 result += paginationStrut; 615 } 616 } 617 618 // Similar to how we apply clearance. Go ahead and boost height() to be the place where we're going to position the child. 619 setLogicalHeight(logicalHeight() + (result - oldTop)); 620 621 // Return the final adjusted logical top. 622 return result; 623 } 624 625 void RenderBlockFlow::rebuildFloatsFromIntruding() 626 { 627 if (m_floatingObjects) 628 m_floatingObjects->setHorizontalWritingMode(isHorizontalWritingMode()); 629 630 HashSet<RenderBox*> oldIntrudingFloatSet; 631 if (!childrenInline() && m_floatingObjects) { 632 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 633 FloatingObjectSetIterator end = floatingObjectSet.end(); 634 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { 635 FloatingObject* floatingObject = *it; 636 if (!floatingObject->isDescendant()) 637 oldIntrudingFloatSet.add(floatingObject->renderer()); 638 } 639 } 640 641 // Inline blocks are covered by the isReplaced() check in the avoidFloats method. 642 if (avoidsFloats() || isRoot() || isRenderView() || isFloatingOrOutOfFlowPositioned() || isTableCell()) { 643 if (m_floatingObjects) { 644 m_floatingObjects->clear(); 645 } 646 if (!oldIntrudingFloatSet.isEmpty()) 647 markAllDescendantsWithFloatsForLayout(); 648 return; 649 } 650 651 RendererToFloatInfoMap floatMap; 652 653 if (m_floatingObjects) { 654 if (childrenInline()) 655 m_floatingObjects->moveAllToFloatInfoMap(floatMap); 656 else 657 m_floatingObjects->clear(); 658 } 659 660 // We should not process floats if the parent node is not a RenderBlockFlow. Otherwise, we will add 661 // floats in an invalid context. This will cause a crash arising from a bad cast on the parent. 662 // See <rdar://problem/8049753>, where float property is applied on a text node in a SVG. 663 if (!parent() || !parent()->isRenderBlockFlow()) 664 return; 665 666 // Attempt to locate a previous sibling with overhanging floats. We skip any elements that are 667 // out of flow (like floating/positioned elements), and we also skip over any objects that may have shifted 668 // to avoid floats. 669 RenderBlockFlow* parentBlockFlow = toRenderBlockFlow(parent()); 670 bool parentHasFloats = false; 671 RenderObject* prev = previousSibling(); 672 while (prev && (prev->isFloatingOrOutOfFlowPositioned() || !prev->isBox() || !prev->isRenderBlock() || toRenderBlock(prev)->avoidsFloats())) { 673 if (prev->isFloating()) 674 parentHasFloats = true; 675 prev = prev->previousSibling(); 676 } 677 678 // First add in floats from the parent. Self-collapsing blocks let their parent track any floats that intrude into 679 // them (as opposed to floats they contain themselves) so check for those here too. 680 LayoutUnit logicalTopOffset = logicalTop(); 681 if (parentHasFloats || (prev && toRenderBlockFlow(prev)->isSelfCollapsingBlock() && parentBlockFlow->lowestFloatLogicalBottom() > logicalTopOffset)) 682 addIntrudingFloats(parentBlockFlow, parentBlockFlow->logicalLeftOffsetForContent(), logicalTopOffset); 683 684 LayoutUnit logicalLeftOffset = 0; 685 if (prev) { 686 logicalTopOffset -= toRenderBox(prev)->logicalTop(); 687 } else { 688 prev = parentBlockFlow; 689 logicalLeftOffset += parentBlockFlow->logicalLeftOffsetForContent(); 690 } 691 692 // Add overhanging floats from the previous RenderBlockFlow, but only if it has a float that intrudes into our space. 693 RenderBlockFlow* blockFlow = toRenderBlockFlow(prev); 694 if (blockFlow->m_floatingObjects && blockFlow->lowestFloatLogicalBottom() > logicalTopOffset) 695 addIntrudingFloats(blockFlow, logicalLeftOffset, logicalTopOffset); 696 697 if (childrenInline()) { 698 LayoutUnit changeLogicalTop = LayoutUnit::max(); 699 LayoutUnit changeLogicalBottom = LayoutUnit::min(); 700 if (m_floatingObjects) { 701 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 702 FloatingObjectSetIterator end = floatingObjectSet.end(); 703 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { 704 FloatingObject* floatingObject = *it; 705 FloatingObject* oldFloatingObject = floatMap.get(floatingObject->renderer()); 706 LayoutUnit logicalBottom = logicalBottomForFloat(floatingObject); 707 if (oldFloatingObject) { 708 LayoutUnit oldLogicalBottom = logicalBottomForFloat(oldFloatingObject); 709 if (logicalWidthForFloat(floatingObject) != logicalWidthForFloat(oldFloatingObject) || logicalLeftForFloat(floatingObject) != logicalLeftForFloat(oldFloatingObject)) { 710 changeLogicalTop = 0; 711 changeLogicalBottom = max(changeLogicalBottom, max(logicalBottom, oldLogicalBottom)); 712 } else { 713 if (logicalBottom != oldLogicalBottom) { 714 changeLogicalTop = min(changeLogicalTop, min(logicalBottom, oldLogicalBottom)); 715 changeLogicalBottom = max(changeLogicalBottom, max(logicalBottom, oldLogicalBottom)); 716 } 717 LayoutUnit logicalTop = logicalTopForFloat(floatingObject); 718 LayoutUnit oldLogicalTop = logicalTopForFloat(oldFloatingObject); 719 if (logicalTop != oldLogicalTop) { 720 changeLogicalTop = min(changeLogicalTop, min(logicalTop, oldLogicalTop)); 721 changeLogicalBottom = max(changeLogicalBottom, max(logicalTop, oldLogicalTop)); 722 } 723 } 724 725 floatMap.remove(floatingObject->renderer()); 726 if (oldFloatingObject->originatingLine() && !selfNeedsLayout()) { 727 ASSERT(oldFloatingObject->originatingLine()->renderer() == this); 728 oldFloatingObject->originatingLine()->markDirty(); 729 } 730 delete oldFloatingObject; 731 } else { 732 changeLogicalTop = 0; 733 changeLogicalBottom = max(changeLogicalBottom, logicalBottom); 734 } 735 } 736 } 737 738 RendererToFloatInfoMap::iterator end = floatMap.end(); 739 for (RendererToFloatInfoMap::iterator it = floatMap.begin(); it != end; ++it) { 740 FloatingObject* floatingObject = (*it).value; 741 if (!floatingObject->isDescendant()) { 742 changeLogicalTop = 0; 743 changeLogicalBottom = max(changeLogicalBottom, logicalBottomForFloat(floatingObject)); 744 } 745 } 746 deleteAllValues(floatMap); 747 748 markLinesDirtyInBlockRange(changeLogicalTop, changeLogicalBottom); 749 } else if (!oldIntrudingFloatSet.isEmpty()) { 750 // If there are previously intruding floats that no longer intrude, then children with floats 751 // should also get layout because they might need their floating object lists cleared. 752 if (m_floatingObjects->set().size() < oldIntrudingFloatSet.size()) { 753 markAllDescendantsWithFloatsForLayout(); 754 } else { 755 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 756 FloatingObjectSetIterator end = floatingObjectSet.end(); 757 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end && !oldIntrudingFloatSet.isEmpty(); ++it) 758 oldIntrudingFloatSet.remove((*it)->renderer()); 759 if (!oldIntrudingFloatSet.isEmpty()) 760 markAllDescendantsWithFloatsForLayout(); 761 } 762 } 763 } 764 765 void RenderBlockFlow::layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloatLogicalBottom, SubtreeLayoutScope& layoutScope) 766 { 767 dirtyForLayoutFromPercentageHeightDescendants(layoutScope); 768 769 LayoutUnit beforeEdge = borderBefore() + paddingBefore(); 770 LayoutUnit afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeight(); 771 772 setLogicalHeight(beforeEdge); 773 774 // Lay out our hypothetical grid line as though it occurs at the top of the block. 775 if (view()->layoutState()->lineGrid() == this) 776 layoutLineGridBox(); 777 778 // The margin struct caches all our current margin collapsing state. The compact struct caches state when we encounter compacts, 779 MarginInfo marginInfo(this, beforeEdge, afterEdge); 780 781 // Fieldsets need to find their legend and position it inside the border of the object. 782 // The legend then gets skipped during normal layout. The same is true for ruby text. 783 // It doesn't get included in the normal layout process but is instead skipped. 784 RenderObject* childToExclude = layoutSpecialExcludedChild(relayoutChildren, layoutScope); 785 786 LayoutUnit previousFloatLogicalBottom = 0; 787 maxFloatLogicalBottom = 0; 788 789 RenderBox* next = firstChildBox(); 790 791 while (next) { 792 RenderBox* child = next; 793 next = child->nextSiblingBox(); 794 795 LayoutRectRecorder recorder(*child); 796 797 if (childToExclude == child) 798 continue; // Skip this child, since it will be positioned by the specialized subclass (fieldsets and ruby runs). 799 800 updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, child); 801 802 if (child->isOutOfFlowPositioned()) { 803 child->containingBlock()->insertPositionedObject(child); 804 adjustPositionedBlock(child, marginInfo); 805 continue; 806 } 807 if (child->isFloating()) { 808 insertFloatingObject(child); 809 adjustFloatingBlock(marginInfo); 810 continue; 811 } 812 813 // Lay out the child. 814 layoutBlockChild(child, marginInfo, previousFloatLogicalBottom, maxFloatLogicalBottom); 815 816 // If doing a partial layout and the child was the target renderer, early exit here. 817 if (frameView()->partialLayout().checkPartialLayoutComplete(child)) 818 break; 819 } 820 821 // Now do the handling of the bottom of the block, adding in our bottom border/padding and 822 // determining the correct collapsed bottom margin information. 823 handleAfterSideOfBlock(beforeEdge, afterEdge, marginInfo); 824 } 825 826 // Our MarginInfo state used when laying out block children. 827 MarginInfo::MarginInfo(RenderBlockFlow* blockFlow, LayoutUnit beforeBorderPadding, LayoutUnit afterBorderPadding) 828 : m_atBeforeSideOfBlock(true) 829 , m_atAfterSideOfBlock(false) 830 , m_hasMarginBeforeQuirk(false) 831 , m_hasMarginAfterQuirk(false) 832 , m_determinedMarginBeforeQuirk(false) 833 , m_discardMargin(false) 834 { 835 RenderStyle* blockStyle = blockFlow->style(); 836 ASSERT(blockFlow->isRenderView() || blockFlow->parent()); 837 m_canCollapseWithChildren = !blockFlow->isRenderView() && !blockFlow->isRoot() && !blockFlow->isOutOfFlowPositioned() 838 && !blockFlow->isFloating() && !blockFlow->isTableCell() && !blockFlow->hasOverflowClip() && !blockFlow->isInlineBlockOrInlineTable() 839 && !blockFlow->isRenderFlowThread() && !blockFlow->isWritingModeRoot() && !blockFlow->parent()->isFlexibleBox() 840 && blockStyle->hasAutoColumnCount() && blockStyle->hasAutoColumnWidth() && !blockStyle->columnSpan(); 841 842 m_canCollapseMarginBeforeWithChildren = m_canCollapseWithChildren && !beforeBorderPadding && blockStyle->marginBeforeCollapse() != MSEPARATE; 843 844 // If any height other than auto is specified in CSS, then we don't collapse our bottom 845 // margins with our children's margins. To do otherwise would be to risk odd visual 846 // effects when the children overflow out of the parent block and yet still collapse 847 // with it. We also don't collapse if we have any bottom border/padding. 848 m_canCollapseMarginAfterWithChildren = m_canCollapseWithChildren && !afterBorderPadding 849 && (blockStyle->logicalHeight().isAuto() && !blockStyle->logicalHeight().value()) && blockStyle->marginAfterCollapse() != MSEPARATE; 850 851 m_quirkContainer = blockFlow->isTableCell() || blockFlow->isBody(); 852 853 m_discardMargin = m_canCollapseMarginBeforeWithChildren && blockFlow->mustDiscardMarginBefore(); 854 855 m_positiveMargin = (m_canCollapseMarginBeforeWithChildren && !blockFlow->mustDiscardMarginBefore()) ? blockFlow->maxPositiveMarginBefore() : LayoutUnit(); 856 m_negativeMargin = (m_canCollapseMarginBeforeWithChildren && !blockFlow->mustDiscardMarginBefore()) ? blockFlow->maxNegativeMarginBefore() : LayoutUnit(); 857 } 858 859 RenderBlockFlow::MarginValues RenderBlockFlow::marginValuesForChild(RenderBox* child) const 860 { 861 LayoutUnit childBeforePositive = 0; 862 LayoutUnit childBeforeNegative = 0; 863 LayoutUnit childAfterPositive = 0; 864 LayoutUnit childAfterNegative = 0; 865 866 LayoutUnit beforeMargin = 0; 867 LayoutUnit afterMargin = 0; 868 869 RenderBlockFlow* childRenderBlockFlow = child->isRenderBlockFlow() ? toRenderBlockFlow(child) : 0; 870 871 // If the child has the same directionality as we do, then we can just return its 872 // margins in the same direction. 873 if (!child->isWritingModeRoot()) { 874 if (childRenderBlockFlow) { 875 childBeforePositive = childRenderBlockFlow->maxPositiveMarginBefore(); 876 childBeforeNegative = childRenderBlockFlow->maxNegativeMarginBefore(); 877 childAfterPositive = childRenderBlockFlow->maxPositiveMarginAfter(); 878 childAfterNegative = childRenderBlockFlow->maxNegativeMarginAfter(); 879 } else { 880 beforeMargin = child->marginBefore(); 881 afterMargin = child->marginAfter(); 882 } 883 } else if (child->isHorizontalWritingMode() == isHorizontalWritingMode()) { 884 // The child has a different directionality. If the child is parallel, then it's just 885 // flipped relative to us. We can use the margins for the opposite edges. 886 if (childRenderBlockFlow) { 887 childBeforePositive = childRenderBlockFlow->maxPositiveMarginAfter(); 888 childBeforeNegative = childRenderBlockFlow->maxNegativeMarginAfter(); 889 childAfterPositive = childRenderBlockFlow->maxPositiveMarginBefore(); 890 childAfterNegative = childRenderBlockFlow->maxNegativeMarginBefore(); 891 } else { 892 beforeMargin = child->marginAfter(); 893 afterMargin = child->marginBefore(); 894 } 895 } else { 896 // The child is perpendicular to us, which means its margins don't collapse but are on the 897 // "logical left/right" sides of the child box. We can just return the raw margin in this case. 898 beforeMargin = marginBeforeForChild(child); 899 afterMargin = marginAfterForChild(child); 900 } 901 902 // Resolve uncollapsing margins into their positive/negative buckets. 903 if (beforeMargin) { 904 if (beforeMargin > 0) 905 childBeforePositive = beforeMargin; 906 else 907 childBeforeNegative = -beforeMargin; 908 } 909 if (afterMargin) { 910 if (afterMargin > 0) 911 childAfterPositive = afterMargin; 912 else 913 childAfterNegative = -afterMargin; 914 } 915 916 return RenderBlockFlow::MarginValues(childBeforePositive, childBeforeNegative, childAfterPositive, childAfterNegative); 917 } 918 919 LayoutUnit RenderBlockFlow::collapseMargins(RenderBox* child, MarginInfo& marginInfo) 920 { 921 bool childDiscardMarginBefore = mustDiscardMarginBeforeForChild(child); 922 bool childDiscardMarginAfter = mustDiscardMarginAfterForChild(child); 923 bool childIsSelfCollapsing = child->isSelfCollapsingBlock(); 924 925 // The child discards the before margin when the the after margin has discard in the case of a self collapsing block. 926 childDiscardMarginBefore = childDiscardMarginBefore || (childDiscardMarginAfter && childIsSelfCollapsing); 927 928 // Get the four margin values for the child and cache them. 929 const RenderBlockFlow::MarginValues childMargins = marginValuesForChild(child); 930 931 // Get our max pos and neg top margins. 932 LayoutUnit posTop = childMargins.positiveMarginBefore(); 933 LayoutUnit negTop = childMargins.negativeMarginBefore(); 934 935 // For self-collapsing blocks, collapse our bottom margins into our 936 // top to get new posTop and negTop values. 937 if (childIsSelfCollapsing) { 938 posTop = max(posTop, childMargins.positiveMarginAfter()); 939 negTop = max(negTop, childMargins.negativeMarginAfter()); 940 } 941 942 // See if the top margin is quirky. We only care if this child has 943 // margins that will collapse with us. 944 bool topQuirk = hasMarginBeforeQuirk(child); 945 946 if (marginInfo.canCollapseWithMarginBefore()) { 947 if (!childDiscardMarginBefore && !marginInfo.discardMargin()) { 948 // This child is collapsing with the top of the 949 // block. If it has larger margin values, then we need to update 950 // our own maximal values. 951 if (!document().inQuirksMode() || !marginInfo.quirkContainer() || !topQuirk) 952 setMaxMarginBeforeValues(max(posTop, maxPositiveMarginBefore()), max(negTop, maxNegativeMarginBefore())); 953 954 // The minute any of the margins involved isn't a quirk, don't 955 // collapse it away, even if the margin is smaller (www.webreference.com 956 // has an example of this, a <dt> with 0.8em author-specified inside 957 // a <dl> inside a <td>. 958 if (!marginInfo.determinedMarginBeforeQuirk() && !topQuirk && (posTop - negTop)) { 959 setHasMarginBeforeQuirk(false); 960 marginInfo.setDeterminedMarginBeforeQuirk(true); 961 } 962 963 if (!marginInfo.determinedMarginBeforeQuirk() && topQuirk && !marginBefore()) { 964 // We have no top margin and our top child has a quirky margin. 965 // We will pick up this quirky margin and pass it through. 966 // This deals with the <td><div><p> case. 967 // Don't do this for a block that split two inlines though. You do 968 // still apply margins in this case. 969 setHasMarginBeforeQuirk(true); 970 } 971 } else { 972 // The before margin of the container will also discard all the margins it is collapsing with. 973 setMustDiscardMarginBefore(); 974 } 975 } 976 977 // Once we find a child with discardMarginBefore all the margins collapsing with us must also discard. 978 if (childDiscardMarginBefore) { 979 marginInfo.setDiscardMargin(true); 980 marginInfo.clearMargin(); 981 } 982 983 if (marginInfo.quirkContainer() && marginInfo.atBeforeSideOfBlock() && (posTop - negTop)) 984 marginInfo.setHasMarginBeforeQuirk(topQuirk); 985 986 LayoutUnit beforeCollapseLogicalTop = logicalHeight(); 987 LayoutUnit logicalTop = beforeCollapseLogicalTop; 988 989 LayoutUnit clearanceForSelfCollapsingBlock; 990 RenderObject* prev = child->previousSibling(); 991 // If the child's previous sibling is a self-collapsing block that cleared a float then its top border edge has been set at the bottom border edge 992 // of the float. Since we want to collapse the child's top margin with the self-collapsing block's top and bottom margins we need to adjust our parent's height to match the 993 // margin top of the self-collapsing block. If the resulting collapsed margin leaves the child still intruding into the float then we will want to clear it. 994 if (!marginInfo.canCollapseWithMarginBefore() && prev && prev->isRenderBlockFlow() && toRenderBlockFlow(prev)->isSelfCollapsingBlock()) { 995 clearanceForSelfCollapsingBlock = toRenderBlockFlow(prev)->marginOffsetForSelfCollapsingBlock(); 996 setLogicalHeight(logicalHeight() - clearanceForSelfCollapsingBlock); 997 } 998 999 if (childIsSelfCollapsing) { 1000 // For a self collapsing block both the before and after margins get discarded. The block doesn't contribute anything to the height of the block. 1001 // Also, the child's top position equals the logical height of the container. 1002 if (!childDiscardMarginBefore && !marginInfo.discardMargin()) { 1003 // This child has no height. We need to compute our 1004 // position before we collapse the child's margins together, 1005 // so that we can get an accurate position for the zero-height block. 1006 LayoutUnit collapsedBeforePos = max(marginInfo.positiveMargin(), childMargins.positiveMarginBefore()); 1007 LayoutUnit collapsedBeforeNeg = max(marginInfo.negativeMargin(), childMargins.negativeMarginBefore()); 1008 marginInfo.setMargin(collapsedBeforePos, collapsedBeforeNeg); 1009 1010 // Now collapse the child's margins together, which means examining our 1011 // bottom margin values as well. 1012 marginInfo.setPositiveMarginIfLarger(childMargins.positiveMarginAfter()); 1013 marginInfo.setNegativeMarginIfLarger(childMargins.negativeMarginAfter()); 1014 1015 if (!marginInfo.canCollapseWithMarginBefore()) { 1016 // We need to make sure that the position of the self-collapsing block 1017 // is correct, since it could have overflowing content 1018 // that needs to be positioned correctly (e.g., a block that 1019 // had a specified height of 0 but that actually had subcontent). 1020 logicalTop = logicalHeight() + collapsedBeforePos - collapsedBeforeNeg; 1021 } 1022 } 1023 } else { 1024 if (mustSeparateMarginBeforeForChild(child)) { 1025 ASSERT(!marginInfo.discardMargin() || (marginInfo.discardMargin() && !marginInfo.margin())); 1026 // If we are at the before side of the block and we collapse, ignore the computed margin 1027 // and just add the child margin to the container height. This will correctly position 1028 // the child inside the container. 1029 LayoutUnit separateMargin = !marginInfo.canCollapseWithMarginBefore() ? marginInfo.margin() : LayoutUnit(0); 1030 setLogicalHeight(logicalHeight() + separateMargin + marginBeforeForChild(child)); 1031 logicalTop = logicalHeight(); 1032 } else if (!marginInfo.discardMargin() && (!marginInfo.atBeforeSideOfBlock() 1033 || (!marginInfo.canCollapseMarginBeforeWithChildren() 1034 && (!document().inQuirksMode() || !marginInfo.quirkContainer() || !marginInfo.hasMarginBeforeQuirk())))) { 1035 // We're collapsing with a previous sibling's margins and not 1036 // with the top of the block. 1037 setLogicalHeight(logicalHeight() + max(marginInfo.positiveMargin(), posTop) - max(marginInfo.negativeMargin(), negTop)); 1038 logicalTop = logicalHeight(); 1039 } 1040 1041 marginInfo.setDiscardMargin(childDiscardMarginAfter); 1042 1043 if (!marginInfo.discardMargin()) { 1044 marginInfo.setPositiveMargin(childMargins.positiveMarginAfter()); 1045 marginInfo.setNegativeMargin(childMargins.negativeMarginAfter()); 1046 } else { 1047 marginInfo.clearMargin(); 1048 } 1049 1050 if (marginInfo.margin()) 1051 marginInfo.setHasMarginAfterQuirk(hasMarginAfterQuirk(child)); 1052 } 1053 1054 // If margins would pull us past the top of the next page, then we need to pull back and pretend like the margins 1055 // collapsed into the page edge. 1056 LayoutState* layoutState = view()->layoutState(); 1057 if (layoutState->isPaginated() && layoutState->pageLogicalHeight() && logicalTop > beforeCollapseLogicalTop 1058 && hasNextPage(beforeCollapseLogicalTop)) { 1059 LayoutUnit oldLogicalTop = logicalTop; 1060 logicalTop = min(logicalTop, nextPageLogicalTop(beforeCollapseLogicalTop)); 1061 setLogicalHeight(logicalHeight() + (logicalTop - oldLogicalTop)); 1062 } 1063 1064 if (prev && prev->isRenderBlockFlow() && !prev->isFloatingOrOutOfFlowPositioned()) { 1065 // If |child| is a self-collapsing block it may have collapsed into a previous sibling and although it hasn't reduced the height of the parent yet 1066 // any floats from the parent will now overhang. 1067 RenderBlockFlow* blockFlow = toRenderBlockFlow(prev); 1068 LayoutUnit oldLogicalHeight = logicalHeight(); 1069 setLogicalHeight(logicalTop); 1070 if (blockFlow->containsFloats() && !blockFlow->avoidsFloats() && (blockFlow->logicalTop() + blockFlow->lowestFloatLogicalBottom()) > logicalTop) 1071 addOverhangingFloats(blockFlow, false); 1072 setLogicalHeight(oldLogicalHeight); 1073 1074 // If |child|'s previous sibling is a self-collapsing block that cleared a float and margin collapsing resulted in |child| moving up 1075 // into the margin area of the self-collapsing block then the float it clears is now intruding into |child|. Layout again so that we can look for 1076 // floats in the parent that overhang |child|'s new logical top. 1077 bool logicalTopIntrudesIntoFloat = clearanceForSelfCollapsingBlock > 0 && logicalTop < beforeCollapseLogicalTop; 1078 if (logicalTopIntrudesIntoFloat && containsFloats() && !child->avoidsFloats() && lowestFloatLogicalBottom() > logicalTop) 1079 child->setNeedsLayout(); 1080 } 1081 1082 return logicalTop; 1083 } 1084 1085 void RenderBlockFlow::adjustPositionedBlock(RenderBox* child, const MarginInfo& marginInfo) 1086 { 1087 bool isHorizontal = isHorizontalWritingMode(); 1088 bool hasStaticBlockPosition = child->style()->hasStaticBlockPosition(isHorizontal); 1089 1090 LayoutUnit logicalTop = logicalHeight(); 1091 updateStaticInlinePositionForChild(child, logicalTop); 1092 1093 if (!marginInfo.canCollapseWithMarginBefore()) { 1094 // Positioned blocks don't collapse margins, so add the margin provided by 1095 // the container now. The child's own margin is added later when calculating its logical top. 1096 LayoutUnit collapsedBeforePos = marginInfo.positiveMargin(); 1097 LayoutUnit collapsedBeforeNeg = marginInfo.negativeMargin(); 1098 logicalTop += collapsedBeforePos - collapsedBeforeNeg; 1099 } 1100 1101 RenderLayer* childLayer = child->layer(); 1102 if (childLayer->staticBlockPosition() != logicalTop) { 1103 childLayer->setStaticBlockPosition(logicalTop); 1104 if (hasStaticBlockPosition) 1105 child->setChildNeedsLayout(MarkOnlyThis); 1106 } 1107 } 1108 1109 LayoutUnit RenderBlockFlow::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos) 1110 { 1111 LayoutUnit heightIncrease = getClearDelta(child, yPos); 1112 if (!heightIncrease) 1113 return yPos; 1114 1115 if (child->isSelfCollapsingBlock()) { 1116 bool childDiscardMargin = mustDiscardMarginBeforeForChild(child) || mustDiscardMarginAfterForChild(child); 1117 1118 // For self-collapsing blocks that clear, they can still collapse their 1119 // margins with following siblings. Reset the current margins to represent 1120 // the self-collapsing block's margins only. 1121 // If DISCARD is specified for -webkit-margin-collapse, reset the margin values. 1122 RenderBlockFlow::MarginValues childMargins = marginValuesForChild(child); 1123 if (!childDiscardMargin) { 1124 marginInfo.setPositiveMargin(max(childMargins.positiveMarginBefore(), childMargins.positiveMarginAfter())); 1125 marginInfo.setNegativeMargin(max(childMargins.negativeMarginBefore(), childMargins.negativeMarginAfter())); 1126 } else { 1127 marginInfo.clearMargin(); 1128 } 1129 marginInfo.setDiscardMargin(childDiscardMargin); 1130 1131 // CSS2.1 states: 1132 // "If the top and bottom margins of an element with clearance are adjoining, its margins collapse with 1133 // the adjoining margins of following siblings but that resulting margin does not collapse with the bottom margin of the parent block." 1134 // So the parent's bottom margin cannot collapse through this block or any subsequent self-collapsing blocks. Check subsequent siblings 1135 // for a block with height - if none is found then don't allow the margins to collapse with the parent. 1136 bool wouldCollapseMarginsWithParent = marginInfo.canCollapseMarginAfterWithChildren(); 1137 for (RenderBox* curr = child->nextSiblingBox(); curr && wouldCollapseMarginsWithParent; curr = curr->nextSiblingBox()) { 1138 if (!curr->isFloatingOrOutOfFlowPositioned() && !curr->isSelfCollapsingBlock()) 1139 wouldCollapseMarginsWithParent = false; 1140 } 1141 if (wouldCollapseMarginsWithParent) 1142 marginInfo.setCanCollapseMarginAfterWithChildren(false); 1143 1144 // For now set the border-top of |child| flush with the bottom border-edge of the float so it can layout any floating or positioned children of 1145 // its own at the correct vertical position. If subsequent siblings attempt to collapse with |child|'s margins in |collapseMargins| we will 1146 // adjust the height of the parent to |child|'s margin top (which if it is positive sits up 'inside' the float it's clearing) so that all three 1147 // margins can collapse at the correct vertical position. 1148 // Per CSS2.1 we need to ensure that any negative margin-top clears |child| beyond the bottom border-edge of the float so that the top border edge of the child 1149 // (i.e. its clearance) is at a position that satisfies the equation: "the amount of clearance is set so that clearance + margin-top = [height of float], 1150 // i.e., clearance = [height of float] - margin-top". 1151 setLogicalHeight(child->logicalTop() + childMargins.negativeMarginBefore()); 1152 } else { 1153 // Increase our height by the amount we had to clear. 1154 setLogicalHeight(logicalHeight() + heightIncrease); 1155 } 1156 1157 if (marginInfo.canCollapseWithMarginBefore()) { 1158 // We can no longer collapse with the top of the block since a clear 1159 // occurred. The empty blocks collapse into the cleared block. 1160 // FIXME: This isn't quite correct. Need clarification for what to do 1161 // if the height the cleared block is offset by is smaller than the 1162 // margins involved. 1163 setMaxMarginBeforeValues(oldTopPosMargin, oldTopNegMargin); 1164 marginInfo.setAtBeforeSideOfBlock(false); 1165 1166 // In case the child discarded the before margin of the block we need to reset the mustDiscardMarginBefore flag to the initial value. 1167 setMustDiscardMarginBefore(style()->marginBeforeCollapse() == MDISCARD); 1168 } 1169 1170 return yPos + heightIncrease; 1171 } 1172 1173 void RenderBlockFlow::setCollapsedBottomMargin(const MarginInfo& marginInfo) 1174 { 1175 if (marginInfo.canCollapseWithMarginAfter() && !marginInfo.canCollapseWithMarginBefore()) { 1176 // Update the after side margin of the container to discard if the after margin of the last child also discards and we collapse with it. 1177 // Don't update the max margin values because we won't need them anyway. 1178 if (marginInfo.discardMargin()) { 1179 setMustDiscardMarginAfter(); 1180 return; 1181 } 1182 1183 // Update our max pos/neg bottom margins, since we collapsed our bottom margins 1184 // with our children. 1185 setMaxMarginAfterValues(max(maxPositiveMarginAfter(), marginInfo.positiveMargin()), max(maxNegativeMarginAfter(), marginInfo.negativeMargin())); 1186 1187 if (!marginInfo.hasMarginAfterQuirk()) 1188 setHasMarginAfterQuirk(false); 1189 1190 if (marginInfo.hasMarginAfterQuirk() && !marginAfter()) { 1191 // We have no bottom margin and our last child has a quirky margin. 1192 // We will pick up this quirky margin and pass it through. 1193 // This deals with the <td><div><p> case. 1194 setHasMarginAfterQuirk(true); 1195 } 1196 } 1197 } 1198 1199 void RenderBlockFlow::marginBeforeEstimateForChild(RenderBox* child, LayoutUnit& positiveMarginBefore, LayoutUnit& negativeMarginBefore, bool& discardMarginBefore) const 1200 { 1201 // Give up if in quirks mode and we're a body/table cell and the top margin of the child box is quirky. 1202 // Give up if the child specified -webkit-margin-collapse: separate that prevents collapsing. 1203 // FIXME: Use writing mode independent accessor for marginBeforeCollapse. 1204 if ((document().inQuirksMode() && hasMarginAfterQuirk(child) && (isTableCell() || isBody())) || child->style()->marginBeforeCollapse() == MSEPARATE) 1205 return; 1206 1207 // The margins are discarded by a child that specified -webkit-margin-collapse: discard. 1208 // FIXME: Use writing mode independent accessor for marginBeforeCollapse. 1209 if (child->style()->marginBeforeCollapse() == MDISCARD) { 1210 positiveMarginBefore = 0; 1211 negativeMarginBefore = 0; 1212 discardMarginBefore = true; 1213 return; 1214 } 1215 1216 LayoutUnit beforeChildMargin = marginBeforeForChild(child); 1217 positiveMarginBefore = max(positiveMarginBefore, beforeChildMargin); 1218 negativeMarginBefore = max(negativeMarginBefore, -beforeChildMargin); 1219 1220 if (!child->isRenderBlockFlow()) 1221 return; 1222 1223 RenderBlockFlow* childBlockFlow = toRenderBlockFlow(child); 1224 if (childBlockFlow->childrenInline() || childBlockFlow->isWritingModeRoot()) 1225 return; 1226 1227 MarginInfo childMarginInfo(childBlockFlow, childBlockFlow->borderBefore() + childBlockFlow->paddingBefore(), childBlockFlow->borderAfter() + childBlockFlow->paddingAfter()); 1228 if (!childMarginInfo.canCollapseMarginBeforeWithChildren()) 1229 return; 1230 1231 RenderBox* grandchildBox = childBlockFlow->firstChildBox(); 1232 for ( ; grandchildBox; grandchildBox = grandchildBox->nextSiblingBox()) { 1233 if (!grandchildBox->isFloatingOrOutOfFlowPositioned()) 1234 break; 1235 } 1236 1237 // Give up if there is clearance on the box, since it probably won't collapse into us. 1238 if (!grandchildBox || grandchildBox->style()->clear() != CNONE) 1239 return; 1240 1241 // Make sure to update the block margins now for the grandchild box so that we're looking at current values. 1242 if (grandchildBox->needsLayout()) { 1243 grandchildBox->computeAndSetBlockDirectionMargins(this); 1244 if (grandchildBox->isRenderBlock()) { 1245 RenderBlock* grandchildBlock = toRenderBlock(grandchildBox); 1246 grandchildBlock->setHasMarginBeforeQuirk(grandchildBox->style()->hasMarginBeforeQuirk()); 1247 grandchildBlock->setHasMarginAfterQuirk(grandchildBox->style()->hasMarginAfterQuirk()); 1248 } 1249 } 1250 1251 // Collapse the margin of the grandchild box with our own to produce an estimate. 1252 childBlockFlow->marginBeforeEstimateForChild(grandchildBox, positiveMarginBefore, negativeMarginBefore, discardMarginBefore); 1253 } 1254 1255 LayoutUnit RenderBlockFlow::estimateLogicalTopPosition(RenderBox* child, const MarginInfo& marginInfo, LayoutUnit& estimateWithoutPagination) 1256 { 1257 // FIXME: We need to eliminate the estimation of vertical position, because when it's wrong we sometimes trigger a pathological 1258 // relayout if there are intruding floats. 1259 LayoutUnit logicalTopEstimate = logicalHeight(); 1260 if (!marginInfo.canCollapseWithMarginBefore()) { 1261 LayoutUnit positiveMarginBefore = 0; 1262 LayoutUnit negativeMarginBefore = 0; 1263 bool discardMarginBefore = false; 1264 if (child->selfNeedsLayout()) { 1265 // Try to do a basic estimation of how the collapse is going to go. 1266 marginBeforeEstimateForChild(child, positiveMarginBefore, negativeMarginBefore, discardMarginBefore); 1267 } else { 1268 // Use the cached collapsed margin values from a previous layout. Most of the time they 1269 // will be right. 1270 RenderBlockFlow::MarginValues marginValues = marginValuesForChild(child); 1271 positiveMarginBefore = max(positiveMarginBefore, marginValues.positiveMarginBefore()); 1272 negativeMarginBefore = max(negativeMarginBefore, marginValues.negativeMarginBefore()); 1273 discardMarginBefore = mustDiscardMarginBeforeForChild(child); 1274 } 1275 1276 // Collapse the result with our current margins. 1277 if (!discardMarginBefore) 1278 logicalTopEstimate += max(marginInfo.positiveMargin(), positiveMarginBefore) - max(marginInfo.negativeMargin(), negativeMarginBefore); 1279 } 1280 1281 // Adjust logicalTopEstimate down to the next page if the margins are so large that we don't fit on the current 1282 // page. 1283 LayoutState* layoutState = view()->layoutState(); 1284 if (layoutState->isPaginated() && layoutState->pageLogicalHeight() && logicalTopEstimate > logicalHeight() 1285 && hasNextPage(logicalHeight())) 1286 logicalTopEstimate = min(logicalTopEstimate, nextPageLogicalTop(logicalHeight())); 1287 1288 logicalTopEstimate += getClearDelta(child, logicalTopEstimate); 1289 1290 estimateWithoutPagination = logicalTopEstimate; 1291 1292 if (layoutState->isPaginated()) { 1293 // If the object has a page or column break value of "before", then we should shift to the top of the next page. 1294 logicalTopEstimate = applyBeforeBreak(child, logicalTopEstimate); 1295 1296 // For replaced elements and scrolled elements, we want to shift them to the next page if they don't fit on the current one. 1297 logicalTopEstimate = adjustForUnsplittableChild(child, logicalTopEstimate); 1298 1299 if (!child->selfNeedsLayout() && child->isRenderBlock()) 1300 logicalTopEstimate += toRenderBlock(child)->paginationStrut(); 1301 } 1302 1303 return logicalTopEstimate; 1304 } 1305 1306 LayoutUnit RenderBlockFlow::marginOffsetForSelfCollapsingBlock() 1307 { 1308 ASSERT(isSelfCollapsingBlock()); 1309 RenderBlockFlow* parentBlock = toRenderBlockFlow(parent()); 1310 if (parentBlock && style()->clear() && parentBlock->getClearDelta(this, logicalHeight())) 1311 return marginValuesForChild(this).positiveMarginBefore(); 1312 return LayoutUnit(); 1313 } 1314 1315 void RenderBlockFlow::adjustFloatingBlock(const MarginInfo& marginInfo) 1316 { 1317 // The float should be positioned taking into account the bottom margin 1318 // of the previous flow. We add that margin into the height, get the 1319 // float positioned properly, and then subtract the margin out of the 1320 // height again. In the case of self-collapsing blocks, we always just 1321 // use the top margins, since the self-collapsing block collapsed its 1322 // own bottom margin into its top margin. 1323 // 1324 // Note also that the previous flow may collapse its margin into the top of 1325 // our block. If this is the case, then we do not add the margin in to our 1326 // height when computing the position of the float. This condition can be tested 1327 // for by simply calling canCollapseWithMarginBefore. See 1328 // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for 1329 // an example of this scenario. 1330 LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() ? LayoutUnit() : marginInfo.margin(); 1331 setLogicalHeight(logicalHeight() + marginOffset); 1332 positionNewFloats(); 1333 setLogicalHeight(logicalHeight() - marginOffset); 1334 } 1335 1336 void RenderBlockFlow::handleAfterSideOfBlock(LayoutUnit beforeSide, LayoutUnit afterSide, MarginInfo& marginInfo) 1337 { 1338 marginInfo.setAtAfterSideOfBlock(true); 1339 1340 // If our last child was a self-collapsing block with clearance then our logical height is flush with the 1341 // bottom edge of the float that the child clears. The correct vertical position for the margin-collapsing we want 1342 // to perform now is at the child's margin-top - so adjust our height to that position. 1343 RenderObject* child = lastChild(); 1344 if (child && child->isRenderBlockFlow() && toRenderBlockFlow(child)->isSelfCollapsingBlock()) 1345 setLogicalHeight(logicalHeight() - toRenderBlockFlow(child)->marginOffsetForSelfCollapsingBlock()); 1346 1347 // If we can't collapse with children then go ahead and add in the bottom margin. 1348 if (!marginInfo.discardMargin() && (!marginInfo.canCollapseWithMarginAfter() && !marginInfo.canCollapseWithMarginBefore() 1349 && (!document().inQuirksMode() || !marginInfo.quirkContainer() || !marginInfo.hasMarginAfterQuirk()))) 1350 setLogicalHeight(logicalHeight() + marginInfo.margin()); 1351 1352 // Now add in our bottom border/padding. 1353 setLogicalHeight(logicalHeight() + afterSide); 1354 1355 // Negative margins can cause our height to shrink below our minimal height (border/padding). 1356 // If this happens, ensure that the computed height is increased to the minimal height. 1357 setLogicalHeight(max(logicalHeight(), beforeSide + afterSide)); 1358 1359 // Update our bottom collapsed margin info. 1360 setCollapsedBottomMargin(marginInfo); 1361 } 1362 1363 void RenderBlockFlow::setMustDiscardMarginBefore(bool value) 1364 { 1365 if (style()->marginBeforeCollapse() == MDISCARD) { 1366 ASSERT(value); 1367 return; 1368 } 1369 1370 if (!m_rareData && !value) 1371 return; 1372 1373 if (!m_rareData) 1374 m_rareData = adoptPtr(new RenderBlockFlowRareData(this)); 1375 1376 m_rareData->m_discardMarginBefore = value; 1377 } 1378 1379 void RenderBlockFlow::setMustDiscardMarginAfter(bool value) 1380 { 1381 if (style()->marginAfterCollapse() == MDISCARD) { 1382 ASSERT(value); 1383 return; 1384 } 1385 1386 if (!m_rareData && !value) 1387 return; 1388 1389 if (!m_rareData) 1390 m_rareData = adoptPtr(new RenderBlockFlowRareData(this)); 1391 1392 m_rareData->m_discardMarginAfter = value; 1393 } 1394 1395 bool RenderBlockFlow::mustDiscardMarginBefore() const 1396 { 1397 return style()->marginBeforeCollapse() == MDISCARD || (m_rareData && m_rareData->m_discardMarginBefore); 1398 } 1399 1400 bool RenderBlockFlow::mustDiscardMarginAfter() const 1401 { 1402 return style()->marginAfterCollapse() == MDISCARD || (m_rareData && m_rareData->m_discardMarginAfter); 1403 } 1404 1405 bool RenderBlockFlow::mustDiscardMarginBeforeForChild(const RenderBox* child) const 1406 { 1407 ASSERT(!child->selfNeedsLayout()); 1408 if (!child->isWritingModeRoot()) 1409 return child->isRenderBlockFlow() ? toRenderBlockFlow(child)->mustDiscardMarginBefore() : (child->style()->marginBeforeCollapse() == MDISCARD); 1410 if (child->isHorizontalWritingMode() == isHorizontalWritingMode()) 1411 return child->isRenderBlockFlow() ? toRenderBlockFlow(child)->mustDiscardMarginAfter() : (child->style()->marginAfterCollapse() == MDISCARD); 1412 1413 // FIXME: We return false here because the implementation is not geometrically complete. We have values only for before/after, not start/end. 1414 // In case the boxes are perpendicular we assume the property is not specified. 1415 return false; 1416 } 1417 1418 bool RenderBlockFlow::mustDiscardMarginAfterForChild(const RenderBox* child) const 1419 { 1420 ASSERT(!child->selfNeedsLayout()); 1421 if (!child->isWritingModeRoot()) 1422 return child->isRenderBlockFlow() ? toRenderBlockFlow(child)->mustDiscardMarginAfter() : (child->style()->marginAfterCollapse() == MDISCARD); 1423 if (child->isHorizontalWritingMode() == isHorizontalWritingMode()) 1424 return child->isRenderBlockFlow() ? toRenderBlockFlow(child)->mustDiscardMarginBefore() : (child->style()->marginBeforeCollapse() == MDISCARD); 1425 1426 // FIXME: See |mustDiscardMarginBeforeForChild| above. 1427 return false; 1428 } 1429 1430 void RenderBlockFlow::setMaxMarginBeforeValues(LayoutUnit pos, LayoutUnit neg) 1431 { 1432 if (!m_rareData) { 1433 if (pos == RenderBlockFlowRareData::positiveMarginBeforeDefault(this) && neg == RenderBlockFlowRareData::negativeMarginBeforeDefault(this)) 1434 return; 1435 m_rareData = adoptPtr(new RenderBlockFlowRareData(this)); 1436 } 1437 m_rareData->m_margins.setPositiveMarginBefore(pos); 1438 m_rareData->m_margins.setNegativeMarginBefore(neg); 1439 } 1440 1441 void RenderBlockFlow::setMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg) 1442 { 1443 if (!m_rareData) { 1444 if (pos == RenderBlockFlowRareData::positiveMarginAfterDefault(this) && neg == RenderBlockFlowRareData::negativeMarginAfterDefault(this)) 1445 return; 1446 m_rareData = adoptPtr(new RenderBlockFlowRareData(this)); 1447 } 1448 m_rareData->m_margins.setPositiveMarginAfter(pos); 1449 m_rareData->m_margins.setNegativeMarginAfter(neg); 1450 } 1451 1452 bool RenderBlockFlow::mustSeparateMarginBeforeForChild(const RenderBox* child) const 1453 { 1454 ASSERT(!child->selfNeedsLayout()); 1455 const RenderStyle* childStyle = child->style(); 1456 if (!child->isWritingModeRoot()) 1457 return childStyle->marginBeforeCollapse() == MSEPARATE; 1458 if (child->isHorizontalWritingMode() == isHorizontalWritingMode()) 1459 return childStyle->marginAfterCollapse() == MSEPARATE; 1460 1461 // FIXME: See |mustDiscardMarginBeforeForChild| above. 1462 return false; 1463 } 1464 1465 bool RenderBlockFlow::mustSeparateMarginAfterForChild(const RenderBox* child) const 1466 { 1467 ASSERT(!child->selfNeedsLayout()); 1468 const RenderStyle* childStyle = child->style(); 1469 if (!child->isWritingModeRoot()) 1470 return childStyle->marginAfterCollapse() == MSEPARATE; 1471 if (child->isHorizontalWritingMode() == isHorizontalWritingMode()) 1472 return childStyle->marginBeforeCollapse() == MSEPARATE; 1473 1474 // FIXME: See |mustDiscardMarginBeforeForChild| above. 1475 return false; 1476 } 1477 1478 LayoutUnit RenderBlockFlow::applyBeforeBreak(RenderBox* child, LayoutUnit logicalOffset) 1479 { 1480 // FIXME: Add page break checking here when we support printing. 1481 bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns(); 1482 bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageLogicalHeight; // FIXME: Once columns can print we have to check this. 1483 RenderFlowThread* flowThread = flowThreadContainingBlock(); 1484 bool checkRegionBreaks = flowThread && flowThread->isRenderNamedFlowThread(); 1485 bool checkBeforeAlways = (checkColumnBreaks && child->style()->columnBreakBefore() == PBALWAYS) || (checkPageBreaks && child->style()->pageBreakBefore() == PBALWAYS) 1486 || (checkRegionBreaks && child->style()->regionBreakBefore() == PBALWAYS); 1487 if (checkBeforeAlways && inNormalFlow(child) && hasNextPage(logicalOffset, IncludePageBoundary)) { 1488 if (checkColumnBreaks) 1489 view()->layoutState()->addForcedColumnBreak(child, logicalOffset); 1490 if (checkRegionBreaks) { 1491 LayoutUnit offsetBreakAdjustment = 0; 1492 if (flowThread->addForcedRegionBreak(offsetFromLogicalTopOfFirstPage() + logicalOffset, child, true, &offsetBreakAdjustment)) 1493 return logicalOffset + offsetBreakAdjustment; 1494 } 1495 return nextPageLogicalTop(logicalOffset, IncludePageBoundary); 1496 } 1497 return logicalOffset; 1498 } 1499 1500 LayoutUnit RenderBlockFlow::applyAfterBreak(RenderBox* child, LayoutUnit logicalOffset, MarginInfo& marginInfo) 1501 { 1502 // FIXME: Add page break checking here when we support printing. 1503 bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns(); 1504 bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageLogicalHeight; // FIXME: Once columns can print we have to check this. 1505 RenderFlowThread* flowThread = flowThreadContainingBlock(); 1506 bool checkRegionBreaks = flowThread && flowThread->isRenderNamedFlowThread(); 1507 bool checkAfterAlways = (checkColumnBreaks && child->style()->columnBreakAfter() == PBALWAYS) || (checkPageBreaks && child->style()->pageBreakAfter() == PBALWAYS) 1508 || (checkRegionBreaks && child->style()->regionBreakAfter() == PBALWAYS); 1509 if (checkAfterAlways && inNormalFlow(child) && hasNextPage(logicalOffset, IncludePageBoundary)) { 1510 LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() ? LayoutUnit() : marginInfo.margin(); 1511 1512 // So our margin doesn't participate in the next collapsing steps. 1513 marginInfo.clearMargin(); 1514 1515 if (checkColumnBreaks) 1516 view()->layoutState()->addForcedColumnBreak(child, logicalOffset); 1517 if (checkRegionBreaks) { 1518 LayoutUnit offsetBreakAdjustment = 0; 1519 if (flowThread->addForcedRegionBreak(offsetFromLogicalTopOfFirstPage() + logicalOffset + marginOffset, child, false, &offsetBreakAdjustment)) 1520 return logicalOffset + marginOffset + offsetBreakAdjustment; 1521 } 1522 return nextPageLogicalTop(logicalOffset, IncludePageBoundary); 1523 } 1524 return logicalOffset; 1525 } 1526 1527 void RenderBlockFlow::addOverflowFromFloats() 1528 { 1529 if (!m_floatingObjects) 1530 return; 1531 1532 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 1533 FloatingObjectSetIterator end = floatingObjectSet.end(); 1534 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { 1535 FloatingObject* floatingObject = *it; 1536 if (floatingObject->isDescendant()) 1537 addOverflowFromChild(floatingObject->renderer(), IntSize(xPositionForFloatIncludingMargin(floatingObject), yPositionForFloatIncludingMargin(floatingObject))); 1538 } 1539 } 1540 1541 void RenderBlockFlow::computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats) 1542 { 1543 RenderBlock::computeOverflow(oldClientAfterEdge, recomputeFloats); 1544 if (!hasColumns() && (recomputeFloats || isRoot() || expandsToEncloseOverhangingFloats() || hasSelfPaintingLayer())) 1545 addOverflowFromFloats(); 1546 } 1547 1548 void RenderBlockFlow::deleteLineBoxTree() 1549 { 1550 if (containsFloats()) 1551 m_floatingObjects->clearLineBoxTreePointers(); 1552 RenderBlock::deleteLineBoxTree(); 1553 } 1554 1555 void RenderBlockFlow::markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove, bool inLayout) 1556 { 1557 if (!everHadLayout() && !containsFloats()) 1558 return; 1559 1560 MarkingBehavior markParents = inLayout ? MarkOnlyThis : MarkContainingBlockChain; 1561 setChildNeedsLayout(markParents); 1562 1563 if (floatToRemove) 1564 removeFloatingObject(floatToRemove); 1565 1566 // Iterate over our children and mark them as needed. 1567 if (!childrenInline()) { 1568 for (RenderObject* child = firstChild(); child; child = child->nextSibling()) { 1569 if ((!floatToRemove && child->isFloatingOrOutOfFlowPositioned()) || !child->isRenderBlock()) 1570 continue; 1571 if (!child->isRenderBlockFlow()) { 1572 RenderBlock* childBlock = toRenderBlock(child); 1573 if (childBlock->shrinkToAvoidFloats() && childBlock->everHadLayout()) 1574 childBlock->setChildNeedsLayout(markParents); 1575 continue; 1576 } 1577 RenderBlockFlow* childBlockFlow = toRenderBlockFlow(child); 1578 if ((floatToRemove ? childBlockFlow->containsFloat(floatToRemove) : childBlockFlow->containsFloats()) || childBlockFlow->shrinkToAvoidFloats()) 1579 childBlockFlow->markAllDescendantsWithFloatsForLayout(floatToRemove, inLayout); 1580 } 1581 } 1582 } 1583 1584 void RenderBlockFlow::markSiblingsWithFloatsForLayout(RenderBox* floatToRemove) 1585 { 1586 if (!m_floatingObjects) 1587 return; 1588 1589 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 1590 FloatingObjectSetIterator end = floatingObjectSet.end(); 1591 1592 for (RenderObject* next = nextSibling(); next; next = next->nextSibling()) { 1593 if (!next->isRenderBlockFlow() || next->isFloatingOrOutOfFlowPositioned() || toRenderBlock(next)->avoidsFloats()) 1594 continue; 1595 1596 RenderBlockFlow* nextBlock = toRenderBlockFlow(next); 1597 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { 1598 RenderBox* floatingBox = (*it)->renderer(); 1599 if (floatToRemove && floatingBox != floatToRemove) 1600 continue; 1601 if (nextBlock->containsFloat(floatingBox)) 1602 nextBlock->markAllDescendantsWithFloatsForLayout(floatingBox); 1603 } 1604 } 1605 } 1606 1607 LayoutUnit RenderBlockFlow::getClearDelta(RenderBox* child, LayoutUnit logicalTop) 1608 { 1609 // There is no need to compute clearance if we have no floats. 1610 if (!containsFloats()) 1611 return 0; 1612 1613 // At least one float is present. We need to perform the clearance computation. 1614 bool clearSet = child->style()->clear() != CNONE; 1615 LayoutUnit logicalBottom = 0; 1616 switch (child->style()->clear()) { 1617 case CNONE: 1618 break; 1619 case CLEFT: 1620 logicalBottom = lowestFloatLogicalBottom(FloatingObject::FloatLeft); 1621 break; 1622 case CRIGHT: 1623 logicalBottom = lowestFloatLogicalBottom(FloatingObject::FloatRight); 1624 break; 1625 case CBOTH: 1626 logicalBottom = lowestFloatLogicalBottom(); 1627 break; 1628 } 1629 1630 // We also clear floats if we are too big to sit on the same line as a float (and wish to avoid floats by default). 1631 LayoutUnit result = clearSet ? max<LayoutUnit>(0, logicalBottom - logicalTop) : LayoutUnit(); 1632 if (!result && child->avoidsFloats()) { 1633 LayoutUnit newLogicalTop = logicalTop; 1634 while (true) { 1635 LayoutUnit availableLogicalWidthAtNewLogicalTopOffset = availableLogicalWidthForLine(newLogicalTop, false, logicalHeightForChild(child)); 1636 if (availableLogicalWidthAtNewLogicalTopOffset == availableLogicalWidthForContent(newLogicalTop)) 1637 return newLogicalTop - logicalTop; 1638 1639 RenderRegion* region = regionAtBlockOffset(logicalTopForChild(child)); 1640 LayoutRect borderBox = child->borderBoxRectInRegion(region, DoNotCacheRenderBoxRegionInfo); 1641 LayoutUnit childLogicalWidthAtOldLogicalTopOffset = isHorizontalWritingMode() ? borderBox.width() : borderBox.height(); 1642 1643 // FIXME: None of this is right for perpendicular writing-mode children. 1644 LayoutUnit childOldLogicalWidth = child->logicalWidth(); 1645 LayoutUnit childOldMarginLeft = child->marginLeft(); 1646 LayoutUnit childOldMarginRight = child->marginRight(); 1647 LayoutUnit childOldLogicalTop = child->logicalTop(); 1648 1649 child->setLogicalTop(newLogicalTop); 1650 child->updateLogicalWidth(); 1651 region = regionAtBlockOffset(logicalTopForChild(child)); 1652 borderBox = child->borderBoxRectInRegion(region, DoNotCacheRenderBoxRegionInfo); 1653 LayoutUnit childLogicalWidthAtNewLogicalTopOffset = isHorizontalWritingMode() ? borderBox.width() : borderBox.height(); 1654 1655 child->setLogicalTop(childOldLogicalTop); 1656 child->setLogicalWidth(childOldLogicalWidth); 1657 child->setMarginLeft(childOldMarginLeft); 1658 child->setMarginRight(childOldMarginRight); 1659 1660 if (childLogicalWidthAtNewLogicalTopOffset <= availableLogicalWidthAtNewLogicalTopOffset) { 1661 // Even though we may not be moving, if the logical width did shrink because of the presence of new floats, then 1662 // we need to force a relayout as though we shifted. This happens because of the dynamic addition of overhanging floats 1663 // from previous siblings when negative margins exist on a child (see the addOverhangingFloats call at the end of collapseMargins). 1664 if (childLogicalWidthAtOldLogicalTopOffset != childLogicalWidthAtNewLogicalTopOffset) 1665 child->setChildNeedsLayout(MarkOnlyThis); 1666 return newLogicalTop - logicalTop; 1667 } 1668 1669 newLogicalTop = nextFloatLogicalBottomBelow(newLogicalTop); 1670 ASSERT(newLogicalTop >= logicalTop); 1671 if (newLogicalTop < logicalTop) 1672 break; 1673 } 1674 ASSERT_NOT_REACHED(); 1675 } 1676 return result; 1677 } 1678 1679 void RenderBlockFlow::createFloatingObjects() 1680 { 1681 m_floatingObjects = adoptPtr(new FloatingObjects(this, isHorizontalWritingMode())); 1682 } 1683 1684 void RenderBlockFlow::styleWillChange(StyleDifference diff, const RenderStyle* newStyle) 1685 { 1686 RenderStyle* oldStyle = style(); 1687 s_canPropagateFloatIntoSibling = oldStyle ? !isFloatingOrOutOfFlowPositioned() && !avoidsFloats() : false; 1688 if (oldStyle && parent() && diff == StyleDifferenceLayout && oldStyle->position() != newStyle->position() 1689 && containsFloats() && !isFloating() && !isOutOfFlowPositioned() && newStyle->hasOutOfFlowPosition()) 1690 markAllDescendantsWithFloatsForLayout(); 1691 1692 RenderBlock::styleWillChange(diff, newStyle); 1693 } 1694 1695 void RenderBlockFlow::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) 1696 { 1697 RenderBlock::styleDidChange(diff, oldStyle); 1698 1699 // After our style changed, if we lose our ability to propagate floats into next sibling 1700 // blocks, then we need to find the top most parent containing that overhanging float and 1701 // then mark its descendants with floats for layout and clear all floats from its next 1702 // sibling blocks that exist in our floating objects list. See bug 56299 and 62875. 1703 bool canPropagateFloatIntoSibling = !isFloatingOrOutOfFlowPositioned() && !avoidsFloats(); 1704 if (diff == StyleDifferenceLayout && s_canPropagateFloatIntoSibling && !canPropagateFloatIntoSibling && hasOverhangingFloats()) { 1705 RenderBlockFlow* parentBlockFlow = this; 1706 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 1707 FloatingObjectSetIterator end = floatingObjectSet.end(); 1708 1709 for (RenderObject* curr = parent(); curr && !curr->isRenderView(); curr = curr->parent()) { 1710 if (curr->isRenderBlockFlow()) { 1711 RenderBlockFlow* currBlock = toRenderBlockFlow(curr); 1712 1713 if (currBlock->hasOverhangingFloats()) { 1714 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { 1715 RenderBox* renderer = (*it)->renderer(); 1716 if (currBlock->hasOverhangingFloat(renderer)) { 1717 parentBlockFlow = currBlock; 1718 break; 1719 } 1720 } 1721 } 1722 } 1723 } 1724 1725 parentBlockFlow->markAllDescendantsWithFloatsForLayout(); 1726 parentBlockFlow->markSiblingsWithFloatsForLayout(); 1727 } 1728 1729 if (renderNamedFlowFragment()) 1730 renderNamedFlowFragment()->setStyleForNamedFlowFragment(style()); 1731 } 1732 1733 void RenderBlockFlow::updateStaticInlinePositionForChild(RenderBox* child, LayoutUnit logicalTop) 1734 { 1735 if (child->style()->isOriginalDisplayInlineType()) 1736 setStaticInlinePositionForChild(child, logicalTop, startAlignedOffsetForLine(logicalTop, false)); 1737 else 1738 setStaticInlinePositionForChild(child, logicalTop, startOffsetForContent(logicalTop)); 1739 } 1740 1741 void RenderBlockFlow::setStaticInlinePositionForChild(RenderBox* child, LayoutUnit blockOffset, LayoutUnit inlinePosition) 1742 { 1743 if (flowThreadContainingBlock()) { 1744 // Shift the inline position to exclude the region offset. 1745 inlinePosition += startOffsetForContent() - startOffsetForContent(blockOffset); 1746 } 1747 child->layer()->setStaticInlinePosition(inlinePosition); 1748 } 1749 1750 void RenderBlockFlow::moveAllChildrenIncludingFloatsTo(RenderBlock* toBlock, bool fullRemoveInsert) 1751 { 1752 RenderBlockFlow* toBlockFlow = toRenderBlockFlow(toBlock); 1753 moveAllChildrenTo(toBlockFlow, fullRemoveInsert); 1754 1755 // When a portion of the render tree is being detached, anonymous blocks 1756 // will be combined as their children are deleted. In this process, the 1757 // anonymous block later in the tree is merged into the one preceeding it. 1758 // It can happen that the later block (this) contains floats that the 1759 // previous block (toBlockFlow) did not contain, and thus are not in the 1760 // floating objects list for toBlockFlow. This can result in toBlockFlow containing 1761 // floats that are not in it's floating objects list, but are in the 1762 // floating objects lists of siblings and parents. This can cause problems 1763 // when the float itself is deleted, since the deletion code assumes that 1764 // if a float is not in it's containing block's floating objects list, it 1765 // isn't in any floating objects list. In order to preserve this condition 1766 // (removing it has serious performance implications), we need to copy the 1767 // floating objects from the old block (this) to the new block (toBlockFlow). 1768 // The float's metrics will likely all be wrong, but since toBlockFlow is 1769 // already marked for layout, this will get fixed before anything gets 1770 // displayed. 1771 // See bug https://code.google.com/p/chromium/issues/detail?id=230907 1772 if (m_floatingObjects) { 1773 if (!toBlockFlow->m_floatingObjects) 1774 toBlockFlow->createFloatingObjects(); 1775 1776 const FloatingObjectSet& fromFloatingObjectSet = m_floatingObjects->set(); 1777 FloatingObjectSetIterator end = fromFloatingObjectSet.end(); 1778 1779 for (FloatingObjectSetIterator it = fromFloatingObjectSet.begin(); it != end; ++it) { 1780 FloatingObject* floatingObject = *it; 1781 1782 // Don't insert the object again if it's already in the list 1783 if (toBlockFlow->containsFloat(floatingObject->renderer())) 1784 continue; 1785 1786 toBlockFlow->m_floatingObjects->add(floatingObject->unsafeClone()); 1787 } 1788 } 1789 1790 } 1791 1792 void RenderBlockFlow::repaintOverhangingFloats(bool paintAllDescendants) 1793 { 1794 // Repaint any overhanging floats (if we know we're the one to paint them). 1795 // Otherwise, bail out. 1796 if (!hasOverhangingFloats()) 1797 return; 1798 1799 // FIXME: Avoid disabling LayoutState. At the very least, don't disable it for floats originating 1800 // in this block. Better yet would be to push extra state for the containers of other floats. 1801 LayoutStateDisabler layoutStateDisabler(view()); 1802 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 1803 FloatingObjectSetIterator end = floatingObjectSet.end(); 1804 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { 1805 FloatingObject* floatingObject = *it; 1806 // Only repaint the object if it is overhanging, is not in its own layer, and 1807 // is our responsibility to paint (m_shouldPaint is set). When paintAllDescendants is true, the latter 1808 // condition is replaced with being a descendant of us. 1809 if (logicalBottomForFloat(floatingObject) > logicalHeight() 1810 && !floatingObject->renderer()->hasSelfPaintingLayer() 1811 && (floatingObject->shouldPaint() || (paintAllDescendants && floatingObject->renderer()->isDescendantOf(this)))) { 1812 1813 RenderBox* floatingRenderer = floatingObject->renderer(); 1814 LayoutRectRecorder recorder(*floatingRenderer); 1815 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) 1816 floatingRenderer->setShouldDoFullRepaintAfterLayout(true); 1817 else 1818 floatingRenderer->repaint(); 1819 1820 floatingRenderer->repaintOverhangingFloats(false); 1821 } 1822 } 1823 } 1824 1825 void RenderBlockFlow::repaintOverflow() 1826 { 1827 // FIXME: We could tighten up the left and right invalidation points if we let layoutInlineChildren fill them in based off the particular lines 1828 // it had to lay out. We wouldn't need the hasOverflowClip() hack in that case either. 1829 LayoutUnit repaintLogicalLeft = logicalLeftVisualOverflow(); 1830 LayoutUnit repaintLogicalRight = logicalRightVisualOverflow(); 1831 if (hasOverflowClip()) { 1832 // If we have clipped overflow, we should use layout overflow as well, since visual overflow from lines didn't propagate to our block's overflow. 1833 // Note the old code did this as well but even for overflow:visible. The addition of hasOverflowClip() at least tightens up the hack a bit. 1834 // layoutInlineChildren should be patched to compute the entire repaint rect. 1835 repaintLogicalLeft = min(repaintLogicalLeft, logicalLeftLayoutOverflow()); 1836 repaintLogicalRight = max(repaintLogicalRight, logicalRightLayoutOverflow()); 1837 } 1838 1839 LayoutRect repaintRect; 1840 if (isHorizontalWritingMode()) 1841 repaintRect = LayoutRect(repaintLogicalLeft, m_repaintLogicalTop, repaintLogicalRight - repaintLogicalLeft, m_repaintLogicalBottom - m_repaintLogicalTop); 1842 else 1843 repaintRect = LayoutRect(m_repaintLogicalTop, repaintLogicalLeft, m_repaintLogicalBottom - m_repaintLogicalTop, repaintLogicalRight - repaintLogicalLeft); 1844 1845 // The repaint rect may be split across columns, in which case adjustRectForColumns() will return the union. 1846 adjustRectForColumns(repaintRect); 1847 1848 repaintRect.inflate(maximalOutlineSize(PaintPhaseOutline)); 1849 1850 if (hasOverflowClip()) { 1851 // Adjust repaint rect for scroll offset 1852 repaintRect.move(-scrolledContentOffset()); 1853 1854 // Don't allow this rect to spill out of our overflow box. 1855 repaintRect.intersect(LayoutRect(LayoutPoint(), size())); 1856 } 1857 1858 // Make sure the rect is still non-empty after intersecting for overflow above 1859 if (!repaintRect.isEmpty()) { 1860 repaintRectangle(repaintRect); // We need to do a partial repaint of our content. 1861 if (hasReflection()) 1862 repaintRectangle(reflectedRect(repaintRect)); 1863 } 1864 1865 m_repaintLogicalTop = 0; 1866 m_repaintLogicalBottom = 0; 1867 } 1868 1869 void RenderBlockFlow::paintFloats(PaintInfo& paintInfo, const LayoutPoint& paintOffset, bool preservePhase) 1870 { 1871 if (!m_floatingObjects) 1872 return; 1873 1874 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 1875 FloatingObjectSetIterator end = floatingObjectSet.end(); 1876 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { 1877 FloatingObject* floatingObject = *it; 1878 // Only paint the object if our m_shouldPaint flag is set. 1879 if (floatingObject->shouldPaint() && !floatingObject->renderer()->hasSelfPaintingLayer()) { 1880 PaintInfo currentPaintInfo(paintInfo); 1881 currentPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground; 1882 // FIXME: LayoutPoint version of xPositionForFloatIncludingMargin would make this much cleaner. 1883 LayoutPoint childPoint = flipFloatForWritingModeForChild(floatingObject, LayoutPoint(paintOffset.x() + xPositionForFloatIncludingMargin(floatingObject) - floatingObject->renderer()->x(), paintOffset.y() + yPositionForFloatIncludingMargin(floatingObject) - floatingObject->renderer()->y())); 1884 floatingObject->renderer()->paint(currentPaintInfo, childPoint); 1885 if (!preservePhase) { 1886 currentPaintInfo.phase = PaintPhaseChildBlockBackgrounds; 1887 floatingObject->renderer()->paint(currentPaintInfo, childPoint); 1888 currentPaintInfo.phase = PaintPhaseFloat; 1889 floatingObject->renderer()->paint(currentPaintInfo, childPoint); 1890 currentPaintInfo.phase = PaintPhaseForeground; 1891 floatingObject->renderer()->paint(currentPaintInfo, childPoint); 1892 currentPaintInfo.phase = PaintPhaseOutline; 1893 floatingObject->renderer()->paint(currentPaintInfo, childPoint); 1894 } 1895 } 1896 } 1897 } 1898 1899 void RenderBlockFlow::clipOutFloatingObjects(RenderBlock* rootBlock, const PaintInfo* paintInfo, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock) 1900 { 1901 if (m_floatingObjects) { 1902 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 1903 FloatingObjectSetIterator end = floatingObjectSet.end(); 1904 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { 1905 FloatingObject* floatingObject = *it; 1906 LayoutRect floatBox(offsetFromRootBlock.width() + xPositionForFloatIncludingMargin(floatingObject), 1907 offsetFromRootBlock.height() + yPositionForFloatIncludingMargin(floatingObject), 1908 floatingObject->renderer()->width(), floatingObject->renderer()->height()); 1909 rootBlock->flipForWritingMode(floatBox); 1910 floatBox.move(rootBlockPhysicalPosition.x(), rootBlockPhysicalPosition.y()); 1911 paintInfo->context->clipOut(pixelSnappedIntRect(floatBox)); 1912 } 1913 } 1914 } 1915 1916 void RenderBlockFlow::clearFloats(EClear clear) 1917 { 1918 positionNewFloats(); 1919 // set y position 1920 LayoutUnit newY = 0; 1921 switch (clear) { 1922 case CLEFT: 1923 newY = lowestFloatLogicalBottom(FloatingObject::FloatLeft); 1924 break; 1925 case CRIGHT: 1926 newY = lowestFloatLogicalBottom(FloatingObject::FloatRight); 1927 break; 1928 case CBOTH: 1929 newY = lowestFloatLogicalBottom(); 1930 default: 1931 break; 1932 } 1933 if (height() < newY) 1934 setLogicalHeight(newY); 1935 } 1936 1937 bool RenderBlockFlow::containsFloat(RenderBox* renderer) const 1938 { 1939 return m_floatingObjects && m_floatingObjects->set().contains<FloatingObjectHashTranslator>(renderer); 1940 } 1941 1942 void RenderBlockFlow::removeFloatingObjects() 1943 { 1944 if (!m_floatingObjects) 1945 return; 1946 1947 m_floatingObjects->clear(); 1948 } 1949 1950 LayoutPoint RenderBlockFlow::flipFloatForWritingModeForChild(const FloatingObject* child, const LayoutPoint& point) const 1951 { 1952 if (!style()->isFlippedBlocksWritingMode()) 1953 return point; 1954 1955 // This is similar to RenderBox::flipForWritingModeForChild. We have to subtract out our left/top offsets twice, since 1956 // it's going to get added back in. We hide this complication here so that the calling code looks normal for the unflipped 1957 // case. 1958 if (isHorizontalWritingMode()) 1959 return LayoutPoint(point.x(), point.y() + height() - child->renderer()->height() - 2 * yPositionForFloatIncludingMargin(child)); 1960 return LayoutPoint(point.x() + width() - child->renderer()->width() - 2 * xPositionForFloatIncludingMargin(child), point.y()); 1961 } 1962 1963 LayoutUnit RenderBlockFlow::logicalLeftOffsetForPositioningFloat(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const 1964 { 1965 LayoutUnit offset = fixedOffset; 1966 if (m_floatingObjects && m_floatingObjects->hasLeftObjects()) 1967 offset = m_floatingObjects->logicalLeftOffsetForPositioningFloat(fixedOffset, logicalTop, heightRemaining); 1968 return adjustLogicalLeftOffsetForLine(offset, applyTextIndent); 1969 } 1970 1971 LayoutUnit RenderBlockFlow::logicalRightOffsetForPositioningFloat(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const 1972 { 1973 LayoutUnit offset = fixedOffset; 1974 if (m_floatingObjects && m_floatingObjects->hasRightObjects()) 1975 offset = m_floatingObjects->logicalRightOffsetForPositioningFloat(fixedOffset, logicalTop, heightRemaining); 1976 return adjustLogicalRightOffsetForLine(offset, applyTextIndent); 1977 } 1978 1979 LayoutPoint RenderBlockFlow::computeLogicalLocationForFloat(const FloatingObject* floatingObject, LayoutUnit logicalTopOffset) const 1980 { 1981 RenderBox* childBox = floatingObject->renderer(); 1982 LayoutUnit logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset. 1983 LayoutUnit logicalRightOffset; // Constant part of right offset. 1984 // FIXME Bug 102948: This only works for shape outside directly set on this block. 1985 ShapeInsideInfo* shapeInsideInfo = this->layoutShapeInsideInfo(); 1986 // FIXME: Implement behavior for right floats. 1987 if (shapeInsideInfo) { 1988 LayoutSize floatLogicalSize = logicalSizeForFloat(floatingObject); 1989 // floatingObject's logicalSize doesn't contain the actual height at this point, so we need to calculate it 1990 floatLogicalSize.setHeight(logicalHeightForChild(childBox) + marginBeforeForChild(childBox) + marginAfterForChild(childBox)); 1991 1992 // FIXME: If the float doesn't fit in the shape we should push it under the content box 1993 logicalTopOffset = shapeInsideInfo->computeFirstFitPositionForFloat(floatLogicalSize); 1994 if (logicalHeight() > logicalTopOffset) 1995 logicalTopOffset = logicalHeight(); 1996 1997 SegmentList segments = shapeInsideInfo->computeSegmentsForLine(logicalTopOffset, floatLogicalSize.height()); 1998 // FIXME: Add support for shapes with multiple segments. 1999 if (segments.size() == 1) { 2000 // The segment offsets are relative to the content box. 2001 logicalRightOffset = logicalLeftOffset + segments[0].logicalRight; 2002 logicalLeftOffset += segments[0].logicalLeft; 2003 } 2004 } else { 2005 logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset); 2006 } 2007 2008 LayoutUnit floatLogicalWidth = min(logicalWidthForFloat(floatingObject), logicalRightOffset - logicalLeftOffset); // The width we look for. 2009 2010 LayoutUnit floatLogicalLeft; 2011 2012 bool insideFlowThread = flowThreadContainingBlock(); 2013 2014 if (childBox->style()->floating() == LeftFloat) { 2015 LayoutUnit heightRemainingLeft = 1; 2016 LayoutUnit heightRemainingRight = 1; 2017 floatLogicalLeft = logicalLeftOffsetForPositioningFloat(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft); 2018 while (logicalRightOffsetForPositioningFloat(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight) - floatLogicalLeft < floatLogicalWidth) { 2019 logicalTopOffset += min(heightRemainingLeft, heightRemainingRight); 2020 floatLogicalLeft = logicalLeftOffsetForPositioningFloat(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft); 2021 if (insideFlowThread) { 2022 // Have to re-evaluate all of our offsets, since they may have changed. 2023 logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset); // Constant part of right offset. 2024 logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset. 2025 floatLogicalWidth = min(logicalWidthForFloat(floatingObject), logicalRightOffset - logicalLeftOffset); 2026 } 2027 } 2028 floatLogicalLeft = max(logicalLeftOffset - borderAndPaddingLogicalLeft(), floatLogicalLeft); 2029 } else { 2030 LayoutUnit heightRemainingLeft = 1; 2031 LayoutUnit heightRemainingRight = 1; 2032 floatLogicalLeft = logicalRightOffsetForPositioningFloat(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight); 2033 while (floatLogicalLeft - logicalLeftOffsetForPositioningFloat(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft) < floatLogicalWidth) { 2034 logicalTopOffset += min(heightRemainingLeft, heightRemainingRight); 2035 floatLogicalLeft = logicalRightOffsetForPositioningFloat(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight); 2036 if (insideFlowThread) { 2037 // Have to re-evaluate all of our offsets, since they may have changed. 2038 logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset); // Constant part of right offset. 2039 logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset. 2040 floatLogicalWidth = min(logicalWidthForFloat(floatingObject), logicalRightOffset - logicalLeftOffset); 2041 } 2042 } 2043 // Use the original width of the float here, since the local variable 2044 // |floatLogicalWidth| was capped to the available line width. See 2045 // fast/block/float/clamped-right-float.html. 2046 floatLogicalLeft -= logicalWidthForFloat(floatingObject); 2047 } 2048 2049 return LayoutPoint(floatLogicalLeft, logicalTopOffset); 2050 } 2051 2052 FloatingObject* RenderBlockFlow::insertFloatingObject(RenderBox* floatBox) 2053 { 2054 ASSERT(floatBox->isFloating()); 2055 2056 // Create the list of special objects if we don't aleady have one 2057 if (!m_floatingObjects) { 2058 createFloatingObjects(); 2059 } else { 2060 // Don't insert the object again if it's already in the list 2061 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 2062 FloatingObjectSetIterator it = floatingObjectSet.find<FloatingObjectHashTranslator>(floatBox); 2063 if (it != floatingObjectSet.end()) 2064 return *it; 2065 } 2066 2067 // Create the special object entry & append it to the list 2068 2069 OwnPtr<FloatingObject> newObj = FloatingObject::create(floatBox); 2070 2071 // Our location is irrelevant if we're unsplittable or no pagination is in effect. 2072 // Just go ahead and lay out the float. 2073 bool isChildRenderBlock = floatBox->isRenderBlock(); 2074 if (isChildRenderBlock && !floatBox->needsLayout() && view()->layoutState()->pageLogicalHeightChanged()) 2075 floatBox->setChildNeedsLayout(MarkOnlyThis); 2076 2077 bool needsBlockDirectionLocationSetBeforeLayout = isChildRenderBlock && view()->layoutState()->needsBlockDirectionLocationSetBeforeLayout(); 2078 if (!needsBlockDirectionLocationSetBeforeLayout || isWritingModeRoot()) { // We are unsplittable if we're a block flow root. 2079 floatBox->layoutIfNeeded(); 2080 } else { 2081 floatBox->updateLogicalWidth(); 2082 floatBox->computeAndSetBlockDirectionMargins(this); 2083 } 2084 2085 setLogicalWidthForFloat(newObj.get(), logicalWidthForChild(floatBox) + marginStartForChild(floatBox) + marginEndForChild(floatBox)); 2086 2087 return m_floatingObjects->add(newObj.release()); 2088 } 2089 2090 void RenderBlockFlow::removeFloatingObject(RenderBox* floatBox) 2091 { 2092 if (m_floatingObjects) { 2093 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 2094 FloatingObjectSetIterator it = floatingObjectSet.find<FloatingObjectHashTranslator>(floatBox); 2095 if (it != floatingObjectSet.end()) { 2096 FloatingObject* floatingObject = *it; 2097 if (childrenInline()) { 2098 LayoutUnit logicalTop = logicalTopForFloat(floatingObject); 2099 LayoutUnit logicalBottom = logicalBottomForFloat(floatingObject); 2100 2101 // Fix for https://bugs.webkit.org/show_bug.cgi?id=54995. 2102 if (logicalBottom < 0 || logicalBottom < logicalTop || logicalTop == LayoutUnit::max()) { 2103 logicalBottom = LayoutUnit::max(); 2104 } else { 2105 // Special-case zero- and less-than-zero-height floats: those don't touch 2106 // the line that they're on, but it still needs to be dirtied. This is 2107 // accomplished by pretending they have a height of 1. 2108 logicalBottom = max(logicalBottom, logicalTop + 1); 2109 } 2110 if (floatingObject->originatingLine()) { 2111 if (!selfNeedsLayout()) { 2112 ASSERT(floatingObject->originatingLine()->renderer() == this); 2113 floatingObject->originatingLine()->markDirty(); 2114 } 2115 #if !ASSERT_DISABLED 2116 floatingObject->setOriginatingLine(0); 2117 #endif 2118 } 2119 markLinesDirtyInBlockRange(0, logicalBottom); 2120 } 2121 m_floatingObjects->remove(floatingObject); 2122 } 2123 } 2124 } 2125 2126 void RenderBlockFlow::removeFloatingObjectsBelow(FloatingObject* lastFloat, int logicalOffset) 2127 { 2128 if (!containsFloats()) 2129 return; 2130 2131 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 2132 FloatingObject* curr = floatingObjectSet.last(); 2133 while (curr != lastFloat && (!curr->isPlaced() || logicalTopForFloat(curr) >= logicalOffset)) { 2134 m_floatingObjects->remove(curr); 2135 if (floatingObjectSet.isEmpty()) 2136 break; 2137 curr = floatingObjectSet.last(); 2138 } 2139 } 2140 2141 bool RenderBlockFlow::positionNewFloats() 2142 { 2143 if (!m_floatingObjects) 2144 return false; 2145 2146 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 2147 if (floatingObjectSet.isEmpty()) 2148 return false; 2149 2150 // If all floats have already been positioned, then we have no work to do. 2151 if (floatingObjectSet.last()->isPlaced()) 2152 return false; 2153 2154 // Move backwards through our floating object list until we find a float that has 2155 // already been positioned. Then we'll be able to move forward, positioning all of 2156 // the new floats that need it. 2157 FloatingObjectSetIterator it = floatingObjectSet.end(); 2158 --it; // Go to last item. 2159 FloatingObjectSetIterator begin = floatingObjectSet.begin(); 2160 FloatingObject* lastPlacedFloatingObject = 0; 2161 while (it != begin) { 2162 --it; 2163 if ((*it)->isPlaced()) { 2164 lastPlacedFloatingObject = *it; 2165 ++it; 2166 break; 2167 } 2168 } 2169 2170 LayoutUnit logicalTop = logicalHeight(); 2171 2172 // The float cannot start above the top position of the last positioned float. 2173 if (lastPlacedFloatingObject) 2174 logicalTop = max(logicalTopForFloat(lastPlacedFloatingObject), logicalTop); 2175 2176 FloatingObjectSetIterator end = floatingObjectSet.end(); 2177 // Now walk through the set of unpositioned floats and place them. 2178 for (; it != end; ++it) { 2179 FloatingObject* floatingObject = *it; 2180 // The containing block is responsible for positioning floats, so if we have floats in our 2181 // list that come from somewhere else, do not attempt to position them. 2182 if (floatingObject->renderer()->containingBlock() != this) 2183 continue; 2184 2185 RenderBox* childBox = floatingObject->renderer(); 2186 LayoutUnit childLogicalLeftMargin = style()->isLeftToRightDirection() ? marginStartForChild(childBox) : marginEndForChild(childBox); 2187 2188 LayoutRect oldRect = childBox->frameRect(); 2189 2190 if (childBox->style()->clear() & CLEFT) 2191 logicalTop = max(lowestFloatLogicalBottom(FloatingObject::FloatLeft), logicalTop); 2192 if (childBox->style()->clear() & CRIGHT) 2193 logicalTop = max(lowestFloatLogicalBottom(FloatingObject::FloatRight), logicalTop); 2194 2195 LayoutPoint floatLogicalLocation = computeLogicalLocationForFloat(floatingObject, logicalTop); 2196 2197 setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x()); 2198 2199 setLogicalLeftForChild(childBox, floatLogicalLocation.x() + childLogicalLeftMargin); 2200 setLogicalTopForChild(childBox, floatLogicalLocation.y() + marginBeforeForChild(childBox)); 2201 2202 SubtreeLayoutScope layoutScope(childBox); 2203 LayoutState* layoutState = view()->layoutState(); 2204 bool isPaginated = layoutState->isPaginated(); 2205 if (isPaginated && !childBox->needsLayout()) 2206 childBox->markForPaginationRelayoutIfNeeded(layoutScope); 2207 2208 childBox->layoutIfNeeded(); 2209 2210 if (isPaginated) { 2211 // If we are unsplittable and don't fit, then we need to move down. 2212 // We include our margins as part of the unsplittable area. 2213 LayoutUnit newLogicalTop = adjustForUnsplittableChild(childBox, floatLogicalLocation.y(), true); 2214 2215 // See if we have a pagination strut that is making us move down further. 2216 // Note that an unsplittable child can't also have a pagination strut, so this is 2217 // exclusive with the case above. 2218 RenderBlock* childBlock = childBox->isRenderBlock() ? toRenderBlock(childBox) : 0; 2219 if (childBlock && childBlock->paginationStrut()) { 2220 newLogicalTop += childBlock->paginationStrut(); 2221 childBlock->setPaginationStrut(0); 2222 } 2223 2224 if (newLogicalTop != floatLogicalLocation.y()) { 2225 floatingObject->setPaginationStrut(newLogicalTop - floatLogicalLocation.y()); 2226 2227 floatLogicalLocation = computeLogicalLocationForFloat(floatingObject, newLogicalTop); 2228 setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x()); 2229 2230 setLogicalLeftForChild(childBox, floatLogicalLocation.x() + childLogicalLeftMargin); 2231 setLogicalTopForChild(childBox, floatLogicalLocation.y() + marginBeforeForChild(childBox)); 2232 2233 if (childBlock) 2234 childBlock->setChildNeedsLayout(MarkOnlyThis); 2235 childBox->layoutIfNeeded(); 2236 } 2237 } 2238 2239 setLogicalTopForFloat(floatingObject, floatLogicalLocation.y()); 2240 2241 setLogicalHeightForFloat(floatingObject, logicalHeightForChild(childBox) + marginBeforeForChild(childBox) + marginAfterForChild(childBox)); 2242 2243 m_floatingObjects->addPlacedObject(floatingObject); 2244 2245 if (ShapeOutsideInfo* shapeOutside = childBox->shapeOutsideInfo()) 2246 shapeOutside->setShapeSize(logicalWidthForChild(childBox), logicalHeightForChild(childBox)); 2247 2248 // If the child moved, we have to repaint it. 2249 if (childBox->checkForRepaintDuringLayout()) 2250 childBox->repaintDuringLayoutIfMoved(oldRect); 2251 } 2252 return true; 2253 } 2254 2255 bool RenderBlockFlow::hasOverhangingFloat(RenderBox* renderer) 2256 { 2257 if (!m_floatingObjects || hasColumns() || !parent()) 2258 return false; 2259 2260 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 2261 FloatingObjectSetIterator it = floatingObjectSet.find<FloatingObjectHashTranslator>(renderer); 2262 if (it == floatingObjectSet.end()) 2263 return false; 2264 2265 return logicalBottomForFloat(*it) > logicalHeight(); 2266 } 2267 2268 void RenderBlockFlow::addIntrudingFloats(RenderBlockFlow* prev, LayoutUnit logicalLeftOffset, LayoutUnit logicalTopOffset) 2269 { 2270 ASSERT(!avoidsFloats()); 2271 2272 // If the parent or previous sibling doesn't have any floats to add, don't bother. 2273 if (!prev->m_floatingObjects) 2274 return; 2275 2276 logicalLeftOffset += marginLogicalLeft(); 2277 2278 const FloatingObjectSet& prevSet = prev->m_floatingObjects->set(); 2279 FloatingObjectSetIterator prevEnd = prevSet.end(); 2280 for (FloatingObjectSetIterator prevIt = prevSet.begin(); prevIt != prevEnd; ++prevIt) { 2281 FloatingObject* floatingObject = *prevIt; 2282 if (logicalBottomForFloat(floatingObject) > logicalTopOffset) { 2283 if (!m_floatingObjects || !m_floatingObjects->set().contains(floatingObject)) { 2284 // We create the floating object list lazily. 2285 if (!m_floatingObjects) 2286 createFloatingObjects(); 2287 2288 // Applying the child's margin makes no sense in the case where the child was passed in. 2289 // since this margin was added already through the modification of the |logicalLeftOffset| variable 2290 // above. |logicalLeftOffset| will equal the margin in this case, so it's already been taken 2291 // into account. Only apply this code if prev is the parent, since otherwise the left margin 2292 // will get applied twice. 2293 LayoutSize offset = isHorizontalWritingMode() 2294 ? LayoutSize(logicalLeftOffset - (prev != parent() ? prev->marginLeft() : LayoutUnit()), logicalTopOffset) 2295 : LayoutSize(logicalTopOffset, logicalLeftOffset - (prev != parent() ? prev->marginTop() : LayoutUnit())); 2296 2297 m_floatingObjects->add(floatingObject->copyToNewContainer(offset)); 2298 } 2299 } 2300 } 2301 } 2302 2303 LayoutUnit RenderBlockFlow::addOverhangingFloats(RenderBlockFlow* child, bool makeChildPaintOtherFloats) 2304 { 2305 // Prevent floats from being added to the canvas by the root element, e.g., <html>. 2306 if (child->hasOverflowClip() || !child->containsFloats() || child->isRoot() || child->hasColumns() || child->isWritingModeRoot()) 2307 return 0; 2308 2309 LayoutUnit childLogicalTop = child->logicalTop(); 2310 LayoutUnit childLogicalLeft = child->logicalLeft(); 2311 LayoutUnit lowestFloatLogicalBottom = 0; 2312 2313 // Floats that will remain the child's responsibility to paint should factor into its 2314 // overflow. 2315 FloatingObjectSetIterator childEnd = child->m_floatingObjects->set().end(); 2316 for (FloatingObjectSetIterator childIt = child->m_floatingObjects->set().begin(); childIt != childEnd; ++childIt) { 2317 FloatingObject* floatingObject = *childIt; 2318 LayoutUnit logicalBottomForFloat = min(this->logicalBottomForFloat(floatingObject), LayoutUnit::max() - childLogicalTop); 2319 LayoutUnit logicalBottom = childLogicalTop + logicalBottomForFloat; 2320 lowestFloatLogicalBottom = max(lowestFloatLogicalBottom, logicalBottom); 2321 2322 if (logicalBottom > logicalHeight()) { 2323 // If the object is not in the list, we add it now. 2324 if (!containsFloat(floatingObject->renderer())) { 2325 LayoutSize offset = isHorizontalWritingMode() ? LayoutSize(-childLogicalLeft, -childLogicalTop) : LayoutSize(-childLogicalTop, -childLogicalLeft); 2326 bool shouldPaint = false; 2327 2328 // The nearest enclosing layer always paints the float (so that zindex and stacking 2329 // behaves properly). We always want to propagate the desire to paint the float as 2330 // far out as we can, to the outermost block that overlaps the float, stopping only 2331 // if we hit a self-painting layer boundary. 2332 if (floatingObject->renderer()->enclosingFloatPaintingLayer() == enclosingFloatPaintingLayer()) { 2333 floatingObject->setShouldPaint(false); 2334 shouldPaint = true; 2335 } 2336 // We create the floating object list lazily. 2337 if (!m_floatingObjects) 2338 createFloatingObjects(); 2339 2340 m_floatingObjects->add(floatingObject->copyToNewContainer(offset, shouldPaint, true)); 2341 } 2342 } else { 2343 if (makeChildPaintOtherFloats && !floatingObject->shouldPaint() && !floatingObject->renderer()->hasSelfPaintingLayer() 2344 && floatingObject->renderer()->isDescendantOf(child) && floatingObject->renderer()->enclosingFloatPaintingLayer() == child->enclosingFloatPaintingLayer()) { 2345 // The float is not overhanging from this block, so if it is a descendant of the child, the child should 2346 // paint it (the other case is that it is intruding into the child), unless it has its own layer or enclosing 2347 // layer. 2348 // If makeChildPaintOtherFloats is false, it means that the child must already know about all the floats 2349 // it should paint. 2350 floatingObject->setShouldPaint(true); 2351 } 2352 2353 // Since the float doesn't overhang, it didn't get put into our list. We need to go ahead and add its overflow in to the 2354 // child now. 2355 if (floatingObject->isDescendant()) 2356 child->addOverflowFromChild(floatingObject->renderer(), LayoutSize(xPositionForFloatIncludingMargin(floatingObject), yPositionForFloatIncludingMargin(floatingObject))); 2357 } 2358 } 2359 return lowestFloatLogicalBottom; 2360 } 2361 2362 LayoutUnit RenderBlockFlow::lowestFloatLogicalBottom(FloatingObject::Type floatType) const 2363 { 2364 if (!m_floatingObjects) 2365 return 0; 2366 2367 return m_floatingObjects->lowestFloatLogicalBottom(floatType); 2368 } 2369 2370 LayoutUnit RenderBlockFlow::nextFloatLogicalBottomBelow(LayoutUnit logicalHeight, ShapeOutsideFloatOffsetMode offsetMode) const 2371 { 2372 if (!m_floatingObjects) 2373 return logicalHeight; 2374 2375 LayoutUnit logicalBottom = LayoutUnit::max(); 2376 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 2377 FloatingObjectSetIterator end = floatingObjectSet.end(); 2378 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { 2379 FloatingObject* floatingObject = *it; 2380 LayoutUnit floatLogicalBottom = logicalBottomForFloat(floatingObject); 2381 ShapeOutsideInfo* shapeOutside = floatingObject->renderer()->shapeOutsideInfo(); 2382 if (shapeOutside && (offsetMode == ShapeOutsideFloatShapeOffset)) { 2383 LayoutUnit shapeLogicalBottom = logicalTopForFloat(floatingObject) + marginBeforeForChild(floatingObject->renderer()) + shapeOutside->shapeLogicalBottom(); 2384 // Use the shapeLogicalBottom unless it extends outside of the margin box, in which case it is clipped. 2385 if (shapeLogicalBottom < floatLogicalBottom) 2386 floatLogicalBottom = shapeLogicalBottom; 2387 } 2388 if (floatLogicalBottom > logicalHeight) 2389 logicalBottom = min(floatLogicalBottom, logicalBottom); 2390 } 2391 2392 return logicalBottom == LayoutUnit::max() ? LayoutUnit() : logicalBottom; 2393 } 2394 2395 bool RenderBlockFlow::hitTestFloats(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) 2396 { 2397 if (!m_floatingObjects) 2398 return false; 2399 2400 LayoutPoint adjustedLocation = accumulatedOffset; 2401 if (isRenderView()) { 2402 adjustedLocation += toLayoutSize(toRenderView(this)->frameView()->scrollPosition()); 2403 } 2404 2405 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 2406 FloatingObjectSetIterator begin = floatingObjectSet.begin(); 2407 for (FloatingObjectSetIterator it = floatingObjectSet.end(); it != begin;) { 2408 --it; 2409 FloatingObject* floatingObject = *it; 2410 if (floatingObject->shouldPaint() && !floatingObject->renderer()->hasSelfPaintingLayer()) { 2411 LayoutUnit xOffset = xPositionForFloatIncludingMargin(floatingObject) - floatingObject->renderer()->x(); 2412 LayoutUnit yOffset = yPositionForFloatIncludingMargin(floatingObject) - floatingObject->renderer()->y(); 2413 LayoutPoint childPoint = flipFloatForWritingModeForChild(floatingObject, adjustedLocation + LayoutSize(xOffset, yOffset)); 2414 if (floatingObject->renderer()->hitTest(request, result, locationInContainer, childPoint)) { 2415 updateHitTestResult(result, locationInContainer.point() - toLayoutSize(childPoint)); 2416 return true; 2417 } 2418 } 2419 } 2420 2421 return false; 2422 } 2423 2424 void RenderBlockFlow::adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const 2425 { 2426 RenderBlock::adjustForBorderFit(x, left, right); 2427 if (m_floatingObjects && style()->visibility() == VISIBLE) { 2428 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 2429 FloatingObjectSetIterator end = floatingObjectSet.end(); 2430 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { 2431 FloatingObject* floatingObject = *it; 2432 // Only examine the object if our m_shouldPaint flag is set. 2433 if (floatingObject->shouldPaint()) { 2434 LayoutUnit floatLeft = xPositionForFloatIncludingMargin(floatingObject) - floatingObject->renderer()->x(); 2435 LayoutUnit floatRight = floatLeft + floatingObject->renderer()->width(); 2436 left = min(left, floatLeft); 2437 right = max(right, floatRight); 2438 } 2439 } 2440 } 2441 } 2442 2443 LayoutUnit RenderBlockFlow::logicalLeftFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit logicalHeight) const 2444 { 2445 if (m_floatingObjects && m_floatingObjects->hasLeftObjects()) 2446 return m_floatingObjects->logicalLeftOffset(fixedOffset, logicalTop, logicalHeight); 2447 2448 return fixedOffset; 2449 } 2450 2451 LayoutUnit RenderBlockFlow::logicalRightFloatOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, LayoutUnit logicalHeight) const 2452 { 2453 if (m_floatingObjects && m_floatingObjects->hasRightObjects()) 2454 return m_floatingObjects->logicalRightOffset(fixedOffset, logicalTop, logicalHeight); 2455 2456 return fixedOffset; 2457 } 2458 2459 GapRects RenderBlockFlow::inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, 2460 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* paintInfo) 2461 { 2462 GapRects result; 2463 2464 bool containsStart = selectionState() == SelectionStart || selectionState() == SelectionBoth; 2465 2466 if (!firstLineBox()) { 2467 if (containsStart) { 2468 // Go ahead and update our lastLogicalTop to be the bottom of the block. <hr>s or empty blocks with height can trip this 2469 // case. 2470 lastLogicalTop = rootBlock->blockDirectionOffset(offsetFromRootBlock) + logicalHeight(); 2471 lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight()); 2472 lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight()); 2473 } 2474 return result; 2475 } 2476 2477 RootInlineBox* lastSelectedLine = 0; 2478 RootInlineBox* curr; 2479 for (curr = firstRootBox(); curr && !curr->hasSelectedChildren(); curr = curr->nextRootBox()) { } 2480 2481 // Now paint the gaps for the lines. 2482 for (; curr && curr->hasSelectedChildren(); curr = curr->nextRootBox()) { 2483 LayoutUnit selTop = curr->selectionTopAdjustedForPrecedingBlock(); 2484 LayoutUnit selHeight = curr->selectionHeightAdjustedForPrecedingBlock(); 2485 2486 if (!containsStart && !lastSelectedLine && selectionState() != SelectionStart && selectionState() != SelectionBoth) { 2487 result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, 2488 lastLogicalLeft, lastLogicalRight, selTop, paintInfo)); 2489 } 2490 2491 LayoutRect logicalRect(curr->logicalLeft(), selTop, curr->logicalWidth(), selTop + selHeight); 2492 logicalRect.move(isHorizontalWritingMode() ? offsetFromRootBlock : offsetFromRootBlock.transposedSize()); 2493 LayoutRect physicalRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, logicalRect); 2494 if (!paintInfo || (isHorizontalWritingMode() && physicalRect.y() < paintInfo->rect.maxY() && physicalRect.maxY() > paintInfo->rect.y()) 2495 || (!isHorizontalWritingMode() && physicalRect.x() < paintInfo->rect.maxX() && physicalRect.maxX() > paintInfo->rect.x())) 2496 result.unite(curr->lineSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, selTop, selHeight, paintInfo)); 2497 2498 lastSelectedLine = curr; 2499 } 2500 2501 if (containsStart && !lastSelectedLine) { 2502 // VisibleSelection must start just after our last line. 2503 lastSelectedLine = lastRootBox(); 2504 } 2505 2506 if (lastSelectedLine && selectionState() != SelectionEnd && selectionState() != SelectionBoth) { 2507 // Go ahead and update our lastY to be the bottom of the last selected line. 2508 lastLogicalTop = rootBlock->blockDirectionOffset(offsetFromRootBlock) + lastSelectedLine->selectionBottom(); 2509 lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, lastSelectedLine->selectionBottom()); 2510 lastLogicalRight = logicalRightSelectionOffset(rootBlock, lastSelectedLine->selectionBottom()); 2511 } 2512 return result; 2513 } 2514 2515 template <typename CharacterType> 2516 static inline TextRun constructTextRunInternal(RenderObject* context, const Font& font, const CharacterType* characters, int length, RenderStyle* style, TextRun::ExpansionBehavior expansion) 2517 { 2518 ASSERT(style); 2519 2520 TextDirection textDirection = LTR; 2521 bool directionalOverride = style->rtlOrdering() == VisualOrder; 2522 2523 TextRun run(characters, length, 0, 0, expansion, textDirection, directionalOverride); 2524 if (textRunNeedsRenderingContext(font)) 2525 run.setRenderingContext(SVGTextRunRenderingContext::create(context)); 2526 2527 return run; 2528 } 2529 2530 template <typename CharacterType> 2531 static inline TextRun constructTextRunInternal(RenderObject* context, const Font& font, const CharacterType* characters, int length, RenderStyle* style, TextRun::ExpansionBehavior expansion, TextRunFlags flags) 2532 { 2533 ASSERT(style); 2534 2535 TextDirection textDirection = LTR; 2536 bool directionalOverride = style->rtlOrdering() == VisualOrder; 2537 if (flags != DefaultTextRunFlags) { 2538 if (flags & RespectDirection) 2539 textDirection = style->direction(); 2540 if (flags & RespectDirectionOverride) 2541 directionalOverride |= isOverride(style->unicodeBidi()); 2542 } 2543 2544 TextRun run(characters, length, 0, 0, expansion, textDirection, directionalOverride); 2545 if (!directionalOverride) { 2546 BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver; 2547 bidiResolver.setStatus(BidiStatus(run.direction(), run.directionalOverride())); 2548 bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&run, 0)); 2549 bool hasStrongDirectionality; 2550 TextDirection direction = bidiResolver.determineParagraphDirectionality(&hasStrongDirectionality); 2551 if (hasStrongDirectionality) 2552 run.setDirection(direction); 2553 } 2554 2555 if (textRunNeedsRenderingContext(font)) 2556 run.setRenderingContext(SVGTextRunRenderingContext::create(context)); 2557 2558 return run; 2559 } 2560 2561 TextRun RenderBlockFlow::constructTextRun(RenderObject* context, const Font& font, const LChar* characters, int length, RenderStyle* style, TextRun::ExpansionBehavior expansion) 2562 { 2563 return constructTextRunInternal(context, font, characters, length, style, expansion); 2564 } 2565 2566 TextRun RenderBlockFlow::constructTextRun(RenderObject* context, const Font& font, const UChar* characters, int length, RenderStyle* style, TextRun::ExpansionBehavior expansion) 2567 { 2568 return constructTextRunInternal(context, font, characters, length, style, expansion); 2569 } 2570 2571 TextRun RenderBlockFlow::constructTextRun(RenderObject* context, const Font& font, const RenderText* text, RenderStyle* style, TextRun::ExpansionBehavior expansion) 2572 { 2573 if (text->is8Bit()) 2574 return constructTextRunInternal(context, font, text->characters8(), text->textLength(), style, expansion); 2575 return constructTextRunInternal(context, font, text->characters16(), text->textLength(), style, expansion); 2576 } 2577 2578 TextRun RenderBlockFlow::constructTextRun(RenderObject* context, const Font& font, const RenderText* text, unsigned offset, unsigned length, RenderStyle* style, TextRun::ExpansionBehavior expansion) 2579 { 2580 ASSERT(offset + length <= text->textLength()); 2581 if (text->is8Bit()) 2582 return constructTextRunInternal(context, font, text->characters8() + offset, length, style, expansion); 2583 return constructTextRunInternal(context, font, text->characters16() + offset, length, style, expansion); 2584 } 2585 2586 TextRun RenderBlockFlow::constructTextRun(RenderObject* context, const Font& font, const String& string, RenderStyle* style, TextRun::ExpansionBehavior expansion, TextRunFlags flags) 2587 { 2588 unsigned length = string.length(); 2589 if (!length) 2590 return constructTextRunInternal(context, font, static_cast<const LChar*>(0), length, style, expansion, flags); 2591 if (string.is8Bit()) 2592 return constructTextRunInternal(context, font, string.characters8(), length, style, expansion, flags); 2593 return constructTextRunInternal(context, font, string.characters16(), length, style, expansion, flags); 2594 } 2595 2596 RootInlineBox* RenderBlockFlow::createRootInlineBox() 2597 { 2598 return new RootInlineBox(this); 2599 } 2600 2601 void RenderBlockFlow::createRenderNamedFlowFragmentIfNeeded() 2602 { 2603 if (!RuntimeEnabledFeatures::cssRegionsEnabled() 2604 || renderNamedFlowFragment() 2605 || isRenderNamedFlowFragment()) 2606 return; 2607 2608 RenderStyle* styleToUse = style(); 2609 if (styleToUse->isDisplayRegionType() && styleToUse->hasFlowFrom() && document().renderView()) { 2610 RenderNamedFlowFragment* flowFragment = RenderNamedFlowFragment::createAnonymous(&document()); 2611 flowFragment->setStyleForNamedFlowFragment(styleToUse); 2612 setRenderNamedFlowFragment(flowFragment); 2613 addChild(flowFragment); 2614 } 2615 } 2616 2617 void RenderBlockFlow::insertedIntoTree() 2618 { 2619 RenderBlock::insertedIntoTree(); 2620 2621 createRenderNamedFlowFragmentIfNeeded(); 2622 } 2623 2624 bool RenderBlockFlow::canHaveChildren() const 2625 { 2626 return !renderNamedFlowFragment() ? RenderBlock::canHaveChildren() : renderNamedFlowFragment()->canHaveChildren(); 2627 } 2628 2629 bool RenderBlockFlow::canHaveGeneratedChildren() const 2630 { 2631 return !renderNamedFlowFragment() ? RenderBlock::canHaveGeneratedChildren() : renderNamedFlowFragment()->canHaveGeneratedChildren(); 2632 } 2633 2634 void RenderBlockFlow::updateLogicalHeight() 2635 { 2636 RenderBlock::updateLogicalHeight(); 2637 2638 if (renderNamedFlowFragment()) 2639 renderNamedFlowFragment()->setLogicalHeight(max<LayoutUnit>(0, logicalHeight() - borderAndPaddingLogicalHeight())); 2640 } 2641 2642 void RenderBlockFlow::setRenderNamedFlowFragment(RenderNamedFlowFragment* flowFragment) 2643 { 2644 RenderBlockFlow::RenderBlockFlowRareData& rareData = ensureRareData(); 2645 if (rareData.m_renderNamedFlowFragment) 2646 rareData.m_renderNamedFlowFragment->destroy(); 2647 rareData.m_renderNamedFlowFragment = flowFragment; 2648 } 2649 2650 RenderBlockFlow::RenderBlockFlowRareData& RenderBlockFlow::ensureRareData() 2651 { 2652 if (m_rareData) 2653 return *m_rareData; 2654 2655 m_rareData = adoptPtr(new RenderBlockFlowRareData(this)); 2656 return *m_rareData; 2657 } 2658 2659 } // namespace WebCore 2660