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