Bug 1315113 - Fix coordinate space confusion in gradient rendering code. r?mattwoodrow draft
authorMarkus Stange <mstange@themasta.com>
Wed, 09 Nov 2016 13:53:33 -0500
changeset 438551 efc543007e4ade583eaf92c10c865e470124dbb9
parent 438550 71fd23fa0803a548b6e571aa25d0533a06cd0421
child 536941 52f7e63900c40d24f6f8a651051d365da9412825
push id35755
push userbmo:mstange@themasta.com
push dateMon, 14 Nov 2016 19:11:18 +0000
reviewersmattwoodrow
bugs1315113
milestone53.0a1
Bug 1315113 - Fix coordinate space confusion in gradient rendering code. r?mattwoodrow MozReview-Commit-ID: 38Zk9qWNyoX
layout/base/Units.h
layout/base/nsCSSRendering.cpp
layout/reftests/bugs/1315113-1-ref.html
layout/reftests/bugs/1315113-1.html
layout/reftests/bugs/1315113-2-ref.html
layout/reftests/bugs/1315113-2.html
layout/reftests/bugs/reftest.list
--- a/layout/base/Units.h
+++ b/layout/base/Units.h
@@ -259,16 +259,23 @@ struct CSSPixel {
   }
 
   static nsRect ToAppUnits(const CSSRect& aRect) {
     return nsRect(NSToCoordRoundWithClamp(aRect.x * float(AppUnitsPerCSSPixel())),
                   NSToCoordRoundWithClamp(aRect.y * float(AppUnitsPerCSSPixel())),
                   NSToCoordRoundWithClamp(aRect.width * float(AppUnitsPerCSSPixel())),
                   NSToCoordRoundWithClamp(aRect.height * float(AppUnitsPerCSSPixel())));
   }
+
+  static nsRect ToAppUnits(const CSSIntRect& aRect) {
+    return nsRect(NSToCoordRoundWithClamp(float(aRect.x) * float(AppUnitsPerCSSPixel())),
+                  NSToCoordRoundWithClamp(float(aRect.y) * float(AppUnitsPerCSSPixel())),
+                  NSToCoordRoundWithClamp(float(aRect.width) * float(AppUnitsPerCSSPixel())),
+                  NSToCoordRoundWithClamp(float(aRect.height) * float(AppUnitsPerCSSPixel())));
+  }
 };
 
 /*
  * The pixels that are referred to as "device pixels" in layout code. In
  * general values measured in LayoutDevicePixels are obtained by dividing a
  * value in app units by AppUnitsPerDevPixel(). Conversion between CSS pixels
  * and LayoutDevicePixels is affected by:
  * 1) the "full zoom" (see nsPresContext::SetFullZoom)
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -2714,26 +2714,31 @@ nsCSSRendering::PaintGradient(nsPresCont
     // things easier, and then rotate the matrix to turn everything back the
     // right way up.
     if (lineStart.x > lineEnd.x || lineStart.y > lineEnd.y) {
       std::swap(lineStart, lineEnd);
       matrix.Scale(-1, -1);
     }
 
     // Fit the gradient line exactly into the source rect.
+    // aSrc is relative to aIntrinsincSize.
+    // srcRectDev will be relative to srcSize, so in the same coordinate space
+    // as lineStart / lineEnd.
+    gfxRect srcRectDev = nsLayoutUtils::RectToGfxRect(
+      CSSPixel::ToAppUnits(aSrc), appUnitsPerDevPixel);
     if (lineStart.x != lineEnd.x) {
-      rectLen = aPresContext->CSSPixelsToDevPixels(aSrc.width);
-      offset = ((double)aSrc.x - lineStart.x) / lineLength;
-      lineStart.x = aSrc.x;
-      lineEnd.x = aSrc.x + rectLen;
+      rectLen = srcRectDev.width;
+      offset = (srcRectDev.x - lineStart.x) / lineLength;
+      lineStart.x = srcRectDev.x;
+      lineEnd.x = srcRectDev.XMost();
     } else {
-      rectLen = aPresContext->CSSPixelsToDevPixels(aSrc.height);
-      offset = ((double)aSrc.y - lineStart.y) / lineLength;
-      lineStart.y = aSrc.y;
-      lineEnd.y = aSrc.y + rectLen;
+      rectLen = srcRectDev.height;
+      offset = (srcRectDev.y - lineStart.y) / lineLength;
+      lineStart.y = srcRectDev.y;
+      lineEnd.y = srcRectDev.YMost();
     }
 
     // Adjust gradient stop positions for the new gradient line.
     double scale = lineLength / rectLen;
     for (size_t i = 0; i < stops.Length(); i++) {
       stops[i].mPosition = (stops[i].mPosition - offset) * fabs(scale);
     }
 
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1315113-1-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html reftest-zoom="2">
+<meta charset="utf-8">
+<title>Reference for test for bug 1315113: Gradient in border image</title>
+<style>
+
+body {
+  margin: 0;
+}
+
+#box {
+  width: 200px;
+  border: 80px solid transparent;
+  padding: 20px;
+  background: linear-gradient(red, blue);
+  background-origin: border-box;
+}
+
+</style>
+
+<div id="box"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1315113-1.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html reftest-zoom="2">
+<meta charset="utf-8">
+<title>Test for bug 1315113: Gradient in border image</title>
+<style>
+
+body {
+  margin: 0;
+}
+
+#box {
+  width: 200px;
+  border: 100px solid;
+  border-image-source: linear-gradient(red, blue);
+  border-image-slice: 40% 40% fill;
+  border-image-width: 80px 80px;
+  border-image-repeat: round stretch;
+  background-color: black;
+}
+
+</style>
+
+<div id="box"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1315113-2-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html reftest-zoom="0.5">
+<meta charset="utf-8">
+<title>Reference for test for bug 1315113: Gradient in border image</title>
+<style>
+
+body {
+  margin: 0;
+}
+
+#box {
+  width: 200px;
+  border: 80px solid transparent;
+  padding: 20px;
+  background: linear-gradient(red, blue);
+  background-origin: border-box;
+}
+
+</style>
+
+<div id="box"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/1315113-2.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html reftest-zoom="0.5">
+<meta charset="utf-8">
+<title>Test for bug 1315113: Gradient in border image</title>
+<style>
+
+body {
+  margin: 0;
+}
+
+#box {
+  width: 200px;
+  border: 100px solid;
+  border-image-source: linear-gradient(red, blue);
+  border-image-slice: 40% 40% fill;
+  border-image-width: 80px 80px;
+  border-image-repeat: round stretch;
+  background-color: black;
+}
+
+</style>
+
+<div id="box"></div>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1968,16 +1968,18 @@ random-if(!winWidget) == 1273154-2.html 
 == 1275411-1.html 1275411-1-ref.html
 == 1288255.html 1288255-ref.html
 fuzzy(8,1900) == 1291528.html 1291528-ref.html
 # Buttons in 2 pages have different position and the rendering result can be
 # different, but they should use the same button style and the background color
 # should be same.  |fuzzy()| here allows the difference in border, but not
 # background color.
 fuzzy(255,1000) skip-if(!cocoaWidget) == 1294102-1.html 1294102-1-ref.html
+fuzzy(2,320000) == 1315113-1.html 1315113-1-ref.html
+fuzzy(2,20000) == 1315113-2.html 1315113-2-ref.html
 == 1315632-1.html 1315632-1-ref.html
 fuzzy(2,40000) == 1316719-1a.html 1316719-1-ref.html
 fuzzy(2,40000) == 1316719-1b.html 1316719-1-ref.html
 fuzzy(2,40000) == 1316719-1c.html 1316719-1-ref.html
 
 HTTP == 652991-1a.html 652991-1-ref.html
 HTTP == 652991-1b.html 652991-1-ref.html
 HTTP == 652991-2.html 652991-2-ref.html