Bug 1408310 - Part 2: Use CSS parser for DOMMatrix::SetMatrixValue. draft
authorBoris Chiou <boris.chiou@gmail.com>
Tue, 14 Nov 2017 17:41:46 +0800
changeset 700515 26057de8aebe46112d370557ce8880e89bef00e6
parent 700514 bcfa9a8f20607b14741b02a385535acb5e56d8de
child 700516 4f507a2c1ba72d4a16347ed576bbdd0b3074ccdf
push id89873
push userbmo:boris.chiou@gmail.com
push dateMon, 20 Nov 2017 09:33:40 +0000
bugs1408310
milestone59.0a1
Bug 1408310 - Part 2: Use CSS parser for DOMMatrix::SetMatrixValue. Now, we use the CSS parser, instead of SVG parser, so we also need to update the tests of DOMMatrix, i.e. we don't support unitless tranform list on CSS parser. MozReview-Commit-ID: 86F992rIa4J
dom/base/DOMMatrix.cpp
dom/base/WebKitCSSMatrix.cpp
dom/tests/mochitest/general/test_DOMMatrix.html
--- a/dom/base/DOMMatrix.cpp
+++ b/dom/base/DOMMatrix.cpp
@@ -1,25 +1,24 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/DOMMatrix.h"
+
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/DOMMatrixBinding.h"
+#include "mozilla/dom/DOMPoint.h"
 #include "mozilla/dom/DOMPointBinding.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/ToJSValue.h"
-
-#include "mozilla/dom/DOMPoint.h"
-#include "mozilla/dom/DOMMatrix.h"
-
-#include "SVGTransformListParser.h"
-#include "SVGTransform.h"
+#include "nsCSSParser.h"
+#include "nsStyleTransformMatrix.h"
 
 #include <math.h>
 
 namespace mozilla {
 namespace dom {
 
 static const double radPerDegree = 2.0 * M_PI / 360.0;
 
@@ -650,35 +649,66 @@ DOMMatrix::InvertSelf()
   }
 
   return this;
 }
 
 DOMMatrix*
 DOMMatrix::SetMatrixValue(const nsAString& aTransformList, ErrorResult& aRv)
 {
-  SVGTransformListParser parser(aTransformList);
-  if (!parser.Parse()) {
+  // An empty string is a no-op.
+  if (aTransformList.IsEmpty()) {
+    return this;
+  }
+
+  nsCSSValue value;
+  nsCSSParser parser;
+  bool parseSuccess = parser.ParseTransformProperty(aTransformList,
+                                                    true,
+                                                    value);
+  if (!parseSuccess) {
     aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
-  } else {
+    return nullptr;
+  }
+
+  // A value of "none" results in a 2D identity matrix.
+  if (value.GetUnit() == eCSSUnit_None) {
     mMatrix3D = nullptr;
     mMatrix2D = new gfx::Matrix();
-    gfxMatrix result;
-    const nsTArray<nsSVGTransform>& mItems = parser.GetTransformList();
+    return this;
+  }
 
-    for (uint32_t i = 0; i < mItems.Length(); ++i) {
-      result.PreMultiply(mItems[i].GetMatrix());
-    }
+  // A value other than a transform-list is a syntax error.
+  if (value.GetUnit() != eCSSUnit_SharedList) {
+    aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+    return nullptr;
+  }
 
-    SetA(result._11);
-    SetB(result._12);
-    SetC(result._21);
-    SetD(result._22);
-    SetE(result._31);
-    SetF(result._32);
+  RuleNodeCacheConditions dummy;
+  nsStyleTransformMatrix::TransformReferenceBox dummyBox;
+  bool contains3dTransform = false;
+  gfx::Matrix4x4 transform = nsStyleTransformMatrix::ReadTransforms(
+                               value.GetSharedListValue()->mHead,
+                               nullptr, nullptr, dummy, dummyBox,
+                               nsPresContext::AppUnitsPerCSSPixel(),
+                               &contains3dTransform);
+
+  if (!contains3dTransform) {
+    mMatrix3D = nullptr;
+    mMatrix2D = new gfx::Matrix();
+
+    SetA(transform._11);
+    SetB(transform._12);
+    SetC(transform._21);
+    SetD(transform._22);
+    SetE(transform._41);
+    SetF(transform._42);
+  } else {
+    mMatrix3D = new gfx::Matrix4x4(transform);
+    mMatrix2D = nullptr;
   }
 
   return this;
 }
 
 JSObject*
 DOMMatrix::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
--- a/dom/base/WebKitCSSMatrix.cpp
+++ b/dom/base/WebKitCSSMatrix.cpp
@@ -4,19 +4,17 @@
  * 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/WebKitCSSMatrix.h"
 
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/WebKitCSSMatrixBinding.h"
 #include "mozilla/Preferences.h"
-#include "nsCSSParser.h"
 #include "nsPresContext.h"
-#include "nsStyleTransformMatrix.h"
 #include "RuleNodeCacheConditions.h"
 
 namespace mozilla {
 namespace dom {
 
 static const double sRadPerDegree = 2.0 * M_PI / 360.0;
 
 bool
@@ -56,68 +54,17 @@ WebKitCSSMatrix::WrapObject(JSContext* a
 {
   return WebKitCSSMatrixBinding::Wrap(aCx, this, aGivenProto);
 }
 
 WebKitCSSMatrix*
 WebKitCSSMatrix::SetMatrixValue(const nsAString& aTransformList,
                                 ErrorResult& aRv)
 {
-  // An empty string is a no-op.
-  if (aTransformList.IsEmpty()) {
-    return this;
-  }
-
-  nsCSSValue value;
-  nsCSSParser parser;
-  bool parseSuccess = parser.ParseTransformProperty(aTransformList,
-                                                    true,
-                                                    value);
-  if (!parseSuccess) {
-    aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
-    return nullptr;
-  }
-
-  // A value of "none" results in a 2D identity matrix.
-  if (value.GetUnit() == eCSSUnit_None) {
-    mMatrix3D = nullptr;
-    mMatrix2D = new gfx::Matrix();
-    return this;
-  }
-
-  // A value other than a transform-list is a syntax error.
-  if (value.GetUnit() != eCSSUnit_SharedList) {
-    aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
-    return nullptr;
-  }
-
-  RuleNodeCacheConditions dummy;
-  nsStyleTransformMatrix::TransformReferenceBox dummyBox;
-  bool contains3dTransform = false;
-  gfx::Matrix4x4 transform = nsStyleTransformMatrix::ReadTransforms(
-                               value.GetSharedListValue()->mHead,
-                               nullptr, nullptr, dummy, dummyBox,
-                               nsPresContext::AppUnitsPerCSSPixel(),
-                               &contains3dTransform);
-
-  if (!contains3dTransform) {
-    mMatrix3D = nullptr;
-    mMatrix2D = new gfx::Matrix();
-
-    SetA(transform._11);
-    SetB(transform._12);
-    SetC(transform._21);
-    SetD(transform._22);
-    SetE(transform._41);
-    SetF(transform._42);
-  } else {
-    mMatrix3D = new gfx::Matrix4x4(transform);
-    mMatrix2D = nullptr;
-  }
-
+  DOMMatrix::SetMatrixValue(aTransformList, aRv);
   return this;
 }
 
 already_AddRefed<WebKitCSSMatrix>
 WebKitCSSMatrix::Multiply(const WebKitCSSMatrix& other) const
 {
   RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
   retval->MultiplySelf(other);
--- a/dom/tests/mochitest/general/test_DOMMatrix.html
+++ b/dom/tests/mochitest/general/test_DOMMatrix.html
@@ -691,23 +691,23 @@ function test3D()
   m2 = new Matrix3D();
   m2 = m2.multiply(m2.translate(2,3,4)).multiply(m2.scale(1.2, 2.3, 3.4));
   m2 = m2.inverse(m2).swap();
   ok(CompareMatrix(m2, m), "translate + scale in inverted 3d didn't match, expected: " + formatMatrix(m2.m) + ", got: " + formatMatrix(m));
 }
 
 function testParsing()
 {
-  var m = new DOMMatrix("translate(10, 20) scale(.5, 2) rotate(45)");
+  var m = new DOMMatrix("translate(10px, 20px) scale(.5, 2) rotate(45deg)");
   var m2 = new DOMMatrix();
   m2.translateSelf(10, 20).scaleNonUniformSelf(.5,2).rotateSelf(45);
   ok(CompareDOMMatrix(m2, m), "string parsing didn't match");
 
   m = new DOMMatrix();
-  m.setMatrixValue("translate(10, 20) scale(.5, 2) rotate(45)");
+  m.setMatrixValue("translate(10px, 20px) scale(.5, 2) rotate(45deg)");
   ok(CompareDOMMatrix(m2, m), "string parsing didn't match");
 }
 
 
 function testStringify() {
     var m = new DOMMatrix();
     var s = "" + m;
     ok(s == "matrix" + formatMatrix(m), "stringifier 1 produced wrong result: " + s);