1 /* 2 * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann (at) kde.org> 3 * Copyright (C) 2004, 2005 Rob Buis <buis (at) 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 23 #if ENABLE(SVG) 24 #include "SVGTransform.h" 25 26 #include "FloatConversion.h" 27 #include "FloatPoint.h" 28 #include "FloatSize.h" 29 #include "SVGAngle.h" 30 #include "SVGSVGElement.h" 31 #include <wtf/MathExtras.h> 32 #include <wtf/text/StringBuilder.h> 33 #include <wtf/text/StringConcatenate.h> 34 35 namespace WebCore { 36 37 SVGTransform::SVGTransform() 38 : m_type(SVG_TRANSFORM_UNKNOWN) 39 , m_angle(0) 40 { 41 } 42 43 SVGTransform::SVGTransform(SVGTransformType type) 44 : m_type(type) 45 , m_angle(0) 46 { 47 } 48 49 SVGTransform::SVGTransform(const AffineTransform& matrix) 50 : m_type(SVG_TRANSFORM_MATRIX) 51 , m_angle(0) 52 , m_matrix(matrix) 53 { 54 } 55 56 void SVGTransform::setMatrix(const AffineTransform& matrix) 57 { 58 m_type = SVG_TRANSFORM_MATRIX; 59 m_angle = 0; 60 m_matrix = matrix; 61 } 62 63 void SVGTransform::updateMatrix() 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 72 void 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 81 FloatPoint SVGTransform::translate() const 82 { 83 return FloatPoint::narrowPrecision(m_matrix.e(), m_matrix.f()); 84 } 85 86 void 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 96 FloatSize SVGTransform::scale() const 97 { 98 return FloatSize::narrowPrecision(m_matrix.a(), m_matrix.d()); 99 } 100 101 void 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 114 void 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 123 void 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 132 String SVGTransform::valueAsString() const 133 { 134 switch (m_type) { 135 case SVG_TRANSFORM_UNKNOWN: 136 return String(); 137 case SVG_TRANSFORM_MATRIX: { 138 StringBuilder builder; 139 builder.append(makeString("matrix(", String::number(m_matrix.a()), ' ', String::number(m_matrix.b()), ' ', String::number(m_matrix.c()), ' ')); 140 builder.append(makeString(String::number(m_matrix.d()), ' ', String::number(m_matrix.e()), ' ', String::number(m_matrix.f()), ')')); 141 return builder.toString(); 142 } 143 case SVG_TRANSFORM_TRANSLATE: 144 return makeString("translate(", String::number(m_matrix.e()), ' ', String::number(m_matrix.f()), ')'); 145 case SVG_TRANSFORM_SCALE: 146 return makeString("scale(", String::number(m_matrix.xScale()), ' ', String::number(m_matrix.yScale()), ')'); 147 case SVG_TRANSFORM_ROTATE: { 148 double angleInRad = deg2rad(m_angle); 149 double cosAngle = cos(angleInRad); 150 double sinAngle = sin(angleInRad); 151 float cx = narrowPrecisionToFloat(cosAngle != 1 ? (m_matrix.e() * (1 - cosAngle) - m_matrix.f() * sinAngle) / (1 - cosAngle) / 2 : 0); 152 float cy = narrowPrecisionToFloat(cosAngle != 1 ? (m_matrix.e() * sinAngle / (1 - cosAngle) + m_matrix.f()) / 2 : 0); 153 if (cx || cy) 154 return makeString("rotate(", String::number(m_angle), ' ', String::number(cx), ' ', String::number(cy), ')'); 155 return makeString("rotate(", String::number(m_angle), ')'); 156 } 157 case SVG_TRANSFORM_SKEWX: 158 return makeString("skewX(", String::number(m_angle), ')'); 159 case SVG_TRANSFORM_SKEWY: 160 return makeString("skewY(", String::number(m_angle), ')'); 161 } 162 163 ASSERT_NOT_REACHED(); 164 return String(); 165 } 166 167 } // namespace WebCore 168 169 #endif // ENABLE(SVG) 170