1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef MOZILLA_DOM_DOMMATRIX_H_ 8 #define MOZILLA_DOM_DOMMATRIX_H_ 9 10 #include <cstring> 11 #include <utility> 12 #include "js/RootingAPI.h" 13 #include "mozilla/AlreadyAddRefed.h" 14 #include "mozilla/Assertions.h" 15 #include "mozilla/UniquePtr.h" 16 #include "mozilla/dom/TypedArray.h" 17 #include "mozilla/gfx/Matrix.h" 18 #include "nsCOMPtr.h" 19 #include "nsCycleCollectionParticipant.h" 20 #include "nsISupports.h" 21 #include "nsStringFwd.h" 22 #include "nsWrapperCache.h" 23 24 class JSObject; 25 class nsIGlobalObject; 26 struct JSContext; 27 struct JSStructuredCloneReader; 28 struct JSStructuredCloneWriter; 29 30 namespace mozilla { 31 class ErrorResult; 32 33 namespace dom { 34 35 class GlobalObject; 36 class DOMMatrix; 37 class DOMPoint; 38 template <typename T> 39 class Optional; 40 class UTF8StringOrUnrestrictedDoubleSequenceOrDOMMatrixReadOnly; 41 struct DOMPointInit; 42 struct DOMMatrixInit; 43 struct DOMMatrix2DInit; 44 45 class DOMMatrixReadOnly : public nsWrapperCache { 46 public: DOMMatrixReadOnly(nsISupports * aParent)47 explicit DOMMatrixReadOnly(nsISupports* aParent) 48 : mParent(aParent), mMatrix2D(new gfx::MatrixDouble()) {} 49 DOMMatrixReadOnly(nsISupports * aParent,const DOMMatrixReadOnly & other)50 DOMMatrixReadOnly(nsISupports* aParent, const DOMMatrixReadOnly& other) 51 : mParent(aParent) { 52 if (other.mMatrix2D) { 53 mMatrix2D = MakeUnique<gfx::MatrixDouble>(*other.mMatrix2D); 54 } else { 55 mMatrix3D = MakeUnique<gfx::Matrix4x4Double>(*other.mMatrix3D); 56 } 57 } 58 DOMMatrixReadOnly(nsISupports * aParent,const gfx::Matrix4x4 & aMatrix)59 DOMMatrixReadOnly(nsISupports* aParent, const gfx::Matrix4x4& aMatrix) 60 : mParent(aParent) { 61 mMatrix3D = MakeUnique<gfx::Matrix4x4Double>(aMatrix); 62 } 63 DOMMatrixReadOnly(nsISupports * aParent,const gfx::Matrix & aMatrix)64 DOMMatrixReadOnly(nsISupports* aParent, const gfx::Matrix& aMatrix) 65 : mParent(aParent) { 66 mMatrix2D = MakeUnique<gfx::MatrixDouble>(aMatrix); 67 } 68 69 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(DOMMatrixReadOnly) NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(DOMMatrixReadOnly)70 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(DOMMatrixReadOnly) 71 72 nsISupports* GetParentObject() const { return mParent; } 73 virtual JSObject* WrapObject(JSContext* cx, 74 JS::Handle<JSObject*> aGivenProto) override; 75 76 static already_AddRefed<DOMMatrixReadOnly> FromMatrix( 77 nsISupports* aParent, const DOMMatrix2DInit& aMatrixInit, 78 ErrorResult& aRv); 79 80 static already_AddRefed<DOMMatrixReadOnly> FromMatrix( 81 nsISupports* aParent, const DOMMatrixInit& aMatrixInit, ErrorResult& aRv); 82 83 static already_AddRefed<DOMMatrixReadOnly> FromMatrix( 84 const GlobalObject& aGlobal, const DOMMatrixInit& aMatrixInit, 85 ErrorResult& aRv); 86 87 static already_AddRefed<DOMMatrixReadOnly> FromFloat32Array( 88 const GlobalObject& aGlobal, const Float32Array& aArray32, 89 ErrorResult& aRv); 90 91 static already_AddRefed<DOMMatrixReadOnly> FromFloat64Array( 92 const GlobalObject& aGlobal, const Float64Array& aArray64, 93 ErrorResult& aRv); 94 95 static already_AddRefed<DOMMatrixReadOnly> Constructor( 96 const GlobalObject& aGlobal, 97 const Optional<UTF8StringOrUnrestrictedDoubleSequenceOrDOMMatrixReadOnly>& 98 aArg, 99 ErrorResult& aRv); 100 101 static already_AddRefed<DOMMatrixReadOnly> ReadStructuredClone( 102 JSContext* aCx, nsIGlobalObject* aGlobal, 103 JSStructuredCloneReader* aReader); 104 105 // clang-format off 106 #define GetMatrixMember(entry2D, entry3D, default) \ 107 { \ 108 if (mMatrix3D) { \ 109 return mMatrix3D->entry3D; \ 110 } \ 111 return mMatrix2D->entry2D; \ 112 } 113 114 #define Get3DMatrixMember(entry3D, default) \ 115 { \ 116 if (mMatrix3D) { \ 117 return mMatrix3D->entry3D; \ 118 } \ 119 return default; \ 120 } 121 122 double A() const GetMatrixMember(_11, _11, 1.0) 123 double B() const GetMatrixMember(_12, _12, 0) 124 double C() const GetMatrixMember(_21, _21, 0) 125 double D() const GetMatrixMember(_22, _22, 1.0) 126 double E() const GetMatrixMember(_31, _41, 0) 127 double F() const GetMatrixMember(_32, _42, 0) 128 129 double M11() const GetMatrixMember(_11, _11, 1.0) 130 double M12() const GetMatrixMember(_12, _12, 0) 131 double M13() const Get3DMatrixMember(_13, 0) 132 double M14() const Get3DMatrixMember(_14, 0) 133 double M21() const GetMatrixMember(_21, _21, 0) 134 double M22() const GetMatrixMember(_22, _22, 1.0) 135 double M23() const Get3DMatrixMember(_23, 0) 136 double M24() const Get3DMatrixMember(_24, 0) 137 double M31() const Get3DMatrixMember(_31, 0) 138 double M32() const Get3DMatrixMember(_32, 0) 139 double M33() const Get3DMatrixMember(_33, 1.0) 140 double M34() const Get3DMatrixMember(_34, 0) 141 double M41() const GetMatrixMember(_31, _41, 0) 142 double M42() const GetMatrixMember(_32, _42, 0) 143 double M43() const Get3DMatrixMember(_43, 0) 144 double M44() const Get3DMatrixMember(_44, 1.0) 145 146 #undef GetMatrixMember 147 #undef Get3DMatrixMember 148 149 // Defined here so we can construct DOMMatrixReadOnly objects. 150 #define Set2DMatrixMember(entry2D, entry3D) \ 151 { \ 152 if (mMatrix3D) { \ 153 mMatrix3D->entry3D = v; \ 154 } else { \ 155 mMatrix2D->entry2D = v; \ 156 } \ 157 } 158 159 #define Set3DMatrixMember(entry3D, default) \ 160 { \ 161 if (mMatrix3D || (v != default)) { \ 162 Ensure3DMatrix(); \ 163 mMatrix3D->entry3D = v; \ 164 } \ 165 } 166 167 void SetA(double v) Set2DMatrixMember(_11, _11) 168 void SetB(double v) Set2DMatrixMember(_12, _12) 169 void SetC(double v) Set2DMatrixMember(_21, _21) 170 void SetD(double v) Set2DMatrixMember(_22, _22) 171 void SetE(double v) Set2DMatrixMember(_31, _41) 172 void SetF(double v) Set2DMatrixMember(_32, _42) 173 174 void SetM11(double v) Set2DMatrixMember(_11, _11) 175 void SetM12(double v) Set2DMatrixMember(_12, _12) 176 void SetM13(double v) Set3DMatrixMember(_13, 0) 177 void SetM14(double v) Set3DMatrixMember(_14, 0) 178 void SetM21(double v) Set2DMatrixMember(_21, _21) 179 void SetM22(double v) Set2DMatrixMember(_22, _22) 180 void SetM23(double v) Set3DMatrixMember(_23, 0) 181 void SetM24(double v) Set3DMatrixMember(_24, 0) 182 void SetM31(double v) Set3DMatrixMember(_31, 0) 183 void SetM32(double v) Set3DMatrixMember(_32, 0) 184 void SetM33(double v) Set3DMatrixMember(_33, 1.0) 185 void SetM34(double v) Set3DMatrixMember(_34, 0) 186 void SetM41(double v) Set2DMatrixMember(_31, _41) 187 void SetM42(double v) Set2DMatrixMember(_32, _42) 188 void SetM43(double v) Set3DMatrixMember(_43, 0) 189 void SetM44(double v) Set3DMatrixMember(_44, 1.0) 190 ; // semi-colon here to get clang-format to align properly from here on 191 192 #undef Set2DMatrixMember 193 #undef Set3DMatrixMember 194 // clang-format on 195 196 already_AddRefed<DOMMatrix> Translate(double aTx, double aTy, 197 double aTz = 0) const; 198 already_AddRefed<DOMMatrix> Scale(double aScaleX, 199 const Optional<double>& aScaleY, 200 double aScaleZ, double aOriginX, 201 double aOriginY, double aOriginZ) const; 202 already_AddRefed<DOMMatrix> Scale3d(double aScale, double aOriginX = 0, 203 double aOriginY = 0, 204 double aOriginZ = 0) const; 205 already_AddRefed<DOMMatrix> ScaleNonUniform(double aScaleX, 206 double aScaleY) const; 207 already_AddRefed<DOMMatrix> Rotate(double aRotX, 208 const Optional<double>& aRotY, 209 const Optional<double>& aRotZ) const; 210 already_AddRefed<DOMMatrix> RotateFromVector(double aX, double aY) const; 211 already_AddRefed<DOMMatrix> RotateAxisAngle(double aX, double aY, double aZ, 212 double aAngle) const; 213 already_AddRefed<DOMMatrix> SkewX(double aSx) const; 214 already_AddRefed<DOMMatrix> SkewY(double aSy) const; 215 already_AddRefed<DOMMatrix> Multiply(const DOMMatrixInit& aOther, 216 ErrorResult& aRv) const; 217 already_AddRefed<DOMMatrix> FlipX() const; 218 already_AddRefed<DOMMatrix> FlipY() const; 219 already_AddRefed<DOMMatrix> Inverse() const; 220 221 bool Is2D() const; 222 bool IsIdentity() const; 223 already_AddRefed<DOMPoint> TransformPoint(const DOMPointInit& aPoint) const; 224 void ToFloat32Array(JSContext* aCx, JS::MutableHandle<JSObject*> aResult, 225 ErrorResult& aRv) const; 226 void ToFloat64Array(JSContext* aCx, JS::MutableHandle<JSObject*> aResult, 227 ErrorResult& aRv) const; 228 void Stringify(nsAString& aResult, ErrorResult& aRv); 229 230 bool WriteStructuredClone(JSContext* aCx, 231 JSStructuredCloneWriter* aWriter) const; GetInternal2D()232 const gfx::MatrixDouble* GetInternal2D() const { 233 if (Is2D()) { 234 return mMatrix2D.get(); 235 } 236 return nullptr; 237 } 238 239 protected: 240 nsCOMPtr<nsISupports> mParent; 241 UniquePtr<gfx::MatrixDouble> mMatrix2D; 242 UniquePtr<gfx::Matrix4x4Double> mMatrix3D; 243 244 virtual ~DOMMatrixReadOnly() = default; 245 246 /** 247 * Sets data from a fully validated and fixed-up matrix init, 248 * where all of its members are properly defined. 249 * The init dictionary's dimension must match the matrix one. 250 */ 251 void SetDataFromMatrix2DInit(const DOMMatrix2DInit& aMatrixInit); 252 void SetDataFromMatrixInit(const DOMMatrixInit& aMatrixInit); 253 254 DOMMatrixReadOnly* SetMatrixValue(const nsACString&, ErrorResult&); 255 void Ensure3DMatrix(); 256 DOMMatrixReadOnly(nsISupports * aParent,bool is2D)257 DOMMatrixReadOnly(nsISupports* aParent, bool is2D) : mParent(aParent) { 258 if (is2D) { 259 mMatrix2D = MakeUnique<gfx::MatrixDouble>(); 260 } else { 261 mMatrix3D = MakeUnique<gfx::Matrix4x4Double>(); 262 } 263 } 264 265 static bool ReadStructuredCloneElements(JSStructuredCloneReader* aReader, 266 DOMMatrixReadOnly* matrix); 267 268 private: 269 DOMMatrixReadOnly() = delete; 270 DOMMatrixReadOnly(const DOMMatrixReadOnly&) = delete; 271 DOMMatrixReadOnly& operator=(const DOMMatrixReadOnly&) = delete; 272 }; 273 274 class DOMMatrix : public DOMMatrixReadOnly { 275 public: DOMMatrix(nsISupports * aParent)276 explicit DOMMatrix(nsISupports* aParent) : DOMMatrixReadOnly(aParent) {} 277 DOMMatrix(nsISupports * aParent,const DOMMatrixReadOnly & other)278 DOMMatrix(nsISupports* aParent, const DOMMatrixReadOnly& other) 279 : DOMMatrixReadOnly(aParent, other) {} 280 DOMMatrix(nsISupports * aParent,const gfx::Matrix4x4 & aMatrix)281 DOMMatrix(nsISupports* aParent, const gfx::Matrix4x4& aMatrix) 282 : DOMMatrixReadOnly(aParent, aMatrix) {} 283 DOMMatrix(nsISupports * aParent,const gfx::Matrix & aMatrix)284 DOMMatrix(nsISupports* aParent, const gfx::Matrix& aMatrix) 285 : DOMMatrixReadOnly(aParent, aMatrix) {} 286 287 static already_AddRefed<DOMMatrix> FromMatrix( 288 nsISupports* aParent, const DOMMatrixInit& aMatrixInit, ErrorResult& aRv); 289 290 static already_AddRefed<DOMMatrix> FromMatrix( 291 const GlobalObject& aGlobal, const DOMMatrixInit& aMatrixInit, 292 ErrorResult& aRv); 293 294 static already_AddRefed<DOMMatrix> FromFloat32Array( 295 const GlobalObject& aGlobal, const Float32Array& aArray32, 296 ErrorResult& aRv); 297 298 static already_AddRefed<DOMMatrix> FromFloat64Array( 299 const GlobalObject& aGlobal, const Float64Array& aArray64, 300 ErrorResult& aRv); 301 302 static already_AddRefed<DOMMatrix> Constructor( 303 const GlobalObject& aGlobal, 304 const Optional<UTF8StringOrUnrestrictedDoubleSequenceOrDOMMatrixReadOnly>& 305 aArg, 306 ErrorResult& aRv); 307 308 static already_AddRefed<DOMMatrix> ReadStructuredClone( 309 JSContext* aCx, nsIGlobalObject* aGlobal, 310 JSStructuredCloneReader* aReader); 311 312 virtual JSObject* WrapObject(JSContext* aCx, 313 JS::Handle<JSObject*> aGivenProto) override; 314 315 DOMMatrix* MultiplySelf(const DOMMatrixInit& aOther, ErrorResult& aRv); 316 DOMMatrix* PreMultiplySelf(const DOMMatrixInit& aOther, ErrorResult& aRv); 317 DOMMatrix* TranslateSelf(double aTx, double aTy, double aTz = 0); 318 DOMMatrix* ScaleSelf(double aScaleX, const Optional<double>& aScaleY, 319 double aScaleZ, double aOriginX, double aOriginY, 320 double aOriginZ); 321 DOMMatrix* Scale3dSelf(double aScale, double aOriginX = 0, 322 double aOriginY = 0, double aOriginZ = 0); 323 DOMMatrix* RotateSelf(double aRotX, const Optional<double>& aRotY, 324 const Optional<double>& aRotZ); 325 DOMMatrix* RotateFromVectorSelf(double aX, double aY); 326 DOMMatrix* RotateAxisAngleSelf(double aX, double aY, double aZ, 327 double aAngle); 328 DOMMatrix* SkewXSelf(double aSx); 329 DOMMatrix* SkewYSelf(double aSy); 330 DOMMatrix* InvertSelf(); 331 DOMMatrix* SetMatrixValue(const nsACString&, ErrorResult&); 332 333 virtual ~DOMMatrix() = default; 334 335 private: DOMMatrix(nsISupports * aParent,bool is2D)336 DOMMatrix(nsISupports* aParent, bool is2D) 337 : DOMMatrixReadOnly(aParent, is2D) {} 338 }; 339 340 } // namespace dom 341 } // namespace mozilla 342 343 #endif /*MOZILLA_DOM_DOMMATRIX_H_*/ 344