Line data Source code
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 : /**
8 : * Notes on transforms in Mozilla and the SVG code.
9 : *
10 : * It's important to note that the matrix convention used in the SVG standard
11 : * is the opposite convention to the one used in the Mozilla code or, more
12 : * specifically, the convention used in Thebes code (code using gfxMatrix).
13 : * Whereas the SVG standard uses the column vector convention, Thebes code uses
14 : * the row vector convention. Thus, whereas in the SVG standard you have
15 : * [M1][M2][M3]|p|, in Thebes you have |p|'[M3]'[M2]'[M1]'. In other words, the
16 : * following are equivalent:
17 : *
18 : * / a1 c1 tx1 \ / a2 c2 tx2 \ / a3 c3 tx3 \ / x \
19 : * SVG: | b1 d1 ty1 | | b2 d2 ty2 | | b3 d3 ty3 | | y |
20 : * \ 0 0 1 / \ 0 0 1 / \ 0 0 1 / \ 1 /
21 : *
22 : * / a3 b3 0 \ / a2 b2 0 \ / a1 b1 0 \
23 : * Thebes: [ x y 1 ] | c3 d3 0 | | c2 d2 0 | | c1 d1 0 |
24 : * \ tx3 ty3 1 / \ tx2 ty2 1 / \ tx1 ty1 1 /
25 : *
26 : * Because the Thebes representation of a transform is the transpose of the SVG
27 : * representation, our transform order must be reversed when representing SVG
28 : * transforms using gfxMatrix in the SVG code. Since the SVG implementation
29 : * stores and obtains matrices in SVG order, to do this we must pre-multiply
30 : * gfxMatrix objects that represent SVG transforms instead of post-multiplying
31 : * them as we would for matrices using SVG's column vector convention.
32 : * Pre-multiplying may look wrong if you're only familiar with the SVG
33 : * convention, but in that case hopefully the above explanation clears things
34 : * up.
35 : */
36 :
37 : #ifndef mozilla_dom_SVGMatrix_h
38 : #define mozilla_dom_SVGMatrix_h
39 :
40 : #include "mozilla/dom/SVGTransform.h"
41 : #include "gfxMatrix.h"
42 : #include "nsCycleCollectionParticipant.h"
43 : #include "nsWrapperCache.h"
44 : #include "mozilla/Attributes.h"
45 :
46 : namespace mozilla {
47 : namespace dom {
48 :
49 : /**
50 : * DOM wrapper for an SVG matrix.
51 : */
52 : class SVGMatrix final : public nsWrapperCache
53 : {
54 : public:
55 0 : NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(SVGMatrix)
56 0 : NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(SVGMatrix)
57 :
58 : /**
59 : * Ctor for SVGMatrix objects that belong to a SVGTransform.
60 : */
61 0 : explicit SVGMatrix(SVGTransform& aTransform) : mTransform(&aTransform) {}
62 :
63 : /**
64 : * Ctors for SVGMatrix objects created independently of a SVGTransform.
65 : */
66 : // Default ctor for gfxMatrix will produce identity mx
67 0 : SVGMatrix() {}
68 :
69 0 : explicit SVGMatrix(const gfxMatrix &aMatrix) : mMatrix(aMatrix) {}
70 :
71 0 : const gfxMatrix& GetMatrix() const {
72 0 : return mTransform ? mTransform->Matrixgfx() : mMatrix;
73 : }
74 :
75 : // WebIDL
76 : SVGTransform* GetParentObject() const;
77 : virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
78 :
79 0 : float A() const { return static_cast<float>(GetMatrix()._11); }
80 : void SetA(float aA, ErrorResult& rv);
81 0 : float B() const { return static_cast<float>(GetMatrix()._12); }
82 : void SetB(float aB, ErrorResult& rv);
83 0 : float C() const { return static_cast<float>(GetMatrix()._21); }
84 : void SetC(float aC, ErrorResult& rv);
85 0 : float D() const { return static_cast<float>(GetMatrix()._22); }
86 : void SetD(float aD, ErrorResult& rv);
87 0 : float E() const { return static_cast<float>(GetMatrix()._31); }
88 : void SetE(float aE, ErrorResult& rv);
89 0 : float F() const { return static_cast<float>(GetMatrix()._32); }
90 : void SetF(float aF, ErrorResult& rv);
91 : already_AddRefed<SVGMatrix> Multiply(SVGMatrix& aMatrix);
92 : already_AddRefed<SVGMatrix> Inverse(ErrorResult& aRv);
93 : already_AddRefed<SVGMatrix> Translate(float x, float y);
94 : already_AddRefed<SVGMatrix> Scale(float scaleFactor);
95 : already_AddRefed<SVGMatrix> ScaleNonUniform(float scaleFactorX,
96 : float scaleFactorY);
97 : already_AddRefed<SVGMatrix> Rotate(float angle);
98 : already_AddRefed<SVGMatrix> RotateFromVector(float x,
99 : float y,
100 : ErrorResult& aRv);
101 : already_AddRefed<SVGMatrix> FlipX();
102 : already_AddRefed<SVGMatrix> FlipY();
103 : already_AddRefed<SVGMatrix> SkewX(float angle, ErrorResult& rv);
104 : already_AddRefed<SVGMatrix> SkewY(float angle, ErrorResult& rv);
105 :
106 : private:
107 0 : ~SVGMatrix() {}
108 :
109 0 : void SetMatrix(const gfxMatrix& aMatrix) {
110 0 : if (mTransform) {
111 0 : mTransform->SetMatrix(aMatrix);
112 : } else {
113 0 : mMatrix = aMatrix;
114 : }
115 0 : }
116 :
117 0 : bool IsAnimVal() const {
118 0 : return mTransform ? mTransform->IsAnimVal() : false;
119 : }
120 :
121 : RefPtr<SVGTransform> mTransform;
122 :
123 : // Typically we operate on the matrix data accessed via mTransform but for
124 : // matrices that exist independently of an SVGTransform we use mMatrix below.
125 : gfxMatrix mMatrix;
126 : };
127 :
128 : } // namespace dom
129 : } // namespace mozilla
130 :
131 : #endif // mozilla_dom_SVGMatrix_h
|