Bug 1377090 - Make the Matrix class templated so we can instantiate it with a double type. r?Bas draft
authorKartikaya Gupta <kgupta@mozilla.com>
Wed, 05 Jul 2017 11:18:48 -0400
changeset 604205 fd339bbccdba406a427f6c59b79da84455ab16ac
parent 604170 211d4dd61025c0a40caea7a54c9066e051bdde8c
child 604206 83180176cfc71e687cad0f17f2938cab1610c16c
push id67001
push userkgupta@mozilla.com
push dateWed, 05 Jul 2017 15:19:48 +0000
reviewersBas
bugs1377090
milestone56.0a1
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