summaryrefslogtreecommitdiff
path: root/dom/base/WebKitCSSMatrix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/base/WebKitCSSMatrix.cpp')
-rw-r--r--dom/base/WebKitCSSMatrix.cpp262
1 files changed, 262 insertions, 0 deletions
diff --git a/dom/base/WebKitCSSMatrix.cpp b/dom/base/WebKitCSSMatrix.cpp
new file mode 100644
index 0000000000..2cb6d6bf09
--- /dev/null
+++ b/dom/base/WebKitCSSMatrix.cpp
@@ -0,0 +1,262 @@
+/* -*- 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/WebKitCSSMatrix.h"
+
+#include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/WebKitCSSMatrixBinding.h"
+#include "mozilla/Preferences.h"
+#include "nsCSSParser.h"
+#include "nsStyleTransformMatrix.h"
+#include "RuleNodeCacheConditions.h"
+
+namespace mozilla {
+namespace dom {
+
+static const double sRadPerDegree = 2.0 * M_PI / 360.0;
+
+bool
+WebKitCSSMatrix::FeatureEnabled(JSContext* aCx, JSObject* aObj)
+{
+ return Preferences::GetBool("layout.css.DOMMatrix.enabled", false) &&
+ Preferences::GetBool("layout.css.prefixes.webkit", false);
+}
+
+already_AddRefed<WebKitCSSMatrix>
+WebKitCSSMatrix::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
+{
+ RefPtr<WebKitCSSMatrix> obj = new WebKitCSSMatrix(aGlobal.GetAsSupports());
+ return obj.forget();
+}
+
+already_AddRefed<WebKitCSSMatrix>
+WebKitCSSMatrix::Constructor(const GlobalObject& aGlobal,
+ const nsAString& aTransformList, ErrorResult& aRv)
+{
+ RefPtr<WebKitCSSMatrix> obj = new WebKitCSSMatrix(aGlobal.GetAsSupports());
+ obj = obj->SetMatrixValue(aTransformList, aRv);
+ return obj.forget();
+}
+
+already_AddRefed<WebKitCSSMatrix>
+WebKitCSSMatrix::Constructor(const GlobalObject& aGlobal,
+ const DOMMatrixReadOnly& aOther, ErrorResult& aRv)
+{
+ RefPtr<WebKitCSSMatrix> obj = new WebKitCSSMatrix(aGlobal.GetAsSupports(),
+ aOther);
+ return obj.forget();
+}
+
+JSObject*
+WebKitCSSMatrix::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+ 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;
+ }
+
+ return this;
+}
+
+already_AddRefed<WebKitCSSMatrix>
+WebKitCSSMatrix::Multiply(const WebKitCSSMatrix& other) const
+{
+ RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
+ retval->MultiplySelf(other);
+
+ return retval.forget();
+}
+
+already_AddRefed<WebKitCSSMatrix>
+WebKitCSSMatrix::Inverse(ErrorResult& aRv) const
+{
+ RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
+ retval->InvertSelfThrow(aRv);
+ if (NS_WARN_IF(aRv.Failed())) {
+ return nullptr;
+ }
+
+ return retval.forget();
+}
+
+WebKitCSSMatrix*
+WebKitCSSMatrix::InvertSelfThrow(ErrorResult& aRv)
+{
+ if (mMatrix3D) {
+ if (!mMatrix3D->Invert()) {
+ aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+ return nullptr;
+ }
+ } else if (!mMatrix2D->Invert()) {
+ aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+ return nullptr;
+ }
+
+ return this;
+}
+
+already_AddRefed<WebKitCSSMatrix>
+WebKitCSSMatrix::Translate(double aTx,
+ double aTy,
+ double aTz) const
+{
+ RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
+ retval->TranslateSelf(aTx, aTy, aTz);
+
+ return retval.forget();
+}
+
+already_AddRefed<WebKitCSSMatrix>
+WebKitCSSMatrix::Scale(double aScaleX,
+ const Optional<double>& aScaleY,
+ double aScaleZ) const
+{
+ double scaleX = aScaleX;
+ double scaleY = aScaleY.WasPassed() ? aScaleY.Value() : scaleX;
+ double scaleZ = aScaleZ;
+
+ RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
+ retval->ScaleNonUniformSelf(scaleX, scaleY, scaleZ);
+
+ return retval.forget();
+}
+
+already_AddRefed<WebKitCSSMatrix>
+WebKitCSSMatrix::Rotate(double aRotX,
+ const Optional<double>& aRotY,
+ const Optional<double>& aRotZ) const
+{
+ double rotX = aRotX;
+ double rotY;
+ double rotZ;
+
+ if (!aRotY.WasPassed() && !aRotZ.WasPassed()) {
+ rotZ = rotX;
+ rotX = 0;
+ rotY = 0;
+ } else {
+ rotY = aRotY.WasPassed() ? aRotY.Value() : 0;
+ rotZ = aRotZ.WasPassed() ? aRotZ.Value() : 0;
+ }
+
+ RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
+ retval->Rotate3dSelf(rotX, rotY, rotZ);
+
+ return retval.forget();
+}
+
+WebKitCSSMatrix*
+WebKitCSSMatrix::Rotate3dSelf(double aRotX,
+ double aRotY,
+ double aRotZ)
+{
+ if (aRotX != 0 || aRotY != 0) {
+ Ensure3DMatrix();
+ }
+
+ if (mMatrix3D) {
+ if (fmod(aRotZ, 360) != 0) {
+ mMatrix3D->RotateZ(aRotZ * sRadPerDegree);
+ }
+ if (fmod(aRotY, 360) != 0) {
+ mMatrix3D->RotateY(aRotY * sRadPerDegree);
+ }
+ if (fmod(aRotX, 360) != 0) {
+ mMatrix3D->RotateX(aRotX * sRadPerDegree);
+ }
+ } else if (fmod(aRotZ, 360) != 0) {
+ mMatrix2D->PreRotate(aRotZ * sRadPerDegree);
+ }
+
+ return this;
+}
+
+already_AddRefed<WebKitCSSMatrix>
+WebKitCSSMatrix::RotateAxisAngle(double aX,
+ double aY,
+ double aZ,
+ double aAngle) const
+{
+ RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
+ retval->RotateAxisAngleSelf(aX, aY, aZ, aAngle);
+
+ return retval.forget();
+}
+
+already_AddRefed<WebKitCSSMatrix>
+WebKitCSSMatrix::SkewX(double aSx) const
+{
+ RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
+ retval->SkewXSelf(aSx);
+
+ return retval.forget();
+}
+
+already_AddRefed<WebKitCSSMatrix>
+WebKitCSSMatrix::SkewY(double aSy) const
+{
+ RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
+ retval->SkewYSelf(aSy);
+
+ return retval.forget();
+}
+
+} // namespace dom
+} // namespace mozilla