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 "nsError.h"
8 : #include "nsSVGTransform.h"
9 : #include "nsContentUtils.h" // for NS_ENSURE_FINITE
10 : #include "nsTextFormatter.h"
11 :
12 : namespace {
13 : const double kRadPerDegree = 2.0 * M_PI / 360.0;
14 : } // namespace
15 :
16 : namespace mozilla {
17 :
18 : void
19 0 : nsSVGTransform::GetValueAsString(nsAString& aValue) const
20 : {
21 : char16_t buf[256];
22 :
23 0 : switch (mType) {
24 : case SVG_TRANSFORM_TRANSLATE:
25 : // The spec say that if Y is not provided, it is assumed to be zero.
26 0 : if (mMatrix._32 != 0)
27 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
28 : u"translate(%g, %g)",
29 0 : mMatrix._31, mMatrix._32);
30 : else
31 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
32 : u"translate(%g)",
33 0 : mMatrix._31);
34 0 : break;
35 : case SVG_TRANSFORM_ROTATE:
36 0 : if (mOriginX != 0.0f || mOriginY != 0.0f)
37 0 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
38 : u"rotate(%g, %g, %g)",
39 0 : mAngle, mOriginX, mOriginY);
40 : else
41 0 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
42 0 : u"rotate(%g)", mAngle);
43 0 : break;
44 : case SVG_TRANSFORM_SCALE:
45 0 : if (mMatrix._11 != mMatrix._22)
46 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
47 0 : u"scale(%g, %g)", mMatrix._11, mMatrix._22);
48 : else
49 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
50 0 : u"scale(%g)", mMatrix._11);
51 0 : break;
52 : case SVG_TRANSFORM_SKEWX:
53 0 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
54 0 : u"skewX(%g)", mAngle);
55 0 : break;
56 : case SVG_TRANSFORM_SKEWY:
57 0 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
58 0 : u"skewY(%g)", mAngle);
59 0 : break;
60 : case SVG_TRANSFORM_MATRIX:
61 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(char16_t),
62 : u"matrix(%g, %g, %g, %g, %g, %g)",
63 0 : mMatrix._11, mMatrix._12,
64 0 : mMatrix._21, mMatrix._22,
65 0 : mMatrix._31, mMatrix._32);
66 0 : break;
67 : default:
68 0 : buf[0] = '\0';
69 0 : NS_ERROR("unknown transformation type");
70 0 : break;
71 : }
72 :
73 0 : aValue.Assign(buf);
74 0 : }
75 :
76 : void
77 0 : nsSVGTransform::SetMatrix(const gfxMatrix& aMatrix)
78 : {
79 0 : mType = SVG_TRANSFORM_MATRIX;
80 0 : mMatrix = aMatrix;
81 : // We set the other members here too, since operator== requires it and
82 : // the DOM requires it for mAngle.
83 0 : mAngle = 0.f;
84 0 : mOriginX = 0.f;
85 0 : mOriginY = 0.f;
86 0 : }
87 :
88 : void
89 7 : nsSVGTransform::SetTranslate(float aTx, float aTy)
90 : {
91 7 : mType = SVG_TRANSFORM_TRANSLATE;
92 7 : mMatrix = gfxMatrix::Translation(aTx, aTy);
93 7 : mAngle = 0.f;
94 7 : mOriginX = 0.f;
95 7 : mOriginY = 0.f;
96 7 : }
97 :
98 : void
99 0 : nsSVGTransform::SetScale(float aSx, float aSy)
100 : {
101 0 : mType = SVG_TRANSFORM_SCALE;
102 0 : mMatrix = gfxMatrix::Scaling(aSx, aSy);
103 0 : mAngle = 0.f;
104 0 : mOriginX = 0.f;
105 0 : mOriginY = 0.f;
106 0 : }
107 :
108 : void
109 0 : nsSVGTransform::SetRotate(float aAngle, float aCx, float aCy)
110 : {
111 0 : mType = SVG_TRANSFORM_ROTATE;
112 0 : mMatrix = gfxMatrix::Translation(aCx, aCy)
113 0 : .PreRotate(aAngle*kRadPerDegree)
114 0 : .PreTranslate(-aCx, -aCy);
115 0 : mAngle = aAngle;
116 0 : mOriginX = aCx;
117 0 : mOriginY = aCy;
118 0 : }
119 :
120 : nsresult
121 0 : nsSVGTransform::SetSkewX(float aAngle)
122 : {
123 0 : double ta = tan(aAngle*kRadPerDegree);
124 0 : NS_ENSURE_FINITE(ta, NS_ERROR_RANGE_ERR);
125 :
126 0 : mType = SVG_TRANSFORM_SKEWX;
127 0 : mMatrix = gfxMatrix();
128 0 : mMatrix._21 = ta;
129 0 : mAngle = aAngle;
130 0 : mOriginX = 0.f;
131 0 : mOriginY = 0.f;
132 0 : return NS_OK;
133 : }
134 :
135 : nsresult
136 0 : nsSVGTransform::SetSkewY(float aAngle)
137 : {
138 0 : double ta = tan(aAngle*kRadPerDegree);
139 0 : NS_ENSURE_FINITE(ta, NS_ERROR_RANGE_ERR);
140 :
141 0 : mType = SVG_TRANSFORM_SKEWY;
142 0 : mMatrix = gfxMatrix();
143 0 : mMatrix._12 = ta;
144 0 : mAngle = aAngle;
145 0 : mOriginX = 0.f;
146 0 : mOriginY = 0.f;
147 0 : return NS_OK;
148 : }
149 :
150 0 : SVGTransformSMILData::SVGTransformSMILData(const nsSVGTransform& aTransform)
151 0 : : mTransformType(aTransform.Type())
152 : {
153 0 : MOZ_ASSERT(mTransformType >= SVG_TRANSFORM_MATRIX &&
154 : mTransformType <= SVG_TRANSFORM_SKEWY,
155 : "Unexpected transform type");
156 :
157 0 : for (uint32_t i = 0; i < NUM_STORED_PARAMS; ++i) {
158 0 : mParams[i] = 0.f;
159 : }
160 :
161 0 : switch (mTransformType) {
162 : case SVG_TRANSFORM_MATRIX: {
163 0 : const gfxMatrix& mx = aTransform.GetMatrix();
164 0 : mParams[0] = static_cast<float>(mx._11);
165 0 : mParams[1] = static_cast<float>(mx._12);
166 0 : mParams[2] = static_cast<float>(mx._21);
167 0 : mParams[3] = static_cast<float>(mx._22);
168 0 : mParams[4] = static_cast<float>(mx._31);
169 0 : mParams[5] = static_cast<float>(mx._32);
170 0 : break;
171 : }
172 : case SVG_TRANSFORM_TRANSLATE: {
173 0 : const gfxMatrix& mx = aTransform.GetMatrix();
174 0 : mParams[0] = static_cast<float>(mx._31);
175 0 : mParams[1] = static_cast<float>(mx._32);
176 0 : break;
177 : }
178 : case SVG_TRANSFORM_SCALE: {
179 0 : const gfxMatrix& mx = aTransform.GetMatrix();
180 0 : mParams[0] = static_cast<float>(mx._11);
181 0 : mParams[1] = static_cast<float>(mx._22);
182 0 : break;
183 : }
184 : case SVG_TRANSFORM_ROTATE:
185 0 : mParams[0] = aTransform.Angle();
186 0 : aTransform.GetRotationOrigin(mParams[1], mParams[2]);
187 0 : break;
188 :
189 : case SVG_TRANSFORM_SKEWX:
190 : case SVG_TRANSFORM_SKEWY:
191 0 : mParams[0] = aTransform.Angle();
192 0 : break;
193 :
194 : default:
195 0 : NS_NOTREACHED("Unexpected transform type");
196 0 : break;
197 : }
198 0 : }
199 :
200 : nsSVGTransform
201 0 : SVGTransformSMILData::ToSVGTransform() const
202 : {
203 0 : nsSVGTransform result;
204 :
205 0 : switch (mTransformType) {
206 : case SVG_TRANSFORM_MATRIX:
207 0 : result.SetMatrix(gfxMatrix(mParams[0], mParams[1],
208 0 : mParams[2], mParams[3],
209 0 : mParams[4], mParams[5]));
210 0 : break;
211 :
212 : case SVG_TRANSFORM_TRANSLATE:
213 0 : result.SetTranslate(mParams[0], mParams[1]);
214 0 : break;
215 :
216 : case SVG_TRANSFORM_SCALE:
217 0 : result.SetScale(mParams[0], mParams[1]);
218 0 : break;
219 :
220 : case SVG_TRANSFORM_ROTATE:
221 0 : result.SetRotate(mParams[0], mParams[1], mParams[2]);
222 0 : break;
223 :
224 : case SVG_TRANSFORM_SKEWX:
225 0 : result.SetSkewX(mParams[0]);
226 0 : break;
227 :
228 : case SVG_TRANSFORM_SKEWY:
229 0 : result.SetSkewY(mParams[0]);
230 0 : break;
231 :
232 : default:
233 0 : NS_NOTREACHED("Unexpected transform type");
234 0 : break;
235 : }
236 0 : return result;
237 : }
238 :
239 : } // namespace mozilla
|