DOMMatrix.h (13563B)
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 13 #include "js/RootingAPI.h" 14 #include "mozilla/AlreadyAddRefed.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: 47 explicit DOMMatrixReadOnly(nsISupports* aParent) 48 : mParent(aParent), mMatrix2D(new gfx::MatrixDouble()) {} 49 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 59 DOMMatrixReadOnly(nsISupports* aParent, const gfx::Matrix4x4& aMatrix) 60 : mParent(aParent) { 61 mMatrix3D = MakeUnique<gfx::Matrix4x4Double>(aMatrix); 62 } 63 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) 70 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_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; 232 const gfx::MatrixDouble* GetInternal2D() const { 233 if (Is2D()) { 234 return mMatrix2D.get(); 235 } 236 return nullptr; 237 } 238 239 static gfx::MatrixDouble ToValidatedMatrixDouble( 240 const DOMMatrix2DInit& aMatrixInit, ErrorResult& aRv); 241 242 protected: 243 nsCOMPtr<nsISupports> mParent; 244 UniquePtr<gfx::MatrixDouble> mMatrix2D; 245 UniquePtr<gfx::Matrix4x4Double> mMatrix3D; 246 247 virtual ~DOMMatrixReadOnly() = default; 248 249 /** 250 * Sets data from a fully validated and fixed-up matrix init, 251 * where all of its members are properly defined. 252 * The init dictionary's dimension must match the matrix one. 253 */ 254 void SetDataFromMatrix2DInit(const DOMMatrix2DInit& aMatrixInit); 255 static gfx::MatrixDouble ToMatrixDouble(const DOMMatrix2DInit& aMatrixInit); 256 void SetDataFromMatrixInit(const DOMMatrixInit& aMatrixInit); 257 258 DOMMatrixReadOnly* SetMatrixValue(const nsACString&, ErrorResult&); 259 void Ensure3DMatrix(); 260 261 DOMMatrixReadOnly(nsISupports* aParent, bool is2D) 262 : DOMMatrixReadOnly(do_AddRef(aParent), is2D) {} 263 DOMMatrixReadOnly(already_AddRefed<nsISupports>&& aParent, bool is2D) 264 : mParent(std::move(aParent)) { 265 if (is2D) { 266 mMatrix2D = MakeUnique<gfx::MatrixDouble>(); 267 } else { 268 mMatrix3D = MakeUnique<gfx::Matrix4x4Double>(); 269 } 270 } 271 272 static bool ReadStructuredCloneElements(JSStructuredCloneReader* aReader, 273 DOMMatrixReadOnly* matrix); 274 275 private: 276 DOMMatrixReadOnly() = delete; 277 DOMMatrixReadOnly(const DOMMatrixReadOnly&) = delete; 278 DOMMatrixReadOnly& operator=(const DOMMatrixReadOnly&) = delete; 279 }; 280 281 class DOMMatrix : public DOMMatrixReadOnly { 282 public: 283 explicit DOMMatrix(nsISupports* aParent) : DOMMatrixReadOnly(aParent) {} 284 285 DOMMatrix(nsISupports* aParent, const DOMMatrixReadOnly& other) 286 : DOMMatrixReadOnly(aParent, other) {} 287 288 DOMMatrix(nsISupports* aParent, const gfx::Matrix4x4& aMatrix) 289 : DOMMatrixReadOnly(aParent, aMatrix) {} 290 291 DOMMatrix(nsISupports* aParent, const gfx::Matrix& aMatrix) 292 : DOMMatrixReadOnly(aParent, aMatrix) {} 293 294 static already_AddRefed<DOMMatrix> FromMatrix( 295 nsISupports* aParent, const DOMMatrixInit& aMatrixInit, ErrorResult& aRv); 296 297 static already_AddRefed<DOMMatrix> FromMatrix( 298 const GlobalObject& aGlobal, const DOMMatrixInit& aMatrixInit, 299 ErrorResult& aRv); 300 301 static already_AddRefed<DOMMatrix> FromFloat32Array( 302 const GlobalObject& aGlobal, const Float32Array& aArray32, 303 ErrorResult& aRv); 304 305 static already_AddRefed<DOMMatrix> FromFloat64Array( 306 const GlobalObject& aGlobal, const Float64Array& aArray64, 307 ErrorResult& aRv); 308 309 static already_AddRefed<DOMMatrix> Constructor( 310 const GlobalObject& aGlobal, 311 const Optional<UTF8StringOrUnrestrictedDoubleSequenceOrDOMMatrixReadOnly>& 312 aArg, 313 ErrorResult& aRv); 314 315 static already_AddRefed<DOMMatrix> ReadStructuredClone( 316 JSContext* aCx, nsIGlobalObject* aGlobal, 317 JSStructuredCloneReader* aReader); 318 319 virtual JSObject* WrapObject(JSContext* aCx, 320 JS::Handle<JSObject*> aGivenProto) override; 321 322 DOMMatrix* MultiplySelf(const DOMMatrixInit& aOther, ErrorResult& aRv); 323 DOMMatrix* PreMultiplySelf(const DOMMatrixInit& aOther, ErrorResult& aRv); 324 DOMMatrix* TranslateSelf(double aTx, double aTy, double aTz = 0); 325 DOMMatrix* ScaleSelf(double aScaleX, const Optional<double>& aScaleY, 326 double aScaleZ, double aOriginX, double aOriginY, 327 double aOriginZ); 328 DOMMatrix* Scale3dSelf(double aScale, double aOriginX = 0, 329 double aOriginY = 0, double aOriginZ = 0); 330 DOMMatrix* RotateSelf(double aRotX, const Optional<double>& aRotY, 331 const Optional<double>& aRotZ); 332 DOMMatrix* RotateFromVectorSelf(double aX, double aY); 333 DOMMatrix* RotateAxisAngleSelf(double aX, double aY, double aZ, 334 double aAngle); 335 DOMMatrix* SkewXSelf(double aSx); 336 DOMMatrix* SkewYSelf(double aSy); 337 DOMMatrix* InvertSelf(); 338 DOMMatrix* SetMatrixValue(const nsACString&, ErrorResult&); 339 340 virtual ~DOMMatrix() = default; 341 342 private: 343 DOMMatrix(nsISupports* aParent, bool is2D) 344 : DOMMatrixReadOnly(aParent, is2D) {} 345 DOMMatrix(already_AddRefed<nsISupports>&& aParent, bool is2D) 346 : DOMMatrixReadOnly(std::move(aParent), is2D) {} 347 }; 348 349 } // namespace dom 350 } // namespace mozilla 351 352 #endif /*MOZILLA_DOM_DOMMATRIX_H_*/