diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
commit | 2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (patch) | |
tree | 988e8c5b116dd0466244ae2fe5af8ee9be926d76 /Source/WebCore/rendering/RenderBox.cpp | |
parent | dd91e772430dc294e3bf478c119ef8d43c0a3358 (diff) | |
download | qtwebkit-2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47.tar.gz |
Imported WebKit commit 7e538425aa020340619e927792f3d895061fb54b (http://svn.webkit.org/repository/webkit/trunk@116286)
Diffstat (limited to 'Source/WebCore/rendering/RenderBox.cpp')
-rw-r--r-- | Source/WebCore/rendering/RenderBox.cpp | 534 |
1 files changed, 293 insertions, 241 deletions
diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp index bafdc376a..b906ec94d 100644 --- a/Source/WebCore/rendering/RenderBox.cpp +++ b/Source/WebCore/rendering/RenderBox.cpp @@ -253,19 +253,25 @@ void RenderBox::willBeDestroyed() if (styleToUse && (styleToUse->logicalHeight().isPercent() || styleToUse->logicalMinHeight().isPercent() || styleToUse->logicalMaxHeight().isPercent())) RenderBlock::removePercentHeightDescendant(this); - // If this renderer is owning renderer for the frameview's custom scrollbars, - // we need to clear it from the scrollbar. See webkit bug 64737. - if (styleToUse && styleToUse->hasPseudoStyle(SCROLLBAR) && frame() && frame()->view()) - frame()->view()->clearOwningRendererForCustomScrollbars(this); + if (styleToUse) { + if (RenderView* view = this->view()) { + if (FrameView* frameView = view->frameView()) { + // If this renderer is owning renderer for the FrameView's custom scrollbars, + // we need to clear it from the scrollbar. See webkit bug 64737. + if (styleToUse->hasPseudoStyle(SCROLLBAR)) + frameView->clearOwningRendererForCustomScrollbars(this); + + if (styleToUse->position() == FixedPosition) + frameView->removeFixedObject(); + } + } + } // If the following assertion fails, logicalHeight()/logicalMinHeight()/ // logicalMaxHeight() values are changed from a percent value to a non-percent // value during laying out. It causes a use-after-free bug. ASSERT(!RenderBlock::hasPercentHeightDescendant(this)); - if (hasOverflowClip() && everHadLayout() && !hasLayer()) - clearCachedSizeForOverflowClip(); - RenderBoxModelObject::willBeDestroyed(); } @@ -363,7 +369,7 @@ void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle // If our zoom factor changes and we have a defined scrollLeft/Top, we need to adjust that value into the // new zoomed coordinate space. - if (hasOverflowClipWithLayer() && oldStyle && newStyle && oldStyle->effectiveZoom() != newStyle->effectiveZoom()) { + if (hasOverflowClip() && oldStyle && newStyle && oldStyle->effectiveZoom() != newStyle->effectiveZoom()) { if (int left = layer()->scrollXOffset()) { left = (left / oldStyle->effectiveZoom()) * newStyle->effectiveZoom(); layer()->scrollToXOffset(left); @@ -419,7 +425,7 @@ void RenderBox::updateBoxModelInfoFromStyle() setHasBoxDecorations(true); setPositioned(styleToUse->isPositioned()); - setFloating(styleToUse->isFloating() && (!isPositioned() || styleToUse->floating() == PositionedFloat)); + setFloating(!isPositioned() && styleToUse->isFloating()); // We also handle <body> and <html>, whose overflow applies to the viewport. if (styleToUse->overflowX() != OVISIBLE && !isRootObject && (isRenderBlock() || isTableRow() || isTableSection())) { @@ -466,10 +472,6 @@ void RenderBox::layout() child = child->nextSibling(); } statePusher.pop(); - - if (hasOverflowClip() && !hasLayer()) - updateCachedSizeForOverflowClip(); - setNeedsLayout(false); } @@ -487,53 +489,53 @@ LayoutUnit RenderBox::clientHeight() const int RenderBox::pixelSnappedClientWidth() const { - return snapSizeToPixel(clientWidth(), clientLeft()); + return snapSizeToPixel(clientWidth(), x() + clientLeft()); } int RenderBox::pixelSnappedClientHeight() const { - return snapSizeToPixel(clientHeight(), clientTop()); + return snapSizeToPixel(clientHeight(), y() + clientTop()); } int RenderBox::scrollWidth() const { - if (hasOverflowClipWithLayer()) + if (hasOverflowClip()) return layer()->scrollWidth(); // For objects with visible overflow, this matches IE. // FIXME: Need to work right with writing modes. if (style()->isLeftToRightDirection()) - return max(clientWidth(), maxXLayoutOverflow() - borderLeft()); - return clientWidth() - min(0, minXLayoutOverflow() - borderLeft()); + return snapSizeToPixel(max(clientWidth(), maxXLayoutOverflow() - borderLeft()), clientLeft()); + return clientWidth() - min(ZERO_LAYOUT_UNIT, minXLayoutOverflow() - borderLeft()); } int RenderBox::scrollHeight() const { - if (hasOverflowClipWithLayer()) + if (hasOverflowClip()) return layer()->scrollHeight(); // For objects with visible overflow, this matches IE. // FIXME: Need to work right with writing modes. - return max(pixelSnappedClientHeight(), maxYLayoutOverflow() - borderTop()); + return snapSizeToPixel(max(clientHeight(), maxYLayoutOverflow() - borderTop()), clientTop()); } int RenderBox::scrollLeft() const { - return hasOverflowClipWithLayer() ? layer()->scrollXOffset() : 0; + return hasOverflowClip() ? layer()->scrollXOffset() : 0; } int RenderBox::scrollTop() const { - return hasOverflowClipWithLayer() ? layer()->scrollYOffset() : 0; + return hasOverflowClip() ? layer()->scrollYOffset() : 0; } void RenderBox::setScrollLeft(int newLeft) { - if (hasOverflowClipWithLayer()) + if (hasOverflowClip()) layer()->scrollToXOffset(newLeft, RenderLayer::ScrollOffsetClamped); } void RenderBox::setScrollTop(int newTop) { - if (hasOverflowClipWithLayer()) + if (hasOverflowClip()) layer()->scrollToYOffset(newTop, RenderLayer::ScrollOffsetClamped); } @@ -554,9 +556,9 @@ void RenderBox::updateLayerTransform() layer()->updateTransform(); } -LayoutRect RenderBox::absoluteContentBox() const +IntRect RenderBox::absoluteContentBox() const { - LayoutRect rect = contentBoxRect(); + IntRect rect = pixelSnappedIntRect(contentBoxRect()); FloatPoint absPos = localToAbsolute(FloatPoint()); rect.move(absPos.x(), absPos.y()); return rect; @@ -622,9 +624,10 @@ int RenderBox::reflectionOffset() const { if (!style()->boxReflect()) return 0; + RenderView* renderView = view(); if (style()->boxReflect()->direction() == ReflectionLeft || style()->boxReflect()->direction() == ReflectionRight) - return style()->boxReflect()->offset().calcValue(borderBoxRect().width()); - return style()->boxReflect()->offset().calcValue(borderBoxRect().height()); + return valueForLength(style()->boxReflect()->offset(), borderBoxRect().width(), renderView); + return valueForLength(style()->boxReflect()->offset(), borderBoxRect().height(), renderView); } LayoutRect RenderBox::reflectedRect(const LayoutRect& r) const @@ -658,13 +661,13 @@ bool RenderBox::fixedElementLaysOutRelativeToFrame(Frame* frame, FrameView* fram bool RenderBox::includeVerticalScrollbarSize() const { - return hasOverflowClipWithLayer() && !layer()->hasOverlayScrollbars() + return hasOverflowClip() && !layer()->hasOverlayScrollbars() && (style()->overflowY() == OSCROLL || style()->overflowY() == OAUTO); } bool RenderBox::includeHorizontalScrollbarSize() const { - return hasOverflowClipWithLayer() && !layer()->hasOverlayScrollbars() + return hasOverflowClip() && !layer()->hasOverlayScrollbars() && (style()->overflowX() == OSCROLL || style()->overflowX() == OAUTO); } @@ -756,56 +759,15 @@ bool RenderBox::needsPreferredWidthsRecalculation() const IntSize RenderBox::scrolledContentOffset() const { ASSERT(hasOverflowClip()); - - if (hasLayer()) - return layer()->scrolledContentOffset(); - - // If we have no layer, it means that we have no overflowing content as we lazily - // allocate it on demand. Thus we don't have any scroll offset. - ASSERT(!requiresLayerForOverflowClip()); - return LayoutSize(); -} - -typedef HashMap<const RenderBox*, LayoutSize> RendererSizeCache; -static RendererSizeCache& cachedSizeForOverflowClipMap() -{ - DEFINE_STATIC_LOCAL(RendererSizeCache, cachedSizeForOverflowClipMap, ()); - return cachedSizeForOverflowClipMap; + ASSERT(hasLayer()); + return layer()->scrolledContentOffset(); } -IntSize RenderBox::cachedSizeForOverflowClip() const +LayoutSize RenderBox::cachedSizeForOverflowClip() const { ASSERT(hasOverflowClip()); - if (hasLayer()) - return layer()->size(); - - ASSERT(!requiresLayerForOverflowClip()); - RendererSizeCache::iterator it = cachedSizeForOverflowClipMap().find(this); - if (it == cachedSizeForOverflowClipMap().end()) - return LayoutSize(); - - return it->second; -} - -void RenderBox::updateCachedSizeForOverflowClip() -{ - ASSERT(hasOverflowClip()); - ASSERT(!requiresLayerForOverflowClip()); - ASSERT(!hasLayer()); - - cachedSizeForOverflowClipMap().set(this, size()); -} - -void RenderBox::clearCachedSizeForOverflowClip() -{ - ASSERT(hasOverflowClip()); - ASSERT(!requiresLayerForOverflowClip()); - ASSERT(!hasLayer()); - - // FIXME: We really would like to enable this ASSERT. However the current updateScrollInfoAfterLayout - // is not bullet-proof and it triggers in non-obvious ways under NRWT. - // ASSERT(cachedSizeForOverflowClipMap().contains(this)); - cachedSizeForOverflowClipMap().remove(this); + ASSERT(hasLayer()); + return layer()->size(); } LayoutUnit RenderBox::minPreferredLogicalWidth() const @@ -991,7 +953,7 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& pai // To avoid the background color bleeding out behind the border, we'll render background and border // into a transparency layer, and then clip that in one go (which requires setting up the clip before // beginning the layer). - RoundedRect border = style()->getRoundedBorderFor(paintRect); + RoundedRect border = style()->getRoundedBorderFor(paintRect, view()); stateSaver.save(); paintInfo.context->addRoundedRectClip(border); paintInfo.context->beginTransparencyLayer(1); @@ -999,17 +961,18 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& pai // If we have a native theme appearance, paint that before painting our background. // The theme will tell us whether or not we should also paint the CSS background. - bool themePainted = style()->hasAppearance() && !theme()->paint(this, paintInfo, paintRect); + IntRect snappedPaintRect(pixelSnappedIntRect(paintRect)); + bool themePainted = style()->hasAppearance() && !theme()->paint(this, paintInfo, snappedPaintRect); if (!themePainted) { paintBackground(paintInfo, paintRect, bleedAvoidance); if (style()->hasAppearance()) - theme()->paintDecorations(this, paintInfo, pixelSnappedIntRect(paintRect)); + theme()->paintDecorations(this, paintInfo, snappedPaintRect); } paintBoxShadow(paintInfo, paintRect, style(), Inset); // The theme will tell us whether or not we should also paint the CSS border. - if ((!style()->hasAppearance() || (!themePainted && theme()->paintBorderOnly(this, paintInfo, pixelSnappedIntRect(paintRect)))) && style()->hasBorder()) + if ((!style()->hasAppearance() || (!themePainted && theme()->paintBorderOnly(this, paintInfo, snappedPaintRect))) && style()->hasBorder()) paintBorder(paintInfo, paintRect, style(), bleedAvoidance); if (bleedAvoidance == BackgroundBleedUseTransparencyLayer) @@ -1049,11 +1012,12 @@ void RenderBox::paintMaskImages(const PaintInfo& paintInfo, const LayoutRect& pa // Figure out if we need to push a transparency layer to render our mask. bool pushTransparencyLayer = false; bool compositedMask = hasLayer() && layer()->hasCompositedMask(); + bool flattenCompositingLayers = view()->frameView() && view()->frameView()->paintBehavior() & PaintBehaviorFlattenCompositingLayers; CompositeOperator compositeOp = CompositeSourceOver; bool allMaskImagesLoaded = true; - if (!compositedMask) { + if (!compositedMask || flattenCompositingLayers) { pushTransparencyLayer = true; StyleImage* maskBoxImage = style()->maskBoxImage().image(); const FillLayer* maskLayers = style()->maskLayers(); @@ -1158,7 +1122,7 @@ void RenderBox::imageChanged(WrappedImagePtr image, const IntRect*) #if USE(ACCELERATED_COMPOSITING) if (hasLayer() && layer()->hasCompositedMask() && layersUseImage(image, style()->maskLayers())) - layer()->contentChanged(RenderLayer::MaskImageChanged); + layer()->contentChanged(MaskImageChanged); #endif } @@ -1237,7 +1201,7 @@ bool RenderBox::pushContentsClip(PaintInfo& paintInfo, const LayoutPoint& accumu return false; bool isControlClip = hasControlClip(); - bool isOverflowClip = hasOverflowClip() && !hasSelfPaintingLayer(); + bool isOverflowClip = hasOverflowClip() && !layer()->isSelfPaintingLayer(); if (!isControlClip && !isOverflowClip) return false; @@ -1259,7 +1223,7 @@ bool RenderBox::pushContentsClip(PaintInfo& paintInfo, const LayoutPoint& accumu void RenderBox::popContentsClip(PaintInfo& paintInfo, PaintPhase originalPhase, const LayoutPoint& accumulatedOffset) { - ASSERT(hasControlClip() || (hasOverflowClip() && !hasSelfPaintingLayer())); + ASSERT(hasControlClip() || (hasOverflowClip() && !layer()->isSelfPaintingLayer())); paintInfo.context->restore(); if (originalPhase == PaintPhaseOutline) { @@ -1292,9 +1256,10 @@ LayoutRect RenderBox::clipRect(const LayoutPoint& location, RenderRegion* region { LayoutRect borderBoxRect = borderBoxRectInRegion(region); LayoutRect clipRect = LayoutRect(borderBoxRect.location() + location, borderBoxRect.size()); + RenderView* renderView = view(); if (!style()->clipLeft().isAuto()) { - LayoutUnit c = style()->clipLeft().calcValue(borderBoxRect.width()); + LayoutUnit c = valueForLength(style()->clipLeft(), borderBoxRect.width(), renderView); clipRect.move(c, 0); clipRect.contract(c, 0); } @@ -1303,16 +1268,16 @@ LayoutRect RenderBox::clipRect(const LayoutPoint& location, RenderRegion* region // from the left and top edges. Therefore it's better to avoid constraining to smaller widths and heights. if (!style()->clipRight().isAuto()) - clipRect.contract(width() - style()->clipRight().calcValue(width()), 0); + clipRect.contract(width() - valueForLength(style()->clipRight(), width(), renderView), 0); if (!style()->clipTop().isAuto()) { - LayoutUnit c = style()->clipTop().calcValue(borderBoxRect.height()); + LayoutUnit c = valueForLength(style()->clipTop(), borderBoxRect.height(), renderView); clipRect.move(0, c); clipRect.contract(0, c); } if (!style()->clipBottom().isAuto()) - clipRect.contract(0, height() - style()->clipBottom().calcValue(height())); + clipRect.contract(0, height() - valueForLength(style()->clipBottom(), height(), renderView)); return clipRect; } @@ -1323,7 +1288,7 @@ LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStar LayoutUnit logicalTopPosition = logicalTop(); LayoutUnit adjustedPageOffsetForContainingBlock = offsetFromLogicalTopOfFirstPage - logicalTop(); if (region) { - LayoutUnit offsetFromLogicalTopOfRegion = region ? region->offsetFromLogicalTopOfFirstPage() - offsetFromLogicalTopOfFirstPage : zeroLayoutUnit; + LayoutUnit offsetFromLogicalTopOfRegion = region ? region->offsetFromLogicalTopOfFirstPage() - offsetFromLogicalTopOfFirstPage : ZERO_LAYOUT_UNIT; logicalTopPosition = max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion); containingBlockRegion = cb->clampToStartAndEndRegions(region); } @@ -1378,6 +1343,20 @@ LayoutUnit RenderBox::containingBlockLogicalWidthForContentInRegion(RenderRegion return max<LayoutUnit>(0, result - (cb->logicalWidth() - boxInfo->logicalWidth())); } +LayoutUnit RenderBox::containingBlockAvailableLineWidthInRegion(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const +{ + RenderBlock* cb = containingBlock(); + RenderRegion* containingBlockRegion = 0; + LayoutUnit logicalTopPosition = logicalTop(); + LayoutUnit adjustedPageOffsetForContainingBlock = offsetFromLogicalTopOfFirstPage - logicalTop(); + if (region) { + LayoutUnit offsetFromLogicalTopOfRegion = region ? region->offsetFromLogicalTopOfFirstPage() - offsetFromLogicalTopOfFirstPage : ZERO_LAYOUT_UNIT; + logicalTopPosition = max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion); + containingBlockRegion = cb->clampToStartAndEndRegions(region); + } + return cb->availableLogicalWidthForLine(logicalTopPosition, false, containingBlockRegion, adjustedPageOffsetForContainingBlock); +} + LayoutUnit RenderBox::perpendicularContainingBlockLogicalHeight() const { RenderBlock* cb = containingBlock(); @@ -1396,7 +1375,7 @@ LayoutUnit RenderBox::perpendicularContainingBlockLogicalHeight() const return cb->computeContentBoxLogicalHeight(logicalHeightLength.value()); } -void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, bool* wasFixed) const +void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, ApplyContainerFlipOrNot, bool* wasFixed) const { if (repaintContainer == this) return; @@ -1450,11 +1429,11 @@ void RenderBox::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool // Transform from render flow coordinates into region coordinates. RenderRegion* region = toRenderFlowThread(o)->mapFromFlowToRegion(transformState); if (region) - region->mapLocalToContainer(region->containerForRepaint(), fixed, useTransforms, transformState, wasFixed); + region->mapLocalToContainer(region->containerForRepaint(), fixed, useTransforms, transformState, DoNotApplyContainerFlip, wasFixed); return; } - o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, wasFixed); + o->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState, DoNotApplyContainerFlip, wasFixed); } void RenderBox::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState& transformState) const @@ -1533,7 +1512,7 @@ void RenderBox::positionLineBox(InlineBox* box) RootInlineBox* root = box->root(); root->block()->setStaticInlinePositionForChild(this, root->lineTopWithLeading(), roundedLayoutUnit(box->logicalLeft())); if (style()->hasStaticInlinePosition(box->isHorizontal())) - setChildNeedsLayout(true, false); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly. + setChildNeedsLayout(true, MarkOnlyThis); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly. } else { // Our object was a block originally, so we make our normal flow position be // just below the line box (as though all the inlines that came before us got @@ -1541,7 +1520,7 @@ void RenderBox::positionLineBox(InlineBox* box) // in flow). This value was cached in the y() of the box. layer()->setStaticBlockPosition(box->logicalTop()); if (style()->hasStaticBlockPosition(box->isHorizontal())) - setChildNeedsLayout(true, false); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly. + setChildNeedsLayout(true, MarkOnlyThis); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly. } // Nuke the box. @@ -1641,18 +1620,6 @@ void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, La if (isWritingModeRoot() && !isPositioned()) flipForWritingMode(rect); -#if ENABLE(CSS_FILTERS) - if (styleToUse->hasFilterOutsets()) { - LayoutUnit topOutset; - LayoutUnit rightOutset; - LayoutUnit bottomOutset; - LayoutUnit leftOutset; - styleToUse->filter().getOutsets(topOutset, rightOutset, bottomOutset, leftOutset); - rect.move(-leftOutset, -topOutset); - rect.expand(leftOutset + rightOutset, topOutset + bottomOutset); - } -#endif - LayoutPoint topLeft = rect.location(); topLeft.move(locationOffset()); @@ -1779,10 +1746,11 @@ void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit off if (isInline() && !isInlineBlockOrInlineTable()) { // just calculate margins - setMarginStart(styleToUse->marginStart().calcMinValue(containerLogicalWidth)); - setMarginEnd(styleToUse->marginEnd().calcMinValue(containerLogicalWidth)); + RenderView* renderView = view(); + setMarginStart(minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView)); + setMarginEnd(minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView)); if (treatAsReplaced) - setLogicalWidth(max<LayoutUnit>(logicalWidthLength.calcFloatValue(0) + borderAndPaddingLogicalWidth(), minPreferredLogicalWidth())); + setLogicalWidth(max<LayoutUnit>(floatValueForLength(logicalWidthLength, 0) + borderAndPaddingLogicalWidth(), minPreferredLogicalWidth())); return; } @@ -1817,12 +1785,17 @@ void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit off } // Margin calculations. - if (logicalWidthLength.isAuto() || hasPerpendicularContainingBlock) { - setMarginStart(styleToUse->marginStart().calcMinValue(containerLogicalWidth)); - setMarginEnd(styleToUse->marginEnd().calcMinValue(containerLogicalWidth)); - } else - computeInlineDirectionMargins(cb, containerLogicalWidth, logicalWidth()); - + if (hasPerpendicularContainingBlock || isFloating() || isInline()) { + RenderView* renderView = view(); + setMarginStart(minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView)); + setMarginEnd(minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView)); + } else { + LayoutUnit containerLogicalWidthForAutoMargins = containerLogicalWidth; + if (avoidsFloats() && cb->containsFloats()) + containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(region, offsetFromLogicalTopOfFirstPage); + computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, logicalWidth()); + } + if (!hasPerpendicularContainingBlock && containerLogicalWidth && containerLogicalWidth != (logicalWidth() + marginStart() + marginEnd()) && !isFloating() && !isInline() && !cb->isFlexibleBoxIncludingDeprecated()) cb->setMarginEndForChild(this, containerLogicalWidth - logicalWidth() - cb->marginStartForChild(this)); @@ -1841,9 +1814,12 @@ LayoutUnit RenderBox::computeLogicalWidthInRegionUsing(LogicalWidthType widthTyp else logicalWidth = styleToUse->logicalMaxWidth(); + ASSERT(!logicalWidth.isUndefined()); + if (logicalWidth.isIntrinsicOrAuto()) { - LayoutUnit marginStart = styleToUse->marginStart().calcMinValue(availableLogicalWidth); - LayoutUnit marginEnd = styleToUse->marginEnd().calcMinValue(availableLogicalWidth); + RenderView* renderView = view(); + LayoutUnit marginStart = minimumValueForLength(styleToUse->marginStart(), availableLogicalWidth, renderView); + LayoutUnit marginEnd = minimumValueForLength(styleToUse->marginEnd(), availableLogicalWidth, renderView); logicalWidthResult = availableLogicalWidth - marginStart - marginEnd; if (shrinkToAvoidFloats() && cb->containsFloats()) @@ -1854,7 +1830,7 @@ LayoutUnit RenderBox::computeLogicalWidthInRegionUsing(LogicalWidthType widthTyp logicalWidthResult = min(logicalWidthResult, maxPreferredLogicalWidth()); } } else // FIXME: If the containing block flow is perpendicular to our direction we need to use the available logical height instead. - logicalWidthResult = computeBorderBoxLogicalWidth(logicalWidth.calcValue(availableLogicalWidth)); + logicalWidthResult = computeBorderBoxLogicalWidth(valueForLength(logicalWidth, availableLogicalWidth, view())); return logicalWidthResult; } @@ -1922,11 +1898,12 @@ void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, Layo const RenderStyle* containingBlockStyle = containingBlock->style(); Length marginStartLength = style()->marginStartUsing(containingBlockStyle); Length marginEndLength = style()->marginEndUsing(containingBlockStyle); + RenderView* renderView = view(); if (isFloating() || isInline()) { // Inline blocks/tables and floats don't have their margins increased. - containingBlock->setMarginStartForChild(this, marginStartLength.calcMinValue(containerWidth)); - containingBlock->setMarginEndForChild(this, marginEndLength.calcMinValue(containerWidth)); + containingBlock->setMarginStartForChild(this, minimumValueForLength(marginStartLength, containerWidth, renderView)); + containingBlock->setMarginEndForChild(this, minimumValueForLength(marginEndLength, containerWidth, renderView)); return; } @@ -1940,7 +1917,7 @@ void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, Layo // 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, marginStartLength.calcValue(containerWidth)); + containingBlock->setMarginStartForChild(this, valueForLength(marginStartLength, containerWidth, renderView)); containingBlock->setMarginEndForChild(this, containerWidth - childWidth - containingBlock->marginStartForChild(this)); return; } @@ -1949,15 +1926,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, marginEndLength.calcValue(containerWidth)); + containingBlock->setMarginEndForChild(this, valueForLength(marginEndLength, containerWidth, renderView)); containingBlock->setMarginStartForChild(this, containerWidth - childWidth - containingBlock->marginEndForChild(this)); 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, marginStartLength.calcMinValue(containerWidth)); - containingBlock->setMarginEndForChild(this, marginEndLength.calcMinValue(containerWidth)); + containingBlock->setMarginStartForChild(this, minimumValueForLength(marginStartLength, containerWidth, renderView)); + containingBlock->setMarginEndForChild(this, minimumValueForLength(marginEndLength, containerWidth, renderView)); } RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, RenderBoxRegionInfoFlags cacheFlag) const @@ -2022,8 +1999,7 @@ RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, Layout LayoutUnit logicalLeftOffset = 0; if (!isPositioned() && avoidsFloats() && cb->containsFloats()) { - LayoutUnit startPositionDelta = cb->computeStartPositionDeltaForChildAvoidingFloats(this, marginStartInRegion, logicalWidthInRegion, - region, offsetFromLogicalTopOfFirstPage); + LayoutUnit startPositionDelta = cb->computeStartPositionDeltaForChildAvoidingFloats(this, marginStartInRegion, region, offsetFromLogicalTopOfFirstPage); if (cb->style()->isLeftToRightDirection()) logicalLeftDelta += startPositionDelta; else @@ -2152,18 +2128,24 @@ void RenderBox::computeLogicalHeight() } } -LayoutUnit RenderBox::computeLogicalHeightUsing(const Length& h) +LayoutUnit RenderBox::computeLogicalHeightUsing(const Length& height) +{ + LayoutUnit logicalHeight = computeContentLogicalHeightUsing(height); + if (logicalHeight != -1) + logicalHeight = computeBorderBoxLogicalHeight(logicalHeight); + return logicalHeight; +} + +LayoutUnit RenderBox::computeContentLogicalHeightUsing(const Length& height) { LayoutUnit logicalHeight = -1; - if (!h.isAuto()) { - if (h.isFixed()) - logicalHeight = h.value(); - else if (h.isPercent()) - logicalHeight = computePercentageLogicalHeight(h); - if (logicalHeight != -1) { - logicalHeight = computeBorderBoxLogicalHeight(logicalHeight); - return logicalHeight; - } + if (!height.isAuto()) { + if (height.isFixed()) + logicalHeight = height.value(); + else if (height.isPercent()) + logicalHeight = computePercentageLogicalHeight(height); + else if (height.isViewportPercentage()) + logicalHeight = valueForLength(height, 0, view()); } return logicalHeight; } @@ -2241,7 +2223,7 @@ LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height) result = cb->computeContentBoxLogicalHeight(cb->availableLogicalHeight()); if (result != -1) { - result = height.calcValue(result); + result = valueForLength(height, result); if (includeBorderPadding) { // It is necessary to use the border-box to match WinIE's broken // box model. This is essential for sizing inside @@ -2270,13 +2252,18 @@ LayoutUnit RenderBox::computeReplacedLogicalWidthUsing(Length logicalWidth) cons switch (logicalWidth.type()) { case Fixed: return computeContentBoxLogicalWidth(logicalWidth.value()); - case Percent: { + case ViewportPercentageWidth: + case ViewportPercentageHeight: + case ViewportPercentageMin: + return computeContentBoxLogicalWidth(valueForLength(logicalWidth, 0, view())); + case Percent: + case Calculated: { // 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 = isPositioned() ? containingBlockLogicalWidthForPositioned(toRenderBoxModelObject(container())) : containingBlockLogicalWidthForContent(); if (cw > 0) - return computeContentBoxLogicalWidth(logicalWidth.calcMinValue(cw)); + return computeContentBoxLogicalWidth(minimumValueForLength(logicalWidth, cw)); } // fall through default: @@ -2302,6 +2289,7 @@ LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(Length logicalHeight) co case Fixed: return computeContentBoxLogicalHeight(logicalHeight.value()); case Percent: + case Calculated: { RenderObject* cb = isPositioned() ? container() : containingBlock(); while (cb->isAnonymous()) { @@ -2318,7 +2306,7 @@ LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(Length logicalHeight) co block->computeLogicalHeight(); LayoutUnit newHeight = block->computeContentBoxLogicalHeight(block->contentHeight()); block->setHeight(oldHeight); - return computeContentBoxLogicalHeight(logicalHeight.calcValue(newHeight)); + return computeContentBoxLogicalHeight(valueForLength(logicalHeight, newHeight)); } // FIXME: availableLogicalHeight() is wrong if the replaced element's block-flow is perpendicular to the @@ -2339,13 +2327,18 @@ LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(Length logicalHeight) co // Don't let table cells squeeze percent-height replaced elements // <http://bugs.webkit.org/show_bug.cgi?id=15359> availableHeight = max(availableHeight, intrinsicLogicalHeight()); - return logicalHeight.calcValue(availableHeight - borderAndPaddingLogicalHeight()); + return valueForLength(logicalHeight, availableHeight - borderAndPaddingLogicalHeight()); } cb = cb->containingBlock(); + toRenderBlock(cb)->addPercentHeightDescendant(const_cast<RenderBox*>(this)); } } - return computeContentBoxLogicalHeight(logicalHeight.calcValue(availableHeight)); + return computeContentBoxLogicalHeight(valueForLength(logicalHeight, availableHeight)); } + case ViewportPercentageWidth: + case ViewportPercentageHeight: + case ViewportPercentageMin: + return computeContentBoxLogicalHeight(valueForLength(logicalHeight, 0, view())); default: return intrinsicLogicalHeight(); } @@ -2379,7 +2372,7 @@ LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h) const availableHeight = containingBlockLogicalHeightForPositioned(containingBlock()); else availableHeight = containingBlock()->availableLogicalHeight(); - return computeContentBoxLogicalHeight(h.calcValue(availableHeight)); + return computeContentBoxLogicalHeight(valueForLength(h, availableHeight)); } // FIXME: We can't just check top/bottom here. @@ -2409,10 +2402,10 @@ void RenderBox::computeBlockDirectionMargins(RenderBlock* containingBlock) // Margins are calculated with respect to the logical width of // the containing block (8.3) LayoutUnit cw = containingBlockLogicalWidthForContent(); - + RenderView* renderView = view(); RenderStyle* containingBlockStyle = containingBlock->style(); - containingBlock->setMarginBeforeForChild(this, style()->marginBeforeUsing(containingBlockStyle).calcMinValue(cw)); - containingBlock->setMarginAfterForChild(this, style()->marginAfterUsing(containingBlockStyle).calcMinValue(cw)); + containingBlock->setMarginBeforeForChild(this, minimumValueForLength(style()->marginBeforeUsing(containingBlockStyle), cw, renderView)); + containingBlock->setMarginAfterForChild(this, minimumValueForLength(style()->marginAfterUsing(containingBlockStyle), cw, renderView)); } LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxModelObject* containingBlock, RenderRegion* region, @@ -2735,6 +2728,7 @@ void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const Re bool logicalWidthIsAuto = logicalWidth.isIntrinsicOrAuto(); bool logicalLeftIsAuto = logicalLeft.isAuto(); bool logicalRightIsAuto = logicalRight.isAuto(); + RenderView* renderView = view(); if (!logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) { /*-----------------------------------------------------------------------*\ @@ -2752,10 +2746,10 @@ void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const Re // NOTE: It is not necessary to solve for 'right' in the over constrained // case because the value is not used for any further calculations. - logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth); - logicalWidthValue = computeContentBoxLogicalWidth(logicalWidth.calcValue(containerLogicalWidth)); + logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView); + logicalWidthValue = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView)); - const LayoutUnit availableSpace = containerLogicalWidth - (logicalLeftValue + logicalWidthValue + logicalRight.calcValue(containerLogicalWidth) + bordersPlusPadding); + const LayoutUnit availableSpace = containerLogicalWidth - (logicalLeftValue + logicalWidthValue + valueForLength(logicalRight, containerLogicalWidth, renderView) + bordersPlusPadding); // Margins are now the only unknown if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) { @@ -2776,16 +2770,16 @@ void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const Re } } else if (marginLogicalLeft.isAuto()) { // Solve for left margin - marginLogicalRightValue = marginLogicalRight.calcValue(containerLogicalWidth); + marginLogicalRightValue = valueForLength(marginLogicalRight, containerLogicalWidth, renderView); marginLogicalLeftValue = availableSpace - marginLogicalRightValue; } else if (marginLogicalRight.isAuto()) { // Solve for right margin - marginLogicalLeftValue = marginLogicalLeft.calcValue(containerLogicalWidth); + marginLogicalLeftValue = valueForLength(marginLogicalLeft, containerLogicalWidth, renderView); marginLogicalRightValue = availableSpace - marginLogicalLeftValue; } else { // Over-constrained, solve for left if direction is RTL - marginLogicalLeftValue = marginLogicalLeft.calcValue(containerLogicalWidth); - marginLogicalRightValue = marginLogicalRight.calcValue(containerLogicalWidth); + marginLogicalLeftValue = valueForLength(marginLogicalLeft, containerLogicalWidth, renderView); + marginLogicalRightValue = valueForLength(marginLogicalRight, containerLogicalWidth, renderView); // Use the containing block's direction rather than the parent block's // per CSS 2.1 reference test abspos-non-replaced-width-margin-000. @@ -2835,8 +2829,8 @@ void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const Re // because the value is not used for any further calculations. // Calculate margins, 'auto' margins are ignored. - marginLogicalLeftValue = marginLogicalLeft.calcMinValue(containerLogicalWidth); - marginLogicalRightValue = marginLogicalRight.calcMinValue(containerLogicalWidth); + marginLogicalLeftValue = minimumValueForLength(marginLogicalLeft, containerLogicalWidth, renderView); + marginLogicalRightValue = minimumValueForLength(marginLogicalRight, containerLogicalWidth, renderView); const LayoutUnit availableSpace = containerLogicalWidth - (marginLogicalLeftValue + marginLogicalRightValue + bordersPlusPadding); @@ -2844,7 +2838,7 @@ void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const Re // Use rule/case that applies. if (logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) { // RULE 1: (use shrink-to-fit for width, and solve of left) - LayoutUnit logicalRightValue = logicalRight.calcValue(containerLogicalWidth); + LayoutUnit logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView); // FIXME: would it be better to have shrink-to-fit in one step? LayoutUnit preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding; @@ -2854,7 +2848,7 @@ void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const Re logicalLeftValue = availableSpace - (logicalWidthValue + logicalRightValue); } else if (!logicalLeftIsAuto && logicalWidthIsAuto && logicalRightIsAuto) { // RULE 3: (use shrink-to-fit for width, and no need solve of right) - logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth); + logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView); // FIXME: would it be better to have shrink-to-fit in one step? LayoutUnit preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding; @@ -2863,16 +2857,16 @@ void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const Re logicalWidthValue = min(max(preferredMinWidth, availableWidth), preferredWidth); } else if (logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) { // RULE 4: (solve for left) - logicalWidthValue = computeContentBoxLogicalWidth(logicalWidth.calcValue(containerLogicalWidth)); - logicalLeftValue = availableSpace - (logicalWidthValue + logicalRight.calcValue(containerLogicalWidth)); + logicalWidthValue = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView)); + logicalLeftValue = availableSpace - (logicalWidthValue + valueForLength(logicalRight, containerLogicalWidth, renderView)); } else if (!logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) { // RULE 5: (solve for width) - logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth); - logicalWidthValue = availableSpace - (logicalLeftValue + logicalRight.calcValue(containerLogicalWidth)); + logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView); + logicalWidthValue = availableSpace - (logicalLeftValue + valueForLength(logicalRight, containerLogicalWidth, renderView)); } else if (!logicalLeftIsAuto && !logicalWidthIsAuto && logicalRightIsAuto) { // RULE 6: (no need solve for right) - logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth); - logicalWidthValue = computeContentBoxLogicalWidth(logicalWidth.calcValue(containerLogicalWidth)); + logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView); + logicalWidthValue = computeContentBoxLogicalWidth(valueForLength(logicalWidth, containerLogicalWidth, renderView)); } } @@ -3068,6 +3062,7 @@ void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength, bool logicalHeightIsAuto = logicalHeightLength.isAuto(); bool logicalTopIsAuto = logicalTop.isAuto(); bool logicalBottomIsAuto = logicalBottom.isAuto(); + RenderView* renderView = view(); // Height is never unsolved for tables. if (isTable()) { @@ -3087,10 +3082,10 @@ void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength, // NOTE: It is not necessary to solve for 'bottom' in the over constrained // case because the value is not used for any further calculations. - logicalHeightValue = computeContentBoxLogicalHeight(logicalHeightLength.calcValue(containerLogicalHeight)); - logicalTopValue = logicalTop.calcValue(containerLogicalHeight); + logicalHeightValue = computeContentBoxLogicalHeight(valueForLength(logicalHeightLength, containerLogicalHeight, renderView)); + logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView); - const LayoutUnit availableSpace = containerLogicalHeight - (logicalTopValue + logicalHeightValue + logicalBottom.calcValue(containerLogicalHeight) + bordersPlusPadding); + const LayoutUnit availableSpace = containerLogicalHeight - (logicalTopValue + logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView) + bordersPlusPadding); // Margins are now the only unknown if (marginBefore.isAuto() && marginAfter.isAuto()) { @@ -3100,16 +3095,16 @@ void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength, marginAfterValue = availableSpace - marginBeforeValue; // account for odd valued differences } else if (marginBefore.isAuto()) { // Solve for top margin - marginAfterValue = marginAfter.calcValue(containerLogicalHeight); + marginAfterValue = valueForLength(marginAfter, containerLogicalHeight, renderView); marginBeforeValue = availableSpace - marginAfterValue; } else if (marginAfter.isAuto()) { // Solve for bottom margin - marginBeforeValue = marginBefore.calcValue(containerLogicalHeight); + marginBeforeValue = valueForLength(marginBefore, containerLogicalHeight, renderView); marginAfterValue = availableSpace - marginBeforeValue; } else { // Over-constrained, (no need solve for bottom) - marginBeforeValue = marginBefore.calcValue(containerLogicalHeight); - marginAfterValue = marginAfter.calcValue(containerLogicalHeight); + marginBeforeValue = valueForLength(marginBefore, containerLogicalHeight, renderView); + marginAfterValue = valueForLength(marginAfter, containerLogicalHeight, renderView); } } else { /*--------------------------------------------------------------------*\ @@ -3138,8 +3133,8 @@ void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength, // because the value is not used for any further calculations. // Calculate margins, 'auto' margins are ignored. - marginBeforeValue = marginBefore.calcMinValue(containerLogicalHeight); - marginAfterValue = marginAfter.calcMinValue(containerLogicalHeight); + marginBeforeValue = minimumValueForLength(marginBefore, containerLogicalHeight, renderView); + marginAfterValue = minimumValueForLength(marginAfter, containerLogicalHeight, renderView); const LayoutUnit availableSpace = containerLogicalHeight - (marginBeforeValue + marginAfterValue + bordersPlusPadding); @@ -3147,23 +3142,23 @@ void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength, if (logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) { // RULE 1: (height is content based, solve of top) logicalHeightValue = contentLogicalHeight; - logicalTopValue = availableSpace - (logicalHeightValue + logicalBottom.calcValue(containerLogicalHeight)); + logicalTopValue = availableSpace - (logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView)); } else if (!logicalTopIsAuto && logicalHeightIsAuto && logicalBottomIsAuto) { // RULE 3: (height is content based, no need solve of bottom) - logicalTopValue = logicalTop.calcValue(containerLogicalHeight); + logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView); logicalHeightValue = contentLogicalHeight; } else if (logicalTopIsAuto && !logicalHeightIsAuto && !logicalBottomIsAuto) { // RULE 4: (solve of top) - logicalHeightValue = computeContentBoxLogicalHeight(logicalHeightLength.calcValue(containerLogicalHeight)); - logicalTopValue = availableSpace - (logicalHeightValue + logicalBottom.calcValue(containerLogicalHeight)); + logicalHeightValue = computeContentBoxLogicalHeight(valueForLength(logicalHeightLength, containerLogicalHeight, renderView)); + logicalTopValue = availableSpace - (logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView)); } else if (!logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) { // RULE 5: (solve of height) - logicalTopValue = logicalTop.calcValue(containerLogicalHeight); - logicalHeightValue = max<LayoutUnit>(0, availableSpace - (logicalTopValue + logicalBottom.calcValue(containerLogicalHeight))); + logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView); + logicalHeightValue = max<LayoutUnit>(0, availableSpace - (logicalTopValue + valueForLength(logicalBottom, containerLogicalHeight, renderView))); } else if (!logicalTopIsAuto && !logicalHeightIsAuto && logicalBottomIsAuto) { // RULE 6: (no need solve of bottom) - logicalHeightValue = computeContentBoxLogicalHeight(logicalHeightLength.calcValue(containerLogicalHeight)); - logicalTopValue = logicalTop.calcValue(containerLogicalHeight); + logicalHeightValue = computeContentBoxLogicalHeight(valueForLength(logicalHeightLength, containerLogicalHeight, renderView)); + logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView); } } @@ -3239,13 +3234,14 @@ void RenderBox::computePositionedLogicalWidthReplaced() \*-----------------------------------------------------------------------*/ LayoutUnit logicalLeftValue = 0; LayoutUnit logicalRightValue = 0; + RenderView* renderView = view(); if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) { // 'left' and 'right' cannot be 'auto' due to step 3 ASSERT(!(logicalLeft.isAuto() && logicalRight.isAuto())); - logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth); - logicalRightValue = logicalRight.calcValue(containerLogicalWidth); + logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView); + logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView); LayoutUnit difference = availableSpace - (logicalLeftValue + logicalRightValue); if (difference > 0) { @@ -3268,39 +3264,39 @@ void RenderBox::computePositionedLogicalWidthReplaced() * that value. \*-----------------------------------------------------------------------*/ } else if (logicalLeft.isAuto()) { - marginLogicalLeftAlias = marginLogicalLeft.calcValue(containerLogicalWidth); - marginLogicalRightAlias = marginLogicalRight.calcValue(containerLogicalWidth); - logicalRightValue = logicalRight.calcValue(containerLogicalWidth); + marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerLogicalWidth, renderView); + marginLogicalRightAlias = valueForLength(marginLogicalRight, containerLogicalWidth, renderView); + logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView); // Solve for 'left' logicalLeftValue = availableSpace - (logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias); } else if (logicalRight.isAuto()) { - marginLogicalLeftAlias = marginLogicalLeft.calcValue(containerLogicalWidth); - marginLogicalRightAlias = marginLogicalRight.calcValue(containerLogicalWidth); - logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth); + marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerLogicalWidth, renderView); + marginLogicalRightAlias = valueForLength(marginLogicalRight, containerLogicalWidth, renderView); + logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView); // Solve for 'right' logicalRightValue = availableSpace - (logicalLeftValue + marginLogicalLeftAlias + marginLogicalRightAlias); } else if (marginLogicalLeft.isAuto()) { - marginLogicalRightAlias = marginLogicalRight.calcValue(containerLogicalWidth); - logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth); - logicalRightValue = logicalRight.calcValue(containerLogicalWidth); + marginLogicalRightAlias = valueForLength(marginLogicalRight, containerLogicalWidth, renderView); + logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView); + logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView); // Solve for 'margin-left' marginLogicalLeftAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalRightAlias); } else if (marginLogicalRight.isAuto()) { - marginLogicalLeftAlias = marginLogicalLeft.calcValue(containerLogicalWidth); - logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth); - logicalRightValue = logicalRight.calcValue(containerLogicalWidth); + marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerLogicalWidth, renderView); + logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView); + logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView); // Solve for 'margin-right' marginLogicalRightAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalLeftAlias); } else { // Nothing is 'auto', just calculate the values. - marginLogicalLeftAlias = marginLogicalLeft.calcValue(containerLogicalWidth); - marginLogicalRightAlias = marginLogicalRight.calcValue(containerLogicalWidth); - logicalRightValue = logicalRight.calcValue(containerLogicalWidth); - logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth); + marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerLogicalWidth, renderView); + marginLogicalRightAlias = valueForLength(marginLogicalRight, containerLogicalWidth, renderView); + logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView); + 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; @@ -3363,6 +3359,7 @@ void RenderBox::computePositionedLogicalHeightReplaced() Length logicalTop = style()->logicalTop(); Length logicalBottom = style()->logicalBottom(); + RenderView* renderView = view(); /*-----------------------------------------------------------------------*\ * 1. The used value of 'height' is determined as for inline replaced @@ -3406,8 +3403,8 @@ void RenderBox::computePositionedLogicalHeightReplaced() // 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combined. ASSERT(!(logicalTop.isAuto() || logicalBottom.isAuto())); - logicalTopValue = logicalTop.calcValue(containerLogicalHeight); - logicalBottomValue = logicalBottom.calcValue(containerLogicalHeight); + logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView); + logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView); LayoutUnit difference = availableSpace - (logicalTopValue + logicalBottomValue); // NOTE: This may result in negative values. @@ -3419,39 +3416,39 @@ void RenderBox::computePositionedLogicalHeightReplaced() * for that value. \*-----------------------------------------------------------------------*/ } else if (logicalTop.isAuto()) { - marginBeforeAlias = marginBefore.calcValue(containerLogicalHeight); - marginAfterAlias = marginAfter.calcValue(containerLogicalHeight); - logicalBottomValue = logicalBottom.calcValue(containerLogicalHeight); + marginBeforeAlias = valueForLength(marginBefore, containerLogicalHeight, renderView); + marginAfterAlias = valueForLength(marginAfter, containerLogicalHeight, renderView); + logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView); // Solve for 'top' logicalTopValue = availableSpace - (logicalBottomValue + marginBeforeAlias + marginAfterAlias); } else if (logicalBottom.isAuto()) { - marginBeforeAlias = marginBefore.calcValue(containerLogicalHeight); - marginAfterAlias = marginAfter.calcValue(containerLogicalHeight); - logicalTopValue = logicalTop.calcValue(containerLogicalHeight); + marginBeforeAlias = valueForLength(marginBefore, containerLogicalHeight, renderView); + marginAfterAlias = valueForLength(marginAfter, containerLogicalHeight, renderView); + logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView); // Solve for 'bottom' // NOTE: It is not necessary to solve for 'bottom' because we don't ever // use the value. } else if (marginBefore.isAuto()) { - marginAfterAlias = marginAfter.calcValue(containerLogicalHeight); - logicalTopValue = logicalTop.calcValue(containerLogicalHeight); - logicalBottomValue = logicalBottom.calcValue(containerLogicalHeight); + marginAfterAlias = valueForLength(marginAfter, containerLogicalHeight, renderView); + logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView); + logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView); // Solve for 'margin-top' marginBeforeAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginAfterAlias); } else if (marginAfter.isAuto()) { - marginBeforeAlias = marginBefore.calcValue(containerLogicalHeight); - logicalTopValue = logicalTop.calcValue(containerLogicalHeight); - logicalBottomValue = logicalBottom.calcValue(containerLogicalHeight); + marginBeforeAlias = valueForLength(marginBefore, containerLogicalHeight, renderView); + logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView); + logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView); // Solve for 'margin-bottom' marginAfterAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginBeforeAlias); } else { // Nothing is 'auto', just calculate the values. - marginBeforeAlias = marginBefore.calcValue(containerLogicalHeight); - marginAfterAlias = marginAfter.calcValue(containerLogicalHeight); - logicalTopValue = logicalTop.calcValue(containerLogicalHeight); + marginBeforeAlias = valueForLength(marginBefore, containerLogicalHeight, renderView); + marginAfterAlias = valueForLength(marginAfter, containerLogicalHeight, renderView); + logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView); // NOTE: It is not necessary to solve for 'bottom' because we don't ever // use the value. } @@ -3529,7 +3526,7 @@ VisiblePosition RenderBox::positionForPoint(const LayoutPoint& point) } // Pass off to the closest child. - LayoutUnit minDist = numeric_limits<LayoutUnit>::max(); + LayoutUnit minDist = MAX_LAYOUT_UNIT; RenderBox* closestRenderer = 0; LayoutPoint adjustedPoint = point; if (isTableRow()) @@ -3545,9 +3542,9 @@ VisiblePosition RenderBox::positionForPoint(const LayoutPoint& point) RenderBox* renderer = toRenderBox(renderObject); - LayoutUnit top = renderer->borderTop() + renderer->paddingTop() + (isTableRow() ? zeroLayoutUnit : renderer->y()); + LayoutUnit top = renderer->borderTop() + renderer->paddingTop() + (isTableRow() ? ZERO_LAYOUT_UNIT : renderer->y()); LayoutUnit bottom = top + renderer->contentHeight(); - LayoutUnit left = renderer->borderLeft() + renderer->paddingLeft() + (isTableRow() ? zeroLayoutUnit : renderer->x()); + LayoutUnit left = renderer->borderLeft() + renderer->paddingLeft() + (isTableRow() ? ZERO_LAYOUT_UNIT : renderer->x()); LayoutUnit right = left + renderer->contentWidth(); if (point.x() <= right && point.x() >= left && point.y() <= top && point.y() >= bottom) { @@ -3600,9 +3597,9 @@ bool RenderBox::shrinkToAvoidFloats() const // Floating objects don't shrink. Objects that don't avoid floats don't shrink. Marquees don't shrink. if ((isInline() && !isHTMLMarquee()) || !avoidsFloats() || isFloating()) return false; - - // All auto-width objects that avoid floats should always use lineWidth. - return style()->width().isAuto(); + + // Only auto width objects can possibly shrink to avoid floats. + return style()->width().isAuto(); } bool RenderBox::avoidsFloats() const @@ -3612,7 +3609,7 @@ bool RenderBox::avoidsFloats() const void RenderBox::addVisualEffectOverflow() { - if (!style()->boxShadow() && !style()->hasBorderImageOutsets() && !style()->hasFilterOutsets()) + if (!style()->boxShadow() && !style()->hasBorderImageOutsets()) return; bool isFlipped = style()->isFlippedBlocksWritingMode(); @@ -3655,21 +3652,6 @@ void RenderBox::addVisualEffectOverflow() overflowMaxY = max(overflowMaxY, borderBox.maxY() + ((!isFlipped || !isHorizontal) ? borderOutsetBottom : borderOutsetTop)); } -#if ENABLE(CSS_FILTERS) - // Compute any filter outset overflow. - if (style()->hasFilterOutsets()) { - LayoutUnit filterOutsetLeft; - LayoutUnit filterOutsetRight; - LayoutUnit filterOutsetTop; - LayoutUnit filterOutsetBottom; - style()->getFilterOutsets(filterOutsetTop, filterOutsetRight, filterOutsetBottom, filterOutsetLeft); - - overflowMinX = min(overflowMinX, borderBox.x() - filterOutsetLeft); - overflowMaxX = max(overflowMaxX, borderBox.maxX() + filterOutsetRight); - overflowMinY = min(overflowMinY, borderBox.y() - filterOutsetTop); - overflowMaxY = max(overflowMaxY, borderBox.maxY() + filterOutsetBottom); - } -#endif // Add in the final overflow with shadows and outsets combined. addVisualOverflow(LayoutRect(overflowMinX, overflowMinY, overflowMaxX - overflowMinX, overflowMaxY - overflowMinY)); } @@ -3733,10 +3715,6 @@ void RenderBox::addLayoutOverflow(const LayoutRect& rect) if (!m_overflow) m_overflow = adoptPtr(new RenderOverflow(clientBox, borderBoxRect())); - // Lazily allocate our layer as we will need it to hold our scroll information. - if (hasOverflowClip()) - ensureLayer(); - m_overflow->addLayoutOverflow(overflowRect); } @@ -4029,4 +4007,78 @@ bool RenderBox::hasRelativeDimensions() const || style()->minHeight().isPercent() || style()->minWidth().isPercent(); } +bool RenderBox::hasRelativeLogicalHeight() const +{ + return style()->logicalHeight().isPercent() + || style()->logicalMinHeight().isPercent() + || style()->logicalMaxHeight().isPercent(); +} + +void RenderBox::moveChildTo(RenderBox* toBox, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert) +{ + ASSERT(this == child->parent()); + ASSERT(!beforeChild || toBox == beforeChild->parent()); + if (fullRemoveInsert && toBox->isRenderBlock()) { + // Takes care of adding the new child correctly if toBlock and fromBlock + // have different kind of children (block vs inline). + toBox->addChild(virtualChildren()->removeChildNode(this, child), beforeChild); + } else + toBox->virtualChildren()->insertChildNode(toBox, virtualChildren()->removeChildNode(this, child, fullRemoveInsert), beforeChild, fullRemoveInsert); +} + +void RenderBox::moveChildrenTo(RenderBox* toBox, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert) +{ + ASSERT(!beforeChild || toBox == beforeChild->parent()); + for (RenderObject* child = startChild; child && child != endChild; ) { + // Save our next sibling as moveChildTo will clear it. + RenderObject* nextSibling = child->nextSibling(); + moveChildTo(toBox, child, beforeChild, fullRemoveInsert); + child = nextSibling; + } +} + +static void markBoxForRelayoutAfterSplit(RenderBox* box) +{ + // FIXME: The table code should handle that automatically. If not, + // we should fix it and remove the table part checks. + if (box->isTable()) + toRenderTable(box)->setNeedsSectionRecalc(); + else if (box->isTableSection()) + toRenderTableSection(box)->setNeedsCellRecalc(); + + box->setNeedsLayoutAndPrefWidthsRecalc(); +} + +RenderObject* RenderBox::splitAnonymousBoxesAroundChild(RenderObject* beforeChild) +{ + bool didSplitParentAnonymousBoxes = false; + + while (beforeChild->parent() != this) { + RenderBox* boxToSplit = toRenderBox(beforeChild->parent()); + if (boxToSplit->firstChild() != beforeChild && boxToSplit->isAnonymous()) { + didSplitParentAnonymousBoxes = true; + + // We have to split the parent box into two boxes and move children + // from |beforeChild| to end into the new post box. + RenderBox* postBox = boxToSplit->createAnonymousBoxWithSameTypeAs(this); + postBox->setChildrenInline(boxToSplit->childrenInline()); + RenderBox* parentBox = toRenderBox(boxToSplit->parent()); + parentBox->virtualChildren()->insertChildNode(parentBox, postBox, boxToSplit->nextSibling()); + boxToSplit->moveChildrenTo(postBox, beforeChild, 0, boxToSplit->hasLayer()); + + markBoxForRelayoutAfterSplit(boxToSplit); + markBoxForRelayoutAfterSplit(postBox); + + beforeChild = postBox; + } else + beforeChild = boxToSplit; + } + + if (didSplitParentAnonymousBoxes) + markBoxForRelayoutAfterSplit(this); + + ASSERT(beforeChild->parent() == this); + return beforeChild; +} + } // namespace WebCore |