Bug 1638051 - Stop clamping radialGradients. r=dholbert

We have to remove one of the radialGradient-basic-03-ref.svg tests (id=gradient5)
because it's testing clamping i.e. an fr just inside the radius is the same as
just outside and that's no longer true. Two of the other references are now different
due to the lack of clamping. In order to get the test and reference the same, the reference is created
using canvas since canvas has never had clamping.

Clamping was required by SVG 1.1 but that requirement was explicitly removed in SVG 2
mostly to match canvas, which has never clamped. Any rendering artifacts would likely
have been uncovered by canvas over the years since it has the same code that SVG uses
absent any clamping.

Differential Revision: https://phabricator.services.mozilla.com/D75706
This commit is contained in:
longsonr 2020-06-07 10:05:00 +00:00
Родитель cf358ddc84
Коммит 6ded748d68
5 изменённых файлов: 37 добавлений и 64 удалений

Просмотреть файл

@ -0,0 +1,36 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<head>
<title>Reference for gradient</title>
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=441780 -->
</head>
<body>
<canvas width="400" height="400"></canvas>
<style>
* { margin: 0; }
</style>
<script>
let canvas = document.querySelector('canvas');
let ctx = canvas.getContext('2d');
function createCircleWithGradient(x, y, r, fx, fy) {
let gradient = ctx.createRadialGradient(fx, y, 0, x, y, r);
gradient.addColorStop(0, 'lime');
gradient.addColorStop(1, 'red');
ctx.beginPath();
ctx.arc(x, y, 50, 0, 2 * Math.PI);
ctx.fillStyle = gradient;
ctx.fill();
}
createCircleWithGradient(100, 100, 50, 50);
createCircleWithGradient(100, 200, 40, 60);
createCircleWithGradient(200, 100, 50, 250);
createCircleWithGradient(200, 200, 70, 280);
</script>
</body>

Просмотреть файл

@ -1,39 +0,0 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<svg xmlns="http://www.w3.org/2000/svg" >
<title>Reference for gradient</title>
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=441780 -->
<defs>
<radialGradient id="gradient1" fx="0.002">
<stop offset="0" stop-color="lime" />
<stop offset="1" stop-color="red"/>
</radialGradient>
<radialGradient id="gradient2" r="0.4" fx="0.104">
<stop offset="0" stop-color="lime" />
<stop offset="1" stop-color="red"/>
</radialGradient>
<radialGradient id="gradient3" fx="0.998">
<stop offset="0" stop-color="lime" />
<stop offset="1" stop-color="red"/>
</radialGradient>
<radialGradient id="gradient4" r="0.7" fx="1.197">
<stop offset="0" stop-color="lime" />
<stop offset="1" stop-color="red"/>
</radialGradient>
<radialGradient id="gradient5" r="0.2" fx="0.308">
<stop offset="0" stop-color="lime" />
<stop offset="1" stop-color="red"/>
</radialGradient>
</defs>
<circle cx="100" cy="100" r="50" fill="url(#gradient1)"/>
<circle cx="100" cy="200" r="50" fill="url(#gradient2)"/>
<circle cx="200" cy="100" r="50" fill="url(#gradient3)"/>
<circle cx="200" cy="200" r="50" fill="url(#gradient4)"/>
<circle cx="300" cy="100" r="50" fill="url(#gradient5)"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.5 KiB

Просмотреть файл

@ -25,15 +25,10 @@
<stop offset="0" stop-color="lime" />
<stop offset="1" stop-color="red"/>
</radialGradient>
<radialGradient id="gradient5" r="0.2" fx="0.3">
<stop offset="0" stop-color="lime" />
<stop offset="1" stop-color="red"/>
</radialGradient>
</defs>
<circle cx="100" cy="100" r="50" fill="url(#gradient1)"/>
<circle cx="100" cy="200" r="50" fill="url(#gradient2)"/>
<circle cx="200" cy="100" r="50" fill="url(#gradient3)"/>
<circle cx="200" cy="200" r="50" fill="url(#gradient4)"/>
<circle cx="300" cy="100" r="50" fill="url(#gradient5)"/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1.5 KiB

После

Ширина:  |  Высота:  |  Размер: 1.2 KiB

Просмотреть файл

@ -400,7 +400,7 @@ fuzzy-if(skiaContent||webrender,0-72,0-1255) == pattern-transformed-01.svg patte
== radialGradient-basic-01.svg pass.svg
== radialGradient-basic-02.svg pass.svg
fuzzy-if(cocoaWidget,0-4,0-15982) fuzzy-if(winWidget,0-4,0-92) fuzzy-if(skiaContent,0-4,0-60) fuzzy-if(geckoview&&webrender,0-5,0-333) == radialGradient-basic-03.svg radialGradient-basic-03-ref.svg
fuzzy(0-1,0-2) fuzzy-if(winWidget,0-32,0-172) fuzzy-if(winWidget&&webrender,96-96,21684-21684) == radialGradient-basic-03.svg radialGradient-basic-03-ref.html
== radialGradient-basic-04.svg pass.svg
== radialGradient-fr-01.svg pass.svg
fuzzy(0-1,0-3235) fuzzy-if(winWidget,0-1,0-7030) == radialGradient-fr-02.svg radialGradient-fr-02-ref.svg

Просмотреть файл

@ -568,25 +568,6 @@ already_AddRefed<gfxPattern> nsSVGRadialGradientFrame::CreateGradient() {
fy = GetLengthValue(dom::SVGRadialGradientElement::ATTR_FY, cy);
fr = GetLengthValue(dom::SVGRadialGradientElement::ATTR_FR);
if (fx != cx || fy != cy) {
// The focal point (fFx and fFy) must be clamped to be *inside* - not on -
// the circumference of the gradient or we'll get rendering anomalies. We
// calculate the distance from the focal point to the gradient center and
// make sure it is *less* than the gradient radius.
// 1/128 is the limit of the fractional part of cairo's 24.8 fixed point
// representation divided by 2 to ensure that we get different cairo
// fractions
double dMax = std::max(0.0, r - 1.0 / 128);
double dx = fx - cx;
double dy = fy - cy;
double d = std::sqrt((dx * dx) + (dy * dy));
if (d > dMax) {
double angle = std::atan2(dy, dx);
fx = float(dMax * std::cos(angle)) + cx;
fy = float(dMax * std::sin(angle)) + cy;
}
}
RefPtr<gfxPattern> pattern = new gfxPattern(fx, fy, fr, cx, cy, r);
return pattern.forget();
}