diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-09-10 19:10:20 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-09-10 19:10:20 +0200 |
commit | 284837daa07b29d6a63a748544a90b1f5842ac5c (patch) | |
tree | ecd258180bde91fe741e0cfd2638beb3c6da7e8e /Source/WebCore/rendering/RenderBox.cpp | |
parent | 2e2ba8ff45915f40ed3e014101269c175f2a89a0 (diff) | |
download | qtwebkit-284837daa07b29d6a63a748544a90b1f5842ac5c.tar.gz |
Imported WebKit commit 68645295d2e3e09af2c942f092556f06aa5f8b0d (http://svn.webkit.org/repository/webkit/trunk@128073)
New snapshot
Diffstat (limited to 'Source/WebCore/rendering/RenderBox.cpp')
-rw-r--r-- | Source/WebCore/rendering/RenderBox.cpp | 494 |
1 files changed, 253 insertions, 241 deletions
diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp index f16457b5e..792b9c28b 100644 --- a/Source/WebCore/rendering/RenderBox.cpp +++ b/Source/WebCore/rendering/RenderBox.cpp @@ -134,16 +134,7 @@ void RenderBox::willBeDestroyed() { clearOverrideSize(); - if (style()) { - RenderBlock::removePercentHeightDescendantIfNeeded(this); - - if (RenderView* view = this->view()) { - if (FrameView* frameView = view->frameView()) { - if (style()->position() == FixedPosition) - frameView->removeFixedObject(this); - } - } - } + RenderBlock::removePercentHeightDescendantIfNeeded(this); RenderBoxModelObject::willBeDestroyed(); } @@ -205,17 +196,6 @@ void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyl } else if (newStyle && isBody()) view()->repaint(); - if (FrameView *frameView = view()->frameView()) { - bool newStyleIsFixed = newStyle && newStyle->position() == FixedPosition; - bool oldStyleIsFixed = oldStyle && oldStyle->position() == FixedPosition; - if (newStyleIsFixed != oldStyleIsFixed) { - if (newStyleIsFixed) - frameView->addFixedObject(this); - else - frameView->removeFixedObject(this); - } - } - RenderBoxModelObject::styleWillChange(diff, newStyle); } @@ -433,7 +413,7 @@ void RenderBox::updateLayerTransform() layer()->updateTransform(); } -LayoutUnit RenderBox::constrainLogicalWidthInRegionByMinMax(LayoutUnit logicalWidth, LayoutUnit availableWidth, RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) +LayoutUnit RenderBox::constrainLogicalWidthInRegionByMinMax(LayoutUnit logicalWidth, LayoutUnit availableWidth, RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const { RenderStyle* styleToUse = style(); if (!styleToUse->logicalMaxWidth().isUndefined()) @@ -441,7 +421,7 @@ LayoutUnit RenderBox::constrainLogicalWidthInRegionByMinMax(LayoutUnit logicalWi return max(logicalWidth, computeLogicalWidthInRegionUsing(MinSize, availableWidth, cb, region, offsetFromLogicalTopOfFirstPage)); } -LayoutUnit RenderBox::constrainLogicalHeightByMinMax(LayoutUnit logicalHeight) +LayoutUnit RenderBox::constrainLogicalHeightByMinMax(LayoutUnit logicalHeight) const { RenderStyle* styleToUse = style(); if (!styleToUse->logicalMaxHeight().isUndefined()) { @@ -758,25 +738,25 @@ LayoutUnit RenderBox::computeContentBoxLogicalHeight(LayoutUnit height) const } // Hit Testing -bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action) +bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action) { LayoutPoint adjustedLocation = accumulatedOffset + location(); // Check kids first. for (RenderObject* child = lastChild(); child; child = child->previousSibling()) { - if (!child->hasLayer() && child->nodeAtPoint(request, result, pointInContainer, adjustedLocation, action)) { - updateHitTestResult(result, pointInContainer.point() - toLayoutSize(adjustedLocation)); + if (!child->hasLayer() && child->nodeAtPoint(request, result, locationInContainer, adjustedLocation, action)) { + updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation)); return true; } } // Check our bounds next. For this purpose always assume that we can only be hit in the // foreground phase (which is true for replaced elements like images). - LayoutRect boundsRect = borderBoxRectInRegion(pointInContainer.region()); + LayoutRect boundsRect = borderBoxRectInRegion(locationInContainer.region()); boundsRect.moveBy(adjustedLocation); - if (visibleToHitTesting() && action == HitTestForeground && pointInContainer.intersects(boundsRect)) { - updateHitTestResult(result, pointInContainer.point() - toLayoutSize(adjustedLocation)); - if (!result.addNodeToRectBasedTestResult(node(), pointInContainer, boundsRect)) + if (visibleToHitTesting() && action == HitTestForeground && locationInContainer.intersects(boundsRect)) { + updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation)); + if (!result.addNodeToRectBasedTestResult(node(), request, locationInContainer, boundsRect)) return true; } @@ -1171,7 +1151,7 @@ LayoutRect RenderBox::clipRect(const LayoutPoint& location, RenderRegion* region return clipRect; } -LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) +LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const { RenderRegion* containingBlockRegion = 0; LayoutUnit logicalTopPosition = logicalTop(); @@ -1374,9 +1354,6 @@ const RenderObject* RenderBox::pushMappingToContainer(const RenderBoxModelObject void RenderBox::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState& transformState) const { - // We don't expect absoluteToLocal() to be called during layout (yet) - ASSERT(!view() || !view()->layoutStateEnabled()); - bool isFixedPos = style()->position() == FixedPosition; bool hasTransform = hasLayer() && layer()->transform(); if (hasTransform) { @@ -1577,7 +1554,7 @@ void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, La if (position == AbsolutePosition && o->isInFlowPositioned() && o->isRenderInline()) topLeft += toRenderInline(o)->offsetForInFlowPositionedInline(this); - else if ((position == RelativePosition) && layer()) { + else if ((position == RelativePosition || position == StickyPosition) && layer()) { // Apply the relative position offset when invalidating a rectangle. The layer // is translated, but the render box isn't, so we need to do this to get the // right dirty rect. Since this is called from RenderObject::setStyle, the relative position @@ -1640,15 +1617,26 @@ void RenderBox::repaintDuringLayoutIfMoved(const LayoutRect& oldRect) void RenderBox::computeLogicalWidth() { - computeLogicalWidthInRegion(); + LogicalExtentComputedValues computedValues; + computeLogicalWidthInRegion(computedValues); + + setLogicalWidth(computedValues.m_extent); + setLogicalLeft(computedValues.m_position); + setMarginStart(computedValues.m_margins.m_start); + setMarginEnd(computedValues.m_margins.m_end); } -void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) +void RenderBox::computeLogicalWidthInRegion(LogicalExtentComputedValues& computedValues, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const { + computedValues.m_extent = logicalWidth(); + computedValues.m_position = logicalLeft(); + computedValues.m_margins.m_start = marginStart(); + computedValues.m_margins.m_end = marginEnd(); + if (isOutOfFlowPositioned()) { // FIXME: This calculation is not patched for block-flow yet. // https://bugs.webkit.org/show_bug.cgi?id=46500 - computePositionedLogicalWidth(region, offsetFromLogicalTopOfFirstPage); + computePositionedLogicalWidth(computedValues, region, offsetFromLogicalTopOfFirstPage); return; } @@ -1661,7 +1649,7 @@ void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit off // FIXME: Account for block-flow in flexible boxes. // https://bugs.webkit.org/show_bug.cgi?id=46418 if (hasOverrideWidth() && parent()->isFlexibleBoxIncludingDeprecated()) { - setLogicalWidth(overrideLogicalContentWidth() + borderAndPaddingLogicalWidth()); + computedValues.m_extent = overrideLogicalContentWidth() + borderAndPaddingLogicalWidth(); return; } @@ -1672,7 +1660,7 @@ void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit off bool treatAsReplaced = shouldComputeSizeAsReplaced() && (!inVerticalBox || !stretching); RenderStyle* styleToUse = style(); - Length logicalWidthLength = (treatAsReplaced) ? Length(computeReplacedLogicalWidth(), Fixed) : styleToUse->logicalWidth(); + Length logicalWidthLength = treatAsReplaced ? Length(computeReplacedLogicalWidth(), Fixed) : styleToUse->logicalWidth(); RenderBlock* cb = containingBlock(); LayoutUnit containerLogicalWidth = max<LayoutUnit>(0, containingBlockLogicalWidthForContentInRegion(region, offsetFromLogicalTopOfFirstPage)); @@ -1684,44 +1672,53 @@ void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit off if (isInline() && !isInlineBlockOrInlineTable()) { // just calculate margins RenderView* renderView = view(); - setMarginStart(minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView)); - setMarginEnd(minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView)); + computedValues.m_margins.m_start = minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView); + computedValues.m_margins.m_end = minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView); if (treatAsReplaced) - setLogicalWidth(max<LayoutUnit>(floatValueForLength(logicalWidthLength, 0) + borderAndPaddingLogicalWidth(), minPreferredLogicalWidth())); + computedValues.m_extent = max<LayoutUnit>(floatValueForLength(logicalWidthLength, 0) + borderAndPaddingLogicalWidth(), minPreferredLogicalWidth()); return; } // Width calculations if (treatAsReplaced) - setLogicalWidth(logicalWidthLength.value() + borderAndPaddingLogicalWidth()); + computedValues.m_extent = logicalWidthLength.value() + borderAndPaddingLogicalWidth(); else { LayoutUnit preferredWidth = computeLogicalWidthInRegionUsing(MainOrPreferredSize, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage); - setLogicalWidth(constrainLogicalWidthInRegionByMinMax(preferredWidth, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage)); + computedValues.m_extent = constrainLogicalWidthInRegionByMinMax(preferredWidth, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage); } // Fieldsets are currently the only objects that stretch to their minimum width. if (stretchesToMinIntrinsicLogicalWidth()) - setLogicalWidth(max(logicalWidth(), minPreferredLogicalWidth())); + computedValues.m_extent = max(computedValues.m_extent, minPreferredLogicalWidth()); // Margin calculations. if (hasPerpendicularContainingBlock || isFloating() || isInline()) { RenderView* renderView = view(); - setMarginStart(minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView)); - setMarginEnd(minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView)); + computedValues.m_margins.m_start = minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView); + computedValues.m_margins.m_end = minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView); } else { LayoutUnit containerLogicalWidthForAutoMargins = containerLogicalWidth; if (avoidsFloats() && cb->containsFloats()) containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(region, offsetFromLogicalTopOfFirstPage); - computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, logicalWidth()); + 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 != (logicalWidth() + marginStart() + marginEnd()) - && !isFloating() && !isInline() && !cb->isFlexibleBoxIncludingDeprecated()) - cb->setMarginEndForChild(this, containerLogicalWidth - logicalWidth() - cb->marginStartForChild(this)); + if (!hasPerpendicularContainingBlock && containerLogicalWidth && containerLogicalWidth != (computedValues.m_extent + computedValues.m_margins.m_start + computedValues.m_margins.m_end) + && !isFloating() && !isInline() && !cb->isFlexibleBoxIncludingDeprecated()) { + 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 + computedValues.m_margins.m_end = newMargin; + } } LayoutUnit RenderBox::computeLogicalWidthInRegionUsing(SizeType widthType, LayoutUnit availableLogicalWidth, - const RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) + const RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const { RenderStyle* styleToUse = style(); Length logicalWidth; @@ -1820,7 +1817,7 @@ bool RenderBox::sizesLogicalWidthToFitContent(SizeType widthType) const return false; } -void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth) +void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const { const RenderStyle* containingBlockStyle = containingBlock->style(); Length marginStartLength = style()->marginStartUsing(containingBlockStyle); @@ -1829,8 +1826,8 @@ void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, Layo if (isFloating() || isInline()) { // Inline blocks/tables and floats don't have their margins increased. - containingBlock->setMarginStartForChild(this, minimumValueForLength(marginStartLength, containerWidth, renderView)); - containingBlock->setMarginEndForChild(this, minimumValueForLength(marginEndLength, containerWidth, renderView)); + marginStart = minimumValueForLength(marginStartLength, containerWidth, renderView); + marginEnd = minimumValueForLength(marginEndLength, containerWidth, renderView); return; } @@ -1841,15 +1838,15 @@ void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, Layo LayoutUnit marginStartWidth = minimumValueForLength(marginStartLength, containerWidth, renderView); LayoutUnit marginEndWidth = minimumValueForLength(marginEndLength, containerWidth, renderView); LayoutUnit centeredMarginBoxStart = max<LayoutUnit>(0, (containerWidth - childWidth - marginStartWidth - marginEndWidth) / 2); - containingBlock->setMarginStartForChild(this, centeredMarginBoxStart + marginStartWidth); - containingBlock->setMarginEndForChild(this, containerWidth - childWidth - containingBlock->marginStartForChild(this) + marginEndWidth); + marginStart = centeredMarginBoxStart + marginStartWidth; + marginEnd = containerWidth - childWidth - marginStart + marginEndWidth; return; } // Case Two: The object is being pushed to the start of the containing block's available logical width. if (marginEndLength.isAuto() && childWidth < containerWidth) { - containingBlock->setMarginStartForChild(this, valueForLength(marginStartLength, containerWidth, renderView)); - containingBlock->setMarginEndForChild(this, containerWidth - childWidth - containingBlock->marginStartForChild(this)); + marginStart = valueForLength(marginStartLength, containerWidth, renderView); + marginEnd = containerWidth - childWidth - marginStart; return; } @@ -1857,15 +1854,15 @@ void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, Layo bool pushToEndFromTextAlign = !marginEndLength.isAuto() && ((!containingBlockStyle->isLeftToRightDirection() && containingBlockStyle->textAlign() == WEBKIT_LEFT) || (containingBlockStyle->isLeftToRightDirection() && containingBlockStyle->textAlign() == WEBKIT_RIGHT)); if ((marginStartLength.isAuto() && childWidth < containerWidth) || pushToEndFromTextAlign) { - containingBlock->setMarginEndForChild(this, valueForLength(marginEndLength, containerWidth, renderView)); - containingBlock->setMarginStartForChild(this, containerWidth - childWidth - containingBlock->marginEndForChild(this)); + marginEnd = valueForLength(marginEndLength, containerWidth, renderView); + marginStart = containerWidth - childWidth - marginEnd; return; } // Case Four: Either no auto margins, or our width is >= the container width (css2.1, 10.3.3). In that case // auto margins will just turn into 0. - containingBlock->setMarginStartForChild(this, minimumValueForLength(marginStartLength, containerWidth, renderView)); - containingBlock->setMarginEndForChild(this, minimumValueForLength(marginEndLength, containerWidth, renderView)); + marginStart = minimumValueForLength(marginStartLength, containerWidth, renderView); + marginEnd = minimumValueForLength(marginEndLength, containerWidth, renderView); } RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, RenderBoxRegionInfoFlags cacheFlag) const @@ -1887,21 +1884,12 @@ RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, Layout || isTableCell() || !isBlockFlow() || isRenderFlowThread()) return 0; - // FIXME: It's gross to cast away the const, but it would be a huge refactoring to - // change all width computation to avoid updating any member variables, and it would be pretty lame to - // make all the variables mutable as well. RenderFlowThread* flowThread = enclosingRenderFlowThread(); if (flowThread->style()->writingMode() != style()->writingMode()) return 0; - LayoutUnit oldLogicalWidth = logicalWidth(); - LayoutUnit oldLogicalLeft = logicalLeft(); - LayoutUnit oldMarginStart = marginStart(); - LayoutUnit oldMarginEnd = marginEnd(); - - RenderBox* mutableBox = const_cast<RenderBox*>(this); - - mutableBox->computeLogicalWidthInRegion(region, offsetFromLogicalTopOfFirstPage); + LogicalExtentComputedValues computedValues; + computeLogicalWidthInRegion(computedValues, region, offsetFromLogicalTopOfFirstPage); // Now determine the insets based off where this object is supposed to be positioned. RenderBlock* cb = containingBlock(); @@ -1911,22 +1899,16 @@ RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, Layout LayoutUnit containingBlockLogicalWidth = cb->logicalWidth(); LayoutUnit containingBlockLogicalWidthInRegion = containingBlockInfo ? containingBlockInfo->logicalWidth() : containingBlockLogicalWidth; - LayoutUnit marginStartInRegion = marginStart(); - LayoutUnit startMarginDelta = marginStartInRegion - oldMarginStart; - LayoutUnit logicalWidthInRegion = logicalWidth(); - LayoutUnit logicalLeftInRegion = logicalLeft(); - LayoutUnit widthDelta = logicalWidthInRegion - oldLogicalWidth; - LayoutUnit logicalLeftDelta = isOutOfFlowPositioned() ? logicalLeftInRegion - oldLogicalLeft : startMarginDelta; + LayoutUnit marginStartInRegion = computedValues.m_margins.m_start; + LayoutUnit startMarginDelta = marginStartInRegion - marginStart(); + LayoutUnit logicalWidthInRegion = computedValues.m_extent; + LayoutUnit logicalLeftInRegion = computedValues.m_position; + LayoutUnit widthDelta = logicalWidthInRegion - logicalWidth(); + LayoutUnit logicalLeftDelta = isOutOfFlowPositioned() ? logicalLeftInRegion - logicalLeft() : startMarginDelta; LayoutUnit logicalRightInRegion = containingBlockLogicalWidthInRegion - (logicalLeftInRegion + logicalWidthInRegion); - LayoutUnit oldLogicalRight = containingBlockLogicalWidth - (oldLogicalLeft + oldLogicalWidth); + LayoutUnit oldLogicalRight = containingBlockLogicalWidth - (logicalLeft() + logicalWidth()); LayoutUnit logicalRightDelta = isOutOfFlowPositioned() ? logicalRightInRegion - oldLogicalRight : startMarginDelta; - // Set our values back. - mutableBox->setLogicalWidth(oldLogicalWidth); - mutableBox->setLogicalLeft(oldLogicalLeft); - mutableBox->setMarginStart(oldMarginStart); - mutableBox->setMarginEnd(oldMarginEnd); - LayoutUnit logicalLeftOffset = 0; if (!isOutOfFlowPositioned() && avoidsFloats() && cb->containsFloats()) { @@ -1953,26 +1935,74 @@ RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, Layout return new RenderBoxRegionInfo(logicalLeftOffset, logicalWidthInRegion, isShifted); } +static bool shouldFlipBeforeAfterMargins(const RenderStyle* containingBlockStyle, const RenderStyle* childStyle) +{ + ASSERT(containingBlockStyle->isHorizontalWritingMode() != childStyle->isHorizontalWritingMode()); + WritingMode childWritingMode = childStyle->writingMode(); + bool shouldFlip = false; + switch (containingBlockStyle->writingMode()) { + case TopToBottomWritingMode: + shouldFlip = (childWritingMode == RightToLeftWritingMode); + break; + case BottomToTopWritingMode: + shouldFlip = (childWritingMode == RightToLeftWritingMode); + break; + case RightToLeftWritingMode: + shouldFlip = (childWritingMode == BottomToTopWritingMode); + break; + case LeftToRightWritingMode: + shouldFlip = (childWritingMode == BottomToTopWritingMode); + break; + } + + if (!containingBlockStyle->isLeftToRightDirection()) + shouldFlip = !shouldFlip; + + return shouldFlip; +} + void RenderBox::computeLogicalHeight() { + LogicalExtentComputedValues computedValues; + computeLogicalHeight(computedValues); + + setLogicalHeight(computedValues.m_extent); + setLogicalTop(computedValues.m_position); + setMarginBefore(computedValues.m_margins.m_before); + setMarginAfter(computedValues.m_margins.m_after); +} + +void RenderBox::computeLogicalHeight(LogicalExtentComputedValues& computedValues) const +{ + computedValues.m_extent = logicalHeight(); + computedValues.m_position = logicalTop(); + // Cell height is managed by the table and inline non-replaced elements do not support a height property. if (isTableCell() || (isInline() && !isReplaced())) return; Length h; if (isOutOfFlowPositioned()) - computePositionedLogicalHeight(); + computePositionedLogicalHeight(computedValues); else { RenderBlock* cb = containingBlock(); bool hasPerpendicularContainingBlock = cb->isHorizontalWritingMode() != isHorizontalWritingMode(); - if (!hasPerpendicularContainingBlock) - computeBlockDirectionMargins(cb); + if (!hasPerpendicularContainingBlock) { + 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); + } // For tables, calculate margins only. if (isTable()) { - if (hasPerpendicularContainingBlock) - computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), logicalHeight()); + if (hasPerpendicularContainingBlock) { + bool shouldFlipBeforeAfter = shouldFlipBeforeAfterMargins(cb->style(), style()); + computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), logicalHeight(), + shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before, + shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after); + } return; } @@ -2018,10 +2048,14 @@ void RenderBox::computeLogicalHeight() heightResult = h.value() + borderAndPaddingLogicalHeight(); } - setLogicalHeight(heightResult); + computedValues.m_extent = heightResult; - if (hasPerpendicularContainingBlock) - computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), heightResult); + if (hasPerpendicularContainingBlock) { + 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); + } } // WinIE quirk: The <html> block always fills the entire canvas in quirks mode. The <body> always fills the @@ -2045,15 +2079,15 @@ void RenderBox::computeLogicalHeight() visHeight = view()->viewWidth(); } if (isRoot()) - setLogicalHeight(max(logicalHeight(), visHeight - margins)); + computedValues.m_extent = max(computedValues.m_extent, visHeight - margins); else { LayoutUnit marginsBordersPadding = margins + parentBox()->marginBefore() + parentBox()->marginAfter() + parentBox()->borderAndPaddingLogicalHeight(); - setLogicalHeight(max(logicalHeight(), visHeight - marginsBordersPadding)); + computedValues.m_extent = max(computedValues.m_extent, visHeight - marginsBordersPadding); } } } -LayoutUnit RenderBox::computeLogicalHeightUsing(SizeType heightType, const Length& height) +LayoutUnit RenderBox::computeLogicalHeightUsing(SizeType heightType, const Length& height) const { LayoutUnit logicalHeight = computeContentLogicalHeightUsing(heightType, height); if (logicalHeight != -1) @@ -2066,10 +2100,10 @@ LayoutUnit RenderBox::computeLogicalClientHeight(SizeType heightType, const Leng LayoutUnit heightIncludingScrollbar = computeContentLogicalHeightUsing(heightType, height); if (heightIncludingScrollbar == -1) return -1; - return std::max(LayoutUnit(0), computeContentBoxLogicalHeight(heightIncludingScrollbar) - scrollbarLogicalHeight()); + return std::max<LayoutUnit>(0, computeContentBoxLogicalHeight(heightIncludingScrollbar) - scrollbarLogicalHeight()); } -LayoutUnit RenderBox::computeContentLogicalHeightUsing(SizeType heightType, const Length& height) +LayoutUnit RenderBox::computeContentLogicalHeightUsing(SizeType heightType, const Length& height) const { if (height.isAuto()) return heightType == MinSize ? 0 : -1; @@ -2082,7 +2116,7 @@ LayoutUnit RenderBox::computeContentLogicalHeightUsing(SizeType heightType, cons return -1; } -LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height) +LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height) const { LayoutUnit result = -1; @@ -2098,7 +2132,7 @@ LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height) break; skippedAutoHeightContainingBlock = true; cb = cb->containingBlock(); - cb->addPercentHeightDescendant(this); + cb->addPercentHeightDescendant(const_cast<RenderBox*>(this)); } RenderStyle* cbstyle = cb->style(); @@ -2138,9 +2172,11 @@ LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height) result = max<LayoutUnit>(0, contentBoxHeightWithScrollbar - cb->scrollbarLogicalHeight()); } else if (cbstyle->logicalHeight().isPercent() && !isOutOfFlowPositionedWithSpecifiedHeight) { // We need to recur and compute the percentage height for our containing block. - result = cb->computePercentageLogicalHeight(cbstyle->logicalHeight()); - if (result != -1) - result = cb->computeContentBoxLogicalHeight(result); + LayoutUnit heightWithScrollbar = cb->computePercentageLogicalHeight(cbstyle->logicalHeight()); + if (heightWithScrollbar != -1) { + LayoutUnit contentBoxHeightWithScrollbar = cb->computeContentBoxLogicalHeight(heightWithScrollbar); + result = max<LayoutUnit>(0, contentBoxHeightWithScrollbar - cb->scrollbarLogicalHeight()); + } } else if (cb->isRenderView() || (cb->isBody() && document()->inQuirksMode()) || isOutOfFlowPositionedWithSpecifiedHeight) { // Don't allow this to affect the block' height() member variable, since this // can get called while the block is still laying out its kids. @@ -2270,10 +2306,7 @@ LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(SizeType sizeType, Lengt cb = cb->containingBlock(); } } - availableHeight = computeContentBoxLogicalHeight(valueForLength(logicalHeight, availableHeight)); - if (cb->isBox() && cb->style()->logicalHeight().isFixed()) - availableHeight = max<LayoutUnit>(0, availableHeight - toRenderBox(cb)->scrollbarLogicalHeight()); - return availableHeight; + return computeContentBoxLogicalHeight(valueForLength(logicalHeight, availableHeight)); } case ViewportPercentageWidth: case ViewportPercentageHeight: @@ -2291,9 +2324,6 @@ LayoutUnit RenderBox::availableLogicalHeight() const LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h) const { - if (h.isFixed()) - return computeContentBoxLogicalHeight(h.value()); - if (isRenderView()) return isHorizontalWritingMode() ? toRenderView(this)->frameView()->visibleHeight() : toRenderView(this)->frameView()->visibleWidth(); @@ -2303,19 +2333,16 @@ LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h) const if (isTableCell() && (h.isAuto() || h.isPercent())) return overrideLogicalContentHeight(); - if (h.isPercent()) { - LayoutUnit availableHeight; - // https://bugs.webkit.org/show_bug.cgi?id=64046 - // For absolutely positioned elements whose containing block is based on a block-level element, - // the percentage is calculated with respect to the height of the padding box of that element - if (isOutOfFlowPositioned()) - availableHeight = containingBlockLogicalHeightForPositioned(containingBlock()); - else - availableHeight = containingBlock()->availableLogicalHeight(); + if (h.isPercent() && isOutOfFlowPositioned()) { + LayoutUnit availableHeight = containingBlockLogicalHeightForPositioned(containingBlock()); return computeContentBoxLogicalHeight(valueForLength(h, availableHeight)); } - // FIXME: We can't just check top/bottom here. + LayoutUnit heightIncludingScrollbar = computeContentLogicalHeightUsing(MainOrPreferredSize, h); + if (heightIncludingScrollbar != -1) + return std::max<LayoutUnit>(0, computeContentBoxLogicalHeight(heightIncludingScrollbar) - scrollbarLogicalHeight()); + + // FIXME: Check logicalTop/logicalBottom here to correctly handle vertical writing-mode. // https://bugs.webkit.org/show_bug.cgi?id=46500 if (isRenderBlock() && isOutOfFlowPositioned() && style()->height().isAuto() && !(style()->top().isAuto() || style()->bottom().isAuto())) { RenderBlock* block = const_cast<RenderBlock*>(toRenderBlock(this)); @@ -2329,13 +2356,13 @@ LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h) const return containingBlock()->availableLogicalHeight(); } -void RenderBox::computeBlockDirectionMargins(const RenderBlock* containingBlock) +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, // we may just do it with an extra anonymous block inside the cell. - setMarginBefore(0); - setMarginAfter(0); + marginBefore = 0; + marginAfter = 0; return; } @@ -2344,8 +2371,17 @@ void RenderBox::computeBlockDirectionMargins(const RenderBlock* containingBlock) LayoutUnit cw = containingBlockLogicalWidthForContent(); RenderView* renderView = view(); RenderStyle* containingBlockStyle = containingBlock->style(); - containingBlock->setMarginBeforeForChild(this, minimumValueForLength(style()->marginBeforeUsing(containingBlockStyle), cw, renderView)); - containingBlock->setMarginAfterForChild(this, minimumValueForLength(style()->marginAfterUsing(containingBlockStyle), cw, renderView)); + marginBefore = minimumValueForLength(style()->marginBeforeUsing(containingBlockStyle), cw, renderView); + marginAfter = minimumValueForLength(style()->marginAfterUsing(containingBlockStyle), cw, renderView); +} + +void RenderBox::computeAndSetBlockDirectionMargins(const RenderBlock* containingBlock) +{ + LayoutUnit marginBefore; + LayoutUnit marginAfter; + computeBlockDirectionMargins(containingBlock, marginBefore, marginAfter); + containingBlock->setMarginBeforeForChild(this, marginBefore); + containingBlock->setMarginAfterForChild(this, marginAfter); } LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxModelObject* containingBlock, RenderRegion* region, @@ -2496,10 +2532,10 @@ static void computeInlineStaticDistance(Length& logicalLeft, Length& logicalRigh } } -void RenderBox::computePositionedLogicalWidth(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) +void RenderBox::computePositionedLogicalWidth(LogicalExtentComputedValues& computedValues, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const { if (isReplaced()) { - computePositionedLogicalWidthReplaced(); // FIXME: Patch for regions when we add replaced element support. + computePositionedLogicalWidthReplaced(computedValues); // FIXME: Patch for regions when we add replaced element support. return; } @@ -2534,8 +2570,6 @@ void RenderBox::computePositionedLogicalWidth(RenderRegion* region, LayoutUnit o const LayoutUnit bordersPlusPadding = borderAndPaddingLogicalWidth(); const Length marginLogicalLeft = isHorizontal ? style()->marginLeft() : style()->marginTop(); const Length marginLogicalRight = isHorizontal ? style()->marginRight() : style()->marginBottom(); - LayoutUnit& marginLogicalLeftAlias = m_marginBox.mutableLogicalLeft(style()->writingMode()); - LayoutUnit& marginLogicalRightAlias = m_marginBox.mutableLogicalRight(style()->writingMode()); Length logicalLeftLength = style()->logicalLeft(); Length logicalRightLength = style()->logicalRight(); @@ -2569,70 +2603,57 @@ void RenderBox::computePositionedLogicalWidth(RenderRegion* region, LayoutUnit o computeInlineStaticDistance(logicalLeftLength, logicalRightLength, this, containerBlock, containerLogicalWidth, region); // Calculate constraint equation values for 'width' case. - LayoutUnit logicalWidthResult; - LayoutUnit logicalLeftResult; computePositionedLogicalWidthUsing(MainOrPreferredSize, style()->logicalWidth(), containerBlock, containerDirection, containerLogicalWidth, bordersPlusPadding, logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight, - logicalWidthResult, marginLogicalLeftAlias, marginLogicalRightAlias, logicalLeftResult); - setLogicalWidth(logicalWidthResult); - setLogicalLeft(logicalLeftResult); + computedValues); // Calculate constraint equation values for 'max-width' case. if (!style()->logicalMaxWidth().isUndefined()) { - LayoutUnit maxLogicalWidth; - LayoutUnit maxMarginLogicalLeft; - LayoutUnit maxMarginLogicalRight; - LayoutUnit maxLogicalLeftPos; + LogicalExtentComputedValues maxValues; computePositionedLogicalWidthUsing(MaxSize, style()->logicalMaxWidth(), containerBlock, containerDirection, containerLogicalWidth, bordersPlusPadding, logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight, - maxLogicalWidth, maxMarginLogicalLeft, maxMarginLogicalRight, maxLogicalLeftPos); + maxValues); - if (logicalWidth() > maxLogicalWidth) { - setLogicalWidth(maxLogicalWidth); - marginLogicalLeftAlias = maxMarginLogicalLeft; - marginLogicalRightAlias = maxMarginLogicalRight; - setLogicalLeft(maxLogicalLeftPos); + if (computedValues.m_extent > maxValues.m_extent) { + computedValues.m_extent = maxValues.m_extent; + computedValues.m_position = maxValues.m_position; + computedValues.m_margins.m_start = maxValues.m_margins.m_start; + computedValues.m_margins.m_end = maxValues.m_margins.m_end; } } // Calculate constraint equation values for 'min-width' case. if (!style()->logicalMinWidth().isZero()) { - LayoutUnit minLogicalWidth; - LayoutUnit minMarginLogicalLeft; - LayoutUnit minMarginLogicalRight; - LayoutUnit minLogicalLeftPos; + LogicalExtentComputedValues minValues; computePositionedLogicalWidthUsing(MinSize, style()->logicalMinWidth(), containerBlock, containerDirection, containerLogicalWidth, bordersPlusPadding, logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight, - minLogicalWidth, minMarginLogicalLeft, minMarginLogicalRight, minLogicalLeftPos); + minValues); - if (logicalWidth() < minLogicalWidth) { - setLogicalWidth(minLogicalWidth); - marginLogicalLeftAlias = minMarginLogicalLeft; - marginLogicalRightAlias = minMarginLogicalRight; - setLogicalLeft(minLogicalLeftPos); + if (computedValues.m_extent < minValues.m_extent) { + computedValues.m_extent = minValues.m_extent; + computedValues.m_position = minValues.m_position; + computedValues.m_margins.m_start = minValues.m_margins.m_start; + computedValues.m_margins.m_end = minValues.m_margins.m_end; } } - if (stretchesToMinIntrinsicLogicalWidth() && logicalWidth() < minPreferredLogicalWidth() - bordersPlusPadding) { + if (stretchesToMinIntrinsicLogicalWidth() && computedValues.m_extent < minPreferredLogicalWidth() - bordersPlusPadding) { computePositionedLogicalWidthUsing(MainOrPreferredSize, Length(minPreferredLogicalWidth() - bordersPlusPadding, Fixed), containerBlock, containerDirection, containerLogicalWidth, bordersPlusPadding, logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight, - logicalWidthResult, marginLogicalLeftAlias, marginLogicalRightAlias, logicalLeftResult); - setLogicalWidth(logicalWidthResult); - setLogicalLeft(logicalLeftResult); + computedValues); } - // Put logicalWidth() into correct form. - setLogicalWidth(logicalWidth() + bordersPlusPadding); + computedValues.m_extent += bordersPlusPadding; // Adjust logicalLeft if we need to for the flipped version of our writing mode in regions. if (inRenderFlowThread() && !region && isWritingModeRoot() && isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode()) { - LayoutUnit logicalLeftPos = logicalLeft(); + LayoutUnit logicalLeftPos = computedValues.m_position; const RenderBlock* cb = toRenderBlock(containerBlock); LayoutUnit cbPageOffset = offsetFromLogicalTopOfFirstPage - logicalTop(); RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset); @@ -2641,7 +2662,7 @@ void RenderBox::computePositionedLogicalWidth(RenderRegion* region, LayoutUnit o RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(cbRegion, cbPageOffset); if (boxInfo) { logicalLeftPos += boxInfo->logicalLeft(); - setLogicalLeft(logicalLeftPos); + computedValues.m_position = logicalLeftPos; } } } @@ -2661,7 +2682,7 @@ static void computeLogicalLeftPositionedOffset(LayoutUnit& logicalLeftPos, const void RenderBox::computePositionedLogicalWidthUsing(SizeType widthSizeType, Length logicalWidth, const RenderBoxModelObject* containerBlock, TextDirection containerDirection, LayoutUnit containerLogicalWidth, LayoutUnit bordersPlusPadding, Length logicalLeft, Length logicalRight, Length marginLogicalLeft, Length marginLogicalRight, - LayoutUnit& logicalWidthValue, LayoutUnit& marginLogicalLeftValue, LayoutUnit& marginLogicalRightValue, LayoutUnit& logicalLeftPos) + LogicalExtentComputedValues& computedValues) const { if (widthSizeType == MinSize && logicalWidth.isAuto()) logicalWidth = Length(0, Fixed); @@ -2676,6 +2697,8 @@ void RenderBox::computePositionedLogicalWidthUsing(SizeType widthSizeType, Lengt bool logicalLeftIsAuto = logicalLeft.isAuto(); bool logicalRightIsAuto = logicalRight.isAuto(); RenderView* renderView = view(); + LayoutUnit& marginLogicalLeftValue = style()->isLeftToRightDirection() ? computedValues.m_margins.m_start : computedValues.m_margins.m_end; + LayoutUnit& marginLogicalRightValue = style()->isLeftToRightDirection() ? computedValues.m_margins.m_end : computedValues.m_margins.m_start; if (!logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) { /*-----------------------------------------------------------------------*\ @@ -2694,9 +2717,9 @@ void RenderBox::computePositionedLogicalWidthUsing(SizeType widthSizeType, Lengt // case because the value is not used for any further calculations. logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView); - logicalWidthValue = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView)); + computedValues.m_extent = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView)); - const LayoutUnit availableSpace = containerLogicalWidth - (logicalLeftValue + logicalWidthValue + valueForLength(logicalRight, containerLogicalWidth, renderView) + bordersPlusPadding); + const LayoutUnit availableSpace = containerLogicalWidth - (logicalLeftValue + computedValues.m_extent + valueForLength(logicalRight, containerLogicalWidth, renderView) + bordersPlusPadding); // Margins are now the only unknown if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) { @@ -2791,8 +2814,8 @@ void RenderBox::computePositionedLogicalWidthUsing(SizeType widthSizeType, Lengt LayoutUnit preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding; LayoutUnit preferredMinWidth = minPreferredLogicalWidth() - bordersPlusPadding; LayoutUnit availableWidth = availableSpace - logicalRightValue; - logicalWidthValue = min(max(preferredMinWidth, availableWidth), preferredWidth); - logicalLeftValue = availableSpace - (logicalWidthValue + logicalRightValue); + computedValues.m_extent = min(max(preferredMinWidth, availableWidth), preferredWidth); + logicalLeftValue = availableSpace - (computedValues.m_extent + logicalRightValue); } else if (!logicalLeftIsAuto && logicalWidthIsAuto && logicalRightIsAuto) { // RULE 3: (use shrink-to-fit for width, and no need solve of right) logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView); @@ -2801,19 +2824,19 @@ void RenderBox::computePositionedLogicalWidthUsing(SizeType widthSizeType, Lengt LayoutUnit preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding; LayoutUnit preferredMinWidth = minPreferredLogicalWidth() - bordersPlusPadding; LayoutUnit availableWidth = availableSpace - logicalLeftValue; - logicalWidthValue = min(max(preferredMinWidth, availableWidth), preferredWidth); + computedValues.m_extent = min(max(preferredMinWidth, availableWidth), preferredWidth); } else if (logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) { // RULE 4: (solve for left) - logicalWidthValue = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView)); - logicalLeftValue = availableSpace - (logicalWidthValue + valueForLength(logicalRight, containerLogicalWidth, renderView)); + computedValues.m_extent = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView)); + logicalLeftValue = availableSpace - (computedValues.m_extent + valueForLength(logicalRight, containerLogicalWidth, renderView)); } else if (!logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) { // RULE 5: (solve for width) logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView); - logicalWidthValue = availableSpace - (logicalLeftValue + valueForLength(logicalRight, containerLogicalWidth, renderView)); + computedValues.m_extent = availableSpace - (logicalLeftValue + valueForLength(logicalRight, containerLogicalWidth, renderView)); } else if (!logicalLeftIsAuto && !logicalWidthIsAuto && logicalRightIsAuto) { // RULE 6: (no need solve for right) logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView); - logicalWidthValue = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView)); + computedValues.m_extent = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView)); } } @@ -2828,13 +2851,13 @@ void RenderBox::computePositionedLogicalWidthUsing(SizeType widthSizeType, Lengt InlineFlowBox* firstLine = flow->firstLineBox(); InlineFlowBox* lastLine = flow->lastLineBox(); if (firstLine && lastLine && firstLine != lastLine) { - logicalLeftPos = logicalLeftValue + marginLogicalLeftValue + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft()); + computedValues.m_position = logicalLeftValue + marginLogicalLeftValue + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft()); return; } } - logicalLeftPos = logicalLeftValue + marginLogicalLeftValue; - computeLogicalLeftPositionedOffset(logicalLeftPos, this, logicalWidthValue, containerBlock, containerLogicalWidth); + computedValues.m_position = logicalLeftValue + marginLogicalLeftValue; + computeLogicalLeftPositionedOffset(computedValues.m_position, this, computedValues.m_extent, containerBlock, containerLogicalWidth); } static void computeBlockStaticDistance(Length& logicalTop, Length& logicalBottom, const RenderBox* child, const RenderBoxModelObject* containerBlock) @@ -2851,10 +2874,10 @@ static void computeBlockStaticDistance(Length& logicalTop, Length& logicalBottom logicalTop.setValue(Fixed, staticLogicalTop); } -void RenderBox::computePositionedLogicalHeight() +void RenderBox::computePositionedLogicalHeight(LogicalExtentComputedValues& computedValues) const { if (isReplaced()) { - computePositionedLogicalHeightReplaced(); + computePositionedLogicalHeightReplaced(computedValues); return; } @@ -2874,9 +2897,6 @@ void RenderBox::computePositionedLogicalHeight() const LayoutUnit bordersPlusPadding = borderAndPaddingLogicalHeight(); const Length marginBefore = styleToUse->marginBefore(); const Length marginAfter = styleToUse->marginAfter(); - LayoutUnit& marginBeforeAlias = m_marginBox.mutableBefore(styleToUse->writingMode()); - LayoutUnit& marginAfterAlias = m_marginBox.mutableAfter(styleToUse->writingMode()); - Length logicalTopLength = styleToUse->logicalTop(); Length logicalBottomLength = styleToUse->logicalBottom(); @@ -2901,62 +2921,52 @@ void RenderBox::computePositionedLogicalHeight() // Calculate the static distance if needed. computeBlockStaticDistance(logicalTopLength, logicalBottomLength, this, containerBlock); - LayoutUnit logicalHeightResult; // Needed to compute overflow. - LayoutUnit logicalTopPos; - // Calculate constraint equation values for 'height' case. computePositionedLogicalHeightUsing(MainOrPreferredSize, styleToUse->logicalHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding, logicalTopLength, logicalBottomLength, marginBefore, marginAfter, - logicalHeightResult, marginBeforeAlias, marginAfterAlias, logicalTopPos); - setLogicalTop(logicalTopPos); + computedValues); // Avoid doing any work in the common case (where the values of min-height and max-height are their defaults). // see FIXME 2 // Calculate constraint equation values for 'max-height' case. if (!styleToUse->logicalMaxHeight().isUndefined()) { - LayoutUnit maxLogicalHeight; - LayoutUnit maxMarginBefore; - LayoutUnit maxMarginAfter; - LayoutUnit maxLogicalTopPos; + LogicalExtentComputedValues maxValues; computePositionedLogicalHeightUsing(MaxSize, styleToUse->logicalMaxHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding, logicalTopLength, logicalBottomLength, marginBefore, marginAfter, - maxLogicalHeight, maxMarginBefore, maxMarginAfter, maxLogicalTopPos); + maxValues); - if (logicalHeightResult > maxLogicalHeight) { - logicalHeightResult = maxLogicalHeight; - marginBeforeAlias = maxMarginBefore; - marginAfterAlias = maxMarginAfter; - setLogicalTop(maxLogicalTopPos); + if (computedValues.m_extent > maxValues.m_extent) { + computedValues.m_extent = maxValues.m_extent; + computedValues.m_position = maxValues.m_position; + computedValues.m_margins.m_before = maxValues.m_margins.m_before; + computedValues.m_margins.m_after = maxValues.m_margins.m_after; } } // Calculate constraint equation values for 'min-height' case. if (!styleToUse->logicalMinHeight().isZero()) { - LayoutUnit minLogicalHeight; - LayoutUnit minMarginBefore; - LayoutUnit minMarginAfter; - LayoutUnit minLogicalTopPos; + LogicalExtentComputedValues minValues; computePositionedLogicalHeightUsing(MinSize, styleToUse->logicalMinHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding, logicalTopLength, logicalBottomLength, marginBefore, marginAfter, - minLogicalHeight, minMarginBefore, minMarginAfter, minLogicalTopPos); + minValues); - if (logicalHeightResult < minLogicalHeight) { - logicalHeightResult = minLogicalHeight; - marginBeforeAlias = minMarginBefore; - marginAfterAlias = minMarginAfter; - setLogicalTop(minLogicalTopPos); + if (computedValues.m_extent < minValues.m_extent) { + computedValues.m_extent = minValues.m_extent; + computedValues.m_position = minValues.m_position; + computedValues.m_margins.m_before = minValues.m_margins.m_before; + computedValues.m_margins.m_after = minValues.m_margins.m_after; } } // Set final height value. - setLogicalHeight(logicalHeightResult + bordersPlusPadding); + computedValues.m_extent += bordersPlusPadding; // Adjust logicalTop if we need to for perpendicular writing modes in regions. if (inRenderFlowThread() && isHorizontalWritingMode() != containerBlock->isHorizontalWritingMode()) { - LayoutUnit logicalTopPos = logicalTop(); + LayoutUnit logicalTopPos = computedValues.m_position; const RenderBlock* cb = toRenderBlock(containerBlock); LayoutUnit cbPageOffset = cb->offsetFromLogicalTopOfFirstPage() - logicalLeft(); RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset); @@ -2965,7 +2975,7 @@ void RenderBox::computePositionedLogicalHeight() RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(cbRegion, cbPageOffset); if (boxInfo) { logicalTopPos += boxInfo->logicalLeft(); - setLogicalTop(logicalTopPos); + computedValues.m_position = logicalTopPos; } } } @@ -2996,7 +3006,7 @@ static void computeLogicalTopPositionedOffset(LayoutUnit& logicalTopPos, const R void RenderBox::computePositionedLogicalHeightUsing(SizeType heightSizeType, Length logicalHeightLength, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalHeight, LayoutUnit bordersPlusPadding, Length logicalTop, Length logicalBottom, Length marginBefore, Length marginAfter, - LayoutUnit& logicalHeightValue, LayoutUnit& marginBeforeValue, LayoutUnit& marginAfterValue, LayoutUnit& logicalTopPos) + LogicalExtentComputedValues& computedValues) const { if (heightSizeType == MinSize && logicalHeightLength.isAuto()) logicalHeightLength = Length(0, Fixed); @@ -3005,6 +3015,7 @@ void RenderBox::computePositionedLogicalHeightUsing(SizeType heightSizeType, Len // converted to the static position in computePositionedLogicalHeight() ASSERT(!(logicalTop.isAuto() && logicalBottom.isAuto())); + LayoutUnit logicalHeightValue; LayoutUnit contentLogicalHeight = logicalHeight() - bordersPlusPadding; LayoutUnit logicalTopValue = 0; @@ -3041,20 +3052,20 @@ void RenderBox::computePositionedLogicalHeightUsing(SizeType heightSizeType, Len if (marginBefore.isAuto() && marginAfter.isAuto()) { // Both margins auto, solve for equality // NOTE: This may result in negative values. - marginBeforeValue = availableSpace / 2; // split the difference - marginAfterValue = availableSpace - marginBeforeValue; // account for odd valued differences + computedValues.m_margins.m_before = availableSpace / 2; // split the difference + computedValues.m_margins.m_after = availableSpace - computedValues.m_margins.m_before; // account for odd valued differences } else if (marginBefore.isAuto()) { // Solve for top margin - marginAfterValue = valueForLength(marginAfter, containerLogicalHeight, renderView); - marginBeforeValue = availableSpace - marginAfterValue; + computedValues.m_margins.m_after = valueForLength(marginAfter, containerLogicalHeight, renderView); + computedValues.m_margins.m_before = availableSpace - computedValues.m_margins.m_after; } else if (marginAfter.isAuto()) { // Solve for bottom margin - marginBeforeValue = valueForLength(marginBefore, containerLogicalHeight, renderView); - marginAfterValue = availableSpace - marginBeforeValue; + computedValues.m_margins.m_before = valueForLength(marginBefore, containerLogicalHeight, renderView); + computedValues.m_margins.m_after = availableSpace - computedValues.m_margins.m_before; } else { // Over-constrained, (no need solve for bottom) - marginBeforeValue = valueForLength(marginBefore, containerLogicalHeight, renderView); - marginAfterValue = valueForLength(marginAfter, containerLogicalHeight, renderView); + computedValues.m_margins.m_before = valueForLength(marginBefore, containerLogicalHeight, renderView); + computedValues.m_margins.m_after = valueForLength(marginAfter, containerLogicalHeight, renderView); } } else { /*--------------------------------------------------------------------*\ @@ -3083,10 +3094,10 @@ void RenderBox::computePositionedLogicalHeightUsing(SizeType heightSizeType, Len // because the value is not used for any further calculations. // Calculate margins, 'auto' margins are ignored. - marginBeforeValue = minimumValueForLength(marginBefore, containerLogicalHeight, renderView); - marginAfterValue = minimumValueForLength(marginAfter, containerLogicalHeight, renderView); + computedValues.m_margins.m_before = minimumValueForLength(marginBefore, containerLogicalHeight, renderView); + computedValues.m_margins.m_after = minimumValueForLength(marginAfter, containerLogicalHeight, renderView); - const LayoutUnit availableSpace = containerLogicalHeight - (marginBeforeValue + marginAfterValue + bordersPlusPadding); + const LayoutUnit availableSpace = containerLogicalHeight - (computedValues.m_margins.m_before + computedValues.m_margins.m_after + bordersPlusPadding); // Use rule/case that applies. if (logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) { @@ -3111,13 +3122,14 @@ void RenderBox::computePositionedLogicalHeightUsing(SizeType heightSizeType, Len logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView); } } + computedValues.m_extent = logicalHeightValue; // Use computed values to calculate the vertical position. - logicalTopPos = logicalTopValue + marginBeforeValue; - computeLogicalTopPositionedOffset(logicalTopPos, this, logicalHeightValue, containerBlock, containerLogicalHeight); + computedValues.m_position = logicalTopValue + computedValues.m_margins.m_before; + computeLogicalTopPositionedOffset(computedValues.m_position, this, logicalHeightValue, containerBlock, containerLogicalHeight); } -void RenderBox::computePositionedLogicalWidthReplaced() +void RenderBox::computePositionedLogicalWidthReplaced(LogicalExtentComputedValues& computedValues) const { // The following is based off of the W3C Working Draft from April 11, 2006 of // CSS 2.1: Section 10.3.8 "Absolutely positioned, replaced elements" @@ -3141,8 +3153,8 @@ void RenderBox::computePositionedLogicalWidthReplaced() Length logicalRight = style()->logicalRight(); Length marginLogicalLeft = isHorizontal ? style()->marginLeft() : style()->marginTop(); Length marginLogicalRight = isHorizontal ? style()->marginRight() : style()->marginBottom(); - LayoutUnit& marginLogicalLeftAlias = m_marginBox.mutableLogicalLeft(style()->writingMode()); - LayoutUnit& marginLogicalRightAlias = m_marginBox.mutableLogicalRight(style()->writingMode()); + LayoutUnit& marginLogicalLeftAlias = style()->isLeftToRightDirection() ? computedValues.m_margins.m_start : computedValues.m_margins.m_end; + LayoutUnit& marginLogicalRightAlias = style()->isLeftToRightDirection() ? computedValues.m_margins.m_end : computedValues.m_margins.m_start; /*-----------------------------------------------------------------------*\ * 1. The used value of 'width' is determined as for inline replaced @@ -3151,9 +3163,9 @@ void RenderBox::computePositionedLogicalWidthReplaced() // NOTE: This value of width is FINAL in that the min/max width calculations // are dealt with in computeReplacedWidth(). This means that the steps to produce // correct max/min in the non-replaced version, are not necessary. - setLogicalWidth(computeReplacedLogicalWidth() + borderAndPaddingLogicalWidth()); + computedValues.m_extent = computeReplacedLogicalWidth() + borderAndPaddingLogicalWidth(); - const LayoutUnit availableSpace = containerLogicalWidth - logicalWidth(); + const LayoutUnit availableSpace = containerLogicalWidth - computedValues.m_extent; /*-----------------------------------------------------------------------*\ * 2. If both 'left' and 'right' have the value 'auto', then if 'direction' @@ -3249,7 +3261,7 @@ void RenderBox::computePositionedLogicalWidthReplaced() logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView); // If the containing block is right-to-left, then push the left position as far to the right as possible if (containerDirection == RTL) { - int totalLogicalWidth = logicalWidth() + logicalLeftValue + logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias; + int totalLogicalWidth = computedValues.m_extent + logicalLeftValue + logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias; logicalLeftValue = containerLogicalWidth - (totalLogicalWidth - logicalLeftValue); } } @@ -3276,17 +3288,17 @@ void RenderBox::computePositionedLogicalWidthReplaced() InlineFlowBox* firstLine = flow->firstLineBox(); InlineFlowBox* lastLine = flow->lastLineBox(); if (firstLine && lastLine && firstLine != lastLine) { - setLogicalLeft(logicalLeftValue + marginLogicalLeftAlias + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft())); + computedValues.m_position = logicalLeftValue + marginLogicalLeftAlias + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft()); return; } } LayoutUnit logicalLeftPos = logicalLeftValue + marginLogicalLeftAlias; - computeLogicalLeftPositionedOffset(logicalLeftPos, this, logicalWidth(), containerBlock, containerLogicalWidth); - setLogicalLeft(logicalLeftPos.round()); + computeLogicalLeftPositionedOffset(logicalLeftPos, this, computedValues.m_extent, containerBlock, containerLogicalWidth); + computedValues.m_position = logicalLeftPos.round(); } -void RenderBox::computePositionedLogicalHeightReplaced() +void RenderBox::computePositionedLogicalHeightReplaced(LogicalExtentComputedValues& computedValues) const { // The following is based off of the W3C Working Draft from April 11, 2006 of // CSS 2.1: Section 10.6.5 "Absolutely positioned, replaced elements" @@ -3302,8 +3314,8 @@ void RenderBox::computePositionedLogicalHeightReplaced() // Variables to solve. Length marginBefore = style()->marginBefore(); Length marginAfter = style()->marginAfter(); - LayoutUnit& marginBeforeAlias = m_marginBox.mutableBefore(style()->writingMode()); - LayoutUnit& marginAfterAlias = m_marginBox.mutableAfter(style()->writingMode()); + LayoutUnit& marginBeforeAlias = computedValues.m_margins.m_before; + LayoutUnit& marginAfterAlias = computedValues.m_margins.m_after; Length logicalTop = style()->logicalTop(); Length logicalBottom = style()->logicalBottom(); @@ -3316,8 +3328,8 @@ void RenderBox::computePositionedLogicalHeightReplaced() // NOTE: This value of height is FINAL in that the min/max height calculations // are dealt with in computeReplacedHeight(). This means that the steps to produce // correct max/min in the non-replaced version, are not necessary. - setLogicalHeight(computeReplacedLogicalHeight() + borderAndPaddingLogicalHeight()); - const LayoutUnit availableSpace = containerLogicalHeight - logicalHeight(); + computedValues.m_extent = computeReplacedLogicalHeight() + borderAndPaddingLogicalHeight(); + const LayoutUnit availableSpace = containerLogicalHeight - computedValues.m_extent; /*-----------------------------------------------------------------------*\ * 2. If both 'top' and 'bottom' have the value 'auto', replace 'top' @@ -3411,8 +3423,8 @@ void RenderBox::computePositionedLogicalHeightReplaced() // Use computed values to calculate the vertical position. LayoutUnit logicalTopPos = logicalTopValue + marginBeforeAlias; - computeLogicalTopPositionedOffset(logicalTopPos, this, logicalHeight(), containerBlock, containerLogicalHeight); - setLogicalTop(logicalTopPos.round()); + computeLogicalTopPositionedOffset(logicalTopPos, this, computedValues.m_extent, containerBlock, containerLogicalHeight); + computedValues.m_position = logicalTopPos.round(); } LayoutRect RenderBox::localCaretRect(InlineBox* box, int caretOffset, LayoutUnit* extraWidthToEndOfLine) |