Merge mozilla-central to autoland on a CLOSED TREE
[gecko.git] / dom / base / DOMMatrix.h
blob19eb6f8ae42974f89ebde3e0088c156c60290148
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/. */
7 #ifndef MOZILLA_DOM_DOMMATRIX_H_
8 #define MOZILLA_DOM_DOMMATRIX_H_
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"
24 class JSObject;
25 class nsIGlobalObject;
26 struct JSContext;
27 struct JSStructuredCloneReader;
28 struct JSStructuredCloneWriter;
30 namespace mozilla {
31 class ErrorResult;
33 namespace dom {
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;
45 class DOMMatrixReadOnly : public nsWrapperCache {
46 public:
47 explicit DOMMatrixReadOnly(nsISupports* aParent)
48 : mParent(aParent), mMatrix2D(new gfx::MatrixDouble()) {}
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);
59 DOMMatrixReadOnly(nsISupports* aParent, const gfx::Matrix4x4& aMatrix)
60 : mParent(aParent) {
61 mMatrix3D = MakeUnique<gfx::Matrix4x4Double>(aMatrix);
64 DOMMatrixReadOnly(nsISupports* aParent, const gfx::Matrix& aMatrix)
65 : mParent(aParent) {
66 mMatrix2D = MakeUnique<gfx::MatrixDouble>(aMatrix);
69 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(DOMMatrixReadOnly)
70 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(DOMMatrixReadOnly)
72 nsISupports* GetParentObject() const { return mParent; }
73 virtual JSObject* WrapObject(JSContext* cx,
74 JS::Handle<JSObject*> aGivenProto) override;
76 static already_AddRefed<DOMMatrixReadOnly> FromMatrix(
77 nsISupports* aParent, const DOMMatrix2DInit& aMatrixInit,
78 ErrorResult& aRv);
80 static already_AddRefed<DOMMatrixReadOnly> FromMatrix(
81 nsISupports* aParent, const DOMMatrixInit& aMatrixInit, ErrorResult& aRv);
83 static already_AddRefed<DOMMatrixReadOnly> FromMatrix(
84 const GlobalObject& aGlobal, const DOMMatrixInit& aMatrixInit,
85 ErrorResult& aRv);
87 static already_AddRefed<DOMMatrixReadOnly> FromFloat32Array(
88 const GlobalObject& aGlobal, const Float32Array& aArray32,
89 ErrorResult& aRv);
91 static already_AddRefed<DOMMatrixReadOnly> FromFloat64Array(
92 const GlobalObject& aGlobal, const Float64Array& aArray64,
93 ErrorResult& aRv);
95 static already_AddRefed<DOMMatrixReadOnly> Constructor(
96 const GlobalObject& aGlobal,
97 const Optional<UTF8StringOrUnrestrictedDoubleSequenceOrDOMMatrixReadOnly>&
98 aArg,
99 ErrorResult& aRv);
101 static already_AddRefed<DOMMatrixReadOnly> ReadStructuredClone(
102 JSContext* aCx, nsIGlobalObject* aGlobal,
103 JSStructuredCloneReader* aReader);
105 // clang-format off
106 #define GetMatrixMember(entry2D, entry3D, default) \
108 if (mMatrix3D) { \
109 return mMatrix3D->entry3D; \
111 return mMatrix2D->entry2D; \
114 #define Get3DMatrixMember(entry3D, default) \
116 if (mMatrix3D) { \
117 return mMatrix3D->entry3D; \
119 return default; \
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)
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)
146 #undef GetMatrixMember
147 #undef Get3DMatrixMember
149 // Defined here so we can construct DOMMatrixReadOnly objects.
150 #define Set2DMatrixMember(entry2D, entry3D) \
152 if (mMatrix3D) { \
153 mMatrix3D->entry3D = v; \
154 } else { \
155 mMatrix2D->entry2D = v; \
159 #define Set3DMatrixMember(entry3D, default) \
161 if (mMatrix3D || (v != default)) { \
162 Ensure3DMatrix(); \
163 mMatrix3D->entry3D = v; \
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)
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
192 #undef Set2DMatrixMember
193 #undef Set3DMatrixMember
194 // clang-format on
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;
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);
230 bool WriteStructuredClone(JSContext* aCx,
231 JSStructuredCloneWriter* aWriter) const;
232 const gfx::MatrixDouble* GetInternal2D() const {
233 if (Is2D()) {
234 return mMatrix2D.get();
236 return nullptr;
239 protected:
240 nsCOMPtr<nsISupports> mParent;
241 UniquePtr<gfx::MatrixDouble> mMatrix2D;
242 UniquePtr<gfx::Matrix4x4Double> mMatrix3D;
244 virtual ~DOMMatrixReadOnly() = default;
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.
251 void SetDataFromMatrix2DInit(const DOMMatrix2DInit& aMatrixInit);
252 void SetDataFromMatrixInit(const DOMMatrixInit& aMatrixInit);
254 DOMMatrixReadOnly* SetMatrixValue(const nsACString&, ErrorResult&);
255 void Ensure3DMatrix();
257 DOMMatrixReadOnly(nsISupports* aParent, bool is2D) : mParent(aParent) {
258 if (is2D) {
259 mMatrix2D = MakeUnique<gfx::MatrixDouble>();
260 } else {
261 mMatrix3D = MakeUnique<gfx::Matrix4x4Double>();
265 static bool ReadStructuredCloneElements(JSStructuredCloneReader* aReader,
266 DOMMatrixReadOnly* matrix);
268 private:
269 DOMMatrixReadOnly() = delete;
270 DOMMatrixReadOnly(const DOMMatrixReadOnly&) = delete;
271 DOMMatrixReadOnly& operator=(const DOMMatrixReadOnly&) = delete;
274 class DOMMatrix : public DOMMatrixReadOnly {
275 public:
276 explicit DOMMatrix(nsISupports* aParent) : DOMMatrixReadOnly(aParent) {}
278 DOMMatrix(nsISupports* aParent, const DOMMatrixReadOnly& other)
279 : DOMMatrixReadOnly(aParent, other) {}
281 DOMMatrix(nsISupports* aParent, const gfx::Matrix4x4& aMatrix)
282 : DOMMatrixReadOnly(aParent, aMatrix) {}
284 DOMMatrix(nsISupports* aParent, const gfx::Matrix& aMatrix)
285 : DOMMatrixReadOnly(aParent, aMatrix) {}
287 static already_AddRefed<DOMMatrix> FromMatrix(
288 nsISupports* aParent, const DOMMatrixInit& aMatrixInit, ErrorResult& aRv);
290 static already_AddRefed<DOMMatrix> FromMatrix(
291 const GlobalObject& aGlobal, const DOMMatrixInit& aMatrixInit,
292 ErrorResult& aRv);
294 static already_AddRefed<DOMMatrix> FromFloat32Array(
295 const GlobalObject& aGlobal, const Float32Array& aArray32,
296 ErrorResult& aRv);
298 static already_AddRefed<DOMMatrix> FromFloat64Array(
299 const GlobalObject& aGlobal, const Float64Array& aArray64,
300 ErrorResult& aRv);
302 static already_AddRefed<DOMMatrix> Constructor(
303 const GlobalObject& aGlobal,
304 const Optional<UTF8StringOrUnrestrictedDoubleSequenceOrDOMMatrixReadOnly>&
305 aArg,
306 ErrorResult& aRv);
308 static already_AddRefed<DOMMatrix> ReadStructuredClone(
309 JSContext* aCx, nsIGlobalObject* aGlobal,
310 JSStructuredCloneReader* aReader);
312 virtual JSObject* WrapObject(JSContext* aCx,
313 JS::Handle<JSObject*> aGivenProto) override;
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&);
333 virtual ~DOMMatrix() = default;
335 private:
336 DOMMatrix(nsISupports* aParent, bool is2D)
337 : DOMMatrixReadOnly(aParent, is2D) {}
340 } // namespace dom
341 } // namespace mozilla
343 #endif /*MOZILLA_DOM_DOMMATRIX_H_*/