Diff
Modified: tags/Safari-537.35.3/LayoutTests/ChangeLog (147179 => 147180)
--- tags/Safari-537.35.3/LayoutTests/ChangeLog 2013-03-28 23:09:03 UTC (rev 147179)
+++ tags/Safari-537.35.3/LayoutTests/ChangeLog 2013-03-28 23:12:50 UTC (rev 147180)
@@ -1,5 +1,21 @@
2013-03-28 Lucas Forschler <[email protected]>
+ Merge r146955
+
+ 2013-03-26 Antti Koivisto <[email protected]>
+
+ Test if non-immediate descendants obscure background
+ https://bugs.webkit.org/show_bug.cgi?id=113137
+
+ Reviewed by Simon Fraser.
+
+ * fast/backgrounds/obscured-background-child-style-change-expected.html:
+ * fast/backgrounds/obscured-background-child-style-change.html:
+ * fast/repaint/obscured-background-no-repaint-expected.txt:
+ * fast/repaint/obscured-background-no-repaint.html:
+
+2013-03-28 Lucas Forschler <[email protected]>
+
Merge r147018
2013-03-22 Geoffrey Garen <[email protected]>
Modified: tags/Safari-537.35.3/LayoutTests/fast/backgrounds/obscured-background-child-style-change-expected.html (147179 => 147180)
--- tags/Safari-537.35.3/LayoutTests/fast/backgrounds/obscured-background-child-style-change-expected.html 2013-03-28 23:09:03 UTC (rev 147179)
+++ tags/Safari-537.35.3/LayoutTests/fast/backgrounds/obscured-background-child-style-change-expected.html 2013-03-28 23:12:50 UTC (rev 147180)
@@ -7,7 +7,7 @@
}
.child {
position: relative;
- background-color: rgba(0,255,0,0.2);
+ background-color: rgba(0,255,0,0.8);
width: 100px;
height: 100px;
}
@@ -16,3 +16,17 @@
<div class=child>
</div>
</div>
+<div class=parent>
+ <div>
+ <div class=child>
+ </div>
+ </div>
+</div>
+<script>
+document.body.offsetTop;
+if (window.testRunner)
+ testRunner.display();
+var children = document.getElementsByClassName("child");
+children[0].style.backgroundColor = "rgba(0,255,0,0.5)";
+children[1].style.backgroundColor = "rgba(0,255,0,0.5)";
+</script>
Modified: tags/Safari-537.35.3/LayoutTests/fast/backgrounds/obscured-background-child-style-change.html (147179 => 147180)
--- tags/Safari-537.35.3/LayoutTests/fast/backgrounds/obscured-background-child-style-change.html 2013-03-28 23:09:03 UTC (rev 147179)
+++ tags/Safari-537.35.3/LayoutTests/fast/backgrounds/obscured-background-child-style-change.html 2013-03-28 23:12:50 UTC (rev 147180)
@@ -6,17 +6,26 @@
height: 100px;
}
.child {
- position: relative;
background-color: red;
width: 100px;
height: 100px;
}
</style>
<div class=parent>
-<div class=child>
+ <div class=child>
+ </div>
</div>
+<div class=parent>
+ <div>
+ <div class=child>
+ </div>
+ </div>
</div>
<script>
document.body.offsetTop;
-document.getElementsByClassName("child")[0].style.backgroundColor = "rgba(0,255,0,0.2)";
+if (window.testRunner)
+ testRunner.display();
+var children = document.getElementsByClassName("child");
+children[0].style.backgroundColor = "rgba(0,255,0,0.5)";
+children[1].style.backgroundColor = "rgba(0,255,0,0.5)";
</script>
Modified: tags/Safari-537.35.3/LayoutTests/fast/repaint/obscured-background-no-repaint-expected.txt (147179 => 147180)
--- tags/Safari-537.35.3/LayoutTests/fast/repaint/obscured-background-no-repaint-expected.txt 2013-03-28 23:09:03 UTC (rev 147179)
+++ tags/Safari-537.35.3/LayoutTests/fast/repaint/obscured-background-no-repaint-expected.txt 2013-03-28 23:12:50 UTC (rev 147180)
@@ -8,3 +8,5 @@
TEST COMPLETE
+
+
Modified: tags/Safari-537.35.3/LayoutTests/fast/repaint/obscured-background-no-repaint.html (147179 => 147180)
--- tags/Safari-537.35.3/LayoutTests/fast/repaint/obscured-background-no-repaint.html 2013-03-28 23:09:03 UTC (rev 147179)
+++ tags/Safari-537.35.3/LayoutTests/fast/repaint/obscured-background-no-repaint.html 2013-03-28 23:12:50 UTC (rev 147180)
@@ -34,6 +34,15 @@
#test3 img {
background-image: url(resources/animated.gif)
}
+ #test4 .parent {
+ position: relative;
+ height: 100px;
+ width: 100px;
+ background-color: red;
+ background-repeat: no-repeat;
+ background-position: center;
+ background-image: url(resources/animated.gif)
+ }
</style>
<script>
description("Test that obscured animated gif does not trigger repaints. This test requires DRT.");
@@ -81,6 +90,16 @@
<div id="test3">
<img src=""
</div>
+<div id="test4">
+ <div class="parent">
+ <a>
+ <div></div>
+ <div>
+ <img src=""
+ </div>
+ </a>
+ </div>
+</div>
</body>
<script src=""
</html>
Modified: tags/Safari-537.35.3/Source/WebCore/ChangeLog (147179 => 147180)
--- tags/Safari-537.35.3/Source/WebCore/ChangeLog 2013-03-28 23:09:03 UTC (rev 147179)
+++ tags/Safari-537.35.3/Source/WebCore/ChangeLog 2013-03-28 23:12:50 UTC (rev 147180)
@@ -1,5 +1,51 @@
2013-03-28 Lucas Forschler <[email protected]>
+ Merge r146955
+
+ 2013-03-26 Antti Koivisto <[email protected]>
+
+ Test if non-immediate descendants obscure background
+ https://bugs.webkit.org/show_bug.cgi?id=113137
+
+ Reviewed by Simon Fraser.
+
+ The current obscuration test only covers immediate children. We can find more cases by looking deeper into descendants.
+
+ The patch makes the test sufficiently smart to stop a heavy fully obscured gif animation on micrsoft.com.
+
+ * loader/cache/CachedImage.cpp:
+ (WebCore::CachedImage::animationAdvanced):
+ * rendering/RenderBox.cpp:
+ (WebCore::RenderBox::styleDidChange):
+
+ Invalidate parents to max test depth.
+
+ (WebCore::RenderBox::backgroundPaintedExtent):
+
+ Background painting is pixel snapped.
+
+ (WebCore::isCandidateForOpaquenessTest):
+ (WebCore::RenderBox::foregroundIsKnownToBeOpaqueInRect):
+
+ Separate foreground testing and make it recursive.
+ Add fast bailout for common static positioned case.
+ Remove maximum child count, the fast bailouts should prevent long tests.
+ Add maximum depth so we know how deep we need to invalidate in styleDidChange.
+
+ (WebCore::RenderBox::computeBackgroundIsKnownToBeObscured):
+ (WebCore):
+ * rendering/RenderBox.h:
+ (RenderBox):
+ * rendering/RenderImage.cpp:
+ (WebCore::RenderImage::foregroundIsKnownToBeOpaqueInRect):
+ (WebCore):
+ (WebCore::RenderImage::computeBackgroundIsKnownToBeObscured):
+
+ * rendering/RenderImage.h:
+ (RenderImage):
+
+2013-03-28 Lucas Forschler <[email protected]>
+
Merge r147050
2013-03-27 Ryosuke Niwa <[email protected]>
Modified: tags/Safari-537.35.3/Source/WebCore/rendering/RenderBox.cpp (147179 => 147180)
--- tags/Safari-537.35.3/Source/WebCore/rendering/RenderBox.cpp 2013-03-28 23:09:03 UTC (rev 147179)
+++ tags/Safari-537.35.3/Source/WebCore/rendering/RenderBox.cpp 2013-03-28 23:12:50 UTC (rev 147180)
@@ -89,6 +89,7 @@
// Size of border belt for autoscroll. When mouse pointer in border belt,
// autoscroll is started.
static const int autoscrollBeltSize = 20;
+static const unsigned backgroundObscurationTestMaxDepth = 4;
bool RenderBox::s_hadOverflowClip = false;
@@ -283,8 +284,13 @@
}
// Our opaqueness might have changed without triggering layout.
- if (parent() && (diff == StyleDifferenceRepaint || diff == StyleDifferenceRepaintLayer))
- parent()->invalidateBackgroundObscurationStatus();
+ if (diff == StyleDifferenceRepaint || diff == StyleDifferenceRepaintLayer) {
+ RenderObject* parentToInvalidate = parent();
+ for (unsigned i = 0; i < backgroundObscurationTestMaxDepth && parentToInvalidate; ++i) {
+ parentToInvalidate->invalidateBackgroundObscurationStatus();
+ parentToInvalidate = parentToInvalidate->parent();
+ }
+ }
bool isBodyRenderer = isBody();
bool isRootRenderer = isRoot();
@@ -1150,7 +1156,7 @@
LayoutRect RenderBox::backgroundPaintedExtent() const
{
ASSERT(hasBackground());
- LayoutRect backgroundRect = borderBoxRect();
+ LayoutRect backgroundRect = pixelSnappedIntRect(borderBoxRect());
Color backgroundColor = style()->visitedDependentColor(CSSPropertyBackgroundColor);
if (backgroundColor.isValid() && backgroundColor.alpha())
@@ -1196,52 +1202,74 @@
return backgroundRect.contains(localRect);
}
-bool RenderBox::computeBackgroundIsKnownToBeObscured()
+static bool isCandidateForOpaquenessTest(RenderBox* childBox)
{
- // Test to see if the children trivially obscure the background.
- // FIXME: This test can be much more comprehensive.
- if (!hasBackground())
+ RenderStyle* childStyle = childBox->style();
+ if (childStyle->position() != StaticPosition && childBox->containingBlock() != childBox->parent())
return false;
- // Table and root background painting is special.
- if (isTable() || isRoot())
+ if (childStyle->visibility() != VISIBLE || childStyle->shapeOutside())
return false;
+ if (!childBox->width() || !childBox->height())
+ return false;
+ if (RenderLayer* childLayer = childBox->layer()) {
+#if USE(ACCELERATED_COMPOSITING)
+ if (childLayer->isComposited())
+ return false;
+#endif
+ // FIXME: Deal with z-index.
+ if (!childStyle->hasAutoZIndex())
+ return false;
+ if (childLayer->hasTransform() || childLayer->isTransparent() || childLayer->hasFilter())
+ return false;
+ }
+ return true;
+}
- LayoutRect backgroundRect = backgroundPaintedExtent();
- // If we don't find a covering child fast there probably isn't one.
- static const unsigned maximumChildrenCountToTest = 4;
- unsigned count = 0;
+bool RenderBox::foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, unsigned maxDepthToTest) const
+{
+ if (!maxDepthToTest)
+ return false;
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (++count > maximumChildrenCountToTest)
- break;
if (!child->isBox())
continue;
RenderBox* childBox = toRenderBox(child);
- RenderStyle* childStyle = child->style();
- if (childStyle->visibility() != VISIBLE || childStyle->shapeOutside())
+ if (!isCandidateForOpaquenessTest(childBox))
continue;
- if (childStyle->position() != StaticPosition && childBox->containingBlock() != this)
- continue;
LayoutPoint childLocation = childBox->location();
if (childBox->isRelPositioned())
childLocation.move(childBox->relativePositionOffset());
- LayoutRect childLocalBackgroundRect = backgroundRect;
- childLocalBackgroundRect.moveBy(-childLocation);
- if (RenderLayer* childLayer = childBox->layer()) {
-#if USE(ACCELERATED_COMPOSITING)
- if (childLayer->isComposited())
- continue;
-#endif
- if (childLayer->zIndex() < 0)
- continue;
- if (childLayer->hasTransform() || childLayer->isTransparent())
- continue;
+ LayoutRect childLocalRect = localRect;
+ childLocalRect.moveBy(-childLocation);
+ if (childLocalRect.y() < 0 || childLocalRect.x() < 0) {
+ // If there is unobscured area above/left of a static positioned box then the rect is probably not covered.
+ if (childBox->style()->position() == StaticPosition)
+ return false;
+ continue;
}
- if (childBox->backgroundIsKnownToBeOpaqueInRect(childLocalBackgroundRect))
+ if (childLocalRect.maxY() > childBox->height() || childLocalRect.maxX() > childBox->width())
+ continue;
+ if (childBox->backgroundIsKnownToBeOpaqueInRect(childLocalRect))
return true;
+ if (childBox->foregroundIsKnownToBeOpaqueInRect(childLocalRect, maxDepthToTest - 1))
+ return true;
}
return false;
}
+bool RenderBox::computeBackgroundIsKnownToBeObscured()
+{
+ // Test to see if the children trivially obscure the background.
+ // FIXME: This test can be much more comprehensive.
+ if (!hasBackground())
+ return false;
+ // Table and root background painting is special.
+ if (isTable() || isRoot())
+ return false;
+
+ LayoutRect backgroundRect = backgroundPaintedExtent();
+ return foregroundIsKnownToBeOpaqueInRect(backgroundRect, backgroundObscurationTestMaxDepth);
+}
+
bool RenderBox::backgroundHasOpaqueTopLayer() const
{
const FillLayer* fillLayer = style()->backgroundLayers();
Modified: tags/Safari-537.35.3/Source/WebCore/rendering/RenderBox.h (147179 => 147180)
--- tags/Safari-537.35.3/Source/WebCore/rendering/RenderBox.h 2013-03-28 23:09:03 UTC (rev 147179)
+++ tags/Safari-537.35.3/Source/WebCore/rendering/RenderBox.h 2013-03-28 23:12:50 UTC (rev 147180)
@@ -594,7 +594,9 @@
virtual void updateFromStyle() OVERRIDE;
LayoutRect backgroundPaintedExtent() const;
+ virtual bool foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, unsigned maxDepthToTest) const;
virtual bool computeBackgroundIsKnownToBeObscured() OVERRIDE;
+
void paintBackground(const PaintInfo&, const LayoutRect&, BackgroundBleedAvoidance = BackgroundBleedNone);
void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, BackgroundBleedAvoidance, CompositeOperator, RenderObject* backgroundObject);
Modified: tags/Safari-537.35.3/Source/WebCore/rendering/RenderImage.cpp (147179 => 147180)
--- tags/Safari-537.35.3/Source/WebCore/rendering/RenderImage.cpp 2013-03-28 23:09:03 UTC (rev 147179)
+++ tags/Safari-537.35.3/Source/WebCore/rendering/RenderImage.cpp 2013-03-28 23:12:50 UTC (rev 147180)
@@ -484,13 +484,15 @@
return !const_cast<RenderImage*>(this)->backgroundIsKnownToBeObscured();
}
-bool RenderImage::computeBackgroundIsKnownToBeObscured()
+bool RenderImage::foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, unsigned maxDepthToTest) const
{
+ UNUSED_PARAM(maxDepthToTest);
if (!m_imageResource->hasImage() || m_imageResource->errorOccurred())
return false;
if (m_imageResource->cachedImage() && !m_imageResource->cachedImage()->isLoaded())
return false;
-
+ if (!contentBoxRect().contains(localRect))
+ return false;
EFillBox backgroundClip = style()->backgroundClip();
// Background paints under borders.
if (backgroundClip == BorderFillBox && style()->hasBorder() && !borderObscuresBackground())
@@ -498,11 +500,17 @@
// Background shows in padding area.
if ((backgroundClip == BorderFillBox || backgroundClip == PaddingFillBox) && style()->hasPadding())
return false;
-
// Check for image with alpha.
return m_imageResource->cachedImage() && m_imageResource->cachedImage()->currentFrameKnownToBeOpaque(this);
}
+bool RenderImage::computeBackgroundIsKnownToBeObscured()
+{
+ if (!hasBackground())
+ return false;
+ return foregroundIsKnownToBeOpaqueInRect(backgroundPaintedExtent(), 0);
+}
+
LayoutUnit RenderImage::minimumReplacedHeight() const
{
return m_imageResource->errorOccurred() ? intrinsicSize().height() : LayoutUnit();
Modified: tags/Safari-537.35.3/Source/WebCore/rendering/RenderImage.h (147179 => 147180)
--- tags/Safari-537.35.3/Source/WebCore/rendering/RenderImage.h 2013-03-28 23:09:03 UTC (rev 147179)
+++ tags/Safari-537.35.3/Source/WebCore/rendering/RenderImage.h 2013-03-28 23:12:50 UTC (rev 147180)
@@ -86,6 +86,7 @@
virtual void paintReplaced(PaintInfo&, const LayoutPoint&);
+ virtual bool foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, unsigned maxDepthToTest) const OVERRIDE;
virtual bool computeBackgroundIsKnownToBeObscured() OVERRIDE;
virtual LayoutUnit minimumReplacedHeight() const OVERRIDE;