• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 WebCore {
30 
SVGTransform()31 SVGTransform::SVGTransform()
32     : m_type(SVG_TRANSFORM_UNKNOWN)
33     , m_angle(0)
34 {
35 }
36 
SVGTransform(SVGTransformType type,ConstructionMode mode)37 SVGTransform::SVGTransform(SVGTransformType type, ConstructionMode mode)
38     : m_type(type)
39     , m_angle(0)
40 {
41     if (mode == ConstructZeroTransform)
42         m_matrix = AffineTransform(0, 0, 0, 0, 0, 0);
43 }
44 
SVGTransform(const AffineTransform & matrix)45 SVGTransform::SVGTransform(const AffineTransform& matrix)
46     : m_type(SVG_TRANSFORM_MATRIX)
47     , m_angle(0)
48     , m_matrix(matrix)
49 {
50 }
51 
setMatrix(const AffineTransform & matrix)52 void SVGTransform::setMatrix(const AffineTransform& matrix)
53 {
54     m_type = SVG_TRANSFORM_MATRIX;
55     m_angle = 0;
56     m_matrix = matrix;
57 }
58 
updateSVGMatrix()59 void SVGTransform::updateSVGMatrix()
60 {
61     // The underlying matrix has been changed, alter the transformation type.
62     // Spec: In case the matrix object is changed directly (i.e., without using the methods on the SVGTransform interface itself)
63     // then the type of the SVGTransform changes to SVG_TRANSFORM_MATRIX.
64     m_type = SVG_TRANSFORM_MATRIX;
65     m_angle = 0;
66 }
67 
setTranslate(float tx,float ty)68 void SVGTransform::setTranslate(float tx, float ty)
69 {
70     m_type = SVG_TRANSFORM_TRANSLATE;
71     m_angle = 0;
72 
73     m_matrix.makeIdentity();
74     m_matrix.translate(tx, ty);
75 }
76 
translate() const77 FloatPoint SVGTransform::translate() const
78 {
79     return FloatPoint::narrowPrecision(m_matrix.e(), m_matrix.f());
80 }
81 
setScale(float sx,float sy)82 void SVGTransform::setScale(float sx, float sy)
83 {
84     m_type = SVG_TRANSFORM_SCALE;
85     m_angle = 0;
86     m_center = FloatPoint();
87 
88     m_matrix.makeIdentity();
89     m_matrix.scaleNonUniform(sx, sy);
90 }
91 
scale() const92 FloatSize SVGTransform::scale() const
93 {
94     return FloatSize::narrowPrecision(m_matrix.a(), m_matrix.d());
95 }
96 
setRotate(float angle,float cx,float cy)97 void SVGTransform::setRotate(float angle, float cx, float cy)
98 {
99     m_type = SVG_TRANSFORM_ROTATE;
100     m_angle = angle;
101     m_center = FloatPoint(cx, cy);
102 
103     // TODO: toString() implementation, which can show cx, cy (need to be stored?)
104     m_matrix.makeIdentity();
105     m_matrix.translate(cx, cy);
106     m_matrix.rotate(angle);
107     m_matrix.translate(-cx, -cy);
108 }
109 
setSkewX(float angle)110 void SVGTransform::setSkewX(float angle)
111 {
112     m_type = SVG_TRANSFORM_SKEWX;
113     m_angle = angle;
114 
115     m_matrix.makeIdentity();
116     m_matrix.skewX(angle);
117 }
118 
setSkewY(float angle)119 void SVGTransform::setSkewY(float angle)
120 {
121     m_type = SVG_TRANSFORM_SKEWY;
122     m_angle = angle;
123 
124     m_matrix.makeIdentity();
125     m_matrix.skewY(angle);
126 }
127 
transformTypePrefixForParsing(SVGTransformType type)128 const String& SVGTransform::transformTypePrefixForParsing(SVGTransformType type)
129 {
130     switch (type) {
131     case SVG_TRANSFORM_UNKNOWN:
132         return emptyString();
133     case SVG_TRANSFORM_MATRIX: {
134         DEFINE_STATIC_LOCAL(String, matrixString, ("matrix("));
135         return matrixString;
136     }
137     case SVG_TRANSFORM_TRANSLATE: {
138         DEFINE_STATIC_LOCAL(String, translateString, ("translate("));
139         return translateString;
140     }
141     case SVG_TRANSFORM_SCALE: {
142         DEFINE_STATIC_LOCAL(String, scaleString, ("scale("));
143         return scaleString;
144     }
145     case SVG_TRANSFORM_ROTATE: {
146         DEFINE_STATIC_LOCAL(String, rotateString, ("rotate("));
147         return rotateString;
148     }
149     case SVG_TRANSFORM_SKEWX: {
150         DEFINE_STATIC_LOCAL(String, skewXString, ("skewX("));
151         return skewXString;
152     }
153     case SVG_TRANSFORM_SKEWY: {
154         DEFINE_STATIC_LOCAL(String, skewYString, ("skewY("));
155         return skewYString;
156     }
157     }
158 
159     ASSERT_NOT_REACHED();
160     return emptyString();
161 }
162 
valueAsString() const163 String SVGTransform::valueAsString() const
164 {
165     const String& prefix = transformTypePrefixForParsing(m_type);
166     switch (m_type) {
167     case SVG_TRANSFORM_UNKNOWN:
168         return prefix;
169     case SVG_TRANSFORM_MATRIX: {
170         StringBuilder builder;
171         builder.append(prefix + String::number(m_matrix.a()) + ' ' + String::number(m_matrix.b()) + ' ' + String::number(m_matrix.c()) + ' ' +
172                        String::number(m_matrix.d()) + ' ' + String::number(m_matrix.e()) + ' ' + String::number(m_matrix.f()) + ')');
173         return builder.toString();
174     }
175     case SVG_TRANSFORM_TRANSLATE:
176         return prefix + String::number(m_matrix.e()) + ' ' + String::number(m_matrix.f()) + ')';
177     case SVG_TRANSFORM_SCALE:
178         return prefix + String::number(m_matrix.xScale()) + ' ' + String::number(m_matrix.yScale()) + ')';
179     case SVG_TRANSFORM_ROTATE: {
180         double angleInRad = deg2rad(m_angle);
181         double cosAngle = cos(angleInRad);
182         double sinAngle = sin(angleInRad);
183         float cx = narrowPrecisionToFloat(cosAngle != 1 ? (m_matrix.e() * (1 - cosAngle) - m_matrix.f() * sinAngle) / (1 - cosAngle) / 2 : 0);
184         float cy = narrowPrecisionToFloat(cosAngle != 1 ? (m_matrix.e() * sinAngle / (1 - cosAngle) + m_matrix.f()) / 2 : 0);
185         if (cx || cy)
186             return prefix + String::number(m_angle) + ' ' + String::number(cx) + ' ' + String::number(cy) + ')';
187         return prefix + String::number(m_angle) + ')';
188     }
189     case SVG_TRANSFORM_SKEWX:
190         return prefix + String::number(m_angle) + ')';
191     case SVG_TRANSFORM_SKEWY:
192         return prefix + String::number(m_angle) + ')';
193     }
194 
195     ASSERT_NOT_REACHED();
196     return emptyString();
197 }
198 
199 } // namespace WebCore
200