1 /* 2 * Copyright (C) 2007 Eric Seidel <eric (at) 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 22 #include "core/svg/SVGTransformDistance.h" 23 24 #include "core/platform/graphics/FloatPoint.h" 25 #include "core/platform/graphics/FloatSize.h" 26 #include "core/svg/SVGTransform.h" 27 28 #include <math.h> 29 30 namespace WebCore { 31 32 SVGTransformDistance::SVGTransformDistance() 33 : m_type(SVGTransform::SVG_TRANSFORM_UNKNOWN) 34 , m_angle(0) 35 , m_cx(0) 36 , m_cy(0) 37 { 38 } 39 40 SVGTransformDistance::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 49 SVGTransformDistance::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 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 61 break; 62 case SVGTransform::SVG_TRANSFORM_ROTATE: { 63 FloatSize centerDistance = toSVGTransform.rotationCenter() - fromSVGTransform.rotationCenter(); 64 m_angle = toSVGTransform.angle() - fromSVGTransform.angle(); 65 m_cx = centerDistance.width(); 66 m_cy = centerDistance.height(); 67 break; 68 } 69 case SVGTransform::SVG_TRANSFORM_TRANSLATE: { 70 FloatSize translationDistance = toSVGTransform.translate() - fromSVGTransform.translate(); 71 m_transform.translate(translationDistance.width(), translationDistance.height()); 72 break; 73 } 74 case SVGTransform::SVG_TRANSFORM_SCALE: { 75 float scaleX = toSVGTransform.scale().width() - fromSVGTransform.scale().width(); 76 float scaleY = toSVGTransform.scale().height() - fromSVGTransform.scale().height(); 77 m_transform.scaleNonUniform(scaleX, scaleY); 78 break; 79 } 80 case SVGTransform::SVG_TRANSFORM_SKEWX: 81 case SVGTransform::SVG_TRANSFORM_SKEWY: 82 m_angle = toSVGTransform.angle() - fromSVGTransform.angle(); 83 break; 84 } 85 } 86 87 SVGTransformDistance SVGTransformDistance::scaledDistance(float scaleFactor) const 88 { 89 switch (m_type) { 90 case SVGTransform::SVG_TRANSFORM_MATRIX: 91 ASSERT_NOT_REACHED(); 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 return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform(m_transform).scale(scaleFactor)); 98 case SVGTransform::SVG_TRANSFORM_TRANSLATE: { 99 AffineTransform newTransform(m_transform); 100 newTransform.setE(m_transform.e() * scaleFactor); 101 newTransform.setF(m_transform.f() * scaleFactor); 102 return SVGTransformDistance(m_type, 0, 0, 0, newTransform); 103 } 104 case SVGTransform::SVG_TRANSFORM_SKEWX: 105 case SVGTransform::SVG_TRANSFORM_SKEWY: 106 return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform()); 107 } 108 109 ASSERT_NOT_REACHED(); 110 return SVGTransformDistance(); 111 } 112 113 SVGTransform SVGTransformDistance::addSVGTransforms(const SVGTransform& first, const SVGTransform& second, unsigned repeatCount) 114 { 115 ASSERT(first.type() == second.type()); 116 117 SVGTransform transform; 118 119 switch (first.type()) { 120 case SVGTransform::SVG_TRANSFORM_MATRIX: 121 ASSERT_NOT_REACHED(); 122 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 123 return SVGTransform(); 124 case SVGTransform::SVG_TRANSFORM_ROTATE: { 125 transform.setRotate(first.angle() + second.angle() * repeatCount, first.rotationCenter().x() + second.rotationCenter().x() * repeatCount, first.rotationCenter().y() + second.rotationCenter().y() * repeatCount); 126 return transform; 127 } 128 case SVGTransform::SVG_TRANSFORM_TRANSLATE: { 129 float dx = first.translate().x() + second.translate().x() * repeatCount; 130 float dy = first.translate().y() + second.translate().y() * repeatCount; 131 transform.setTranslate(dx, dy); 132 return transform; 133 } 134 case SVGTransform::SVG_TRANSFORM_SCALE: { 135 FloatSize scale = second.scale(); 136 scale.scale(repeatCount); 137 scale += first.scale(); 138 transform.setScale(scale.width(), scale.height()); 139 return transform; 140 } 141 case SVGTransform::SVG_TRANSFORM_SKEWX: 142 transform.setSkewX(first.angle() + second.angle() * repeatCount); 143 return transform; 144 case SVGTransform::SVG_TRANSFORM_SKEWY: 145 transform.setSkewY(first.angle() + second.angle() * repeatCount); 146 return transform; 147 } 148 ASSERT_NOT_REACHED(); 149 return SVGTransform(); 150 } 151 152 SVGTransform SVGTransformDistance::addToSVGTransform(const SVGTransform& transform) const 153 { 154 ASSERT(m_type == transform.type() || transform == SVGTransform()); 155 156 SVGTransform newTransform(transform); 157 158 switch (m_type) { 159 case SVGTransform::SVG_TRANSFORM_MATRIX: 160 ASSERT_NOT_REACHED(); 161 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 162 return SVGTransform(); 163 case SVGTransform::SVG_TRANSFORM_TRANSLATE: { 164 FloatPoint translation = transform.translate(); 165 translation += FloatSize::narrowPrecision(m_transform.e(), m_transform.f()); 166 newTransform.setTranslate(translation.x(), translation.y()); 167 return newTransform; 168 } 169 case SVGTransform::SVG_TRANSFORM_SCALE: { 170 FloatSize scale = transform.scale(); 171 scale += FloatSize::narrowPrecision(m_transform.a(), m_transform.d()); 172 newTransform.setScale(scale.width(), scale.height()); 173 return newTransform; 174 } 175 case SVGTransform::SVG_TRANSFORM_ROTATE: { 176 FloatPoint center = transform.rotationCenter(); 177 newTransform.setRotate(transform.angle() + m_angle, center.x() + m_cx, center.y() + m_cy); 178 return newTransform; 179 } 180 case SVGTransform::SVG_TRANSFORM_SKEWX: 181 newTransform.setSkewX(transform.angle() + m_angle); 182 return newTransform; 183 case SVGTransform::SVG_TRANSFORM_SKEWY: 184 newTransform.setSkewY(transform.angle() + m_angle); 185 return newTransform; 186 } 187 188 ASSERT_NOT_REACHED(); 189 return SVGTransform(); 190 } 191 192 bool SVGTransformDistance::isZero() const 193 { 194 return m_transform.isIdentity() && !m_angle; 195 } 196 197 float SVGTransformDistance::distance() const 198 { 199 switch (m_type) { 200 case SVGTransform::SVG_TRANSFORM_MATRIX: 201 ASSERT_NOT_REACHED(); 202 case SVGTransform::SVG_TRANSFORM_UNKNOWN: 203 return 0; 204 case SVGTransform::SVG_TRANSFORM_ROTATE: 205 return sqrtf(m_angle * m_angle + m_cx * m_cx + m_cy * m_cy); 206 case SVGTransform::SVG_TRANSFORM_SCALE: 207 return static_cast<float>(sqrt(m_transform.a() * m_transform.a() + m_transform.d() * m_transform.d())); 208 case SVGTransform::SVG_TRANSFORM_TRANSLATE: 209 return static_cast<float>(sqrt(m_transform.e() * m_transform.e() + m_transform.f() * m_transform.f())); 210 case SVGTransform::SVG_TRANSFORM_SKEWX: 211 case SVGTransform::SVG_TRANSFORM_SKEWY: 212 return m_angle; 213 } 214 ASSERT_NOT_REACHED(); 215 return 0; 216 } 217 218 } 219