Bug 1315113 - Fix coordinate space confusion in gradient rendering code. r?mattwoodrow
MozReview-Commit-ID: 38Zk9qWNyoX
--- 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