ec75c1fae54d03cd0bb8bb94e02460e0f0d489cd
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / svg / SVGTransform.cpp
1 /*
2  * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #include "config.h"
22 #include "core/svg/SVGTransform.h"
23
24 #include "platform/FloatConversion.h"
25 #include "platform/geometry/FloatSize.h"
26 #include "wtf/MathExtras.h"
27 #include "wtf/text/StringBuilder.h"
28
29 namespace blink {
30
31 SVGTransform::SVGTransform()
32     : SVGPropertyBase(classType())
33     , m_transformType(SVG_TRANSFORM_UNKNOWN)
34     , m_angle(0)
35 {
36 }
37
38 SVGTransform::SVGTransform(SVGTransformType transformType, ConstructionMode mode)
39     : SVGPropertyBase(classType())
40     , m_transformType(transformType)
41     , m_angle(0)
42 {
43     if (mode == ConstructZeroTransform)
44         m_matrix = AffineTransform(0, 0, 0, 0, 0, 0);
45 }
46
47 SVGTransform::SVGTransform(const AffineTransform& matrix)
48     : SVGPropertyBase(classType())
49     , m_transformType(SVG_TRANSFORM_MATRIX)
50     , m_angle(0)
51     , m_matrix(matrix)
52 {
53 }
54
55 SVGTransform::SVGTransform(SVGTransformType transformType, float angle, const FloatPoint& center, const AffineTransform& matrix)
56     : SVGPropertyBase(classType())
57     , m_transformType(transformType)
58     , m_angle(angle)
59     , m_center(center)
60     , m_matrix(matrix)
61 {
62 }
63
64 SVGTransform::~SVGTransform()
65 {
66 }
67
68 PassRefPtr<SVGTransform> SVGTransform::clone() const
69 {
70     return adoptRef(new SVGTransform(m_transformType, m_angle, m_center, m_matrix));
71 }
72
73 PassRefPtr<SVGPropertyBase> SVGTransform::cloneForAnimation(const String&) const
74 {
75     // SVGTransform is never animated.
76     ASSERT_NOT_REACHED();
77     return nullptr;
78 }
79
80 void SVGTransform::setMatrix(const AffineTransform& matrix)
81 {
82     onMatrixChange();
83     m_matrix = matrix;
84 }
85
86 void SVGTransform::onMatrixChange()
87 {
88     m_transformType = SVG_TRANSFORM_MATRIX;
89     m_angle = 0;
90 }
91
92 void SVGTransform::setTranslate(float tx, float ty)
93 {
94     m_transformType = SVG_TRANSFORM_TRANSLATE;
95     m_angle = 0;
96
97     m_matrix.makeIdentity();
98     m_matrix.translate(tx, ty);
99 }
100
101 FloatPoint SVGTransform::translate() const
102 {
103     return FloatPoint::narrowPrecision(m_matrix.e(), m_matrix.f());
104 }
105
106 void SVGTransform::setScale(float sx, float sy)
107 {
108     m_transformType = SVG_TRANSFORM_SCALE;
109     m_angle = 0;
110     m_center = FloatPoint();
111
112     m_matrix.makeIdentity();
113     m_matrix.scaleNonUniform(sx, sy);
114 }
115
116 FloatSize SVGTransform::scale() const
117 {
118     return FloatSize::narrowPrecision(m_matrix.a(), m_matrix.d());
119 }
120
121 void SVGTransform::setRotate(float angle, float cx, float cy)
122 {
123     m_transformType = SVG_TRANSFORM_ROTATE;
124     m_angle = angle;
125     m_center = FloatPoint(cx, cy);
126
127     // TODO: toString() implementation, which can show cx, cy (need to be stored?)
128     m_matrix.makeIdentity();
129     m_matrix.translate(cx, cy);
130     m_matrix.rotate(angle);
131     m_matrix.translate(-cx, -cy);
132 }
133
134 void SVGTransform::setSkewX(float angle)
135 {
136     m_transformType = SVG_TRANSFORM_SKEWX;
137     m_angle = angle;
138
139     m_matrix.makeIdentity();
140     m_matrix.skewX(angle);
141 }
142
143 void SVGTransform::setSkewY(float angle)
144 {
145     m_transformType = SVG_TRANSFORM_SKEWY;
146     m_angle = angle;
147
148     m_matrix.makeIdentity();
149     m_matrix.skewY(angle);
150 }
151
152 namespace {
153
154 const String& transformTypePrefixForParsing(SVGTransformType type)
155 {
156     switch (type) {
157     case SVG_TRANSFORM_UNKNOWN:
158         return emptyString();
159     case SVG_TRANSFORM_MATRIX: {
160         DEFINE_STATIC_LOCAL(String, matrixString, ("matrix("));
161         return matrixString;
162     }
163     case SVG_TRANSFORM_TRANSLATE: {
164         DEFINE_STATIC_LOCAL(String, translateString, ("translate("));
165         return translateString;
166     }
167     case SVG_TRANSFORM_SCALE: {
168         DEFINE_STATIC_LOCAL(String, scaleString, ("scale("));
169         return scaleString;
170     }
171     case SVG_TRANSFORM_ROTATE: {
172         DEFINE_STATIC_LOCAL(String, rotateString, ("rotate("));
173         return rotateString;
174     }
175     case SVG_TRANSFORM_SKEWX: {
176         DEFINE_STATIC_LOCAL(String, skewXString, ("skewX("));
177         return skewXString;
178     }
179     case SVG_TRANSFORM_SKEWY: {
180         DEFINE_STATIC_LOCAL(String, skewYString, ("skewY("));
181         return skewYString;
182     }
183     }
184
185     ASSERT_NOT_REACHED();
186     return emptyString();
187 }
188
189 }
190
191 String SVGTransform::valueAsString() const
192 {
193     const String& prefix = transformTypePrefixForParsing(m_transformType);
194     switch (m_transformType) {
195     case SVG_TRANSFORM_UNKNOWN:
196         return prefix;
197     case SVG_TRANSFORM_MATRIX: {
198         StringBuilder builder;
199         builder.append(prefix + String::number(m_matrix.a()) + ' ' + String::number(m_matrix.b()) + ' ' + String::number(m_matrix.c()) + ' ' +
200                        String::number(m_matrix.d()) + ' ' + String::number(m_matrix.e()) + ' ' + String::number(m_matrix.f()) + ')');
201         return builder.toString();
202     }
203     case SVG_TRANSFORM_TRANSLATE:
204         return prefix + String::number(m_matrix.e()) + ' ' + String::number(m_matrix.f()) + ')';
205     case SVG_TRANSFORM_SCALE:
206         return prefix + String::number(m_matrix.a()) + ' ' + String::number(m_matrix.d()) + ')';
207     case SVG_TRANSFORM_ROTATE: {
208         double angleInRad = deg2rad(m_angle);
209         double cosAngle = cos(angleInRad);
210         double sinAngle = sin(angleInRad);
211         float cx = narrowPrecisionToFloat(cosAngle != 1 ? (m_matrix.e() * (1 - cosAngle) - m_matrix.f() * sinAngle) / (1 - cosAngle) / 2 : 0);
212         float cy = narrowPrecisionToFloat(cosAngle != 1 ? (m_matrix.e() * sinAngle / (1 - cosAngle) + m_matrix.f()) / 2 : 0);
213         if (cx || cy)
214             return prefix + String::number(m_angle) + ' ' + String::number(cx) + ' ' + String::number(cy) + ')';
215         return prefix + String::number(m_angle) + ')';
216     }
217     case SVG_TRANSFORM_SKEWX:
218         return prefix + String::number(m_angle) + ')';
219     case SVG_TRANSFORM_SKEWY:
220         return prefix + String::number(m_angle) + ')';
221     }
222
223     ASSERT_NOT_REACHED();
224     return emptyString();
225 }
226
227 void SVGTransform::add(PassRefPtrWillBeRawPtr<SVGPropertyBase>, SVGElement*)
228 {
229     // SVGTransform is not animated by itself.
230     ASSERT_NOT_REACHED();
231 }
232
233 void SVGTransform::calculateAnimatedValue(SVGAnimationElement*, float, unsigned, PassRefPtr<SVGPropertyBase>, PassRefPtr<SVGPropertyBase>, PassRefPtr<SVGPropertyBase>, SVGElement*)
234 {
235     // SVGTransform is not animated by itself.
236     ASSERT_NOT_REACHED();
237 }
238
239 float SVGTransform::calculateDistance(PassRefPtr<SVGPropertyBase>, SVGElement*)
240 {
241     // SVGTransform is not animated by itself.
242     ASSERT_NOT_REACHED();
243
244     return -1;
245 }
246
247 } // namespace blink