1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
3 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Mozilla SVG Project code.
17 : *
18 : * The Initial Developer of the Original Code is the Mozilla Foundation.
19 : * Portions created by the Initial Developer are Copyright (C) 2011
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Brian Birtles <birtles@gmail.com>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "SVGTransform.h"
40 : #include "nsContentUtils.h"
41 : #include "nsTextFormatter.h"
42 :
43 : namespace {
44 : const double radPerDegree = 2.0*3.1415926535 / 360.0;
45 : }
46 :
47 : namespace mozilla {
48 :
49 : void
50 0 : SVGTransform::GetValueAsString(nsAString& aValue) const
51 : {
52 : PRUnichar buf[256];
53 :
54 0 : switch (mType) {
55 : case nsIDOMSVGTransform::SVG_TRANSFORM_TRANSLATE:
56 0 : if (mMatrix.x0 != 0.0f)
57 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
58 0 : NS_LITERAL_STRING("translate(%g, %g)").get(),
59 0 : mMatrix.x0, mMatrix.y0);
60 : else
61 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
62 0 : NS_LITERAL_STRING("translate(%g)").get(),
63 0 : mMatrix.x0);
64 0 : break;
65 : case nsIDOMSVGTransform::SVG_TRANSFORM_ROTATE:
66 0 : if (mOriginX != 0.0f || mOriginY != 0.0f)
67 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
68 0 : NS_LITERAL_STRING("rotate(%g, %g, %g)").get(),
69 0 : mAngle, mOriginX, mOriginY);
70 : else
71 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
72 0 : NS_LITERAL_STRING("rotate(%g)").get(), mAngle);
73 0 : break;
74 : case nsIDOMSVGTransform::SVG_TRANSFORM_SCALE:
75 0 : if (mMatrix.xx != mMatrix.yy)
76 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
77 0 : NS_LITERAL_STRING("scale(%g, %g)").get(), mMatrix.xx, mMatrix.yy);
78 : else
79 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
80 0 : NS_LITERAL_STRING("scale(%g)").get(), mMatrix.xx);
81 0 : break;
82 : case nsIDOMSVGTransform::SVG_TRANSFORM_SKEWX:
83 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
84 0 : NS_LITERAL_STRING("skewX(%g)").get(), mAngle);
85 0 : break;
86 : case nsIDOMSVGTransform::SVG_TRANSFORM_SKEWY:
87 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
88 0 : NS_LITERAL_STRING("skewY(%g)").get(), mAngle);
89 0 : break;
90 : case nsIDOMSVGTransform::SVG_TRANSFORM_MATRIX:
91 : nsTextFormatter::snprintf(buf, sizeof(buf)/sizeof(PRUnichar),
92 0 : NS_LITERAL_STRING("matrix(%g, %g, %g, %g, %g, %g)").get(),
93 : mMatrix.xx, mMatrix.yx,
94 : mMatrix.xy, mMatrix.yy,
95 0 : mMatrix.x0, mMatrix.y0);
96 0 : break;
97 : default:
98 0 : buf[0] = '\0';
99 0 : NS_ERROR("unknown transformation type");
100 0 : break;
101 : }
102 :
103 0 : aValue.Assign(buf);
104 0 : }
105 :
106 : void
107 0 : SVGTransform::SetMatrix(const gfxMatrix& aMatrix)
108 : {
109 0 : mType = nsIDOMSVGTransform::SVG_TRANSFORM_MATRIX;
110 0 : mMatrix = aMatrix;
111 : // We set the other members here too, since operator== requires it and
112 : // the DOM requires it for mAngle.
113 0 : mAngle = 0.f;
114 0 : mOriginX = 0.f;
115 0 : mOriginY = 0.f;
116 0 : }
117 :
118 : void
119 0 : SVGTransform::SetTranslate(float aTx, float aTy)
120 : {
121 0 : mType = nsIDOMSVGTransform::SVG_TRANSFORM_TRANSLATE;
122 0 : mMatrix.Reset();
123 0 : mMatrix.x0 = aTx;
124 0 : mMatrix.y0 = aTy;
125 0 : mAngle = 0.f;
126 0 : mOriginX = 0.f;
127 0 : mOriginY = 0.f;
128 0 : }
129 :
130 : void
131 0 : SVGTransform::SetScale(float aSx, float aSy)
132 : {
133 0 : mType = nsIDOMSVGTransform::SVG_TRANSFORM_SCALE;
134 0 : mMatrix.Reset();
135 0 : mMatrix.xx = aSx;
136 0 : mMatrix.yy = aSy;
137 0 : mAngle = 0.f;
138 0 : mOriginX = 0.f;
139 0 : mOriginY = 0.f;
140 0 : }
141 :
142 : void
143 0 : SVGTransform::SetRotate(float aAngle, float aCx, float aCy)
144 : {
145 0 : mType = nsIDOMSVGTransform::SVG_TRANSFORM_ROTATE;
146 0 : mMatrix.Reset();
147 0 : mMatrix.Translate(gfxPoint(aCx, aCy));
148 0 : mMatrix.Rotate(aAngle*radPerDegree);
149 0 : mMatrix.Translate(gfxPoint(-aCx, -aCy));
150 0 : mAngle = aAngle;
151 0 : mOriginX = aCx;
152 0 : mOriginY = aCy;
153 0 : }
154 :
155 : nsresult
156 0 : SVGTransform::SetSkewX(float aAngle)
157 : {
158 0 : double ta = tan(aAngle*radPerDegree);
159 0 : NS_ENSURE_FINITE(ta, NS_ERROR_DOM_SVG_INVALID_VALUE_ERR);
160 :
161 0 : mType = nsIDOMSVGTransform::SVG_TRANSFORM_SKEWX;
162 0 : mMatrix.Reset();
163 0 : mMatrix.xy = ta;
164 0 : mAngle = aAngle;
165 0 : mOriginX = 0.f;
166 0 : mOriginY = 0.f;
167 0 : return NS_OK;
168 : }
169 :
170 : nsresult
171 0 : SVGTransform::SetSkewY(float aAngle)
172 : {
173 0 : double ta = tan(aAngle*radPerDegree);
174 0 : NS_ENSURE_FINITE(ta, NS_ERROR_DOM_SVG_INVALID_VALUE_ERR);
175 :
176 0 : mType = nsIDOMSVGTransform::SVG_TRANSFORM_SKEWY;
177 0 : mMatrix.Reset();
178 0 : mMatrix.yx = ta;
179 0 : mAngle = aAngle;
180 0 : mOriginX = 0.f;
181 0 : mOriginY = 0.f;
182 0 : return NS_OK;
183 : }
184 :
185 0 : SVGTransformSMILData::SVGTransformSMILData(const SVGTransform& aTransform)
186 0 : : mTransformType(aTransform.Type())
187 : {
188 0 : NS_ABORT_IF_FALSE(
189 : mTransformType >= nsIDOMSVGTransform::SVG_TRANSFORM_MATRIX &&
190 : mTransformType <= nsIDOMSVGTransform::SVG_TRANSFORM_SKEWY,
191 : "Unexpected transform type");
192 :
193 0 : for (PRUint32 i = 0; i < NUM_STORED_PARAMS; ++i) {
194 0 : mParams[i] = 0.f;
195 : }
196 :
197 0 : switch (mTransformType) {
198 : case nsIDOMSVGTransform::SVG_TRANSFORM_MATRIX: {
199 0 : const gfxMatrix& mx = aTransform.Matrix();
200 0 : mParams[0] = static_cast<float>(mx.xx);
201 0 : mParams[1] = static_cast<float>(mx.yx);
202 0 : mParams[2] = static_cast<float>(mx.xy);
203 0 : mParams[3] = static_cast<float>(mx.yy);
204 0 : mParams[4] = static_cast<float>(mx.x0);
205 0 : mParams[5] = static_cast<float>(mx.y0);
206 0 : break;
207 : }
208 : case nsIDOMSVGTransform::SVG_TRANSFORM_TRANSLATE: {
209 0 : const gfxMatrix& mx = aTransform.Matrix();
210 0 : mParams[0] = static_cast<float>(mx.x0);
211 0 : mParams[1] = static_cast<float>(mx.y0);
212 0 : break;
213 : }
214 : case nsIDOMSVGTransform::SVG_TRANSFORM_SCALE: {
215 0 : const gfxMatrix& mx = aTransform.Matrix();
216 0 : mParams[0] = static_cast<float>(mx.xx);
217 0 : mParams[1] = static_cast<float>(mx.yy);
218 0 : break;
219 : }
220 : case nsIDOMSVGTransform::SVG_TRANSFORM_ROTATE:
221 0 : mParams[0] = aTransform.Angle();
222 0 : aTransform.GetRotationOrigin(mParams[1], mParams[2]);
223 0 : break;
224 :
225 : case nsIDOMSVGTransform::SVG_TRANSFORM_SKEWX:
226 : case nsIDOMSVGTransform::SVG_TRANSFORM_SKEWY:
227 0 : mParams[0] = aTransform.Angle();
228 0 : break;
229 :
230 : default:
231 0 : NS_NOTREACHED("Unexpected transform type");
232 0 : break;
233 : }
234 0 : }
235 :
236 : SVGTransform
237 0 : SVGTransformSMILData::ToSVGTransform() const
238 : {
239 0 : SVGTransform result;
240 :
241 0 : switch (mTransformType) {
242 : case nsIDOMSVGTransform::SVG_TRANSFORM_MATRIX:
243 0 : result.SetMatrix(gfxMatrix(mParams[0], mParams[1],
244 0 : mParams[2], mParams[3],
245 0 : mParams[4], mParams[5]));
246 0 : break;
247 :
248 : case nsIDOMSVGTransform::SVG_TRANSFORM_TRANSLATE:
249 0 : result.SetTranslate(mParams[0], mParams[1]);
250 0 : break;
251 :
252 : case nsIDOMSVGTransform::SVG_TRANSFORM_SCALE:
253 0 : result.SetScale(mParams[0], mParams[1]);
254 0 : break;
255 :
256 : case nsIDOMSVGTransform::SVG_TRANSFORM_ROTATE:
257 0 : result.SetRotate(mParams[0], mParams[1], mParams[2]);
258 0 : break;
259 :
260 : case nsIDOMSVGTransform::SVG_TRANSFORM_SKEWX:
261 0 : result.SetSkewX(mParams[0]);
262 0 : break;
263 :
264 : case nsIDOMSVGTransform::SVG_TRANSFORM_SKEWY:
265 0 : result.SetSkewY(mParams[0]);
266 0 : break;
267 :
268 : default:
269 0 : NS_NOTREACHED("Unexpected transform type");
270 0 : break;
271 : }
272 : return result;
273 : }
274 :
275 : } // namespace mozilla
|