Home | History | Annotate | Download | only in svg
      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