diff options
Diffstat (limited to 'Source/WebCore/rendering/RenderBox.cpp')
-rw-r--r-- | Source/WebCore/rendering/RenderBox.cpp | 91 |
1 files changed, 67 insertions, 24 deletions
diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp index f3ca0b1d1..d21c2405d 100644 --- a/Source/WebCore/rendering/RenderBox.cpp +++ b/Source/WebCore/rendering/RenderBox.cpp @@ -746,6 +746,13 @@ bool RenderBox::needsPreferredWidthsRecalculation() const return style()->paddingStart().isPercent() || style()->paddingEnd().isPercent(); } +IntSize RenderBox::scrolledContentOffset() const +{ + ASSERT(hasOverflowClip()); + ASSERT(hasLayer()); + return layer()->scrolledContentOffset(); +} + LayoutUnit RenderBox::minPreferredLogicalWidth() const { if (preferredLogicalWidthsDirty()) @@ -917,11 +924,12 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& pai // balloon layout is an example of this). borderFitAdjust(paintRect); + BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context); + // FIXME: Should eventually give the theme control over whether the box shadow should paint, since controls could have // custom shadows of their own. - paintBoxShadow(paintInfo, paintRect, style(), Normal); - - BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context); + if (!boxShadowShouldBeAppliedToBackground(bleedAvoidance)) + paintBoxShadow(paintInfo, paintRect, style(), Normal); GraphicsContextStateSaver stateSaver(*paintInfo.context, false); if (bleedAvoidance == BackgroundBleedUseTransparencyLayer) { @@ -941,12 +949,12 @@ void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& pai paintBackground(paintInfo, paintRect, bleedAvoidance); if (style()->hasAppearance()) - theme()->paintDecorations(this, paintInfo, paintRect); + theme()->paintDecorations(this, paintInfo, pixelSnappedIntRect(paintRect)); } 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, paintRect))) && style()->hasBorder()) + if ((!style()->hasAppearance() || (!themePainted && theme()->paintBorderOnly(this, paintInfo, pixelSnappedIntRect(paintRect)))) && style()->hasBorder()) paintBorder(paintInfo, paintRect, style(), bleedAvoidance); if (bleedAvoidance == BackgroundBleedUseTransparencyLayer) @@ -1186,7 +1194,7 @@ bool RenderBox::pushContentsClip(PaintInfo& paintInfo, const LayoutPoint& accumu paintObject(paintInfo, accumulatedOffset); paintInfo.phase = PaintPhaseChildBlockBackgrounds; } - IntRect clipRect(isControlClip ? controlClipRect(accumulatedOffset) : overflowClipRect(accumulatedOffset, paintInfo.renderRegion)); + IntRect clipRect = pixelSnappedIntRect(isControlClip ? controlClipRect(accumulatedOffset) : overflowClipRect(accumulatedOffset, paintInfo.renderRegion)); paintInfo.context->save(); if (style()->hasBorderRadius()) paintInfo.context->addRoundedRectClip(style()->getRoundedInnerBorderFor(LayoutRect(accumulatedOffset, size()))); @@ -1251,11 +1259,50 @@ LayoutRect RenderBox::clipRect(const LayoutPoint& location, RenderRegion* region return clipRect; } +LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) +{ + RenderRegion* containingBlockRegion = 0; + LayoutUnit logicalTopPosition = logicalTop(); + LayoutUnit adjustedPageOffsetForContainingBlock = offsetFromLogicalTopOfFirstPage - logicalTop(); + if (region) { + LayoutUnit offsetFromLogicalTopOfRegion = region ? region->offsetFromLogicalTopOfFirstPage() - offsetFromLogicalTopOfFirstPage : 0; + logicalTopPosition = max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion); + containingBlockRegion = cb->clampToStartAndEndRegions(region); + } + + LayoutUnit result = cb->availableLogicalWidthForLine(logicalTopPosition, false, containingBlockRegion, adjustedPageOffsetForContainingBlock) - childMarginStart - childMarginEnd; + + // We need to see if margins on either the start side or the end side can contain the floats in question. If they can, + // then just using the line width is inaccurate. In the case where a float completely fits, we don't need to use the line + // offset at all, but can instead push all the way to the content edge of the containing block. In the case where the float + // doesn't fit, we can use the line offset, but we need to grow it by the margin to reflect the fact that the margin was + // "consumed" by the float. Negative margins aren't consumed by the float, and so we ignore them. + if (childMarginStart > 0) { + LayoutUnit startContentSide = cb->startOffsetForContent(containingBlockRegion, adjustedPageOffsetForContainingBlock); + LayoutUnit startContentSideWithMargin = startContentSide + childMarginStart; + LayoutUnit startOffset = cb->startOffsetForLine(logicalTopPosition, false, containingBlockRegion, adjustedPageOffsetForContainingBlock); + if (startOffset > startContentSideWithMargin) + result += childMarginStart; + else + result += startOffset - startContentSide; + } + + if (childMarginEnd > 0) { + LayoutUnit endContentSide = cb->endOffsetForContent(containingBlockRegion, adjustedPageOffsetForContainingBlock); + LayoutUnit endContentSideWithMargin = endContentSide + childMarginEnd; + LayoutUnit endOffset = cb->endOffsetForLine(logicalTopPosition, false, containingBlockRegion, adjustedPageOffsetForContainingBlock); + if (endOffset > endContentSideWithMargin) + result += childMarginEnd; + else + result += endOffset - endContentSide; + } + + return result; +} + LayoutUnit RenderBox::containingBlockLogicalWidthForContent() const { RenderBlock* cb = containingBlock(); - if (shrinkToAvoidFloats() && !inRenderFlowThread()) - return cb->availableLogicalWidthForLine(logicalTop(), false); return cb->availableLogicalWidth(); } @@ -1266,10 +1313,6 @@ LayoutUnit RenderBox::containingBlockLogicalWidthForContentInRegion(RenderRegion RenderBlock* cb = containingBlock(); RenderRegion* containingBlockRegion = cb->clampToStartAndEndRegions(region); - if (shrinkToAvoidFloats()) { - LayoutUnit offsetFromLogicalTopOfRegion = region->offsetFromLogicalTopOfFirstPage() - offsetFromLogicalTopOfFirstPage; - return cb->availableLogicalWidthForLine(max(logicalTop(), logicalTop() + offsetFromLogicalTopOfRegion), false, containingBlockRegion, offsetFromLogicalTopOfFirstPage - logicalTop()); - } LayoutUnit result = cb->availableLogicalWidth(); RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(containingBlockRegion, offsetFromLogicalTopOfFirstPage - logicalTop()); if (!boxInfo) @@ -1397,7 +1440,7 @@ LayoutSize RenderBox::offsetFromContainer(RenderObject* o, const LayoutPoint& po } if (o->hasOverflowClip()) - offset -= toRenderBox(o)->layer()->scrolledContentOffset(); + offset -= toRenderBox(o)->scrolledContentOffset(); if (style()->position() == AbsolutePosition && o->isRelPositioned() && o->isRenderInline()) offset += toRenderInline(o)->relativePositionedInlineOffset(this); @@ -1596,7 +1639,7 @@ void RenderBox::computeRectForRepaint(RenderBoxModelObject* repaintContainer, La // o->height() is inaccurate if we're in the middle of a layout of |o|, so use the // layer's size instead. Even if the layer's size is wrong, the layer itself will repaint // anyway if its size does change. - topLeft -= containerBox->layer()->scrolledContentOffset(); // For overflow:auto/scroll/hidden. + topLeft -= containerBox->scrolledContentOffset(); // For overflow:auto/scroll/hidden. LayoutRect repaintRect(topLeft, rect.size()); LayoutRect boxRect(LayoutPoint(), containerBox->layer()->size()); @@ -1691,11 +1734,11 @@ void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit off setLogicalWidth(logicalWidthLength.value() + borderAndPaddingLogicalWidth()); else { // Calculate LogicalWidth - setLogicalWidth(computeLogicalWidthUsing(LogicalWidth, containerWidthInInlineDirection)); + setLogicalWidth(computeLogicalWidthInRegionUsing(LogicalWidth, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage)); // Calculate MaxLogicalWidth if (!styleToUse->logicalMaxWidth().isUndefined()) { - LayoutUnit maxLogicalWidth = computeLogicalWidthUsing(MaxLogicalWidth, containerWidthInInlineDirection); + LayoutUnit maxLogicalWidth = computeLogicalWidthInRegionUsing(MaxLogicalWidth, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage); if (logicalWidth() > maxLogicalWidth) { setLogicalWidth(maxLogicalWidth); logicalWidthLength = styleToUse->logicalMaxWidth(); @@ -1703,7 +1746,7 @@ void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit off } // Calculate MinLogicalWidth - LayoutUnit minLogicalWidth = computeLogicalWidthUsing(MinLogicalWidth, containerWidthInInlineDirection); + LayoutUnit minLogicalWidth = computeLogicalWidthInRegionUsing(MinLogicalWidth, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage); if (logicalWidth() < minLogicalWidth) { setLogicalWidth(minLogicalWidth); logicalWidthLength = styleToUse->logicalMinWidth(); @@ -1728,7 +1771,8 @@ void RenderBox::computeLogicalWidthInRegion(RenderRegion* region, LayoutUnit off cb->setMarginEndForChild(this, containerLogicalWidth - logicalWidth() - cb->marginStartForChild(this)); } -LayoutUnit RenderBox::computeLogicalWidthUsing(LogicalWidthType widthType, LayoutUnit availableLogicalWidth) +LayoutUnit RenderBox::computeLogicalWidthInRegionUsing(LogicalWidthType widthType, LayoutUnit availableLogicalWidth, + const RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) { LayoutUnit logicalWidthResult = logicalWidth(); RenderStyle* styleToUse = style(); @@ -1745,6 +1789,9 @@ LayoutUnit RenderBox::computeLogicalWidthUsing(LogicalWidthType widthType, Layou LayoutUnit marginEnd = styleToUse->marginEnd().calcMinValue(availableLogicalWidth); logicalWidthResult = availableLogicalWidth - marginStart - marginEnd; + if (shrinkToAvoidFloats() && cb->containsFloats()) + logicalWidthResult = shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, cb, region, offsetFromLogicalTopOfFirstPage); + if (sizesToIntrinsicLogicalWidth(widthType)) { logicalWidthResult = max(logicalWidthResult, minPreferredLogicalWidth()); logicalWidthResult = min(logicalWidthResult, maxPreferredLogicalWidth()); @@ -1997,7 +2044,6 @@ void RenderBox::computeLogicalHeight() LayoutUnit heightResult; if (checkMinMaxHeight) { heightResult = computeLogicalHeightUsing(styleToUse->logicalHeight()); - // FIXME: Use < 0 or roughlyEquals when we move to float, see https://bugs.webkit.org/show_bug.cgi?id=66148 if (heightResult == -1) heightResult = logicalHeight(); LayoutUnit minH = computeLogicalHeightUsing(styleToUse->logicalMinHeight()); // Leave as -1 if unset. @@ -2056,7 +2102,6 @@ LayoutUnit RenderBox::computeLogicalHeightUsing(const Length& h) logicalHeight = h.value(); else if (h.isPercent()) logicalHeight = computePercentageLogicalHeight(h); - // FIXME: Use < 0 or roughlyEquals when we move to float, see https://bugs.webkit.org/show_bug.cgi?id=66148 if (logicalHeight != -1) { logicalHeight = computeBorderBoxLogicalHeight(logicalHeight); return logicalHeight; @@ -2123,7 +2168,6 @@ LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height) else if (cbstyle->logicalHeight().isPercent() && !isPositionedWithSpecifiedHeight) { // We need to recur and compute the percentage height for our containing block. result = cb->computePercentageLogicalHeight(cbstyle->logicalHeight()); - // FIXME: Use < 0 or roughlyEquals when we move to float, see https://bugs.webkit.org/show_bug.cgi?id=66148 if (result != -1) result = cb->computeContentBoxLogicalHeight(result); } else if (cb->isRenderView() || (cb->isBody() && document()->inQuirksMode()) || isPositionedWithSpecifiedHeight) { @@ -2138,7 +2182,6 @@ LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height) // always. Note we could only hit this case by recurring into computePercentageLogicalHeight on a positioned containing block. result = cb->computeContentBoxLogicalHeight(cb->availableLogicalHeight()); - // FIXME: Use < 0 or roughlyEquals when we move to float, see https://bugs.webkit.org/show_bug.cgi?id=66148 if (result != -1) { result = height.calcValue(result); if (includeBorderPadding) { @@ -3444,9 +3487,9 @@ VisiblePosition RenderBox::positionForPoint(const LayoutPoint& point) RenderBox* renderer = toRenderBox(renderObject); - LayoutUnit top = renderer->borderTop() + renderer->paddingTop() + (isTableRow() ? 0 : renderer->y()); + LayoutUnit top = renderer->borderTop() + renderer->paddingTop() + (isTableRow() ? zeroLayoutUnit : renderer->y()); LayoutUnit bottom = top + renderer->contentHeight(); - LayoutUnit left = renderer->borderLeft() + renderer->paddingLeft() + (isTableRow() ? 0 : renderer->x()); + LayoutUnit left = renderer->borderLeft() + renderer->paddingLeft() + (isTableRow() ? zeroLayoutUnit : renderer->x()); LayoutUnit right = left + renderer->contentWidth(); if (point.x() <= right && point.x() >= left && point.y() <= top && point.y() >= bottom) { |