Bug 610594 - "ABORT: F.6.6.3 should prevent this. Will sqrt(-num)!". r=longsonr, a=blocking

This commit is contained in:
Jonathan Watt 2011-01-03 09:26:28 +00:00
parent 43225ec75d
commit c7eb7f1b6c
3 changed files with 39 additions and 30 deletions

View File

@ -554,9 +554,9 @@ SVGPathData::GetMarkerPositioningData(nsTArray<nsSVGMark> *aMarks) const
case nsIDOMSVGPathSeg::PATHSEG_ARC_ABS:
case nsIDOMSVGPathSeg::PATHSEG_ARC_REL:
{
float rx = mData[i];
float ry = mData[i+1];
float angle = mData[i+2];
double rx = mData[i];
double ry = mData[i+1];
double angle = mData[i+2];
PRBool largeArcFlag = mData[i+3] != 0.0f;
PRBool sweepFlag = mData[i+4] != 0.0f;
if (segType == nsIDOMSVGPathSeg::PATHSEG_ARC_ABS) {
@ -595,46 +595,47 @@ SVGPathData::GetMarkerPositioningData(nsTArray<nsSVGMark> *aMarks) const
// F.6.5.1:
angle = angle * M_PI/180.0;
float x1p = cos(angle) * (segStart.x - segEnd.x) / 2.0
+ sin(angle) * (segStart.y - segEnd.y) / 2.0;
float y1p = -sin(angle) * (segStart.x - segEnd.x) / 2.0
+ cos(angle) *(segStart.y - segEnd.y) / 2.0;
double x1p = cos(angle) * (segStart.x - segEnd.x) / 2.0
+ sin(angle) * (segStart.y - segEnd.y) / 2.0;
double y1p = -sin(angle) * (segStart.x - segEnd.x) / 2.0
+ cos(angle) * (segStart.y - segEnd.y) / 2.0;
// This is the root in F.6.5.2 and the numerator under that root:
float root;
float numerator = rx*rx*ry*ry - rx*rx*y1p*y1p - ry*ry*x1p*x1p;
double root;
double numerator = rx*rx*ry*ry - rx*rx*y1p*y1p - ry*ry*x1p*x1p;
if (numerator < 0.0) {
// F.6.6 step 3 - |numerator < 0.0| is equivalent to the result of
// F.6.6.2 (lamedh) being greater than one. What we have here is radii
// that do not reach between segStart and segEnd, so we need to correct
// them.
float lamedh = 1.0 - numerator/(rx*rx*ry*ry); // equiv to eqn F.6.6.2
float s = sqrt(lamedh);
if (numerator >= 0.0) {
root = sqrt(numerator/(rx*rx*y1p*y1p + ry*ry*x1p*x1p));
if (largeArcFlag == sweepFlag)
root = -root;
} else {
// F.6.6 step 3 - |numerator < 0.0|. This is equivalent to the result
// of F.6.6.2 (lamedh) being greater than one. What we have here is
// ellipse radii that are too small for the ellipse to reach between
// segStart and segEnd. We scale the radii up uniformly so that the
// ellipse is just big enough to fit (i.e. to the point where there is
// exactly one solution).
double lamedh = 1.0 - numerator/(rx*rx*ry*ry); // equiv to eqn F.6.6.2
double s = sqrt(lamedh);
rx *= s; // F.6.6.3
ry *= s;
// rx and ry changed, so we have to recompute numerator
numerator = rx*rx*ry*ry - rx*rx*y1p*y1p - ry*ry*x1p*x1p;
NS_ABORT_IF_FALSE(numerator >= 0,
"F.6.6.3 should prevent this. Will sqrt(-num)!");
root = 0.0;
}
root = sqrt(numerator/(rx*rx*y1p*y1p + ry*ry*x1p*x1p));
if (largeArcFlag == sweepFlag)
root = -root;
float cxp = root * rx * y1p / ry; // F.6.5.2
float cyp = -root * ry * x1p / rx;
double cxp = root * rx * y1p / ry; // F.6.5.2
double cyp = -root * ry * x1p / rx;
float theta, delta;
theta = CalcVectorAngle(1.0, 0.0, (x1p-cxp)/rx, (y1p-cyp)/ry); // F.6.5.5
delta = CalcVectorAngle((x1p-cxp)/rx, (y1p-cyp)/ry,
(-x1p-cxp)/rx, (-y1p-cyp)/ry); // F.6.5.6
double theta, delta;
theta = CalcVectorAngle(1.0, 0.0, (x1p-cxp)/rx, (y1p-cyp)/ry); // F.6.5.5
delta = CalcVectorAngle((x1p-cxp)/rx, (y1p-cyp)/ry,
(-x1p-cxp)/rx, (-y1p-cyp)/ry); // F.6.5.6
if (!sweepFlag && delta > 0)
delta -= 2.0 * M_PI;
else if (sweepFlag && delta < 0)
delta += 2.0 * M_PI;
float tx1, ty1, tx2, ty2;
double tx1, ty1, tx2, ty2;
tx1 = -cos(angle)*rx*sin(theta) - sin(angle)*ry*cos(theta);
ty1 = -sin(angle)*rx*sin(theta) + cos(angle)*ry*cos(theta);
tx2 = -cos(angle)*rx*sin(theta+delta) - sin(angle)*ry*cos(theta+delta);

View File

@ -0,0 +1,6 @@
<!DOCTYPE html>
<html>
<body>
<svg><path d="M 0 5 a 2 5 -30 104 -5" marker-mid="url(#q)"></path></svg>
</body>
</html>

View File

@ -97,7 +97,9 @@ load 587336-1.html
load 590291-1.svg
load 601999-1.html
load 605626-1.svg
load 610594-1.html
load 610954-1.html
load 612662-1.svg
load 612662-2.svg
load 621598-1.svg