2 Copyright (C) 2007 Eric Seidel <eric@webkit.org>
4 This file is part of the WebKit project
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.
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.
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.
24 #include "SVGTransformDistance.h"
26 #include "FloatConversion.h"
27 #include "FloatPoint.h"
28 #include "FloatSize.h"
29 #include "SVGTransform.h"
35 SVGTransformDistance::SVGTransformDistance()
36 : m_type(SVGTransform::SVG_TRANSFORM_UNKNOWN
)
43 SVGTransformDistance::SVGTransformDistance(SVGTransform::SVGTransformType type
, float angle
, float cx
, float cy
, const TransformationMatrix
& transform
)
48 , m_transform(transform
)
52 SVGTransformDistance::SVGTransformDistance(const SVGTransform
& fromSVGTransform
, const SVGTransform
& toSVGTransform
)
53 : m_type(fromSVGTransform
.type())
58 ASSERT(m_type
== toSVGTransform
.type());
61 case SVGTransform::SVG_TRANSFORM_UNKNOWN
:
63 case SVGTransform::SVG_TRANSFORM_MATRIX
:
64 // FIXME: need to be able to subtract to matrices
66 case SVGTransform::SVG_TRANSFORM_ROTATE
:
68 FloatSize centerDistance
= toSVGTransform
.rotationCenter() - fromSVGTransform
.rotationCenter();
69 m_angle
= toSVGTransform
.angle() - fromSVGTransform
.angle();
70 m_cx
= centerDistance
.width();
71 m_cy
= centerDistance
.height();
74 case SVGTransform::SVG_TRANSFORM_TRANSLATE
:
76 FloatSize translationDistance
= toSVGTransform
.translate() - fromSVGTransform
.translate();
77 m_transform
.translate(translationDistance
.width(), translationDistance
.height());
80 case SVGTransform::SVG_TRANSFORM_SCALE
:
82 float scaleX
= toSVGTransform
.scale().width() - fromSVGTransform
.scale().width();
83 float scaleY
= toSVGTransform
.scale().height() - fromSVGTransform
.scale().height();
84 m_transform
.scaleNonUniform(scaleX
, scaleY
);
87 case SVGTransform::SVG_TRANSFORM_SKEWX
:
88 case SVGTransform::SVG_TRANSFORM_SKEWY
:
89 m_angle
= toSVGTransform
.angle() - fromSVGTransform
.angle();
94 SVGTransformDistance
SVGTransformDistance::scaledDistance(float scaleFactor
) const
97 case SVGTransform::SVG_TRANSFORM_UNKNOWN
:
98 return SVGTransformDistance();
99 case SVGTransform::SVG_TRANSFORM_ROTATE
:
100 return SVGTransformDistance(m_type
, m_angle
* scaleFactor
, m_cx
* scaleFactor
, m_cy
* scaleFactor
, TransformationMatrix());
101 case SVGTransform::SVG_TRANSFORM_SCALE
:
102 case SVGTransform::SVG_TRANSFORM_MATRIX
:
103 return SVGTransformDistance(m_type
, m_angle
* scaleFactor
, m_cx
* scaleFactor
, m_cy
* scaleFactor
, TransformationMatrix(m_transform
).scale(scaleFactor
));
104 case SVGTransform::SVG_TRANSFORM_TRANSLATE
:
106 TransformationMatrix
newTransform(m_transform
);
107 newTransform
.setE(m_transform
.e() * scaleFactor
);
108 newTransform
.setF(m_transform
.f() * scaleFactor
);
109 return SVGTransformDistance(m_type
, 0, 0, 0, newTransform
);
111 case SVGTransform::SVG_TRANSFORM_SKEWX
:
112 case SVGTransform::SVG_TRANSFORM_SKEWY
:
113 return SVGTransformDistance(m_type
, m_angle
* scaleFactor
, m_cx
* scaleFactor
, m_cy
* scaleFactor
, TransformationMatrix());
116 ASSERT_NOT_REACHED();
117 return SVGTransformDistance();
120 SVGTransform
SVGTransformDistance::addSVGTransforms(const SVGTransform
& first
, const SVGTransform
& second
)
122 ASSERT(first
.type() == second
.type());
124 SVGTransform transform
;
126 switch (first
.type()) {
127 case SVGTransform::SVG_TRANSFORM_UNKNOWN
:
128 return SVGTransform();
129 case SVGTransform::SVG_TRANSFORM_ROTATE
:
131 transform
.setRotate(first
.angle() + second
.angle(), first
.rotationCenter().x() + second
.rotationCenter().x(),
132 first
.rotationCenter().y() + second
.rotationCenter().y());
135 case SVGTransform::SVG_TRANSFORM_MATRIX
:
136 transform
.setMatrix(first
.matrix() * second
.matrix());
138 case SVGTransform::SVG_TRANSFORM_TRANSLATE
:
140 float dx
= first
.translate().x() + second
.translate().x();
141 float dy
= first
.translate().y() + second
.translate().y();
142 transform
.setTranslate(dx
, dy
);
145 case SVGTransform::SVG_TRANSFORM_SCALE
:
147 FloatSize scale
= first
.scale() + second
.scale();
148 transform
.setScale(scale
.width(), scale
.height());
151 case SVGTransform::SVG_TRANSFORM_SKEWX
:
152 transform
.setSkewX(first
.angle() + second
.angle());
154 case SVGTransform::SVG_TRANSFORM_SKEWY
:
155 transform
.setSkewY(first
.angle() + second
.angle());
159 ASSERT_NOT_REACHED();
160 return SVGTransform();
163 void SVGTransformDistance::addSVGTransform(const SVGTransform
& transform
, bool absoluteValue
)
165 // If this is the first add, set the type for this SVGTransformDistance
166 if (m_type
== SVGTransform::SVG_TRANSFORM_UNKNOWN
)
167 m_type
= transform
.type();
169 ASSERT(m_type
== transform
.type());
172 case SVGTransform::SVG_TRANSFORM_UNKNOWN
:
174 case SVGTransform::SVG_TRANSFORM_MATRIX
:
175 m_transform
*= transform
.matrix(); // FIXME: what does 'distance' between two transforms mean? how should we respect 'absoluteValue' here?
177 case SVGTransform::SVG_TRANSFORM_ROTATE
:
178 m_angle
+= absoluteValue
? fabsf(transform
.angle()) : transform
.angle();
179 m_cx
+= absoluteValue
? fabsf(transform
.rotationCenter().x()) : transform
.rotationCenter().x();
180 m_cy
+= absoluteValue
? fabsf(transform
.rotationCenter().y()) : transform
.rotationCenter().y();
182 case SVGTransform::SVG_TRANSFORM_TRANSLATE
:
184 float dx
= absoluteValue
? fabsf(transform
.translate().x()) : transform
.translate().x();
185 float dy
= absoluteValue
? fabsf(transform
.translate().y()) : transform
.translate().y();
186 m_transform
.translate(dx
, dy
);
189 case SVGTransform::SVG_TRANSFORM_SCALE
:
191 float scaleX
= absoluteValue
? fabsf(transform
.scale().width()) : transform
.scale().width();
192 float scaleY
= absoluteValue
? fabsf(transform
.scale().height()) : transform
.scale().height();
193 m_transform
.scaleNonUniform(scaleX
, scaleY
);
196 case SVGTransform::SVG_TRANSFORM_SKEWX
:
197 case SVGTransform::SVG_TRANSFORM_SKEWY
:
198 m_angle
+= absoluteValue
? fabsf(transform
.angle()) : transform
.angle();
202 ASSERT_NOT_REACHED();
206 SVGTransform
SVGTransformDistance::addToSVGTransform(const SVGTransform
& transform
) const
208 ASSERT(m_type
== transform
.type() || transform
== SVGTransform());
210 SVGTransform
newTransform(transform
);
213 case SVGTransform::SVG_TRANSFORM_UNKNOWN
:
214 return SVGTransform();
215 case SVGTransform::SVG_TRANSFORM_MATRIX
:
216 return SVGTransform(transform
.matrix() * m_transform
);
217 case SVGTransform::SVG_TRANSFORM_TRANSLATE
:
219 FloatPoint translation
= transform
.translate();
220 translation
+= FloatSize::narrowPrecision(m_transform
.e(), m_transform
.f());
221 newTransform
.setTranslate(translation
.x(), translation
.y());
224 case SVGTransform::SVG_TRANSFORM_SCALE
:
226 FloatSize scale
= transform
.scale();
227 scale
+= FloatSize::narrowPrecision(m_transform
.a(), m_transform
.d());
228 newTransform
.setScale(scale
.width(), scale
.height());
231 case SVGTransform::SVG_TRANSFORM_ROTATE
:
233 // FIXME: I'm not certain the translation is calculated correctly here
234 FloatPoint center
= transform
.rotationCenter();
235 newTransform
.setRotate(transform
.angle() + m_angle
,
240 case SVGTransform::SVG_TRANSFORM_SKEWX
:
241 newTransform
.setSkewX(transform
.angle() + m_angle
);
243 case SVGTransform::SVG_TRANSFORM_SKEWY
:
244 newTransform
.setSkewY(transform
.angle() + m_angle
);
248 ASSERT_NOT_REACHED();
249 return SVGTransform();
252 bool SVGTransformDistance::isZero() const
254 return (m_transform
== TransformationMatrix() && m_angle
== 0);
257 float SVGTransformDistance::distance() const
260 case SVGTransform::SVG_TRANSFORM_UNKNOWN
:
262 case SVGTransform::SVG_TRANSFORM_ROTATE
:
263 return sqrtf(m_angle
* m_angle
+ m_cx
* m_cx
+ m_cy
* m_cy
);
264 case SVGTransform::SVG_TRANSFORM_MATRIX
:
265 return 0.0f
; // I'm not quite sure yet what distance between two matrices means.
266 case SVGTransform::SVG_TRANSFORM_SCALE
:
267 return static_cast<float>(sqrt(m_transform
.a() * m_transform
.a() + m_transform
.d() * m_transform
.d()));
268 case SVGTransform::SVG_TRANSFORM_TRANSLATE
:
269 return static_cast<float>(sqrt(m_transform
.e() * m_transform
.e() + m_transform
.f() * m_transform
.f()));
270 case SVGTransform::SVG_TRANSFORM_SKEWX
:
271 case SVGTransform::SVG_TRANSFORM_SKEWY
:
274 ASSERT_NOT_REACHED();