Bug 1069417 - Generalize Matrix4x4 into Matrix4x4Typed<SourceUnits, TargetUnits>. r=Bas

Matrix4x4 remains a typedef for Matrix4x4Typed<UnknownUnits, UnknownUnits>.

No client code needed changing, except for forward-declarations of Matrix4x4
as a class (since it's now a typedef).
This commit is contained in:
Botond Ballo 2015-12-02 18:52:00 -05:00
parent 1eb88b293a
commit 34ea66cb43
22 changed files with 591 additions and 668 deletions

View File

@ -15,7 +15,9 @@
using namespace std; using namespace std;
namespace {
namespace mozilla {
namespace gfx {
/* Force small values to zero. We do this to avoid having sin(360deg) /* Force small values to zero. We do this to avoid having sin(360deg)
* evaluate to a tiny but nonzero value. * evaluate to a tiny but nonzero value.
@ -57,11 +59,6 @@ SafeTangent(double aTheta)
return FlushToZero(sinTheta / cosTheta); return FlushToZero(sinTheta / cosTheta);
} }
} // namespace
namespace mozilla {
namespace gfx {
std::ostream& std::ostream&
operator<<(std::ostream& aStream, const Matrix& aMatrix) operator<<(std::ostream& aStream, const Matrix& aMatrix)
{ {
@ -74,17 +71,6 @@ operator<<(std::ostream& aStream, const Matrix& aMatrix)
<< "; ]"; << "; ]";
} }
std::ostream&
operator<<(std::ostream& aStream, const Matrix4x4& aMatrix)
{
const Float *f = &aMatrix._11;
aStream << "[ " << f[0] << " " << f[1] << " " << f[2] << " " << f[3] << " ;" << std::endl; f += 4;
aStream << " " << f[0] << " " << f[1] << " " << f[2] << " " << f[3] << " ;" << std::endl; f += 4;
aStream << " " << f[0] << " " << f[1] << " " << f[2] << " " << f[3] << " ;" << std::endl; f += 4;
aStream << " " << f[0] << " " << f[1] << " " << f[2] << " " << f[3] << " ]" << std::endl;
return aStream;
}
Matrix Matrix
Matrix::Rotation(Float aAngle) Matrix::Rotation(Float aAngle)
{ {
@ -144,512 +130,5 @@ Matrix::NudgeToIntegers()
return *this; return *this;
} }
template<class F>
RectTyped<UnknownUnits, F>
Matrix4x4::TransformBounds(const RectTyped<UnknownUnits, F>& aRect) const
{
Point4DTyped<UnknownUnits, F> verts[4];
verts[0] = *this * Point4DTyped<UnknownUnits, F>(aRect.x, aRect.y, 0.0, 1.0);
verts[1] = *this * Point4DTyped<UnknownUnits, F>(aRect.XMost(), aRect.y, 0.0, 1.0);
verts[2] = *this * Point4DTyped<UnknownUnits, F>(aRect.XMost(), aRect.YMost(), 0.0, 1.0);
verts[3] = *this * Point4DTyped<UnknownUnits, F>(aRect.x, aRect.YMost(), 0.0, 1.0);
PointTyped<UnknownUnits, F> quad[4];
F min_x, max_x;
F min_y, max_y;
quad[0] = *this * aRect.TopLeft();
quad[1] = *this * aRect.TopRight();
quad[2] = *this * aRect.BottomLeft();
quad[3] = *this * aRect.BottomRight();
min_x = max_x = quad[0].x;
min_y = max_y = quad[0].y;
for (int i = 1; i < 4; i++) {
if (quad[i].x < min_x) {
min_x = quad[i].x;
}
if (quad[i].x > max_x) {
max_x = quad[i].x;
}
if (quad[i].y < min_y) {
min_y = quad[i].y;
}
if (quad[i].y > max_y) {
max_y = quad[i].y;
}
}
return RectTyped<UnknownUnits, F>(min_x, min_y, max_x - min_x, max_y - min_y);
}
template<class F>
Point4DTyped<UnknownUnits, F>
ComputePerspectivePlaneIntercept(const Point4DTyped<UnknownUnits, F>& aFirst,
const Point4DTyped<UnknownUnits, F>& aSecond)
{
// This function will always return a point with a w value of 0.
// The X, Y, and Z components will point towards an infinite vanishing
// point.
// We want to interpolate aFirst and aSecond to find the point intersecting
// with the w=0 plane.
// Since we know what we want the w component to be, we can rearrange the
// interpolation equation and solve for t.
float t = -aFirst.w / (aSecond.w - aFirst.w);
// Use t to find the remainder of the components
return aFirst + (aSecond - aFirst) * t;
}
template <class F>
RectTyped<UnknownUnits, F>
Matrix4x4::ProjectRectBounds(const RectTyped<UnknownUnits, F>& aRect, const RectTyped<UnknownUnits, F>& aClip) const
{
// This function must never return std::numeric_limits<Float>::max() or any
// other arbitrary large value in place of inifinity. This often occurs when
// aRect is an inversed projection matrix or when aRect is transformed to be
// partly behind and in front of the camera (w=0 plane in homogenous
// coordinates) - See Bug 1035611
// Some call-sites will call RoundGfxRectToAppRect which clips both the
// extents and dimensions of the rect to be bounded by nscoord_MAX.
// If we return a Rect that, when converted to nscoords, has a width or height
// greater than nscoord_MAX, RoundGfxRectToAppRect will clip the overflow
// off both the min and max end of the rect after clipping the extents of the
// rect, resulting in a translation of the rect towards the infinite end.
// The bounds returned by ProjectRectBounds are expected to be clipped only on
// the edges beyond the bounds of the coordinate system; otherwise, the
// clipped bounding box would be smaller than the correct one and result
// bugs such as incorrect culling (eg. Bug 1073056)
// To address this without requiring all code to work in homogenous
// coordinates or interpret infinite values correctly, a specialized
// clipping function is integrated into ProjectRectBounds.
// Callers should pass an aClip value that represents the extents to clip
// the result to, in the same coordinate system as aRect.
Point4DTyped<UnknownUnits, F> points[4];
points[0] = ProjectPoint(aRect.TopLeft());
points[1] = ProjectPoint(aRect.TopRight());
points[2] = ProjectPoint(aRect.BottomRight());
points[3] = ProjectPoint(aRect.BottomLeft());
F min_x = std::numeric_limits<F>::max();
F min_y = std::numeric_limits<F>::max();
F max_x = -std::numeric_limits<F>::max();
F max_y = -std::numeric_limits<F>::max();
for (int i=0; i<4; i++) {
// Only use points that exist above the w=0 plane
if (points[i].HasPositiveWCoord()) {
PointTyped<UnknownUnits, F> point2d = aClip.ClampPoint(points[i].As2DPoint());
min_x = std::min<F>(point2d.x, min_x);
max_x = std::max<F>(point2d.x, max_x);
min_y = std::min<F>(point2d.y, min_y);
max_y = std::max<F>(point2d.y, max_y);
}
int next = (i == 3) ? 0 : i + 1;
if (points[i].HasPositiveWCoord() != points[next].HasPositiveWCoord()) {
// If the line between two points crosses the w=0 plane, then interpolate
// to find the point of intersection with the w=0 plane and use that
// instead.
Point4DTyped<UnknownUnits, F> intercept =
ComputePerspectivePlaneIntercept(points[i], points[next]);
// Since intercept.w will always be 0 here, we interpret x,y,z as a
// direction towards an infinite vanishing point.
if (intercept.x < 0.0f) {
min_x = aClip.x;
} else if (intercept.x > 0.0f) {
max_x = aClip.XMost();
}
if (intercept.y < 0.0f) {
min_y = aClip.y;
} else if (intercept.y > 0.0f) {
max_y = aClip.YMost();
}
}
}
if (max_x < min_x || max_y < min_y) {
return RectTyped<UnknownUnits, F>(0, 0, 0, 0);
}
return RectTyped<UnknownUnits, F>(min_x, min_y, max_x - min_x, max_y - min_y);
}
template<class F>
size_t
Matrix4x4::TransformAndClipRect(const RectTyped<UnknownUnits, F>& aRect,
const RectTyped<UnknownUnits, F>& aClip,
PointTyped<UnknownUnits, F>* aVerts) const
{
// Initialize a double-buffered array of points in homogenous space with
// the input rectangle, aRect.
Point4DTyped<UnknownUnits, F> points[2][kTransformAndClipRectMaxVerts];
Point4DTyped<UnknownUnits, F>* dstPoint = points[0];
*dstPoint++ = *this * Point4DTyped<UnknownUnits, F>(aRect.x, aRect.y, 0, 1);
*dstPoint++ = *this * Point4DTyped<UnknownUnits, F>(aRect.XMost(), aRect.y, 0, 1);
*dstPoint++ = *this * Point4DTyped<UnknownUnits, F>(aRect.XMost(), aRect.YMost(), 0, 1);
*dstPoint++ = *this * Point4DTyped<UnknownUnits, F>(aRect.x, aRect.YMost(), 0, 1);
// View frustum clipping planes are described as normals originating from
// the 0,0,0,0 origin.
Point4DTyped<UnknownUnits, F> planeNormals[4];
planeNormals[0] = Point4DTyped<UnknownUnits, F>(1.0, 0.0, 0.0, -aClip.x);
planeNormals[1] = Point4DTyped<UnknownUnits, F>(-1.0, 0.0, 0.0, aClip.XMost());
planeNormals[2] = Point4DTyped<UnknownUnits, F>(0.0, 1.0, 0.0, -aClip.y);
planeNormals[3] = Point4DTyped<UnknownUnits, F>(0.0, -1.0, 0.0, aClip.YMost());
// Iterate through each clipping plane and clip the polygon.
// In each pass, we double buffer, alternating between points[0] and
// points[1].
for (int plane=0; plane < 4; plane++) {
planeNormals[plane].Normalize();
Point4DTyped<UnknownUnits, F>* srcPoint = points[plane & 1];
Point4DTyped<UnknownUnits, F>* srcPointEnd = dstPoint;
dstPoint = points[~plane & 1];
Point4DTyped<UnknownUnits, F>* prevPoint = srcPointEnd - 1;
F prevDot = planeNormals[plane].DotProduct(*prevPoint);
while (srcPoint < srcPointEnd) {
F nextDot = planeNormals[plane].DotProduct(*srcPoint);
if ((nextDot >= 0.0) != (prevDot >= 0.0)) {
// An intersection with the clipping plane has been detected.
// Interpolate to find the intersecting point and emit it.
F t = -prevDot / (nextDot - prevDot);
*dstPoint++ = *srcPoint * t + *prevPoint * (1.0 - t);
}
if (nextDot >= 0.0) {
// Emit any source points that are on the positive side of the
// clipping plane.
*dstPoint++ = *srcPoint;
}
prevPoint = srcPoint++;
prevDot = nextDot;
}
}
size_t dstPointCount = 0;
size_t srcPointCount = dstPoint - points[0];
for (Point4DTyped<UnknownUnits, F>* srcPoint = points[0]; srcPoint < points[0] + srcPointCount; srcPoint++) {
PointTyped<UnknownUnits, F> p;
if (srcPoint->w == 0.0) {
// If a point lies on the intersection of the clipping planes at
// (0,0,0,0), we must avoid a division by zero w component.
p = PointTyped<UnknownUnits, F>(0.0, 0.0);
} else {
p = srcPoint->As2DPoint();
}
// Emit only unique points
if (dstPointCount == 0 || p != aVerts[dstPointCount - 1]) {
aVerts[dstPointCount++] = p;
}
}
return dstPointCount;
}
bool
Matrix4x4::Invert()
{
Float det = Determinant();
if (!det) {
return false;
}
Matrix4x4 result;
result._11 = _23 * _34 * _42 - _24 * _33 * _42 + _24 * _32 * _43 - _22 * _34 * _43 - _23 * _32 * _44 + _22 * _33 * _44;
result._12 = _14 * _33 * _42 - _13 * _34 * _42 - _14 * _32 * _43 + _12 * _34 * _43 + _13 * _32 * _44 - _12 * _33 * _44;
result._13 = _13 * _24 * _42 - _14 * _23 * _42 + _14 * _22 * _43 - _12 * _24 * _43 - _13 * _22 * _44 + _12 * _23 * _44;
result._14 = _14 * _23 * _32 - _13 * _24 * _32 - _14 * _22 * _33 + _12 * _24 * _33 + _13 * _22 * _34 - _12 * _23 * _34;
result._21 = _24 * _33 * _41 - _23 * _34 * _41 - _24 * _31 * _43 + _21 * _34 * _43 + _23 * _31 * _44 - _21 * _33 * _44;
result._22 = _13 * _34 * _41 - _14 * _33 * _41 + _14 * _31 * _43 - _11 * _34 * _43 - _13 * _31 * _44 + _11 * _33 * _44;
result._23 = _14 * _23 * _41 - _13 * _24 * _41 - _14 * _21 * _43 + _11 * _24 * _43 + _13 * _21 * _44 - _11 * _23 * _44;
result._24 = _13 * _24 * _31 - _14 * _23 * _31 + _14 * _21 * _33 - _11 * _24 * _33 - _13 * _21 * _34 + _11 * _23 * _34;
result._31 = _22 * _34 * _41 - _24 * _32 * _41 + _24 * _31 * _42 - _21 * _34 * _42 - _22 * _31 * _44 + _21 * _32 * _44;
result._32 = _14 * _32 * _41 - _12 * _34 * _41 - _14 * _31 * _42 + _11 * _34 * _42 + _12 * _31 * _44 - _11 * _32 * _44;
result._33 = _12 * _24 * _41 - _14 * _22 * _41 + _14 * _21 * _42 - _11 * _24 * _42 - _12 * _21 * _44 + _11 * _22 * _44;
result._34 = _14 * _22 * _31 - _12 * _24 * _31 - _14 * _21 * _32 + _11 * _24 * _32 + _12 * _21 * _34 - _11 * _22 * _34;
result._41 = _23 * _32 * _41 - _22 * _33 * _41 - _23 * _31 * _42 + _21 * _33 * _42 + _22 * _31 * _43 - _21 * _32 * _43;
result._42 = _12 * _33 * _41 - _13 * _32 * _41 + _13 * _31 * _42 - _11 * _33 * _42 - _12 * _31 * _43 + _11 * _32 * _43;
result._43 = _13 * _22 * _41 - _12 * _23 * _41 - _13 * _21 * _42 + _11 * _23 * _42 + _12 * _21 * _43 - _11 * _22 * _43;
result._44 = _12 * _23 * _31 - _13 * _22 * _31 + _13 * _21 * _32 - _11 * _23 * _32 - _12 * _21 * _33 + _11 * _22 * _33;
result._11 /= det;
result._12 /= det;
result._13 /= det;
result._14 /= det;
result._21 /= det;
result._22 /= det;
result._23 /= det;
result._24 /= det;
result._31 /= det;
result._32 /= det;
result._33 /= det;
result._34 /= det;
result._41 /= det;
result._42 /= det;
result._43 /= det;
result._44 /= det;
*this = result;
return true;
}
void
Matrix4x4::SetNAN()
{
_11 = UnspecifiedNaN<Float>();
_21 = UnspecifiedNaN<Float>();
_31 = UnspecifiedNaN<Float>();
_41 = UnspecifiedNaN<Float>();
_12 = UnspecifiedNaN<Float>();
_22 = UnspecifiedNaN<Float>();
_32 = UnspecifiedNaN<Float>();
_42 = UnspecifiedNaN<Float>();
_13 = UnspecifiedNaN<Float>();
_23 = UnspecifiedNaN<Float>();
_33 = UnspecifiedNaN<Float>();
_43 = UnspecifiedNaN<Float>();
_14 = UnspecifiedNaN<Float>();
_24 = UnspecifiedNaN<Float>();
_34 = UnspecifiedNaN<Float>();
_44 = UnspecifiedNaN<Float>();
}
void
Matrix4x4::SetRotationFromQuaternion(const Quaternion& q)
{
const Float x2 = q.x + q.x, y2 = q.y + q.y, z2 = q.z + q.z;
const Float xx = q.x * x2, xy = q.x * y2, xz = q.x * z2;
const Float yy = q.y * y2, yz = q.y * z2, zz = q.z * z2;
const Float wx = q.w * x2, wy = q.w * y2, wz = q.w * z2;
_11 = 1.0f - (yy + zz);
_21 = xy + wz;
_31 = xz - wy;
_41 = 0.0f;
_12 = xy - wz;
_22 = 1.0f - (xx + zz);
_32 = yz + wx;
_42 = 0.0f;
_13 = xz + wy;
_23 = yz - wx;
_33 = 1.0f - (xx + yy);
_43 = 0.0f;
_14 = _42 = _43 = 0.0f;
_44 = 1.0f;
}
void
Matrix4x4::SkewXY(double aXSkew, double aYSkew)
{
// XXX Is double precision really necessary here
float tanX = SafeTangent(aXSkew);
float tanY = SafeTangent(aYSkew);
float temp;
temp = _11;
_11 += tanY * _21;
_21 += tanX * temp;
temp = _12;
_12 += tanY * _22;
_22 += tanX * temp;
temp = _13;
_13 += tanY * _23;
_23 += tanX * temp;
temp = _14;
_14 += tanY * _24;
_24 += tanX * temp;
}
void
Matrix4x4::RotateX(double aTheta)
{
// XXX Is double precision really necessary here
double cosTheta = FlushToZero(cos(aTheta));
double sinTheta = FlushToZero(sin(aTheta));
float temp;
temp = _21;
_21 = cosTheta * _21 + sinTheta * _31;
_31 = -sinTheta * temp + cosTheta * _31;
temp = _22;
_22 = cosTheta * _22 + sinTheta * _32;
_32 = -sinTheta * temp + cosTheta * _32;
temp = _23;
_23 = cosTheta * _23 + sinTheta * _33;
_33 = -sinTheta * temp + cosTheta * _33;
temp = _24;
_24 = cosTheta * _24 + sinTheta * _34;
_34 = -sinTheta * temp + cosTheta * _34;
}
void
Matrix4x4::RotateY(double aTheta)
{
// XXX Is double precision really necessary here
double cosTheta = FlushToZero(cos(aTheta));
double sinTheta = FlushToZero(sin(aTheta));
float temp;
temp = _11;
_11 = cosTheta * _11 + -sinTheta * _31;
_31 = sinTheta * temp + cosTheta * _31;
temp = _12;
_12 = cosTheta * _12 + -sinTheta * _32;
_32 = sinTheta * temp + cosTheta * _32;
temp = _13;
_13 = cosTheta * _13 + -sinTheta * _33;
_33 = sinTheta * temp + cosTheta * _33;
temp = _14;
_14 = cosTheta * _14 + -sinTheta * _34;
_34 = sinTheta * temp + cosTheta * _34;
}
void
Matrix4x4::RotateZ(double aTheta)
{
// XXX Is double precision really necessary here
double cosTheta = FlushToZero(cos(aTheta));
double sinTheta = FlushToZero(sin(aTheta));
float temp;
temp = _11;
_11 = cosTheta * _11 + sinTheta * _21;
_21 = -sinTheta * temp + cosTheta * _21;
temp = _12;
_12 = cosTheta * _12 + sinTheta * _22;
_22 = -sinTheta * temp + cosTheta * _22;
temp = _13;
_13 = cosTheta * _13 + sinTheta * _23;
_23 = -sinTheta * temp + cosTheta * _23;
temp = _14;
_14 = cosTheta * _14 + sinTheta * _24;
_24 = -sinTheta * temp + cosTheta * _24;
}
void
Matrix4x4::Perspective(float aDepth)
{
MOZ_ASSERT(aDepth > 0.0f, "Perspective must be positive!");
_31 += -1.0/aDepth * _41;
_32 += -1.0/aDepth * _42;
_33 += -1.0/aDepth * _43;
_34 += -1.0/aDepth * _44;
}
Point3D
Matrix4x4::GetNormalVector() const
{
// Define a plane in transformed space as the transformations
// of 3 points on the z=0 screen plane.
Point3D a = *this * Point3D(0, 0, 0);
Point3D b = *this * Point3D(0, 1, 0);
Point3D c = *this * Point3D(1, 0, 0);
// Convert to two vectors on the surface of the plane.
Point3D ab = b - a;
Point3D ac = c - a;
return ac.CrossProduct(ab);
}
template<class F>
RectTyped<UnknownUnits, F>
Matrix4x4::TransformAndClipBounds(const RectTyped<UnknownUnits, F>& aRect,
const RectTyped<UnknownUnits, F>& aClip) const
{
PointTyped<UnknownUnits, F> verts[kTransformAndClipRectMaxVerts];
size_t vertCount = TransformAndClipRect(aRect, aClip, verts);
F min_x = std::numeric_limits<F>::max();
F min_y = std::numeric_limits<F>::max();
F max_x = -std::numeric_limits<F>::max();
F max_y = -std::numeric_limits<F>::max();
for (size_t i=0; i < vertCount; i++) {
min_x = std::min(min_x, verts[i].x);
max_x = std::max(max_x, verts[i].x);
min_y = std::min(min_y, verts[i].y);
max_y = std::max(max_y, verts[i].y);
}
if (max_x < min_x || max_y < min_y) {
return RectTyped<UnknownUnits, F>(0, 0, 0, 0);
}
return RectTyped<UnknownUnits, F>(min_x, min_y, max_x - min_x, max_y - min_y);
}
// Explicit template instantiation for float and double precision
template
size_t
Matrix4x4::TransformAndClipRect(const Rect& aRect, const Rect& aClip,
Point* aVerts) const;
template
size_t
Matrix4x4::TransformAndClipRect(const RectDouble& aRect,
const RectDouble& aClip,
PointDouble* aVerts) const;
template
Rect
Matrix4x4::TransformAndClipBounds(const Rect& aRect,
const Rect& aClip) const;
template
RectDouble
Matrix4x4::TransformAndClipBounds(const RectDouble& aRect,
const RectDouble& aClip) const;
template
Rect
Matrix4x4::TransformBounds(const Rect& aRect) const;
template
RectDouble
Matrix4x4::TransformBounds(const RectDouble& aRect) const;
template
Rect
Matrix4x4::ProjectRectBounds(const Rect& aRect, const Rect& aClip) const;
template
RectDouble
Matrix4x4::ProjectRectBounds(const RectDouble& aRect, const RectDouble& aClip) const;
} // namespace gfx } // namespace gfx
} // namespace mozilla } // namespace mozilla

View File

@ -9,6 +9,7 @@
#include "Types.h" #include "Types.h"
#include "Rect.h" #include "Rect.h"
#include "Point.h" #include "Point.h"
#include "Quaternion.h"
#include <iosfwd> #include <iosfwd>
#include <math.h> #include <math.h>
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
@ -18,8 +19,6 @@
namespace mozilla { namespace mozilla {
namespace gfx { namespace gfx {
class Quaternion;
static bool FuzzyEqual(Float aV1, Float aV2) { static bool FuzzyEqual(Float aV1, Float aV2) {
// XXX - Check if fabs does the smart thing and just negates the sign bit. // XXX - Check if fabs does the smart thing and just negates the sign bit.
return fabs(aV2 - aV1) < 1e-6; return fabs(aV2 - aV1) < 1e-6;
@ -400,27 +399,64 @@ public:
} }
}; };
class Matrix4x4 // Helper functions used by Matrix4x4Typed defined in Matrix.cpp
double
SafeTangent(double aTheta);
double
FlushToZero(double aVal);
template<class Units, class F>
Point4DTyped<Units, F>
ComputePerspectivePlaneIntercept(const Point4DTyped<Units, F>& aFirst,
const Point4DTyped<Units, F>& aSecond)
{
// This function will always return a point with a w value of 0.
// The X, Y, and Z components will point towards an infinite vanishing
// point.
// We want to interpolate aFirst and aSecond to find the point intersecting
// with the w=0 plane.
// Since we know what we want the w component to be, we can rearrange the
// interpolation equation and solve for t.
float t = -aFirst.w / (aSecond.w - aFirst.w);
// Use t to find the remainder of the components
return aFirst + (aSecond - aFirst) * t;
}
template <typename SourceUnits, typename TargetUnits>
class Matrix4x4Typed
{ {
public: public:
Matrix4x4() typedef PointTyped<SourceUnits> SourcePoint;
typedef PointTyped<TargetUnits> TargetPoint;
typedef Point3DTyped<SourceUnits> SourcePoint3D;
typedef Point3DTyped<TargetUnits> TargetPoint3D;
typedef Point4DTyped<SourceUnits> SourcePoint4D;
typedef Point4DTyped<TargetUnits> TargetPoint4D;
typedef RectTyped<SourceUnits> SourceRect;
typedef RectTyped<TargetUnits> TargetRect;
Matrix4x4Typed()
: _11(1.0f), _12(0.0f), _13(0.0f), _14(0.0f) : _11(1.0f), _12(0.0f), _13(0.0f), _14(0.0f)
, _21(0.0f), _22(1.0f), _23(0.0f), _24(0.0f) , _21(0.0f), _22(1.0f), _23(0.0f), _24(0.0f)
, _31(0.0f), _32(0.0f), _33(1.0f), _34(0.0f) , _31(0.0f), _32(0.0f), _33(1.0f), _34(0.0f)
, _41(0.0f), _42(0.0f), _43(0.0f), _44(1.0f) , _41(0.0f), _42(0.0f), _43(0.0f), _44(1.0f)
{} {}
Matrix4x4(Float a11, Float a12, Float a13, Float a14, Matrix4x4Typed(Float a11, Float a12, Float a13, Float a14,
Float a21, Float a22, Float a23, Float a24, Float a21, Float a22, Float a23, Float a24,
Float a31, Float a32, Float a33, Float a34, Float a31, Float a32, Float a33, Float a34,
Float a41, Float a42, Float a43, Float a44) Float a41, Float a42, Float a43, Float a44)
: _11(a11), _12(a12), _13(a13), _14(a14) : _11(a11), _12(a12), _13(a13), _14(a14)
, _21(a21), _22(a22), _23(a23), _24(a24) , _21(a21), _22(a22), _23(a23), _24(a24)
, _31(a31), _32(a32), _33(a33), _34(a34) , _31(a31), _32(a32), _33(a33), _34(a34)
, _41(a41), _42(a42), _43(a43), _44(a44) , _41(a41), _42(a42), _43(a43), _44(a44)
{} {}
Matrix4x4(const Matrix4x4& aOther) Matrix4x4Typed(const Matrix4x4Typed& aOther)
{ {
memcpy(this, &aOther, sizeof(*this)); memcpy(this, &aOther, sizeof(*this));
} }
@ -430,7 +466,15 @@ public:
Float _31, _32, _33, _34; Float _31, _32, _33, _34;
Float _41, _42, _43, _44; Float _41, _42, _43, _44;
friend std::ostream& operator<<(std::ostream& aStream, const Matrix4x4& aMatrix); friend std::ostream& operator<<(std::ostream& aStream, const Matrix4x4Typed& aMatrix)
{
const Float *f = &aMatrix._11;
aStream << "[ " << f[0] << " " << f[1] << " " << f[2] << " " << f[3] << " ;" << std::endl; f += 4;
aStream << " " << f[0] << " " << f[1] << " " << f[2] << " " << f[3] << " ;" << std::endl; f += 4;
aStream << " " << f[0] << " " << f[1] << " " << f[2] << " " << f[3] << " ;" << std::endl; f += 4;
aStream << " " << f[0] << " " << f[1] << " " << f[2] << " " << f[3] << " ]" << std::endl;
return aStream;
}
Point4D& operator[](int aIndex) Point4D& operator[](int aIndex)
{ {
@ -496,7 +540,7 @@ public:
return true; return true;
} }
Matrix4x4& ProjectTo2D() { Matrix4x4Typed& ProjectTo2D() {
_31 = 0.0f; _31 = 0.0f;
_32 = 0.0f; _32 = 0.0f;
_13 = 0.0f; _13 = 0.0f;
@ -508,8 +552,8 @@ public:
} }
template<class F> template<class F>
Point4DTyped<UnknownUnits, F> Point4DTyped<TargetUnits, F>
ProjectPoint(const PointTyped<UnknownUnits, F>& aPoint) const { ProjectPoint(const PointTyped<SourceUnits, F>& aPoint) const {
// Find a value for z that will transform to 0. // Find a value for z that will transform to 0.
// The transformed value of z is computed as: // The transformed value of z is computed as:
@ -519,19 +563,116 @@ public:
F z = -(aPoint.x * _13 + aPoint.y * _23 + _43) / _33; F z = -(aPoint.x * _13 + aPoint.y * _23 + _43) / _33;
// Compute the transformed point // Compute the transformed point
return *this * Point4DTyped<UnknownUnits, F>(aPoint.x, aPoint.y, z, 1); return *this * Point4DTyped<SourceUnits, F>(aPoint.x, aPoint.y, z, 1);
} }
template<class F> template<class F>
RectTyped<UnknownUnits, F> RectTyped<TargetUnits, F>
ProjectRectBounds(const RectTyped<UnknownUnits, F>& aRect, const RectTyped<UnknownUnits, F>& aClip) const; ProjectRectBounds(const RectTyped<SourceUnits, F>& aRect, const RectTyped<TargetUnits, F>& aClip) const
{
// This function must never return std::numeric_limits<Float>::max() or any
// other arbitrary large value in place of inifinity. This often occurs when
// aRect is an inversed projection matrix or when aRect is transformed to be
// partly behind and in front of the camera (w=0 plane in homogenous
// coordinates) - See Bug 1035611
// Some call-sites will call RoundGfxRectToAppRect which clips both the
// extents and dimensions of the rect to be bounded by nscoord_MAX.
// If we return a Rect that, when converted to nscoords, has a width or height
// greater than nscoord_MAX, RoundGfxRectToAppRect will clip the overflow
// off both the min and max end of the rect after clipping the extents of the
// rect, resulting in a translation of the rect towards the infinite end.
// The bounds returned by ProjectRectBounds are expected to be clipped only on
// the edges beyond the bounds of the coordinate system; otherwise, the
// clipped bounding box would be smaller than the correct one and result
// bugs such as incorrect culling (eg. Bug 1073056)
// To address this without requiring all code to work in homogenous
// coordinates or interpret infinite values correctly, a specialized
// clipping function is integrated into ProjectRectBounds.
// Callers should pass an aClip value that represents the extents to clip
// the result to, in the same coordinate system as aRect.
Point4DTyped<TargetUnits, F> points[4];
points[0] = ProjectPoint(aRect.TopLeft());
points[1] = ProjectPoint(aRect.TopRight());
points[2] = ProjectPoint(aRect.BottomRight());
points[3] = ProjectPoint(aRect.BottomLeft());
F min_x = std::numeric_limits<F>::max();
F min_y = std::numeric_limits<F>::max();
F max_x = -std::numeric_limits<F>::max();
F max_y = -std::numeric_limits<F>::max();
for (int i=0; i<4; i++) {
// Only use points that exist above the w=0 plane
if (points[i].HasPositiveWCoord()) {
PointTyped<TargetUnits, F> point2d = aClip.ClampPoint(points[i].As2DPoint());
min_x = std::min<F>(point2d.x, min_x);
max_x = std::max<F>(point2d.x, max_x);
min_y = std::min<F>(point2d.y, min_y);
max_y = std::max<F>(point2d.y, max_y);
}
int next = (i == 3) ? 0 : i + 1;
if (points[i].HasPositiveWCoord() != points[next].HasPositiveWCoord()) {
// If the line between two points crosses the w=0 plane, then interpolate
// to find the point of intersection with the w=0 plane and use that
// instead.
Point4DTyped<TargetUnits, F> intercept =
ComputePerspectivePlaneIntercept(points[i], points[next]);
// Since intercept.w will always be 0 here, we interpret x,y,z as a
// direction towards an infinite vanishing point.
if (intercept.x < 0.0f) {
min_x = aClip.x;
} else if (intercept.x > 0.0f) {
max_x = aClip.XMost();
}
if (intercept.y < 0.0f) {
min_y = aClip.y;
} else if (intercept.y > 0.0f) {
max_y = aClip.YMost();
}
}
}
if (max_x < min_x || max_y < min_y) {
return RectTyped<TargetUnits, F>(0, 0, 0, 0);
}
return RectTyped<TargetUnits, F>(min_x, min_y, max_x - min_x, max_y - min_y);
}
/** /**
* TransformAndClipBounds transforms aRect as a bounding box, while clipping * TransformAndClipBounds transforms aRect as a bounding box, while clipping
* the transformed bounds to the extents of aClip. * the transformed bounds to the extents of aClip.
*/ */
template<class F> template<class F>
RectTyped<UnknownUnits, F> TransformAndClipBounds(const RectTyped<UnknownUnits, F>& aRect, const RectTyped<UnknownUnits, F>& aClip) const; RectTyped<TargetUnits, F> TransformAndClipBounds(const RectTyped<SourceUnits, F>& aRect,
const RectTyped<TargetUnits, F>& aClip) const
{
PointTyped<UnknownUnits, F> verts[kTransformAndClipRectMaxVerts];
size_t vertCount = TransformAndClipRect(aRect, aClip, verts);
F min_x = std::numeric_limits<F>::max();
F min_y = std::numeric_limits<F>::max();
F max_x = -std::numeric_limits<F>::max();
F max_y = -std::numeric_limits<F>::max();
for (size_t i=0; i < vertCount; i++) {
min_x = std::min(min_x, verts[i].x);
max_x = std::max(max_x, verts[i].x);
min_y = std::min(min_y, verts[i].y);
max_y = std::max(max_y, verts[i].y);
}
if (max_x < min_x || max_y < min_y) {
return RectTyped<TargetUnits, F>(0, 0, 0, 0);
}
return RectTyped<TargetUnits, F>(min_x, min_y, max_x - min_x, max_y - min_y);
}
/** /**
* TransformAndClipRect projects a rectangle and clips against view frustum * TransformAndClipRect projects a rectangle and clips against view frustum
@ -544,13 +685,85 @@ public:
* within aClip. * within aClip.
*/ */
template<class F> template<class F>
size_t TransformAndClipRect(const RectTyped<UnknownUnits, F>& aRect, size_t TransformAndClipRect(const RectTyped<SourceUnits, F>& aRect,
const RectTyped<UnknownUnits, F>& aClip, const RectTyped<TargetUnits, F>& aClip,
PointTyped<UnknownUnits, F>* aVerts) const; PointTyped<TargetUnits, F>* aVerts) const
{
// Initialize a double-buffered array of points in homogenous space with
// the input rectangle, aRect.
Point4DTyped<UnknownUnits, F> points[2][kTransformAndClipRectMaxVerts];
Point4DTyped<UnknownUnits, F>* dstPoint = points[0];
*dstPoint++ = *this * Point4DTyped<UnknownUnits, F>(aRect.x, aRect.y, 0, 1);
*dstPoint++ = *this * Point4DTyped<UnknownUnits, F>(aRect.XMost(), aRect.y, 0, 1);
*dstPoint++ = *this * Point4DTyped<UnknownUnits, F>(aRect.XMost(), aRect.YMost(), 0, 1);
*dstPoint++ = *this * Point4DTyped<UnknownUnits, F>(aRect.x, aRect.YMost(), 0, 1);
// View frustum clipping planes are described as normals originating from
// the 0,0,0,0 origin.
Point4DTyped<UnknownUnits, F> planeNormals[4];
planeNormals[0] = Point4DTyped<UnknownUnits, F>(1.0, 0.0, 0.0, -aClip.x);
planeNormals[1] = Point4DTyped<UnknownUnits, F>(-1.0, 0.0, 0.0, aClip.XMost());
planeNormals[2] = Point4DTyped<UnknownUnits, F>(0.0, 1.0, 0.0, -aClip.y);
planeNormals[3] = Point4DTyped<UnknownUnits, F>(0.0, -1.0, 0.0, aClip.YMost());
// Iterate through each clipping plane and clip the polygon.
// In each pass, we double buffer, alternating between points[0] and
// points[1].
for (int plane=0; plane < 4; plane++) {
planeNormals[plane].Normalize();
Point4DTyped<UnknownUnits, F>* srcPoint = points[plane & 1];
Point4DTyped<UnknownUnits, F>* srcPointEnd = dstPoint;
dstPoint = points[~plane & 1];
Point4DTyped<UnknownUnits, F>* prevPoint = srcPointEnd - 1;
F prevDot = planeNormals[plane].DotProduct(*prevPoint);
while (srcPoint < srcPointEnd) {
F nextDot = planeNormals[plane].DotProduct(*srcPoint);
if ((nextDot >= 0.0) != (prevDot >= 0.0)) {
// An intersection with the clipping plane has been detected.
// Interpolate to find the intersecting point and emit it.
F t = -prevDot / (nextDot - prevDot);
*dstPoint++ = *srcPoint * t + *prevPoint * (1.0 - t);
}
if (nextDot >= 0.0) {
// Emit any source points that are on the positive side of the
// clipping plane.
*dstPoint++ = *srcPoint;
}
prevPoint = srcPoint++;
prevDot = nextDot;
}
}
size_t dstPointCount = 0;
size_t srcPointCount = dstPoint - points[0];
for (Point4DTyped<UnknownUnits, F>* srcPoint = points[0]; srcPoint < points[0] + srcPointCount; srcPoint++) {
PointTyped<TargetUnits, F> p;
if (srcPoint->w == 0.0) {
// If a point lies on the intersection of the clipping planes at
// (0,0,0,0), we must avoid a division by zero w component.
p = PointTyped<TargetUnits, F>(0.0, 0.0);
} else {
p = srcPoint->As2DPoint();
}
// Emit only unique points
if (dstPointCount == 0 || p != aVerts[dstPointCount - 1]) {
aVerts[dstPointCount++] = p;
}
}
return dstPointCount;
}
static const size_t kTransformAndClipRectMaxVerts = 32; static const size_t kTransformAndClipRectMaxVerts = 32;
static Matrix4x4 From2D(const Matrix &aMatrix) { static Matrix4x4Typed From2D(const Matrix &aMatrix) {
Matrix4x4 matrix; Matrix4x4Typed matrix;
matrix._11 = aMatrix._11; matrix._11 = aMatrix._11;
matrix._12 = aMatrix._12; matrix._12 = aMatrix._12;
matrix._21 = aMatrix._21; matrix._21 = aMatrix._21;
@ -565,20 +778,20 @@ public:
return Is2D() && As2D().IsIntegerTranslation(); return Is2D() && As2D().IsIntegerTranslation();
} }
Point4D TransposeTransform4D(const Point4D& aPoint) const TargetPoint4D TransposeTransform4D(const SourcePoint4D& aPoint) const
{ {
Float x = aPoint.x * _11 + aPoint.y * _12 + aPoint.z * _13 + aPoint.w * _14; Float x = aPoint.x * _11 + aPoint.y * _12 + aPoint.z * _13 + aPoint.w * _14;
Float y = aPoint.x * _21 + aPoint.y * _22 + aPoint.z * _23 + aPoint.w * _24; Float y = aPoint.x * _21 + aPoint.y * _22 + aPoint.z * _23 + aPoint.w * _24;
Float z = aPoint.x * _31 + aPoint.y * _32 + aPoint.z * _33 + aPoint.w * _34; Float z = aPoint.x * _31 + aPoint.y * _32 + aPoint.z * _33 + aPoint.w * _34;
Float w = aPoint.x * _41 + aPoint.y * _42 + aPoint.z * _43 + aPoint.w * _44; Float w = aPoint.x * _41 + aPoint.y * _42 + aPoint.z * _43 + aPoint.w * _44;
return Point4D(x, y, z, w); return TargetPoint4D(x, y, z, w);
} }
template<class F> template<class F>
Point4DTyped<UnknownUnits, F> operator *(const Point4DTyped<UnknownUnits, F>& aPoint) const Point4DTyped<TargetUnits, F> operator *(const Point4DTyped<SourceUnits, F>& aPoint) const
{ {
Point4DTyped<UnknownUnits, F> retPoint; Point4DTyped<TargetUnits, F> retPoint;
retPoint.x = aPoint.x * _11 + aPoint.y * _21 + aPoint.z * _31 + _41; retPoint.x = aPoint.x * _11 + aPoint.y * _21 + aPoint.z * _31 + _41;
retPoint.y = aPoint.x * _12 + aPoint.y * _22 + aPoint.z * _32 + _42; retPoint.y = aPoint.x * _12 + aPoint.y * _22 + aPoint.z * _32 + _42;
@ -589,39 +802,73 @@ public:
} }
template<class F> template<class F>
Point3DTyped<UnknownUnits, F> operator *(const Point3DTyped<UnknownUnits, F>& aPoint) const Point3DTyped<TargetUnits, F> operator *(const Point3DTyped<SourceUnits, F>& aPoint) const
{ {
Point4DTyped<UnknownUnits, F> temp(aPoint.x, aPoint.y, aPoint.z, 1); Point4DTyped<SourceUnits, F> temp(aPoint.x, aPoint.y, aPoint.z, 1);
temp = *this * temp; Point4DTyped<TargetUnits, F> result = *this * temp;
temp /= temp.w; result /= result.w;
return Point3DTyped<UnknownUnits, F>(temp.x, temp.y, temp.z); return Point3DTyped<TargetUnits, F>(result.x, result.y, result.z);
} }
template<class F> template<class F>
PointTyped<UnknownUnits, F> operator *(const PointTyped<UnknownUnits, F> &aPoint) const PointTyped<TargetUnits, F> operator *(const PointTyped<SourceUnits, F> &aPoint) const
{ {
Point4DTyped<UnknownUnits, F> temp(aPoint.x, aPoint.y, 0, 1); Point4DTyped<SourceUnits, F> temp(aPoint.x, aPoint.y, 0, 1);
Point4DTyped<TargetUnits, F> result = *this * temp;
temp = *this * temp; return result.As2DPoint();
temp /= temp.w;
return PointTyped<UnknownUnits, F>(temp.x, temp.y);
} }
template<class F> template<class F>
GFX2D_API RectTyped<UnknownUnits, F> TransformBounds(const RectTyped<UnknownUnits, F>& aRect) const; GFX2D_API RectTyped<TargetUnits, F> TransformBounds(const RectTyped<SourceUnits, F>& aRect) const
static Matrix4x4 Translation(Float aX, Float aY, Float aZ)
{ {
return Matrix4x4(1.0f, 0.0f, 0.0f, 0.0f, Point4DTyped<TargetUnits, F> verts[4];
0.0f, 1.0f, 0.0f, 0.0f, verts[0] = *this * Point4DTyped<SourceUnits, F>(aRect.x, aRect.y, 0.0, 1.0);
0.0f, 0.0f, 1.0f, 0.0f, verts[1] = *this * Point4DTyped<SourceUnits, F>(aRect.XMost(), aRect.y, 0.0, 1.0);
aX, aY, aZ, 1.0f); verts[2] = *this * Point4DTyped<SourceUnits, F>(aRect.XMost(), aRect.YMost(), 0.0, 1.0);
verts[3] = *this * Point4DTyped<SourceUnits, F>(aRect.x, aRect.YMost(), 0.0, 1.0);
PointTyped<TargetUnits, F> quad[4];
F min_x, max_x;
F min_y, max_y;
quad[0] = *this * aRect.TopLeft();
quad[1] = *this * aRect.TopRight();
quad[2] = *this * aRect.BottomLeft();
quad[3] = *this * aRect.BottomRight();
min_x = max_x = quad[0].x;
min_y = max_y = quad[0].y;
for (int i = 1; i < 4; i++) {
if (quad[i].x < min_x) {
min_x = quad[i].x;
}
if (quad[i].x > max_x) {
max_x = quad[i].x;
}
if (quad[i].y < min_y) {
min_y = quad[i].y;
}
if (quad[i].y > max_y) {
max_y = quad[i].y;
}
}
return RectTyped<TargetUnits, F>(min_x, min_y, max_x - min_x, max_y - min_y);
} }
static Matrix4x4 Translation(const Point3D& aP) static Matrix4x4Typed Translation(Float aX, Float aY, Float aZ)
{
return Matrix4x4Typed(1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
aX, aY, aZ, 1.0f);
}
static Matrix4x4Typed Translation(const Point3D& aP)
{ {
return Translation(aP.x, aP.y, aP.z); return Translation(aP.x, aP.y, aP.z);
} }
@ -645,7 +892,7 @@ public:
* this method would be preferred since it only involves 12 floating-point * this method would be preferred since it only involves 12 floating-point
* multiplications.) * multiplications.)
*/ */
Matrix4x4 &PreTranslate(Float aX, Float aY, Float aZ) Matrix4x4Typed &PreTranslate(Float aX, Float aY, Float aZ)
{ {
_41 += aX * _11 + aY * _21 + aZ * _31; _41 += aX * _11 + aY * _21 + aZ * _31;
_42 += aX * _12 + aY * _22 + aZ * _32; _42 += aX * _12 + aY * _22 + aZ * _32;
@ -655,7 +902,7 @@ public:
return *this; return *this;
} }
Matrix4x4 &PreTranslate(const Point3D& aPoint) { Matrix4x4Typed &PreTranslate(const Point3D& aPoint) {
return PreTranslate(aPoint.x, aPoint.y, aPoint.z); return PreTranslate(aPoint.x, aPoint.y, aPoint.z);
} }
@ -671,7 +918,7 @@ public:
* the Post* methods add a transform to the device space end of the * the Post* methods add a transform to the device space end of the
* transformation. * transformation.
*/ */
Matrix4x4 &PostTranslate(Float aX, Float aY, Float aZ) Matrix4x4Typed &PostTranslate(Float aX, Float aY, Float aZ)
{ {
_11 += _14 * aX; _11 += _14 * aX;
_21 += _24 * aX; _21 += _24 * aX;
@ -689,22 +936,22 @@ public:
return *this; return *this;
} }
Matrix4x4 &PostTranslate(const Point3D& aPoint) { Matrix4x4Typed &PostTranslate(const Point3D& aPoint) {
return PostTranslate(aPoint.x, aPoint.y, aPoint.z); return PostTranslate(aPoint.x, aPoint.y, aPoint.z);
} }
static Matrix4x4 Scaling(Float aScaleX, Float aScaleY, float aScaleZ) static Matrix4x4Typed Scaling(Float aScaleX, Float aScaleY, float aScaleZ)
{ {
return Matrix4x4(aScaleX, 0.0f, 0.0f, 0.0f, return Matrix4x4Typed(aScaleX, 0.0f, 0.0f, 0.0f,
0.0f, aScaleY, 0.0f, 0.0f, 0.0f, aScaleY, 0.0f, 0.0f,
0.0f, 0.0f, aScaleZ, 0.0f, 0.0f, 0.0f, aScaleZ, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f); 0.0f, 0.0f, 0.0f, 1.0f);
} }
/** /**
* Similar to PreTranslate, but applies a scale instead of a translation. * Similar to PreTranslate, but applies a scale instead of a translation.
*/ */
Matrix4x4 &PreScale(Float aX, Float aY, Float aZ) Matrix4x4Typed &PreScale(Float aX, Float aY, Float aZ)
{ {
_11 *= aX; _11 *= aX;
_12 *= aX; _12 *= aX;
@ -725,7 +972,7 @@ public:
/** /**
* Similar to PostTranslate, but applies a scale instead of a translation. * Similar to PostTranslate, but applies a scale instead of a translation.
*/ */
Matrix4x4 &PostScale(Float aScaleX, Float aScaleY, Float aScaleZ) Matrix4x4Typed &PostScale(Float aScaleX, Float aScaleY, Float aScaleZ)
{ {
_11 *= aScaleX; _11 *= aScaleX;
_21 *= aScaleX; _21 *= aScaleX;
@ -758,12 +1005,12 @@ public:
(*this)[2] += (*this)[1] * aSkew; (*this)[2] += (*this)[1] * aSkew;
} }
Matrix4x4 &ChangeBasis(const Point3D& aOrigin) Matrix4x4Typed &ChangeBasis(const Point3D& aOrigin)
{ {
return ChangeBasis(aOrigin.x, aOrigin.y, aOrigin.z); return ChangeBasis(aOrigin.x, aOrigin.y, aOrigin.z);
} }
Matrix4x4 &ChangeBasis(Float aX, Float aY, Float aZ) Matrix4x4Typed &ChangeBasis(Float aX, Float aY, Float aZ)
{ {
// Translate to the origin before applying this matrix // Translate to the origin before applying this matrix
PreTranslate(-aX, -aY, -aZ); PreTranslate(-aX, -aY, -aZ);
@ -774,7 +1021,7 @@ public:
return *this; return *this;
} }
Matrix4x4& Transpose() { Matrix4x4Typed& Transpose() {
std::swap(_12, _21); std::swap(_12, _21);
std::swap(_13, _31); std::swap(_13, _31);
std::swap(_14, _41); std::swap(_14, _41);
@ -787,7 +1034,7 @@ public:
return *this; return *this;
} }
bool operator==(const Matrix4x4& o) const bool operator==(const Matrix4x4Typed& o) const
{ {
// XXX would be nice to memcmp here, but that breaks IEEE 754 semantics // XXX would be nice to memcmp here, but that breaks IEEE 754 semantics
return _11 == o._11 && _12 == o._12 && _13 == o._13 && _14 == o._14 && return _11 == o._11 && _12 == o._12 && _13 == o._13 && _14 == o._14 &&
@ -796,14 +1043,15 @@ public:
_41 == o._41 && _42 == o._42 && _43 == o._43 && _44 == o._44; _41 == o._41 && _42 == o._42 && _43 == o._43 && _44 == o._44;
} }
bool operator!=(const Matrix4x4& o) const bool operator!=(const Matrix4x4Typed& o) const
{ {
return !((*this) == o); return !((*this) == o);
} }
Matrix4x4 operator*(const Matrix4x4 &aMatrix) const template <typename NewTargetUnits>
Matrix4x4Typed<SourceUnits, NewTargetUnits> operator*(const Matrix4x4Typed<TargetUnits, NewTargetUnits> &aMatrix) const
{ {
Matrix4x4 matrix; Matrix4x4Typed<SourceUnits, NewTargetUnits> matrix;
matrix._11 = _11 * aMatrix._11 + _12 * aMatrix._21 + _13 * aMatrix._31 + _14 * aMatrix._41; matrix._11 = _11 * aMatrix._11 + _12 * aMatrix._21 + _13 * aMatrix._31 + _14 * aMatrix._41;
matrix._21 = _21 * aMatrix._11 + _22 * aMatrix._21 + _23 * aMatrix._31 + _24 * aMatrix._41; matrix._21 = _21 * aMatrix._11 + _22 * aMatrix._21 + _23 * aMatrix._31 + _24 * aMatrix._41;
@ -825,7 +1073,7 @@ public:
return matrix; return matrix;
} }
Matrix4x4& operator*=(const Matrix4x4 &aMatrix) Matrix4x4Typed& operator*=(const Matrix4x4Typed<TargetUnits, TargetUnits> &aMatrix)
{ {
*this = *this * aMatrix; *this = *this * aMatrix;
return *this; return *this;
@ -874,11 +1122,57 @@ public:
+ _11 * _22 * _33 * _44; + _11 * _22 * _33 * _44;
} }
bool Invert(); // Invert() is not unit-correct. Prefer Inverse() where possible.
bool Invert()
Matrix4x4 Inverse() const
{ {
Matrix4x4 clone = *this; Float det = Determinant();
if (!det) {
return false;
}
Matrix4x4Typed<SourceUnits, TargetUnits> result;
result._11 = _23 * _34 * _42 - _24 * _33 * _42 + _24 * _32 * _43 - _22 * _34 * _43 - _23 * _32 * _44 + _22 * _33 * _44;
result._12 = _14 * _33 * _42 - _13 * _34 * _42 - _14 * _32 * _43 + _12 * _34 * _43 + _13 * _32 * _44 - _12 * _33 * _44;
result._13 = _13 * _24 * _42 - _14 * _23 * _42 + _14 * _22 * _43 - _12 * _24 * _43 - _13 * _22 * _44 + _12 * _23 * _44;
result._14 = _14 * _23 * _32 - _13 * _24 * _32 - _14 * _22 * _33 + _12 * _24 * _33 + _13 * _22 * _34 - _12 * _23 * _34;
result._21 = _24 * _33 * _41 - _23 * _34 * _41 - _24 * _31 * _43 + _21 * _34 * _43 + _23 * _31 * _44 - _21 * _33 * _44;
result._22 = _13 * _34 * _41 - _14 * _33 * _41 + _14 * _31 * _43 - _11 * _34 * _43 - _13 * _31 * _44 + _11 * _33 * _44;
result._23 = _14 * _23 * _41 - _13 * _24 * _41 - _14 * _21 * _43 + _11 * _24 * _43 + _13 * _21 * _44 - _11 * _23 * _44;
result._24 = _13 * _24 * _31 - _14 * _23 * _31 + _14 * _21 * _33 - _11 * _24 * _33 - _13 * _21 * _34 + _11 * _23 * _34;
result._31 = _22 * _34 * _41 - _24 * _32 * _41 + _24 * _31 * _42 - _21 * _34 * _42 - _22 * _31 * _44 + _21 * _32 * _44;
result._32 = _14 * _32 * _41 - _12 * _34 * _41 - _14 * _31 * _42 + _11 * _34 * _42 + _12 * _31 * _44 - _11 * _32 * _44;
result._33 = _12 * _24 * _41 - _14 * _22 * _41 + _14 * _21 * _42 - _11 * _24 * _42 - _12 * _21 * _44 + _11 * _22 * _44;
result._34 = _14 * _22 * _31 - _12 * _24 * _31 - _14 * _21 * _32 + _11 * _24 * _32 + _12 * _21 * _34 - _11 * _22 * _34;
result._41 = _23 * _32 * _41 - _22 * _33 * _41 - _23 * _31 * _42 + _21 * _33 * _42 + _22 * _31 * _43 - _21 * _32 * _43;
result._42 = _12 * _33 * _41 - _13 * _32 * _41 + _13 * _31 * _42 - _11 * _33 * _42 - _12 * _31 * _43 + _11 * _32 * _43;
result._43 = _13 * _22 * _41 - _12 * _23 * _41 - _13 * _21 * _42 + _11 * _23 * _42 + _12 * _21 * _43 - _11 * _22 * _43;
result._44 = _12 * _23 * _31 - _13 * _22 * _31 + _13 * _21 * _32 - _11 * _23 * _32 - _12 * _21 * _33 + _11 * _22 * _33;
result._11 /= det;
result._12 /= det;
result._13 /= det;
result._14 /= det;
result._21 /= det;
result._22 /= det;
result._23 /= det;
result._24 /= det;
result._31 /= det;
result._32 /= det;
result._33 /= det;
result._34 /= det;
result._41 /= det;
result._42 /= det;
result._43 /= det;
result._44 /= det;
*this = result;
return true;
}
Matrix4x4Typed<TargetUnits, SourceUnits> Inverse() const
{
typedef Matrix4x4Typed<TargetUnits, SourceUnits> InvertedMatrix;
InvertedMatrix clone = InvertedMatrix::FromUnknownMatrix(ToUnknownMatrix());
DebugOnly<bool> inverted = clone.Invert(); DebugOnly<bool> inverted = clone.Invert();
MOZ_ASSERT(inverted, "Attempted to get the inverse of a non-invertible matrix"); MOZ_ASSERT(inverted, "Attempted to get the inverse of a non-invertible matrix");
return clone; return clone;
@ -893,7 +1187,7 @@ public:
} }
} }
bool FuzzyEqual(const Matrix4x4& o) const bool FuzzyEqual(const Matrix4x4Typed& o) const
{ {
return gfx::FuzzyEqual(_11, o._11) && gfx::FuzzyEqual(_12, o._12) && return gfx::FuzzyEqual(_11, o._11) && gfx::FuzzyEqual(_12, o._12) &&
gfx::FuzzyEqual(_13, o._13) && gfx::FuzzyEqual(_14, o._14) && gfx::FuzzyEqual(_13, o._13) && gfx::FuzzyEqual(_14, o._14) &&
@ -905,7 +1199,7 @@ public:
gfx::FuzzyEqual(_43, o._43) && gfx::FuzzyEqual(_44, o._44); gfx::FuzzyEqual(_43, o._43) && gfx::FuzzyEqual(_44, o._44);
} }
bool FuzzyEqualsMultiplicative(const Matrix4x4& o) const bool FuzzyEqualsMultiplicative(const Matrix4x4Typed& o) const
{ {
return ::mozilla::FuzzyEqualsMultiplicative(_11, o._11) && return ::mozilla::FuzzyEqualsMultiplicative(_11, o._11) &&
::mozilla::FuzzyEqualsMultiplicative(_12, o._12) && ::mozilla::FuzzyEqualsMultiplicative(_12, o._12) &&
@ -935,7 +1229,7 @@ public:
return (__33 * det) < 0; return (__33 * det) < 0;
} }
Matrix4x4 &NudgeToIntegersFixedEpsilon() Matrix4x4Typed &NudgeToIntegersFixedEpsilon()
{ {
NudgeToInteger(&_11); NudgeToInteger(&_11);
NudgeToInteger(&_12); NudgeToInteger(&_12);
@ -960,7 +1254,7 @@ public:
// Nudge the 3D components to integer so that this matrix will become 2D if // Nudge the 3D components to integer so that this matrix will become 2D if
// it's very close to already being 2D. // it's very close to already being 2D.
// This doesn't change the _41 and _42 components. // This doesn't change the _41 and _42 components.
Matrix4x4 &NudgeTo2D() Matrix4x4Typed &NudgeTo2D()
{ {
NudgeToInteger(&_13); NudgeToInteger(&_13);
NudgeToInteger(&_14); NudgeToInteger(&_14);
@ -993,22 +1287,175 @@ public:
// Sets this matrix to a rotation matrix given by aQuat. // Sets this matrix to a rotation matrix given by aQuat.
// This quaternion *MUST* be normalized! // This quaternion *MUST* be normalized!
// Implemented in Quaternion.cpp // Implemented in Quaternion.cpp
void SetRotationFromQuaternion(const Quaternion& aQuat); void SetRotationFromQuaternion(const Quaternion& q)
{
const Float x2 = q.x + q.x, y2 = q.y + q.y, z2 = q.z + q.z;
const Float xx = q.x * x2, xy = q.x * y2, xz = q.x * z2;
const Float yy = q.y * y2, yz = q.y * z2, zz = q.z * z2;
const Float wx = q.w * x2, wy = q.w * y2, wz = q.w * z2;
_11 = 1.0f - (yy + zz);
_21 = xy + wz;
_31 = xz - wy;
_41 = 0.0f;
_12 = xy - wz;
_22 = 1.0f - (xx + zz);
_32 = yz + wx;
_42 = 0.0f;
_13 = xz + wy;
_23 = yz - wx;
_33 = 1.0f - (xx + yy);
_43 = 0.0f;
_14 = _42 = _43 = 0.0f;
_44 = 1.0f;
}
// Set all the members of the matrix to NaN // Set all the members of the matrix to NaN
void SetNAN(); void SetNAN()
{
_11 = UnspecifiedNaN<Float>();
_21 = UnspecifiedNaN<Float>();
_31 = UnspecifiedNaN<Float>();
_41 = UnspecifiedNaN<Float>();
_12 = UnspecifiedNaN<Float>();
_22 = UnspecifiedNaN<Float>();
_32 = UnspecifiedNaN<Float>();
_42 = UnspecifiedNaN<Float>();
_13 = UnspecifiedNaN<Float>();
_23 = UnspecifiedNaN<Float>();
_33 = UnspecifiedNaN<Float>();
_43 = UnspecifiedNaN<Float>();
_14 = UnspecifiedNaN<Float>();
_24 = UnspecifiedNaN<Float>();
_34 = UnspecifiedNaN<Float>();
_44 = UnspecifiedNaN<Float>();
}
void SkewXY(double aXSkew, double aYSkew); void SkewXY(double aXSkew, double aYSkew)
{
// XXX Is double precision really necessary here
float tanX = SafeTangent(aXSkew);
float tanY = SafeTangent(aYSkew);
float temp;
void RotateX(double aTheta); temp = _11;
_11 += tanY * _21;
_21 += tanX * temp;
void RotateY(double aTheta); temp = _12;
_12 += tanY * _22;
_22 += tanX * temp;
void RotateZ(double aTheta); temp = _13;
_13 += tanY * _23;
_23 += tanX * temp;
void Perspective(float aDepth); temp = _14;
_14 += tanY * _24;
_24 += tanX * temp;
}
Point3D GetNormalVector() const; void RotateX(double aTheta)
{
// XXX Is double precision really necessary here
double cosTheta = FlushToZero(cos(aTheta));
double sinTheta = FlushToZero(sin(aTheta));
float temp;
temp = _21;
_21 = cosTheta * _21 + sinTheta * _31;
_31 = -sinTheta * temp + cosTheta * _31;
temp = _22;
_22 = cosTheta * _22 + sinTheta * _32;
_32 = -sinTheta * temp + cosTheta * _32;
temp = _23;
_23 = cosTheta * _23 + sinTheta * _33;
_33 = -sinTheta * temp + cosTheta * _33;
temp = _24;
_24 = cosTheta * _24 + sinTheta * _34;
_34 = -sinTheta * temp + cosTheta * _34;
}
void RotateY(double aTheta)
{
// XXX Is double precision really necessary here
double cosTheta = FlushToZero(cos(aTheta));
double sinTheta = FlushToZero(sin(aTheta));
float temp;
temp = _11;
_11 = cosTheta * _11 + -sinTheta * _31;
_31 = sinTheta * temp + cosTheta * _31;
temp = _12;
_12 = cosTheta * _12 + -sinTheta * _32;
_32 = sinTheta * temp + cosTheta * _32;
temp = _13;
_13 = cosTheta * _13 + -sinTheta * _33;
_33 = sinTheta * temp + cosTheta * _33;
temp = _14;
_14 = cosTheta * _14 + -sinTheta * _34;
_34 = sinTheta * temp + cosTheta * _34;
}
void RotateZ(double aTheta)
{
// XXX Is double precision really necessary here
double cosTheta = FlushToZero(cos(aTheta));
double sinTheta = FlushToZero(sin(aTheta));
float temp;
temp = _11;
_11 = cosTheta * _11 + sinTheta * _21;
_21 = -sinTheta * temp + cosTheta * _21;
temp = _12;
_12 = cosTheta * _12 + sinTheta * _22;
_22 = -sinTheta * temp + cosTheta * _22;
temp = _13;
_13 = cosTheta * _13 + sinTheta * _23;
_23 = -sinTheta * temp + cosTheta * _23;
temp = _14;
_14 = cosTheta * _14 + sinTheta * _24;
_24 = -sinTheta * temp + cosTheta * _24;
}
void Perspective(float aDepth)
{
MOZ_ASSERT(aDepth > 0.0f, "Perspective must be positive!");
_31 += -1.0/aDepth * _41;
_32 += -1.0/aDepth * _42;
_33 += -1.0/aDepth * _43;
_34 += -1.0/aDepth * _44;
}
Point3D GetNormalVector() const
{
// Define a plane in transformed space as the transformations
// of 3 points on the z=0 screen plane.
Point3D a = *this * Point3D(0, 0, 0);
Point3D b = *this * Point3D(0, 1, 0);
Point3D c = *this * Point3D(1, 0, 0);
// Convert to two vectors on the surface of the plane.
Point3D ab = b - a;
Point3D ac = c - a;
return ac.CrossProduct(ab);
}
/** /**
* Returns true if the matrix has any transform other * Returns true if the matrix has any transform other
@ -1039,8 +1486,26 @@ public:
bool HasPerspectiveComponent() const { bool HasPerspectiveComponent() const {
return _14 != 0 || _24 != 0 || _34 != 0 || _44 != 1; return _14 != 0 || _24 != 0 || _34 != 0 || _44 != 1;
} }
/**
* Convert between typed and untyped matrices.
*/
Matrix4x4 ToUnknownMatrix() const {
return Matrix4x4{_11, _12, _13, _14,
_21, _22, _23, _24,
_31, _32, _33, _34,
_41, _42, _43, _44};
}
static Matrix4x4Typed FromUnknownMatrix(const Matrix4x4& aUnknown) {
return Matrix4x4Typed{aUnknown._11, aUnknown._12, aUnknown._13, aUnknown._14,
aUnknown._21, aUnknown._22, aUnknown._23, aUnknown._24,
aUnknown._31, aUnknown._32, aUnknown._33, aUnknown._34,
aUnknown._41, aUnknown._42, aUnknown._43, aUnknown._44};
}
}; };
typedef Matrix4x4Typed<UnknownUnits, UnknownUnits> Matrix4x4;
class Matrix5x4 class Matrix5x4
{ {
public: public:

26
gfx/2d/MatrixFwd.h Normal file
View File

@ -0,0 +1,26 @@
/* -*- 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/. */
#ifndef MOZILLA_GFX_MATRIX_FWD_H_
#define MOZILLA_GFX_MATRIX_FWD_H_
// Forward declare enough things to define the typedef |Matrix4x4|.
namespace mozilla {
namespace gfx {
struct UnknownUnits;
template<class SourceUnits, class TargetUnits>
class Matrix4x4Typed;
typedef Matrix4x4Typed<UnknownUnits, UnknownUnits> Matrix4x4;
} // namespace gfx
} // namespace mozilla
#endif

View File

@ -10,12 +10,11 @@
#include <math.h> #include <math.h>
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/DebugOnly.h" #include "mozilla/DebugOnly.h"
#include "mozilla/gfx/MatrixFwd.h"
namespace mozilla { namespace mozilla {
namespace gfx { namespace gfx {
class Matrix4x4;
class Quaternion class Quaternion
{ {
public: public:

View File

@ -32,6 +32,7 @@ EXPORTS.mozilla.gfx += [
'JobScheduler_win32.h', 'JobScheduler_win32.h',
'Logging.h', 'Logging.h',
'Matrix.h', 'Matrix.h',
'MatrixFwd.h',
'NumericTools.h', 'NumericTools.h',
'PathHelpers.h', 'PathHelpers.h',
'PatternHelpers.h', 'PatternHelpers.h',

View File

@ -13,17 +13,12 @@
#include "gfxPlatform.h" #include "gfxPlatform.h"
#include "GLDefs.h" #include "GLDefs.h"
#include "mozilla/gfx/2D.h" #include "mozilla/gfx/2D.h"
#include "mozilla/gfx/MatrixFwd.h"
#include "mozilla/Monitor.h" #include "mozilla/Monitor.h"
#include "SurfaceTexture.h" #include "SurfaceTexture.h"
#include "AndroidNativeWindow.h" #include "AndroidNativeWindow.h"
namespace mozilla {
namespace gfx {
class Matrix4x4;
}
}
namespace mozilla { namespace mozilla {
namespace gl { namespace gl {

View File

@ -19,9 +19,6 @@
#endif #endif
namespace mozilla { namespace mozilla {
namespace gfx {
class Matrix4x4;
} // namespace gfx
namespace layers { namespace layers {

View File

@ -9,6 +9,7 @@
#include "Units.h" // for ScreenPoint #include "Units.h" // for ScreenPoint
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/RefPtr.h" // for already_AddRefed, RefCounted #include "mozilla/RefPtr.h" // for already_AddRefed, RefCounted
#include "mozilla/gfx/MatrixFwd.h" // for Matrix4x4
#include "mozilla/gfx/Point.h" // for IntSize, Point #include "mozilla/gfx/Point.h" // for IntSize, Point
#include "mozilla/gfx/Rect.h" // for Rect, IntRect #include "mozilla/gfx/Rect.h" // for Rect, IntRect
#include "mozilla/gfx/Types.h" // for Float #include "mozilla/gfx/Types.h" // for Float
@ -110,7 +111,6 @@ class nsIWidget;
namespace mozilla { namespace mozilla {
namespace gfx { namespace gfx {
class Matrix; class Matrix;
class Matrix4x4;
class DrawTarget; class DrawTarget;
} // namespace gfx } // namespace gfx

View File

@ -7,6 +7,7 @@
#define GFX_LAYERSLOGGING_H #define GFX_LAYERSLOGGING_H
#include "FrameMetrics.h" // for FrameMetrics, etc #include "FrameMetrics.h" // for FrameMetrics, etc
#include "mozilla/gfx/MatrixFwd.h" // for Matrix4x4
#include "mozilla/gfx/Point.h" // for IntSize, etc #include "mozilla/gfx/Point.h" // for IntSize, etc
#include "mozilla/gfx/Types.h" // for Filter, SurfaceFormat #include "mozilla/gfx/Types.h" // for Filter, SurfaceFormat
#include "mozilla/layers/CompositorTypes.h" // for TextureFlags #include "mozilla/layers/CompositorTypes.h" // for TextureFlags
@ -17,7 +18,6 @@
namespace mozilla { namespace mozilla {
namespace gfx { namespace gfx {
class Matrix4x4;
template <class units, class F> struct RectTyped; template <class units, class F> struct RectTyped;
} // namespace gfx } // namespace gfx

View File

@ -12,6 +12,7 @@
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/Attributes.h" // for override #include "mozilla/Attributes.h" // for override
#include "mozilla/RefPtr.h" // for RefPtr, RefCounted, etc #include "mozilla/RefPtr.h" // for RefPtr, RefCounted, etc
#include "mozilla/gfx/MatrixFwd.h" // for Matrix4x4
#include "mozilla/gfx/Point.h" // for Point #include "mozilla/gfx/Point.h" // for Point
#include "mozilla/gfx/Rect.h" // for Rect #include "mozilla/gfx/Rect.h" // for Rect
#include "mozilla/gfx/Types.h" // for Filter #include "mozilla/gfx/Types.h" // for Filter
@ -30,7 +31,6 @@
namespace mozilla { namespace mozilla {
namespace gfx { namespace gfx {
class Matrix4x4;
class DataSourceSurface; class DataSourceSurface;
} // namespace gfx } // namespace gfx

View File

@ -18,9 +18,6 @@
#include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL #include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL
namespace mozilla { namespace mozilla {
namespace gfx {
class Matrix4x4;
} // namespace gfx
using namespace gfx; using namespace gfx;
namespace layers { namespace layers {

View File

@ -14,6 +14,7 @@
#include "mozilla/Attributes.h" // for override #include "mozilla/Attributes.h" // for override
#include "mozilla/RefPtr.h" // for RefPtr #include "mozilla/RefPtr.h" // for RefPtr
#include "mozilla/gfx/BasePoint.h" // for BasePoint #include "mozilla/gfx/BasePoint.h" // for BasePoint
#include "mozilla/gfx/MatrixFwd.h" // for Matrix4x4
#include "mozilla/gfx/Point.h" // for Point #include "mozilla/gfx/Point.h" // for Point
#include "mozilla/gfx/Rect.h" // for Rect #include "mozilla/gfx/Rect.h" // for Rect
#include "mozilla/gfx/Types.h" // for Filter #include "mozilla/gfx/Types.h" // for Filter
@ -34,9 +35,6 @@
#include "nscore.h" // for nsACString #include "nscore.h" // for nsACString
namespace mozilla { namespace mozilla {
namespace gfx {
class Matrix4x4;
} // namespace gfx
namespace layers { namespace layers {
class Compositor; class Compositor;
class ThebesBufferData; class ThebesBufferData;

View File

@ -20,9 +20,6 @@
#define BIAS_TIME_MS 1.0 #define BIAS_TIME_MS 1.0
namespace mozilla { namespace mozilla {
namespace gfx {
class Matrix4x4;
} // namespace gfx
using namespace gfx; using namespace gfx;

View File

@ -10,6 +10,7 @@
#include "CompositableHost.h" // for CompositableHost #include "CompositableHost.h" // for CompositableHost
#include "mozilla/Attributes.h" // for override #include "mozilla/Attributes.h" // for override
#include "mozilla/RefPtr.h" // for RefPtr #include "mozilla/RefPtr.h" // for RefPtr
#include "mozilla/gfx/MatrixFwd.h" // for Matrix4x4
#include "mozilla/gfx/Point.h" // for Point #include "mozilla/gfx/Point.h" // for Point
#include "mozilla/gfx/Rect.h" // for Rect #include "mozilla/gfx/Rect.h" // for Rect
#include "mozilla/gfx/Types.h" // for Filter #include "mozilla/gfx/Types.h" // for Filter
@ -24,9 +25,6 @@
#include "nscore.h" // for nsACString #include "nscore.h" // for nsACString
namespace mozilla { namespace mozilla {
namespace gfx {
class Matrix4x4;
} // namespace gfx
namespace layers { namespace layers {
class Compositor; class Compositor;

View File

@ -15,6 +15,7 @@
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/Attributes.h" // for override #include "mozilla/Attributes.h" // for override
#include "mozilla/RefPtr.h" // for RefPtr #include "mozilla/RefPtr.h" // for RefPtr
#include "mozilla/gfx/MatrixFwd.h" // for Matrix4x4
#include "mozilla/gfx/Point.h" // for Point #include "mozilla/gfx/Point.h" // for Point
#include "mozilla/gfx/Rect.h" // for Rect #include "mozilla/gfx/Rect.h" // for Rect
#include "mozilla/gfx/Types.h" // for Filter #include "mozilla/gfx/Types.h" // for Filter
@ -32,9 +33,6 @@
#endif #endif
namespace mozilla { namespace mozilla {
namespace gfx {
class Matrix4x4;
} // namespace gfx
namespace layers { namespace layers {

View File

@ -17,6 +17,7 @@
#include "mozilla/RefPtr.h" // for already_AddRefed, RefPtr #include "mozilla/RefPtr.h" // for already_AddRefed, RefPtr
#include "mozilla/gfx/2D.h" // for DrawTarget #include "mozilla/gfx/2D.h" // for DrawTarget
#include "mozilla/gfx/BaseSize.h" // for BaseSize #include "mozilla/gfx/BaseSize.h" // for BaseSize
#include "mozilla/gfx/MatrixFwd.h" // for Matrix4x4
#include "mozilla/gfx/Point.h" // for IntSize, Point #include "mozilla/gfx/Point.h" // for IntSize, Point
#include "mozilla/gfx/Rect.h" // for Rect, IntRect #include "mozilla/gfx/Rect.h" // for Rect, IntRect
#include "mozilla/gfx/Types.h" // for Float, SurfaceFormat, etc #include "mozilla/gfx/Types.h" // for Float, SurfaceFormat, etc
@ -37,10 +38,6 @@ class nsIWidget;
namespace mozilla { namespace mozilla {
namespace gfx {
class Matrix4x4;
} // namespace gfx
namespace layers { namespace layers {
class CompositingRenderTarget; class CompositingRenderTarget;

View File

@ -21,12 +21,7 @@
#include "nsStringGlue.h" // for nsCString #include "nsStringGlue.h" // for nsCString
#include "xpcom-config.h" // for CPP_THROW_NEW #include "xpcom-config.h" // for CPP_THROW_NEW
#include "mozilla/Move.h" // for mozilla::Move #include "mozilla/Move.h" // for mozilla::Move
#include "mozilla/gfx/MatrixFwd.h" // for mozilla::gfx::Matrix4x4
namespace mozilla {
namespace gfx {
class Matrix4x4;
} // namespace gfx
} // namespace mozilla
#include "pixman.h" #include "pixman.h"

View File

@ -10,12 +10,7 @@
#include "gfxTypes.h" #include "gfxTypes.h"
#include "gfxRect.h" #include "gfxRect.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/gfx/MatrixFwd.h"
namespace mozilla {
namespace gfx {
class Matrix4x4;
} // namespace gfx
} // namespace mozilla
// XX - I don't think this class should use gfxFloat at all, // XX - I don't think this class should use gfxFloat at all,
// but should use 'double' and be called gfxDoubleMatrix; // but should use 'double' and be called gfxDoubleMatrix;

View File

@ -12,14 +12,9 @@
#include "nsRect.h" #include "nsRect.h"
#include "mozilla/gfx/BaseMargin.h" #include "mozilla/gfx/BaseMargin.h"
#include "mozilla/gfx/BaseRect.h" #include "mozilla/gfx/BaseRect.h"
#include "mozilla/gfx/MatrixFwd.h"
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
namespace mozilla {
namespace gfx {
class Matrix4x4;
} // namepsace gfx
} // namespace mozilla
struct gfxQuad; struct gfxQuad;
struct gfxMargin : public mozilla::gfx::BaseMargin<gfxFloat, gfxMargin> { struct gfxMargin : public mozilla::gfx::BaseMargin<gfxFloat, gfxMargin> {

View File

@ -12,6 +12,7 @@
#include "nsRegion.h" #include "nsRegion.h"
#include "nsIFrame.h" #include "nsIFrame.h"
#include "DisplayItemClip.h" #include "DisplayItemClip.h"
#include "mozilla/gfx/MatrixFwd.h"
#include "mozilla/layers/LayersTypes.h" #include "mozilla/layers/LayersTypes.h"
#include "LayerState.h" #include "LayerState.h"
#include "LayerUserData.h" #include "LayerUserData.h"
@ -31,10 +32,6 @@ class PaintedLayer;
class ImageLayer; class ImageLayer;
} // namespace layers } // namespace layers
namespace gfx {
class Matrix4x4;
} // namespace gfx
class FrameLayerBuilder; class FrameLayerBuilder;
class LayerManagerData; class LayerManagerData;
class PaintedLayerData; class PaintedLayerData;

View File

@ -8,6 +8,7 @@
#ifndef mozilla_StyleAnimationValue_h_ #ifndef mozilla_StyleAnimationValue_h_
#define mozilla_StyleAnimationValue_h_ #define mozilla_StyleAnimationValue_h_
#include "mozilla/gfx/MatrixFwd.h"
#include "nsStringFwd.h" #include "nsStringFwd.h"
#include "nsStringBuffer.h" #include "nsStringBuffer.h"
#include "nsCoord.h" #include "nsCoord.h"
@ -29,10 +30,6 @@ namespace dom {
class Element; class Element;
} // namespace dom } // namespace dom
namespace gfx {
class Matrix4x4;
} // namespace gfx
struct PropertyStyleAnimationValuePair; struct PropertyStyleAnimationValuePair;
/** /**

View File

@ -13,6 +13,7 @@
#include "Units.h" #include "Units.h"
#include "mozilla/EventForwards.h" #include "mozilla/EventForwards.h"
#include "mozilla/TimeStamp.h" #include "mozilla/TimeStamp.h"
#include "mozilla/gfx/MatrixFwd.h"
template<class E> struct already_AddRefed; template<class E> struct already_AddRefed;
class nsIWidget; class nsIWidget;
@ -23,10 +24,6 @@ namespace dom {
class Touch; class Touch;
} // namespace dom } // namespace dom
namespace gfx {
class Matrix4x4;
} // namespace gfx
enum InputType enum InputType
{ {
MULTITOUCH_INPUT, MULTITOUCH_INPUT,