1/* 2 * Copyright (C) 2007 Eric Seidel <eric@webkit.org> 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20#include "config.h" 21#include "SVGTransformDistance.h" 22 23#include "FloatConversion.h" 24#include "FloatPoint.h" 25#include "FloatSize.h" 26#include "SVGTransform.h" 27 28#include <math.h> 29 30namespace WebCore { 31 32SVGTransformDistance::SVGTransformDistance() 33 : m_type(SVGTransform::SVG_TRANSFORM_UNKNOWN) 34 , m_angle(0) 35 , m_cx(0) 36 , m_cy(0) 37{ 38} 39 40SVGTransformDistance::SVGTransformDistance(SVGTransform::SVGTransformType type, float angle, float cx, float cy, const AffineTransform& transform) 41 : m_type(type) 42 , m_angle(angle) 43 , m_cx(cx) 44 , m_cy(cy) 45 , m_transform(transform) 46{ 47} 48 49SVGTransformDistance::SVGTransformDistance(const SVGTransform& fromSVGTransform, const SVGTransform& toSVGTransform) 50 : m_type(fromSVGTransform.type()) 51 , m_angle(0) 52 , m_cx(0) 53 , m_cy(0) 54{ 55 ASSERT(m_type == toSVGTransform.type()); 56 57 switch (m_type) { 58 case SVGTransform::SVG_TRANSFORM_MATRIX: 59 ASSERT_NOT_REACHED(); 60#if ASSERT_DISABLED 61 FALLTHROUGH; 62#endif 63 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 64 break; 65 case SVGTransform::SVG_TRANSFORM_ROTATE: { 66 FloatSize centerDistance = toSVGTransform.rotationCenter() - fromSVGTransform.rotationCenter(); 67 m_angle = toSVGTransform.angle() - fromSVGTransform.angle(); 68 m_cx = centerDistance.width(); 69 m_cy = centerDistance.height(); 70 break; 71 } 72 case SVGTransform::SVG_TRANSFORM_TRANSLATE: { 73 FloatSize translationDistance = toSVGTransform.translate() - fromSVGTransform.translate(); 74 m_transform.translate(translationDistance.width(), translationDistance.height()); 75 break; 76 } 77 case SVGTransform::SVG_TRANSFORM_SCALE: { 78 float scaleX = toSVGTransform.scale().width() - fromSVGTransform.scale().width(); 79 float scaleY = toSVGTransform.scale().height() - fromSVGTransform.scale().height(); 80 m_transform.scaleNonUniform(scaleX, scaleY); 81 break; 82 } 83 case SVGTransform::SVG_TRANSFORM_SKEWX: 84 case SVGTransform::SVG_TRANSFORM_SKEWY: 85 m_angle = toSVGTransform.angle() - fromSVGTransform.angle(); 86 break; 87 } 88} 89 90SVGTransformDistance SVGTransformDistance::scaledDistance(float scaleFactor) const 91{ 92 switch (m_type) { 93 case SVGTransform::SVG_TRANSFORM_MATRIX: 94 ASSERT_NOT_REACHED(); 95#if ASSERT_DISABLED 96 FALLTHROUGH; 97#endif 98 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 99 return SVGTransformDistance(); 100 case SVGTransform::SVG_TRANSFORM_ROTATE: 101 return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform()); 102 case SVGTransform::SVG_TRANSFORM_SCALE: 103 return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform(m_transform).scale(scaleFactor)); 104 case SVGTransform::SVG_TRANSFORM_TRANSLATE: { 105 AffineTransform newTransform(m_transform); 106 newTransform.setE(m_transform.e() * scaleFactor); 107 newTransform.setF(m_transform.f() * scaleFactor); 108 return SVGTransformDistance(m_type, 0, 0, 0, newTransform); 109 } 110 case SVGTransform::SVG_TRANSFORM_SKEWX: 111 case SVGTransform::SVG_TRANSFORM_SKEWY: 112 return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform()); 113 } 114 115 ASSERT_NOT_REACHED(); 116 return SVGTransformDistance(); 117} 118 119SVGTransform SVGTransformDistance::addSVGTransforms(const SVGTransform& first, const SVGTransform& second, unsigned repeatCount) 120{ 121 ASSERT(first.type() == second.type()); 122 123 SVGTransform transform; 124 125 switch (first.type()) { 126 case SVGTransform::SVG_TRANSFORM_MATRIX: 127 ASSERT_NOT_REACHED(); 128#if ASSERT_DISABLED 129 FALLTHROUGH; 130#endif 131 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 132 return SVGTransform(); 133 case SVGTransform::SVG_TRANSFORM_ROTATE: { 134 transform.setRotate(first.angle() + second.angle() * repeatCount, first.rotationCenter().x() + second.rotationCenter().x() * repeatCount, first.rotationCenter().y() + second.rotationCenter().y() * repeatCount); 135 return transform; 136 } 137 case SVGTransform::SVG_TRANSFORM_TRANSLATE: { 138 float dx = first.translate().x() + second.translate().x() * repeatCount; 139 float dy = first.translate().y() + second.translate().y() * repeatCount; 140 transform.setTranslate(dx, dy); 141 return transform; 142 } 143 case SVGTransform::SVG_TRANSFORM_SCALE: { 144 FloatSize scale = second.scale(); 145 scale.scale(repeatCount); 146 scale += first.scale(); 147 transform.setScale(scale.width(), scale.height()); 148 return transform; 149 } 150 case SVGTransform::SVG_TRANSFORM_SKEWX: 151 transform.setSkewX(first.angle() + second.angle() * repeatCount); 152 return transform; 153 case SVGTransform::SVG_TRANSFORM_SKEWY: 154 transform.setSkewY(first.angle() + second.angle() * repeatCount); 155 return transform; 156 } 157 ASSERT_NOT_REACHED(); 158 return SVGTransform(); 159} 160 161SVGTransform SVGTransformDistance::addToSVGTransform(const SVGTransform& transform) const 162{ 163 ASSERT(m_type == transform.type() || transform == SVGTransform()); 164 165 SVGTransform newTransform(transform); 166 167 switch (m_type) { 168 case SVGTransform::SVG_TRANSFORM_MATRIX: 169 ASSERT_NOT_REACHED(); 170#if ASSERT_DISABLED 171 FALLTHROUGH; 172#endif 173 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 174 return SVGTransform(); 175 case SVGTransform::SVG_TRANSFORM_TRANSLATE: { 176 FloatPoint translation = transform.translate(); 177 translation += FloatSize::narrowPrecision(m_transform.e(), m_transform.f()); 178 newTransform.setTranslate(translation.x(), translation.y()); 179 return newTransform; 180 } 181 case SVGTransform::SVG_TRANSFORM_SCALE: { 182 FloatSize scale = transform.scale(); 183 scale += FloatSize::narrowPrecision(m_transform.a(), m_transform.d()); 184 newTransform.setScale(scale.width(), scale.height()); 185 return newTransform; 186 } 187 case SVGTransform::SVG_TRANSFORM_ROTATE: { 188 FloatPoint center = transform.rotationCenter(); 189 newTransform.setRotate(transform.angle() + m_angle, center.x() + m_cx, center.y() + m_cy); 190 return newTransform; 191 } 192 case SVGTransform::SVG_TRANSFORM_SKEWX: 193 newTransform.setSkewX(transform.angle() + m_angle); 194 return newTransform; 195 case SVGTransform::SVG_TRANSFORM_SKEWY: 196 newTransform.setSkewY(transform.angle() + m_angle); 197 return newTransform; 198 } 199 200 ASSERT_NOT_REACHED(); 201 return SVGTransform(); 202} 203 204bool SVGTransformDistance::isZero() const 205{ 206 return m_transform.isIdentity() && !m_angle; 207} 208 209float SVGTransformDistance::distance() const 210{ 211 switch (m_type) { 212 case SVGTransform::SVG_TRANSFORM_MATRIX: 213 ASSERT_NOT_REACHED(); 214#if ASSERT_DISABLED 215 FALLTHROUGH; 216#endif 217 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 218 return 0; 219 case SVGTransform::SVG_TRANSFORM_ROTATE: 220 return sqrtf(m_angle * m_angle + m_cx * m_cx + m_cy * m_cy); 221 case SVGTransform::SVG_TRANSFORM_SCALE: 222 return static_cast<float>(sqrt(m_transform.a() * m_transform.a() + m_transform.d() * m_transform.d())); 223 case SVGTransform::SVG_TRANSFORM_TRANSLATE: 224 return static_cast<float>(sqrt(m_transform.e() * m_transform.e() + m_transform.f() * m_transform.f())); 225 case SVGTransform::SVG_TRANSFORM_SKEWX: 226 case SVGTransform::SVG_TRANSFORM_SKEWY: 227 return m_angle; 228 } 229 ASSERT_NOT_REACHED(); 230 return 0; 231} 232 233} 234