diff options
author | Job Bautista <jobbautista9@aol.com> | 2023-05-12 15:42:46 +0800 |
---|---|---|
committer | Job Bautista <jobbautista9@aol.com> | 2023-05-12 16:26:06 +0800 |
commit | b2889d844f8c2f826100588b23b741f73e96cbbc (patch) | |
tree | e14cb0225f044641194ce5f09839af9aba2a434e /dom/base | |
parent | fdfe7a8245eb33db252f2a9a3474ac931f15a7d8 (diff) | |
download | uxp-b2889d844f8c2f826100588b23b741f73e96cbbc.tar.gz |
Issue #2241 - Part 6: Implement DOMMatrix.fromMatrix.
Also fixes .multiply() to use DOMMatrixInit.
Backported from Mozilla bug 1560462.
Diffstat (limited to 'dom/base')
-rw-r--r-- | dom/base/DOMMatrix.cpp | 177 | ||||
-rw-r--r-- | dom/base/DOMMatrix.h | 23 | ||||
-rw-r--r-- | dom/base/WebKitCSSMatrix.cpp | 4 | ||||
-rw-r--r-- | dom/base/WebKitCSSMatrix.h | 3 |
4 files changed, 187 insertions, 20 deletions
diff --git a/dom/base/DOMMatrix.cpp b/dom/base/DOMMatrix.cpp index 0045e17d84..09c186e77e 100644 --- a/dom/base/DOMMatrix.cpp +++ b/dom/base/DOMMatrix.cpp @@ -17,6 +17,8 @@ #include <math.h> +#include "js/Equality.h" // JS::SameValueZero + namespace mozilla { namespace dom { @@ -37,6 +39,130 @@ DOMMatrixReadOnly::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) return DOMMatrixReadOnlyBinding::Wrap(aCx, this, aGivenProto); } +// https://drafts.fxtf.org/geometry/#matrix-validate-and-fixup-2d +static bool +ValidateAndFixupMatrix2DInit(DOMMatrix2DInit& aMatrixInit, ErrorResult& aRv) +{ +#define ValidateAliases(field, alias, fieldName, aliasName) \ + if ((field).WasPassed() && (alias).WasPassed() && \ + !JS::SameValueZero((field).Value(), (alias).Value())) { \ + aRv.ThrowTypeError<MSG_MATRIX_INIT_CONFLICTING_VALUE>((fieldName), \ + (aliasName)); \ + return false; \ + } +#define SetFromAliasOrDefault(field, alias, defaultValue) \ + if (!(field).WasPassed()) { \ + if ((alias).WasPassed()) { \ + (field).Construct((alias).Value()); \ + } else { \ + (field).Construct(defaultValue); \ + } \ + } +#define ValidateAndSet(field, alias, fieldName, aliasName, defaultValue) \ + ValidateAliases((field), (alias), NS_LITERAL_STRING(fieldName), \ + NS_LITERAL_STRING(aliasName)); \ + SetFromAliasOrDefault((field), (alias), (defaultValue)); + + ValidateAndSet(aMatrixInit.mM11, aMatrixInit.mA, "m11", "a", 1); + ValidateAndSet(aMatrixInit.mM12, aMatrixInit.mB, "m12", "b", 0); + ValidateAndSet(aMatrixInit.mM21, aMatrixInit.mC, "m21", "c", 0); + ValidateAndSet(aMatrixInit.mM22, aMatrixInit.mD, "m22", "d", 1); + ValidateAndSet(aMatrixInit.mM41, aMatrixInit.mE, "m41", "e", 0); + ValidateAndSet(aMatrixInit.mM42, aMatrixInit.mF, "m42", "f", 0); + + return true; + +#undef ValidateAliases +#undef SetFromAliasOrDefault +#undef ValidateAndSet +} + +// https://drafts.fxtf.org/geometry/#matrix-validate-and-fixup +static bool +ValidateAndFixupMatrixInit(DOMMatrixInit& aMatrixInit, ErrorResult& aRv) +{ +#define Check3DField(field, fieldName, defaultValue) \ + if ((field) != (defaultValue)) { \ + if (!aMatrixInit.mIs2D.WasPassed()) { \ + aMatrixInit.mIs2D.Construct(false); \ + return true; \ + } \ + if (aMatrixInit.mIs2D.Value()) { \ + aRv.ThrowTypeError<MSG_MATRIX_INIT_EXCEEDS_2D>( \ + NS_LITERAL_STRING(fieldName)); \ + return false; \ + } \ + } + + if (!ValidateAndFixupMatrix2DInit(aMatrixInit, aRv)) { + return false; + } + + Check3DField(aMatrixInit.mM13, "m13", 0); + Check3DField(aMatrixInit.mM14, "m14", 0); + Check3DField(aMatrixInit.mM23, "m23", 0); + Check3DField(aMatrixInit.mM24, "m24", 0); + Check3DField(aMatrixInit.mM31, "m31", 0); + Check3DField(aMatrixInit.mM32, "m32", 0); + Check3DField(aMatrixInit.mM34, "m34", 0); + Check3DField(aMatrixInit.mM43, "m43", 0); + Check3DField(aMatrixInit.mM33, "m33", 1); + Check3DField(aMatrixInit.mM44, "m44", 1); + + if (!aMatrixInit.mIs2D.WasPassed()) { + aMatrixInit.mIs2D.Construct(true); + } + return true; + +#undef Check3DField +} + +void +DOMMatrixReadOnly::SetDataFromMatrixInit(DOMMatrixInit& aMatrixInit) +{ + const bool is2D = aMatrixInit.mIs2D.Value(); + MOZ_ASSERT(is2D == Is2D()); + if (is2D) { + mMatrix2D->_11 = aMatrixInit.mM11.Value(); + mMatrix2D->_12 = aMatrixInit.mM12.Value(); + mMatrix2D->_21 = aMatrixInit.mM21.Value(); + mMatrix2D->_22 = aMatrixInit.mM22.Value(); + mMatrix2D->_31 = aMatrixInit.mM41.Value(); + mMatrix2D->_32 = aMatrixInit.mM42.Value(); + } else { + mMatrix3D->_11 = aMatrixInit.mM11.Value(); + mMatrix3D->_12 = aMatrixInit.mM12.Value(); + mMatrix3D->_13 = aMatrixInit.mM13; + mMatrix3D->_14 = aMatrixInit.mM14; + mMatrix3D->_21 = aMatrixInit.mM21.Value(); + mMatrix3D->_22 = aMatrixInit.mM22.Value(); + mMatrix3D->_23 = aMatrixInit.mM23; + mMatrix3D->_24 = aMatrixInit.mM24; + mMatrix3D->_31 = aMatrixInit.mM31; + mMatrix3D->_32 = aMatrixInit.mM32; + mMatrix3D->_33 = aMatrixInit.mM33; + mMatrix3D->_34 = aMatrixInit.mM34; + mMatrix3D->_41 = aMatrixInit.mM41.Value(); + mMatrix3D->_42 = aMatrixInit.mM42.Value(); + mMatrix3D->_43 = aMatrixInit.mM43; + mMatrix3D->_44 = aMatrixInit.mM44; + } +} + +already_AddRefed<DOMMatrixReadOnly> +DOMMatrixReadOnly::FromMatrix(const GlobalObject& aGlobal, const DOMMatrixInit& aMatrixInit, ErrorResult& aRv) +{ + DOMMatrixInit matrixInit(aMatrixInit); + if (!ValidateAndFixupMatrixInit(matrixInit, aRv)) { + return nullptr; + }; + + RefPtr<DOMMatrixReadOnly> rval = + new DOMMatrixReadOnly(aGlobal.GetAsSupports(), matrixInit.mIs2D.Value()); + rval->SetDataFromMatrixInit(matrixInit); + return rval.forget(); +} + already_AddRefed<DOMMatrixReadOnly> DOMMatrixReadOnly::Constructor( const GlobalObject& aGlobal, @@ -182,10 +308,10 @@ DOMMatrixReadOnly::SkewY(double aSy) const } already_AddRefed<DOMMatrix> -DOMMatrixReadOnly::Multiply(const DOMMatrix& other) const +DOMMatrixReadOnly::Multiply(const DOMMatrixInit& other, ErrorResult& aRv) const { RefPtr<DOMMatrix> retval = new DOMMatrix(mParent, *this); - retval->MultiplySelf(other); + retval->MultiplySelf(other, aRv); return retval.forget(); } @@ -427,6 +553,27 @@ DOMMatrixReadOnly::ReadStructuredCloneElements(JSStructuredCloneReader* aReader, } already_AddRefed<DOMMatrix> +DOMMatrix::FromMatrix(nsISupports* aParent, const DOMMatrixInit& aMatrixInit, ErrorResult& aRv) +{ + DOMMatrixInit matrixInit(aMatrixInit); + if (!ValidateAndFixupMatrixInit(matrixInit, aRv)) { + return nullptr; + }; + + RefPtr<DOMMatrix> matrix = new DOMMatrix(aParent, matrixInit.mIs2D.Value()); + matrix->SetDataFromMatrixInit(matrixInit); + return matrix.forget(); +} + +already_AddRefed<DOMMatrix> +DOMMatrix::FromMatrix(const GlobalObject& aGlobal, const DOMMatrixInit& aMatrixInit, ErrorResult& aRv) +{ + RefPtr<DOMMatrix> matrix = + FromMatrix(aGlobal.GetAsSupports(), aMatrixInit, aRv); + return matrix.forget(); +} + +already_AddRefed<DOMMatrix> DOMMatrix::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv) { RefPtr<DOMMatrix> obj = new DOMMatrix(aGlobal.GetAsSupports()); @@ -546,42 +693,44 @@ DOMMatrixReadOnly::Ensure3DMatrix() } DOMMatrix* -DOMMatrix::MultiplySelf(const DOMMatrix& aOther) +DOMMatrix::MultiplySelf(const DOMMatrixInit& aOtherInit, ErrorResult& aRv) { - if (aOther.Identity()) { + RefPtr<DOMMatrix> other = FromMatrix(mParent, aOtherInit, aRv); + if (other->Identity()) { return this; } - if (aOther.Is2D()) { + if (other->Is2D()) { if (mMatrix3D) { - *mMatrix3D = gfx::Matrix4x4::From2D(*aOther.mMatrix2D) * *mMatrix3D; + *mMatrix3D = gfx::Matrix4x4::From2D(*other->mMatrix2D) * *mMatrix3D; } else { - *mMatrix2D = *aOther.mMatrix2D * *mMatrix2D; + *mMatrix2D = *other->mMatrix2D * *mMatrix2D; } } else { Ensure3DMatrix(); - *mMatrix3D = *aOther.mMatrix3D * *mMatrix3D; + *mMatrix3D = *other->mMatrix3D * *mMatrix3D; } return this; } DOMMatrix* -DOMMatrix::PreMultiplySelf(const DOMMatrix& aOther) +DOMMatrix::PreMultiplySelf(const DOMMatrixInit& aOtherInit, ErrorResult& aRv) { - if (aOther.Identity()) { + RefPtr<DOMMatrix> other = FromMatrix(mParent, aOtherInit, aRv); + if (other->Identity()) { return this; } - if (aOther.Is2D()) { + if (other->Is2D()) { if (mMatrix3D) { - *mMatrix3D = *mMatrix3D * gfx::Matrix4x4::From2D(*aOther.mMatrix2D); + *mMatrix3D = *mMatrix3D * gfx::Matrix4x4::From2D(*other->mMatrix2D); } else { - *mMatrix2D = *mMatrix2D * *aOther.mMatrix2D; + *mMatrix2D = *mMatrix2D * *other->mMatrix2D; } } else { Ensure3DMatrix(); - *mMatrix3D = *mMatrix3D * *aOther.mMatrix3D; + *mMatrix3D = *mMatrix3D * *other->mMatrix3D; } return this; diff --git a/dom/base/DOMMatrix.h b/dom/base/DOMMatrix.h index fe1325c594..9bbdef688f 100644 --- a/dom/base/DOMMatrix.h +++ b/dom/base/DOMMatrix.h @@ -25,6 +25,7 @@ class DOMMatrix; class DOMPoint; class StringOrUnrestrictedDoubleSequence; struct DOMPointInit; +struct DOMMatrixInit; class DOMMatrixReadOnly : public nsWrapperCache { @@ -57,6 +58,9 @@ public: virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override; static already_AddRefed<DOMMatrixReadOnly> + FromMatrix(const GlobalObject& aGlobal, const DOMMatrixInit& aMatrixInit, ErrorResult& aRv); + + static already_AddRefed<DOMMatrixReadOnly> Constructor(const GlobalObject& aGlobal, const Optional<StringOrUnrestrictedDoubleSequence>& aArg, ErrorResult& aRv); static already_AddRefed<DOMMatrixReadOnly> @@ -180,7 +184,8 @@ public: double aAngle) const; already_AddRefed<DOMMatrix> SkewX(double aSx) const; already_AddRefed<DOMMatrix> SkewY(double aSy) const; - already_AddRefed<DOMMatrix> Multiply(const DOMMatrix& aOther) const; + already_AddRefed<DOMMatrix> Multiply(const DOMMatrixInit& aOther, + ErrorResult& aRv) const; already_AddRefed<DOMMatrix> FlipX() const; already_AddRefed<DOMMatrix> FlipY() const; already_AddRefed<DOMMatrix> Inverse() const; @@ -204,6 +209,13 @@ protected: virtual ~DOMMatrixReadOnly() {} + /** + * Sets data from a fully validated and fixed-up matrix init, + * where all of its members are properly defined. + * The init dictionary's dimension must match the matrix one. + */ + void SetDataFromMatrixInit(DOMMatrixInit& aMatrixInit); + DOMMatrixReadOnly* SetMatrixValue(const nsAString& aTransformList, ErrorResult& aRv); void Ensure3DMatrix(); @@ -237,6 +249,11 @@ public: {} static already_AddRefed<DOMMatrix> + FromMatrix(nsISupports* aParent, const DOMMatrixInit& aMatrixInit, ErrorResult& aRv); + static already_AddRefed<DOMMatrix> + FromMatrix(const GlobalObject& aGlobal, const DOMMatrixInit& aMatrixInit, ErrorResult& aRv); + + static already_AddRefed<DOMMatrix> Constructor(const GlobalObject& aGlobal, ErrorResult& aRv); static already_AddRefed<DOMMatrix> Constructor(const GlobalObject& aGlobal, const nsAString& aTransformList, ErrorResult& aRv); @@ -254,8 +271,8 @@ public: virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; - DOMMatrix* MultiplySelf(const DOMMatrix& aOther); - DOMMatrix* PreMultiplySelf(const DOMMatrix& aOther); + DOMMatrix* MultiplySelf(const DOMMatrixInit& aOther, ErrorResult& aRv); + DOMMatrix* PreMultiplySelf(const DOMMatrixInit& aOther, ErrorResult& aRv); DOMMatrix* TranslateSelf(double aTx, double aTy, double aTz = 0); diff --git a/dom/base/WebKitCSSMatrix.cpp b/dom/base/WebKitCSSMatrix.cpp index fe26b74554..003fdfea30 100644 --- a/dom/base/WebKitCSSMatrix.cpp +++ b/dom/base/WebKitCSSMatrix.cpp @@ -115,10 +115,10 @@ WebKitCSSMatrix::SetMatrixValue(const nsAString& aTransformList, } already_AddRefed<WebKitCSSMatrix> -WebKitCSSMatrix::Multiply(const WebKitCSSMatrix& other) const +WebKitCSSMatrix::Multiply(const DOMMatrixInit& aOtherInit, ErrorResult& aRv) const { RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this); - retval->MultiplySelf(other); + retval->MultiplySelf(aOtherInit, aRv); return retval.forget(); } diff --git a/dom/base/WebKitCSSMatrix.h b/dom/base/WebKitCSSMatrix.h index e50c617260..590548b767 100644 --- a/dom/base/WebKitCSSMatrix.h +++ b/dom/base/WebKitCSSMatrix.h @@ -40,7 +40,8 @@ public: WebKitCSSMatrix* SetMatrixValue(const nsAString& aTransformList, ErrorResult& aRv); - already_AddRefed<WebKitCSSMatrix> Multiply(const WebKitCSSMatrix& aOther) const; + already_AddRefed<WebKitCSSMatrix> Multiply(const DOMMatrixInit& aOtherInit, + ErrorResult& aRv) const; already_AddRefed<WebKitCSSMatrix> Inverse(ErrorResult& aRv) const; already_AddRefed<WebKitCSSMatrix> Translate(double aTx, double aTy, |