Merge mozilla-central to autoland on a CLOSED TREE
[gecko.git] / dom / svg / SVGTransform.cpp
blobc993253c4c6ce003663b42e1f62b25ab8f938628
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 #include "SVGTransform.h"
9 #include "nsError.h"
10 #include "nsContentUtils.h" // for NS_ENSURE_FINITE
11 #include "nsTextFormatter.h"
13 namespace {
14 const double kRadPerDegree = 2.0 * M_PI / 360.0;
15 } // namespace
17 namespace mozilla {
19 using namespace dom::SVGTransform_Binding;
21 void SVGTransform::GetValueAsString(nsAString& aValue) const {
22 switch (mType) {
23 case SVG_TRANSFORM_TRANSLATE:
24 // The spec say that if Y is not provided, it is assumed to be zero.
25 if (mMatrix._32 != 0)
26 nsTextFormatter::ssprintf(aValue, u"translate(%g, %g)", mMatrix._31,
27 mMatrix._32);
28 else
29 nsTextFormatter::ssprintf(aValue, u"translate(%g)", mMatrix._31);
30 break;
31 case SVG_TRANSFORM_ROTATE:
32 if (mOriginX != 0.0f || mOriginY != 0.0f)
33 nsTextFormatter::ssprintf(aValue, u"rotate(%g, %g, %g)", mAngle,
34 mOriginX, mOriginY);
35 else
36 nsTextFormatter::ssprintf(aValue, u"rotate(%g)", mAngle);
37 break;
38 case SVG_TRANSFORM_SCALE:
39 if (mMatrix._11 != mMatrix._22)
40 nsTextFormatter::ssprintf(aValue, u"scale(%g, %g)", mMatrix._11,
41 mMatrix._22);
42 else
43 nsTextFormatter::ssprintf(aValue, u"scale(%g)", mMatrix._11);
44 break;
45 case SVG_TRANSFORM_SKEWX:
46 nsTextFormatter::ssprintf(aValue, u"skewX(%g)", mAngle);
47 break;
48 case SVG_TRANSFORM_SKEWY:
49 nsTextFormatter::ssprintf(aValue, u"skewY(%g)", mAngle);
50 break;
51 case SVG_TRANSFORM_MATRIX:
52 nsTextFormatter::ssprintf(aValue, u"matrix(%g, %g, %g, %g, %g, %g)",
53 mMatrix._11, mMatrix._12, mMatrix._21,
54 mMatrix._22, mMatrix._31, mMatrix._32);
55 break;
56 default:
57 aValue.Truncate();
58 NS_ERROR("unknown transformation type");
59 break;
63 void SVGTransform::SetMatrix(const gfxMatrix& aMatrix) {
64 mType = SVG_TRANSFORM_MATRIX;
65 mMatrix = aMatrix;
66 // We set the other members here too, since operator== requires it and
67 // the DOM requires it for mAngle.
68 mAngle = 0.f;
69 mOriginX = 0.f;
70 mOriginY = 0.f;
73 void SVGTransform::SetTranslate(float aTx, float aTy) {
74 mType = SVG_TRANSFORM_TRANSLATE;
75 mMatrix = gfxMatrix::Translation(aTx, aTy);
76 mAngle = 0.f;
77 mOriginX = 0.f;
78 mOriginY = 0.f;
81 void SVGTransform::SetScale(float aSx, float aSy) {
82 mType = SVG_TRANSFORM_SCALE;
83 mMatrix = gfxMatrix::Scaling(aSx, aSy);
84 mAngle = 0.f;
85 mOriginX = 0.f;
86 mOriginY = 0.f;
89 void SVGTransform::SetRotate(float aAngle, float aCx, float aCy) {
90 mType = SVG_TRANSFORM_ROTATE;
91 mMatrix = gfxMatrix::Translation(aCx, aCy)
92 .PreRotate(aAngle * kRadPerDegree)
93 .PreTranslate(-aCx, -aCy);
94 mAngle = aAngle;
95 mOriginX = aCx;
96 mOriginY = aCy;
99 nsresult SVGTransform::SetSkewX(float aAngle) {
100 double ta = tan(aAngle * kRadPerDegree);
101 // No one actually cares about the exact error return type here.
102 NS_ENSURE_FINITE(ta, NS_ERROR_INVALID_ARG);
104 mType = SVG_TRANSFORM_SKEWX;
105 mMatrix = gfxMatrix();
106 mMatrix._21 = ta;
107 mAngle = aAngle;
108 mOriginX = 0.f;
109 mOriginY = 0.f;
110 return NS_OK;
113 nsresult SVGTransform::SetSkewY(float aAngle) {
114 double ta = tan(aAngle * kRadPerDegree);
115 // No one actually cares about the exact error return type here.
116 NS_ENSURE_FINITE(ta, NS_ERROR_INVALID_ARG);
118 mType = SVG_TRANSFORM_SKEWY;
119 mMatrix = gfxMatrix();
120 mMatrix._12 = ta;
121 mAngle = aAngle;
122 mOriginX = 0.f;
123 mOriginY = 0.f;
124 return NS_OK;
127 SVGTransformSMILData::SVGTransformSMILData(const SVGTransform& aTransform)
128 : mTransformType(aTransform.Type()) {
129 MOZ_ASSERT(mTransformType >= SVG_TRANSFORM_MATRIX &&
130 mTransformType <= SVG_TRANSFORM_SKEWY,
131 "Unexpected transform type");
133 for (uint32_t i = 0; i < NUM_STORED_PARAMS; ++i) {
134 mParams[i] = 0.f;
137 switch (mTransformType) {
138 case SVG_TRANSFORM_MATRIX: {
139 const gfxMatrix& mx = aTransform.GetMatrix();
140 mParams[0] = static_cast<float>(mx._11);
141 mParams[1] = static_cast<float>(mx._12);
142 mParams[2] = static_cast<float>(mx._21);
143 mParams[3] = static_cast<float>(mx._22);
144 mParams[4] = static_cast<float>(mx._31);
145 mParams[5] = static_cast<float>(mx._32);
146 break;
148 case SVG_TRANSFORM_TRANSLATE: {
149 const gfxMatrix& mx = aTransform.GetMatrix();
150 mParams[0] = static_cast<float>(mx._31);
151 mParams[1] = static_cast<float>(mx._32);
152 break;
154 case SVG_TRANSFORM_SCALE: {
155 const gfxMatrix& mx = aTransform.GetMatrix();
156 mParams[0] = static_cast<float>(mx._11);
157 mParams[1] = static_cast<float>(mx._22);
158 break;
160 case SVG_TRANSFORM_ROTATE:
161 mParams[0] = aTransform.Angle();
162 aTransform.GetRotationOrigin(mParams[1], mParams[2]);
163 break;
165 case SVG_TRANSFORM_SKEWX:
166 case SVG_TRANSFORM_SKEWY:
167 mParams[0] = aTransform.Angle();
168 break;
170 default:
171 MOZ_ASSERT_UNREACHABLE("Unexpected transform type");
172 break;
176 SVGTransform SVGTransformSMILData::ToSVGTransform() const {
177 SVGTransform result;
179 switch (mTransformType) {
180 case SVG_TRANSFORM_MATRIX:
181 result.SetMatrix(gfxMatrix(mParams[0], mParams[1], mParams[2], mParams[3],
182 mParams[4], mParams[5]));
183 break;
185 case SVG_TRANSFORM_TRANSLATE:
186 result.SetTranslate(mParams[0], mParams[1]);
187 break;
189 case SVG_TRANSFORM_SCALE:
190 result.SetScale(mParams[0], mParams[1]);
191 break;
193 case SVG_TRANSFORM_ROTATE:
194 result.SetRotate(mParams[0], mParams[1], mParams[2]);
195 break;
197 case SVG_TRANSFORM_SKEWX:
198 result.SetSkewX(mParams[0]);
199 break;
201 case SVG_TRANSFORM_SKEWY:
202 result.SetSkewY(mParams[0]);
203 break;
205 default:
206 MOZ_ASSERT_UNREACHABLE("Unexpected transform type");
207 break;
209 return result;
212 } // namespace mozilla