Bug 1377090 - Make the Matrix class templated so we can instantiate it with a double type. r=bas
authorKartikaya Gupta <kgupta@mozilla.com>
Wed, 05 Jul 2017 11:18:48 -0400
changeset 367401 aecdc7b7c8303f80717392bfc8a977ab4132d2ff
parent 367400 051408cf1c53ae86857be4354d54792b5514b61e
child 367402 e6f68aad8e3db6b209b0cbc5eb9eb1f6858548e3
push id32134
push userkwierso@gmail.com
push dateWed, 05 Jul 2017 23:45:30 +0000
treeherdermozilla-central@e25d645e59ea [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbas
bugs1377090
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1377090 - Make the Matrix class templated so we can instantiate it with a double type. r=bas This extracts a BaseMatrix template of which Matrix is now a particular specialization. The BaseMatrix allows us to reuse the same code for floats and doubles, much like the other "base" classes (BasePoint, BaseRect, etc.). MozReview-Commit-ID: HO7bA83S9E0
dom/ipc/PBrowser.ipdl
dom/svg/SVGContentUtils.h
dom/svg/SVGMotionSMILType.h
dom/svg/nsSVGElement.h
gfx/2d/Matrix.cpp
gfx/2d/Matrix.h
gfx/2d/MatrixFwd.h
gfx/layers/Compositor.h
gfx/layers/RotatedBuffer.h
layout/base/Units.h
layout/generic/nsIFrame.h
layout/svg/nsSVGDisplayableFrame.h
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -28,17 +28,17 @@ include JavaScriptTypes;
 include URIParams;
 include PPrintingTypes;
 include PTabContext;
 
 include "mozilla/GfxMessageUtils.h";
 include "mozilla/layers/LayersMessageUtils.h";
 
 using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h";
-using class mozilla::gfx::Matrix from "mozilla/gfx/Matrix.h";
+using mozilla::gfx::Matrix from "mozilla/gfx/Matrix.h";
 using mozilla::LayoutDeviceIntPoint from "Units.h";
 using mozilla::LayoutDevicePoint from "Units.h";
 using mozilla::ScreenIntPoint from "Units.h";
 using ScreenIntSize from "Units.h";
 using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
 using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
 using struct mozilla::layers::ZoomConstraints from "FrameMetrics.h";
 using mozilla::layers::MaybeZoomConstraints from "FrameMetrics.h";
--- a/dom/svg/SVGContentUtils.h
+++ b/dom/svg/SVGContentUtils.h
@@ -29,19 +29,16 @@ class nsSVGAnimatedTransformList;
 class SVGAnimatedPreserveAspectRatio;
 class SVGContextPaint;
 class SVGPreserveAspectRatio;
 namespace dom {
 class Element;
 class SVGSVGElement;
 } // namespace dom
 
-namespace gfx {
-class Matrix;
-} // namespace gfx
 } // namespace mozilla
 
 #define SVG_ZERO_LENGTH_PATH_FIX_FACTOR 512
 
 /**
  * SVGTransformTypes controls the transforms that PrependLocalTransformsTo
  * applies.
  *
--- a/dom/svg/SVGMotionSMILType.h
+++ b/dom/svg/SVGMotionSMILType.h
@@ -12,20 +12,16 @@
 #include "mozilla/gfx/2D.h"
 #include "mozilla/Attributes.h"
 #include "nsISMILType.h"
 
 class nsSMILValue;
 
 namespace mozilla {
 
-namespace gfx {
-class Matrix;
-} // namespace gfx
-
 /**
  * MotionRotateType: Enum to indicate the type of our "rotate" attribute.
  */
 enum RotateType {
   eRotateType_Explicit,     // for e.g. rotate="45"/"45deg"/"0.785rad"
   eRotateType_Auto,         // for rotate="auto"
   eRotateType_AutoReverse   // for rotate="auto-reverse"
 };
--- a/dom/svg/nsSVGElement.h
+++ b/dom/svg/nsSVGElement.h
@@ -15,16 +15,17 @@
 #include "mozilla/Attributes.h"
 #include "nsAutoPtr.h"
 #include "nsChangeHint.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsError.h"
 #include "mozilla/dom/DOMRect.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/gfx/MatrixFwd.h"
 #include "nsISupportsImpl.h"
 #include "nsStyledElement.h"
 #include "nsSVGClass.h"
 #include "nsIDOMSVGElement.h"
 #include "SVGContentUtils.h"
 
 class nsSVGAngle;
 class nsSVGBoolean;
@@ -55,20 +56,16 @@ class SVGAnimatedLengthList;
 class SVGUserUnitList;
 class SVGAnimatedPointList;
 class SVGAnimatedPathSegList;
 class SVGAnimatedPreserveAspectRatio;
 class nsSVGAnimatedTransformList;
 class SVGStringList;
 class DOMSVGStringList;
 
-namespace gfx {
-class Matrix;
-} // namespace gfx
-
 } // namespace mozilla
 
 class gfxMatrix;
 struct nsSVGEnumMapping;
 
 typedef nsStyledElement nsSVGElementBase;
 
 class nsSVGElement : public nsSVGElementBase    // nsIContent
--- a/gfx/2d/Matrix.cpp
+++ b/gfx/2d/Matrix.cpp
@@ -54,45 +54,33 @@ SafeTangent(double aTheta)
   if (cosTheta >= 0 && cosTheta < kEpsilon) {
     cosTheta = kEpsilon;
   } else if (cosTheta < 0 && cosTheta >= -kEpsilon) {
     cosTheta = -kEpsilon;
   }
   return FlushToZero(sinTheta / cosTheta);
 }
 
-std::ostream&
-operator<<(std::ostream& aStream, const Matrix& aMatrix)
-{
-  return aStream << "[ " << aMatrix._11
-                 << " "  << aMatrix._12
-                 << "; " << aMatrix._21
-                 << " "  << aMatrix._22
-                 << "; " << aMatrix._31
-                 << " "  << aMatrix._32
-                 << "; ]";
-}
-
-Matrix
+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;
 }
 
-Rect
+template<> Rect
 Matrix::TransformBounds(const Rect &aRect) const
 {
   int i;
   Point quad[4];
   Float min_x, max_x;
   Float min_y, max_y;
 
   quad[0] = TransformPoint(aRect.TopLeft());
@@ -113,17 +101,17 @@ Matrix::TransformBounds(const Rect &aRec
       min_y = quad[i].y;
     if (quad[i].y > max_y)
       max_y = quad[i].y;
   }
 
   return Rect(min_x, min_y, max_x - min_x, max_y - min_y);
 }
 
-Matrix&
+template<> Matrix&
 Matrix::NudgeToIntegers()
 {
   NudgeToInteger(&_11);
   NudgeToInteger(&_12);
   NudgeToInteger(&_21);
   NudgeToInteger(&_22);
   NudgeToInteger(&_31);
   NudgeToInteger(&_32);
--- a/gfx/2d/Matrix.h
+++ b/gfx/2d/Matrix.h
@@ -15,49 +15,59 @@
 #include <math.h>
 #include "mozilla/Attributes.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/FloatingPoint.h"
 
 namespace mozilla {
 namespace gfx {
 
-static bool FuzzyEqual(Float aV1, Float aV2) {
+static inline bool FuzzyEqual(Float aV1, Float aV2) {
   // XXX - Check if fabs does the smart thing and just negates the sign bit.
   return fabs(aV2 - aV1) < 1e-6;
 }
 
-class Matrix
+template<class T>
+class BaseMatrix
 {
 public:
-  Matrix()
+  BaseMatrix()
     : _11(1.0f), _12(0)
     , _21(0), _22(1.0f)
     , _31(0), _32(0)
   {}
-  Matrix(Float a11, Float a12, Float a21, Float a22, Float a31, Float a32)
+  BaseMatrix(T a11, T a12, T a21, T a22, T a31, T a32)
     : _11(a11), _12(a12)
     , _21(a21), _22(a22)
     , _31(a31), _32(a32)
   {}
   union {
     struct {
-      Float _11, _12;
-      Float _21, _22;
-      Float _31, _32;
+      T _11, _12;
+      T _21, _22;
+      T _31, _32;
     };
-    Float components[6];
+    T components[6];
   };
 
-  MOZ_ALWAYS_INLINE Matrix Copy() const
+  MOZ_ALWAYS_INLINE BaseMatrix Copy() const
   {
-    return Matrix(*this);
+    return BaseMatrix<T>(*this);
   }
 
-  friend std::ostream& operator<<(std::ostream& aStream, const Matrix& aMatrix);
+  friend std::ostream& operator<<(std::ostream& aStream, const BaseMatrix& aMatrix)
+  {
+    return aStream << "[ " << aMatrix._11
+                   << " "  << aMatrix._12
+                   << "; " << aMatrix._21
+                   << " "  << aMatrix._22
+                   << "; " << aMatrix._31
+                   << " "  << aMatrix._32
+                   << "; ]";
+  }
 
   Point TransformPoint(const Point &aPoint) const
   {
     Point retPoint;
 
     retPoint.x = aPoint.x * _11 + aPoint.y * _21 + _31;
     retPoint.y = aPoint.x * _12 + aPoint.y * _22 + _32;
 
@@ -69,213 +79,213 @@ public:
     Size retSize;
 
     retSize.width = aSize.width * _11 + aSize.height * _21;
     retSize.height = aSize.width * _12 + aSize.height * _22;
 
     return retSize;
   }
 
-  GFX2D_API Rect TransformBounds(const Rect& rect) const;
+  GFX2D_API Rect TransformBounds(const Rect& aRect) const;
 
-  static Matrix Translation(Float aX, Float aY)
+  static BaseMatrix<T> Translation(T aX, T aY)
   {
-    return Matrix(1.0f, 0.0f, 0.0f, 1.0f, aX, aY);
+    return BaseMatrix<T>(1.0f, 0.0f, 0.0f, 1.0f, aX, aY);
   }
 
-  static Matrix Translation(Point aPoint)
+  static BaseMatrix<T> Translation(Point aPoint)
   {
     return Translation(aPoint.x, aPoint.y);
   }
 
   /**
    * Apply a translation to this matrix.
    *
    * The "Pre" in this method's name means that the translation is applied
    * -before- this matrix's existing transformation. That is, any vector that
    * is multiplied by the resulting matrix will first be translated, then be
    * transformed by the original transform.
    *
    * Calling this method will result in this matrix having the same value as
    * the result of:
    *
-   *   Matrix::Translation(x, y) * this
+   *   BaseMatrix<T>::Translation(x, y) * this
    *
    * (Note that in performance critical code multiplying by the result of a
    * Translation()/Scaling() call is not recommended since that results in a
    * full matrix multiply involving 12 floating-point multiplications. Calling
    * this method would be preferred since it only involves four floating-point
    * multiplications.)
    */
-  Matrix &PreTranslate(Float aX, Float aY)
+  BaseMatrix<T> &PreTranslate(T aX, T aY)
   {
     _31 += _11 * aX + _21 * aY;
     _32 += _12 * aX + _22 * aY;
 
     return *this;
   }
 
-  Matrix &PreTranslate(const Point &aPoint)
+  BaseMatrix<T> &PreTranslate(const Point &aPoint)
   {
     return PreTranslate(aPoint.x, aPoint.y);
   }
 
   /**
    * Similar to PreTranslate, but the translation is applied -after- this
    * matrix's existing transformation instead of before it.
    *
    * This method is generally less used than PreTranslate since typically code
    * want to adjust an existing user space to device space matrix to create a
    * transform to device space from a -new- user space (translated from the
    * previous user space). In that case consumers will need to use the Pre*
    * variants of the matrix methods rather than using the Post* methods, since
    * the Post* methods add a transform to the device space end of the
    * transformation.
    */
-  Matrix &PostTranslate(Float aX, Float aY)
+  BaseMatrix<T> &PostTranslate(T aX, T aY)
   {
     _31 += aX;
     _32 += aY;
     return *this;
   }
 
-  Matrix &PostTranslate(const Point &aPoint)
+  BaseMatrix<T> &PostTranslate(const Point &aPoint)
   {
     return PostTranslate(aPoint.x, aPoint.y);
   }
 
-  static Matrix Scaling(Float aScaleX, Float aScaleY)
+  static BaseMatrix<T> Scaling(T aScaleX, T aScaleY)
   {
-    return Matrix(aScaleX, 0.0f, 0.0f, aScaleY, 0.0f, 0.0f);
+    return BaseMatrix<T>(aScaleX, 0.0f, 0.0f, aScaleY, 0.0f, 0.0f);
   }
   
   /**
    * Similar to PreTranslate, but applies a scale instead of a translation.
    */
-  Matrix &PreScale(Float aX, Float aY)
+  BaseMatrix<T> &PreScale(T aX, T aY)
   {
     _11 *= aX;
     _12 *= aX;
     _21 *= aY;
     _22 *= aY;
 
     return *this;
   }
 
   /**
    * Similar to PostTranslate, but applies a scale instead of a translation.
    */
-  Matrix &PostScale(Float aScaleX, Float aScaleY)
+  BaseMatrix<T> &PostScale(T aScaleX, T aScaleY)
   {
     _11 *= aScaleX;
     _12 *= aScaleY;
     _21 *= aScaleX;
     _22 *= aScaleY;
     _31 *= aScaleX;
     _32 *= aScaleY;
 
     return *this;
   }
 
-  GFX2D_API static Matrix Rotation(Float aAngle);
+  GFX2D_API static BaseMatrix<T> Rotation(T aAngle);
 
   /**
    * Similar to PreTranslate, but applies a rotation instead of a translation.
    */
-  Matrix &PreRotate(Float aAngle)
+  BaseMatrix<T> &PreRotate(T aAngle)
   {
-    return *this = Matrix::Rotation(aAngle) * *this;
+    return *this = BaseMatrix<T>::Rotation(aAngle) * *this;
   }
 
   bool Invert()
   {
     // Compute co-factors.
-    Float A = _22;
-    Float B = -_21;
-    Float C = _21 * _32 - _22 * _31;
-    Float D = -_12;
-    Float E = _11;
-    Float F = _31 * _12 - _11 * _32;
+    T A = _22;
+    T B = -_21;
+    T C = _21 * _32 - _22 * _31;
+    T D = -_12;
+    T E = _11;
+    T F = _31 * _12 - _11 * _32;
 
-    Float det = Determinant();
+    T det = Determinant();
 
     if (!det) {
       return false;
     }
 
-    Float inv_det = 1 / det;
+    T inv_det = 1 / det;
 
     _11 = inv_det * A;
     _12 = inv_det * D;
     _21 = inv_det * B;
     _22 = inv_det * E;
     _31 = inv_det * C;
     _32 = inv_det * F;
 
     return true;
   }
 
-  Matrix Inverse() const
+  BaseMatrix<T> Inverse() const
   {
-    Matrix clone = *this;
+    BaseMatrix<T> clone = *this;
     DebugOnly<bool> inverted = clone.Invert();
     MOZ_ASSERT(inverted, "Attempted to get the inverse of a non-invertible matrix");
     return clone;
   }
 
-  Float Determinant() const
+  T Determinant() const
   {
     return _11 * _22 - _12 * _21;
   }
 
-  Matrix operator*(const Matrix &aMatrix) const
+  BaseMatrix<T> operator*(const BaseMatrix<T> &aMatrix) const
   {
-    Matrix resultMatrix;
+    BaseMatrix<T> resultMatrix;
 
     resultMatrix._11 = this->_11 * aMatrix._11 + this->_12 * aMatrix._21;
     resultMatrix._12 = this->_11 * aMatrix._12 + this->_12 * aMatrix._22;
     resultMatrix._21 = this->_21 * aMatrix._11 + this->_22 * aMatrix._21;
     resultMatrix._22 = this->_21 * aMatrix._12 + this->_22 * aMatrix._22;
     resultMatrix._31 = this->_31 * aMatrix._11 + this->_32 * aMatrix._21 + aMatrix._31;
     resultMatrix._32 = this->_31 * aMatrix._12 + this->_32 * aMatrix._22 + aMatrix._32;
 
     return resultMatrix;
   }
 
-  Matrix& operator*=(const Matrix &aMatrix)
+  BaseMatrix<T>& operator*=(const BaseMatrix<T> &aMatrix)
   {
     *this = *this * aMatrix;
     return *this;
   }
 
   /**
    * Multiplies in the opposite order to operator=*.
    */
-  Matrix &PreMultiply(const Matrix &aMatrix)
+  BaseMatrix<T> &PreMultiply(const BaseMatrix<T> &aMatrix)
   {
     *this = aMatrix * *this;
     return *this;
   }
 
   /* Returns true if the other matrix is fuzzy-equal to this matrix.
    * Note that this isn't a cheap comparison!
    */
-  bool operator==(const Matrix& other) const
+  bool operator==(const BaseMatrix<T>& other) const
   {
     return FuzzyEqual(_11, other._11) && FuzzyEqual(_12, other._12) &&
            FuzzyEqual(_21, other._21) && FuzzyEqual(_22, other._22) &&
            FuzzyEqual(_31, other._31) && FuzzyEqual(_32, other._32);
   }
 
-  bool operator!=(const Matrix& other) const
+  bool operator!=(const BaseMatrix<T>& other) const
   {
     return !(*this == other);
   }
 
-  bool ExactlyEquals(const Matrix& o) const
+  bool ExactlyEquals(const BaseMatrix<T>& o) const
   {
     return _11 == o._11 && _12 == o._12 &&
            _21 == o._21 && _22 == o._22 &&
            _31 == o._31 && _32 == o._32;
   }
 
   /* Verifies that the matrix contains no Infs or NaNs. */
   bool IsFinite() const
@@ -299,18 +309,18 @@ public:
   }
 
   /**
    * Returns true if the matrix is anything other than a straight
    * translation by integers.
   */
   bool HasNonIntegerTranslation() const {
     return HasNonTranslation() ||
-      !FuzzyEqual(_31, floor(_31 + Float(0.5))) ||
-      !FuzzyEqual(_32, floor(_32 + Float(0.5)));
+      !FuzzyEqual(_31, floor(_31 + T(0.5))) ||
+      !FuzzyEqual(_32, floor(_32 + T(0.5)));
   }
 
   /**
    * Returns true if the matrix only has an integer translation.
    */
   bool HasOnlyIntegerTranslation() const {
     return !HasNonIntegerTranslation();
   }
@@ -342,29 +352,29 @@ public:
            _21 == 0.0f && _22 == 1.0f &&
            _31 == 0.0f && _32 == 0.0f;
   }
 
   /* Returns true if the matrix is singular.
    */
   bool IsSingular() const
   {
-    Float det = Determinant();
+    T det = Determinant();
     return !mozilla::IsFinite(det) || det == 0;
   }
 
-  GFX2D_API Matrix &NudgeToIntegers();
+  GFX2D_API BaseMatrix<T> &NudgeToIntegers();
 
   bool IsTranslation() const
   {
     return FuzzyEqual(_11, 1.0f) && FuzzyEqual(_12, 0.0f) &&
            FuzzyEqual(_21, 0.0f) && FuzzyEqual(_22, 1.0f);
   }
 
-  static bool FuzzyIsInteger(Float aValue)
+  static bool FuzzyIsInteger(T aValue)
   {
     return FuzzyEqual(aValue, floorf(aValue + 0.5f));
   }
 
   bool IsIntegerTranslation() const
   {
     return IsTranslation() && FuzzyIsInteger(_31) && FuzzyIsInteger(_32);
   }
@@ -401,16 +411,18 @@ public:
   /**
    * Returns true if the matrix has negative scaling (i.e. flip).
    */
   bool HasNegativeScaling() const {
       return (_11 < 0.0) || (_22 < 0.0);
   }
 };
 
+typedef BaseMatrix<Float> Matrix;
+
 // 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>
--- a/gfx/2d/MatrixFwd.h
+++ b/gfx/2d/MatrixFwd.h
@@ -3,21 +3,27 @@
  * 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|.
+// Forward declare enough things to define the typedefs |Matrix| and |Matrix4x4|.
 
 namespace mozilla {
 namespace gfx {
 
+template<class T>
+class BaseMatrix;
+
+typedef float Float;
+typedef BaseMatrix<Float> Matrix;
+
 struct UnknownUnits;
 
 template<class SourceUnits, class TargetUnits>
 class Matrix4x4Typed;
 
 typedef Matrix4x4Typed<UnknownUnits, UnknownUnits> Matrix4x4;
 
 } // namespace gfx
--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -5,17 +5,17 @@
 
 #ifndef MOZILLA_GFX_COMPOSITOR_H
 #define MOZILLA_GFX_COMPOSITOR_H
 
 #include "Units.h"                      // for ScreenPoint
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/RefPtr.h"             // for already_AddRefed, RefCounted
 #include "mozilla/gfx/2D.h"             // for DrawTarget
-#include "mozilla/gfx/MatrixFwd.h"      // for Matrix4x4
+#include "mozilla/gfx/MatrixFwd.h"      // for Matrix, Matrix4x4
 #include "mozilla/gfx/Point.h"          // for IntSize, Point
 #include "mozilla/gfx/Polygon.h"        // for Polygon
 #include "mozilla/gfx/Rect.h"           // for Rect, IntRect
 #include "mozilla/gfx/Types.h"          // for Float
 #include "mozilla/gfx/Triangle.h"       // for Triangle, TexturedTriangle
 #include "mozilla/layers/CompositorTypes.h"  // for DiagnosticTypes, etc
 #include "mozilla/layers/LayersTypes.h"  // for LayersBackend
 #include "mozilla/layers/TextureSourceProvider.h"
@@ -109,17 +109,16 @@
  * Depending on the type of data that needs to be serialized, you may need to
  * add specific TextureClient implementations.
  */
 
 class nsIWidget;
 
 namespace mozilla {
 namespace gfx {
-class Matrix;
 class DrawTarget;
 class DataSourceSurface;
 } // namespace gfx
 
 namespace layers {
 
 struct Effect;
 struct EffectChain;
--- a/gfx/layers/RotatedBuffer.h
+++ b/gfx/layers/RotatedBuffer.h
@@ -6,28 +6,25 @@
 #ifndef ROTATEDBUFFER_H_
 #define ROTATEDBUFFER_H_
 
 #include "gfxTypes.h"
 #include <stdint.h>                     // for uint32_t
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/RefPtr.h"             // for RefPtr, already_AddRefed
 #include "mozilla/gfx/2D.h"             // for DrawTarget, etc
+#include "mozilla/gfx/MatrixFwd.h"      // for Matrix
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsRegion.h"                   // for nsIntRegion
 #include "LayersTypes.h"
 
 namespace mozilla {
-namespace gfx {
-class Matrix;
-} // namespace gfx
-
 namespace layers {
 
 class TextureClient;
 class PaintedLayer;
 
 /**
  * This is a cairo/Thebes surface, but with a literal twist. Scrolling
  * causes the layer's visible region to move. We want to keep
--- a/layout/base/Units.h
+++ b/layout/base/Units.h
@@ -3,17 +3,16 @@
 /* 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 MOZ_UNITS_H_
 #define MOZ_UNITS_H_
 
 #include "mozilla/gfx/Coord.h"
-#include "mozilla/gfx/Matrix.h"
 #include "mozilla/gfx/Point.h"
 #include "mozilla/gfx/Rect.h"
 #include "mozilla/gfx/ScaleFactor.h"
 #include "mozilla/gfx/ScaleFactors2D.h"
 #include "nsMargin.h"
 #include "nsRect.h"
 #include "nsRegion.h"
 #include "mozilla/AppUnits.h"
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -38,16 +38,17 @@
 #include "nsLayoutUtils.h"
 #include "nsQueryFrame.h"
 #include "nsStringGlue.h"
 #include "nsStyleContext.h"
 #include "nsStyleStruct.h"
 #include "Visibility.h"
 #include "nsChangeHint.h"
 #include "nsStyleContextInlines.h"
+#include "mozilla/gfx/MatrixFwd.h"
 
 #ifdef ACCESSIBILITY
 #include "mozilla/a11y/AccTypes.h"
 #endif
 
 /**
  * New rules of reflow:
  * 1. you get a WillReflow() followed by a Reflow() followed by a DidReflow() in order
@@ -103,19 +104,16 @@ class ReflowOutput;
 class ServoRestyleState;
 class DisplayItemData;
 class EffectSet;
 
 namespace layers {
 class Layer;
 } // namespace layers
 
-namespace gfx {
-class Matrix;
-} // namespace gfx
 } // namespace mozilla
 
 /**
  * Indication of how the frame can be split. This is used when doing runaround
  * of floats, and when pulling up child frames from a next-in-flow.
  *
  * The choices are splittable, not splittable at all, and splittable in
  * a non-rectangular fashion. This last type only applies to block-level
--- a/layout/svg/nsSVGDisplayableFrame.h
+++ b/layout/svg/nsSVGDisplayableFrame.h
@@ -3,34 +3,32 @@
  * 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 __NS_ISVGCHILDFRAME_H__
 #define __NS_ISVGCHILDFRAME_H__
 
 #include "gfxRect.h"
 #include "nsQueryFrame.h"
+#include "mozilla/gfx/MatrixFwd.h"
 
 class gfxContext;
 class gfxMatrix;
 class nsIFrame;
 class SVGBBox;
 
 struct nsRect;
 
 namespace mozilla {
 class SVGAnimatedLengthList;
 class SVGAnimatedNumberList;
 class SVGLengthList;
 class SVGNumberList;
 class SVGUserUnitList;
 
-namespace gfx {
-class Matrix;
-} // namespace gfx
 } // namespace mozilla
 
 /**
  * This class is used for elements that can be part of a directly displayable
  * section of a document.  This includes SVGGeometryFrame and nsSVGGframe.
  * (Even though the latter doesn't display anything itself, if it contains
  * SVGGeometryFrame descendants it is can still be part of a displayable
  * section of a document)  This class is not used for elements that can never