diff options
Diffstat (limited to 'karbon/shapes/vspiral.cc')
-rw-r--r-- | karbon/shapes/vspiral.cc | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/karbon/shapes/vspiral.cc b/karbon/shapes/vspiral.cc new file mode 100644 index 00000000..8f6d17c2 --- /dev/null +++ b/karbon/shapes/vspiral.cc @@ -0,0 +1,186 @@ +/* This file is part of the KDE project + Copyright (C) 2001, 2002, 2003 The Karbon Developers + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + + +#include <math.h> + +#include <qwmatrix.h> +#include <qdom.h> + +#include "vglobal.h" +#include "vspiral.h" +#include "vtransformcmd.h" +#include <klocale.h> +#include <KoUnit.h> +#include <vdocument.h> + +VSpiral::VSpiral( VObject* parent, VState state ) + : VPath( parent, state ) +{ +} + +VSpiral::VSpiral( VObject* parent, + const KoPoint& center, double radius, uint segments, double fade, + bool clockwise, double angle, VSpiralType type ) + : VPath( parent ), m_center( center), m_radius( radius ), m_fade( fade ), m_segments( segments ), m_clockwise( clockwise ), m_angle( angle ), m_type( type ) +{ + init(); +} + +void +VSpiral::init() +{ + // It makes sense to have at least one segment: + if( m_segments < 1 ) + m_segments = 1; + + // Make sure the radius is positive: + if( m_radius < 0.0 ) + m_radius = -m_radius; + + // Fall back, when fade is out of range: + if( m_fade <= 0.0 || m_fade >= 1.0 ) + m_fade = 0.5; + + setFillRule( winding ); + + // advance by pi/2 clockwise or cclockwise? + double adv_ang = ( m_clockwise ? -1.0 : 1.0 ) * VGlobal::pi_2; + // radius of first segment is non-faded radius: + double r = m_radius; + + KoPoint oldP( 0.0, ( m_clockwise ? -1.0 : 1.0 ) * m_radius ); + KoPoint newP; + KoPoint newCenter( 0.0, 0.0 ); + moveTo( oldP ); + + for ( uint i = 0; i < m_segments; ++i ) + { + newP.setX( r * cos( adv_ang * ( i + 2 ) ) + newCenter.x() ); + newP.setY( r * sin( adv_ang * ( i + 2 ) ) + newCenter.y() ); + + if( m_type == round ) + arcTo( oldP + newP - newCenter, newP, r ); + else + lineTo( newP ); + + newCenter += ( newP - newCenter ) * ( 1.0 - m_fade ); + oldP = newP; + r *= m_fade; + } + + // translate path to center: + QWMatrix m; + m.translate( m_center.x(), m_center.y() ); + + // sadly it's not feasible to simply add angle while creation. + m.rotate( + ( m_angle + ( m_clockwise ? VGlobal::pi : 0.0 ) ) * // make cw-spiral start at mouse-pointer + VGlobal::one_pi_180 ); // one_pi_180 = 1/(pi/180) = 180/pi. + + // only tranform the path data + VTransformCmd cmd( 0L, m ); + cmd.VVisitor::visitVPath( *this ); + + m_matrix.reset(); +} + +QString +VSpiral::name() const +{ + QString result = VObject::name(); + return !result.isEmpty() ? result : i18n( "Spiral" ); +} + +void +VSpiral::save( QDomElement& element ) const +{ + VDocument *doc = document(); + if( doc && doc->saveAsPath() ) + { + VPath::save( element ); + return; + } + + if( state() != deleted ) + { + QDomElement me = element.ownerDocument().createElement( "SPIRAL" ); + element.appendChild( me ); + + // save fill/stroke untransformed + VPath path( *this ); + VTransformCmd cmd( 0L, m_matrix.invert() ); + cmd.visit( path ); + path.VObject::save( me ); + //VObject::save( me ); + + me.setAttribute( "cx", m_center.x() ); + me.setAttribute( "cy", m_center.y() ); + + me.setAttribute( "radius", m_radius ); + me.setAttribute( "angle", m_angle ); + me.setAttribute( "fade", m_fade ); + + me.setAttribute( "segments", m_segments ); + + me.setAttribute( "clockwise", m_clockwise ); + + me.setAttribute( "type", m_type ); + + QString transform = buildSvgTransform(); + if( !transform.isEmpty() ) + me.setAttribute( "transform", transform ); + } +} + +void +VSpiral::load( const QDomElement& element ) +{ + setState( normal ); + + QDomNodeList list = element.childNodes(); + for( uint i = 0; i < list.count(); ++i ) + if( list.item( i ).isElement() ) + VObject::load( list.item( i ).toElement() ); + + m_radius = KoUnit::parseValue( element.attribute( "radius" ) ); + m_angle = element.attribute( "angle" ).toDouble(); + m_fade = element.attribute( "fade" ).toDouble(); + + m_center.setX( KoUnit::parseValue( element.attribute( "cx" ) ) ); + m_center.setY( KoUnit::parseValue( element.attribute( "cy" ) ) ); + + m_segments = element.attribute( "segments" ).toUInt(), + + m_clockwise = element.attribute( "clockwise" ).toInt(); + + m_type = (VSpiral::VSpiralType)element.attribute( "type" ).toInt(); + + init(); + + QString trafo = element.attribute( "transform" ); + if( !trafo.isEmpty() ) + transform( trafo ); +} + +VPath* +VSpiral::clone() const +{ + return new VSpiral( *this ); +} |