Bug 1322537 - Increase tolerance when splitting Bezier curves to prevent hang. r=bas
MozReview-Commit-ID: 3qhj9He65Bh
--- a/gfx/2d/Path.cpp
+++ b/gfx/2d/Path.cpp
@@ -253,32 +253,40 @@ FlattenBezierCurveSegment(const BezierCo
* The basic premise is that for a small t the third order term in the
* equation of a cubic bezier curve is insignificantly small. This can
* then be approximated by a quadratic equation for which the maximum
* difference from a linear approximation can be much more easily determined.
*/
BezierControlPoints currentCP = aControlPoints;
double t = 0;
+ double currentTolerance = aTolerance;
while (t < 1.0) {
PointD cp21 = currentCP.mCP2 - currentCP.mCP1;
PointD cp31 = currentCP.mCP3 - currentCP.mCP1;
/* To remove divisions and check for divide-by-zero, this is optimized from:
* Float s3 = (cp31.x * cp21.y - cp31.y * cp21.x) / hypotf(cp21.x, cp21.y);
* t = 2 * Float(sqrt(aTolerance / (3. * std::abs(s3))));
*/
double cp21x31 = cp31.x * cp21.y - cp31.y * cp21.x;
double h = hypot(cp21.x, cp21.y);
if (cp21x31 * h == 0) {
break;
}
double s3inv = h / cp21x31;
- t = 2 * sqrt(aTolerance * std::abs(s3inv) / 3.);
+ t = 2 * sqrt(currentTolerance * std::abs(s3inv) / 3.);
+ currentTolerance *= 1 + aTolerance;
+ // Increase tolerance every iteration to prevent this loop from executing
+ // too many times. This approximates the length of large curves more
+ // roughly. In practice, aTolerance is the constant kFlatteningTolerance
+ // which has value 0.0001. With this value, it takes 6,932 splits to double
+ // currentTolerance (to 0.0002) and 23,028 splits to increase
+ // currentTolerance by an order of magnitude (to 0.001).
if (t >= 1.0) {
break;
}
SplitBezier(currentCP, nullptr, ¤tCP, t);
aSink->LineTo(currentCP.mCP1.ToPoint());
}
new file mode 100644
--- /dev/null
+++ b/layout/svg/crashtests/1322537-1.html
@@ -0,0 +1,2 @@
+<svg>
+<animateMotion path='M8,0l69,97m45,-17592186044414A71,23 46,0,0 16382,98Q50,10 48,72T21,0Z'/>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/layout/svg/crashtests/1322537-2.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<head>
+ <script>
+ function go() {
+ var path = document.getElementById("myPath");
+ var len = path.getTotalLength();
+ console.log(len);
+ }
+ </script>
+</head>
+<body onload="go()">
+ <svg>
+ <path id="myPath" d="M45,-17592186044414A71,23 46,0,0 16382,98"/>
+ </svg>
+</body>
--- a/layout/svg/crashtests/crashtests.list
+++ b/layout/svg/crashtests/crashtests.list
@@ -193,11 +193,13 @@ load 993443.svg
load 1016145.svg
load 1028512.svg
load 1140080-1.svg
load 1149542-1.svg
load 1156581-1.svg
load 1182496-1.html
load 1209525-1.svg
load 1223281-1.svg
+load 1322537-1.html
+load 1322537-2.html
load 1348564.svg
load conditional-outer-svg-nondirty-reflow-assert.xhtml
load extref-test-1.xhtml