karbon

vspiral.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001, 2002, 2003 The Karbon Developers
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 
00021 #include <math.h>
00022 
00023 #include <qwmatrix.h>
00024 #include <qdom.h>
00025 
00026 #include "vglobal.h"
00027 #include "vspiral.h"
00028 #include "vtransformcmd.h"
00029 #include <klocale.h>
00030 #include <KoUnit.h>
00031 #include <vdocument.h>
00032 
00033 VSpiral::VSpiral( VObject* parent, VState state )
00034     : VPath( parent, state )
00035 {
00036 }
00037 
00038 VSpiral::VSpiral( VObject* parent,
00039         const KoPoint& center, double radius, uint segments, double fade,
00040         bool clockwise, double angle, VSpiralType type )
00041     : VPath( parent ), m_center( center), m_radius( radius ), m_fade( fade ), m_segments( segments ), m_clockwise( clockwise ), m_angle( angle ), m_type( type )
00042 {
00043     init();
00044 }
00045 
00046 void
00047 VSpiral::init()
00048 {
00049     // It makes sense to have at least one segment:
00050     if( m_segments < 1 )
00051         m_segments = 1;
00052 
00053     // Make sure the radius is positive:
00054     if( m_radius < 0.0 )
00055         m_radius = -m_radius;
00056 
00057     // Fall back, when fade is out of range:
00058     if( m_fade <= 0.0 || m_fade >= 1.0 )
00059         m_fade = 0.5;
00060 
00061     setFillRule( winding );
00062 
00063     // advance by pi/2 clockwise or cclockwise?
00064     double adv_ang = ( m_clockwise ? -1.0 : 1.0 ) * VGlobal::pi_2;
00065     // radius of first segment is non-faded radius:
00066     double r = m_radius;
00067 
00068     KoPoint oldP( 0.0, ( m_clockwise ? -1.0 : 1.0 ) * m_radius );
00069     KoPoint newP;
00070     KoPoint newCenter( 0.0, 0.0 );
00071     moveTo( oldP );
00072 
00073     for ( uint i = 0; i < m_segments; ++i )
00074     {
00075         newP.setX( r * cos( adv_ang * ( i + 2 ) ) + newCenter.x() );
00076         newP.setY( r * sin( adv_ang * ( i + 2 ) ) + newCenter.y() );
00077 
00078         if( m_type == round )
00079             arcTo( oldP + newP - newCenter, newP, r );
00080         else
00081             lineTo( newP );
00082 
00083         newCenter += ( newP - newCenter ) * ( 1.0 - m_fade );
00084         oldP = newP;
00085         r *= m_fade;
00086     }
00087 
00088     // translate path to center:
00089     QWMatrix m;
00090     m.translate( m_center.x(), m_center.y() );
00091 
00092     // sadly it's not feasible to simply add angle while creation.
00093     m.rotate(
00094         ( m_angle + ( m_clockwise ? VGlobal::pi : 0.0 ) ) * // make cw-spiral start at mouse-pointer
00095             VGlobal::one_pi_180 );  // one_pi_180 = 1/(pi/180) = 180/pi.
00096 
00097     // only tranform the path data
00098     VTransformCmd cmd( 0L, m );
00099     cmd.VVisitor::visitVPath( *this );
00100 
00101     m_matrix.reset();
00102 }
00103 
00104 QString
00105 VSpiral::name() const
00106 {
00107     QString result = VObject::name();
00108     return !result.isEmpty() ? result : i18n( "Spiral" );
00109 }
00110 
00111 void
00112 VSpiral::save( QDomElement& element ) const
00113 {
00114     VDocument *doc = document();
00115     if( doc && doc->saveAsPath() )
00116     {
00117         VPath::save( element );
00118         return;
00119     }
00120 
00121     if( state() != deleted )
00122     {
00123         QDomElement me = element.ownerDocument().createElement( "SPIRAL" );
00124         element.appendChild( me );
00125 
00126         // save fill/stroke untransformed
00127         VPath path( *this );
00128         VTransformCmd cmd( 0L, m_matrix.invert() );
00129         cmd.visit( path );
00130         path.VObject::save( me );
00131         //VObject::save( me );
00132 
00133         me.setAttribute( "cx", m_center.x() );
00134         me.setAttribute( "cy", m_center.y() );
00135 
00136         me.setAttribute( "radius", m_radius );
00137         me.setAttribute( "angle", m_angle );
00138         me.setAttribute( "fade", m_fade );
00139 
00140         me.setAttribute( "segments", m_segments );
00141 
00142         me.setAttribute( "clockwise", m_clockwise );
00143 
00144         me.setAttribute( "type", m_type );
00145 
00146         QString transform = buildSvgTransform();
00147         if( !transform.isEmpty() )
00148             me.setAttribute( "transform", transform );
00149     }
00150 }
00151 
00152 void
00153 VSpiral::load( const QDomElement& element )
00154 {
00155     setState( normal );
00156 
00157     QDomNodeList list = element.childNodes();
00158     for( uint i = 0; i < list.count(); ++i )
00159         if( list.item( i ).isElement() )
00160             VObject::load( list.item( i ).toElement() );
00161 
00162     m_radius  = KoUnit::parseValue( element.attribute( "radius" ) );
00163     m_angle = element.attribute( "angle" ).toDouble();
00164     m_fade = element.attribute( "fade" ).toDouble();
00165 
00166     m_center.setX( KoUnit::parseValue( element.attribute( "cx" ) ) );
00167     m_center.setY( KoUnit::parseValue( element.attribute( "cy" ) ) );
00168 
00169     m_segments  = element.attribute( "segments" ).toUInt(),
00170 
00171     m_clockwise = element.attribute( "clockwise" ).toInt();
00172 
00173     m_type = (VSpiral::VSpiralType)element.attribute( "type" ).toInt();
00174 
00175     init();
00176 
00177     QString trafo = element.attribute( "transform" );
00178     if( !trafo.isEmpty() )
00179         transform( trafo );
00180 }
00181 
00182 VPath* 
00183 VSpiral::clone() const
00184 {
00185     return new VSpiral( *this );
00186 }
KDE Home | KDE Accessibility Home | Description of Access Keys