Bug 1645747 - Change SVGPoint.matrixTransform to take a DOMMatrix2DInit parameter rather than SVGMatrix r=emilio
authorlongsonr <longsonr@gmail.com>
Mon, 15 Jun 2020 16:40:50 +0000
changeset 535758 4e980826c69795f6361c67eda6d02affd76c3031
parent 535757 24a7a83e8ac3f57d36c3f16a5c9b3e17ac7c4dda
child 535759 cad26877b1f56af9d246fa01e150de91f48be834
push id119055
push userlongsonr@gmail.com
push dateMon, 15 Jun 2020 19:51:19 +0000
treeherderautoland@4e980826c697 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1645747
milestone79.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 1645747 - Change SVGPoint.matrixTransform to take a DOMMatrix2DInit parameter rather than SVGMatrix r=emilio Differential Revision: https://phabricator.services.mozilla.com/D79681
dom/svg/DOMSVGPoint.cpp
dom/svg/DOMSVGPoint.h
dom/svg/SVGSVGElement.cpp
dom/svg/SVGSVGElement.h
dom/svg/SVGViewportElement.cpp
dom/svg/nsISVGPoint.h
dom/svg/test/test_transform.xhtml
dom/webidl/SVGPoint.webidl
--- a/dom/svg/DOMSVGPoint.cpp
+++ b/dom/svg/DOMSVGPoint.cpp
@@ -7,18 +7,18 @@
 #include "DOMSVGPoint.h"
 
 #include "DOMSVGPointList.h"
 #include "gfx2DGlue.h"
 #include "mozAutoDocUpdate.h"
 #include "nsCOMPtr.h"
 #include "nsError.h"
 #include "SVGPoint.h"
+#include "mozilla/dom/DOMMatrix.h"
 #include "mozilla/dom/SVGElement.h"
-#include "mozilla/dom/SVGMatrix.h"
 
 // See the architecture comment in DOMSVGPointList.h.
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace dom {
 
@@ -98,19 +98,26 @@ void DOMSVGPoint::SetY(float aY, ErrorRe
     AutoChangePointNotifier notifier(this);
     InternalItem().mY = aY;
     return;
   }
   mPt.mY = aY;
 }
 
 already_AddRefed<nsISVGPoint> DOMSVGPoint::MatrixTransform(
-    dom::SVGMatrix& matrix) {
-  float x = HasOwner() ? InternalItem().mX : mPt.mX;
-  float y = HasOwner() ? InternalItem().mY : mPt.mY;
-
-  Point pt = ToMatrix(matrix.GetMatrix()).TransformPoint(Point(x, y));
-  nsCOMPtr<nsISVGPoint> newPoint = new DOMSVGPoint(pt);
+    const DOMMatrix2DInit& aMatrix, ErrorResult& aRv) {
+  RefPtr<DOMMatrixReadOnly> matrix =
+      DOMMatrixReadOnly::FromMatrix(GetParentObject(), aMatrix, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+  const auto* matrix2D = matrix->GetInternal2D();
+  if (!matrix2D->IsFinite()) {
+    aRv.ThrowTypeError<MSG_NOT_FINITE>("MatrixTransform matrix");
+    return nullptr;
+  }
+  auto pt = matrix2D->TransformPoint(HasOwner() ? InternalItem() : mPt);
+  nsCOMPtr<nsISVGPoint> newPoint = new DOMSVGPoint(ToPoint(pt));
   return newPoint.forget();
 }
 
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/svg/DOMSVGPoint.h
+++ b/dom/svg/DOMSVGPoint.h
@@ -13,18 +13,18 @@
 #include "nsISVGPoint.h"
 #include "SVGPoint.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/FloatingPoint.h"
 
 namespace mozilla {
 
 namespace dom {
+struct DOMMatrix2DInit;
 class SVGElement;
-class SVGMatrix;
 
 /**
  * Class DOMSVGPoint
  *
  * This class creates the DOM objects that wrap internal SVGPoint objects that
  * are in an SVGPointList. It is also used to create the objects returned by
  * SVGSVGElement.createSVGPoint() and other functions that return DOM SVGPoint
  * objects.
@@ -57,35 +57,30 @@ class DOMSVGPoint final : public nsISVGP
   }
 
   explicit DOMSVGPoint(const DOMSVGPoint* aPt = nullptr) : nsISVGPoint() {
     if (aPt) {
       mPt = aPt->ToSVGPoint();
     }
   }
 
-  DOMSVGPoint(float aX, float aY) : nsISVGPoint() {
-    mPt.mX = aX;
-    mPt.mY = aY;
-  }
-
   explicit DOMSVGPoint(const Point& aPt) : nsISVGPoint() {
     mPt.mX = aPt.x;
     mPt.mY = aPt.y;
     NS_ASSERTION(IsFinite(mPt.mX) && IsFinite(mPt.mY),
                  "DOMSVGPoint coords are not finite");
   }
 
   // WebIDL
   virtual float X() override;
   virtual void SetX(float aX, ErrorResult& rv) override;
   virtual float Y() override;
   virtual void SetY(float aY, ErrorResult& rv) override;
   virtual already_AddRefed<nsISVGPoint> MatrixTransform(
-      SVGMatrix& matrix) override;
+      const DOMMatrix2DInit& aMatrix, ErrorResult& aRv) override;
   nsISupports* GetParentObject() override { return mList; }
 
   virtual DOMSVGPoint* Copy() override { return new DOMSVGPoint(this); }
 
  protected:
   SVGElement* Element() { return mList->Element(); }
 };
 
--- a/dom/svg/SVGSVGElement.cpp
+++ b/dom/svg/SVGSVGElement.cpp
@@ -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/. */
 
 #include "mozilla/dom/SVGSVGElement.h"
 
 #include "mozilla/ContentEvents.h"
 #include "mozilla/dom/BindContext.h"
+#include "mozilla/dom/DOMMatrix.h"
 #include "mozilla/dom/SVGSVGElementBinding.h"
 #include "mozilla/dom/SVGMatrix.h"
 #include "mozilla/dom/SVGRect.h"
 #include "mozilla/dom/SVGViewElement.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/PresShell.h"
 #include "mozilla/SMILAnimationController.h"
 #include "mozilla/SMILTimeContainer.h"
@@ -54,40 +55,47 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   // We have to qualify nsISVGPoint because NS_GET_IID looks for a class in the
   // global namespace
   NS_INTERFACE_MAP_ENTRY(nsISVGPoint)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 DOMSVGPoint* DOMSVGTranslatePoint::Copy() {
-  return new DOMSVGPoint(mPt.GetX(), mPt.GetY());
+  return new DOMSVGPoint(ToPoint(mPt));
 }
 
 nsISupports* DOMSVGTranslatePoint::GetParentObject() {
   return ToSupports(mElement);
 }
 
 void DOMSVGTranslatePoint::SetX(float aValue, ErrorResult& rv) {
   mElement->SetCurrentTranslate(aValue, mPt.GetY());
 }
 
 void DOMSVGTranslatePoint::SetY(float aValue, ErrorResult& rv) {
   mElement->SetCurrentTranslate(mPt.GetX(), aValue);
 }
 
 already_AddRefed<nsISVGPoint> DOMSVGTranslatePoint::MatrixTransform(
-    SVGMatrix& matrix) {
-  float a = matrix.A(), b = matrix.B(), c = matrix.C();
-  float d = matrix.D(), e = matrix.E(), f = matrix.F();
-  float x = mPt.GetX();
-  float y = mPt.GetY();
+    const DOMMatrix2DInit& aMatrix, ErrorResult& aRv) {
+  RefPtr<DOMMatrixReadOnly> matrix =
+      DOMMatrixReadOnly::FromMatrix(GetParentObject(), aMatrix, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  const auto* matrix2D = matrix->GetInternal2D();
+  if (!matrix2D->IsFinite()) {
+    aRv.ThrowTypeError<MSG_NOT_FINITE>("MatrixTransform matrix");
+    return nullptr;
+  }
 
   nsCOMPtr<nsISVGPoint> point =
-      new DOMSVGPoint(a * x + c * y + e, b * x + d * y + f);
+      new DOMSVGPoint(ToPoint(matrix2D->TransformPoint(mPt)));
   return point.forget();
 }
 
 JSObject* SVGSVGElement::WrapNode(JSContext* aCx,
                                   JS::Handle<JSObject*> aGivenProto) {
   return SVGSVGElement_Binding::Wrap(aCx, this, aGivenProto);
 }
 
@@ -257,17 +265,17 @@ already_AddRefed<DOMSVGLength> SVGSVGEle
   return do_AddRef(new DOMSVGLength());
 }
 
 already_AddRefed<DOMSVGAngle> SVGSVGElement::CreateSVGAngle() {
   return do_AddRef(new DOMSVGAngle(this));
 }
 
 already_AddRefed<nsISVGPoint> SVGSVGElement::CreateSVGPoint() {
-  return do_AddRef(new DOMSVGPoint(0, 0));
+  return do_AddRef(new DOMSVGPoint(Point(0, 0)));
 }
 
 already_AddRefed<SVGMatrix> SVGSVGElement::CreateSVGMatrix() {
   return do_AddRef(new SVGMatrix());
 }
 
 already_AddRefed<SVGRect> SVGSVGElement::CreateSVGRect() {
   return do_AddRef(new SVGRect(this));
--- a/dom/svg/SVGSVGElement.h
+++ b/dom/svg/SVGSVGElement.h
@@ -54,17 +54,17 @@ class DOMSVGTranslatePoint final : publi
   virtual DOMSVGPoint* Copy() override;
 
   // WebIDL
   virtual float X() override { return mPt.GetX(); }
   virtual float Y() override { return mPt.GetY(); }
   virtual void SetX(float aValue, ErrorResult& rv) override;
   virtual void SetY(float aValue, ErrorResult& rv) override;
   virtual already_AddRefed<nsISVGPoint> MatrixTransform(
-      SVGMatrix& matrix) override;
+      const DOMMatrix2DInit& aMatrix, ErrorResult& aRv) override;
 
   virtual nsISupports* GetParentObject() override;
 
   RefPtr<SVGSVGElement> mElement;
 
  private:
   ~DOMSVGTranslatePoint() = default;
 };
--- a/dom/svg/SVGViewportElement.cpp
+++ b/dom/svg/SVGViewportElement.cpp
@@ -11,17 +11,16 @@
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/ContentEvents.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/Likely.h"
 #include "mozilla/SMILTypes.h"
 #include "mozilla/SVGContentUtils.h"
 #include "mozilla/dom/Document.h"
 #include "mozilla/dom/SVGLengthBinding.h"
-#include "mozilla/dom/SVGMatrix.h"
 #include "mozilla/dom/SVGViewElement.h"
 
 #include "DOMSVGLength.h"
 #include "DOMSVGPoint.h"
 #include "nsContentUtils.h"
 #include "nsFrameSelection.h"
 #include "nsError.h"
 #include "nsGkAtoms.h"
--- a/dom/svg/nsISVGPoint.h
+++ b/dom/svg/nsISVGPoint.h
@@ -19,17 +19,17 @@
     }                                                \
   }
 
 #define MOZ_SVG_LIST_INDEX_BIT_COUNT 29
 
 namespace mozilla {
 
 namespace dom {
-class SVGMatrix;
+struct DOMMatrix2DInit;
 
 /**
  * Class nsISVGPoint
  *
  * This class creates the DOM objects that wrap internal SVGPoint objects.
  * An nsISVGPoint can be either a DOMSVGPoint or a DOMSVGTranslatePoint
  */
 class nsISVGPoint : public nsISupports, public nsWrapperCache {
@@ -120,17 +120,18 @@ class nsISVGPoint : public nsISupports, 
   bool IsReadonly() const { return mIsReadonly; }
   void SetReadonly(bool aReadonly) { mIsReadonly = aReadonly; }
 
   // WebIDL
   virtual float X() = 0;
   virtual void SetX(float aX, ErrorResult& rv) = 0;
   virtual float Y() = 0;
   virtual void SetY(float aY, ErrorResult& rv) = 0;
-  virtual already_AddRefed<nsISVGPoint> MatrixTransform(SVGMatrix& matrix) = 0;
+  virtual already_AddRefed<nsISVGPoint> MatrixTransform(
+      const DOMMatrix2DInit& aMatrix, ErrorResult& aRv) = 0;
   virtual JSObject* WrapObject(JSContext* cx,
                                JS::Handle<JSObject*> aGivenProto) override {
     return SVGPoint_Binding::Wrap(cx, this, aGivenProto);
   }
 
   virtual nsISupports* GetParentObject() = 0;
 
  protected:
--- a/dom/svg/test/test_transform.xhtml
+++ b/dom/svg/test/test_transform.xhtml
@@ -125,20 +125,43 @@ function run() {
 
   // check transform object identity after manipulation
   ok(t === g.transform.baseVal.getItem(0),
      "Got different transform objects after manipulation");
   ok(t.matrix === m,
      "Got different matrix objects after manipulation");
 
   testCreateTransform();
+  testMatrixTransform();
 
   SimpleTest.finish();
 }
 
+function testMatrixTransform() {
+  let svg = $("svg");
+  const epsilon = 1 / 65536;
+
+  let point = svg.createSVGPoint();
+  point.x = 5;
+  point.y = 4;
+  let matrix = createMatrix(2, 0, 0, 2, 10, 10);
+  let result = point.matrixTransform(matrix);
+  let expected = DOMPoint.fromPoint(point).matrixTransform(matrix);
+  isfuzzy(result.x, expected.x, epsilon, "matrix transformation x");
+  isfuzzy(result.y, expected.y, epsilon, "matrix transformation y");
+
+  svg.currentTranslate.x = 5;
+  svg.currentTranslate.y = 4;
+  result = svg.currentTranslate.matrixTransform(matrix);
+  isfuzzy(result.x, expected.x, epsilon, "svg matrix transformation x");
+  isfuzzy(result.y, expected.y, epsilon, "svg matrix transformation y");
+  svg.currentTranslate.x = 0;
+  svg.currentTranslate.y = 0;
+}
+
 function testCreateTransform() {
   let svg = $("svg");
   let t = svg.createSVGTransform();
   ok(t != svg.createSVGTransform(),
      "Got identical objects when creating new transform");
   checkTransform(t, SVGTransform.SVG_TRANSFORM_MATRIX,
                  createMatrix(1, 0, 0, 1, 0, 0), 0, "createSVGTransform");
 
--- a/dom/webidl/SVGPoint.webidl
+++ b/dom/webidl/SVGPoint.webidl
@@ -13,12 +13,12 @@
 [Exposed=Window]
 interface SVGPoint {
 
   [SetterThrows]
   attribute float x;
   [SetterThrows]
   attribute float y;
 
-  [NewObject]
-  SVGPoint matrixTransform(SVGMatrix matrix);
+  [NewObject, Throws]
+  SVGPoint matrixTransform(optional DOMMatrix2DInit matrix = {});
 };