KHtml

SVGTransformDistance.cpp
1 /*
2  Copyright (C) 2007 Eric Seidel <[email protected]>
3 
4  This file is part of the WebKit project
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 "wtf/Platform.h"
23 #if ENABLE(SVG)
24 #include "SVGTransformDistance.h"
25 
26 #include "FloatConversion.h"
27 #include "FloatPoint.h"
28 #include "FloatSize.h"
29 
30 #include <math.h>
31 
32 namespace WebCore
33 {
34 
35 SVGTransformDistance::SVGTransformDistance()
36  : m_type(SVGTransform::SVG_TRANSFORM_UNKNOWN)
37  , m_angle(0)
38 {
39 }
40 
41 SVGTransformDistance::SVGTransformDistance(SVGTransform::SVGTransformType type, float angle, float cx, float cy, const AffineTransform &transform)
42  : m_type(type)
43  , m_angle(angle)
44  , m_cx(cx)
45  , m_cy(cy)
46  , m_transform(transform)
47 {
48 }
49 
50 SVGTransformDistance::SVGTransformDistance(const SVGTransform &fromSVGTransform, const SVGTransform &toSVGTransform)
51  : m_type(fromSVGTransform.type())
52  , m_angle(0)
53  , m_cx(0)
54  , m_cy(0)
55 {
56  ASSERT(m_type == toSVGTransform.type());
57 
58  switch (m_type) {
59  case SVGTransform::SVG_TRANSFORM_UNKNOWN:
60  return;
61  case SVGTransform::SVG_TRANSFORM_MATRIX:
62  // FIXME: need to be able to subtract to matrices
63  return;
64  case SVGTransform::SVG_TRANSFORM_ROTATE: {
65  FloatSize centerDistance = toSVGTransform.rotationCenter() - fromSVGTransform.rotationCenter();
66  m_angle = toSVGTransform.angle() - fromSVGTransform.angle();
67  m_cx = centerDistance.width();
68  m_cy = centerDistance.height();
69  return;
70  }
71  case SVGTransform::SVG_TRANSFORM_TRANSLATE: {
72  FloatSize translationDistance = toSVGTransform.translate() - fromSVGTransform.translate();
73  m_transform.translate(translationDistance.width(), translationDistance.height());
74  return;
75  }
76  case SVGTransform::SVG_TRANSFORM_SCALE: {
77  float scaleX = toSVGTransform.scale().width() - fromSVGTransform.scale().width();
78  float scaleY = toSVGTransform.scale().height() - fromSVGTransform.scale().height();
79  m_transform.scale(scaleX, scaleY);
80  return;
81  }
82  case SVGTransform::SVG_TRANSFORM_SKEWX:
83  case SVGTransform::SVG_TRANSFORM_SKEWY:
84  m_angle = toSVGTransform.angle() - fromSVGTransform.angle();
85  return;
86  }
87 }
88 
89 SVGTransformDistance SVGTransformDistance::scaledDistance(float scaleFactor) const
90 {
91  switch (m_type) {
92  case SVGTransform::SVG_TRANSFORM_UNKNOWN:
93  return SVGTransformDistance();
94  case SVGTransform::SVG_TRANSFORM_ROTATE:
95  return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform());
96  case SVGTransform::SVG_TRANSFORM_SCALE:
97  case SVGTransform::SVG_TRANSFORM_MATRIX:
98  return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform(m_transform).scale(scaleFactor));
99  case SVGTransform::SVG_TRANSFORM_TRANSLATE: {
100  AffineTransform newTransform(m_transform);
101  newTransform.setE(m_transform.e() * scaleFactor);
102  newTransform.setF(m_transform.f() * scaleFactor);
103  return SVGTransformDistance(m_type, 0, 0, 0, newTransform);
104  }
105  case SVGTransform::SVG_TRANSFORM_SKEWX:
106  case SVGTransform::SVG_TRANSFORM_SKEWY:
107  return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform());
108  }
109 
110  ASSERT_NOT_REACHED();
111  return SVGTransformDistance();
112 }
113 
114 SVGTransform SVGTransformDistance::addSVGTransforms(const SVGTransform &first, const SVGTransform &second)
115 {
116  ASSERT(first.type() == second.type());
117 
118  SVGTransform transform;
119 
120  switch (first.type()) {
121  case SVGTransform::SVG_TRANSFORM_UNKNOWN:
122  return SVGTransform();
123  case SVGTransform::SVG_TRANSFORM_ROTATE: {
124  transform.setRotate(first.angle() + second.angle(), first.rotationCenter().x() + second.rotationCenter().x(),
125  first.rotationCenter().y() + second.rotationCenter().y());
126  return transform;
127  }
128  case SVGTransform::SVG_TRANSFORM_MATRIX:
129  transform.setMatrix(first.matrix() * second.matrix());
130  return transform;
131  case SVGTransform::SVG_TRANSFORM_TRANSLATE: {
132  float dx = first.translate().x() + second.translate().x();
133  float dy = first.translate().y() + second.translate().y();
134  transform.setTranslate(dx, dy);
135  return transform;
136  }
137  case SVGTransform::SVG_TRANSFORM_SCALE: {
138  FloatSize scale = first.scale() + second.scale();
139  transform.setScale(scale.width(), scale.height());
140  return transform;
141  }
142  case SVGTransform::SVG_TRANSFORM_SKEWX:
143  transform.setSkewX(first.angle() + second.angle());
144  return transform;
145  case SVGTransform::SVG_TRANSFORM_SKEWY:
146  transform.setSkewY(first.angle() + second.angle());
147  return transform;
148  }
149 
150  ASSERT_NOT_REACHED();
151  return SVGTransform();
152 }
153 
154 void SVGTransformDistance::addSVGTransform(const SVGTransform &transform, bool absoluteValue)
155 {
156  // If this is the first add, set the type for this SVGTransformDistance
157  if (m_type == SVGTransform::SVG_TRANSFORM_UNKNOWN) {
158  m_type = transform.type();
159  }
160 
161  ASSERT(m_type == transform.type());
162 
163  switch (m_type) {
164  case SVGTransform::SVG_TRANSFORM_UNKNOWN:
165  return;
166  case SVGTransform::SVG_TRANSFORM_MATRIX:
167  m_transform *= transform.matrix(); // FIXME: what does 'distance' between two transforms mean? how should we respect 'absoluteValue' here?
168  return;
169  case SVGTransform::SVG_TRANSFORM_ROTATE:
170  m_angle += absoluteValue ? fabsf(transform.angle()) : transform.angle();
171  m_cx += absoluteValue ? fabsf(transform.rotationCenter().x()) : transform.rotationCenter().x();
172  m_cy += absoluteValue ? fabsf(transform.rotationCenter().y()) : transform.rotationCenter().y();
173  // fall through
174  case SVGTransform::SVG_TRANSFORM_TRANSLATE: {
175  float dx = absoluteValue ? fabsf(transform.translate().x()) : transform.translate().x();
176  float dy = absoluteValue ? fabsf(transform.translate().y()) : transform.translate().y();
177  m_transform.translate(dx, dy);
178  return;
179  }
180  case SVGTransform::SVG_TRANSFORM_SCALE: {
181  float scaleX = absoluteValue ? fabsf(transform.scale().width()) : transform.scale().width();
182  float scaleY = absoluteValue ? fabsf(transform.scale().height()) : transform.scale().height();
183  m_transform.scale(scaleX, scaleY);
184  return;
185  }
186  case SVGTransform::SVG_TRANSFORM_SKEWX:
187  case SVGTransform::SVG_TRANSFORM_SKEWY:
188  m_angle += absoluteValue ? fabsf(transform.angle()) : transform.angle();
189  return;
190  }
191 
192  ASSERT_NOT_REACHED();
193  return;
194 }
195 
196 SVGTransform SVGTransformDistance::addToSVGTransform(const SVGTransform &transform) const
197 {
198  ASSERT(m_type == transform.type() || transform == SVGTransform());
199 
200  SVGTransform newTransform(transform);
201 
202  switch (m_type) {
203  case SVGTransform::SVG_TRANSFORM_UNKNOWN:
204  return SVGTransform();
205  case SVGTransform::SVG_TRANSFORM_MATRIX:
206  return SVGTransform(transform.matrix() * m_transform);
207  case SVGTransform::SVG_TRANSFORM_TRANSLATE: {
208  FloatPoint translation = transform.translate();
209  translation += FloatSize::narrowPrecision(m_transform.e(), m_transform.f());
210  newTransform.setTranslate(translation.x(), translation.y());
211  return newTransform;
212  }
213  case SVGTransform::SVG_TRANSFORM_SCALE: {
214  FloatSize scale = transform.scale();
215  scale += FloatSize::narrowPrecision(m_transform.a(), m_transform.d());
216  newTransform.setScale(scale.width(), scale.height());
217  return newTransform;
218  }
219  case SVGTransform::SVG_TRANSFORM_ROTATE: {
220  // FIXME: I'm not certain the translation is calculated correctly here
221  FloatPoint center = transform.rotationCenter();
222  newTransform.setRotate(transform.angle() + m_angle,
223  center.x() + m_cx,
224  center.y() + m_cy);
225  return newTransform;
226  }
227  case SVGTransform::SVG_TRANSFORM_SKEWX:
228  newTransform.setSkewX(transform.angle() + m_angle);
229  return newTransform;
230  case SVGTransform::SVG_TRANSFORM_SKEWY:
231  newTransform.setSkewY(transform.angle() + m_angle);
232  return newTransform;
233  }
234 
235  ASSERT_NOT_REACHED();
236  return SVGTransform();
237 }
238 
239 bool SVGTransformDistance::isZero() const
240 {
241  return (m_transform == AffineTransform() && m_angle == 0);
242 }
243 
244 float SVGTransformDistance::distance() const
245 {
246  switch (m_type) {
247  case SVGTransform::SVG_TRANSFORM_UNKNOWN:
248  return 0.0f;
249  case SVGTransform::SVG_TRANSFORM_ROTATE:
250  return sqrtf(m_angle * m_angle + m_cx * m_cx + m_cy * m_cy);
251  case SVGTransform::SVG_TRANSFORM_MATRIX:
252  return 0.0f; // I'm not quite sure yet what distance between two matrices means.
253  case SVGTransform::SVG_TRANSFORM_SCALE:
254  return static_cast<float>(sqrt(m_transform.a() * m_transform.a() + m_transform.d() * m_transform.d()));
255  case SVGTransform::SVG_TRANSFORM_TRANSLATE:
256  return static_cast<float>(sqrt(m_transform.e() * m_transform.e() + m_transform.f() * m_transform.f()));
257  case SVGTransform::SVG_TRANSFORM_SKEWX:
258  case SVGTransform::SVG_TRANSFORM_SKEWY:
259  return m_angle;
260  }
261  ASSERT_NOT_REACHED();
262  return 0.0f;
263 }
264 
265 }
266 
267 #endif
KDOCTOOLS_EXPORT QString transform(const QString &file, const QString &stylesheet, const QVector< const char * > &params=QVector< const char * >())
Type type(const QSqlDatabase &db)
QTextStream & center(QTextStream &stream)
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Oct 16 2021 22:48:02 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.