2 * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
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.
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.
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.
22 #include "core/svg/SVGTransform.h"
24 #include "platform/FloatConversion.h"
25 #include "platform/geometry/FloatSize.h"
26 #include "wtf/MathExtras.h"
27 #include "wtf/text/StringBuilder.h"
31 SVGTransform::SVGTransform()
32 : SVGPropertyBase(classType())
33 , m_transformType(SVG_TRANSFORM_UNKNOWN)
38 SVGTransform::SVGTransform(SVGTransformType transformType, ConstructionMode mode)
39 : SVGPropertyBase(classType())
40 , m_transformType(transformType)
43 if (mode == ConstructZeroTransform)
44 m_matrix = AffineTransform(0, 0, 0, 0, 0, 0);
47 SVGTransform::SVGTransform(const AffineTransform& matrix)
48 : SVGPropertyBase(classType())
49 , m_transformType(SVG_TRANSFORM_MATRIX)
55 SVGTransform::SVGTransform(SVGTransformType transformType, float angle, const FloatPoint& center, const AffineTransform& matrix)
56 : SVGPropertyBase(classType())
57 , m_transformType(transformType)
64 SVGTransform::~SVGTransform()
68 PassRefPtr<SVGTransform> SVGTransform::clone() const
70 return adoptRef(new SVGTransform(m_transformType, m_angle, m_center, m_matrix));
73 PassRefPtr<SVGPropertyBase> SVGTransform::cloneForAnimation(const String&) const
75 // SVGTransform is never animated.
80 void SVGTransform::setMatrix(const AffineTransform& matrix)
86 void SVGTransform::onMatrixChange()
88 m_transformType = SVG_TRANSFORM_MATRIX;
92 void SVGTransform::setTranslate(float tx, float ty)
94 m_transformType = SVG_TRANSFORM_TRANSLATE;
97 m_matrix.makeIdentity();
98 m_matrix.translate(tx, ty);
101 FloatPoint SVGTransform::translate() const
103 return FloatPoint::narrowPrecision(m_matrix.e(), m_matrix.f());
106 void SVGTransform::setScale(float sx, float sy)
108 m_transformType = SVG_TRANSFORM_SCALE;
110 m_center = FloatPoint();
112 m_matrix.makeIdentity();
113 m_matrix.scaleNonUniform(sx, sy);
116 FloatSize SVGTransform::scale() const
118 return FloatSize::narrowPrecision(m_matrix.a(), m_matrix.d());
121 void SVGTransform::setRotate(float angle, float cx, float cy)
123 m_transformType = SVG_TRANSFORM_ROTATE;
125 m_center = FloatPoint(cx, cy);
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);
134 void SVGTransform::setSkewX(float angle)
136 m_transformType = SVG_TRANSFORM_SKEWX;
139 m_matrix.makeIdentity();
140 m_matrix.skewX(angle);
143 void SVGTransform::setSkewY(float angle)
145 m_transformType = SVG_TRANSFORM_SKEWY;
148 m_matrix.makeIdentity();
149 m_matrix.skewY(angle);
154 const String& transformTypePrefixForParsing(SVGTransformType type)
157 case SVG_TRANSFORM_UNKNOWN:
158 return emptyString();
159 case SVG_TRANSFORM_MATRIX: {
160 DEFINE_STATIC_LOCAL(String, matrixString, ("matrix("));
163 case SVG_TRANSFORM_TRANSLATE: {
164 DEFINE_STATIC_LOCAL(String, translateString, ("translate("));
165 return translateString;
167 case SVG_TRANSFORM_SCALE: {
168 DEFINE_STATIC_LOCAL(String, scaleString, ("scale("));
171 case SVG_TRANSFORM_ROTATE: {
172 DEFINE_STATIC_LOCAL(String, rotateString, ("rotate("));
175 case SVG_TRANSFORM_SKEWX: {
176 DEFINE_STATIC_LOCAL(String, skewXString, ("skewX("));
179 case SVG_TRANSFORM_SKEWY: {
180 DEFINE_STATIC_LOCAL(String, skewYString, ("skewY("));
185 ASSERT_NOT_REACHED();
186 return emptyString();
191 String SVGTransform::valueAsString() const
193 const String& prefix = transformTypePrefixForParsing(m_transformType);
194 switch (m_transformType) {
195 case SVG_TRANSFORM_UNKNOWN:
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();
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);
214 return prefix + String::number(m_angle) + ' ' + String::number(cx) + ' ' + String::number(cy) + ')';
215 return prefix + String::number(m_angle) + ')';
217 case SVG_TRANSFORM_SKEWX:
218 return prefix + String::number(m_angle) + ')';
219 case SVG_TRANSFORM_SKEWY:
220 return prefix + String::number(m_angle) + ')';
223 ASSERT_NOT_REACHED();
224 return emptyString();
227 void SVGTransform::add(PassRefPtrWillBeRawPtr<SVGPropertyBase>, SVGElement*)
229 // SVGTransform is not animated by itself.
230 ASSERT_NOT_REACHED();
233 void SVGTransform::calculateAnimatedValue(SVGAnimationElement*, float, unsigned, PassRefPtr<SVGPropertyBase>, PassRefPtr<SVGPropertyBase>, PassRefPtr<SVGPropertyBase>, SVGElement*)
235 // SVGTransform is not animated by itself.
236 ASSERT_NOT_REACHED();
239 float SVGTransform::calculateDistance(PassRefPtr<SVGPropertyBase>, SVGElement*)
241 // SVGTransform is not animated by itself.
242 ASSERT_NOT_REACHED();