File indexing completed on 2024-04-28 15:24:42
0001 /* 0002 Copyright (C) 2007 Eric Seidel <eric@webkit.org> 0003 0004 This file is part of the WebKit project 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "wtf/Platform.h" 0023 #if ENABLE(SVG) 0024 #include "SVGTransformDistance.h" 0025 0026 #include "FloatConversion.h" 0027 #include "FloatPoint.h" 0028 #include "FloatSize.h" 0029 0030 #include <math.h> 0031 0032 namespace WebCore 0033 { 0034 0035 SVGTransformDistance::SVGTransformDistance() 0036 : m_type(SVGTransform::SVG_TRANSFORM_UNKNOWN) 0037 , m_angle(0) 0038 { 0039 } 0040 0041 SVGTransformDistance::SVGTransformDistance(SVGTransform::SVGTransformType type, float angle, float cx, float cy, const AffineTransform &transform) 0042 : m_type(type) 0043 , m_angle(angle) 0044 , m_cx(cx) 0045 , m_cy(cy) 0046 , m_transform(transform) 0047 { 0048 } 0049 0050 SVGTransformDistance::SVGTransformDistance(const SVGTransform &fromSVGTransform, const SVGTransform &toSVGTransform) 0051 : m_type(fromSVGTransform.type()) 0052 , m_angle(0) 0053 , m_cx(0) 0054 , m_cy(0) 0055 { 0056 ASSERT(m_type == toSVGTransform.type()); 0057 0058 switch (m_type) { 0059 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 0060 return; 0061 case SVGTransform::SVG_TRANSFORM_MATRIX: 0062 // FIXME: need to be able to subtract to matrices 0063 return; 0064 case SVGTransform::SVG_TRANSFORM_ROTATE: { 0065 FloatSize centerDistance = toSVGTransform.rotationCenter() - fromSVGTransform.rotationCenter(); 0066 m_angle = toSVGTransform.angle() - fromSVGTransform.angle(); 0067 m_cx = centerDistance.width(); 0068 m_cy = centerDistance.height(); 0069 return; 0070 } 0071 case SVGTransform::SVG_TRANSFORM_TRANSLATE: { 0072 FloatSize translationDistance = toSVGTransform.translate() - fromSVGTransform.translate(); 0073 m_transform.translate(translationDistance.width(), translationDistance.height()); 0074 return; 0075 } 0076 case SVGTransform::SVG_TRANSFORM_SCALE: { 0077 float scaleX = toSVGTransform.scale().width() - fromSVGTransform.scale().width(); 0078 float scaleY = toSVGTransform.scale().height() - fromSVGTransform.scale().height(); 0079 m_transform.scale(scaleX, scaleY); 0080 return; 0081 } 0082 case SVGTransform::SVG_TRANSFORM_SKEWX: 0083 case SVGTransform::SVG_TRANSFORM_SKEWY: 0084 m_angle = toSVGTransform.angle() - fromSVGTransform.angle(); 0085 return; 0086 } 0087 } 0088 0089 SVGTransformDistance SVGTransformDistance::scaledDistance(float scaleFactor) const 0090 { 0091 switch (m_type) { 0092 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 0093 return SVGTransformDistance(); 0094 case SVGTransform::SVG_TRANSFORM_ROTATE: 0095 return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform()); 0096 case SVGTransform::SVG_TRANSFORM_SCALE: 0097 case SVGTransform::SVG_TRANSFORM_MATRIX: 0098 return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform(m_transform).scale(scaleFactor)); 0099 case SVGTransform::SVG_TRANSFORM_TRANSLATE: { 0100 AffineTransform newTransform(m_transform); 0101 newTransform.setE(m_transform.e() * scaleFactor); 0102 newTransform.setF(m_transform.f() * scaleFactor); 0103 return SVGTransformDistance(m_type, 0, 0, 0, newTransform); 0104 } 0105 case SVGTransform::SVG_TRANSFORM_SKEWX: 0106 case SVGTransform::SVG_TRANSFORM_SKEWY: 0107 return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform()); 0108 } 0109 0110 ASSERT_NOT_REACHED(); 0111 return SVGTransformDistance(); 0112 } 0113 0114 SVGTransform SVGTransformDistance::addSVGTransforms(const SVGTransform &first, const SVGTransform &second) 0115 { 0116 ASSERT(first.type() == second.type()); 0117 0118 SVGTransform transform; 0119 0120 switch (first.type()) { 0121 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 0122 return SVGTransform(); 0123 case SVGTransform::SVG_TRANSFORM_ROTATE: { 0124 transform.setRotate(first.angle() + second.angle(), first.rotationCenter().x() + second.rotationCenter().x(), 0125 first.rotationCenter().y() + second.rotationCenter().y()); 0126 return transform; 0127 } 0128 case SVGTransform::SVG_TRANSFORM_MATRIX: 0129 transform.setMatrix(first.matrix() * second.matrix()); 0130 return transform; 0131 case SVGTransform::SVG_TRANSFORM_TRANSLATE: { 0132 float dx = first.translate().x() + second.translate().x(); 0133 float dy = first.translate().y() + second.translate().y(); 0134 transform.setTranslate(dx, dy); 0135 return transform; 0136 } 0137 case SVGTransform::SVG_TRANSFORM_SCALE: { 0138 FloatSize scale = first.scale() + second.scale(); 0139 transform.setScale(scale.width(), scale.height()); 0140 return transform; 0141 } 0142 case SVGTransform::SVG_TRANSFORM_SKEWX: 0143 transform.setSkewX(first.angle() + second.angle()); 0144 return transform; 0145 case SVGTransform::SVG_TRANSFORM_SKEWY: 0146 transform.setSkewY(first.angle() + second.angle()); 0147 return transform; 0148 } 0149 0150 ASSERT_NOT_REACHED(); 0151 return SVGTransform(); 0152 } 0153 0154 void SVGTransformDistance::addSVGTransform(const SVGTransform &transform, bool absoluteValue) 0155 { 0156 // If this is the first add, set the type for this SVGTransformDistance 0157 if (m_type == SVGTransform::SVG_TRANSFORM_UNKNOWN) { 0158 m_type = transform.type(); 0159 } 0160 0161 ASSERT(m_type == transform.type()); 0162 0163 switch (m_type) { 0164 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 0165 return; 0166 case SVGTransform::SVG_TRANSFORM_MATRIX: 0167 m_transform *= transform.matrix(); // FIXME: what does 'distance' between two transforms mean? how should we respect 'absoluteValue' here? 0168 return; 0169 case SVGTransform::SVG_TRANSFORM_ROTATE: 0170 m_angle += absoluteValue ? fabsf(transform.angle()) : transform.angle(); 0171 m_cx += absoluteValue ? fabsf(transform.rotationCenter().x()) : transform.rotationCenter().x(); 0172 m_cy += absoluteValue ? fabsf(transform.rotationCenter().y()) : transform.rotationCenter().y(); 0173 // fall through 0174 case SVGTransform::SVG_TRANSFORM_TRANSLATE: { 0175 float dx = absoluteValue ? fabsf(transform.translate().x()) : transform.translate().x(); 0176 float dy = absoluteValue ? fabsf(transform.translate().y()) : transform.translate().y(); 0177 m_transform.translate(dx, dy); 0178 return; 0179 } 0180 case SVGTransform::SVG_TRANSFORM_SCALE: { 0181 float scaleX = absoluteValue ? fabsf(transform.scale().width()) : transform.scale().width(); 0182 float scaleY = absoluteValue ? fabsf(transform.scale().height()) : transform.scale().height(); 0183 m_transform.scale(scaleX, scaleY); 0184 return; 0185 } 0186 case SVGTransform::SVG_TRANSFORM_SKEWX: 0187 case SVGTransform::SVG_TRANSFORM_SKEWY: 0188 m_angle += absoluteValue ? fabsf(transform.angle()) : transform.angle(); 0189 return; 0190 } 0191 0192 ASSERT_NOT_REACHED(); 0193 return; 0194 } 0195 0196 SVGTransform SVGTransformDistance::addToSVGTransform(const SVGTransform &transform) const 0197 { 0198 ASSERT(m_type == transform.type() || transform == SVGTransform()); 0199 0200 SVGTransform newTransform(transform); 0201 0202 switch (m_type) { 0203 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 0204 return SVGTransform(); 0205 case SVGTransform::SVG_TRANSFORM_MATRIX: 0206 return SVGTransform(transform.matrix() * m_transform); 0207 case SVGTransform::SVG_TRANSFORM_TRANSLATE: { 0208 FloatPoint translation = transform.translate(); 0209 translation += FloatSize::narrowPrecision(m_transform.e(), m_transform.f()); 0210 newTransform.setTranslate(translation.x(), translation.y()); 0211 return newTransform; 0212 } 0213 case SVGTransform::SVG_TRANSFORM_SCALE: { 0214 FloatSize scale = transform.scale(); 0215 scale += FloatSize::narrowPrecision(m_transform.a(), m_transform.d()); 0216 newTransform.setScale(scale.width(), scale.height()); 0217 return newTransform; 0218 } 0219 case SVGTransform::SVG_TRANSFORM_ROTATE: { 0220 // FIXME: I'm not certain the translation is calculated correctly here 0221 FloatPoint center = transform.rotationCenter(); 0222 newTransform.setRotate(transform.angle() + m_angle, 0223 center.x() + m_cx, 0224 center.y() + m_cy); 0225 return newTransform; 0226 } 0227 case SVGTransform::SVG_TRANSFORM_SKEWX: 0228 newTransform.setSkewX(transform.angle() + m_angle); 0229 return newTransform; 0230 case SVGTransform::SVG_TRANSFORM_SKEWY: 0231 newTransform.setSkewY(transform.angle() + m_angle); 0232 return newTransform; 0233 } 0234 0235 ASSERT_NOT_REACHED(); 0236 return SVGTransform(); 0237 } 0238 0239 bool SVGTransformDistance::isZero() const 0240 { 0241 return (m_transform == AffineTransform() && m_angle == 0); 0242 } 0243 0244 float SVGTransformDistance::distance() const 0245 { 0246 switch (m_type) { 0247 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 0248 return 0.0f; 0249 case SVGTransform::SVG_TRANSFORM_ROTATE: 0250 return sqrtf(m_angle * m_angle + m_cx * m_cx + m_cy * m_cy); 0251 case SVGTransform::SVG_TRANSFORM_MATRIX: 0252 return 0.0f; // I'm not quite sure yet what distance between two matrices means. 0253 case SVGTransform::SVG_TRANSFORM_SCALE: 0254 return static_cast<float>(sqrt(m_transform.a() * m_transform.a() + m_transform.d() * m_transform.d())); 0255 case SVGTransform::SVG_TRANSFORM_TRANSLATE: 0256 return static_cast<float>(sqrt(m_transform.e() * m_transform.e() + m_transform.f() * m_transform.f())); 0257 case SVGTransform::SVG_TRANSFORM_SKEWX: 0258 case SVGTransform::SVG_TRANSFORM_SKEWY: 0259 return m_angle; 0260 } 0261 ASSERT_NOT_REACHED(); 0262 return 0.0f; 0263 } 0264 0265 } 0266 0267 #endif