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