• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KHTML

SVGTransformDistance.cpp

Go to the documentation of this file.
00001 /*
00002  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
00003  
00004  This file is part of the WebKit project
00005  
00006  This library is free software; you can redistribute it and/or
00007  modify it under the terms of the GNU Library General Public
00008  License as published by the Free Software Foundation; either
00009  version 2 of the License, or (at your option) any later version.
00010  
00011  This library is distributed in the hope that it will be useful,
00012  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  Library General Public License for more details.
00015  
00016  You should have received a copy of the GNU Library General Public License
00017  along with this library; see the file COPYING.LIB.  If not, write to
00018  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  Boston, MA 02110-1301, USA.
00020  */
00021 
00022 #include "config.h"
00023 #include "wtf/Platform.h"
00024 #if ENABLE(SVG)
00025 #include "SVGTransformDistance.h"
00026 
00027 #include "FloatConversion.h"
00028 #include "FloatPoint.h"
00029 #include "FloatSize.h"
00030 #include "SVGTransform.h"
00031 
00032 #include <math.h>
00033 
00034 namespace WebCore {
00035     
00036 SVGTransformDistance::SVGTransformDistance()
00037     : m_type(SVGTransform::SVG_TRANSFORM_UNKNOWN)
00038     , m_angle(0)
00039 {
00040 }
00041 
00042 SVGTransformDistance::SVGTransformDistance(SVGTransform::SVGTransformType type, float angle, float cx, float cy, const AffineTransform& transform)
00043     : m_type(type)
00044     , m_angle(angle)
00045     , m_cx(cx)
00046     , m_cy(cy)
00047     , m_transform(transform)
00048 {
00049 }
00050 
00051 SVGTransformDistance::SVGTransformDistance(const SVGTransform& fromSVGTransform, const SVGTransform& toSVGTransform)
00052     : m_type(fromSVGTransform.type())
00053     , m_angle(0)
00054     , m_cx(0)
00055     , m_cy(0)
00056 {
00057     ASSERT(m_type == toSVGTransform.type());
00058     
00059     switch (m_type) {
00060     case SVGTransform::SVG_TRANSFORM_UNKNOWN:
00061         return;
00062     case SVGTransform::SVG_TRANSFORM_MATRIX:
00063         // FIXME: need to be able to subtract to matrices
00064         return;
00065     case SVGTransform::SVG_TRANSFORM_ROTATE:
00066     {
00067         FloatSize centerDistance = toSVGTransform.rotationCenter() - fromSVGTransform.rotationCenter();
00068         m_angle = toSVGTransform.angle() - fromSVGTransform.angle();
00069         m_cx = centerDistance.width();
00070         m_cy = centerDistance.height();
00071         return;
00072     }
00073     case SVGTransform::SVG_TRANSFORM_TRANSLATE:
00074     {
00075         FloatSize translationDistance = toSVGTransform.translate() - fromSVGTransform.translate();
00076         m_transform.translate(translationDistance.width(), translationDistance.height());
00077         return;
00078     }
00079     case SVGTransform::SVG_TRANSFORM_SCALE:
00080     {
00081         float scaleX = toSVGTransform.scale().width() - fromSVGTransform.scale().width();        
00082         float scaleY = toSVGTransform.scale().height() - fromSVGTransform.scale().height();
00083         m_transform.scale(scaleX, scaleY);
00084         return;
00085     }
00086     case SVGTransform::SVG_TRANSFORM_SKEWX:
00087     case SVGTransform::SVG_TRANSFORM_SKEWY:
00088         m_angle = toSVGTransform.angle() - fromSVGTransform.angle();
00089         return;
00090     }
00091 }
00092 
00093 SVGTransformDistance SVGTransformDistance::scaledDistance(float scaleFactor) const
00094 {
00095     switch (m_type) {
00096     case SVGTransform::SVG_TRANSFORM_UNKNOWN:
00097         return SVGTransformDistance();
00098     case SVGTransform::SVG_TRANSFORM_ROTATE:
00099         return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform());
00100     case SVGTransform::SVG_TRANSFORM_SCALE:
00101     case SVGTransform::SVG_TRANSFORM_MATRIX:
00102         return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform(m_transform).scale(scaleFactor));
00103     case SVGTransform::SVG_TRANSFORM_TRANSLATE:
00104     {
00105         AffineTransform newTransform(m_transform);
00106         newTransform.setE(m_transform.e() * scaleFactor);
00107         newTransform.setF(m_transform.f() * scaleFactor);
00108         return SVGTransformDistance(m_type, 0, 0, 0, newTransform);
00109     }
00110     case SVGTransform::SVG_TRANSFORM_SKEWX:
00111     case SVGTransform::SVG_TRANSFORM_SKEWY:
00112         return SVGTransformDistance(m_type, m_angle * scaleFactor, m_cx * scaleFactor, m_cy * scaleFactor, AffineTransform());
00113     }
00114     
00115     ASSERT_NOT_REACHED();
00116     return SVGTransformDistance();
00117 }
00118 
00119 SVGTransform SVGTransformDistance::addSVGTransforms(const SVGTransform& first, const SVGTransform& second)
00120 {
00121     ASSERT(first.type() == second.type());
00122     
00123     SVGTransform transform;
00124     
00125     switch (first.type()) {
00126     case SVGTransform::SVG_TRANSFORM_UNKNOWN:
00127         return SVGTransform();
00128     case SVGTransform::SVG_TRANSFORM_ROTATE:
00129     {
00130         transform.setRotate(first.angle() + second.angle(), first.rotationCenter().x() + second.rotationCenter().x(),
00131                             first.rotationCenter().y() + second.rotationCenter().y());
00132         return transform;
00133     }
00134     case SVGTransform::SVG_TRANSFORM_MATRIX:
00135         transform.setMatrix(first.matrix() * second.matrix());
00136         return transform;
00137     case SVGTransform::SVG_TRANSFORM_TRANSLATE:
00138     {
00139         float dx = first.translate().x() + second.translate().x();
00140         float dy = first.translate().y() + second.translate().y();
00141         transform.setTranslate(dx, dy);
00142         return transform;
00143     }
00144     case SVGTransform::SVG_TRANSFORM_SCALE:
00145     {
00146         FloatSize scale = first.scale() + second.scale();
00147         transform.setScale(scale.width(), scale.height());
00148         return transform;
00149     }
00150     case SVGTransform::SVG_TRANSFORM_SKEWX:
00151         transform.setSkewX(first.angle() + second.angle());
00152         return transform;
00153     case SVGTransform::SVG_TRANSFORM_SKEWY:
00154         transform.setSkewY(first.angle() + second.angle());
00155         return transform;
00156     }
00157     
00158     ASSERT_NOT_REACHED();
00159     return SVGTransform();
00160 }
00161 
00162 void SVGTransformDistance::addSVGTransform(const SVGTransform& transform, bool absoluteValue)
00163 {
00164     // If this is the first add, set the type for this SVGTransformDistance
00165     if (m_type == SVGTransform::SVG_TRANSFORM_UNKNOWN)
00166         m_type = transform.type();
00167     
00168     ASSERT(m_type == transform.type());
00169     
00170     switch (m_type) {
00171     case SVGTransform::SVG_TRANSFORM_UNKNOWN:
00172         return;
00173     case SVGTransform::SVG_TRANSFORM_MATRIX:
00174         m_transform *= transform.matrix(); // FIXME: what does 'distance' between two transforms mean?  how should we respect 'absoluteValue' here?
00175         return;
00176     case SVGTransform::SVG_TRANSFORM_ROTATE:
00177         m_angle += absoluteValue ? fabsf(transform.angle()) : transform.angle();
00178         m_cx += absoluteValue ? fabsf(transform.rotationCenter().x()) : transform.rotationCenter().x();
00179         m_cy += absoluteValue ? fabsf(transform.rotationCenter().y()) : transform.rotationCenter().y();
00180         // fall through
00181     case SVGTransform::SVG_TRANSFORM_TRANSLATE:
00182     {
00183         float dx = absoluteValue ? fabsf(transform.translate().x()) : transform.translate().x();
00184         float dy = absoluteValue ? fabsf(transform.translate().y()) : transform.translate().y();
00185         m_transform.translate(dx, dy);
00186         return;
00187     }
00188     case SVGTransform::SVG_TRANSFORM_SCALE:
00189     {
00190         float scaleX = absoluteValue ? fabsf(transform.scale().width()) : transform.scale().width();
00191         float scaleY = absoluteValue ? fabsf(transform.scale().height()) : transform.scale().height();
00192         m_transform.scale(scaleX, scaleY);
00193         return;
00194     }
00195     case SVGTransform::SVG_TRANSFORM_SKEWX:
00196     case SVGTransform::SVG_TRANSFORM_SKEWY:
00197         m_angle += absoluteValue ? fabsf(transform.angle()) : transform.angle();
00198         return;
00199     }
00200     
00201     ASSERT_NOT_REACHED();
00202     return;
00203 }
00204 
00205 SVGTransform SVGTransformDistance::addToSVGTransform(const SVGTransform& transform) const
00206 {
00207     ASSERT(m_type == transform.type() || transform == SVGTransform());
00208     
00209     SVGTransform newTransform(transform);
00210     
00211     switch (m_type) {
00212     case SVGTransform::SVG_TRANSFORM_UNKNOWN:
00213         return SVGTransform();
00214     case SVGTransform::SVG_TRANSFORM_MATRIX:
00215         return SVGTransform(transform.matrix() * m_transform);
00216     case SVGTransform::SVG_TRANSFORM_TRANSLATE:
00217     {
00218         FloatPoint translation = transform.translate();
00219         translation += FloatSize::narrowPrecision(m_transform.e(), m_transform.f());
00220         newTransform.setTranslate(translation.x(), translation.y());
00221         return newTransform;
00222     }
00223     case SVGTransform::SVG_TRANSFORM_SCALE:
00224     {
00225         FloatSize scale = transform.scale();
00226         scale += FloatSize::narrowPrecision(m_transform.a(), m_transform.d());
00227         newTransform.setScale(scale.width(), scale.height());
00228         return newTransform;
00229     }
00230     case SVGTransform::SVG_TRANSFORM_ROTATE:
00231     {
00232         // FIXME: I'm not certain the translation is calculated correctly here
00233         FloatPoint center = transform.rotationCenter();
00234         newTransform.setRotate(transform.angle() + m_angle,
00235                                center.x() + m_cx,
00236                                center.y() + m_cy);
00237         return newTransform;
00238     }
00239     case SVGTransform::SVG_TRANSFORM_SKEWX:
00240         newTransform.setSkewX(transform.angle() + m_angle);
00241         return newTransform;
00242     case SVGTransform::SVG_TRANSFORM_SKEWY:
00243         newTransform.setSkewY(transform.angle() + m_angle);
00244         return newTransform;
00245     }
00246     
00247     ASSERT_NOT_REACHED();
00248     return SVGTransform();
00249 }
00250 
00251 bool SVGTransformDistance::isZero() const
00252 {
00253     return (m_transform == AffineTransform() && m_angle == 0);
00254 }
00255 
00256 float SVGTransformDistance::distance() const
00257 {
00258     switch (m_type) {
00259     case SVGTransform::SVG_TRANSFORM_UNKNOWN:
00260         return 0.0f;
00261     case SVGTransform::SVG_TRANSFORM_ROTATE:
00262         return sqrtf(m_angle * m_angle + m_cx * m_cx + m_cy * m_cy);
00263     case SVGTransform::SVG_TRANSFORM_MATRIX:
00264         return 0.0f; // I'm not quite sure yet what distance between two matrices means.
00265     case SVGTransform::SVG_TRANSFORM_SCALE:
00266         return static_cast<float>(sqrt(m_transform.a() * m_transform.a() + m_transform.d() * m_transform.d()));
00267     case SVGTransform::SVG_TRANSFORM_TRANSLATE:
00268         return static_cast<float>(sqrt(m_transform.e() * m_transform.e() + m_transform.f() * m_transform.f()));
00269     case SVGTransform::SVG_TRANSFORM_SKEWX:
00270     case SVGTransform::SVG_TRANSFORM_SKEWY:
00271         return m_angle;
00272     }
00273     ASSERT_NOT_REACHED();
00274     return 0.0f;
00275 }
00276 
00277 }
00278 
00279 #endif

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal