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