SVGTransform.cpp revision cad810f21b803229eb11403f9209855525a25d57
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
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
35namespace WebCore {
36
37SVGTransform::SVGTransform()
38    : m_type(SVG_TRANSFORM_UNKNOWN)
39    , m_angle(0)
40{
41}
42
43SVGTransform::SVGTransform(SVGTransformType type)
44    : m_type(type)
45    , m_angle(0)
46{
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::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
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
132String 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