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