Bug 1364338 - Force a repaint when CSS 'outline-width' or 'outline-offset' change. r=heycam, a=gchang
authorDaniel Holbert <dholbert@cs.stanford.edu>
Fri, 12 May 2017 18:42:10 -0700
changeset 396383 9a2261759cafade59687156d8b31c3426ad82678
parent 396382 bc0068cb9e0b1338879eed37127bdbb98f497db2
child 396384 68ebebce80d23ed6de11f67aebe717d822d90fa9
push id1468
push userasasaki@mozilla.com
push dateMon, 05 Jun 2017 19:31:07 +0000
treeherdermozilla-release@0641fc6ee9d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam, gchang
bugs1364338
milestone54.0
Bug 1364338 - Force a repaint when CSS 'outline-width' or 'outline-offset' change. r=heycam, a=gchang Previously, when these properties changed, we'd only send change hints to recompute overflow areas & trigger DLBI. If the outline was always outside of the element's border box, this old strategy was generally OK, because the outline tweak would cause a change to the overflow areas' size, and that would invalidate the changed area via DLBI & trigger a repaint. However, for outlines that are *inside* of the element (via negative 'outline-offset'), these change hints were not sufficient, because tweaks to the outline width & offset will NOT affect the size of the element's overflow areas and will not trigger any DLBI invalidation. So in order to correctly handle these changes, we really need to request a repaint of the affected element, since some piece of the element may need to be repainted even if it's not changing in size. MozReview-Commit-ID: J4KGUHrJ09U
layout/reftests/outline/outline-dynamic-change-1-ref.html
layout/reftests/outline/outline-dynamic-change-1a.html
layout/reftests/outline/outline-dynamic-change-1b.html
layout/reftests/outline/reftest.list
layout/style/nsStyleStruct.cpp
new file mode 100644
--- /dev/null
+++ b/layout/reftests/outline/outline-dynamic-change-1-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <style>
+    #tweakMe {
+      height: 100px;
+      width: 100px;
+      background: gray;
+      outline: solid 6px black;
+      outline-offset: -16px;
+    }
+  </style>
+</head>
+<body>
+  <div id="tweakMe"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/outline/outline-dynamic-change-1a.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+  <title>
+    Test that dynamic tweaks to 'outline-offset' are reflected in the rendering.
+  </title>
+  <style>
+    #tweakMe {
+      height: 100px;
+      width: 100px;
+      background: gray;
+      outline: solid 6px black;
+      outline-offset: -10px;
+    }
+  </style>
+  <script>
+window.addEventListener("MozReftestInvalidate", function() {
+  tweakMe.style.outlineOffset = "-16px";
+  document.documentElement.removeAttribute("class");
+});
+  </script>
+</head>
+<body>
+  <div id="tweakMe"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/outline/outline-dynamic-change-1b.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+  <title>
+    Test that dynamic tweaks to 'outline-width' are reflected in the rendering.
+  </title>
+  <style>
+    #tweakMe {
+      height: 100px;
+      width: 100px;
+      background: gray;
+      outline: solid 2px black;
+      outline-offset: -16px;
+    }
+  </style>
+  <script>
+window.addEventListener("MozReftestInvalidate", function() {
+  tweakMe.style.outlineWidth = "6px";
+  document.documentElement.removeAttribute("class");
+});
+  </script>
+</head>
+<body>
+  <div id="tweakMe"></div>
+</body>
+</html>
--- a/layout/reftests/outline/reftest.list
+++ b/layout/reftests/outline/reftest.list
@@ -1,12 +1,14 @@
 fuzzy(2,18) == outline-and-box-shadow.html outline-and-box-shadow-ref.html
 fails-if(webrender) == outline-and-3d-transform-1a.html outline-and-3d-transform-1-ref.html
 fails-if(webrender) == outline-and-3d-transform-1b.html outline-and-3d-transform-1-ref.html
 fuzzy-if(gtkWidget,136,120) fuzzy-if(Android,255,356) fuzzy-if(d2d,16,96) fuzzy-if(cocoaWidget,255,120) fuzzy-if(winWidget,255,216) fails-if(webrender) == outline-and-3d-transform-2.html outline-and-3d-transform-2-ref.html
+== outline-dynamic-change-1a.html outline-dynamic-change-1-ref.html
+== outline-dynamic-change-1b.html outline-dynamic-change-1-ref.html
 == outline-overflow-block-abspos.html outline-overflow-block-ref.html
 == outline-overflow-block-float.html outline-overflow-block-ref.html
 == outline-overflow-inlineblock-abspos.html outline-overflow-inlineblock-ref.html
 == outline-overflow-inlineblock-float.html outline-overflow-inlineblock-ref.html
 pref(layout.css.outline-style-auto.enabled,true) skip-if(!gtkWidget&&!winWidget&&!cocoaWidget) == outline-auto-001.html outline-auto-001-ref.html # only works on platforms that supports NS_THEME_FOCUS_OUTLINE
 pref(layout.css.outline-style-auto.enabled,false) == outline-auto-001.html outline-auto-001-solid-ref.html
 == outline-initial-1a.html outline-initial-1-ref.html
 == outline-initial-1b.html outline-initial-1-ref.html
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -569,17 +569,18 @@ nsStyleOutline::RecalcData()
 
 nsChangeHint
 nsStyleOutline::CalcDifference(const nsStyleOutline& aNewData) const
 {
   if (mActualOutlineWidth != aNewData.mActualOutlineWidth ||
       (mActualOutlineWidth > 0 &&
        mOutlineOffset != aNewData.mOutlineOffset)) {
     return nsChangeHint_UpdateOverflow |
-           nsChangeHint_SchedulePaint;
+           nsChangeHint_SchedulePaint |
+           nsChangeHint_RepaintFrame;
   }
 
   if (mOutlineStyle != aNewData.mOutlineStyle ||
       mOutlineColor != aNewData.mOutlineColor ||
       mOutlineRadius != aNewData.mOutlineRadius) {
     if (mActualOutlineWidth > 0) {
       return nsChangeHint_RepaintFrame;
     }