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