Bug 1062870 - Restore the post-filter dirtyRect after building the filtered display items. r=roc
authorMarkus Stange <mstange@themasta.com>
Tue, 09 Sep 2014 17:14:47 +0200
changeset 227596 cc2245e496e7649df27aaccccdd2a8801b38a5d7
parent 227595 7c5219e1fa26337acf0076db4145f81df1cb5a15
child 227597 91c108dfb3f66e868e91b053eaa39bb9078a6a7a
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs1062870
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1062870 - Restore the post-filter dirtyRect after building the filtered display items. r=roc
layout/generic/nsFrame.cpp
layout/reftests/bugs/1059498-2.html
layout/reftests/bugs/1059498-3.html
layout/reftests/bugs/reftest.list
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1931,16 +1931,17 @@ nsIFrame::BuildDisplayListForStackingCon
   bool inTransform = aBuilder->IsInTransform();
   bool isTransformed = IsTransformed();
   // reset blend mode so we can keep track if this stacking context needs have
   // a nsDisplayBlendContainer. Set the blend mode back when the routine exits
   // so we keep track if the parent stacking context needs a container too.
   AutoSaveRestoreBlendMode autoRestoreBlendMode(*aBuilder);
   aBuilder->SetContainsBlendModes(BlendModeSet());
  
+  nsRect dirtyRectOutsideTransform = dirtyRect;
   if (isTransformed) {
     const nsRect overflow = GetVisualOverflowRectRelativeToSelf();
     if (aBuilder->IsForPainting() &&
         nsDisplayTransform::ShouldPrerenderTransformedContent(aBuilder, this)) {
       dirtyRect = overflow;
     } else {
       if (overflow.IsEmpty() && !Preserves3DChildren()) {
         return;
@@ -1955,16 +1956,17 @@ nsIFrame::BuildDisplayListForStackingCon
         // This should only happen if the transform is singular, in which case nothing is visible anyway
         dirtyRect.SetEmpty();
       }
     }
     inTransform = true;
   }
 
   bool usingSVGEffects = nsSVGIntegrationUtils::UsingEffectsForFrame(this);
+  nsRect dirtyRectOutsideSVGEffects = dirtyRect;
   if (usingSVGEffects) {
     dirtyRect =
       nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect);
   }
 
   bool useOpacity = HasVisualOpacity() && !nsSVGUtils::CanOptimizeOpacity(this);
   bool useBlendMode = disp->mMixBlendMode != NS_STYLE_BLEND_NORMAL;
   bool useStickyPosition = disp->mPosition == NS_STYLE_POSITION_STICKY &&
@@ -2077,16 +2079,18 @@ nsIFrame::BuildDisplayListForStackingCon
   }
 
   /* If there are any SVG effects, wrap the list up in an SVG effects item
    * (which also handles CSS group opacity). Note that we create an SVG effects
    * item even if resultList is empty, since a filter can produce graphical
    * output even if the element being filtered wouldn't otherwise do so.
    */
   if (usingSVGEffects) {
+    // Revert to the post-filter dirty rect.
+    buildingDisplayList.SetDirtyRect(dirtyRectOutsideSVGEffects);
     /* List now emptied, so add the new list to the top. */
     resultList.AppendNewToTop(
         new (aBuilder) nsDisplaySVGEffects(aBuilder, this, &resultList));
   }
   /* Else, if the list is non-empty and there is CSS group opacity without SVG
    * effects, wrap it up in an opacity item.
    */
   else if (useOpacity && !resultList.IsEmpty()) {
@@ -2111,17 +2115,17 @@ nsIFrame::BuildDisplayListForStackingCon
    * We also traverse into sublists created by nsDisplayWrapList or nsDisplayOpacity, so that
    * we find all the correct children.
    */
   if (isTransformed && !resultList.IsEmpty()) {
     // Restore clip state now so nsDisplayTransform is clipped properly.
     clipState.Restore();
     // Revert to the dirtyrect coming in from the parent, without our transform
     // taken into account.
-    buildingDisplayList.SetDirtyRect(aDirtyRect);
+    buildingDisplayList.SetDirtyRect(dirtyRectOutsideTransform);
     // Revert to the outer reference frame and offset because all display
     // items we create from now on are outside the transform.
     const nsIFrame* outerReferenceFrame =
       aBuilder->FindReferenceFrameFor(nsLayoutUtils::GetTransformRootFrame(this));
     buildingDisplayList.SetReferenceFrameAndCurrentOffset(outerReferenceFrame,
       GetOffsetToCrossDoc(outerReferenceFrame));
 
     if (Preserves3DChildren()) {
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1059498-2.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Test for bug 1059498 - Paint parts of the filter that are caused by parts of the source that are invisible</title>
+
+<style>
+
+body {
+  margin: 0;
+}
+
+#filtered {
+  margin-top: -110px;
+  margin-left: -10px;
+  width: 100px;
+  height: 100px;
+  background-color: white;
+  filter: url(#filter);
+}
+
+#transformed {
+  transform: translateX(10px);
+  width: 200px;
+}
+
+</style>
+
+<div id="transformed">
+  <div id="filtered"></div>
+</div>
+
+<svg height="0">
+  <defs>
+    <filter id="filter" filterUnits="objectBoundingBox"
+            x="0%" y="0%" width="100%" height="200%"
+            color-interpolation-filters="sRGB">
+      <feDropShadow stdDeviation="0" dx="0" dy="40" flood-color="lime"/>
+    </filter>
+  </defs>
+</svg>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1059498-3.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Test for bug 1059498 - Paint parts of the filter that are caused by parts of the source that are invisible</title>
+
+<style>
+
+body {
+  margin: 0;
+}
+
+#filtered {
+  margin-top: -150px;
+  margin-left: -10px;
+  width: 100px;
+  height: 100px;
+  background-color: white;
+  filter: url(#filter);
+  transform: translateY(40px);
+}
+
+#transformed {
+  transform: translateX(10px);
+  width: 200px;
+}
+
+</style>
+
+<div id="transformed">
+  <div id="filtered"></div>
+</div>
+
+<svg height="0">
+  <defs>
+    <filter id="filter" filterUnits="objectBoundingBox"
+            x="0%" y="0%" width="100%" height="200%"
+            color-interpolation-filters="sRGB">
+      <feDropShadow stdDeviation="0" dx="0" dy="40" flood-color="lime"/>
+    </filter>
+  </defs>
+</svg>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1826,8 +1826,10 @@ pref(browser.display.use_document_fonts,
 == 1042104-1.html 1042104-1-ref.html
 == 1044198-1.html 1044198-1-ref.html
 == 1049499-1.html 1049499-1-ref.html
 == 1050788-1.html about:blank
 == 1053035-1-flex.html 1053035-1-ref.html
 test-pref(layout.css.grid.enabled,true) == 1053035-1-grid.html 1053035-1-ref.html
 == 1059167-1.html 1059167-1-ref.html
 == 1059498-1.html 1059498-1-ref.html
+== 1059498-2.html 1059498-1-ref.html
+== 1059498-3.html 1059498-1-ref.html