diff options
Diffstat (limited to 'dom/base/WebKitCSSMatrix.cpp')
-rw-r--r-- | dom/base/WebKitCSSMatrix.cpp | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/dom/base/WebKitCSSMatrix.cpp b/dom/base/WebKitCSSMatrix.cpp new file mode 100644 index 000000000..2cb6d6bf0 --- /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 |