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 : #include "mozilla/dom/WebKitCSSMatrix.h"
8 :
9 : #include "mozilla/dom/BindingUtils.h"
10 : #include "mozilla/dom/WebKitCSSMatrixBinding.h"
11 : #include "mozilla/Preferences.h"
12 : #include "nsCSSParser.h"
13 : #include "nsPresContext.h"
14 : #include "nsStyleTransformMatrix.h"
15 : #include "RuleNodeCacheConditions.h"
16 :
17 : namespace mozilla {
18 : namespace dom {
19 :
20 : static const double sRadPerDegree = 2.0 * M_PI / 360.0;
21 :
22 : bool
23 0 : WebKitCSSMatrix::FeatureEnabled(JSContext* aCx, JSObject* aObj)
24 : {
25 0 : return Preferences::GetBool("layout.css.DOMMatrix.enabled", false) &&
26 0 : Preferences::GetBool("layout.css.prefixes.webkit", false);
27 : }
28 :
29 : already_AddRefed<WebKitCSSMatrix>
30 0 : WebKitCSSMatrix::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
31 : {
32 0 : RefPtr<WebKitCSSMatrix> obj = new WebKitCSSMatrix(aGlobal.GetAsSupports());
33 0 : return obj.forget();
34 : }
35 :
36 : already_AddRefed<WebKitCSSMatrix>
37 0 : WebKitCSSMatrix::Constructor(const GlobalObject& aGlobal,
38 : const nsAString& aTransformList, ErrorResult& aRv)
39 : {
40 0 : RefPtr<WebKitCSSMatrix> obj = new WebKitCSSMatrix(aGlobal.GetAsSupports());
41 0 : obj = obj->SetMatrixValue(aTransformList, aRv);
42 0 : return obj.forget();
43 : }
44 :
45 : already_AddRefed<WebKitCSSMatrix>
46 0 : WebKitCSSMatrix::Constructor(const GlobalObject& aGlobal,
47 : const DOMMatrixReadOnly& aOther, ErrorResult& aRv)
48 : {
49 0 : RefPtr<WebKitCSSMatrix> obj = new WebKitCSSMatrix(aGlobal.GetAsSupports(),
50 0 : aOther);
51 0 : return obj.forget();
52 : }
53 :
54 : JSObject*
55 0 : WebKitCSSMatrix::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
56 : {
57 0 : return WebKitCSSMatrixBinding::Wrap(aCx, this, aGivenProto);
58 : }
59 :
60 : WebKitCSSMatrix*
61 0 : WebKitCSSMatrix::SetMatrixValue(const nsAString& aTransformList,
62 : ErrorResult& aRv)
63 : {
64 : // An empty string is a no-op.
65 0 : if (aTransformList.IsEmpty()) {
66 0 : return this;
67 : }
68 :
69 0 : nsCSSValue value;
70 0 : nsCSSParser parser;
71 : bool parseSuccess = parser.ParseTransformProperty(aTransformList,
72 : true,
73 0 : value);
74 0 : if (!parseSuccess) {
75 0 : aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
76 0 : return nullptr;
77 : }
78 :
79 : // A value of "none" results in a 2D identity matrix.
80 0 : if (value.GetUnit() == eCSSUnit_None) {
81 0 : mMatrix3D = nullptr;
82 0 : mMatrix2D = new gfx::Matrix();
83 0 : return this;
84 : }
85 :
86 : // A value other than a transform-list is a syntax error.
87 0 : if (value.GetUnit() != eCSSUnit_SharedList) {
88 0 : aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
89 0 : return nullptr;
90 : }
91 :
92 0 : RuleNodeCacheConditions dummy;
93 0 : nsStyleTransformMatrix::TransformReferenceBox dummyBox;
94 0 : bool contains3dTransform = false;
95 : gfx::Matrix4x4 transform = nsStyleTransformMatrix::ReadTransforms(
96 0 : value.GetSharedListValue()->mHead,
97 : nullptr, nullptr, dummy, dummyBox,
98 0 : nsPresContext::AppUnitsPerCSSPixel(),
99 0 : &contains3dTransform);
100 :
101 0 : if (!contains3dTransform) {
102 0 : mMatrix3D = nullptr;
103 0 : mMatrix2D = new gfx::Matrix();
104 :
105 0 : SetA(transform._11);
106 0 : SetB(transform._12);
107 0 : SetC(transform._21);
108 0 : SetD(transform._22);
109 0 : SetE(transform._41);
110 0 : SetF(transform._42);
111 : } else {
112 0 : mMatrix3D = new gfx::Matrix4x4(transform);
113 0 : mMatrix2D = nullptr;
114 : }
115 :
116 0 : return this;
117 : }
118 :
119 : already_AddRefed<WebKitCSSMatrix>
120 0 : WebKitCSSMatrix::Multiply(const WebKitCSSMatrix& other) const
121 : {
122 0 : RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
123 0 : retval->MultiplySelf(other);
124 :
125 0 : return retval.forget();
126 : }
127 :
128 : already_AddRefed<WebKitCSSMatrix>
129 0 : WebKitCSSMatrix::Inverse(ErrorResult& aRv) const
130 : {
131 0 : RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
132 0 : retval->InvertSelfThrow(aRv);
133 0 : if (NS_WARN_IF(aRv.Failed())) {
134 0 : return nullptr;
135 : }
136 :
137 0 : return retval.forget();
138 : }
139 :
140 : WebKitCSSMatrix*
141 0 : WebKitCSSMatrix::InvertSelfThrow(ErrorResult& aRv)
142 : {
143 0 : if (mMatrix3D) {
144 0 : if (!mMatrix3D->Invert()) {
145 0 : aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
146 0 : return nullptr;
147 : }
148 0 : } else if (!mMatrix2D->Invert()) {
149 0 : aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
150 0 : return nullptr;
151 : }
152 :
153 0 : return this;
154 : }
155 :
156 : already_AddRefed<WebKitCSSMatrix>
157 0 : WebKitCSSMatrix::Translate(double aTx,
158 : double aTy,
159 : double aTz) const
160 : {
161 0 : RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
162 0 : retval->TranslateSelf(aTx, aTy, aTz);
163 :
164 0 : return retval.forget();
165 : }
166 :
167 : already_AddRefed<WebKitCSSMatrix>
168 0 : WebKitCSSMatrix::Scale(double aScaleX,
169 : const Optional<double>& aScaleY,
170 : double aScaleZ) const
171 : {
172 0 : double scaleX = aScaleX;
173 0 : double scaleY = aScaleY.WasPassed() ? aScaleY.Value() : scaleX;
174 0 : double scaleZ = aScaleZ;
175 :
176 0 : RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
177 0 : retval->ScaleNonUniformSelf(scaleX, scaleY, scaleZ);
178 :
179 0 : return retval.forget();
180 : }
181 :
182 : already_AddRefed<WebKitCSSMatrix>
183 0 : WebKitCSSMatrix::Rotate(double aRotX,
184 : const Optional<double>& aRotY,
185 : const Optional<double>& aRotZ) const
186 : {
187 0 : double rotX = aRotX;
188 : double rotY;
189 : double rotZ;
190 :
191 0 : if (!aRotY.WasPassed() && !aRotZ.WasPassed()) {
192 0 : rotZ = rotX;
193 0 : rotX = 0;
194 0 : rotY = 0;
195 : } else {
196 0 : rotY = aRotY.WasPassed() ? aRotY.Value() : 0;
197 0 : rotZ = aRotZ.WasPassed() ? aRotZ.Value() : 0;
198 : }
199 :
200 0 : RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
201 0 : retval->Rotate3dSelf(rotX, rotY, rotZ);
202 :
203 0 : return retval.forget();
204 : }
205 :
206 : WebKitCSSMatrix*
207 0 : WebKitCSSMatrix::Rotate3dSelf(double aRotX,
208 : double aRotY,
209 : double aRotZ)
210 : {
211 0 : if (aRotX != 0 || aRotY != 0) {
212 0 : Ensure3DMatrix();
213 : }
214 :
215 0 : if (mMatrix3D) {
216 0 : if (fmod(aRotZ, 360) != 0) {
217 0 : mMatrix3D->RotateZ(aRotZ * sRadPerDegree);
218 : }
219 0 : if (fmod(aRotY, 360) != 0) {
220 0 : mMatrix3D->RotateY(aRotY * sRadPerDegree);
221 : }
222 0 : if (fmod(aRotX, 360) != 0) {
223 0 : mMatrix3D->RotateX(aRotX * sRadPerDegree);
224 : }
225 0 : } else if (fmod(aRotZ, 360) != 0) {
226 0 : mMatrix2D->PreRotate(aRotZ * sRadPerDegree);
227 : }
228 :
229 0 : return this;
230 : }
231 :
232 : already_AddRefed<WebKitCSSMatrix>
233 0 : WebKitCSSMatrix::RotateAxisAngle(double aX,
234 : double aY,
235 : double aZ,
236 : double aAngle) const
237 : {
238 0 : RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
239 0 : retval->RotateAxisAngleSelf(aX, aY, aZ, aAngle);
240 :
241 0 : return retval.forget();
242 : }
243 :
244 : already_AddRefed<WebKitCSSMatrix>
245 0 : WebKitCSSMatrix::SkewX(double aSx) const
246 : {
247 0 : RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
248 0 : retval->SkewXSelf(aSx);
249 :
250 0 : return retval.forget();
251 : }
252 :
253 : already_AddRefed<WebKitCSSMatrix>
254 0 : WebKitCSSMatrix::SkewY(double aSy) const
255 : {
256 0 : RefPtr<WebKitCSSMatrix> retval = new WebKitCSSMatrix(mParent, *this);
257 0 : retval->SkewYSelf(aSy);
258 :
259 0 : return retval.forget();
260 : }
261 :
262 : } // namespace dom
263 : } // namespace mozilla
|