gecko-dev/gfx/2d/Matrix.cpp
Kartikaya Gupta 8609d33dec Bug 1377090 - Further generify the Matrix class and define MatrixDouble. r=bas
To allow MatrixDouble to be a drop-in replacement for gfxMatrix, it
needs to accept the "double" versions of Point, Rect, and Size. This
patch does that by adding some extra typedefs inside BaseMatrix to
abstract over that.

It also moves some function implementations into the .h file as they
don't need specialization. I left some function implementations in
the Matrix.cpp file:
- Rotation, because it is specialized for Float and Double, since it uses
  sinf/cosf vs sin/cos in the two implementations.
- The Matrix4x4 multiplication operator overload, because if I put it
  inside the BaseMatrix class declaration Matrix4x4 isn't defined yet
  and the compiler doesn't like it.

MozReview-Commit-ID: K56dZjJhXWS

--HG--
extra : rebase_source : d009151942811a725ee6bf854238073e59665d5c
2017-07-05 11:18:49 -04:00

124 lines
3.2 KiB
C++

/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Matrix.h"
#include "Quaternion.h"
#include "Tools.h"
#include <algorithm>
#include <ostream>
#include <math.h>
#include <float.h> // for FLT_EPSILON
#include "mozilla/FloatingPoint.h" // for UnspecifiedNaN
using namespace std;
namespace mozilla {
namespace gfx {
/* Force small values to zero. We do this to avoid having sin(360deg)
* evaluate to a tiny but nonzero value.
*/
double
FlushToZero(double aVal)
{
// XXX Is double precision really necessary here
if (-FLT_EPSILON < aVal && aVal < FLT_EPSILON) {
return 0.0f;
} else {
return aVal;
}
}
/* Computes tan(aTheta). For values of aTheta such that tan(aTheta) is
* undefined or very large, SafeTangent returns a manageably large value
* of the correct sign.
*/
double
SafeTangent(double aTheta)
{
// XXX Is double precision really necessary here
const double kEpsilon = 0.0001;
/* tan(theta) = sin(theta)/cos(theta); problems arise when
* cos(theta) is too close to zero. Limit cos(theta) to the
* range [-1, -epsilon] U [epsilon, 1].
*/
double sinTheta = sin(aTheta);
double cosTheta = cos(aTheta);
if (cosTheta >= 0 && cosTheta < kEpsilon) {
cosTheta = kEpsilon;
} else if (cosTheta < 0 && cosTheta >= -kEpsilon) {
cosTheta = -kEpsilon;
}
return FlushToZero(sinTheta / cosTheta);
}
template<> Matrix
Matrix::Rotation(Float aAngle)
{
Matrix newMatrix;
Float s = sinf(aAngle);
Float c = cosf(aAngle);
newMatrix._11 = c;
newMatrix._12 = s;
newMatrix._21 = -s;
newMatrix._22 = c;
return newMatrix;
}
template<> MatrixDouble
MatrixDouble::Rotation(Double aAngle)
{
MatrixDouble newMatrix;
Double s = sin(aAngle);
Double c = cos(aAngle);
newMatrix._11 = c;
newMatrix._12 = s;
newMatrix._21 = -s;
newMatrix._22 = c;
return newMatrix;
}
template<> Matrix4x4
MatrixDouble::operator*(const Matrix4x4& aMatrix) const
{
Matrix4x4 resultMatrix;
resultMatrix._11 = this->_11 * aMatrix._11 + this->_12 * aMatrix._21;
resultMatrix._12 = this->_11 * aMatrix._12 + this->_12 * aMatrix._22;
resultMatrix._13 = this->_11 * aMatrix._13 + this->_12 * aMatrix._23;
resultMatrix._14 = this->_11 * aMatrix._14 + this->_12 * aMatrix._24;
resultMatrix._21 = this->_21 * aMatrix._11 + this->_22 * aMatrix._21;
resultMatrix._22 = this->_21 * aMatrix._12 + this->_22 * aMatrix._22;
resultMatrix._23 = this->_21 * aMatrix._13 + this->_22 * aMatrix._23;
resultMatrix._24 = this->_21 * aMatrix._14 + this->_22 * aMatrix._24;
resultMatrix._31 = aMatrix._31;
resultMatrix._32 = aMatrix._32;
resultMatrix._33 = aMatrix._33;
resultMatrix._34 = aMatrix._34;
resultMatrix._41 = this->_31 * aMatrix._11 + this->_32 * aMatrix._21 + aMatrix._41;
resultMatrix._42 = this->_31 * aMatrix._12 + this->_32 * aMatrix._22 + aMatrix._42;
resultMatrix._43 = this->_31 * aMatrix._13 + this->_32 * aMatrix._23 + aMatrix._43;
resultMatrix._44 = this->_31 * aMatrix._14 + this->_32 * aMatrix._24 + aMatrix._44;
return resultMatrix;
}
} // namespace gfx
} // namespace mozilla