1/* 2 * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org> 3 * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Library General Public License for more details. 14 * 15 * You should have received a copy of the GNU Library General Public License 16 * along with this library; see the file COPYING.LIB. If not, write to 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * Boston, MA 02110-1301, USA. 19 */ 20 21#include "config.h" 22#include "SVGTransform.h" 23 24#include "FloatConversion.h" 25#include "FloatPoint.h" 26#include "FloatSize.h" 27#include "SVGAngle.h" 28#include "SVGSVGElement.h" 29#include <wtf/MathExtras.h> 30#include <wtf/text/StringBuilder.h> 31#include <wtf/text/WTFString.h> 32 33namespace WebCore { 34 35SVGTransform::SVGTransform() 36 : m_type(SVG_TRANSFORM_UNKNOWN) 37 , m_angle(0) 38{ 39} 40 41SVGTransform::SVGTransform(SVGTransformType type, ConstructionMode mode) 42 : m_type(type) 43 , m_angle(0) 44{ 45 if (mode == ConstructZeroTransform) 46 m_matrix = AffineTransform(0, 0, 0, 0, 0, 0); 47} 48 49SVGTransform::SVGTransform(const AffineTransform& matrix) 50 : m_type(SVG_TRANSFORM_MATRIX) 51 , m_angle(0) 52 , m_matrix(matrix) 53{ 54} 55 56void SVGTransform::setMatrix(const AffineTransform& matrix) 57{ 58 m_type = SVG_TRANSFORM_MATRIX; 59 m_angle = 0; 60 m_matrix = matrix; 61} 62 63void SVGTransform::updateSVGMatrix() 64{ 65 // The underlying matrix has been changed, alter the transformation type. 66 // Spec: In case the matrix object is changed directly (i.e., without using the methods on the SVGTransform interface itself) 67 // then the type of the SVGTransform changes to SVG_TRANSFORM_MATRIX. 68 m_type = SVG_TRANSFORM_MATRIX; 69 m_angle = 0; 70} 71 72void SVGTransform::setTranslate(float tx, float ty) 73{ 74 m_type = SVG_TRANSFORM_TRANSLATE; 75 m_angle = 0; 76 77 m_matrix.makeIdentity(); 78 m_matrix.translate(tx, ty); 79} 80 81FloatPoint SVGTransform::translate() const 82{ 83 return FloatPoint::narrowPrecision(m_matrix.e(), m_matrix.f()); 84} 85 86void SVGTransform::setScale(float sx, float sy) 87{ 88 m_type = SVG_TRANSFORM_SCALE; 89 m_angle = 0; 90 m_center = FloatPoint(); 91 92 m_matrix.makeIdentity(); 93 m_matrix.scaleNonUniform(sx, sy); 94} 95 96FloatSize SVGTransform::scale() const 97{ 98 return FloatSize::narrowPrecision(m_matrix.a(), m_matrix.d()); 99} 100 101void SVGTransform::setRotate(float angle, float cx, float cy) 102{ 103 m_type = SVG_TRANSFORM_ROTATE; 104 m_angle = angle; 105 m_center = FloatPoint(cx, cy); 106 107 // TODO: toString() implementation, which can show cx, cy (need to be stored?) 108 m_matrix.makeIdentity(); 109 m_matrix.translate(cx, cy); 110 m_matrix.rotate(angle); 111 m_matrix.translate(-cx, -cy); 112} 113 114void SVGTransform::setSkewX(float angle) 115{ 116 m_type = SVG_TRANSFORM_SKEWX; 117 m_angle = angle; 118 119 m_matrix.makeIdentity(); 120 m_matrix.skewX(angle); 121} 122 123void SVGTransform::setSkewY(float angle) 124{ 125 m_type = SVG_TRANSFORM_SKEWY; 126 m_angle = angle; 127 128 m_matrix.makeIdentity(); 129 m_matrix.skewY(angle); 130} 131 132const String& SVGTransform::transformTypePrefixForParsing(SVGTransformType type) 133{ 134 switch (type) { 135 case SVG_TRANSFORM_UNKNOWN: 136 return emptyString(); 137 case SVG_TRANSFORM_MATRIX: { 138 DEPRECATED_DEFINE_STATIC_LOCAL(String, matrixString, (ASCIILiteral("matrix("))); 139 return matrixString; 140 } 141 case SVG_TRANSFORM_TRANSLATE: { 142 DEPRECATED_DEFINE_STATIC_LOCAL(String, translateString, (ASCIILiteral("translate("))); 143 return translateString; 144 } 145 case SVG_TRANSFORM_SCALE: { 146 DEPRECATED_DEFINE_STATIC_LOCAL(String, scaleString, (ASCIILiteral("scale("))); 147 return scaleString; 148 } 149 case SVG_TRANSFORM_ROTATE: { 150 DEPRECATED_DEFINE_STATIC_LOCAL(String, rotateString, (ASCIILiteral("rotate("))); 151 return rotateString; 152 } 153 case SVG_TRANSFORM_SKEWX: { 154 DEPRECATED_DEFINE_STATIC_LOCAL(String, skewXString, (ASCIILiteral("skewX("))); 155 return skewXString; 156 } 157 case SVG_TRANSFORM_SKEWY: { 158 DEPRECATED_DEFINE_STATIC_LOCAL(String, skewYString, (ASCIILiteral("skewY("))); 159 return skewYString; 160 } 161 } 162 163 ASSERT_NOT_REACHED(); 164 return emptyString(); 165} 166 167String SVGTransform::valueAsString() const 168{ 169 const String& prefix = transformTypePrefixForParsing(m_type); 170 switch (m_type) { 171 case SVG_TRANSFORM_UNKNOWN: 172 return prefix; 173 case SVG_TRANSFORM_MATRIX: { 174 StringBuilder builder; 175 builder.append(prefix); 176 builder.appendNumber(m_matrix.a()); 177 builder.append(' '); 178 builder.appendNumber(m_matrix.b()); 179 builder.append(' '); 180 builder.appendNumber(m_matrix.c()); 181 builder.append(' '); 182 builder.appendNumber(m_matrix.d()); 183 builder.append(' '); 184 builder.appendNumber(m_matrix.e()); 185 builder.append(' '); 186 builder.appendNumber(m_matrix.f()); 187 builder.append(')'); 188 return builder.toString(); 189 } 190 case SVG_TRANSFORM_TRANSLATE: { 191 StringBuilder builder; 192 builder.append(prefix); 193 builder.appendNumber(m_matrix.e()); 194 builder.append(' '); 195 builder.appendNumber(m_matrix.f()); 196 builder.append(')'); 197 return builder.toString(); 198 } 199 case SVG_TRANSFORM_SCALE: { 200 StringBuilder builder; 201 builder.append(prefix); 202 builder.appendNumber(m_matrix.xScale()); 203 builder.append(' '); 204 builder.appendNumber(m_matrix.yScale()); 205 builder.append(')'); 206 return builder.toString(); 207 } 208 case SVG_TRANSFORM_ROTATE: { 209 double angleInRad = deg2rad(m_angle); 210 double cosAngle = cos(angleInRad); 211 double sinAngle = sin(angleInRad); 212 float cx = narrowPrecisionToFloat(cosAngle != 1 ? (m_matrix.e() * (1 - cosAngle) - m_matrix.f() * sinAngle) / (1 - cosAngle) / 2 : 0); 213 float cy = narrowPrecisionToFloat(cosAngle != 1 ? (m_matrix.e() * sinAngle / (1 - cosAngle) + m_matrix.f()) / 2 : 0); 214 StringBuilder builder; 215 builder.append(prefix); 216 builder.appendNumber(m_angle); 217 if (cx || cy) { 218 builder.append(' '); 219 builder.appendNumber(cx); 220 builder.append(' '); 221 builder.appendNumber(cy); 222 } 223 builder.append(')'); 224 return builder.toString(); 225 } 226 case SVG_TRANSFORM_SKEWX: 227 case SVG_TRANSFORM_SKEWY: { 228 StringBuilder builder; 229 builder.append(prefix); 230 builder.appendNumber(m_angle); 231 builder.append(')'); 232 return builder.toString(); 233 } 234 } 235 236 ASSERT_NOT_REACHED(); 237 return emptyString(); 238} 239 240} // namespace WebCore 241