X-Git-Url: http://git.webkit.org/?p=WebKit-https.git;a=blobdiff_plain;f=Source%2FWebCore%2Frendering%2FRenderBox.cpp;h=bb801b554220c5becb20bc8d4598a255cec0e137;hp=7ebf811201ab621c8074ea294b046fc9d09e7f6f;hb=00b2d7d220338726fe041cf917a87cf3db2de973;hpb=362cf34dffe27b0ef35e64b3dc9764b5c5b6c99b diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp index 7ebf811..bb801b5 100644 --- a/Source/WebCore/rendering/RenderBox.cpp +++ b/Source/WebCore/rendering/RenderBox.cpp @@ -25,6 +25,7 @@ #include "config.h" #include "RenderBox.h" +#include "CSSFontSelector.h" #include "Chrome.h" #include "ChromeClient.h" #include "Document.h" @@ -245,6 +246,8 @@ LayoutRect RenderBox::borderBoxRectInRegion(RenderRegion* region, RenderBoxRegio break; currentBox = currentBox->containingBlock(); + if (!currentBox) + break; region = currentBox->clampToStartAndEndRegions(region); currentBoxInfo = currentBox->renderBoxRegionInfo(region); } @@ -378,18 +381,15 @@ void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle bool isBodyRenderer = isBody(); bool isDocElementRenderer = isDocumentElementRenderer(); - // Set the text color if we're the body. - if (isBodyRenderer) - document().setTextColor(newStyle.visitedDependentColor(CSSPropertyColor)); - if (isDocElementRenderer || isBodyRenderer) { // Propagate the new writing mode and direction up to the RenderView. + auto* documentElementRenderer = document().documentElement()->renderer(); RenderStyle& viewStyle = view().style(); bool viewChangedWritingMode = false; bool rootStyleChanged = false; bool viewStyleChanged = false; - RenderObject* rootRenderer = isBodyRenderer ? document().documentElement()->renderer() : nullptr; - if (viewStyle.direction() != newStyle.direction() && (isDocElementRenderer || !document().directionSetOnDocumentElement())) { + auto* rootRenderer = isBodyRenderer ? documentElementRenderer : nullptr; + if (viewStyle.direction() != newStyle.direction() && (isDocElementRenderer || !documentElementRenderer->style().hasExplicitlySetDirection())) { viewStyle.setDirection(newStyle.direction()); viewStyleChanged = true; if (isBodyRenderer) { @@ -399,7 +399,7 @@ void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle setNeedsLayoutAndPrefWidthsRecalc(); } - if (viewStyle.writingMode() != newStyle.writingMode() && (isDocElementRenderer || !document().writingModeSetOnDocumentElement())) { + if (viewStyle.writingMode() != newStyle.writingMode() && (isDocElementRenderer || !documentElementRenderer->style().hasExplicitlySetWritingMode())) { viewStyle.setWritingMode(newStyle.writingMode()); viewChangedWritingMode = true; viewStyleChanged = true; @@ -427,6 +427,15 @@ void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle if (rootStyleChanged && is(rootRenderer) && downcast(*rootRenderer).multiColumnFlowThread()) downcast(*rootRenderer).updateStylesForColumnChildren(); + + if (isBodyRenderer && pagination.mode != Pagination::Unpaginated && frame().page()->paginationLineGridEnabled()) { + // Propagate the body font back up to the RenderView and use it as + // the basis of the grid. + if (newStyle.fontDescription() != view().style().fontDescription()) { + view().style().setFontDescription(newStyle.fontDescription()); + view().style().fontCascade().update(&document().fontSelector()); + } + } if (diff != StyleDifferenceEqual) view().compositor().rootOrBodyStyleChanged(*this, oldStyle); @@ -637,7 +646,7 @@ void RenderBox::updateLayerTransform() layer()->updateTransform(); } -LayoutUnit RenderBox::constrainLogicalWidthInRegionByMinMax(LayoutUnit logicalWidth, LayoutUnit availableWidth, RenderBlock* cb, RenderRegion* region) const +LayoutUnit RenderBox::constrainLogicalWidthInRegionByMinMax(LayoutUnit logicalWidth, LayoutUnit availableWidth, RenderBlock& cb, RenderRegion* region) const { const RenderStyle& styleToUse = style(); if (!styleToUse.logicalMaxWidth().isUndefined()) @@ -681,6 +690,15 @@ RoundedRect::Radii RenderBox::borderRadii() const return style.getRoundedBorderFor(bounds).radii(); } +LayoutRect RenderBox::contentBoxRect() const +{ + LayoutUnit x = borderLeft() + paddingLeft(); + if (layer() && layer()->verticalScrollbarIsOnLeft()) + x += verticalScrollbarWidth(); + LayoutUnit y = borderTop() + paddingTop(); + return LayoutRect(x, y, contentWidth(), contentHeight()); +} + IntRect RenderBox::absoluteContentBox() const { // This is wrong with transforms and flipped writing modes. @@ -718,10 +736,10 @@ LayoutRect RenderBox::outlineBoundsForRepaint(const RenderLayerModelObject* repa return LayoutRect(snapRectToDevicePixels(box, document().deviceScaleFactor())); } -void RenderBox::addFocusRingRects(Vector& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject*) +void RenderBox::addFocusRingRects(Vector& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject*) { if (!size().isEmpty()) - rects.append(snappedIntRect(additionalOffset, size())); + rects.append(LayoutRect(additionalOffset, size())); } int RenderBox::reflectionOffset() const @@ -1679,7 +1697,7 @@ void RenderBox::imageChanged(WrappedImagePtr image, const IntRect*) #if ENABLE(CSS_SHAPES) ShapeValue* shapeOutsideValue = style().shapeOutside(); - if (!view().frameView().isInLayout() && isFloating() && shapeOutsideValue && shapeOutsideValue->image() && shapeOutsideValue->image()->data() == image) { + if (!view().frameView().isInRenderTreeLayout() && isFloating() && shapeOutsideValue && shapeOutsideValue->image() && shapeOutsideValue->image()->data() == image) { ShapeOutsideInfo::ensureInfo(*this).markShapeAsDirty(); markShapeOutsideDependentsForLayout(); } @@ -1808,11 +1826,11 @@ LayoutRect RenderBox::overflowClipRect(const LayoutPoint& location, RenderRegion clipRect.setSize(clipRect.size() - LayoutSize(borderLeft() + borderRight(), borderTop() + borderBottom())); // Subtract out scrollbars if we have them. - if (layer()) { - if (style().shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) + if (layer()) { + if (style().shouldPlaceBlockDirectionScrollbarOnLeft()) clipRect.move(layer()->verticalScrollbarWidth(relevancy), 0); clipRect.contract(layer()->verticalScrollbarWidth(relevancy), layer()->horizontalScrollbarHeight(relevancy)); - } + } return clipRect; } @@ -1846,18 +1864,18 @@ LayoutRect RenderBox::clipRect(const LayoutPoint& location, RenderRegion* region return clipRect; } -LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlock* cb, RenderRegion* region) const +LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlock& cb, RenderRegion* region) const { RenderRegion* containingBlockRegion = nullptr; LayoutUnit logicalTopPosition = logicalTop(); if (region) { LayoutUnit offsetFromLogicalTopOfRegion = region ? region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage() : LayoutUnit(); logicalTopPosition = std::max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion); - containingBlockRegion = cb->clampToStartAndEndRegions(region); + containingBlockRegion = cb.clampToStartAndEndRegions(region); } - LayoutUnit logicalHeight = cb->logicalHeightForChild(*this); - LayoutUnit result = cb->availableLogicalWidthForLineInRegion(logicalTopPosition, false, containingBlockRegion, logicalHeight) - childMarginStart - childMarginEnd; + LayoutUnit logicalHeight = cb.logicalHeightForChild(*this); + LayoutUnit result = cb.availableLogicalWidthForLineInRegion(logicalTopPosition, DoNotIndentText, containingBlockRegion, logicalHeight) - childMarginStart - childMarginEnd; // We need to see if margins on either the start side or the end side can contain the floats in question. If they can, // then just using the line width is inaccurate. In the case where a float completely fits, we don't need to use the line @@ -1865,9 +1883,9 @@ LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStar // doesn't fit, we can use the line offset, but we need to grow it by the margin to reflect the fact that the margin was // "consumed" by the float. Negative margins aren't consumed by the float, and so we ignore them. if (childMarginStart > 0) { - LayoutUnit startContentSide = cb->startOffsetForContent(containingBlockRegion); + LayoutUnit startContentSide = cb.startOffsetForContent(containingBlockRegion); LayoutUnit startContentSideWithMargin = startContentSide + childMarginStart; - LayoutUnit startOffset = cb->startOffsetForLineInRegion(logicalTopPosition, false, containingBlockRegion, logicalHeight); + LayoutUnit startOffset = cb.startOffsetForLineInRegion(logicalTopPosition, DoNotIndentText, containingBlockRegion, logicalHeight); if (startOffset > startContentSideWithMargin) result += childMarginStart; else @@ -1875,9 +1893,9 @@ LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStar } if (childMarginEnd > 0) { - LayoutUnit endContentSide = cb->endOffsetForContent(containingBlockRegion); + LayoutUnit endContentSide = cb.endOffsetForContent(containingBlockRegion); LayoutUnit endContentSideWithMargin = endContentSide + childMarginEnd; - LayoutUnit endOffset = cb->endOffsetForLineInRegion(logicalTopPosition, false, containingBlockRegion, logicalHeight); + LayoutUnit endOffset = cb.endOffsetForLineInRegion(logicalTopPosition, DoNotIndentText, containingBlockRegion, logicalHeight); if (endOffset > endContentSideWithMargin) result += childMarginEnd; else @@ -1941,7 +1959,7 @@ LayoutUnit RenderBox::containingBlockAvailableLineWidthInRegion(RenderRegion* re logicalTopPosition = std::max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion); containingBlockRegion = cb->clampToStartAndEndRegions(region); } - return cb->availableLogicalWidthForLineInRegion(logicalTopPosition, false, containingBlockRegion, availableLogicalHeight(IncludeMarginBorderPadding)); + return cb->availableLogicalWidthForLineInRegion(logicalTopPosition, DoNotIndentText, containingBlockRegion, availableLogicalHeight(IncludeMarginBorderPadding)); } LayoutUnit RenderBox::perpendicularContainingBlockLogicalHeight() const @@ -2166,17 +2184,10 @@ LayoutRect RenderBox::clippedOverflowRectForRepaint(const RenderLayerModelObject { if (style().visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent()) return LayoutRect(); - LayoutRect r = visualOverflowRect(); - // FIXME: layoutDelta needs to be applied in parts before/after transforms and // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308 r.move(view().layoutDelta()); - - // We have to use maximalOutlineSize() because a child might have an outline - // that projects outside of our overflowRect. - ASSERT(style().outlineSize() <= view().maximalOutlineSize()); - r.inflate(view().maximalOutlineSize()); return computeRectForRepaint(r, repaintContainer); } @@ -2369,14 +2380,19 @@ void RenderBox::computeLogicalWidthInRegion(LogicalExtentComputedValues& compute // https://bugs.webkit.org/show_bug.cgi?id=46418 bool inVerticalBox = parent()->isDeprecatedFlexibleBox() && (parent()->style().boxOrient() == VERTICAL); bool stretching = (parent()->style().boxAlign() == BSTRETCH); + // FIXME: Stretching is the only reason why we don't want the box to be treated as a replaced element, so we could perhaps + // refactor all this logic, not only for flex and grid since alignment is intended to be applied to any block. bool treatAsReplaced = shouldComputeSizeAsReplaced() && (!inVerticalBox || !stretching); +#if ENABLE(CSS_GRID_LAYOUT) + treatAsReplaced = treatAsReplaced && (!isGridItem() || !hasStretchedLogicalWidth()); +#endif const RenderStyle& styleToUse = style(); Length logicalWidthLength = treatAsReplaced ? Length(computeReplacedLogicalWidth(), Fixed) : styleToUse.logicalWidth(); - RenderBlock* cb = containingBlock(); + RenderBlock& cb = *containingBlock(); LayoutUnit containerLogicalWidth = std::max(0, containingBlockLogicalWidthForContentInRegion(region)); - bool hasPerpendicularContainingBlock = cb->isHorizontalWritingMode() != isHorizontalWritingMode(); + bool hasPerpendicularContainingBlock = cb.isHorizontalWritingMode() != isHorizontalWritingMode(); if (isInline() && !isInlineBlockOrInlineTable()) { // just calculate margins @@ -2410,22 +2426,22 @@ void RenderBox::computeLogicalWidthInRegion(LogicalExtentComputedValues& compute computedValues.m_margins.m_end = minimumValueForLength(styleToUse.marginEnd(), containerLogicalWidth); } else { LayoutUnit containerLogicalWidthForAutoMargins = containerLogicalWidth; - if (avoidsFloats() && cb->containsFloats()) + if (avoidsFloats() && cb.containsFloats()) containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(region); - bool hasInvertedDirection = cb->style().isLeftToRightDirection() != style().isLeftToRightDirection(); + bool hasInvertedDirection = cb.style().isLeftToRightDirection() != style().isLeftToRightDirection(); computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, computedValues.m_extent, hasInvertedDirection ? computedValues.m_margins.m_end : computedValues.m_margins.m_start, hasInvertedDirection ? computedValues.m_margins.m_start : computedValues.m_margins.m_end); } if (!hasPerpendicularContainingBlock && containerLogicalWidth && containerLogicalWidth != (computedValues.m_extent + computedValues.m_margins.m_start + computedValues.m_margins.m_end) - && !isFloating() && !isInline() && !cb->isFlexibleBoxIncludingDeprecated() + && !isFloating() && !isInline() && !cb.isFlexibleBoxIncludingDeprecated() #if ENABLE(CSS_GRID_LAYOUT) - && !cb->isRenderGrid() + && !cb.isRenderGrid() #endif ) { - LayoutUnit newMargin = containerLogicalWidth - computedValues.m_extent - cb->marginStartForChild(*this); - bool hasInvertedDirection = cb->style().isLeftToRightDirection() != style().isLeftToRightDirection(); + LayoutUnit newMargin = containerLogicalWidth - computedValues.m_extent - cb.marginStartForChild(*this); + bool hasInvertedDirection = cb.style().isLeftToRightDirection() != style().isLeftToRightDirection(); if (hasInvertedDirection) computedValues.m_margins.m_start = newMargin; else @@ -2473,7 +2489,7 @@ LayoutUnit RenderBox::computeIntrinsicLogicalWidthUsing(Length logicalWidthLengt } LayoutUnit RenderBox::computeLogicalWidthInRegionUsing(SizeType widthType, Length logicalWidth, LayoutUnit availableLogicalWidth, - const RenderBlock* cb, RenderRegion* region) const + const RenderBlock& cb, RenderRegion* region) const { ASSERT(widthType == MinSize || widthType == MainOrPreferredSize || !logicalWidth.isAuto()); if (widthType == MinSize && logicalWidth.isAuto()) @@ -2491,7 +2507,7 @@ LayoutUnit RenderBox::computeLogicalWidthInRegionUsing(SizeType widthType, Lengt LayoutUnit marginEnd = 0; LayoutUnit logicalWidthResult = fillAvailableMeasure(availableLogicalWidth, marginStart, marginEnd); - if (shrinkToAvoidFloats() && cb->containsFloats()) + if (shrinkToAvoidFloats() && cb.containsFloats()) logicalWidthResult = std::min(logicalWidthResult, shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, cb, region)); if (widthType == MainOrPreferredSize && sizesLogicalWidthToFitContent(widthType)) @@ -2517,6 +2533,23 @@ static bool isStretchingColumnFlexItem(const RenderBox& flexitem) return false; } +// FIXME: Can/Should we move this inside specific layout classes (flex. grid)? Can we refactor columnFlexItemHasStretchAlignment logic? +bool RenderBox::hasStretchedLogicalWidth() const +{ + auto& style = this->style(); + if (!style.logicalWidth().isAuto() || style.marginStart().isAuto() || style.marginEnd().isAuto()) + return false; + RenderBlock* containingBlock = this->containingBlock(); + if (!containingBlock) { + // We are evaluating align-self/justify-self, which default to 'normal' for the root element. + // The 'normal' value behaves like 'start' except for Flexbox Items, which obviously should have a container. + return false; + } + if (containingBlock->isHorizontalWritingMode() != isHorizontalWritingMode()) + return RenderStyle::resolveAlignment(containingBlock->style(), style, ItemPositionStretch) == ItemPositionStretch; + return RenderStyle::resolveJustification(containingBlock->style(), style, ItemPositionStretch) == ItemPositionStretch; +} + bool RenderBox::sizesLogicalWidthToFitContent(SizeType widthType) const { // Anonymous inline blocks always fill the width of their containing block. @@ -2529,10 +2562,8 @@ bool RenderBox::sizesLogicalWidthToFitContent(SizeType widthType) const return true; #if ENABLE(CSS_GRID_LAYOUT) - if (parent()->isRenderGrid()) { - bool allowedToStretchChildAlongRowAxis = style().logicalWidth().isAuto() && !style().marginStartUsing(&parent()->style()).isAuto() && !style().marginEndUsing(&parent()->style()).isAuto(); - return !allowedToStretchChildAlongRowAxis || RenderStyle::resolveJustification(parent()->style(), style(), ItemPositionStretch) != ItemPositionStretch; - } + if (isGridItem()) + return !hasStretchedLogicalWidth(); #endif // This code may look a bit strange. Basically width:intrinsic should clamp the size when testing both @@ -2546,7 +2577,7 @@ bool RenderBox::sizesLogicalWidthToFitContent(SizeType widthType) const // FIXME: Think about block-flow here. Need to find out how marquee direction relates to // block-flow (as well as how marquee overflow should relate to block flow). // https://bugs.webkit.org/show_bug.cgi?id=46472 - if (parent()->style().overflowX() == OMARQUEE) { + if (parent()->isHTMLMarquee()) { EMarqueeDirection dir = parent()->style().marqueeDirection(); if (dir == MAUTO || dir == MFORWARD || dir == MBACKWARD || dir == MLEFT || dir == MRIGHT) return true; @@ -2583,9 +2614,9 @@ bool RenderBox::sizesLogicalWidthToFitContent(SizeType widthType) const return false; } -void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const +void RenderBox::computeInlineDirectionMargins(RenderBlock& containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const { - const RenderStyle& containingBlockStyle = containingBlock->style(); + const RenderStyle& containingBlockStyle = containingBlock.style(); Length marginStartLength = style().marginStartUsing(&containingBlockStyle); Length marginEndLength = style().marginEndUsing(&containingBlockStyle); @@ -2598,7 +2629,7 @@ void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, Layo // Case One: The object is being centered in the containing block's available logical width. if ((marginStartLength.isAuto() && marginEndLength.isAuto() && childWidth < containerWidth) - || (!marginStartLength.isAuto() && !marginEndLength.isAuto() && containingBlock->style().textAlign() == WEBKIT_CENTER)) { + || (!marginStartLength.isAuto() && !marginEndLength.isAuto() && containingBlock.style().textAlign() == WEBKIT_CENTER)) { // Other browsers center the margin box for align=center elements so we match them here. LayoutUnit marginStartWidth = minimumValueForLength(marginStartLength, containerWidth); LayoutUnit marginEndWidth = minimumValueForLength(marginEndLength, containerWidth); @@ -2653,10 +2684,10 @@ RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, Render computeLogicalWidthInRegion(computedValues, region); // Now determine the insets based off where this object is supposed to be positioned. - RenderBlock* cb = containingBlock(); - RenderRegion* clampedContainingBlockRegion = cb->clampToStartAndEndRegions(region); - RenderBoxRegionInfo* containingBlockInfo = cb->renderBoxRegionInfo(clampedContainingBlockRegion); - LayoutUnit containingBlockLogicalWidth = cb->logicalWidth(); + RenderBlock& cb = *containingBlock(); + RenderRegion* clampedContainingBlockRegion = cb.clampToStartAndEndRegions(region); + RenderBoxRegionInfo* containingBlockInfo = cb.renderBoxRegionInfo(clampedContainingBlockRegion); + LayoutUnit containingBlockLogicalWidth = cb.logicalWidth(); LayoutUnit containingBlockLogicalWidthInRegion = containingBlockInfo ? containingBlockInfo->logicalWidth() : containingBlockLogicalWidth; LayoutUnit marginStartInRegion = computedValues.m_margins.m_start; @@ -2671,15 +2702,15 @@ RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, Render LayoutUnit logicalLeftOffset = 0; - if (!isOutOfFlowPositioned() && avoidsFloats() && cb->containsFloats()) { - LayoutUnit startPositionDelta = cb->computeStartPositionDeltaForChildAvoidingFloats(*this, marginStartInRegion, region); - if (cb->style().isLeftToRightDirection()) + if (!isOutOfFlowPositioned() && avoidsFloats() && cb.containsFloats()) { + LayoutUnit startPositionDelta = cb.computeStartPositionDeltaForChildAvoidingFloats(*this, marginStartInRegion, region); + if (cb.style().isLeftToRightDirection()) logicalLeftDelta += startPositionDelta; else logicalRightDelta += startPositionDelta; } - if (cb->style().isLeftToRightDirection()) + if (cb.style().isLeftToRightDirection()) logicalLeftOffset += logicalLeftDelta; else logicalLeftOffset -= (widthDelta + logicalRightDelta); @@ -2745,11 +2776,11 @@ void RenderBox::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logica if (isOutOfFlowPositioned()) computePositionedLogicalHeight(computedValues); else { - RenderBlock* cb = containingBlock(); - bool hasPerpendicularContainingBlock = cb->isHorizontalWritingMode() != isHorizontalWritingMode(); + RenderBlock& cb = *containingBlock(); + bool hasPerpendicularContainingBlock = cb.isHorizontalWritingMode() != isHorizontalWritingMode(); if (!hasPerpendicularContainingBlock) { - bool shouldFlipBeforeAfter = cb->style().writingMode() != style().writingMode(); + bool shouldFlipBeforeAfter = cb.style().writingMode() != style().writingMode(); computeBlockDirectionMargins(cb, shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before, shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after); @@ -2758,7 +2789,7 @@ void RenderBox::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logica // For tables, calculate margins only. if (isTable()) { if (hasPerpendicularContainingBlock) { - bool shouldFlipBeforeAfter = shouldFlipBeforeAfterMargins(cb->style(), &style()); + bool shouldFlipBeforeAfter = shouldFlipBeforeAfterMargins(cb.style(), &style()); computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), computedValues.m_extent, shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before, shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after); @@ -2823,7 +2854,7 @@ void RenderBox::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logica computedValues.m_extent = heightResult; if (hasPerpendicularContainingBlock) { - bool shouldFlipBeforeAfter = shouldFlipBeforeAfterMargins(cb->style(), &style()); + bool shouldFlipBeforeAfter = shouldFlipBeforeAfterMargins(cb.style(), &style()); computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), heightResult, shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before, shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after); @@ -2890,18 +2921,18 @@ Optional RenderBox::computeContentAndScrollbarLogicalHeightUsing(Siz return Nullopt; } -bool RenderBox::skipContainingBlockForPercentHeightCalculation(const RenderBox* containingBlock, bool isPerpendicularWritingMode) const +bool RenderBox::skipContainingBlockForPercentHeightCalculation(const RenderBox& containingBlock, bool isPerpendicularWritingMode) const { // Flow threads for multicol or paged overflow should be skipped. They are invisible to the DOM, // and percent heights of children should be resolved against the multicol or paged container. - if (containingBlock->isInFlowRenderFlowThread() && !isPerpendicularWritingMode) + if (containingBlock.isInFlowRenderFlowThread() && !isPerpendicularWritingMode) return true; // For quirks mode and anonymous blocks, we skip auto-height containingBlocks when computing percentages. // For standards mode, we treat the percentage as auto if it has an auto-height containing block. - if (!document().inQuirksMode() && !containingBlock->isAnonymousBlock()) + if (!document().inQuirksMode() && !containingBlock.isAnonymousBlock()) return false; - return !containingBlock->isTableCell() && !containingBlock->isOutOfFlowPositioned() && containingBlock->style().logicalHeight().isAuto() && isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode(); + return !containingBlock.isTableCell() && !containingBlock.isOutOfFlowPositioned() && containingBlock.style().logicalHeight().isAuto() && isHorizontalWritingMode() == containingBlock.isHorizontalWritingMode(); } static bool tableCellShouldHaveZeroInitialSize(const RenderBlock& block, bool scrollsOverflowY) @@ -2926,7 +2957,7 @@ Optional RenderBox::computePercentageLogicalHeight(const Length& hei const RenderBox* containingBlockChild = this; LayoutUnit rootMarginBorderPaddingHeight = 0; bool isHorizontal = isHorizontalWritingMode(); - while (!cb->isRenderView() && skipContainingBlockForPercentHeightCalculation(cb, isHorizontal != cb->isHorizontalWritingMode())) { + while (cb && !is(*cb) && skipContainingBlockForPercentHeightCalculation(*cb, isHorizontal != cb->isHorizontalWritingMode())) { if (cb->isBody() || cb->isDocumentElementRenderer()) rootMarginBorderPaddingHeight += cb->marginBefore() + cb->marginAfter() + cb->borderAndPaddingLogicalHeight(); skippedAutoHeightContainingBlock = true; @@ -3032,7 +3063,7 @@ LayoutUnit RenderBox::computeReplacedLogicalWidthUsing(SizeType widthType, Lengt // FIXME: containingBlockLogicalWidthForContent() is wrong if the replaced element's block-flow is perpendicular to the // containing block's block-flow. // https://bugs.webkit.org/show_bug.cgi?id=46496 - const LayoutUnit cw = isOutOfFlowPositioned() ? containingBlockLogicalWidthForPositioned(downcast(container())) : containingBlockLogicalWidthForContent(); + const LayoutUnit cw = isOutOfFlowPositioned() ? containingBlockLogicalWidthForPositioned(downcast(*container())) : containingBlockLogicalWidthForContent(); Length containerLogicalWidth = containingBlock()->style().logicalWidth(); // FIXME: Handle cases when containing block width is calculated or viewport percent. // https://bugs.webkit.org/show_bug.cgi?id=91071 @@ -3079,7 +3110,7 @@ LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(SizeType heightType, Len case Calculated: { auto cb = isOutOfFlowPositioned() ? container() : containingBlock(); - while (cb->isAnonymous() && !is(*cb)) { + while (cb && cb->isAnonymous() && !is(*cb)) { cb = cb->containingBlock(); downcast(*cb).addPercentHeightDescendant(const_cast(*this)); } @@ -3101,7 +3132,7 @@ LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(SizeType heightType, Len // https://bugs.webkit.org/show_bug.cgi?id=46496 LayoutUnit availableHeight; if (isOutOfFlowPositioned()) - availableHeight = containingBlockLogicalHeightForPositioned(downcast(cb)); + availableHeight = containingBlockLogicalHeightForPositioned(downcast(*cb)); else { availableHeight = containingBlockLogicalHeightForContent(IncludeMarginBorderPadding); // It is necessary to use the border-box to match WinIE's broken @@ -3109,7 +3140,7 @@ LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(SizeType heightType, Len // table cells using percentage heights. // FIXME: This needs to be made block-flow-aware. If the cell and image are perpendicular block-flows, this isn't right. // https://bugs.webkit.org/show_bug.cgi?id=46997 - while (cb && !cb->isRenderView() && (cb->style().logicalHeight().isAuto() || cb->style().logicalHeight().isPercentOrCalculated())) { + while (cb && !is(*cb) && (cb->style().logicalHeight().isAuto() || cb->style().logicalHeight().isPercentOrCalculated())) { if (cb->isTableCell()) { // Don't let table cells squeeze percent-height replaced elements // @@ -3150,7 +3181,7 @@ LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h, AvailableLogi if (h.isPercentOrCalculated() && isOutOfFlowPositioned() && !isRenderFlowThread()) { // FIXME: This is wrong if the containingBlock has a perpendicular writing mode. - LayoutUnit availableHeight = containingBlockLogicalHeightForPositioned(containingBlock()); + LayoutUnit availableHeight = containingBlockLogicalHeightForPositioned(*containingBlock()); return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(h, availableHeight)); } @@ -3176,7 +3207,7 @@ LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h, AvailableLogi return availableHeight; } -void RenderBox::computeBlockDirectionMargins(const RenderBlock* containingBlock, LayoutUnit& marginBefore, LayoutUnit& marginAfter) const +void RenderBox::computeBlockDirectionMargins(const RenderBlock& containingBlock, LayoutUnit& marginBefore, LayoutUnit& marginAfter) const { if (isTableCell()) { // FIXME: Not right if we allow cells to have different directionality than the table. If we do allow this, though, @@ -3189,23 +3220,23 @@ void RenderBox::computeBlockDirectionMargins(const RenderBlock* containingBlock, // Margins are calculated with respect to the logical width of // the containing block (8.3) LayoutUnit cw = containingBlockLogicalWidthForContent(); - const RenderStyle& containingBlockStyle = containingBlock->style(); + const RenderStyle& containingBlockStyle = containingBlock.style(); marginBefore = minimumValueForLength(style().marginBeforeUsing(&containingBlockStyle), cw); marginAfter = minimumValueForLength(style().marginAfterUsing(&containingBlockStyle), cw); } -void RenderBox::computeAndSetBlockDirectionMargins(const RenderBlock* containingBlock) +void RenderBox::computeAndSetBlockDirectionMargins(const RenderBlock& containingBlock) { LayoutUnit marginBefore; LayoutUnit marginAfter; computeBlockDirectionMargins(containingBlock, marginBefore, marginAfter); - containingBlock->setMarginBeforeForChild(*this, marginBefore); - containingBlock->setMarginAfterForChild(*this, marginAfter); + containingBlock.setMarginBeforeForChild(*this, marginBefore); + containingBlock.setMarginAfterForChild(*this, marginAfter); } -LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxModelObject* containingBlock, RenderRegion* region, bool checkForPerpendicularWritingMode) const +LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxModelObject& containingBlock, RenderRegion* region, bool checkForPerpendicularWritingMode) const { - if (checkForPerpendicularWritingMode && containingBlock->isHorizontalWritingMode() != isHorizontalWritingMode()) + if (checkForPerpendicularWritingMode && containingBlock.isHorizontalWritingMode() != isHorizontalWritingMode()) return containingBlockLogicalHeightForPositioned(containingBlock, false); #if ENABLE(CSS_GRID_LAYOUT) @@ -3215,44 +3246,44 @@ LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxMo } #endif - if (is(*containingBlock)) { + if (is(containingBlock)) { bool isFixedPosition = style().position() == FixedPosition; RenderFlowThread* flowThread = flowThreadContainingBlock(); if (!flowThread) { - if (isFixedPosition && is(*containingBlock)) - return downcast(*containingBlock).clientLogicalWidthForFixedPosition(); + if (isFixedPosition && is(containingBlock)) + return downcast(containingBlock).clientLogicalWidthForFixedPosition(); - return downcast(*containingBlock).clientLogicalWidth(); + return downcast(containingBlock).clientLogicalWidth(); } - if (isFixedPosition && is(*containingBlock)) - return containingBlock->view().clientLogicalWidth(); + if (isFixedPosition && is(containingBlock)) + return containingBlock.view().clientLogicalWidth(); - if (!is(*containingBlock)) - return downcast(*containingBlock).clientLogicalWidth(); + if (!is(containingBlock)) + return downcast(containingBlock).clientLogicalWidth(); - const RenderBlock& cb = downcast(*containingBlock); + const RenderBlock& cb = downcast(containingBlock); RenderBoxRegionInfo* boxInfo = nullptr; if (!region) { - if (is(*containingBlock) && !checkForPerpendicularWritingMode) - return downcast(*containingBlock).contentLogicalWidthOfFirstRegion(); + if (is(containingBlock) && !checkForPerpendicularWritingMode) + return downcast(containingBlock).contentLogicalWidthOfFirstRegion(); if (isWritingModeRoot()) { LayoutUnit cbPageOffset = cb.offsetFromLogicalTopOfFirstPage(); RenderRegion* cbRegion = cb.regionAtBlockOffset(cbPageOffset); if (cbRegion) boxInfo = cb.renderBoxRegionInfo(cbRegion); } - } else if (flowThread->isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode()) { + } else if (flowThread->isHorizontalWritingMode() == containingBlock.isHorizontalWritingMode()) { RenderRegion* containingBlockRegion = cb.clampToStartAndEndRegions(region); boxInfo = cb.renderBoxRegionInfo(containingBlockRegion); } return (boxInfo) ? std::max(0, cb.clientLogicalWidth() - (cb.logicalWidth() - boxInfo->logicalWidth())) : cb.clientLogicalWidth(); } - ASSERT(containingBlock->isInFlowPositioned()); + ASSERT(containingBlock.isInFlowPositioned()); - const auto& flow = downcast(*containingBlock); + const auto& flow = downcast(containingBlock); InlineFlowBox* first = flow.firstLineBox(); InlineFlowBox* last = flow.lastLineBox(); @@ -3262,7 +3293,7 @@ LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxMo LayoutUnit fromLeft; LayoutUnit fromRight; - if (containingBlock->style().isLeftToRightDirection()) { + if (containingBlock.style().isLeftToRightDirection()) { fromLeft = first->logicalLeft() + first->borderLogicalLeft(); fromRight = last->logicalLeft() + last->logicalWidth() - last->borderLogicalRight(); } else { @@ -3273,9 +3304,9 @@ LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxMo return std::max(0, fromRight - fromLeft); } -LayoutUnit RenderBox::containingBlockLogicalHeightForPositioned(const RenderBoxModelObject* containingBlock, bool checkForPerpendicularWritingMode) const +LayoutUnit RenderBox::containingBlockLogicalHeightForPositioned(const RenderBoxModelObject& containingBlock, bool checkForPerpendicularWritingMode) const { - if (checkForPerpendicularWritingMode && containingBlock->isHorizontalWritingMode() != isHorizontalWritingMode()) + if (checkForPerpendicularWritingMode && containingBlock.isHorizontalWritingMode() != isHorizontalWritingMode()) return containingBlockLogicalWidthForPositioned(containingBlock, nullptr, false); #if ENABLE(CSS_GRID_LAYOUT) @@ -3285,26 +3316,26 @@ LayoutUnit RenderBox::containingBlockLogicalHeightForPositioned(const RenderBoxM } #endif - if (containingBlock->isBox()) { + if (containingBlock.isBox()) { bool isFixedPosition = style().position() == FixedPosition; - if (isFixedPosition && is(*containingBlock)) - return downcast(*containingBlock).clientLogicalHeightForFixedPosition(); + if (isFixedPosition && is(containingBlock)) + return downcast(containingBlock).clientLogicalHeightForFixedPosition(); - const RenderBlock* cb = is(*containingBlock) ? downcast(containingBlock) : containingBlock->containingBlock(); - LayoutUnit result = cb->clientLogicalHeight(); + const RenderBlock& cb = is(containingBlock) ? downcast(containingBlock) : *containingBlock.containingBlock(); + LayoutUnit result = cb.clientLogicalHeight(); RenderFlowThread* flowThread = flowThreadContainingBlock(); - if (flowThread && is(*containingBlock) && flowThread->isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode()) { - if (is(*containingBlock) && isFixedPosition) - return containingBlock->view().clientLogicalHeight(); - return downcast(*containingBlock).contentLogicalHeightOfFirstRegion(); + if (flowThread && is(containingBlock) && flowThread->isHorizontalWritingMode() == containingBlock.isHorizontalWritingMode()) { + if (is(containingBlock) && isFixedPosition) + return containingBlock.view().clientLogicalHeight(); + return downcast(containingBlock).contentLogicalHeightOfFirstRegion(); } return result; } - ASSERT(containingBlock->isInFlowPositioned()); + ASSERT(containingBlock.isInFlowPositioned()); - const auto& flow = downcast(*containingBlock); + const auto& flow = downcast(containingBlock); InlineFlowBox* first = flow.firstLineBox(); InlineFlowBox* last = flow.lastLineBox(); @@ -3314,23 +3345,23 @@ LayoutUnit RenderBox::containingBlockLogicalHeightForPositioned(const RenderBoxM LayoutUnit heightResult; LayoutRect boundingBox = flow.linesBoundingBox(); - if (containingBlock->isHorizontalWritingMode()) + if (containingBlock.isHorizontalWritingMode()) heightResult = boundingBox.height(); else heightResult = boundingBox.width(); - heightResult -= (containingBlock->borderBefore() + containingBlock->borderAfter()); + heightResult -= (containingBlock.borderBefore() + containingBlock.borderAfter()); return heightResult; } -static void computeInlineStaticDistance(Length& logicalLeft, Length& logicalRight, const RenderBox* child, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalWidth, RenderRegion* region) +static void computeInlineStaticDistance(Length& logicalLeft, Length& logicalRight, const RenderBox* child, const RenderBoxModelObject& containerBlock, LayoutUnit containerLogicalWidth, RenderRegion* region) { if (!logicalLeft.isAuto() || !logicalRight.isAuto()) return; // FIXME: The static distance computation has not been patched for mixed writing modes yet. if (child->parent()->style().direction() == LTR) { - LayoutUnit staticPosition = child->layer()->staticInlinePosition() - containerBlock->borderLogicalLeft(); - for (auto* current = child->parent(); current && current != containerBlock; current = current->container()) { + LayoutUnit staticPosition = child->layer()->staticInlinePosition() - containerBlock.borderLogicalLeft(); + for (auto* current = child->parent(); current && current != &containerBlock; current = current->container()) { if (!is(*current)) continue; const auto& renderBox = downcast(*current); @@ -3348,10 +3379,10 @@ static void computeInlineStaticDistance(Length& logicalLeft, Length& logicalRigh logicalLeft.setValue(Fixed, staticPosition); } else { const RenderBox& enclosingBox = child->parent()->enclosingBox(); - LayoutUnit staticPosition = child->layer()->staticInlinePosition() + containerLogicalWidth + containerBlock->borderLogicalLeft(); + LayoutUnit staticPosition = child->layer()->staticInlinePosition() + containerLogicalWidth + containerBlock.borderLogicalLeft(); for (const RenderElement* current = &enclosingBox; current; current = current->container()) { if (is(*current)) { - if (current != containerBlock) { + if (current != &containerBlock) { const auto& renderBox = downcast(*current); staticPosition -= renderBox.logicalLeft(); if (renderBox.isInFlowPositioned()) @@ -3364,14 +3395,14 @@ static void computeInlineStaticDistance(Length& logicalLeft, Length& logicalRigh region = currentBlock.clampToStartAndEndRegions(region); RenderBoxRegionInfo* boxInfo = currentBlock.renderBoxRegionInfo(region); if (boxInfo) { - if (current != containerBlock) + if (current != &containerBlock) staticPosition -= currentBlock.logicalWidth() - (boxInfo->logicalLeft() + boxInfo->logicalWidth()); if (current == &enclosingBox) staticPosition += enclosingBox.logicalWidth() - boxInfo->logicalWidth(); } } } - if (current == containerBlock) + if (current == &containerBlock) break; } logicalRight.setValue(Fixed, staticPosition); @@ -3405,14 +3436,14 @@ void RenderBox::computePositionedLogicalWidth(LogicalExtentComputedValues& compu // We don't use containingBlock(), since we may be positioned by an enclosing // relative positioned inline. - const RenderBoxModelObject* containerBlock = downcast(container()); + const RenderBoxModelObject& containerBlock = downcast(*container()); const LayoutUnit containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, region); // Use the container block's direction except when calculating the static distance // This conforms with the reference results for abspos-replaced-width-margin-000.htm // of the CSS 2.1 test suite - TextDirection containerDirection = containerBlock->style().direction(); + TextDirection containerDirection = containerBlock.style().direction(); bool isHorizontal = isHorizontalWritingMode(); const LayoutUnit bordersPlusPadding = borderAndPaddingLogicalWidth(); @@ -3496,14 +3527,19 @@ void RenderBox::computePositionedLogicalWidth(LogicalExtentComputedValues& compu #endif computedValues.m_extent += bordersPlusPadding; + if (is(containerBlock)) { + auto& containingBox = downcast(containerBlock); + if (containingBox.layer() && containingBox.layer()->verticalScrollbarIsOnLeft()) + computedValues.m_position += containingBox.verticalScrollbarWidth(); + } // Adjust logicalLeft if we need to for the flipped version of our writing mode in regions. // FIXME: Add support for other types of objects as containerBlock, not only RenderBlock. RenderFlowThread* flowThread = flowThreadContainingBlock(); - if (flowThread && !region && isWritingModeRoot() && isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode() && is(*containerBlock)) { - ASSERT(containerBlock->canHaveBoxInfoInRegion()); + if (flowThread && !region && isWritingModeRoot() && isHorizontalWritingMode() == containerBlock.isHorizontalWritingMode() && is(containerBlock)) { + ASSERT(containerBlock.canHaveBoxInfoInRegion()); LayoutUnit logicalLeftPos = computedValues.m_position; - const RenderBlock& renderBlock = downcast(*containerBlock); + const RenderBlock& renderBlock = downcast(containerBlock); LayoutUnit cbPageOffset = renderBlock.offsetFromLogicalTopOfFirstPage(); RenderRegion* cbRegion = renderBlock.regionAtBlockOffset(cbPageOffset); if (cbRegion) { @@ -3516,18 +3552,18 @@ void RenderBox::computePositionedLogicalWidth(LogicalExtentComputedValues& compu } } -static void computeLogicalLeftPositionedOffset(LayoutUnit& logicalLeftPos, const RenderBox* child, LayoutUnit logicalWidthValue, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalWidth) +static void computeLogicalLeftPositionedOffset(LayoutUnit& logicalLeftPos, const RenderBox* child, LayoutUnit logicalWidthValue, const RenderBoxModelObject& containerBlock, LayoutUnit containerLogicalWidth) { // Deal with differing writing modes here. Our offset needs to be in the containing block's coordinate space. If the containing block is flipped // along this axis, then we need to flip the coordinate. This can only happen if the containing block is both a flipped mode and perpendicular to us. - if (containerBlock->isHorizontalWritingMode() != child->isHorizontalWritingMode() && containerBlock->style().isFlippedBlocksWritingMode()) { + if (containerBlock.isHorizontalWritingMode() != child->isHorizontalWritingMode() && containerBlock.style().isFlippedBlocksWritingMode()) { logicalLeftPos = containerLogicalWidth - logicalWidthValue - logicalLeftPos; - logicalLeftPos += (child->isHorizontalWritingMode() ? containerBlock->borderRight() : containerBlock->borderBottom()); + logicalLeftPos += (child->isHorizontalWritingMode() ? containerBlock.borderRight() : containerBlock.borderBottom()); } else - logicalLeftPos += (child->isHorizontalWritingMode() ? containerBlock->borderLeft() : containerBlock->borderTop()); + logicalLeftPos += (child->isHorizontalWritingMode() ? containerBlock.borderLeft() : containerBlock.borderTop()); } -void RenderBox::computePositionedLogicalWidthUsing(SizeType widthType, Length logicalWidth, const RenderBoxModelObject* containerBlock, TextDirection containerDirection, +void RenderBox::computePositionedLogicalWidthUsing(SizeType widthType, Length logicalWidth, const RenderBoxModelObject& containerBlock, TextDirection containerDirection, LayoutUnit containerLogicalWidth, LayoutUnit bordersPlusPadding, Length logicalLeft, Length logicalRight, Length marginLogicalLeft, Length marginLogicalRight, LogicalExtentComputedValues& computedValues) const @@ -3698,8 +3734,8 @@ void RenderBox::computePositionedLogicalWidthUsing(SizeType widthType, Length lo // positioned, inline because right now, it is using the logical left position // of the first line box when really it should use the last line box. When // this is fixed elsewhere, this block should be removed. - if (is(*containerBlock) && !containerBlock->style().isLeftToRightDirection()) { - const auto& flow = downcast(*containerBlock); + if (is(containerBlock) && !containerBlock.style().isLeftToRightDirection()) { + const auto& flow = downcast(containerBlock); InlineFlowBox* firstLine = flow.firstLineBox(); InlineFlowBox* lastLine = flow.lastLineBox(); if (firstLine && lastLine && firstLine != lastLine) { @@ -3712,14 +3748,14 @@ void RenderBox::computePositionedLogicalWidthUsing(SizeType widthType, Length lo computeLogicalLeftPositionedOffset(computedValues.m_position, this, computedValues.m_extent, containerBlock, containerLogicalWidth); } -static void computeBlockStaticDistance(Length& logicalTop, Length& logicalBottom, const RenderBox* child, const RenderBoxModelObject* containerBlock) +static void computeBlockStaticDistance(Length& logicalTop, Length& logicalBottom, const RenderBox* child, const RenderBoxModelObject& containerBlock) { if (!logicalTop.isAuto() || !logicalBottom.isAuto()) return; // FIXME: The static distance computation has not been patched for mixed writing modes. - LayoutUnit staticLogicalTop = child->layer()->staticBlockPosition() - containerBlock->borderBefore(); - for (RenderElement* container = child->parent(); container && container != containerBlock; container = container->container()) { + LayoutUnit staticLogicalTop = child->layer()->staticBlockPosition() - containerBlock.borderBefore(); + for (RenderElement* container = child->parent(); container && container != &containerBlock; container = container->container()) { if (!is(*container)) continue; const auto& renderBox = downcast(*container); @@ -3746,7 +3782,7 @@ void RenderBox::computePositionedLogicalHeight(LogicalExtentComputedValues& comp // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline. - const RenderBoxModelObject* containerBlock = downcast(container()); + const RenderBoxModelObject& containerBlock = downcast(*container()); const LayoutUnit containerLogicalHeight = containingBlockLogicalHeightForPositioned(containerBlock); @@ -3830,10 +3866,10 @@ void RenderBox::computePositionedLogicalHeight(LogicalExtentComputedValues& comp // Adjust logicalTop if we need to for perpendicular writing modes in regions. // FIXME: Add support for other types of objects as containerBlock, not only RenderBlock. RenderFlowThread* flowThread = flowThreadContainingBlock(); - if (flowThread && isHorizontalWritingMode() != containerBlock->isHorizontalWritingMode() && is(*containerBlock)) { - ASSERT(containerBlock->canHaveBoxInfoInRegion()); + if (flowThread && isHorizontalWritingMode() != containerBlock.isHorizontalWritingMode() && is(containerBlock)) { + ASSERT(containerBlock.canHaveBoxInfoInRegion()); LayoutUnit logicalTopPos = computedValues.m_position; - const RenderBlock& renderBox = downcast(*containerBlock); + const RenderBlock& renderBox = downcast(containerBlock); LayoutUnit cbPageOffset = renderBox.offsetFromLogicalTopOfFirstPage() - logicalLeft(); RenderRegion* cbRegion = renderBox.regionAtBlockOffset(cbPageOffset); if (cbRegion) { @@ -3846,29 +3882,29 @@ void RenderBox::computePositionedLogicalHeight(LogicalExtentComputedValues& comp } } -static void computeLogicalTopPositionedOffset(LayoutUnit& logicalTopPos, const RenderBox* child, LayoutUnit logicalHeightValue, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalHeight) +static void computeLogicalTopPositionedOffset(LayoutUnit& logicalTopPos, const RenderBox* child, LayoutUnit logicalHeightValue, const RenderBoxModelObject& containerBlock, LayoutUnit containerLogicalHeight) { // Deal with differing writing modes here. Our offset needs to be in the containing block's coordinate space. If the containing block is flipped // along this axis, then we need to flip the coordinate. This can only happen if the containing block is both a flipped mode and perpendicular to us. - if ((child->style().isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() != containerBlock->isHorizontalWritingMode()) - || (child->style().isFlippedBlocksWritingMode() != containerBlock->style().isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode())) + if ((child->style().isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() != containerBlock.isHorizontalWritingMode()) + || (child->style().isFlippedBlocksWritingMode() != containerBlock.style().isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() == containerBlock.isHorizontalWritingMode())) logicalTopPos = containerLogicalHeight - logicalHeightValue - logicalTopPos; // Our offset is from the logical bottom edge in a flipped environment, e.g., right for vertical-rl and bottom for horizontal-bt. - if (containerBlock->style().isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode()) { + if (containerBlock.style().isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() == containerBlock.isHorizontalWritingMode()) { if (child->isHorizontalWritingMode()) - logicalTopPos += containerBlock->borderBottom(); + logicalTopPos += containerBlock.borderBottom(); else - logicalTopPos += containerBlock->borderRight(); + logicalTopPos += containerBlock.borderRight(); } else { if (child->isHorizontalWritingMode()) - logicalTopPos += containerBlock->borderTop(); + logicalTopPos += containerBlock.borderTop(); else - logicalTopPos += containerBlock->borderLeft(); + logicalTopPos += containerBlock.borderLeft(); } } -void RenderBox::computePositionedLogicalHeightUsing(SizeType heightType, Length logicalHeightLength, const RenderBoxModelObject* containerBlock, +void RenderBox::computePositionedLogicalHeightUsing(SizeType heightType, Length logicalHeightLength, const RenderBoxModelObject& containerBlock, LayoutUnit containerLogicalHeight, LayoutUnit bordersPlusPadding, LayoutUnit logicalHeight, Length logicalTop, Length logicalBottom, Length marginBefore, Length marginAfter, LogicalExtentComputedValues& computedValues) const @@ -4012,14 +4048,14 @@ void RenderBox::computePositionedLogicalWidthReplaced(LogicalExtentComputedValue // We don't use containingBlock(), since we may be positioned by an enclosing // relative positioned inline. - const RenderBoxModelObject* containerBlock = downcast(container()); + const RenderBoxModelObject& containerBlock = downcast(*container()); const LayoutUnit containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock); const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, nullptr, false); // To match WinIE, in quirks mode use the parent's 'direction' property // instead of the the container block's. - TextDirection containerDirection = containerBlock->style().direction(); + TextDirection containerDirection = containerBlock.style().direction(); // Variables to solve. bool isHorizontal = isHorizontalWritingMode(); @@ -4156,8 +4192,8 @@ void RenderBox::computePositionedLogicalWidthReplaced(LogicalExtentComputedValue // positioned, inline containing block because right now, it is using the logical left position // of the first line box when really it should use the last line box. When // this is fixed elsewhere, this block should be removed. - if (is(*containerBlock) && !containerBlock->style().isLeftToRightDirection()) { - const auto& flow = downcast(*containerBlock); + if (is(containerBlock) && !containerBlock.style().isLeftToRightDirection()) { + const auto& flow = downcast(containerBlock); InlineFlowBox* firstLine = flow.firstLineBox(); InlineFlowBox* lastLine = flow.lastLineBox(); if (firstLine && lastLine && firstLine != lastLine) { @@ -4180,7 +4216,7 @@ void RenderBox::computePositionedLogicalHeightReplaced(LogicalExtentComputedValu // the numbers correspond to numbers in spec) // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline. - const RenderBoxModelObject* containerBlock = downcast(container()); + const RenderBoxModelObject& containerBlock = downcast(*container()); const LayoutUnit containerLogicalHeight = containingBlockLogicalHeightForPositioned(containerBlock); const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, nullptr, false); @@ -4469,11 +4505,10 @@ bool RenderBox::avoidsFloats() const void RenderBox::addVisualEffectOverflow() { - if (!style().boxShadow() && !style().hasBorderImageOutsets()) + if (!style().boxShadow() && !style().hasBorderImageOutsets() && !outlineStyleForRepaint().hasOutlineInVisualOverflow()) return; - LayoutRect borderBox = borderBoxRect(); - addVisualOverflow(applyVisualEffectOverflow(borderBox)); + addVisualOverflow(applyVisualEffectOverflow(borderBoxRect())); RenderFlowThread* flowThread = flowThreadContainingBlock(); if (flowThread) @@ -4517,6 +4552,13 @@ LayoutRect RenderBox::applyVisualEffectOverflow(const LayoutRect& borderBox) con overflowMaxY = std::max(overflowMaxY, borderBox.maxY() + ((!isFlipped || !isHorizontal) ? borderOutsets.bottom() : borderOutsets.top())); } + if (outlineStyleForRepaint().hasOutlineInVisualOverflow()) { + LayoutUnit outlineSize = outlineStyleForRepaint().outlineSize(); + overflowMinX = std::min(overflowMinX, borderBox.x() - outlineSize); + overflowMaxX = std::max(overflowMaxX, borderBox.maxX() + outlineSize); + overflowMinY = std::min(overflowMinY, borderBox.y() - outlineSize); + overflowMaxY = std::max(overflowMaxY, borderBox.maxY() + outlineSize); + } // Add in the final overflow with shadows and outsets combined. return LayoutRect(overflowMinX, overflowMinY, overflowMaxX - overflowMinX, overflowMaxY - overflowMinY); } @@ -4607,7 +4649,7 @@ void RenderBox::clearOverflow() static bool logicalWidthIsResolvable(const RenderBox& renderBox) { const RenderBox* box = &renderBox; - while (!box->isRenderView() && !box->isOutOfFlowPositioned() + while (box && !is(*box) && !box->isOutOfFlowPositioned() #if ENABLE(CSS_GRID_LAYOUT) && !box->hasOverrideContainingBlockLogicalWidth() #endif @@ -4637,22 +4679,22 @@ bool RenderBox::hasDefiniteLogicalWidth() const return logicalWidthIsResolvable(*this); } -inline static bool percentageLogicalHeightIsResolvable(const RenderBox* box) +inline static bool percentageLogicalHeightIsResolvable(const RenderBox& box) { - return RenderBox::percentageLogicalHeightIsResolvableFromBlock(box->containingBlock(), box->isOutOfFlowPositioned(), box->scrollsOverflowY()); + return RenderBox::percentageLogicalHeightIsResolvableFromBlock(*box.containingBlock(), box.isOutOfFlowPositioned(), box.scrollsOverflowY()); } -bool RenderBox::percentageLogicalHeightIsResolvableFromBlock(const RenderBlock* containingBlock, bool isOutOfFlowPositioned, bool scrollsOverflowY) +bool RenderBox::percentageLogicalHeightIsResolvableFromBlock(const RenderBlock& containingBlock, bool isOutOfFlowPositioned, bool scrollsOverflowY) { // In quirks mode, blocks with auto height are skipped, and we keep looking for an enclosing // block that may have a specified height and then use it. In strict mode, this violates the // specification, which states that percentage heights just revert to auto if the containing // block has an auto height. We still skip anonymous containing blocks in both modes, though, and look // only at explicit containers. - const RenderBlock* cb = containingBlock; + const RenderBlock* cb = &containingBlock; bool inQuirksMode = cb->document().inQuirksMode(); bool skippedAutoHeightContainingBlock = false; - while (!cb->isRenderView() && !cb->isBody() && !cb->isTableCell() && !cb->isOutOfFlowPositioned() && cb->style().logicalHeight().isAuto()) { + while (cb && !is(*cb) && !cb->isBody() && !cb->isTableCell() && !cb->isOutOfFlowPositioned() && cb->style().logicalHeight().isAuto()) { if (!inQuirksMode && !cb->isAnonymousBlock()) break; #if ENABLE(CSS_GRID_LAYOUT) @@ -4682,7 +4724,7 @@ bool RenderBox::percentageLogicalHeightIsResolvableFromBlock(const RenderBlock* if (cb->style().logicalHeight().isFixed()) return true; if (cb->style().logicalHeight().isPercentOrCalculated() && !isOutOfFlowPositionedWithSpecifiedHeight) - return percentageLogicalHeightIsResolvableFromBlock(cb->containingBlock(), cb->isOutOfFlowPositioned(), cb->scrollsOverflowY()); + return percentageLogicalHeightIsResolvableFromBlock(*cb->containingBlock(), cb->isOutOfFlowPositioned(), cb->scrollsOverflowY()); if (cb->isRenderView() || inQuirksMode || isOutOfFlowPositionedWithSpecifiedHeight) return true; if (cb->isDocumentElementRenderer() && isOutOfFlowPositioned) { @@ -4710,7 +4752,7 @@ bool RenderBox::hasDefiniteLogicalHeight() const if (logicalHeight.isIntrinsicOrAuto()) return false; - return percentageLogicalHeightIsResolvable(this); + return percentageLogicalHeightIsResolvable(*this); } bool RenderBox::hasUnsplittableScrollingOverflow() const @@ -4726,8 +4768,8 @@ bool RenderBox::hasUnsplittableScrollingOverflow() const // conditions, but it should work out to be good enough for common cases. Paginating overflow // with scrollbars present is not the end of the world and is what we used to do in the old model anyway. return !style().logicalHeight().isIntrinsicOrAuto() - || (!style().logicalMaxHeight().isIntrinsicOrAuto() && !style().logicalMaxHeight().isUndefined() && (!style().logicalMaxHeight().isPercentOrCalculated() || percentageLogicalHeightIsResolvable(this))) - || (!style().logicalMinHeight().isIntrinsicOrAuto() && style().logicalMinHeight().isPositive() && (!style().logicalMinHeight().isPercentOrCalculated() || percentageLogicalHeightIsResolvable(this))); + || (!style().logicalMaxHeight().isIntrinsicOrAuto() && !style().logicalMaxHeight().isUndefined() && (!style().logicalMaxHeight().isPercentOrCalculated() || percentageLogicalHeightIsResolvable(*this))) + || (!style().logicalMinHeight().isIntrinsicOrAuto() && style().logicalMinHeight().isPositive() && (!style().logicalMinHeight().isPercentOrCalculated() || percentageLogicalHeightIsResolvable(*this))); } bool RenderBox::isUnsplittableForPagination() const @@ -4860,6 +4902,8 @@ LayoutRect RenderBox::flippedClientBoxRect() const flipForWritingMode(rect); // Subtract space occupied by scrollbars. They are at their physical edge in this coordinate // system, so order is important here: first flip, then subtract scrollbars. + if (style().shouldPlaceBlockDirectionScrollbarOnLeft() && style().isLeftToRightDirection()) + rect.move(verticalScrollbarWidth(), 0); rect.contract(verticalScrollbarWidth(), horizontalScrollbarHeight()); return rect; }