Bug 1377090 - Turn gfxMatrix into a typedef for MatrixDouble. r=jrmuizel
authorKartikaya Gupta <kgupta@mozilla.com>
Wed, 05 Jul 2017 11:18:49 -0400
changeset 367404 e21a77cab74059d05ab1b4aa2c2c306cdc83d752
parent 367403 5468507e9a0ac5bedf2cde709e7676e39d84aa06
child 367405 1c0e2e2b2bb745eba98a15423c480e6148402a69
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)
reviewersjrmuizel
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 - Turn gfxMatrix into a typedef for MatrixDouble. r=jrmuizel Most of this patch is updating a few places that use gfxMatrix to use the equivalent-but-differently-named functions on MatrixDouble: - Translate/Rotate/Scale get turned into PreTranslate/PreRotate/PreScale - Transform(Point) gets turned into TransformPoint(Point) - gfxMatrix::TransformBounds(gfxRect) gets turned into gfxRect::TransformBoundsBy(gfxMatrix). - gfxMatrix::Transform(gfxRect) gets turned into gfxRect::TransformBy(gfxMatrix). The last two functions are added in this patch as convenience wrappers to gfxRect instead of Matrix.h because we don't want Matrix.h to "know" about gfxRect (to avoid adding gecko dependencies on Moz2D). Once we turn gfxRect into a typedef for RectDouble these will be eliminated anyway. MozReview-Commit-ID: BnOjHzmOSKn
dom/canvas/CanvasRenderingContext2D.cpp
dom/media/webrtc/MediaEngineTabVideoSource.cpp
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/svg/SVGMatrix.cpp
dom/svg/SVGTransform.h
dom/svg/nsSVGElement.h
dom/svg/nsSVGTransform.cpp
dom/svg/nsSVGTransform.h
gfx/layers/LayerScope.h
gfx/layers/client/SingleTiledContentClient.cpp
gfx/layers/client/TiledContentClient.cpp
gfx/src/nsDeviceContext.cpp
gfx/thebes/gfxContext.cpp
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxFontEntry.cpp
gfx/thebes/gfxMatrix.cpp
gfx/thebes/gfxMatrix.h
gfx/thebes/gfxRect.cpp
gfx/thebes/gfxRect.h
gfx/thebes/moz.build
image/ImageRegion.h
image/OrientedImage.cpp
image/VectorImage.cpp
layout/base/PresShell.cpp
layout/base/nsLayoutUtils.cpp
layout/generic/nsCanvasFrame.cpp
layout/generic/nsPluginFrame.cpp
layout/generic/nsTextFrame.cpp
layout/mathml/nsMathMLChar.cpp
layout/painting/FrameLayerBuilder.cpp
layout/painting/nsCSSRendering.cpp
layout/painting/nsCSSRenderingGradients.cpp
layout/painting/nsDisplayList.cpp
layout/svg/SVGTextFrame.cpp
layout/svg/nsFilterInstance.cpp
layout/svg/nsSVGClipPathFrame.cpp
layout/svg/nsSVGDisplayableFrame.h
layout/svg/nsSVGForeignObjectFrame.cpp
layout/svg/nsSVGIntegrationUtils.cpp
layout/svg/nsSVGSwitchFrame.cpp
layout/svg/nsSVGUtils.cpp
widget/android/fennec/ThumbnailHelper.h
widget/windows/nsNativeThemeWin.cpp
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -5459,19 +5459,19 @@ CanvasRenderingContext2D::DrawDirectlyTo
   AutoRestoreTransform autoRestoreTransform(mTarget);
 
   RefPtr<gfxContext> context = gfxContext::CreateOrNull(tempTarget);
   if (!context) {
     gfxDevCrash(LogReason::InvalidContext) << "Canvas context problem";
     return;
   }
   context->SetMatrix(contextMatrix.
-                       Scale(1.0 / contextScale.width,
-                             1.0 / contextScale.height).
-                       Translate(aDest.x - aSrc.x, aDest.y - aSrc.y));
+                       PreScale(1.0 / contextScale.width,
+                                1.0 / contextScale.height).
+                       PreTranslate(aDest.x - aSrc.x, aDest.y - aSrc.y));
 
   // FLAG_CLAMP is added for increased performance, since we never tile here.
   uint32_t modifiedFlags = aImage.mDrawingFlags | imgIContainer::FLAG_CLAMP;
 
   CSSIntSize sz(scaledImageSize.width, scaledImageSize.height); // XXX hmm is scaledImageSize really in CSS pixels?
   SVGImageContext svgContext(Some(sz));
 
   auto result = aImage.mImgContainer->
--- a/dom/media/webrtc/MediaEngineTabVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineTabVideoSource.cpp
@@ -339,18 +339,18 @@ MediaEngineTabVideoSource::Draw() {
                                      true);
   if (!dt || !dt->IsValid()) {
     return;
   }
 
   if (mWindow) {
     RefPtr<gfxContext> context = gfxContext::CreateOrNull(dt);
     MOZ_ASSERT(context); // already checked the draw target above
-    context->SetMatrix(context->CurrentMatrix().Scale((((float) size.width)/mViewportWidth),
-                                                      (((float) size.height)/mViewportHeight)));
+    context->SetMatrix(context->CurrentMatrix().PreScale((((float) size.width)/mViewportWidth),
+                                                         (((float) size.height)/mViewportHeight)));
 
     nscolor bgColor = NS_RGB(255, 255, 255);
     uint32_t renderDocFlags = mScrollWithPage? 0 :
       (nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING |
        nsIPresShell::RENDER_DOCUMENT_RELATIVE);
     nsRect r(nsPresContext::CSSPixelsToAppUnits((float)mViewportOffsetX),
              nsPresContext::CSSPixelsToAppUnits((float)mViewportOffsetY),
              nsPresContext::CSSPixelsToAppUnits((float)mViewportWidth),
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -3120,17 +3120,17 @@ void nsPluginInstanceOwner::Paint(gfxCon
   bool transparent;
   mInstance->IsTransparent(&transparent);
   if (!transparent)
     rendererFlags |= Renderer::DRAW_IS_OPAQUE;
 
   // Renderer::Draw() draws a rectangle with top-left at the aContext origin.
   gfxContextAutoSaveRestore autoSR(aContext);
   aContext->SetMatrix(
-    aContext->CurrentMatrix().Translate(pluginRect.TopLeft()));
+    aContext->CurrentMatrix().PreTranslate(pluginRect.TopLeft()));
 
   Renderer renderer(window, this, pluginSize, pluginDirtyRect);
 
   Display* dpy = mozilla::DefaultXDisplay();
   Screen* screen = DefaultScreenOfDisplay(dpy);
   Visual* visual = DefaultVisualOfScreen(screen);
 
   renderer.Draw(aContext, nsIntSize(window->width, window->height),
--- a/dom/svg/SVGMatrix.cpp
+++ b/dom/svg/SVGMatrix.cpp
@@ -128,53 +128,53 @@ SVGMatrix::Inverse(ErrorResult& rv)
   RefPtr<SVGMatrix> matrix = new SVGMatrix(mat);
   return matrix.forget();
 }
 
 already_AddRefed<SVGMatrix>
 SVGMatrix::Translate(float x, float y)
 {
   RefPtr<SVGMatrix> matrix =
-    new SVGMatrix(gfxMatrix(GetMatrix()).Translate(gfxPoint(x, y)));
+    new SVGMatrix(gfxMatrix(GetMatrix()).PreTranslate(gfxPoint(x, y)));
   return matrix.forget();
 }
 
 already_AddRefed<SVGMatrix>
 SVGMatrix::Scale(float scaleFactor)
 {
   return ScaleNonUniform(scaleFactor, scaleFactor);
 }
 
 already_AddRefed<SVGMatrix>
 SVGMatrix::ScaleNonUniform(float scaleFactorX,
                            float scaleFactorY)
 {
   RefPtr<SVGMatrix> matrix =
-    new SVGMatrix(gfxMatrix(GetMatrix()).Scale(scaleFactorX, scaleFactorY));
+    new SVGMatrix(gfxMatrix(GetMatrix()).PreScale(scaleFactorX, scaleFactorY));
   return matrix.forget();
 }
 
 already_AddRefed<SVGMatrix>
 SVGMatrix::Rotate(float angle)
 {
   RefPtr<SVGMatrix> matrix =
-    new SVGMatrix(gfxMatrix(GetMatrix()).Rotate(angle*radPerDegree));
+    new SVGMatrix(gfxMatrix(GetMatrix()).PreRotate(angle*radPerDegree));
   return matrix.forget();
 }
 
 already_AddRefed<SVGMatrix>
 SVGMatrix::RotateFromVector(float x, float y, ErrorResult& rv)
 {
   if (x == 0.0 || y == 0.0) {
     rv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return nullptr;
   }
 
   RefPtr<SVGMatrix> matrix =
-    new SVGMatrix(gfxMatrix(GetMatrix()).Rotate(atan2(y, x)));
+    new SVGMatrix(gfxMatrix(GetMatrix()).PreRotate(atan2(y, x)));
   return matrix.forget();
 }
 
 already_AddRefed<SVGMatrix>
 SVGMatrix::FlipX()
 {
   const gfxMatrix& mx = GetMatrix();
   RefPtr<SVGMatrix> matrix =
--- a/dom/svg/SVGTransform.h
+++ b/dom/svg/SVGTransform.h
@@ -3,28 +3,27 @@
 /* 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_dom_SVGTransform_h
 #define mozilla_dom_SVGTransform_h
 
 #include "DOMSVGTransformList.h"
+#include "gfxMatrix.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDebug.h"
 #include "nsID.h"
 #include "nsSVGTransform.h"
 #include "nsWrapperCache.h"
 #include "mozilla/Attributes.h"
 
 class nsSVGElement;
 
-class gfxMatrix;
-
 #define MOZ_SVG_LIST_INDEX_BIT_COUNT 31 // supports > 2 billion list items
 
 namespace mozilla {
 namespace dom {
 
 class SVGMatrix;
 
 /**
--- a/dom/svg/nsSVGElement.h
+++ b/dom/svg/nsSVGElement.h
@@ -21,16 +21,17 @@
 #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"
+#include "gfxMatrix.h"
 
 class nsSVGAngle;
 class nsSVGBoolean;
 class nsSVGEnum;
 class nsSVGInteger;
 class nsSVGIntegerPair;
 class nsSVGLength2;
 class nsSVGNumber2;
@@ -58,17 +59,16 @@ class SVGAnimatedPointList;
 class SVGAnimatedPathSegList;
 class SVGAnimatedPreserveAspectRatio;
 class nsSVGAnimatedTransformList;
 class SVGStringList;
 class DOMSVGStringList;
 
 } // namespace mozilla
 
-class gfxMatrix;
 struct nsSVGEnumMapping;
 
 typedef nsStyledElement nsSVGElementBase;
 
 class nsSVGElement : public nsSVGElementBase    // nsIContent
                    , public nsIDOMSVGElement
 {
 protected:
--- a/dom/svg/nsSVGTransform.cpp
+++ b/dom/svg/nsSVGTransform.cpp
@@ -84,72 +84,67 @@ nsSVGTransform::SetMatrix(const gfxMatri
   mOriginX = 0.f;
   mOriginY = 0.f;
 }
 
 void
 nsSVGTransform::SetTranslate(float aTx, float aTy)
 {
   mType    = SVG_TRANSFORM_TRANSLATE;
-  mMatrix.Reset();
-  mMatrix._31 = aTx;
-  mMatrix._32 = aTy;
+  mMatrix  = gfxMatrix::Translation(aTx, aTy);
   mAngle   = 0.f;
   mOriginX = 0.f;
   mOriginY = 0.f;
 }
 
 void
 nsSVGTransform::SetScale(float aSx, float aSy)
 {
   mType    = SVG_TRANSFORM_SCALE;
-  mMatrix.Reset();
-  mMatrix._11 = aSx;
-  mMatrix._22 = aSy;
+  mMatrix  = gfxMatrix::Scaling(aSx, aSy);
   mAngle   = 0.f;
   mOriginX = 0.f;
   mOriginY = 0.f;
 }
 
 void
 nsSVGTransform::SetRotate(float aAngle, float aCx, float aCy)
 {
   mType    = SVG_TRANSFORM_ROTATE;
-  mMatrix.Reset();
-  mMatrix.Translate(aCx, aCy);
-  mMatrix.Rotate(aAngle*kRadPerDegree);
-  mMatrix.Translate(-aCx, -aCy);
+  mMatrix  = gfxMatrix::Translation(aCx, aCy)
+                       .PreRotate(aAngle*kRadPerDegree)
+                       .PreTranslate(-aCx, -aCy);
   mAngle   = aAngle;
   mOriginX = aCx;
   mOriginY = aCy;
 }
 
 nsresult
 nsSVGTransform::SetSkewX(float aAngle)
 {
   double ta = tan(aAngle*kRadPerDegree);
   NS_ENSURE_FINITE(ta, NS_ERROR_RANGE_ERR);
 
   mType    = SVG_TRANSFORM_SKEWX;
-  mMatrix.Reset();
+  mMatrix  = gfxMatrix();
   mMatrix._21 = ta;
   mAngle   = aAngle;
   mOriginX = 0.f;
   mOriginY = 0.f;
   return NS_OK;
 }
 
 nsresult
 nsSVGTransform::SetSkewY(float aAngle)
 {
   double ta = tan(aAngle*kRadPerDegree);
   NS_ENSURE_FINITE(ta, NS_ERROR_RANGE_ERR);
 
   mType    = SVG_TRANSFORM_SKEWY;
-  mMatrix.Reset();
+  mMatrix  = gfxMatrix();
   mMatrix._12 = ta;
   mAngle   = aAngle;
   mOriginX = 0.f;
   mOriginY = 0.f;
   return NS_OK;
 }
 
 SVGTransformSMILData::SVGTransformSMILData(const nsSVGTransform& aTransform)
--- a/dom/svg/nsSVGTransform.h
+++ b/dom/svg/nsSVGTransform.h
@@ -3,16 +3,17 @@
 /* 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_SVGTRANSFORM_H__
 #define MOZILLA_SVGTRANSFORM_H__
 
 #include "gfxMatrix.h"
+#include "mozilla/gfx/Matrix.h"
 #include "nsDebug.h"
 
 namespace mozilla {
 
 // Transform Types
 static const unsigned short SVG_TRANSFORM_UNKNOWN = 0;
 static const unsigned short SVG_TRANSFORM_MATRIX = 1;
 static const unsigned short SVG_TRANSFORM_TRANSLATE = 2;
--- a/gfx/layers/LayerScope.h
+++ b/gfx/layers/LayerScope.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef GFX_LAYERSCOPE_H
 #define GFX_LAYERSCOPE_H
 
 #include <stdint.h>
 #include <mozilla/UniquePtr.h>
 #include "gfxMatrix.h"
+#include "mozilla/gfx/Rect.h"
 
 namespace mozilla {
 
 namespace gl { class GLContext; }
 
 namespace layers {
 
 
--- a/gfx/layers/client/SingleTiledContentClient.cpp
+++ b/gfx/layers/client/SingleTiledContentClient.cpp
@@ -226,17 +226,17 @@ ClientSingleTiledLayerBuffer::PaintThebe
   }
 
   {
     RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(dt);
     if (!ctx) {
       gfxDevCrash(gfx::LogReason::InvalidContext) << "SingleTiledContextClient context problem " << gfx::hexa(dt);
       return;
     }
-    ctx->SetMatrix(ctx->CurrentMatrix().Translate(-mTilingOrigin.x, -mTilingOrigin.y));
+    ctx->SetMatrix(ctx->CurrentMatrix().PreTranslate(-mTilingOrigin.x, -mTilingOrigin.y));
 
     aCallback(&mPaintedLayer, ctx, paintRegion, paintRegion, DrawRegionClip::DRAW, nsIntRegion(), aCallbackData);
   }
 
   // Mark the area we just drew into the back buffer as invalid in the front buffer as they're
   // now out of sync.
   mTile.mInvalidFront.OrWith(tileDirtyRegion);
 
--- a/gfx/layers/client/TiledContentClient.cpp
+++ b/gfx/layers/client/TiledContentClient.cpp
@@ -980,17 +980,17 @@ void ClientMultiTiledLayerBuffer::Update
         gfxDevCrash(LogReason::InvalidContext) << "Invalid tiled draw target";
         return;
       }
       drawTarget->SetTransform(Matrix());
 
       RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(drawTarget);
       MOZ_ASSERT(ctx); // already checked the draw target above
       ctx->SetMatrix(
-        ctx->CurrentMatrix().Scale(mResolution, mResolution).Translate(ThebesPoint(-mTilingOrigin)));
+        ctx->CurrentMatrix().PreScale(mResolution, mResolution).PreTranslate(ThebesPoint(-mTilingOrigin)));
 
       mCallback(&mPaintedLayer, ctx, aPaintRegion, aDirtyRegion,
                 DrawRegionClip::DRAW, nsIntRegion(), mCallbackData);
       mMoz2DTiles.clear();
       // Reset:
       mTilingOrigin = IntPoint(std::numeric_limits<int32_t>::max(),
                                std::numeric_limits<int32_t>::max());
     }
--- a/gfx/src/nsDeviceContext.cpp
+++ b/gfx/src/nsDeviceContext.cpp
@@ -398,23 +398,23 @@ nsDeviceContext::CreateRenderingContextC
 
     RefPtr<gfxContext> pContext = gfxContext::CreateOrNull(dt);
     MOZ_ASSERT(pContext); // already checked draw target above
 
     gfxMatrix transform;
     if (mPrintTarget->RotateNeededForLandscape()) {
       // Rotate page 90 degrees to draw landscape page on portrait paper
       IntSize size = mPrintTarget->GetSize();
-      transform.Translate(gfxPoint(0, size.width));
+      transform.PreTranslate(gfxPoint(0, size.width));
       gfxMatrix rotate(0, -1,
                        1,  0,
                        0,  0);
       transform = rotate * transform;
     }
-    transform.Scale(mPrintingScale, mPrintingScale);
+    transform.PreScale(mPrintingScale, mPrintingScale);
 
     pContext->SetMatrix(transform);
     return pContext.forget();
 }
 
 nsresult
 nsDeviceContext::GetDepth(uint32_t& aDepth)
 {
--- a/gfx/thebes/gfxContext.cpp
+++ b/gfx/thebes/gfxContext.cpp
@@ -227,17 +227,18 @@ gfxContext::Rectangle(const gfxRect& rec
   Rect rec = ToRect(rect);
 
   if (snapToPixels) {
     gfxRect newRect(rect);
     if (UserToDevicePixelSnapped(newRect, true)) {
       gfxMatrix mat = ThebesMatrix(mTransform);
       if (mat.Invert()) {
         // We need the user space rect.
-        rec = ToRect(mat.TransformBounds(newRect));
+        newRect.TransformBoundsBy(mat);
+        rec = ToRect(newRect);
       } else {
         rec = Rect();
       }
     }
   }
 
   if (!mPathBuilder && !mPathIsRect) {
     mPathIsRect = true;
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -2080,32 +2080,32 @@ gfxFont::Draw(const gfxTextRun *aTextRun
         // Get a matrix we can use to draw the (horizontally-shaped) textrun
         // with 90-degree CW rotation.
         const gfxFloat
             rotation = (aOrientation ==
                         gfx::ShapedTextFlags::TEXT_ORIENT_VERTICAL_SIDEWAYS_LEFT)
                        ? -M_PI / 2.0 : M_PI / 2.0;
         gfxMatrix mat =
             aRunParams.context->CurrentMatrix().
-            Translate(p).     // translate origin for rotation
-            Rotate(rotation). // turn 90deg CCW (sideways-left) or CW (*-right)
-            Translate(-p);    // undo the translation
+            PreTranslate(p).     // translate origin for rotation
+            PreRotate(rotation). // turn 90deg CCW (sideways-left) or CW (*-right)
+            PreTranslate(-p);    // undo the translation
 
         // If we're drawing rotated horizontal text for an element styled
         // text-orientation:mixed, the dominant baseline will be vertical-
         // centered. So in this case, we need to adjust the position so that
         // the rotated horizontal text (which uses an alphabetic baseline) will
         // look OK when juxtaposed with upright glyphs (rendered on a centered
         // vertical baseline). The adjustment here is somewhat ad hoc; we
         // should eventually look for baseline tables[1] in the fonts and use
         // those if available.
         // [1] See http://www.microsoft.com/typography/otspec/base.htm
         if (aTextRun->UseCenterBaseline()) {
             gfxPoint baseAdj(0, (metrics.emAscent - metrics.emDescent) / 2);
-            mat.Translate(baseAdj);
+            mat.PreTranslate(baseAdj);
         }
 
         aRunParams.context->SetMatrix(mat);
     }
 
     RefPtr<SVGContextPaint> contextPaint;
     if (fontParams.haveSVGGlyphs && !fontParams.contextPaint) {
         // If no pattern is specified for fill, use the current pattern
@@ -2219,18 +2219,18 @@ gfxFont::RenderSVGGlyph(gfxContext *aCon
     }
 
     const gfxFloat devUnitsPerSVGUnit =
         GetAdjustedSize() / GetFontEntry()->UnitsPerEm();
     gfxContextMatrixAutoSaveRestore matrixRestore(aContext);
 
     aContext->Save();
     aContext->SetMatrix(
-      aContext->CurrentMatrix().Translate(aPoint.x, aPoint.y).
-                                Scale(devUnitsPerSVGUnit, devUnitsPerSVGUnit));
+      aContext->CurrentMatrix().PreTranslate(aPoint.x, aPoint.y).
+                                PreScale(devUnitsPerSVGUnit, devUnitsPerSVGUnit));
 
     aContextPaint->InitStrokeGeometry(aContext, devUnitsPerSVGUnit);
 
     GetFontEntry()->RenderSVGGlyph(aContext, aGlyphId, aContextPaint);
     aContext->Restore();
     aContext->NewPath();
     return true;
 }
--- a/gfx/thebes/gfxFontEntry.cpp
+++ b/gfx/thebes/gfxFontEntry.cpp
@@ -336,17 +336,17 @@ gfxFontEntry::GetSVGGlyphExtents(DrawTar
                "font has invalid unitsPerEm");
 
     cairo_matrix_t fontMatrix;
     cairo_get_font_matrix(gfxFont::RefCairo(aDrawTarget), &fontMatrix);
 
     gfxMatrix svgToAppSpace(fontMatrix.xx, fontMatrix.yx,
                             fontMatrix.xy, fontMatrix.yy,
                             fontMatrix.x0, fontMatrix.y0);
-    svgToAppSpace.Scale(1.0f / mUnitsPerEm, 1.0f / mUnitsPerEm);
+    svgToAppSpace.PreScale(1.0f / mUnitsPerEm, 1.0f / mUnitsPerEm);
 
     return mSVGGlyphs->GetGlyphExtents(aGlyphId, svgToAppSpace, aResult);
 }
 
 void
 gfxFontEntry::RenderSVGGlyph(gfxContext *aContext, uint32_t aGlyphId,
                              SVGContextPaint* aContextPaint)
 {
deleted file mode 100644
--- a/gfx/thebes/gfxMatrix.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "gfxMatrix.h"
-#include "cairo.h"
-#include "mozilla/gfx/Tools.h"
-#include "mozilla/gfx/Matrix.h" // for Matrix4x4
-
-#define CAIRO_MATRIX(x) reinterpret_cast<cairo_matrix_t*>((x))
-#define CONST_CAIRO_MATRIX(x) reinterpret_cast<const cairo_matrix_t*>((x))
-
-const gfxMatrix&
-gfxMatrix::Reset()
-{
-    cairo_matrix_init_identity(CAIRO_MATRIX(this));
-    return *this;
-}
-
-bool
-gfxMatrix::Invert()
-{
-    return cairo_matrix_invert(CAIRO_MATRIX(this)) == CAIRO_STATUS_SUCCESS;
-}
-
-gfxMatrix&
-gfxMatrix::Scale(gfxFloat x, gfxFloat y)
-{
-    cairo_matrix_scale(CAIRO_MATRIX(this), x, y);
-    return *this;
-}
-
-gfxMatrix&
-gfxMatrix::Translate(const gfxPoint& pt)
-{
-    cairo_matrix_translate(CAIRO_MATRIX(this), pt.x, pt.y);
-    return *this;
-}
-
-gfxMatrix&
-gfxMatrix::Rotate(gfxFloat radians)
-{
-    cairo_matrix_rotate(CAIRO_MATRIX(this), radians);
-    return *this;
-}
-
-const gfxMatrix&
-gfxMatrix::operator *= (const gfxMatrix& m)
-{
-    cairo_matrix_multiply(CAIRO_MATRIX(this), CAIRO_MATRIX(this), CONST_CAIRO_MATRIX(&m));
-    return *this;
-}
-
-gfxMatrix&
-gfxMatrix::PreMultiply(const gfxMatrix& m)
-{
-    cairo_matrix_multiply(CAIRO_MATRIX(this), CONST_CAIRO_MATRIX(&m), CAIRO_MATRIX(this));
-    return *this;
-}
-
-/* static */ gfxMatrix
-gfxMatrix::Rotation(gfxFloat aAngle)
-{
-    gfxMatrix newMatrix;
-
-    gfxFloat s = sin(aAngle);
-    gfxFloat c = cos(aAngle);
-
-    newMatrix._11 = c;
-    newMatrix._12 = s;
-    newMatrix._21 = -s;
-    newMatrix._22 = c;
-
-    return newMatrix;
-}
-
-gfxPoint
-gfxMatrix::Transform(const gfxPoint& point) const
-{
-    gfxPoint ret = point;
-    cairo_matrix_transform_point(CONST_CAIRO_MATRIX(this), &ret.x, &ret.y);
-    return ret;
-}
-
-gfxSize
-gfxMatrix::Transform(const gfxSize& size) const
-{
-    gfxSize ret = size;
-    cairo_matrix_transform_distance(CONST_CAIRO_MATRIX(this), &ret.width, &ret.height);
-    return ret;
-}
-
-gfxRect
-gfxMatrix::Transform(const gfxRect& rect) const
-{
-    return gfxRect(Transform(rect.TopLeft()), Transform(rect.Size()));
-}
-
-gfxRect
-gfxMatrix::TransformBounds(const gfxRect& rect) const
-{
-    /* Code taken from cairo-matrix.c, _cairo_matrix_transform_bounding_box isn't public */
-    int i;
-    double quad_x[4], quad_y[4];
-    double min_x, max_x;
-    double min_y, max_y;
-
-    quad_x[0] = rect.X();
-    quad_y[0] = rect.Y();
-    cairo_matrix_transform_point (CONST_CAIRO_MATRIX(this), &quad_x[0], &quad_y[0]);
-
-    quad_x[1] = rect.XMost();
-    quad_y[1] = rect.Y();
-    cairo_matrix_transform_point (CONST_CAIRO_MATRIX(this), &quad_x[1], &quad_y[1]);
-
-    quad_x[2] = rect.X();
-    quad_y[2] = rect.YMost();
-    cairo_matrix_transform_point (CONST_CAIRO_MATRIX(this), &quad_x[2], &quad_y[2]);
-
-    quad_x[3] = rect.XMost();
-    quad_y[3] = rect.YMost();
-    cairo_matrix_transform_point (CONST_CAIRO_MATRIX(this), &quad_x[3], &quad_y[3]);
-
-    min_x = max_x = quad_x[0];
-    min_y = max_y = quad_y[0];
-
-    for (i = 1; i < 4; i++) {
-        if (quad_x[i] < min_x)
-            min_x = quad_x[i];
-        if (quad_x[i] > max_x)
-            max_x = quad_x[i];
-
-        if (quad_y[i] < min_y)
-            min_y = quad_y[i];
-        if (quad_y[i] > max_y)
-            max_y = quad_y[i];
-    }
-
-    return gfxRect(min_x, min_y, max_x - min_x, max_y - min_y);
-}
-
-gfxMatrix&
-gfxMatrix::NudgeToIntegers(void)
-{
-    mozilla::gfx::NudgeToInteger(&_11);
-    mozilla::gfx::NudgeToInteger(&_21);
-    mozilla::gfx::NudgeToInteger(&_12);
-    mozilla::gfx::NudgeToInteger(&_22);
-    mozilla::gfx::NudgeToInteger(&_31);
-    mozilla::gfx::NudgeToInteger(&_32);
-    return *this;
-}
-
-mozilla::gfx::Matrix4x4
-gfxMatrix::operator *(const mozilla::gfx::Matrix4x4& aMatrix) const
-{
-  Matrix4x4 resultMatrix;
-
-  resultMatrix._11 = _11 * aMatrix._11 + _12 * aMatrix._21;
-  resultMatrix._12 = _11 * aMatrix._12 + _12 * aMatrix._22;
-  resultMatrix._13 = _11 * aMatrix._13 + _12 * aMatrix._23;
-  resultMatrix._14 = _11 * aMatrix._14 + _12 * aMatrix._24;
-
-  resultMatrix._21 = _21 * aMatrix._11 + _22 * aMatrix._21;
-  resultMatrix._22 = _21 * aMatrix._12 + _22 * aMatrix._22;
-  resultMatrix._23 = _21 * aMatrix._13 + _22 * aMatrix._23;
-  resultMatrix._24 = _21 * aMatrix._14 + _22 * aMatrix._24;
-
-  resultMatrix._31 = aMatrix._31;
-  resultMatrix._32 = aMatrix._32;
-  resultMatrix._33 = aMatrix._33;
-  resultMatrix._34 = aMatrix._34;
-
-  resultMatrix._41 = _31 * aMatrix._11 + _32 * aMatrix._21 + aMatrix._41;
-  resultMatrix._42 = _31 * aMatrix._12 + _32 * aMatrix._22 + aMatrix._42;
-  resultMatrix._43 = _31 * aMatrix._13 + _32 * aMatrix._23 + aMatrix._43;
-  resultMatrix._44 = _31 * aMatrix._14 + _32 * aMatrix._24 + aMatrix._44;
-
-  return resultMatrix;
-}
--- a/gfx/thebes/gfxMatrix.h
+++ b/gfx/thebes/gfxMatrix.h
@@ -1,322 +1,13 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * 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 GFX_MATRIX_H
 #define GFX_MATRIX_H
 
-#include "gfxPoint.h"
-#include "gfxTypes.h"
-#include "gfxRect.h"
-#include "mozilla/Attributes.h"
 #include "mozilla/gfx/MatrixFwd.h"
 
-// XX - I don't think this class should use gfxFloat at all,
-// but should use 'double' and be called gfxDoubleMatrix;
-// we can then typedef that to gfxMatrix where we typedef
-// double to be gfxFloat.
-
-/**
- * A matrix that represents an affine transformation. Projective
- * transformations are not supported. This matrix looks like:
- *
- * / a  b  0 \
- * | c  d  0 |
- * \ tx ty 1 /
- *
- * So, transforming a point (x, y) results in:
- *
- *           / a  b  0 \   / a * x + c * y + tx \ T
- * (x y 1) * | c  d  0 | = | b * x + d * y + ty |
- *           \ tx ty 1 /   \         1          /
- *
- */
-class gfxMatrix {
-public:
-    double _11; double _12;
-    double _21; double _22;
-    double _31; double _32;
-
-    /**
-     * Initializes this matrix as the identity matrix.
-     */
-    gfxMatrix() { Reset(); }
-
-    /**
-     * Initializes the matrix from individual components. See the class
-     * description for the layout of the matrix.
-     */
-    gfxMatrix(gfxFloat a, gfxFloat b, gfxFloat c, gfxFloat d, gfxFloat tx, gfxFloat ty) :
-        _11(a),  _12(b),
-        _21(c),  _22(d),
-        _31(tx), _32(ty) { }
-
-    MOZ_ALWAYS_INLINE gfxMatrix Copy() const {
-        return gfxMatrix(*this);
-    }
-
-    friend std::ostream& operator<<(std::ostream& stream, const gfxMatrix& m) {
-      if (m.IsIdentity()) {
-        return stream << "[identity]";
-      }
-
-      return stream << "["
-             << m._11 << " " << m._12
-             << m._21 << " " << m._22
-             << m._31 << " " << m._32
-             << "]";
-    }
-
-    /**
-     * Post-multiplies m onto the matrix.
-     */
-    const gfxMatrix& operator *= (const gfxMatrix& m);
-
-    /**
-     * Multiplies *this with m and returns the result.
-     */
-    gfxMatrix operator * (const gfxMatrix& m) const {
-        return gfxMatrix(*this) *= m;
-    }
-
-    /**
-     * Multiplies *this with aMatrix and returns the result.
-     */
-    mozilla::gfx::Matrix4x4 operator * (const mozilla::gfx::Matrix4x4& aMatrix) const;
-
-    /* Returns true if the other matrix is fuzzy-equal to this matrix.
-     * Note that this isn't a cheap comparison!
-     */
-    bool operator==(const gfxMatrix& 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 gfxMatrix& other) const
-    {
-      return !(*this == other);
-    }
-
-    // matrix operations
-    /**
-     * Resets this matrix to the identity matrix.
-     */
-    const gfxMatrix& Reset();
-
-    bool IsIdentity() const {
-       return _11 == 1.0 && _12 == 0.0 &&
-              _21 == 0.0 && _22 == 1.0 &&
-              _31 == 0.0 && _32 == 0.0;
-    }
-
-    /* Returns true if the matrix is a rectilinear transformation (i.e.
-     * grid-aligned rectangles are transformed to grid-aligned rectangles)
-     */
-    bool IsRectilinear() const {
-      if (FuzzyEqual(_12, 0) && FuzzyEqual(_21, 0)) {
-        return true;
-      } else if (FuzzyEqual(_22, 0) && FuzzyEqual(_11, 0)) {
-        return true;
-      }
-      return false;
-    }
-
-    /**
-     * Inverts this matrix, if possible. Otherwise, the matrix is left
-     * unchanged.
-     *
-     * XXX should this do something with the return value of
-     * cairo_matrix_invert?
-     */
-    bool Invert();
-
-    /**
-     * Check if matrix is singular (no inverse exists).
-     */
-    bool IsSingular() const {
-        // if the determinant (ad - bc) is zero it's singular
-        return (_11 * _22) == (_12 * _21);
-    }
-
-    /**
-     * Scales this matrix. The scale is pre-multiplied onto this matrix,
-     * i.e. the scaling takes place before the other transformations.
-     */
-    gfxMatrix& Scale(gfxFloat x, gfxFloat y);
-
-    /**
-     * Translates this matrix. The translation is pre-multiplied onto this matrix,
-     * i.e. the translation takes place before the other transformations.
-     */
-    gfxMatrix& Translate(const gfxPoint& pt);
-
-    gfxMatrix& Translate(gfxFloat x, gfxFloat y) {
-      return Translate(gfxPoint(x, y));
-    }
-
-    /**
-     * Rotates this matrix. The rotation is pre-multiplied onto this matrix,
-     * i.e. the translation takes place after the other transformations.
-     *
-     * @param radians Angle in radians.
-     */
-    gfxMatrix& Rotate(gfxFloat radians);
-
-    /**
-     * Multiplies the current matrix with m.
-     * This is a pre-multiplication, i.e. the transformations of m are
-     * applied _before_ the existing transformations.
-     */
-    gfxMatrix& PreMultiply(const gfxMatrix& m);
-
-    static gfxMatrix Translation(gfxFloat aX, gfxFloat aY)
-    {
-        return gfxMatrix(1.0, 0.0, 0.0, 1.0, aX, aY);
-    }
-
-    static gfxMatrix Translation(gfxPoint aPoint)
-    {
-        return Translation(aPoint.x, aPoint.y);
-    }
-
-    static gfxMatrix Rotation(gfxFloat aAngle);
-
-    static gfxMatrix Scaling(gfxFloat aX, gfxFloat aY)
-    {
-        return gfxMatrix(aX, 0.0, 0.0, aY, 0.0, 0.0);
-    }
-
-    /**
-     * Transforms a point according to this matrix.
-     */
-    gfxPoint Transform(const gfxPoint& point) const;
-
-
-    /**
-     * Transform a distance according to this matrix. This does not apply
-     * any translation components.
-     */
-    gfxSize Transform(const gfxSize& size) const;
-
-    /**
-     * Transforms both the point and distance according to this matrix.
-     */
-    gfxRect Transform(const gfxRect& rect) const;
-
-    gfxRect TransformBounds(const gfxRect& rect) const;
-
-    /**
-     * Returns the translation component of this matrix.
-     */
-    gfxPoint GetTranslation() const {
-        return gfxPoint(_31, _32);
-    }
-
-    /**
-     * Returns true if the matrix is anything other than a straight
-     * translation by integers.
-     */
-    bool HasNonIntegerTranslation() const {
-        return HasNonTranslation() ||
-            !FuzzyEqual(_31, floor(_31 + 0.5)) ||
-            !FuzzyEqual(_32, floor(_32 + 0.5));
-    }
-
-    /**
-     * Returns true if the matrix has any transform other
-     * than a straight translation
-     */
-    bool HasNonTranslation() const {
-        return !FuzzyEqual(_11, 1.0) || !FuzzyEqual(_22, 1.0) ||
-               !FuzzyEqual(_21, 0.0) || !FuzzyEqual(_12, 0.0);
-    }
-
-    /**
-     * Returns true if the matrix only has an integer translation.
-     */
-    bool HasOnlyIntegerTranslation() const {
-        return !HasNonIntegerTranslation();
-    }
-
-    /**
-     * Returns true if the matrix has any transform other
-     * than a translation or a -1 y scale (y axis flip)
-     */
-    bool HasNonTranslationOrFlip() const {
-        return !FuzzyEqual(_11, 1.0) ||
-               (!FuzzyEqual(_22, 1.0) && !FuzzyEqual(_22, -1.0)) ||
-               !FuzzyEqual(_21, 0.0) || !FuzzyEqual(_12, 0.0);
-    }
-
-    /**
-     * Returns true if the matrix has any transform other
-     * than a translation or scale; this is, if there is
-     * no rotation.
-     */
-    bool HasNonAxisAlignedTransform() const {
-        return !FuzzyEqual(_21, 0.0) || !FuzzyEqual(_12, 0.0);
-    }
-
-    /**
-     * Computes the determinant of this matrix.
-     */
-    double Determinant() const {
-        return _11*_22 - _12*_21;
-    }
-
-    /* Computes the scale factors of this matrix; that is,
-     * the amounts each basis vector is scaled by.
-     * The xMajor parameter indicates if the larger scale is
-     * to be assumed to be in the X direction or not.
-     */
-    gfxSize ScaleFactors(bool xMajor) const {
-        double det = Determinant();
-
-        if (det == 0.0)
-            return gfxSize(0.0, 0.0);
-
-        gfxSize sz = xMajor ? gfxSize(1.0, 0.0) : gfxSize(0.0, 1.0);
-        sz = Transform(sz);
-
-        double major = sqrt(sz.width * sz.width + sz.height * sz.height);
-        double minor = 0.0;
-
-        // ignore mirroring
-        if (det < 0.0)
-            det = - det;
-
-        if (major)
-            minor = det / major;
-
-        if (xMajor)
-            return gfxSize(major, minor);
-
-        return gfxSize(minor, major);
-    }
-
-    /**
-     * Snap matrix components that are close to integers
-     * to integers. In particular, components that are integral when
-     * converted to single precision are set to those integers.
-     */
-    gfxMatrix& NudgeToIntegers(void);
-
-    /**
-     * Returns true if matrix is multiple of 90 degrees rotation with flipping,
-     * scaling and translation.
-     */
-    bool PreservesAxisAlignedRectangles() const {
-        return ((FuzzyEqual(_11, 0.0) && FuzzyEqual(_22, 0.0))
-            || (FuzzyEqual(_21, 0.0) && FuzzyEqual(_12, 0.0)));
-    }
-
-private:
-    static bool FuzzyEqual(gfxFloat aV1, gfxFloat aV2) {
-        return fabs(aV2 - aV1) < 1e-6;
-    }
-};
+typedef mozilla::gfx::MatrixDouble gfxMatrix;
 
 #endif /* GFX_MATRIX_H */
--- a/gfx/thebes/gfxRect.cpp
+++ b/gfx/thebes/gfxRect.cpp
@@ -20,16 +20,34 @@ gfxRect::TransformToQuad(const mozilla::
   points[1] = aMatrix.TransformPoint(TopRight());
   points[2] = aMatrix.TransformPoint(BottomRight());
   points[3] = aMatrix.TransformPoint(BottomLeft());
 
   // Could this ever result in lines that intersect? I don't think so.
   return gfxQuad(points[0], points[1], points[2], points[3]);
 }
 
+void
+gfxRect::TransformBy(const mozilla::gfx::MatrixDouble& aMatrix)
+{
+  *this = gfxRect(aMatrix.TransformPoint(TopLeft()),
+                  aMatrix.TransformSize(Size()));
+}
+
+void
+gfxRect::TransformBoundsBy(const mozilla::gfx::MatrixDouble& aMatrix)
+{
+  RectDouble tmp(x, y, width, height);
+  tmp = aMatrix.TransformBounds(tmp);
+  x = tmp.x;
+  y = tmp.y;
+  width = tmp.width;
+  height = tmp.height;
+}
+
 static bool
 WithinEpsilonOfInteger(gfxFloat aX, gfxFloat aEpsilon)
 {
     return fabs(NS_round(aX) - aX) <= fabs(aEpsilon);
 }
 
 bool
 gfxRect::WithinEpsilonOfIntegerPixels(gfxFloat aEpsilon) const
--- a/gfx/thebes/gfxRect.h
+++ b/gfx/thebes/gfxRect.h
@@ -98,11 +98,17 @@ struct gfxRect :
         width /= k;
         height /= k;
     }
 
     /*
      * Transform this rectangle with aMatrix, resulting in a gfxQuad.
      */
     gfxQuad TransformToQuad(const mozilla::gfx::Matrix4x4 &aMatrix) const;
+
+    // Some temporary functions that we need until gfxRect gets turned into a
+    // typedef for RectDouble. It would be simpler to put these in Matrix.h
+    // but that code shouldn't #include gfxRect.h so we put it here instead.
+    void TransformBy(const mozilla::gfx::MatrixDouble& aMatrix);
+    void TransformBoundsBy(const mozilla::gfx::MatrixDouble& aMatrix);
 };
 
 #endif /* GFX_RECT_H */
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -193,17 +193,16 @@ UNIFIED_SOURCES += [
     'gfxFontInfoLoader.cpp',
     'gfxFontMissingGlyphs.cpp',
     'gfxGlyphExtents.cpp',
     'gfxGradientCache.cpp',
     'gfxGraphiteShaper.cpp',
     'gfxHarfBuzzShaper.cpp',
     'gfxImageSurface.cpp',
     'gfxMathTable.cpp',
-    'gfxMatrix.cpp',
     'gfxPattern.cpp',
     'gfxPlatformFontList.cpp',
     'gfxRect.cpp',
     'gfxScriptItemizer.cpp',
     'gfxSkipChars.cpp',
     'gfxSVGGlyphs.cpp',
     'gfxTextRun.cpp',
     'gfxUserFontSet.cpp',
--- a/image/ImageRegion.h
+++ b/image/ImageRegion.h
@@ -105,27 +105,27 @@ public:
     mRect.Scale(sx, sy);
     if (mIsRestricted) {
       mRestriction.Scale(sx, sy);
     }
   }
 
   void TransformBy(const gfxMatrix& aMatrix)
   {
-    mRect = aMatrix.Transform(mRect);
+    mRect.TransformBy(aMatrix);
     if (mIsRestricted) {
-      mRestriction = aMatrix.Transform(mRestriction);
+      mRestriction.TransformBy(aMatrix);
     }
   }
 
   void TransformBoundsBy(const gfxMatrix& aMatrix)
   {
-    mRect = aMatrix.TransformBounds(mRect);
+    mRect.TransformBoundsBy(aMatrix);
     if (mIsRestricted) {
-      mRestriction = aMatrix.TransformBounds(mRestriction);
+      mRestriction.TransformBoundsBy(aMatrix);
     }
   }
 
   ImageRegion operator-(const gfxPoint& aPt) const
   {
     if (mIsRestricted) {
       return CreateWithSamplingRestriction(mRect - aPt, mRestriction - aPt);
     }
--- a/image/OrientedImage.cpp
+++ b/image/OrientedImage.cpp
@@ -179,35 +179,35 @@ struct MatrixBuilder
 
   gfxMatrix Build() { return mMatrix; }
 
   void Scale(gfxFloat aX, gfxFloat aY)
   {
     if (mInvert) {
       mMatrix *= gfxMatrix::Scaling(1.0 / aX, 1.0 / aY);
     } else {
-      mMatrix.Scale(aX, aY);
+      mMatrix.PreScale(aX, aY);
     }
   }
 
   void Rotate(gfxFloat aPhi)
   {
     if (mInvert) {
       mMatrix *= gfxMatrix::Rotation(-aPhi);
     } else {
-      mMatrix.Rotate(aPhi);
+      mMatrix.PreRotate(aPhi);
     }
   }
 
   void Translate(gfxPoint aDelta)
   {
     if (mInvert) {
       mMatrix *= gfxMatrix::Translation(-aDelta);
     } else {
-      mMatrix.Translate(aDelta);
+      mMatrix.PreTranslate(aDelta);
     }
   }
 
 private:
   gfxMatrix mMatrix;
   bool      mInvert;
 };
 
@@ -359,17 +359,17 @@ OrientedImage::GetImageSpaceInvalidation
   rv = NS_FAILED(rv) ? rv : InnerImage()->GetHeight(&innerSize.height);
   if (NS_FAILED(rv)) {
     // Fall back to identity if the width and height aren't available.
     return rect;
   }
 
   // Transform the invalidation rect into the correct orientation.
   gfxMatrix matrix(OrientationMatrix(innerSize));
-  gfxRect invalidRect(matrix.TransformBounds(gfxRect(rect.x, rect.y,
-                                                     rect.width, rect.height)));
+  gfxRect invalidRect(rect.x, rect.y, rect.width, rect.height);
+  invalidRect.TransformBoundsBy(matrix);
 
   return IntRect::RoundOut(invalidRect.x, invalidRect.y,
                            invalidRect.width, invalidRect.height);
 }
 
 } // namespace image
 } // namespace mozilla
--- a/image/VectorImage.cpp
+++ b/image/VectorImage.cpp
@@ -299,18 +299,18 @@ SVGDrawingCallback::operator()(gfxContex
   aContext->Clip();
 
   gfxMatrix matrix = aTransform;
   if (!matrix.Invert()) {
     return false;
   }
   aContext->SetMatrix(
     aContext->CurrentMatrix().PreMultiply(matrix).
-                              Scale(double(mSize.width) / mViewportSize.width,
-                                    double(mSize.height) / mViewportSize.height));
+                              PreScale(double(mSize.width) / mViewportSize.width,
+                                       double(mSize.height) / mViewportSize.height));
 
   nsPresContext* presContext = presShell->GetPresContext();
   MOZ_ASSERT(presContext, "pres shell w/out pres context");
 
   nsRect svgRect(0, 0,
                  presContext->DevPixelsToAppUnits(mViewportSize.width),
                  presContext->DevPixelsToAppUnits(mViewportSize.height));
 
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -4690,18 +4690,18 @@ PresShell::RenderDocument(const nsRect& 
   gfxPoint offset(-nsPresContext::AppUnitsToFloatCSSPixels(aRect.x),
                   -nsPresContext::AppUnitsToFloatCSSPixels(aRect.y));
   gfxFloat scale = gfxFloat(devCtx->AppUnitsPerDevPixel())/nsPresContext::AppUnitsPerCSSPixel();
 
   // Since canvas APIs use floats to set up their matrices, we may have some
   // slight rounding errors here.  We use NudgeToIntegers() here to adjust
   // matrix components that are integers up to the accuracy of floats to be
   // those integers.
-  gfxMatrix newTM = aThebesContext->CurrentMatrix().Translate(offset).
-                                                    Scale(scale, scale).
+  gfxMatrix newTM = aThebesContext->CurrentMatrix().PreTranslate(offset).
+                                                    PreScale(scale, scale).
                                                     NudgeToIntegers();
   aThebesContext->SetMatrix(newTM);
 
   AutoSaveRestoreRenderingState _(this);
 
   bool wouldFlushRetainedLayers = false;
   PaintFrameFlags flags = PaintFrameFlags::PAINT_IGNORE_SUPPRESSION;
   if (aThebesContext->CurrentMatrix().HasNonIntegerTranslation()) {
@@ -5088,22 +5088,22 @@ PresShell::PaintRangePaintInfo(const nsT
 
     RefPtr<Path> path = builder->Finish();
     ctx->Clip(path);
   }
 
   gfxMatrix initialTM = ctx->CurrentMatrix();
 
   if (resize)
-    initialTM.Scale(scale, scale);
+    initialTM.PreScale(scale, scale);
 
   // translate so that points are relative to the surface area
   gfxPoint surfaceOffset =
     nsLayoutUtils::PointToGfxPoint(-aArea.TopLeft(), pc->AppUnitsPerDevPixel());
-  initialTM.Translate(surfaceOffset);
+  initialTM.PreTranslate(surfaceOffset);
 
   // temporarily hide the selection so that text is drawn normally. If a
   // selection is being rendered, use that, otherwise use the presshell's
   // selection.
   RefPtr<nsFrameSelection> frameSelection;
   if (aSelection) {
     frameSelection = aSelection->AsSelection()->GetFrameSelection();
   }
@@ -5115,17 +5115,17 @@ PresShell::PaintRangePaintInfo(const nsT
 
   // next, paint each range in the selection
   for (const UniquePtr<RangePaintInfo>& rangeInfo : aItems) {
     // the display lists paint relative to the offset from the reference
     // frame, so account for that translation too:
     gfxPoint rootOffset =
       nsLayoutUtils::PointToGfxPoint(rangeInfo->mRootOffset,
                                      pc->AppUnitsPerDevPixel());
-    ctx->SetMatrix(gfxMatrix(initialTM).Translate(rootOffset));
+    ctx->SetMatrix(gfxMatrix(initialTM).PreTranslate(rootOffset));
     aArea.MoveBy(-rangeInfo->mRootOffset.x, -rangeInfo->mRootOffset.y);
     nsRegion visible(aArea);
     RefPtr<LayerManager> layerManager =
         rangeInfo->mList.PaintRoot(&rangeInfo->mBuilder, ctx,
                                    nsDisplayList::PAINT_DEFAULT);
     aArea.MoveBy(rangeInfo->mRootOffset.x, rangeInfo->mRootOffset.y);
   }
 
@@ -10495,17 +10495,17 @@ void ReflowCountMgr::PaintCount(const ch
     if (counter != nullptr && counter->mName.EqualsASCII(aName)) {
       DrawTarget* drawTarget = aRenderingContext->GetDrawTarget();
       int32_t appUnitsPerDevPixel = aPresContext->AppUnitsPerDevPixel();
 
       aRenderingContext->Save();
       gfxPoint devPixelOffset =
         nsLayoutUtils::PointToGfxPoint(aOffset, appUnitsPerDevPixel);
       aRenderingContext->SetMatrix(
-        aRenderingContext->CurrentMatrix().Translate(devPixelOffset));
+        aRenderingContext->CurrentMatrix().PreTranslate(devPixelOffset));
 
       // We don't care about the document language or user fonts here;
       // just get a default Latin font.
       nsFont font(eFamily_serif, nsPresContext::CSSPixelsToAppUnits(11));
       nsFontMetrics::Params params;
       params.language = nsGkAtoms::x_western;
       params.textPerf = aPresContext->GetTextPerfMetrics();
       RefPtr<nsFontMetrics> fm =
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -3533,17 +3533,17 @@ nsLayoutUtils::PaintFrame(gfxContext* aR
       // scrolled frame instead of the root frame.
       nsPoint pos = rootScrollableFrame->GetScrollPosition();
       visibleRegion.MoveBy(-pos);
       if (aRenderingContext) {
         gfxPoint devPixelOffset =
           nsLayoutUtils::PointToGfxPoint(pos,
                                          presContext->AppUnitsPerDevPixel());
         aRenderingContext->SetMatrix(
-          aRenderingContext->CurrentMatrix().Translate(devPixelOffset));
+          aRenderingContext->CurrentMatrix().PreTranslate(devPixelOffset));
       }
     }
     builder.SetIgnoreScrollFrame(rootScrollFrame);
 
     nsCanvasFrame* canvasFrame =
       do_QueryFrame(rootScrollableFrame->GetScrolledFrame());
     if (canvasFrame) {
       // Use UnionRect here to ensure that areas where the scrollbars
@@ -6542,17 +6542,17 @@ ComputeSnappedImageDrawingParameters(gfx
                          gfxFloat(anchor.y)/aAppUnitsPerDevPixel);
     gfxPoint imageSpaceAnchorPoint =
       MapToFloatImagePixels(imageSize, devPixelDest, anchorPoint);
 
     if (didSnap) {
       imageSpaceAnchorPoint = StableRound(imageSpaceAnchorPoint);
       anchorPoint = imageSpaceAnchorPoint;
       anchorPoint = MapToFloatUserPixels(imageSize, devPixelDest, anchorPoint);
-      anchorPoint = currentMatrix.Transform(anchorPoint);
+      anchorPoint = currentMatrix.TransformPoint(anchorPoint);
       anchorPoint = StableRound(anchorPoint);
     }
 
     // Compute an unsnapped version of the dest rect's size. We continue to
     // follow the pattern that we take |currentMatrix| into account only if
     // |didSnap| is true.
     gfxSize unsnappedDestSize
       = didSnap ? devPixelDest.Size() * currentMatrix.ScaleFactors(true)
@@ -6582,25 +6582,29 @@ ComputeSnappedImageDrawingParameters(gfx
   // filtering will occur, and restricting the fill rect to the dirty rect
   // would change the values computed for edge pixels, which we can't allow.
   // Also, if 'didSnap' is false then rounding out 'devPixelDirty' might not
   // produce pixel-aligned coordinates, which would also break the values
   // computed for edge pixels.
   if (didSnap && !invTransform.HasNonIntegerTranslation()) {
     // This form of Transform is safe to call since non-axis-aligned
     // transforms wouldn't be snapped.
-    devPixelDirty = currentMatrix.Transform(devPixelDirty);
+    devPixelDirty.TransformBy(currentMatrix);
     devPixelDirty.RoundOut();
     fill = fill.Intersect(devPixelDirty);
   }
   if (fill.IsEmpty())
     return SnappedImageDrawingParameters();
 
-  gfxRect imageSpaceFill(didSnap ? invTransform.Transform(fill)
-                                 : invTransform.TransformBounds(fill));
+  gfxRect imageSpaceFill = fill;
+  if (didSnap) {
+    imageSpaceFill.TransformBy(invTransform);
+  } else {
+    imageSpaceFill.TransformBoundsBy(invTransform);
+  }
 
   // If we didn't snap, we need to post-multiply the matrix on the context to
   // get the final matrix we'll draw with, because we didn't take it into
   // account when computing the matrices above.
   if (!didSnap) {
     transform = transform * currentMatrix;
   }
 
--- a/layout/generic/nsCanvasFrame.cpp
+++ b/layout/generic/nsCanvasFrame.cpp
@@ -383,17 +383,17 @@ nsDisplayCanvasBackgroundImage::Paint(ns
     }
 
     dt = destDT->CreateSimilarDrawTarget(IntSize::Ceil(destRect.width,
                                                        destRect.height),
                                          SurfaceFormat::B8G8R8A8);
     if (dt && dt->IsValid()) {
       RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(dt);
       MOZ_ASSERT(ctx); // already checked draw target above
-      ctx->SetMatrix(ctx->CurrentMatrix().Translate(-destRect.x, -destRect.y));
+      ctx->SetMatrix(ctx->CurrentMatrix().PreTranslate(-destRect.x, -destRect.y));
       PaintInternal(aBuilder, ctx, bgClipRect, &bgClipRect);
       BlitSurface(dest->GetDrawTarget(), destRect, dt);
       frame->SetProperty(nsIFrame::CachedBackgroundImageDT(),
                               dt.forget().take());
       return;
     }
   }
 #endif
--- a/layout/generic/nsPluginFrame.cpp
+++ b/layout/generic/nsPluginFrame.cpp
@@ -875,17 +875,17 @@ nsPluginFrame::PaintPrintPlugin(nsIFrame
                                 const nsRect& aDirtyRect, nsPoint aPt)
 {
   // Translate the context:
   nsPoint pt = aPt + aFrame->GetContentRectRelativeToSelf().TopLeft();
   gfxPoint devPixelPt =
     nsLayoutUtils::PointToGfxPoint(pt, aFrame->PresContext()->AppUnitsPerDevPixel());
 
   gfxContextMatrixAutoSaveRestore autoSR(aCtx);
-  aCtx->SetMatrix(aCtx->CurrentMatrix().Translate(devPixelPt));
+  aCtx->SetMatrix(aCtx->CurrentMatrix().PreTranslate(devPixelPt));
 
   // FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
 
   static_cast<nsPluginFrame*>(aFrame)->PrintPlugin(*aCtx, aDirtyRect);
 }
 
 /**
  * nsDisplayPluginReadback creates an active ReadbackLayer. The ReadbackLayer
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -5268,17 +5268,17 @@ nsDisplayText::RenderToContext(gfxContex
   if (f->StyleContext()->IsTextCombined()) {
     float scaleFactor = GetTextCombineScaleFactor(f);
     if (scaleFactor != 1.0f) {
       // Setup matrix to compress text for text-combine-upright if
       // necessary. This is done here because we want selection be
       // compressed at the same time as text.
       gfxPoint pt = nsLayoutUtils::PointToGfxPoint(framePt, A2D);
       gfxMatrix mat = aCtx->CurrentMatrix()
-        .Translate(pt).Scale(scaleFactor, 1.0).Translate(-pt);
+        .PreTranslate(pt).PreScale(scaleFactor, 1.0).PreTranslate(-pt);
       aCtx->SetMatrix(mat);
     }
   }
   nsTextFrame::PaintTextParams params(aCtx);
   params.framePt = gfxPoint(framePt.x, framePt.y);
   params.dirtyRect = extraVisible;
 
   if (aBuilder->IsForGenerateGlyphMask()) {
@@ -7291,17 +7291,17 @@ nsTextFrame::DrawTextRunAndDecorations(R
     // we need to revert the scaling here.
     gfxContextMatrixAutoSaveRestore scaledRestorer;
     if (StyleContext()->IsTextCombined()) {
       float scaleFactor = GetTextCombineScaleFactor(this);
       if (scaleFactor != 1.0f) {
         scaledRestorer.SetContext(aParams.context);
         gfxMatrix unscaled = aParams.context->CurrentMatrix();
         gfxPoint pt(x / app, y / app);
-        unscaled.Translate(pt).Scale(1.0f / scaleFactor, 1.0f).Translate(-pt);
+        unscaled.PreTranslate(pt).PreScale(1.0f / scaleFactor, 1.0f).PreTranslate(-pt);
         aParams.context->SetMatrix(unscaled);
       }
     }
 
     typedef gfxFont::Metrics Metrics;
     auto paintDecorationLine = [&](const LineDecoration& dec,
                                    gfxFloat Metrics::* lineSize,
                                    gfxFloat Metrics::* lineOffset) {
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -2015,25 +2015,25 @@ nsMathMLChar::ApplyTransforms(gfxContext
                               nsRect &r)
 {
   // apply the transforms
   if (mMirrored) {
     nsPoint pt = r.TopRight();
     gfxPoint devPixelOffset(NSAppUnitsToFloatPixels(pt.x, aAppUnitsPerGfxUnit),
                             NSAppUnitsToFloatPixels(pt.y, aAppUnitsPerGfxUnit));
     aThebesContext->SetMatrix(
-      aThebesContext->CurrentMatrix().Translate(devPixelOffset).
-                                      Scale(-mScaleX, mScaleY));
+      aThebesContext->CurrentMatrix().PreTranslate(devPixelOffset).
+                                      PreScale(-mScaleX, mScaleY));
   } else {
     nsPoint pt = r.TopLeft();
     gfxPoint devPixelOffset(NSAppUnitsToFloatPixels(pt.x, aAppUnitsPerGfxUnit),
                             NSAppUnitsToFloatPixels(pt.y, aAppUnitsPerGfxUnit));
     aThebesContext->SetMatrix(
-      aThebesContext->CurrentMatrix().Translate(devPixelOffset).
-                                      Scale(mScaleX, mScaleY));
+      aThebesContext->CurrentMatrix().PreTranslate(devPixelOffset).
+                                      PreScale(mScaleX, mScaleY));
   }
 
   // update the bounding rectangle.
   r.x = r.y = 0;
   r.width /= mScaleX;
   r.height /= mScaleY;
 }
 
--- a/layout/painting/FrameLayerBuilder.cpp
+++ b/layout/painting/FrameLayerBuilder.cpp
@@ -6214,34 +6214,34 @@ FrameLayerBuilder::DrawPaintedLayer(Pain
 
       DrawForcedBackgroundColor(aDrawTarget, iterRect,
                                 userData->mForcedBackgroundColor);
 
       // Apply the residual transform if it has been enabled, to ensure that
       // snapping when we draw into aContext exactly matches the ideal transform.
       // See above for why this is OK.
       aContext->SetMatrix(
-        aContext->CurrentMatrix().Translate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y)).
-                                  Scale(userData->mXScale, userData->mYScale));
+        aContext->CurrentMatrix().PreTranslate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y)).
+                                  PreScale(userData->mXScale, userData->mYScale));
 
       layerBuilder->PaintItems(entry->mItems, iterRect, aContext, aContext,
                                builder, presContext,
                                offset, userData->mXScale, userData->mYScale,
                                entry->mCommonClipCount);
       if (gfxPrefs::GfxLoggingPaintedPixelCountEnabled()) {
         aLayer->Manager()->AddPaintedPixelCount(iterRect.Area());
       }
     }
   } else {
     // Apply the residual transform if it has been enabled, to ensure that
     // snapping when we draw into aContext exactly matches the ideal transform.
     // See above for why this is OK.
     aContext->SetMatrix(
-      aContext->CurrentMatrix().Translate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y)).
-                                Scale(userData->mXScale,userData->mYScale));
+      aContext->CurrentMatrix().PreTranslate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y)).
+                                PreScale(userData->mXScale,userData->mYScale));
 
     layerBuilder->PaintItems(entry->mItems, aRegionToDraw.GetBounds(), aContext, aContext,
                              builder, presContext,
                              offset, userData->mXScale, userData->mYScale,
                              entry->mCommonClipCount);
     if (gfxPrefs::GfxLoggingPaintedPixelCountEnabled()) {
       aLayer->Manager()->AddPaintedPixelCount(
         aRegionToDraw.GetBounds().Area());
--- a/layout/painting/nsCSSRendering.cpp
+++ b/layout/painting/nsCSSRendering.cpp
@@ -1569,17 +1569,17 @@ nsCSSRendering::PaintBoxShadowOuter(nsPr
 
       // Draw the widget shape
       gfxContextMatrixAutoSaveRestore save(shadowContext);
       gfxPoint devPixelOffset =
         nsLayoutUtils::PointToGfxPoint(nsPoint(shadowItem->mXOffset,
                                                shadowItem->mYOffset),
                                        aPresContext->AppUnitsPerDevPixel());
       shadowContext->SetMatrix(
-        shadowContext->CurrentMatrix().Translate(devPixelOffset));
+        shadowContext->CurrentMatrix().PreTranslate(devPixelOffset));
 
       nsRect nativeRect = aDirtyRect;
       nativeRect.MoveBy(-nsPoint(shadowItem->mXOffset, shadowItem->mYOffset));
       nativeRect.IntersectRect(frameRect, nativeRect);
       aPresContext->GetTheme()->DrawWidgetBackground(shadowContext, aForFrame,
           styleDisplay->mAppearance, aFrameArea, nativeRect);
 
       blurringArea.DoPaint();
@@ -4282,24 +4282,25 @@ nsContextBoxBlur::Init(const nsRect& aRe
   // Convert from app units to device pixels
   gfxRect rect = nsLayoutUtils::RectToGfxRect(aRect, aAppUnitsPerDevPixel);
 
   gfxRect dirtyRect =
     nsLayoutUtils::RectToGfxRect(aDirtyRect, aAppUnitsPerDevPixel);
   dirtyRect.RoundOut();
 
   gfxMatrix transform = aDestinationCtx->CurrentMatrix();
-  rect = transform.TransformBounds(rect);
+  rect.TransformBoundsBy(transform);
 
   mPreTransformed = !transform.IsIdentity();
 
   // Create the temporary surface for blurring
-  dirtyRect = transform.TransformBounds(dirtyRect);
+  dirtyRect.TransformBoundsBy(transform);
   if (aSkipRect) {
-    gfxRect skipRect = transform.TransformBounds(*aSkipRect);
+    gfxRect skipRect = *aSkipRect;
+    skipRect.TransformBoundsBy(transform);
     mContext = mAlphaBoxBlur.Init(aDestinationCtx, rect, spreadRadius,
                                   blurRadius, &dirtyRect, &skipRect);
   } else {
     mContext = mAlphaBoxBlur.Init(aDestinationCtx, rect, spreadRadius,
                                   blurRadius, &dirtyRect, nullptr);
   }
 
   if (mContext) {
@@ -4392,19 +4393,21 @@ nsContextBoxBlur::BlurRectangle(gfxConte
   }
 
   gfxPoint blurStdDev = ComputeBlurStdDev(aBlurRadius, aAppUnitsPerDevPixel, scaleX, scaleY);
 
   gfxRect dirtyRect =
     nsLayoutUtils::RectToGfxRect(aDirtyRect, aAppUnitsPerDevPixel);
   dirtyRect.RoundOut();
 
-  gfxRect shadowThebesRect = transform.TransformBounds(ThebesRect(shadowGfxRect));
-  dirtyRect = transform.TransformBounds(dirtyRect);
-  gfxRect skipRect = transform.TransformBounds(aSkipRect);
+  gfxRect shadowThebesRect = ThebesRect(shadowGfxRect);
+  shadowThebesRect.TransformBoundsBy(transform);
+  dirtyRect.TransformBoundsBy(transform);
+  gfxRect skipRect = aSkipRect;
+  skipRect.TransformBoundsBy(transform);
 
   if (aCornerRadii) {
     aCornerRadii->Scale(scaleX, scaleY);
   }
 
   gfxAlphaBoxBlur::BlurRectangle(aDestinationCtx,
                                  shadowThebesRect,
                                  aCornerRadii,
--- a/layout/painting/nsCSSRenderingGradients.cpp
+++ b/layout/painting/nsCSSRenderingGradients.cpp
@@ -282,23 +282,23 @@ static bool
 RectIsBeyondLinearGradientEdge(const gfxRect& aRect,
                                const gfxMatrix& aPatternMatrix,
                                const nsTArray<ColorStop>& aStops,
                                const gfxPoint& aGradientStart,
                                const gfxPoint& aGradientEnd,
                                Color* aOutEdgeColor)
 {
   gfxFloat topLeft = LinearGradientStopPositionForPoint(
-    aGradientStart, aGradientEnd, aPatternMatrix.Transform(aRect.TopLeft()));
+    aGradientStart, aGradientEnd, aPatternMatrix.TransformPoint(aRect.TopLeft()));
   gfxFloat topRight = LinearGradientStopPositionForPoint(
-    aGradientStart, aGradientEnd, aPatternMatrix.Transform(aRect.TopRight()));
+    aGradientStart, aGradientEnd, aPatternMatrix.TransformPoint(aRect.TopRight()));
   gfxFloat bottomLeft = LinearGradientStopPositionForPoint(
-    aGradientStart, aGradientEnd, aPatternMatrix.Transform(aRect.BottomLeft()));
+    aGradientStart, aGradientEnd, aPatternMatrix.TransformPoint(aRect.BottomLeft()));
   gfxFloat bottomRight = LinearGradientStopPositionForPoint(
-    aGradientStart, aGradientEnd, aPatternMatrix.Transform(aRect.BottomRight()));
+    aGradientStart, aGradientEnd, aPatternMatrix.TransformPoint(aRect.BottomRight()));
 
   const ColorStop& firstStop = aStops[0];
   if (topLeft < firstStop.mPosition && topRight < firstStop.mPosition &&
       bottomLeft < firstStop.mPosition && bottomRight < firstStop.mPosition) {
     *aOutEdgeColor = firstStop.mColor;
     return true;
   }
 
@@ -689,17 +689,17 @@ nsCSSGradientRenderer::Paint(gfxContext&
     // The position of the start of the rectangle along the gradient.
     double offset;
 
     // The gradient line is "backwards". Flip the line upside down to make
     // things easier, and then rotate the matrix to turn everything back the
     // right way up.
     if (mLineStart.x > mLineEnd.x || mLineStart.y > mLineEnd.y) {
       std::swap(mLineStart, mLineEnd);
-      matrix.Scale(-1, -1);
+      matrix.PreScale(-1, -1);
     }
 
     // Fit the gradient line exactly into the source rect.
     // aSrc is relative to aIntrinsincSize.
     // srcRectDev will be relative to srcSize, so in the same coordinate space
     // as lineStart / lineEnd.
     gfxRect srcRectDev = nsLayoutUtils::RectToGfxRect(
       CSSPixel::ToAppUnits(aSrc), appUnitsPerDevPixel);
@@ -862,26 +862,26 @@ nsCSSGradientRenderer::Paint(gfxContext&
     gradientPattern = new gfxPattern(mLineStart.x, mLineStart.y, innerRadius,
                                      mLineStart.x, mLineStart.y, outerRadius);
     if (mRadiusX != mRadiusY) {
       // Stretch the circles into ellipses vertically by setting a transform
       // in the pattern.
       // Recall that this is the transform from user space to pattern space.
       // So to stretch the ellipse by factor of P vertically, we scale
       // user coordinates by 1/P.
-      matrix.Translate(mLineStart);
-      matrix.Scale(1.0, mRadiusX/mRadiusY);
-      matrix.Translate(-mLineStart);
+      matrix.PreTranslate(mLineStart);
+      matrix.PreScale(1.0, mRadiusX/mRadiusY);
+      matrix.PreTranslate(-mLineStart);
     }
   }
   // Use a pattern transform to take account of source and dest rects
-  matrix.Translate(gfxPoint(mPresContext->CSSPixelsToDevPixels(aSrc.x),
-                            mPresContext->CSSPixelsToDevPixels(aSrc.y)));
-  matrix.Scale(gfxFloat(mPresContext->CSSPixelsToAppUnits(aSrc.width))/aDest.width,
-               gfxFloat(mPresContext->CSSPixelsToAppUnits(aSrc.height))/aDest.height);
+  matrix.PreTranslate(gfxPoint(mPresContext->CSSPixelsToDevPixels(aSrc.x),
+                               mPresContext->CSSPixelsToDevPixels(aSrc.y)));
+  matrix.PreScale(gfxFloat(mPresContext->CSSPixelsToAppUnits(aSrc.width))/aDest.width,
+                  gfxFloat(mPresContext->CSSPixelsToAppUnits(aSrc.height))/aDest.height);
   gradientPattern->SetMatrix(matrix);
 
   if (stopDelta == 0.0) {
     // Non-repeating gradient with all stops in same place -> just add
     // first stop and last stop, both at position 0.
     // Repeating gradient with all stops in the same place, or radial
     // gradient with radius of 0 -> just paint the last stop color.
     // We use firstStop offset to keep |stops| with same units (will later normalize to 0).
@@ -985,17 +985,17 @@ nsCSSGradientRenderer::Paint(gfxContext&
       Color edgeColor;
       if (mGradient->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR && !isRepeat &&
           RectIsBeyondLinearGradientEdge(fillRectRelativeToTile, matrix, mStops,
                                          gradientStart, gradientEnd, &edgeColor)) {
         edgeColor.a *= aOpacity;
         aContext.SetColor(edgeColor);
       } else {
         aContext.SetMatrix(
-          aContext.CurrentMatrix().Copy().Translate(tileRect.TopLeft()));
+          aContext.CurrentMatrix().Copy().PreTranslate(tileRect.TopLeft()));
         aContext.SetPattern(gradientPattern);
       }
       aContext.Fill();
       aContext.SetMatrix(ctm);
     }
   }
 }
 
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -692,17 +692,17 @@ GenerateAndPushTextMask(nsIFrame* aFrame
   gfxContext* sourceCtx = aContext;
   gfxRect bounds =
     nsLayoutUtils::RectToGfxRect(aFillRect,
                                  aFrame->PresContext()->AppUnitsPerDevPixel());
 
   {
     // Paint text selection background into sourceCtx.
     gfxContextMatrixAutoSaveRestore save(sourceCtx);
-    sourceCtx->SetMatrix(sourceCtx->CurrentMatrix().Translate(bounds.TopLeft()));
+    sourceCtx->SetMatrix(sourceCtx->CurrentMatrix().PreTranslate(bounds.TopLeft()));
 
     nsLayoutUtils::PaintFrame(aContext, aFrame,
                               nsRect(nsPoint(0, 0), aFrame->GetSize()),
                               NS_RGB(255, 255, 255),
                               nsDisplayListBuilderMode::PAINTING_SELECTION_BACKGROUND);
   }
 
   // Evaluate required surface size.
@@ -8405,17 +8405,17 @@ ComputeMaskGeometry(PaintFramesParams& a
   nsIFrame* frame = aParams.frame;
 
   nsPoint offsetToUserSpace = ComputeOffsetToUserSpace(aParams);
   gfxPoint devPixelOffsetToUserSpace =
     nsLayoutUtils::PointToGfxPoint(offsetToUserSpace,
                                    frame->PresContext()->AppUnitsPerDevPixel());
 
   gfxContextMatrixAutoSaveRestore matSR(&ctx);
-  ctx.SetMatrix(ctx.CurrentMatrix().Translate(devPixelOffsetToUserSpace));
+  ctx.SetMatrix(ctx.CurrentMatrix().PreTranslate(devPixelOffsetToUserSpace));
 
   // Convert boaderArea and dirtyRect to user space.
   int32_t appUnitsPerDevPixel = frame->PresContext()->AppUnitsPerDevPixel();
   nsRect userSpaceBorderArea = aParams.borderArea - offsetToUserSpace;
   nsRect userSpaceDirtyRect = aParams.dirtyRect - offsetToUserSpace;
 
   // Union all mask layer rectangles in user space.
   gfxRect maskInUserSpace;
--- a/layout/svg/SVGTextFrame.cpp
+++ b/layout/svg/SVGTextFrame.cpp
@@ -426,18 +426,18 @@ FrameIfAnonymousChildReflowed(SVGTextFra
 }
 
 static double
 GetContextScale(const gfxMatrix& aMatrix)
 {
   // The context scale is the ratio of the length of the transformed
   // diagonal vector (1,1) to the length of the untransformed diagonal
   // (which is sqrt(2)).
-  gfxPoint p = aMatrix.Transform(gfxPoint(1, 1)) -
-               aMatrix.Transform(gfxPoint(0, 0));
+  gfxPoint p = aMatrix.TransformPoint(gfxPoint(1, 1)) -
+               aMatrix.TransformPoint(gfxPoint(0, 0));
   return SVGContentUtils::ComputeNormalizedHypotenuse(p.x, p.y);
 }
 
 // ============================================================================
 // Utility classes
 
 namespace mozilla {
 
@@ -797,40 +797,40 @@ TextRenderedRun::GetTransformFromUserSpa
   if (!mFrame) {
     return m;
   }
 
   float cssPxPerDevPx = aContext->
     AppUnitsToFloatCSSPixels(aContext->AppUnitsPerDevPixel());
 
   // Glyph position in user space.
-  m.Translate(mPosition / cssPxPerDevPx);
+  m.PreTranslate(mPosition / cssPxPerDevPx);
 
   // Take into account any font size scaling and scaling due to textLength="".
-  m.Scale(1.0 / mFontSizeScaleFactor, 1.0 / mFontSizeScaleFactor);
+  m.PreScale(1.0 / mFontSizeScaleFactor, 1.0 / mFontSizeScaleFactor);
 
   // Rotation due to rotate="" or a <textPath>.
-  m.Rotate(mRotate);
-
-  m.Scale(mLengthAdjustScaleFactor, 1.0);
+  m.PreRotate(mRotate);
+
+  m.PreScale(mLengthAdjustScaleFactor, 1.0);
 
   // Translation to get the text frame in the right place.
   nsPoint t;
   if (IsVertical()) {
     t = nsPoint(-mBaseline,
                 IsRightToLeft()
                   ? -mFrame->GetRect().height + aItem.mVisIEndEdge
                   : -aItem.mVisIStartEdge);
   } else {
     t = nsPoint(IsRightToLeft()
                   ? -mFrame->GetRect().width + aItem.mVisIEndEdge
                   : -aItem.mVisIStartEdge,
                 -mBaseline);
   }
-  m.Translate(AppUnitsToGfxUnits(t, aContext));
+  m.PreTranslate(AppUnitsToGfxUnits(t, aContext));
 
   return m;
 }
 
 gfxMatrix
 TextRenderedRun::GetTransformFromRunUserSpaceToUserSpace(
                                                   nsPresContext* aContext) const
 {
@@ -841,39 +841,39 @@ TextRenderedRun::GetTransformFromRunUser
 
   float cssPxPerDevPx = aContext->
     AppUnitsToFloatCSSPixels(aContext->AppUnitsPerDevPixel());
 
   nscoord start, end;
   GetClipEdges(start, end);
 
   // Glyph position in user space.
-  m.Translate(mPosition);
+  m.PreTranslate(mPosition);
 
   // Rotation due to rotate="" or a <textPath>.
-  m.Rotate(mRotate);
+  m.PreRotate(mRotate);
 
   // Scale due to textLength="".
-  m.Scale(mLengthAdjustScaleFactor, 1.0);
+  m.PreScale(mLengthAdjustScaleFactor, 1.0);
 
   // Translation to get the text frame in the right place.
   nsPoint t;
   if (IsVertical()) {
     t = nsPoint(-mBaseline,
                 IsRightToLeft()
                   ? -mFrame->GetRect().height + start + end
                   : 0);
   } else {
     t = nsPoint(IsRightToLeft()
                   ? -mFrame->GetRect().width + start + end
                   : 0,
                 -mBaseline);
   }
-  m.Translate(AppUnitsToGfxUnits(t, aContext) *
-                cssPxPerDevPx / mFontSizeScaleFactor);
+  m.PreTranslate(AppUnitsToGfxUnits(t, aContext) *
+                   cssPxPerDevPx / mFontSizeScaleFactor);
 
   return m;
 }
 
 gfxMatrix
 TextRenderedRun::GetTransformFromRunUserSpaceToFrameUserSpace(
                                                   nsPresContext* aContext) const
 {
@@ -885,17 +885,17 @@ TextRenderedRun::GetTransformFromRunUser
   nscoord start, end;
   GetClipEdges(start, end);
 
   // Translate by the horizontal distance into the text frame this
   // rendered run is.
   gfxFloat appPerCssPx = aContext->AppUnitsPerCSSPixel();
   gfxPoint t = IsVertical() ? gfxPoint(0, start / appPerCssPx)
                             : gfxPoint(start / appPerCssPx, 0);
-  return m.Translate(t);
+  return m.PreTranslate(t);
 }
 
 SVGBBox
 TextRenderedRun::GetRunUserSpaceRect(nsPresContext* aContext,
                                      uint32_t aFlags) const
 {
   SVGBBox r;
   if (!mFrame) {
@@ -994,33 +994,37 @@ SVGBBox
 TextRenderedRun::GetFrameUserSpaceRect(nsPresContext* aContext,
                                        uint32_t aFlags) const
 {
   SVGBBox r = GetRunUserSpaceRect(aContext, aFlags);
   if (r.IsEmpty()) {
     return r;
   }
   gfxMatrix m = GetTransformFromRunUserSpaceToFrameUserSpace(aContext);
-  return m.TransformBounds(r.ToThebesRect());
+  gfxRect thebesRect = r.ToThebesRect();
+  thebesRect.TransformBoundsBy(m);
+  return thebesRect;
 }
 
 SVGBBox
 TextRenderedRun::GetUserSpaceRect(nsPresContext* aContext,
                                   uint32_t aFlags,
                                   const gfxMatrix* aAdditionalTransform) const
 {
   SVGBBox r = GetRunUserSpaceRect(aContext, aFlags);
   if (r.IsEmpty()) {
     return r;
   }
   gfxMatrix m = GetTransformFromRunUserSpaceToUserSpace(aContext);
   if (aAdditionalTransform) {
     m *= *aAdditionalTransform;
   }
-  return m.TransformBounds(r.ToThebesRect());
+  gfxRect thebesRect = r.ToThebesRect();
+  thebesRect.TransformBoundsBy(m);
+  return thebesRect;
 }
 
 void
 TextRenderedRun::GetClipEdges(nscoord& aVisIStartEdge,
                               nscoord& aVisIEndEdge) const
 {
   uint32_t contentLength = mFrame->GetContentLength();
   if (mTextFrameContentOffset == 0 &&
@@ -1098,17 +1102,17 @@ TextRenderedRun::GetCharNumAtPosition(ns
     AppUnitsToFloatCSSPixels(aContext->AppUnitsPerDevPixel());
 
   // Convert the point from user space into run user space, and take
   // into account any mFontSizeScaleFactor.
   gfxMatrix m = GetTransformFromRunUserSpaceToUserSpace(aContext);
   if (!m.Invert()) {
     return -1;
   }
-  gfxPoint p = m.Transform(aPoint) / cssPxPerDevPx * mFontSizeScaleFactor;
+  gfxPoint p = m.TransformPoint(aPoint) / cssPxPerDevPx * mFontSizeScaleFactor;
 
   // First check that the point lies vertically between the top and bottom
   // edges of the text.
   gfxFloat ascent, descent;
   GetAscentAndDescentInAppUnits(mFrame, ascent, descent);
 
   WritingMode writingMode = mFrame->GetWritingMode();
   if (writingMode.IsVertical()) {
@@ -3619,31 +3623,31 @@ SVGTextFrame::PaintSVG(gfxContext& aCont
                      aDirtyRect->width, aDirtyRect->height);
 
     gfxFloat appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
     gfxRect frameRect(mRect.x / appUnitsPerDevPixel,
                       mRect.y / appUnitsPerDevPixel,
                       mRect.width / appUnitsPerDevPixel,
                       mRect.height / appUnitsPerDevPixel);
 
-    nsRect canvasRect = nsLayoutUtils::RoundGfxRectToAppRect(
-        GetCanvasTM().TransformBounds(frameRect), 1);
+    frameRect.TransformBoundsBy(GetCanvasTM());
+    nsRect canvasRect = nsLayoutUtils::RoundGfxRectToAppRect(frameRect, 1);
     if (!canvasRect.Intersects(dirtyRect)) {
       return;
     }
   }
 
   // SVG frames' PaintSVG methods paint in CSS px, but normally frames paint in
   // dev pixels. Here we multiply a CSS-px-to-dev-pixel factor onto aTransform
   // so our non-SVG nsTextFrame children paint correctly.
   auto auPerDevPx = presContext->AppUnitsPerDevPixel();
   float cssPxPerDevPx = presContext->AppUnitsToFloatCSSPixels(auPerDevPx);
   gfxMatrix canvasTMForChildren = aTransform;
-  canvasTMForChildren.Scale(cssPxPerDevPx, cssPxPerDevPx);
-  initialMatrix.Scale(1 / cssPxPerDevPx, 1 / cssPxPerDevPx);
+  canvasTMForChildren.PreScale(cssPxPerDevPx, cssPxPerDevPx);
+  initialMatrix.PreScale(1 / cssPxPerDevPx, 1 / cssPxPerDevPx);
 
   gfxContextAutoSaveRestore save(&aContext);
   aContext.NewPath();
   aContext.Multiply(canvasTMForChildren);
   gfxMatrix currentMatrix = aContext.CurrentMatrix();
 
   RefPtr<nsCaret> caret = presContext->PresShell()->GetCaret();
   nsRect caretRect;
@@ -3750,17 +3754,17 @@ SVGTextFrame::GetFrameForPoint(const gfx
       continue;
     }
 
     gfxMatrix m = run.GetTransformFromRunUserSpaceToUserSpace(presContext);
     if (!m.Invert()) {
       return nullptr;
     }
 
-    gfxPoint pointInRunUserSpace = m.Transform(aPoint);
+    gfxPoint pointInRunUserSpace = m.TransformPoint(aPoint);
     gfxRect frameRect =
       run.GetRunUserSpaceRect(presContext, TextRenderedRun::eIncludeFill |
                                            TextRenderedRun::eIncludeStroke).ToThebesRect();
 
     if (Inside(frameRect, pointInRunUserSpace)) {
       hit = run.mFrame;
     }
   }
@@ -4274,35 +4278,36 @@ SVGTextFrame::GetExtentOfChar(nsIContent
 
   // Get the advance of the glyph.
   gfxFloat advance = it.GetGlyphAdvance(presContext);
   gfxFloat x = it.TextRun()->IsRightToLeft() ? -advance : 0.0;
 
   // The horizontal extent is the origin of the glyph plus the advance
   // in the direction of the glyph's rotation.
   gfxMatrix m;
-  m.Translate(mPositions[startIndex].mPosition);
-  m.Rotate(mPositions[startIndex].mAngle);
-  m.Scale(1 / mFontSizeScaleFactor, 1 / mFontSizeScaleFactor);
+  m.PreTranslate(mPositions[startIndex].mPosition);
+  m.PreRotate(mPositions[startIndex].mAngle);
+  m.PreScale(1 / mFontSizeScaleFactor, 1 / mFontSizeScaleFactor);
 
   gfxRect glyphRect;
   if (it.TextRun()->IsVertical()) {
     glyphRect =
       gfxRect(-presContext->AppUnitsToGfxUnits(descent) * cssPxPerDevPx, x,
               presContext->AppUnitsToGfxUnits(ascent + descent) * cssPxPerDevPx,
               advance);
   } else {
     glyphRect =
       gfxRect(x, -presContext->AppUnitsToGfxUnits(ascent) * cssPxPerDevPx,
               advance,
               presContext->AppUnitsToGfxUnits(ascent + descent) * cssPxPerDevPx);
   }
 
   // Transform the glyph's rect into user space.
-  gfxRect r = m.TransformBounds(glyphRect);
+  glyphRect.TransformBoundsBy(m);
+  gfxRect r = glyphRect;
 
   NS_ADDREF(*aResult = new dom::SVGRect(aContent, r.x, r.y, r.width, r.height));
   return NS_OK;
 }
 
 /**
  * Implements the SVG DOM GetRotationOfChar method for the specified
  * text content element.
@@ -5484,17 +5489,17 @@ SVGTextFrame::TransformFramePointToTextC
                      TextRenderedRun::eIncludeStroke |
                      TextRenderedRun::eNoHorizontalOverflow;
     gfxRect runRect = run.GetRunUserSpaceRect(presContext, flags).ToThebesRect();
 
     gfxMatrix m = run.GetTransformFromRunUserSpaceToUserSpace(presContext);
     if (!m.Invert()) {
       return aPoint;
     }
-    gfxPoint pointInRunUserSpace = m.Transform(ThebesPoint(pointInUserSpace));
+    gfxPoint pointInRunUserSpace = m.TransformPoint(ThebesPoint(pointInUserSpace));
 
     if (Inside(runRect, pointInRunUserSpace)) {
       // The point was inside the rendered run's rect, so we choose it.
       dx = 0;
       dy = 0;
       pointInRun = pointInRunUserSpace;
       hit = run;
     } else if (nsLayoutUtils::PointIsCloserToRect(pointInRunUserSpace,
@@ -5512,18 +5517,18 @@ SVGTextFrame::TransformFramePointToTextC
   if (!hit.mFrame) {
     // We didn't find any rendered runs for the frame.
     return aPoint;
   }
 
   // Return the point in user units relative to the nsTextFrame,
   // but taking into account mFontSizeScaleFactor.
   gfxMatrix m = hit.GetTransformFromRunUserSpaceToFrameUserSpace(presContext);
-  m.Scale(mFontSizeScaleFactor, mFontSizeScaleFactor);
-  return ToPoint(m.Transform(pointInRun) / cssPxPerDevPx);
+  m.PreScale(mFontSizeScaleFactor, mFontSizeScaleFactor);
+  return ToPoint(m.TransformPoint(pointInRun) / cssPxPerDevPx);
 }
 
 /**
  * For each rendered run beneath aChildFrame, translate aRect from
  * aChildFrame to the run's text frame, transform it then into
  * the run's frame user space, intersect it with the run's
  * frame user space rect, then transform it up to user space.
  * The result is the union of all of these.
@@ -5559,18 +5564,19 @@ SVGTextFrame::TransformFrameRectFromText
     uint32_t flags = TextRenderedRun::eIncludeFill |
                      TextRenderedRun::eIncludeStroke;
 
     if (rectInFrameUserSpace.IntersectRect(rectInFrameUserSpace,
         run.GetFrameUserSpaceRect(presContext, flags).ToThebesRect())) {
       // Transform it up to user space of the <text>, also taking into
       // account the font size scale.
       gfxMatrix m = run.GetTransformFromRunUserSpaceToUserSpace(presContext);
-      m.Scale(mFontSizeScaleFactor, mFontSizeScaleFactor);
-      gfxRect rectInUserSpace = m.Transform(rectInFrameUserSpace);
+      m.PreScale(mFontSizeScaleFactor, mFontSizeScaleFactor);
+      gfxRect rectInUserSpace = rectInFrameUserSpace;
+      rectInUserSpace.TransformBy(m);
 
       // Union it into the result.
       result.UnionRect(result, rectInUserSpace);
     }
   }
 
   // Subtract the mRect offset from the result, as our user space for
   // this frame is relative to the top-left of mRect.
--- a/layout/svg/nsFilterInstance.cpp
+++ b/layout/svg/nsFilterInstance.cpp
@@ -553,35 +553,35 @@ nsFilterInstance::FrameSpaceToFilterSpac
 {
   nsIntRect rect = OutputFilterSpaceBounds();
   if (aRect) {
     if (aRect->IsEmpty()) {
       return nsIntRect();
     }
     gfxRect rectInCSSPx =
       nsLayoutUtils::RectToGfxRect(*aRect, nsPresContext::AppUnitsPerCSSPixel());
-    gfxRect rectInFilterSpace =
-      mFrameSpaceInCSSPxToFilterSpaceTransform.TransformBounds(rectInCSSPx);
+    gfxRect rectInFilterSpace = rectInCSSPx;
+    rectInFilterSpace.TransformBoundsBy(mFrameSpaceInCSSPxToFilterSpaceTransform);
     rectInFilterSpace.RoundOut();
     nsIntRect intRect;
     if (gfxUtils::GfxRectToIntRect(rectInFilterSpace, &intRect)) {
       rect = intRect;
     }
   }
   return rect;
 }
 
 nsRect
 nsFilterInstance::FilterSpaceToFrameSpace(const nsIntRect& aRect) const
 {
   if (aRect.IsEmpty()) {
     return nsRect();
   }
   gfxRect r(aRect.x, aRect.y, aRect.width, aRect.height);
-  r = mFilterSpaceToFrameSpaceInCSSPxTransform.TransformBounds(r);
+  r.TransformBoundsBy(mFilterSpaceToFrameSpaceInCSSPxTransform);
   // nsLayoutUtils::RoundGfxRectToAppRect rounds out.
   return nsLayoutUtils::RoundGfxRectToAppRect(r, nsPresContext::AppUnitsPerCSSPixel());
 }
 
 nsIntRegion
 nsFilterInstance::FrameSpaceToFilterSpace(const nsRegion* aRegion) const
 {
   if (!aRegion) {
--- a/layout/svg/nsSVGClipPathFrame.cpp
+++ b/layout/svg/nsSVGClipPathFrame.cpp
@@ -296,17 +296,17 @@ nsSVGClipPathFrame::PointIsInsideClipPat
   if (MOZ_UNLIKELY(!refChainGuard.Reference())) {
     return false; // Break reference chain
   }
 
   gfxMatrix matrix = GetClipPathTransform(aClippedFrame);
   if (!matrix.Invert()) {
     return false;
   }
-  gfxPoint point = matrix.Transform(aPoint);
+  gfxPoint point = matrix.TransformPoint(aPoint);
 
   // clipPath elements can themselves be clipped by a different clip path. In
   // that case the other clip path further clips away the element that is being
   // clipped by the original clipPath. If this clipPath is being clipped by a
   // different clip path we need to check if it prevents the original element
   // from recieving events at aPoint:
   nsSVGClipPathFrame *clipPathFrame =
     nsSVGEffects::GetEffectProperties(this).GetClipPathFrame();
@@ -321,17 +321,17 @@ nsSVGClipPathFrame::PointIsInsideClipPat
     if (SVGFrame) {
       gfxPoint pointForChild = point;
       gfxMatrix m = static_cast<nsSVGElement*>(kid->GetContent())->
         PrependLocalTransformsTo(gfxMatrix(), eUserSpaceToParent);
       if (!m.IsIdentity()) {
         if (!m.Invert()) {
           return false;
         }
-        pointForChild = m.Transform(point);
+        pointForChild = m.TransformPoint(point);
       }
       if (SVGFrame->GetFrameForPoint(pointForChild)) {
         return true;
       }
     }
   }
 
   return false;
--- a/layout/svg/nsSVGDisplayableFrame.h
+++ b/layout/svg/nsSVGDisplayableFrame.h
@@ -1,22 +1,22 @@
 /* -*- Mode: C++; tab-width: 2; 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 __NS_ISVGCHILDFRAME_H__
 #define __NS_ISVGCHILDFRAME_H__
 
+#include "gfxMatrix.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;
--- a/layout/svg/nsSVGForeignObjectFrame.cpp
+++ b/layout/svg/nsSVGForeignObjectFrame.cpp
@@ -229,17 +229,17 @@ nsSVGForeignObjectFrame::PaintSVG(gfxCon
                  "Display lists handle dirty rect intersection test");
     // Transform the dirty rect into app units in our userspace.
     gfxMatrix invmatrix = aTransform;
     DebugOnly<bool> ok = invmatrix.Invert();
     NS_ASSERTION(ok, "inverse of non-singular matrix should be non-singular");
 
     gfxRect transDirtyRect = gfxRect(aDirtyRect->x, aDirtyRect->y,
                                      aDirtyRect->width, aDirtyRect->height);
-    transDirtyRect = invmatrix.TransformBounds(transDirtyRect);
+    transDirtyRect.TransformBoundsBy(invmatrix);
 
     kidDirtyRect.IntersectRect(kidDirtyRect,
       nsLayoutUtils::RoundGfxRectToAppRect(transDirtyRect,
                        PresContext()->AppUnitsPerCSSPixel()));
 
     // XXX after bug 614732 is fixed, we will compare mRect with aDirtyRect,
     // not with kidDirtyRect. I.e.
     // int32_t appUnitsPerDevPx = PresContext()->AppUnitsPerDevPixel();
@@ -261,17 +261,17 @@ nsSVGForeignObjectFrame::PaintSVG(gfxCon
   }
 
   // SVG paints in CSS px, but normally frames paint in dev pixels. Here we
   // multiply a CSS-px-to-dev-pixel factor onto aTransform so our children
   // paint correctly.
   float cssPxPerDevPx = PresContext()->
     AppUnitsToFloatCSSPixels(PresContext()->AppUnitsPerDevPixel());
   gfxMatrix canvasTMForChildren = aTransform;
-  canvasTMForChildren.Scale(cssPxPerDevPx, cssPxPerDevPx);
+  canvasTMForChildren.PreScale(cssPxPerDevPx, cssPxPerDevPx);
 
   aContext.Multiply(canvasTMForChildren);
 
   using PaintFrameFlags = nsLayoutUtils::PaintFrameFlags;
   PaintFrameFlags flags = PaintFrameFlags::PAINT_IN_TRANSFORM;
   if (SVGAutoRenderState::IsPaintingToWindow(aContext.GetDrawTarget())) {
     flags |= PaintFrameFlags::PAINT_TO_WINDOW;
   }
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -389,17 +389,17 @@ public:
                      const nsIntRect* aDirtyRect,
                      imgDrawingParams& aImgParams) override
   {
     BasicLayerManager* basic = mLayerManager->AsBasicLayerManager();
     RefPtr<gfxContext> oldCtx = basic->GetTarget();
     basic->SetTarget(&aContext);
 
     gfxContextMatrixAutoSaveRestore autoSR(&aContext);
-    aContext.SetMatrix(aContext.CurrentMatrix().Translate(-mUserSpaceToFrameSpaceOffset));
+    aContext.SetMatrix(aContext.CurrentMatrix().PreTranslate(-mUserSpaceToFrameSpaceOffset));
 
     mLayerManager->EndTransaction(FrameLayerBuilder::DrawPaintedLayer, mBuilder);
     basic->SetTarget(oldCtx);
   }
 
 private:
   nsDisplayListBuilder* mBuilder;
   LayerManager* mLayerManager;
@@ -686,17 +686,17 @@ ComputeEffectOffset(nsIFrame* aFrame, co
  * origin of aParams.ctx to the user space of aFrame.
  */
 static EffectOffsets
 MoveContextOriginToUserSpace(nsIFrame* aFrame, const PaintFramesParams& aParams)
 {
   EffectOffsets offset = ComputeEffectOffset(aFrame, aParams);
 
   aParams.ctx.SetMatrix(
-    aParams.ctx.CurrentMatrix().Translate(offset.offsetToUserSpaceInDevPx));
+    aParams.ctx.CurrentMatrix().PreTranslate(offset.offsetToUserSpaceInDevPx));
 
   return offset;
 }
 
 bool
 nsSVGIntegrationUtils::IsMaskResourceReady(nsIFrame* aFrame)
 {
   nsIFrame* firstFrame =
--- a/layout/svg/nsSVGSwitchFrame.cpp
+++ b/layout/svg/nsSVGSwitchFrame.cpp
@@ -135,17 +135,17 @@ nsSVGSwitchFrame::GetFrameForPoint(const
       static_cast<const nsSVGElement*>(mContent)->
         PrependLocalTransformsTo(gfxMatrix(), eChildToUserSpace);
     m = static_cast<const nsSVGElement*>(kid->GetContent())->
           PrependLocalTransformsTo(m, eUserSpaceToParent);
     if (!m.IsIdentity()) {
       if (!m.Invert()) {
         return nullptr;
       }
-      point = m.Transform(point);
+      point = m.TransformPoint(point);
     }
     return svgFrame->GetFrameForPoint(point);
   }
 
   return nullptr;
 }
 
 void
--- a/layout/svg/nsSVGUtils.cpp
+++ b/layout/svg/nsSVGUtils.cpp
@@ -466,18 +466,19 @@ public:
 
     // aDirtyRect is in user-space pixels, we need to convert to
     // outer-SVG-frame-relative device pixels.
     if (aDirtyRect) {
       gfxMatrix userToDeviceSpace = aTransform;
       if (userToDeviceSpace.IsSingular()) {
         return;
       }
-      gfxRect dirtyBounds = userToDeviceSpace.TransformBounds(
-        gfxRect(aDirtyRect->x, aDirtyRect->y, aDirtyRect->width, aDirtyRect->height));
+      gfxRect dirtyBounds =
+        gfxRect(aDirtyRect->x, aDirtyRect->y, aDirtyRect->width, aDirtyRect->height);
+      dirtyBounds.TransformBoundsBy(userToDeviceSpace);
       dirtyBounds.RoundOut();
       if (gfxUtils::GfxRectToIntRect(dirtyBounds, &tmpDirtyRect)) {
         dirtyRect = &tmpDirtyRect;
       }
     }
 
     svgFrame->PaintSVG(aContext, nsSVGUtils::GetCSSPxToDevPxMatrix(aTarget),
                        aImgParams, dirtyRect);
@@ -838,19 +839,19 @@ nsSVGUtils::PaintFrameWithEffects(nsIFra
       // aDirtyRect is in outer-<svg> device pixels, but the filter code needs
       // it in frame space.
       gfxMatrix userToDeviceSpace = aTransform;
       if (userToDeviceSpace.IsSingular()) {
         return;
       }
       gfxMatrix deviceToUserSpace = userToDeviceSpace;
       deviceToUserSpace.Invert();
-      gfxRect dirtyBounds = deviceToUserSpace.TransformBounds(
-                              gfxRect(aDirtyRect->x, aDirtyRect->y,
-                                      aDirtyRect->width, aDirtyRect->height));
+      gfxRect dirtyBounds = gfxRect(aDirtyRect->x, aDirtyRect->y,
+                                    aDirtyRect->width, aDirtyRect->height);
+      dirtyBounds.TransformBoundsBy(deviceToUserSpace);
       tmpDirtyRegion =
         nsLayoutUtils::RoundGfxRectToAppRect(
           dirtyBounds, aFrame->PresContext()->AppUnitsPerCSSPixel()) -
         aFrame->GetPosition();
       dirtyRegion = &tmpDirtyRegion;
     }
 
     SVGPaintCallback paintCallback;
@@ -913,17 +914,17 @@ nsSVGUtils::HitTestChildren(nsSVGDisplay
   if (aFrame->GetContent()->IsSVGElement()) { // must check before cast
     gfxMatrix m = static_cast<const nsSVGElement*>(aFrame->GetContent())->
                     PrependLocalTransformsTo(gfxMatrix(),
                                              eChildToUserSpace);
     if (!m.IsIdentity()) {
       if (!m.Invert()) {
         return nullptr;
       }
-      point = m.Transform(point);
+      point = m.TransformPoint(point);
     }
   }
 
   // Traverse the list in reverse order, so that if we get a hit we know that's
   // the topmost frame that intersects the point; then we can just return it.
   nsIFrame* result = nullptr;
   for (nsIFrame* current = aFrame->PrincipalChildList().LastChild();
        current;
@@ -941,17 +942,17 @@ nsSVGUtils::HitTestChildren(nsSVGDisplay
       if (content->IsSVGElement()) { // must check before cast
         gfxMatrix m = static_cast<const nsSVGElement*>(content)->
                         PrependLocalTransformsTo(gfxMatrix(),
                                                  eUserSpaceToParent);
         if (!m.IsIdentity()) {
           if (!m.Invert()) {
             continue;
           }
-          p = m.Transform(p);
+          p = m.TransformPoint(p);
         }
       }
       result = SVGFrame->GetFrameForPoint(p);
       if (result)
         break;
     }
   }
 
@@ -963,18 +964,18 @@ nsSVGUtils::HitTestChildren(nsSVGDisplay
 
 nsRect
 nsSVGUtils::TransformFrameRectToOuterSVG(const nsRect& aRect,
                                          const gfxMatrix& aMatrix,
                                          nsPresContext* aPresContext)
 {
   gfxRect r(aRect.x, aRect.y, aRect.width, aRect.height);
   r.Scale(1.0 / nsPresContext::AppUnitsPerCSSPixel());
-  return nsLayoutUtils::RoundGfxRectToAppRect(
-    aMatrix.TransformBounds(r), aPresContext->AppUnitsPerDevPixel());
+  r.TransformBoundsBy(aMatrix);
+  return nsLayoutUtils::RoundGfxRectToAppRect(r, aPresContext->AppUnitsPerDevPixel());
 }
 
 IntSize
 nsSVGUtils::ConvertToSurfaceSize(const gfxSize& aSize,
                                  bool *aResultOverflows)
 {
   IntSize surfaceSize(ClampToInt(ceil(aSize.width)), ClampToInt(ceil(aSize.height)));
 
@@ -1148,35 +1149,35 @@ nsSVGUtils::GetBBox(nsIFrame* aFrame, ui
     y = fillBBox.y;
     width = fillBBox.width;
     height = fillBBox.height;
     bool hasClip = aFrame->StyleDisplay()->IsScrollableOverflow();
     if (hasClip) {
       clipRect =
         nsSVGUtils::GetClipRectForFrame(aFrame, x, y, width, height);
       if (aFrame->IsSVGForeignObjectFrame() || aFrame->IsSVGUseFrame()) {
-        clipRect = matrix.TransformBounds(clipRect);
+        clipRect.TransformBoundsBy(matrix);
       }
     }
     nsSVGEffects::EffectProperties effectProperties =
       nsSVGEffects::GetEffectProperties(aFrame);
     if (effectProperties.HasInvalidClipPath()) {
       bbox = gfxRect(0, 0, 0, 0);
     } else {
       nsSVGClipPathFrame *clipPathFrame =
         effectProperties.GetClipPathFrame();
       if (clipPathFrame) {
         SVGClipPathElement *clipContent =
           static_cast<SVGClipPathElement*>(clipPathFrame->GetContent());
         RefPtr<SVGAnimatedEnumeration> units = clipContent->ClipPathUnits();
         if (units->AnimVal() == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
-          matrix.Translate(gfxPoint(x, y));
-          matrix.Scale(width, height);
+          matrix.PreTranslate(gfxPoint(x, y));
+          matrix.PreScale(width, height);
         } else if (aFrame->IsSVGForeignObjectFrame()) {
-          matrix.Reset();
+          matrix = gfxMatrix();
         }
         bbox =
           clipPathFrame->GetBBoxForClipPathFrame(bbox, matrix).ToThebesRect();
       }
 
       if (hasClip) {
         bbox = bbox.Intersect(clipRect);
       }
@@ -1297,18 +1298,18 @@ gfxMatrix
 nsSVGUtils::AdjustMatrixForUnits(const gfxMatrix &aMatrix,
                                  nsSVGEnum *aUnits,
                                  nsIFrame *aFrame)
 {
   if (aFrame &&
       aUnits->GetAnimValue() == SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
     gfxRect bbox = GetBBox(aFrame);
     gfxMatrix tm = aMatrix;
-    tm.Translate(gfxPoint(bbox.X(), bbox.Y()));
-    tm.Scale(bbox.Width(), bbox.Height());
+    tm.PreTranslate(gfxPoint(bbox.X(), bbox.Y()));
+    tm.PreScale(bbox.Width(), bbox.Height());
     return tm;
   }
   return aMatrix;
 }
 
 nsIFrame*
 nsSVGUtils::GetFirstNonAAncestorFrame(nsIFrame* aStartFrame)
 {
@@ -1882,18 +1883,20 @@ nsSVGUtils::GetSVGGlyphExtents(Element* 
   return true;
 }
 
 nsRect
 nsSVGUtils::ToCanvasBounds(const gfxRect &aUserspaceRect,
                            const gfxMatrix &aToCanvas,
                            const nsPresContext *presContext)
 {
+  gfxRect userspaceRect = aUserspaceRect;
+  userspaceRect.TransformBoundsBy(aToCanvas);
   return nsLayoutUtils::RoundGfxRectToAppRect(
-                          aToCanvas.TransformBounds(aUserspaceRect),
+                          userspaceRect,
                           presContext->AppUnitsPerDevPixel());
 }
 
 gfxMatrix
 nsSVGUtils::GetCSSPxToDevPxMatrix(nsIFrame* aNonSVGFrame)
 {
   int32_t appUnitsPerDevPixel = aNonSVGFrame->PresContext()->AppUnitsPerDevPixel();
   float devPxPerCSSPx =
--- a/widget/android/fennec/ThumbnailHelper.h
+++ b/widget/android/fennec/ThumbnailHelper.h
@@ -154,17 +154,17 @@ class ThumbnailHelper final
         if (!dt || !dt->IsValid()) {
             return nullptr;
         }
 
         nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
         RefPtr<gfxContext> context = gfxContext::CreateOrNull(dt);
         MOZ_ASSERT(context); // checked the draw target above
 
-        context->SetMatrix(context->CurrentMatrix().Scale(
+        context->SetMatrix(context->CurrentMatrix().PreScale(
                 aZoomFactor * float(aThumbWidth) / aPageRect.width,
                 aZoomFactor * float(aThumbHeight) / aPageRect.height));
 
         const nsRect drawRect(
                 nsPresContext::CSSPixelsToAppUnits(aPageRect.x),
                 nsPresContext::CSSPixelsToAppUnits(aPageRect.y),
                 nsPresContext::CSSPixelsToAppUnits(aPageRect.width),
                 nsPresContext::CSSPixelsToAppUnits(aPageRect.height));
--- a/widget/windows/nsNativeThemeWin.cpp
+++ b/widget/windows/nsNativeThemeWin.cpp
@@ -1440,17 +1440,17 @@ nsNativeThemeWin::DrawWidgetBackground(g
     return NS_OK;
   }
 
   RefPtr<gfxContext> ctx = aContext;
   gfxContextMatrixAutoSaveRestore save(ctx);
 
   double themeScale = GetThemeDpiScaleFactor(aFrame);
   if (themeScale != 1.0) {
-    ctx->SetMatrix(ctx->CurrentMatrix().Scale(themeScale, themeScale));
+    ctx->SetMatrix(ctx->CurrentMatrix().PreScale(themeScale, themeScale));
   }
 
   gfxFloat p2a = gfxFloat(aFrame->PresContext()->AppUnitsPerDevPixel());
   RECT widgetRect;
   RECT clipRect;
   gfxRect tr(aRect.x, aRect.y, aRect.width, aRect.height),
           dr(aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);