Bug 1467277 - Avoid getting zero normalized vector of rotate3d when setting a rotate matrix. r=nical

For example, if we set a transform to rotate3d(0, 0, 1e50, 45deg), the
expected normalized rotate axis is (0, 0, 1).
However, the length is larger than the maximum of float, so the actual value is
(0/inf, 0/inf, 1e50/inf) == (0, 0, 0). Therefore, we scale the vector before
doing normalization to avoid getting a zero vector.

MozReview-Commit-ID: 5LUDWD4RuNj

--HG--
extra : rebase_source : eb82f0b3979bf6ea3cd11b643ebb30a49edc24f8
This commit is contained in:
Boris Chiou 2018-07-05 15:40:39 -07:00
Родитель f0bf583292
Коммит ffa1da7545
4 изменённых файлов: 33 добавлений и 11 удалений

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

@ -87,10 +87,10 @@ struct BasePoint3D {
} }
Sub& operator/=(T aScale) { Sub& operator/=(T aScale) {
x /= aScale; x /= aScale;
y /= aScale; y /= aScale;
z /= aScale; z /= aScale;
return *static_cast<Sub*>(this); return *static_cast<Sub*>(this);
} }
Sub operator-() const { Sub operator-() const {
@ -98,22 +98,34 @@ struct BasePoint3D {
} }
Sub CrossProduct(const Sub& aPoint) const { Sub CrossProduct(const Sub& aPoint) const {
return Sub(y * aPoint.z - aPoint.y * z, return Sub(y * aPoint.z - aPoint.y * z,
z * aPoint.x - aPoint.z * x, z * aPoint.x - aPoint.z * x,
x * aPoint.y - aPoint.x * y); x * aPoint.y - aPoint.x * y);
} }
T DotProduct(const Sub& aPoint) const { T DotProduct(const Sub& aPoint) const {
return x * aPoint.x + y * aPoint.y + z * aPoint.z; return x * aPoint.x + y * aPoint.y + z * aPoint.z;
} }
T Length() const { T Length() const {
return sqrt(x*x + y*y + z*z); return sqrt(x*x + y*y + z*z);
} }
// Invalid for points with distance from origin of 0. // Invalid for points with distance from origin of 0.
void Normalize() { void Normalize() {
*this /= Length(); *this /= Length();
}
void RobustNormalize() {
// If the distance is infinite, we scale it by 1/(the maximum value of T)
// before doing normalization, so we can avoid getting a zero point.
T length = Length();
if (mozilla::IsInfinite(length)) {
*this /= std::numeric_limits<T>::max();
length = Length();
}
*this /= length;
} }
friend std::ostream& operator<<(std::ostream& stream, const BasePoint3D<T, Sub>& aPoint) { friend std::ostream& operator<<(std::ostream& stream, const BasePoint3D<T, Sub>& aPoint) {

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

@ -1650,7 +1650,7 @@ public:
if (!vector.Length()) { if (!vector.Length()) {
return; return;
} }
vector.Normalize(); vector.RobustNormalize();
double x = vector.x; double x = vector.x;
double y = vector.y; double y = vector.y;

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

@ -0,0 +1,9 @@
<html>
<head>
</head>
<body>
<div style="transform: rotate3d(1e50, 0, 0, 45deg); width: 100px; height: 100px;">
Test Text
</div>
</body>
</html>

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

@ -32,6 +32,7 @@ fuzzy-if(winWidget,143,689) fuzzy-if(OSX,224,924) fuzzy-if(winWidget,154,644) ra
fuzzy-if(skiaContent,1,4) == matrix3d-1a.html matrix3d-1-ref.html fuzzy-if(skiaContent,1,4) == matrix3d-1a.html matrix3d-1-ref.html
== matrix3d-2a.html matrix3d-2-ref.html == matrix3d-2a.html matrix3d-2-ref.html
== rotate3d-1a.html rotatex-1-ref.html == rotate3d-1a.html rotatex-1-ref.html
== 1467277-1.html rotatex-1-ref.html
fuzzy-if(webrender,0-1,0-6) == rotate3d-2a.html rotatey-1-ref.html fuzzy-if(webrender,0-1,0-6) == rotate3d-2a.html rotatey-1-ref.html
!= backface-visibility-1a.html about:blank != backface-visibility-1a.html about:blank
== backface-visibility-1b.html about:blank == backface-visibility-1b.html about:blank