KHTML
SVGTransformDistance.cpp
Go to the documentation of this file.
00001 /* 00002 Copyright (C) 2007 Eric Seidel <eric@webkit.org> 00003 00004 This file is part of the WebKit project 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #include "config.h" 00023 #include "wtf/Platform.h" 00024 #if ENABLE(SVG) 00025 #include "SVGTransformDistance.h" 00026 00027 #include "FloatConversion.h" 00028 #include "FloatPoint.h" 00029 #include "FloatSize.h" 00030 #include "SVGTransform.h" 00031 00032 #include <math.h> 00033 00034 namespace WebCore { 00035 00036 SVGTransformDistance::SVGTransformDistance() 00037 : m_type(SVGTransform::SVG_TRANSFORM_UNKNOWN) 00038 , m_angle(0) 00039 { 00040 } 00041 00042 SVGTransformDistance::SVGTransformDistance(SVGTransform::SVGTransformType type, float angle, float cx, float cy, const AffineTransform& transform) 00043 : m_type(type) 00044 , m_angle(angle) 00045 , m_cx(cx) 00046 , m_cy(cy) 00047 , m_transform(transform) 00048 { 00049 } 00050 00051 SVGTransformDistance::SVGTransformDistance(const SVGTransform& fromSVGTransform, const SVGTransform& toSVGTransform) 00052 : m_type(fromSVGTransform.type()) 00053 , m_angle(0) 00054 , m_cx(0) 00055 , m_cy(0) 00056 { 00057 ASSERT(m_type == toSVGTransform.type()); 00058 00059 switch (m_type) { 00060 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 00061 return; 00062 case SVGTransform::SVG_TRANSFORM_MATRIX: 00063 // FIXME: need to be able to subtract to matrices 00064 return; 00065 case SVGTransform::SVG_TRANSFORM_ROTATE: 00066 { 00067 FloatSize centerDistance = toSVGTransform.rotationCenter() - fromSVGTransform.rotationCenter(); 00068 m_angle = toSVGTransform.angle() - fromSVGTransform.angle(); 00069 m_cx = centerDistance.width(); 00070 m_cy = centerDistance.height(); 00071 return; 00072 } 00073 case SVGTransform::SVG_TRANSFORM_TRANSLATE: 00074 { 00075 FloatSize translationDistance = toSVGTransform.translate() - fromSVGTransform.translate(); 00076 m_transform.translate(translationDistance.width(), translationDistance.height()); 00077 return; 00078 } 00079 case SVGTransform::SVG_TRANSFORM_SCALE: 00080 { 00081 float scaleX = toSVGTransform.scale().width() - fromSVGTransform.scale().width(); 00082 float scaleY = toSVGTransform.scale().height() - fromSVGTransform.scale().height(); 00083 m_transform.scale(scaleX, scaleY); 00084 return; 00085 } 00086 case SVGTransform::SVG_TRANSFORM_SKEWX: 00087 case SVGTransform::SVG_TRANSFORM_SKEWY: 00088 m_angle = toSVGTransform.angle() - fromSVGTransform.angle(); 00089 return; 00090 } 00091 } 00092 00093 SVGTransformDistance SVGTransformDistance::scaledDistance(float scaleFactor) const 00094 { 00095 switch (m_type) { 00096 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 00097 return SVGTransformDistance(); 00098 case SVGTransform::SVG_TRANSFORM_ROTATE: 00099 return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform()); 00100 case SVGTransform::SVG_TRANSFORM_SCALE: 00101 case SVGTransform::SVG_TRANSFORM_MATRIX: 00102 return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform(m_transform).scale(scaleFactor)); 00103 case SVGTransform::SVG_TRANSFORM_TRANSLATE: 00104 { 00105 AffineTransform newTransform(m_transform); 00106 newTransform.setE(m_transform.e() * scaleFactor); 00107 newTransform.setF(m_transform.f() * scaleFactor); 00108 return SVGTransformDistance(m_type, 0, 0, 0, newTransform); 00109 } 00110 case SVGTransform::SVG_TRANSFORM_SKEWX: 00111 case SVGTransform::SVG_TRANSFORM_SKEWY: 00112 return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform()); 00113 } 00114 00115 ASSERT_NOT_REACHED(); 00116 return SVGTransformDistance(); 00117 } 00118 00119 SVGTransform SVGTransformDistance::addSVGTransforms(const SVGTransform& first, const SVGTransform& second) 00120 { 00121 ASSERT(first.type() == second.type()); 00122 00123 SVGTransform transform; 00124 00125 switch (first.type()) { 00126 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 00127 return SVGTransform(); 00128 case SVGTransform::SVG_TRANSFORM_ROTATE: 00129 { 00130 transform.setRotate(first.angle() + second.angle(), first.rotationCenter().x() + second.rotationCenter().x(), 00131 first.rotationCenter().y() + second.rotationCenter().y()); 00132 return transform; 00133 } 00134 case SVGTransform::SVG_TRANSFORM_MATRIX: 00135 transform.setMatrix(first.matrix() * second.matrix()); 00136 return transform; 00137 case SVGTransform::SVG_TRANSFORM_TRANSLATE: 00138 { 00139 float dx = first.translate().x() + second.translate().x(); 00140 float dy = first.translate().y() + second.translate().y(); 00141 transform.setTranslate(dx, dy); 00142 return transform; 00143 } 00144 case SVGTransform::SVG_TRANSFORM_SCALE: 00145 { 00146 FloatSize scale = first.scale() + second.scale(); 00147 transform.setScale(scale.width(), scale.height()); 00148 return transform; 00149 } 00150 case SVGTransform::SVG_TRANSFORM_SKEWX: 00151 transform.setSkewX(first.angle() + second.angle()); 00152 return transform; 00153 case SVGTransform::SVG_TRANSFORM_SKEWY: 00154 transform.setSkewY(first.angle() + second.angle()); 00155 return transform; 00156 } 00157 00158 ASSERT_NOT_REACHED(); 00159 return SVGTransform(); 00160 } 00161 00162 void SVGTransformDistance::addSVGTransform(const SVGTransform& transform, bool absoluteValue) 00163 { 00164 // If this is the first add, set the type for this SVGTransformDistance 00165 if (m_type == SVGTransform::SVG_TRANSFORM_UNKNOWN) 00166 m_type = transform.type(); 00167 00168 ASSERT(m_type == transform.type()); 00169 00170 switch (m_type) { 00171 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 00172 return; 00173 case SVGTransform::SVG_TRANSFORM_MATRIX: 00174 m_transform *= transform.matrix(); // FIXME: what does 'distance' between two transforms mean? how should we respect 'absoluteValue' here? 00175 return; 00176 case SVGTransform::SVG_TRANSFORM_ROTATE: 00177 m_angle += absoluteValue ? fabsf(transform.angle()) : transform.angle(); 00178 m_cx += absoluteValue ? fabsf(transform.rotationCenter().x()) : transform.rotationCenter().x(); 00179 m_cy += absoluteValue ? fabsf(transform.rotationCenter().y()) : transform.rotationCenter().y(); 00180 // fall through 00181 case SVGTransform::SVG_TRANSFORM_TRANSLATE: 00182 { 00183 float dx = absoluteValue ? fabsf(transform.translate().x()) : transform.translate().x(); 00184 float dy = absoluteValue ? fabsf(transform.translate().y()) : transform.translate().y(); 00185 m_transform.translate(dx, dy); 00186 return; 00187 } 00188 case SVGTransform::SVG_TRANSFORM_SCALE: 00189 { 00190 float scaleX = absoluteValue ? fabsf(transform.scale().width()) : transform.scale().width(); 00191 float scaleY = absoluteValue ? fabsf(transform.scale().height()) : transform.scale().height(); 00192 m_transform.scale(scaleX, scaleY); 00193 return; 00194 } 00195 case SVGTransform::SVG_TRANSFORM_SKEWX: 00196 case SVGTransform::SVG_TRANSFORM_SKEWY: 00197 m_angle += absoluteValue ? fabsf(transform.angle()) : transform.angle(); 00198 return; 00199 } 00200 00201 ASSERT_NOT_REACHED(); 00202 return; 00203 } 00204 00205 SVGTransform SVGTransformDistance::addToSVGTransform(const SVGTransform& transform) const 00206 { 00207 ASSERT(m_type == transform.type() || transform == SVGTransform()); 00208 00209 SVGTransform newTransform(transform); 00210 00211 switch (m_type) { 00212 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 00213 return SVGTransform(); 00214 case SVGTransform::SVG_TRANSFORM_MATRIX: 00215 return SVGTransform(transform.matrix() * m_transform); 00216 case SVGTransform::SVG_TRANSFORM_TRANSLATE: 00217 { 00218 FloatPoint translation = transform.translate(); 00219 translation += FloatSize::narrowPrecision(m_transform.e(), m_transform.f()); 00220 newTransform.setTranslate(translation.x(), translation.y()); 00221 return newTransform; 00222 } 00223 case SVGTransform::SVG_TRANSFORM_SCALE: 00224 { 00225 FloatSize scale = transform.scale(); 00226 scale += FloatSize::narrowPrecision(m_transform.a(), m_transform.d()); 00227 newTransform.setScale(scale.width(), scale.height()); 00228 return newTransform; 00229 } 00230 case SVGTransform::SVG_TRANSFORM_ROTATE: 00231 { 00232 // FIXME: I'm not certain the translation is calculated correctly here 00233 FloatPoint center = transform.rotationCenter(); 00234 newTransform.setRotate(transform.angle() + m_angle, 00235 center.x() + m_cx, 00236 center.y() + m_cy); 00237 return newTransform; 00238 } 00239 case SVGTransform::SVG_TRANSFORM_SKEWX: 00240 newTransform.setSkewX(transform.angle() + m_angle); 00241 return newTransform; 00242 case SVGTransform::SVG_TRANSFORM_SKEWY: 00243 newTransform.setSkewY(transform.angle() + m_angle); 00244 return newTransform; 00245 } 00246 00247 ASSERT_NOT_REACHED(); 00248 return SVGTransform(); 00249 } 00250 00251 bool SVGTransformDistance::isZero() const 00252 { 00253 return (m_transform == AffineTransform() && m_angle == 0); 00254 } 00255 00256 float SVGTransformDistance::distance() const 00257 { 00258 switch (m_type) { 00259 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 00260 return 0.0f; 00261 case SVGTransform::SVG_TRANSFORM_ROTATE: 00262 return sqrtf(m_angle * m_angle + m_cx * m_cx + m_cy * m_cy); 00263 case SVGTransform::SVG_TRANSFORM_MATRIX: 00264 return 0.0f; // I'm not quite sure yet what distance between two matrices means. 00265 case SVGTransform::SVG_TRANSFORM_SCALE: 00266 return static_cast<float>(sqrt(m_transform.a() * m_transform.a() + m_transform.d() * m_transform.d())); 00267 case SVGTransform::SVG_TRANSFORM_TRANSLATE: 00268 return static_cast<float>(sqrt(m_transform.e() * m_transform.e() + m_transform.f() * m_transform.f())); 00269 case SVGTransform::SVG_TRANSFORM_SKEWX: 00270 case SVGTransform::SVG_TRANSFORM_SKEWY: 00271 return m_angle; 00272 } 00273 ASSERT_NOT_REACHED(); 00274 return 0.0f; 00275 } 00276 00277 } 00278 00279 #endif
KDE 4.6 API Reference