summaryrefslogtreecommitdiffstats
path: root/karbon/shapes
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
commit8362bf63dea22bbf6736609b0f49c152f975eb63 (patch)
tree0eea3928e39e50fae91d4e68b21b1e6cbae25604 /karbon/shapes
downloadkoffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz
koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'karbon/shapes')
-rw-r--r--karbon/shapes/Makefile.am29
-rw-r--r--karbon/shapes/vellipse.cc316
-rw-r--r--karbon/shapes/vellipse.h63
-rw-r--r--karbon/shapes/vpolygon.cc185
-rw-r--r--karbon/shapes/vpolygon.h52
-rw-r--r--karbon/shapes/vpolyline.cc184
-rw-r--r--karbon/shapes/vpolyline.h50
-rw-r--r--karbon/shapes/vrectangle.cc229
-rw-r--r--karbon/shapes/vrectangle.h54
-rw-r--r--karbon/shapes/vsinus.cc206
-rw-r--r--karbon/shapes/vsinus.h51
-rw-r--r--karbon/shapes/vspiral.cc186
-rw-r--r--karbon/shapes/vspiral.h60
-rw-r--r--karbon/shapes/vstar.cc348
-rw-r--r--karbon/shapes/vstar.h91
15 files changed, 2104 insertions, 0 deletions
diff --git a/karbon/shapes/Makefile.am b/karbon/shapes/Makefile.am
new file mode 100644
index 00000000..bbb7899b
--- /dev/null
+++ b/karbon/shapes/Makefile.am
@@ -0,0 +1,29 @@
+INCLUDES = $(KOFFICE_INCLUDES) $(KOPAINTER_INCLUDES) \
+ -I$(srcdir)/.. \
+ -I$(srcdir)/../core \
+ -I$(srcdir)/../commands \
+ $(all_includes)
+
+noinst_LTLIBRARIES = libkarbonshapes.la
+
+noinst_HEADERS = \
+ vellipse.h \
+ vpolyline.h \
+ vpolygon.h \
+ vrectangle.h \
+ vsinus.h \
+ vspiral.h \
+ vstar.h
+
+libkarbonshapes_la_SOURCES = \
+ vellipse.cc \
+ vpolyline.cc \
+ vpolygon.cc \
+ vrectangle.cc \
+ vsinus.cc \
+ vspiral.cc \
+ vstar.cc
+
+libkarbonshapes_la_METASOURCES = \
+ AUTO
+
diff --git a/karbon/shapes/vellipse.cc b/karbon/shapes/vellipse.cc
new file mode 100644
index 00000000..c2afc804
--- /dev/null
+++ b/karbon/shapes/vellipse.cc
@@ -0,0 +1,316 @@
+/* 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 "vellipse.h"
+#include "vtransformcmd.h"
+#include <klocale.h>
+#include <KoUnit.h>
+#include <KoStore.h>
+#include <KoXmlWriter.h>
+#include <KoXmlNS.h>
+#include <vglobal.h>
+#include <vdocument.h>
+#include <qdom.h>
+#include <core/vfill.h>
+
+VEllipse::VEllipse( VObject* parent, VState state ) : VPath( parent, state )
+{
+}
+
+VEllipse::VEllipse( VObject* parent,
+ const KoPoint& topLeft, double width, double height,
+ VEllipseType type, double startAngle, double endAngle )
+ : VPath( parent ), m_type( type ), m_startAngle( startAngle ), m_endAngle( endAngle )
+{
+ setDrawCenterNode();
+
+ m_rx = width / 2.0;
+ m_ry = height / 2.0;
+ m_center.setX( topLeft.x() + m_rx );
+ m_center.setY( topLeft.y() + m_ry );
+
+ init();
+}
+
+void
+VEllipse::init()
+{
+ // to radials
+ int nsegs;
+ if( m_startAngle < m_endAngle )
+ nsegs = int( floor( ( m_endAngle - m_startAngle ) / 90.0 ) );
+ else
+ nsegs = 4 - int( ceil( ( m_startAngle - m_endAngle ) / 90.0 ) );
+ double startAngle = m_startAngle - 90.0;
+ if( startAngle < 0 ) startAngle += 360.0;
+ startAngle = VGlobal::pi_2 * ( startAngle / 90.0 );
+ double endAngle = m_endAngle - 90.0;
+ if( endAngle < 0 ) endAngle += 360.0;
+ endAngle = VGlobal::pi_2 * ( endAngle / 90.0 );
+ // Create (half-)unity circle with topLeft at (0|0):
+ double currentAngle = -startAngle - VGlobal::pi_2;
+ KoPoint start( 0.5 * sin( -startAngle ), 0.5 * cos( -startAngle ) );
+ moveTo( KoPoint( start.x(), start.y() ) );
+ double midAngle = currentAngle + VGlobal::pi_2 / 2.0;
+ double midAmount = 0.5 / sin( VGlobal::pi_2 / 2.0 );
+ for( int i = 0;i < nsegs;i++ )
+ {
+ midAngle -= VGlobal::pi_2;
+ arcTo( KoPoint( cos( midAngle ) * midAmount, -sin( midAngle ) * midAmount ),
+ KoPoint( 0.5 * sin( currentAngle ), 0.5 * cos( currentAngle ) ), 0.5 );
+ currentAngle -= VGlobal::pi_2;
+ }
+ double rest = ( -endAngle - VGlobal::pi_2 - currentAngle ) * 90.0 / VGlobal::pi_2;
+ if( rest > 0 )
+ rest -= 360.0;
+ if( rest != 0 )
+ {
+ midAngle = currentAngle - ( -rest / 360.0 ) * VGlobal::pi;
+ midAmount = 0.5 / cos( currentAngle - midAngle );
+ KoPoint end( 0.5 * sin( -endAngle ), 0.5 * cos( -endAngle ) );
+ arcTo( KoPoint( cos( midAngle ) * midAmount, -sin( midAngle ) * midAmount ),
+ KoPoint( 0.5 * sin( -endAngle ), 0.5 * cos( -endAngle ) ), 0.5 );
+ }
+ if( m_type == cut )
+ lineTo( KoPoint( 0.0, 0.0 ) );
+ if( m_type != arc )
+ close();
+
+ // Translate and scale:
+ QWMatrix m;
+ m.translate( m_center.x(), m_center.y() );
+ m.scale( 2.0 * m_rx, 2.0 * m_ry );
+
+ // only tranform the path data
+ VTransformCmd cmd( 0L, m );
+ cmd.VVisitor::visitVPath( *this );
+
+ m_matrix.reset();
+}
+
+QString
+VEllipse::name() const
+{
+ QString result = VObject::name();
+ return !result.isEmpty() ? result : i18n( "Ellipse" );
+}
+
+void
+VEllipse::save( QDomElement& element ) const
+{
+ VDocument *doc = document();
+ if( doc && doc->saveAsPath() )
+ {
+ VPath::save( element );
+ return;
+ }
+
+ if( state() != deleted )
+ {
+ QDomElement me = element.ownerDocument().createElement( "ELLIPSE" );
+ 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( "rx", m_rx );
+ me.setAttribute( "ry", m_ry );
+
+ me.setAttribute( "start-angle", m_startAngle );
+ me.setAttribute( "end-angle", m_endAngle );
+
+ if( m_type == cut )
+ me.setAttribute( "kind", "cut" );
+ else if( m_type == section )
+ me.setAttribute( "kind", "section" );
+ else if( m_type == arc )
+ me.setAttribute( "kind", "arc" );
+ else
+ me.setAttribute( "kind", "full" );
+
+ QString transform = buildSvgTransform();
+ if( !transform.isEmpty() )
+ me.setAttribute( "transform", transform );
+ }
+}
+
+void
+VEllipse::saveOasis( KoStore *store, KoXmlWriter *docWriter, KoGenStyles &mainStyles, int &index ) const
+{
+ // do not save deleted objects
+ if( state() == deleted )
+ return;
+
+ docWriter->startElement( "draw:ellipse" );
+
+ //save all into pt
+ docWriter->addAttributePt( "svg:cx", m_center.x() );
+ docWriter->addAttributePt( "svg:cy", m_center.y() );
+ docWriter->addAttributePt( "svg:rx", m_rx );
+ docWriter->addAttributePt( "svg:ry", m_ry );
+
+ if( m_type == full )
+ docWriter->addAttribute( "draw:kind", "full" );
+ else
+ {
+ // the meaning of cut and section is mixed up in karbon, so just set them so for now
+ // be sure to do the right thing tm for karbon 2.0
+ if( m_type == section )
+ docWriter->addAttribute( "draw:kind", "cut" );
+ else if( m_type == cut )
+ docWriter->addAttribute( "draw:kind", "section" );
+ else
+ docWriter->addAttribute( "draw:kind", "arc" );
+
+ docWriter->addAttribute( "draw:start-angle", m_startAngle );
+ docWriter->addAttribute( "draw:end-angle", m_endAngle );
+ }
+
+ VObject::saveOasis( store, docWriter, mainStyles, index );
+
+ QWMatrix tmpMat;
+ tmpMat.scale( 1, -1 );
+ tmpMat.translate( 0, -document()->height() );
+
+ QString transform = buildOasisTransform( m_matrix*tmpMat );
+ if( !transform.isEmpty() )
+ docWriter->addAttribute( "draw:transform", transform );
+
+ docWriter->endElement();
+}
+
+bool
+VEllipse::loadOasis( const QDomElement &element, KoOasisLoadingContext &context )
+{
+ setState( normal );
+
+ if( element.tagName() == "ellipse" )
+ {
+ if( element.hasAttributeNS( KoXmlNS::svg, "rx" ) )
+ m_rx = KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "rx", QString::null ) );
+ else
+ m_rx = 0.5 * KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "width", QString::null ) );
+
+ if( element.hasAttributeNS( KoXmlNS::svg, "ry" ) )
+ m_ry = KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "ry", QString::null ) );
+ else
+ m_ry = 0.5 * KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "height", QString::null ) );
+
+ }
+ else if( element.tagName() == "circle" )
+ {
+ if( element.hasAttributeNS( KoXmlNS::svg, "r" ) )
+ m_rx = m_ry = KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "r", QString::null ) );
+ else
+ m_rx = m_ry = 0.5 * KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "width", QString::null ) );
+ }
+
+ if( element.hasAttributeNS( KoXmlNS::svg, "cx" ) )
+ m_center.setX( KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "cx", QString::null ) ) );
+ else
+ m_center.setX( m_rx + KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "x", QString::null ) ) );
+
+ if( element.hasAttributeNS( KoXmlNS::svg, "cy" ) )
+ m_center.setY( KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "cy", QString::null ) ) );
+ else
+ m_center.setY( m_ry + KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "y", QString::null ) ) );
+
+ // the meaning of cut and section is mixed up in karbon, so just set them so for now
+ // be sure to do the right thing tm for karbon 2.0
+ QString kind = element.attributeNS( KoXmlNS::draw, "kind", QString::null );
+ if( kind == "cut" )
+ m_type = section;
+ else if( kind == "section" )
+ m_type = cut;
+ else if( kind == "arc" )
+ m_type = arc;
+ else
+ m_type = full;
+
+ double startAngle = element.attributeNS( KoXmlNS::draw, "start-angle", QString::null ).toDouble();
+ double endAngle = element.attributeNS( KoXmlNS::draw, "end-angle", QString::null ).toDouble();
+
+ // the shape gets mirrored in y-direction, so make the angles temporary clockwise
+ // just for creating the path
+ m_startAngle = 360.0 - endAngle;
+ m_endAngle = 360.0 - startAngle;
+
+ init();
+
+ // now set the right angles
+ m_startAngle = startAngle;
+ m_endAngle = endAngle;
+
+ transformByViewbox( element, element.attributeNS( KoXmlNS::svg, "viewBox", QString::null ) );
+
+ QString trafo = element.attributeNS( KoXmlNS::draw, "transform", QString::null );
+ if( !trafo.isEmpty() )
+ transformOasis( trafo );
+
+ return VObject::loadOasis( element, context );
+}
+
+void
+VEllipse::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_rx = KoUnit::parseValue( element.attribute( "rx" ) );
+ m_ry = KoUnit::parseValue( element.attribute( "ry" ) );
+
+ m_center.setX( KoUnit::parseValue( element.attribute( "cx" ) ) );
+ m_center.setY( KoUnit::parseValue( element.attribute( "cy" ) ) );
+
+ m_startAngle = element.attribute( "start-angle" ).toDouble();
+ m_endAngle = element.attribute( "end-angle" ).toDouble();
+
+ if( element.attribute( "kind" ) == "cut" )
+ m_type = cut;
+ else if( element.attribute( "kind" ) == "section" )
+ m_type = section;
+ else if( element.attribute( "kind" ) == "arc" )
+ m_type = arc;
+ else
+ m_type = full;
+
+ init();
+
+ QString trafo = element.attribute( "transform" );
+ if( !trafo.isEmpty() )
+ transform( trafo );
+}
+
+VPath*
+VEllipse::clone() const
+{
+ return new VEllipse( *this );
+}
diff --git a/karbon/shapes/vellipse.h b/karbon/shapes/vellipse.h
new file mode 100644
index 00000000..e7decbd2
--- /dev/null
+++ b/karbon/shapes/vellipse.h
@@ -0,0 +1,63 @@
+/* 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.
+*/
+
+#ifndef __VELLIPSE_H__
+#define __VELLIPSE_H__
+
+#include "vcomposite.h"
+#include <koffice_export.h>
+
+class KARBONBASE_EXPORT VEllipse : public VPath
+{
+public:
+ enum VEllipseType
+ {
+ full,
+ section,
+ cut,
+ arc
+ };
+ VEllipse( VObject* parent, VState state = edit );
+ VEllipse( VObject* parent,
+ const KoPoint& topLeft, double width, double height,
+ VEllipseType type = full, double startAngle = 0, double endAngle = 0 );
+
+ virtual QString name() const;
+
+ virtual void save( QDomElement& element ) const;
+ virtual void saveOasis( KoStore *store, KoXmlWriter *docWriter, KoGenStyles &mainStyles, int &index ) const;
+ virtual void load( const QDomElement& element );
+ virtual bool loadOasis( const QDomElement &element, KoOasisLoadingContext &context );
+
+ virtual VPath* clone() const;
+
+protected:
+ void init();
+
+private:
+ VEllipseType m_type;
+ KoPoint m_center;
+ double m_rx;
+ double m_ry;
+ double m_startAngle;
+ double m_endAngle;
+};
+
+#endif
+
diff --git a/karbon/shapes/vpolygon.cc b/karbon/shapes/vpolygon.cc
new file mode 100644
index 00000000..aa74ca90
--- /dev/null
+++ b/karbon/shapes/vpolygon.cc
@@ -0,0 +1,185 @@
+/* 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 <qdom.h>
+
+#include "vglobal.h"
+#include "vpolygon.h"
+#include "vtransformcmd.h"
+#include <klocale.h>
+#include <KoUnit.h>
+#include <KoStore.h>
+#include <KoXmlWriter.h>
+#include <KoXmlNS.h>
+#include <vdocument.h>
+
+VPolygon::VPolygon( VObject* parent, VState state )
+ : VPath( parent, state )
+{
+}
+
+VPolygon::VPolygon( VObject* parent, const QString &points,
+ const KoPoint& topLeft, double width, double height )
+ : VPath( parent ), m_topLeft( topLeft ), m_width( width), m_height( height ), m_points( points )
+{
+ init();
+}
+
+void
+VPolygon::init()
+{
+ bool bFirst = true;
+
+ QString points = m_points.simplifyWhiteSpace();
+ points.replace( ',', ' ' );
+ points.remove( '\r' );
+ points.remove( '\n' );
+ QStringList pointList = QStringList::split( ' ', points );
+ QStringList::Iterator end(pointList.end());
+ for( QStringList::Iterator it = pointList.begin(); it != end; ++it )
+ {
+ KoPoint point;
+ point.setX( (*it).toDouble() );
+ point.setY( (*++it).toDouble() );
+ if( bFirst )
+ {
+ moveTo( point );
+ bFirst = false;
+ }
+ else
+ lineTo( point );
+ }
+ close();
+
+ QWMatrix m;
+ m.translate( m_topLeft.x(), m_topLeft.y() );
+
+ // only tranform the path data
+ VTransformCmd cmd( 0L, m );
+ cmd.VVisitor::visitVPath( *this );
+}
+
+QString
+VPolygon::name() const
+{
+ QString result = VObject::name();
+ return !result.isEmpty() ? result : i18n( "Polygon" );
+}
+
+void
+VPolygon::save( QDomElement& element ) const
+{
+ VDocument *doc = document();
+ if( doc && doc->saveAsPath() )
+ {
+ VPath::save( element );
+ return;
+ }
+
+ if( state() != deleted )
+ {
+ QDomElement me = element.ownerDocument().createElement( "POLYGON" );
+ 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( "x", m_topLeft.x() );
+ me.setAttribute( "y", m_topLeft.y() );
+
+ me.setAttribute( "width", QString("%1pt").arg( m_width ) );
+ me.setAttribute( "height", QString("%1pt").arg( m_height ) );
+
+ me.setAttribute( "points", m_points );
+
+ QString transform = buildSvgTransform();
+ if( !transform.isEmpty() )
+ me.setAttribute( "transform", transform );
+ }
+}
+
+void
+VPolygon::saveOasis( KoStore *store, KoXmlWriter *docWriter, KoGenStyles &mainStyles, int &index ) const
+{
+ // do not save deleted objects
+ if( state() == deleted )
+ return;
+
+ docWriter->startElement( "draw:polygon" );
+
+ docWriter->addAttribute( "draw:points", m_points );
+
+ VObject::saveOasis( store, docWriter, mainStyles, index );
+
+ docWriter->endElement();
+}
+
+void
+VPolygon::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_points = element.attribute( "points" );
+
+ m_width = KoUnit::parseValue( element.attribute( "width" ), 10.0 );
+ m_height = KoUnit::parseValue( element.attribute( "height" ), 10.0 );
+
+ m_topLeft.setX( KoUnit::parseValue( element.attribute( "x" ) ) );
+ m_topLeft.setY( KoUnit::parseValue( element.attribute( "y" ) ) );
+
+ init();
+
+ QString trafo = element.attribute( "transform" );
+ if( !trafo.isEmpty() )
+ transform( trafo );
+}
+
+bool
+VPolygon::loadOasis( const QDomElement &element, KoOasisLoadingContext &context )
+{
+ setState( normal );
+
+ m_points = element.attributeNS( KoXmlNS::draw, "points", QString::null );
+
+ init();
+
+ transformByViewbox( element, element.attributeNS( KoXmlNS::svg, "viewBox", QString::null ) );
+
+ QString trafo = element.attributeNS( KoXmlNS::draw, "transform", QString::null );
+ if( !trafo.isEmpty() )
+ transformOasis( trafo );
+
+ return VObject::loadOasis( element, context );
+}
+
+VPath*
+VPolygon::clone() const
+{
+ return new VPolygon( *this );
+}
diff --git a/karbon/shapes/vpolygon.h b/karbon/shapes/vpolygon.h
new file mode 100644
index 00000000..9b7bc940
--- /dev/null
+++ b/karbon/shapes/vpolygon.h
@@ -0,0 +1,52 @@
+/* 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.
+*/
+
+#ifndef __VPOLYGON_H__
+#define __VPOLYGON_H__
+
+#include "vcomposite.h"
+
+class VPolygon : public VPath
+{
+public:
+ VPolygon( VObject* parent, VState state = edit );
+ VPolygon( VObject* parent, const QString &points,
+ const KoPoint& topLeft, double width, double height );
+
+ virtual QString name() const;
+
+ virtual void save( QDomElement& element ) const;
+ virtual void saveOasis( KoStore *store, KoXmlWriter *docWriter, KoGenStyles &mainStyles, int &index ) const;
+ virtual void load( const QDomElement& element );
+ virtual bool loadOasis( const QDomElement &element, KoOasisLoadingContext &context );
+
+ virtual VPath* clone() const;
+
+protected:
+ void init();
+
+private:
+ KoPoint m_topLeft;
+ double m_width;
+ double m_height;
+ QString m_points;
+};
+
+#endif
+
diff --git a/karbon/shapes/vpolyline.cc b/karbon/shapes/vpolyline.cc
new file mode 100644
index 00000000..c55c0d14
--- /dev/null
+++ b/karbon/shapes/vpolyline.cc
@@ -0,0 +1,184 @@
+/* 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 "vpolyline.h"
+#include <qdom.h>
+
+#include "vglobal.h"
+#include <klocale.h>
+#include <vdocument.h>
+#include "vtransformcmd.h"
+
+#include <KoStore.h>
+#include <KoXmlWriter.h>
+#include <KoXmlNS.h>
+
+VPolyline::VPolyline( VObject* parent, VState state )
+ : VPath( parent, state )
+{
+}
+
+/*VPolyline::VPolyline( VObject* parent, VState state )
+ : VPath( parent, state )
+{
+}*/
+
+/*VPolyline::VPolyline( VObject* parent, const QString &points )
+ : VPath( parent ), m_points( points )
+{
+ init();
+}*/
+
+void
+VPolyline::init()
+{
+ bool bFirst = true;
+
+ QString points = m_points.simplifyWhiteSpace();
+ points.replace( ',', ' ' );
+ points.remove( '\r' );
+ points.remove( '\n' );
+ QStringList pointList = QStringList::split( ' ', points );
+ QStringList::Iterator end(pointList.end());
+ for( QStringList::Iterator it = pointList.begin(); it != end; ++it )
+ {
+ KoPoint point;
+ point.setX( (*it).toDouble() );
+ point.setY( (*++it).toDouble() );
+ if( bFirst )
+ {
+ moveTo( point );
+ bFirst = false;
+ }
+ else
+ lineTo( point );
+ }
+}
+
+QString
+VPolyline::name() const
+{
+ QString result = VObject::name();
+ return !result.isEmpty() ? result : i18n( "Polyline" );
+}
+
+void
+VPolyline::save( QDomElement& element ) const
+{
+ VDocument *doc = document();
+ if( doc && doc->saveAsPath() )
+ {
+ VPath::save( element );
+ return;
+ }
+
+ if( state() != deleted )
+ {
+ QDomElement me = element.ownerDocument().createElement( "POLYLINE" );
+ 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( "points", m_points );
+
+ QString transform = buildSvgTransform();
+ if( !transform.isEmpty() )
+ me.setAttribute( "transform", transform );
+ }
+}
+
+void
+VPolyline::saveOasis( KoStore *store, KoXmlWriter *docWriter, KoGenStyles &mainStyles, int &index ) const
+{
+ // do not save deleted objects
+ if( state() == deleted )
+ return;
+
+ docWriter->startElement( "draw:polyline" );
+
+ docWriter->addAttribute( "svg:points", m_points );
+
+ VObject::saveOasis( store, docWriter, mainStyles, index );
+
+ docWriter->endElement();
+}
+
+void
+VPolyline::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_points = element.attribute( "points" );
+
+ init();
+
+ QString trafo = element.attribute( "transform" );
+ if( !trafo.isEmpty() )
+ transform( trafo );
+}
+
+bool
+VPolyline::loadOasis( const QDomElement &element, KoOasisLoadingContext &context )
+{
+ setState( normal );
+
+ if( element.localName() == "line" )
+ {
+ KoPoint p1, p2;
+ p1.setX( KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "x1", QString::null ) ) );
+ p1.setY( KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "y1", QString::null ) ) );
+ p2.setX( KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "x2", QString::null ) ) );
+ p2.setY( KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "y2", QString::null ) ) );
+
+ m_points = QString( "%1,%2 %3,%4" ).arg( p1.x() ).arg( p1.y() ).arg( p2.x() ).arg( p2.y() );
+
+ moveTo( p1 );
+ lineTo( p2 );
+ }
+ else if( element.localName() == "polyline" )
+ {
+ m_points = element.attributeNS( KoXmlNS::draw, "points", QString::null );
+ init();
+ }
+
+ transformByViewbox( element, element.attributeNS( KoXmlNS::svg, "viewBox", QString::null ) );
+
+ QString trafo = element.attributeNS( KoXmlNS::draw, "transform", QString::null );
+ if( !trafo.isEmpty() )
+ transformOasis( trafo );
+
+ return VObject::loadOasis( element, context );
+}
+
+VPath*
+VPolyline::clone() const
+{
+ return new VPolyline( *this );
+}
diff --git a/karbon/shapes/vpolyline.h b/karbon/shapes/vpolyline.h
new file mode 100644
index 00000000..34da9716
--- /dev/null
+++ b/karbon/shapes/vpolyline.h
@@ -0,0 +1,50 @@
+/* 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.
+*/
+
+#ifndef __VPOLYLINE_H__
+#define __VPOLYLINE_H__
+
+#include "vcomposite.h"
+#include <qstring.h>
+
+class VPolyline : public VPath
+{
+public:
+ VPolyline( VObject* parent, VState state = edit );
+ //VPolyline( VObject* parent, VState state = edit );
+ //VPolyline( VObject* parent, const QString &points );
+
+ virtual QString name() const;
+
+ virtual void save( QDomElement& element ) const;
+ virtual void saveOasis( KoStore *store, KoXmlWriter *docWriter, KoGenStyles &mainStyles, int &index ) const;
+ virtual void load( const QDomElement& element );
+ virtual bool loadOasis( const QDomElement &element, KoOasisLoadingContext &context );
+
+ virtual VPath* clone() const;
+
+protected:
+ void init();
+
+private:
+ QString m_points;
+};
+
+#endif
+
diff --git a/karbon/shapes/vrectangle.cc b/karbon/shapes/vrectangle.cc
new file mode 100644
index 00000000..966c2bb2
--- /dev/null
+++ b/karbon/shapes/vrectangle.cc
@@ -0,0 +1,229 @@
+/* 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 "vrectangle.h"
+#include <klocale.h>
+#include <KoUnit.h>
+#include <KoStore.h>
+#include <KoXmlWriter.h>
+#include <KoXmlNS.h>
+#include <qdom.h>
+#include <kdebug.h>
+#include "vglobal.h"
+#include <vdocument.h>
+#include "vtransformcmd.h"
+
+VRectangle::VRectangle( VObject* parent, VState state )
+ : VPath( parent, state )
+{
+}
+
+VRectangle::VRectangle( VObject* parent,
+ const KoPoint& topLeft, double width, double height, double rx, double ry )
+ : VPath( parent ), m_topLeft( topLeft ), m_width( width), m_height( height ), m_rx( rx ), m_ry( ry )
+{
+ setDrawCenterNode();
+
+ if( m_rx < 0.0 ) m_rx = 0.0;
+ if( m_ry < 0.0 ) m_ry = 0.0;
+ // Catch case, when radius is larger than width or height:
+ if( m_rx > m_width * 0.5 )
+ m_rx = m_width * 0.5;
+ if( m_ry > m_height * 0.5 )
+ m_ry = m_height * 0.5;
+
+ init();
+}
+
+void
+VRectangle::init()
+{
+ if( m_rx == 0 && m_ry == 0 )
+ {
+ moveTo( m_topLeft );
+ lineTo( KoPoint( m_topLeft.x(), m_topLeft.y() - m_height ) );
+ lineTo( KoPoint( m_topLeft.x() + m_width, m_topLeft.y() - m_height ) );
+ lineTo( KoPoint( m_topLeft.x() + m_width, m_topLeft.y() ) );
+ }
+ else
+ {
+ double rx = m_rx;
+ double ry = m_ry;
+ double x = m_topLeft.x();
+ double y = m_topLeft.y();
+ moveTo( KoPoint( x + rx, y ) );
+ curveTo( KoPoint( x + rx * ( 1 - 0.552 ), y ),
+ KoPoint( x, y - ry * ( 1 - 0.552 ) ),
+ KoPoint( x, y - ry ) );
+ if( ry < m_height / 2 )
+ lineTo( KoPoint( x, y - m_height + ry ) );
+ curveTo( KoPoint( x, y - m_height + ry * ( 1 - 0.552 ) ),
+ KoPoint( x + rx * ( 1 - 0.552 ), y - m_height ),
+ KoPoint( x + rx, y - m_height ) );
+ if( rx < m_width / 2 )
+ lineTo( KoPoint( x + m_width - rx, y - m_height ) );
+ curveTo( KoPoint( x + m_width - rx * ( 1 - 0.552 ), y - m_height ),
+ KoPoint( x + m_width, y - m_height + ry * ( 1 - 0.552 ) ),
+ KoPoint( x + m_width, y - m_height + ry ) );
+ if( ry < m_height / 2 )
+ lineTo( KoPoint( x + m_width, y - ry ) );
+ curveTo( KoPoint( x + m_width, y - ry * ( 1 - 0.552 ) ),
+ KoPoint( x + m_width - rx * ( 1 - 0.552 ), y ),
+ KoPoint( x + m_width - rx, y ) );
+ if( rx < m_width / 2 )
+ lineTo( KoPoint( x + rx, y ) );
+ }
+ close();
+}
+
+QString
+VRectangle::name() const
+{
+ QString result = VObject::name();
+ return !result.isEmpty() ? result : i18n( "Rectangle" );
+}
+
+void
+VRectangle::save( QDomElement& element ) const
+{
+ VDocument *doc = document();
+ if( doc && doc->saveAsPath() )
+ {
+ VPath::save( element );
+ return;
+ }
+
+ if( state() != deleted )
+ {
+ QDomElement me = element.ownerDocument().createElement( "RECT" );
+ 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( "x", m_topLeft.x() );
+ me.setAttribute( "y", m_topLeft.y() );
+
+ me.setAttribute( "width", QString("%1pt").arg( m_width ) );
+ me.setAttribute( "height", QString("%1pt").arg( m_height ) );
+
+ me.setAttribute( "rx", m_rx );
+ me.setAttribute( "ry", m_ry );
+
+ QString transform = buildSvgTransform();
+ if( !transform.isEmpty() )
+ me.setAttribute( "transform", transform );
+ }
+}
+
+void
+VRectangle::saveOasis( KoStore *store, KoXmlWriter *docWriter, KoGenStyles &mainStyles, int &index ) const
+{
+ // do not save deleted objects
+ if( state() == deleted )
+ return;
+
+ // different rx/ry is not supported by oasis, so act like it is a normal path
+ if( m_rx != 0. && m_ry != 0. && m_rx != m_ry )
+ return VPath::saveOasis( store, docWriter, mainStyles, index );
+
+ docWriter->startElement( "draw:rect" );
+
+ //save all into pt
+ docWriter->addAttributePt( "svg:x", m_topLeft.x() );
+ docWriter->addAttributePt( "svg:y", m_topLeft.y()-m_height );
+ docWriter->addAttributePt( "svg:width", m_width );
+ docWriter->addAttributePt( "svg:height", m_height );
+
+ if( m_rx != 0. && m_ry != 0. && m_rx == m_ry )
+ docWriter->addAttributePt( "draw:corner-radius", m_rx );
+
+ VObject::saveOasis( store, docWriter, mainStyles, index );
+
+ QWMatrix tmpMat;
+ tmpMat.scale( 1, -1 );
+ tmpMat.translate( 0, -document()->height() );
+
+ QString transform = buildOasisTransform( m_matrix*tmpMat );
+ if( !transform.isEmpty() )
+ docWriter->addAttribute( "draw:transform", transform );
+
+ docWriter->endElement();
+}
+
+bool
+VRectangle::loadOasis( const QDomElement &element, KoOasisLoadingContext &context )
+{
+ setState( normal );
+
+ m_width = KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "width", QString::null ), 10.0 );
+ m_height = KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "height", QString::null ), 10.0 );
+
+ m_topLeft.setX( KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "x", QString::null ) ) );
+ m_topLeft.setY( m_height + KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "y", QString::null ) ) );
+
+ m_rx = m_ry = KoUnit::parseValue( element.attributeNS( KoXmlNS::draw, "corner-radius", QString::null ) );
+
+ init();
+
+ transformByViewbox( element, element.attributeNS( KoXmlNS::svg, "viewBox", QString::null ) );
+
+ QString trafo = element.attributeNS( KoXmlNS::draw, "transform", QString::null );
+ if( !trafo.isEmpty() )
+ transformOasis( trafo );
+
+ return VObject::loadOasis( element, context );
+}
+
+void
+VRectangle::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_width = KoUnit::parseValue( element.attribute( "width" ), 10.0 );
+ m_height = KoUnit::parseValue( element.attribute( "height" ), 10.0 );
+
+ m_topLeft.setX( KoUnit::parseValue( element.attribute( "x" ) ) );
+ m_topLeft.setY( KoUnit::parseValue( element.attribute( "y" ) ) );
+
+ m_rx = KoUnit::parseValue( element.attribute( "rx" ) );
+ m_ry = KoUnit::parseValue( element.attribute( "ry" ) );
+
+ init();
+
+ QString trafo = element.attribute( "transform" );
+ if( !trafo.isEmpty() )
+ transform( trafo );
+}
+
+VPath*
+VRectangle::clone() const
+{
+ return new VRectangle( *this );
+}
diff --git a/karbon/shapes/vrectangle.h b/karbon/shapes/vrectangle.h
new file mode 100644
index 00000000..04bd20d0
--- /dev/null
+++ b/karbon/shapes/vrectangle.h
@@ -0,0 +1,54 @@
+/* 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.
+*/
+
+#ifndef __VRECTANGLE_H__
+#define __VRECTANGLE_H__
+
+#include "vcomposite.h"
+#include <koffice_export.h>
+
+class KARBONBASE_EXPORT VRectangle : public VPath
+{
+public:
+ VRectangle( VObject* parent, VState state = edit );
+ VRectangle( VObject* parent,
+ const KoPoint& topLeft, double width, double height, double rx = 0.0, double ry = 0.0 );
+
+ virtual QString name() const;
+
+ virtual void save( QDomElement& element ) const;
+ virtual void saveOasis( KoStore *store, KoXmlWriter *docWriter, KoGenStyles &mainStyles, int &index ) const;
+ virtual void load( const QDomElement& element );
+ virtual bool loadOasis( const QDomElement &element, KoOasisLoadingContext &context );
+
+ virtual VPath* clone() const;
+
+protected:
+ void init();
+
+private:
+ KoPoint m_topLeft;
+ double m_width;
+ double m_height;
+ double m_rx;
+ double m_ry;
+};
+
+#endif
+
diff --git a/karbon/shapes/vsinus.cc b/karbon/shapes/vsinus.cc
new file mode 100644
index 00000000..a6c9ec4f
--- /dev/null
+++ b/karbon/shapes/vsinus.cc
@@ -0,0 +1,206 @@
+/* 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 <qwmatrix.h>
+
+#include "vglobal.h"
+#include "vsinus.h"
+#include "vtransformcmd.h"
+#include <klocale.h>
+#include <KoUnit.h>
+#include <qdom.h>
+#include <vdocument.h>
+
+VSinus::VSinus( VObject* parent, VState state )
+ : VPath( parent, state )
+{
+}
+
+VSinus::VSinus( VObject* parent,
+ const KoPoint& topLeft, double width, double height, uint periods )
+ : VPath( parent ), m_topLeft( topLeft ), m_width( width), m_height( height ), m_periods( periods )
+{
+ // We want at least 1 period:
+ if( m_periods < 1 )
+ m_periods = 1;
+ init();
+}
+
+void
+VSinus::init()
+{
+ KoPoint p1;
+ KoPoint p2;
+ KoPoint p3( 0.0, 0.0 );
+ moveTo( p3 );
+
+ for ( uint i = 0; i < m_periods; ++i )
+ {
+ p1.setX( i + 1.0/24.0 );
+ p1.setY( ( 2.0 * VGlobal::sqrt2 - 1.0 ) * VGlobal::one_7 );
+ p2.setX( i + 1.0/12.0 );
+ p2.setY( ( 4.0 * VGlobal::sqrt2 - 2.0 ) * VGlobal::one_7 );
+ p3.setX( i + 1.0/8.0 );
+ p3.setY( VGlobal::sqrt2 * 0.5 );
+ curveTo( p1, p2, p3 );
+
+ p1.setX( i + 1.0/6.0 );
+ p1.setY( ( 3.0 * VGlobal::sqrt2 + 2.0 ) * VGlobal::one_7 );
+ p2.setX( i + 5.0/24.0 );
+ p2.setY( 1.0 );
+ p3.setX( i + 1.0/4.0 );
+ p3.setY( 1.0 );
+ curveTo( p1, p2, p3 );
+
+ p1.setX( i + 7.0/24.0 );
+ p1.setY( 1.0 );
+ p2.setX( i + 1.0/3.0 );
+ p2.setY( ( 3.0 * VGlobal::sqrt2 + 2.0 ) * VGlobal::one_7 );
+ p3.setX( i + 3.0/8.0 );
+ p3.setY( VGlobal::sqrt2 * 0.5 );
+ curveTo( p1, p2, p3 );
+
+ p1.setX( i + 5.0/12.0 );
+ p1.setY( ( 4.0 * VGlobal::sqrt2 - 2.0 ) * VGlobal::one_7 );
+ p2.setX( i + 11.0/24.0 );
+ p2.setY( ( 2.0 * VGlobal::sqrt2 - 1.0 ) * VGlobal::one_7 );
+ p3.setX( i + 1.0/2.0 );
+ p3.setY( 0.0 );
+ curveTo( p1, p2, p3 );
+
+ p1.setX( i + 13.0/24.0 );
+ p1.setY( -( 2.0 * VGlobal::sqrt2 - 1.0 ) * VGlobal::one_7 );
+ p2.setX( i + 7.0/12.0 );
+ p2.setY( -( 4.0 * VGlobal::sqrt2 - 2.0 ) * VGlobal::one_7 );
+ p3.setX( i + 5.0/8.0 );
+ p3.setY( -VGlobal::sqrt2 * 0.5 );
+ curveTo( p1, p2, p3 );
+
+ p1.setX( i + 2.0/3.0 );
+ p1.setY( -( 3.0 * VGlobal::sqrt2 + 2.0 ) * VGlobal::one_7 );
+ p2.setX( i + 17.0/24.0 );
+ p2.setY( -1.0 );
+ p3.setX( i + 3.0/4.0 );
+ p3.setY( -1.0 );
+ curveTo( p1, p2, p3 );
+
+ p1.setX( i + 19.0/24.0 );
+ p1.setY( -1.0 );
+ p2.setX( i + 5.0/6.0 );
+ p2.setY( -( 3.0 * VGlobal::sqrt2 + 2.0 ) * VGlobal::one_7 );
+ p3.setX( i + 7.0/8.0 );
+ p3.setY( -VGlobal::sqrt2 * 0.5 );
+ curveTo( p1, p2, p3 );
+
+ p1.setX( i + 11.0/12.0 );
+ p1.setY( -( 4.0 * VGlobal::sqrt2 - 2.0 ) * VGlobal::one_7 );
+ p2.setX( i + 23.0/24.0 );
+ p2.setY( -( 2.0 * VGlobal::sqrt2 - 1.0 ) * VGlobal::one_7 );
+ p3.setX( i + 1.0 );
+ p3.setY( 0.0 );
+ curveTo( p1, p2, p3 );
+ }
+
+ // Translate and scale:
+ QWMatrix m;
+ m.translate( m_topLeft.x(), m_topLeft.y() - m_height * 0.5 );
+ m.scale( m_width / m_periods, m_height * 0.5 );
+
+ // only tranform the path data
+ VTransformCmd cmd( 0L, m );
+ cmd.VVisitor::visitVPath( *this );
+
+ m_matrix.reset();
+}
+
+QString
+VSinus::name() const
+{
+ QString result = VObject::name();
+ return !result.isEmpty() ? result : i18n( "Sinus" );
+}
+
+void
+VSinus::save( QDomElement& element ) const
+{
+ VDocument *doc = document();
+ if( doc && doc->saveAsPath() )
+ {
+ VPath::save( element );
+ return;
+ }
+
+ if( state() != deleted )
+ {
+ QDomElement me = element.ownerDocument().createElement( "SINUS" );
+ 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( "x", m_topLeft.x() );
+ me.setAttribute( "y", m_topLeft.y() );
+
+ me.setAttribute( "width", m_width );
+ me.setAttribute( "height", m_height );
+
+ me.setAttribute( "periods", m_periods );
+
+ QString transform = buildSvgTransform();
+ if( !transform.isEmpty() )
+ me.setAttribute( "transform", transform );
+ }
+}
+
+void
+VSinus::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_width = KoUnit::parseValue( element.attribute( "width" ), 10.0 );
+ m_height = KoUnit::parseValue( element.attribute( "height" ), 10.0 );
+
+ m_topLeft.setX( KoUnit::parseValue( element.attribute( "x" ) ) );
+ m_topLeft.setY( KoUnit::parseValue( element.attribute( "y" ) ) );
+
+ m_periods = element.attribute( "periods" ).toUInt();
+
+ init();
+
+ QString trafo = element.attribute( "transform" );
+ if( !trafo.isEmpty() )
+ transform( trafo );
+}
+
+VPath*
+VSinus::clone() const
+{
+ return new VSinus( *this );
+}
+
diff --git a/karbon/shapes/vsinus.h b/karbon/shapes/vsinus.h
new file mode 100644
index 00000000..eb8d4f00
--- /dev/null
+++ b/karbon/shapes/vsinus.h
@@ -0,0 +1,51 @@
+/* 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.
+*/
+
+#ifndef __VSINUS_H__
+#define __VSINUS_H__
+
+#include "vcomposite.h"
+#include <koffice_export.h>
+
+class KARBONBASE_EXPORT VSinus : public VPath
+{
+public:
+ VSinus( VObject* parent, VState state = edit );
+ VSinus( VObject* parent,
+ const KoPoint& topLeft, double width, double height, uint periods );
+
+ virtual QString name() const;
+
+ virtual void save( QDomElement& element ) const;
+ virtual void load( const QDomElement& element );
+
+ virtual VPath* clone() const;
+
+protected:
+ void init();
+
+private:
+ KoPoint m_topLeft;
+ double m_width;
+ double m_height;
+ uint m_periods;
+};
+
+#endif
+
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 );
+}
diff --git a/karbon/shapes/vspiral.h b/karbon/shapes/vspiral.h
new file mode 100644
index 00000000..2b80f6ad
--- /dev/null
+++ b/karbon/shapes/vspiral.h
@@ -0,0 +1,60 @@
+/* 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.
+*/
+
+#ifndef __VSPIRAL_H__
+#define __VSPIRAL_H__
+
+#include "vcomposite.h"
+#include <koffice_export.h>
+
+class KARBONBASE_EXPORT VSpiral : public VPath
+{
+public:
+ enum VSpiralType
+ {
+ round,
+ rectangular
+ };
+ VSpiral( VObject* parent, VState state = edit );
+ VSpiral( VObject* parent,
+ const KoPoint& center, double radius, uint segments,
+ double fade, bool clockwise, double angle = 0.0, VSpiralType type = round );
+
+ virtual QString name() const;
+
+ virtual void save( QDomElement& element ) const;
+ virtual void load( const QDomElement& element );
+
+ virtual VPath* clone() const;
+
+protected:
+ void init();
+
+private:
+ KoPoint m_center;
+ double m_radius;
+ double m_fade;
+ uint m_segments;
+ bool m_clockwise;
+ double m_angle;
+ VSpiralType m_type;
+};
+
+#endif
+
diff --git a/karbon/shapes/vstar.cc b/karbon/shapes/vstar.cc
new file mode 100644
index 00000000..98391272
--- /dev/null
+++ b/karbon/shapes/vstar.cc
@@ -0,0 +1,348 @@
+/* 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 "vstar.h"
+#include "vtransformcmd.h"
+#include <klocale.h>
+#include <KoUnit.h>
+#include <vdocument.h>
+
+VStar::VStar( VObject* parent, VState state )
+ : VPath( parent, state )
+{
+}
+
+VStar::VStar( VObject* parent,
+ const KoPoint& center, double outerRadius, double innerRadius,
+ uint edges, double angle, uint innerAngle, double roundness, VStarType type )
+ : VPath( parent ), m_center( center), m_outerRadius( outerRadius ), m_innerRadius( innerRadius), m_edges( edges ), m_angle( angle ), m_innerAngle( innerAngle ), m_roundness( roundness ), m_type( type )
+{
+ init();
+}
+
+void
+VStar::init()
+{
+ double angle = m_angle;
+
+ // A star should have at least 3 edges:
+ if( m_edges < 3 )
+ m_edges = 3;
+
+ // Make sure, radii are positive:
+ if( m_outerRadius < 0.0 )
+ m_outerRadius = -m_outerRadius;
+
+ if( m_innerRadius < 0.0 )
+ m_innerRadius = -m_innerRadius;
+
+ // trick for spoke, wheel (libart bug?)
+ if( m_type == spoke || m_type == wheel && m_roundness == 0.0 )
+ m_roundness = 0.01;
+
+ // We start at angle + VGlobal::pi_2:
+ KoPoint p2, p3;
+ KoPoint p(
+ m_outerRadius * cos( angle + VGlobal::pi_2 ),
+ m_outerRadius * sin( angle + VGlobal::pi_2 ) );
+ moveTo( p );
+
+ double inAngle = VGlobal::twopi / 360 * m_innerAngle;
+
+ if( m_type == star )
+ {
+ int j = ( m_edges % 2 == 0 ) ? ( m_edges - 2 ) / 2 : ( m_edges - 1 ) / 2;
+ //innerRadius = getOptimalInnerRadius( outerRadius, edges, innerAngle );
+ int jumpto = 0;
+ bool discontinueous = ( m_edges % 4 == 2 );
+
+ double outerRoundness = ( VGlobal::twopi * m_outerRadius * m_roundness ) / m_edges;
+ double nextOuterAngle;
+
+ for ( uint i = 1; i < m_edges + 1; ++i )
+ {
+ double nextInnerAngle = angle + inAngle + VGlobal::pi_2 + VGlobal::twopi / m_edges * ( jumpto + 0.5 );
+ p.setX( m_innerRadius * cos( nextInnerAngle ) );
+ p.setY( m_innerRadius * sin( nextInnerAngle ) );
+ if( m_roundness == 0.0 )
+ lineTo( p );
+ else
+ {
+ nextOuterAngle = angle + VGlobal::pi_2 + VGlobal::twopi / m_edges * jumpto;
+ p2.setX( m_outerRadius * cos( nextOuterAngle ) -
+ cos( angle + VGlobal::twopi / m_edges * jumpto ) * outerRoundness );
+ p2.setY( m_outerRadius * sin( nextOuterAngle ) -
+ sin( angle + VGlobal::twopi / m_edges * jumpto ) * outerRoundness );
+
+ curveTo( p2, p, p );
+ }
+
+ jumpto = ( i * j ) % m_edges;
+ nextInnerAngle = angle + inAngle + VGlobal::pi_2 + VGlobal::twopi / m_edges * ( jumpto - 0.5 );
+ p.setX( m_innerRadius * cos( nextInnerAngle ) );
+ p.setY( m_innerRadius * sin( nextInnerAngle ) );
+ lineTo( p );
+
+ nextOuterAngle = angle + VGlobal::pi_2 + VGlobal::twopi / m_edges * jumpto;
+ p.setX( m_outerRadius * cos( nextOuterAngle ) );
+ p.setY( m_outerRadius * sin( nextOuterAngle ) );
+
+ if( m_roundness == 0.0 )
+ lineTo( p );
+ else
+ {
+ p2.setX( m_innerRadius * cos( nextInnerAngle ) );
+ p2.setY( m_innerRadius * sin( nextInnerAngle ) );
+
+ p3.setX( m_outerRadius * cos( nextOuterAngle ) +
+ cos( angle + VGlobal::twopi / m_edges * jumpto ) * outerRoundness );
+ p3.setY( m_outerRadius * sin( nextOuterAngle ) +
+ sin( angle + VGlobal::twopi / m_edges * jumpto ) * outerRoundness );
+
+ curveTo( p2, p3, p );
+ }
+ if( discontinueous && i == ( m_edges / 2 ) )
+ {
+ angle += VGlobal::pi;
+ nextOuterAngle = angle + VGlobal::pi_2 + VGlobal::twopi / m_edges * jumpto;
+ p.setX( m_outerRadius * cos( nextOuterAngle ) );
+ p.setY( m_outerRadius * sin( nextOuterAngle ) );
+ moveTo( p );
+ }
+ }
+ }
+ else
+ {
+ if( m_type == wheel || m_type == spoke )
+ m_innerRadius = 0.0;
+
+ double innerRoundness = ( VGlobal::twopi * m_innerRadius * m_roundness ) / m_edges;
+ double outerRoundness = ( VGlobal::twopi * m_outerRadius * m_roundness ) / m_edges;
+
+ for ( uint i = 0; i < m_edges; ++i )
+ {
+ double nextOuterAngle = angle + VGlobal::pi_2 + VGlobal::twopi / m_edges * ( i + 1.0 );
+ double nextInnerAngle = angle + inAngle + VGlobal::pi_2 + VGlobal::twopi / m_edges * ( i + 0.5 );
+ if( m_type != polygon )
+ {
+ p.setX( m_innerRadius * cos( nextInnerAngle ) );
+ p.setY( m_innerRadius * sin( nextInnerAngle ) );
+
+ if( m_roundness == 0.0 )
+ lineTo( p );
+ else
+ {
+ p2.setX( m_outerRadius *
+ cos( angle + VGlobal::pi_2 + VGlobal::twopi / m_edges * ( i ) ) -
+ cos( angle + VGlobal::twopi / m_edges * ( i ) ) * outerRoundness );
+ p2.setY( m_outerRadius *
+ sin( angle + VGlobal::pi_2 + VGlobal::twopi / m_edges * ( i ) ) -
+ sin( angle + VGlobal::twopi / m_edges * ( i ) ) * outerRoundness );
+
+ p3.setX( m_innerRadius * cos( nextInnerAngle ) +
+ cos( angle + inAngle + VGlobal::twopi / m_edges * ( i + 0.5 ) ) * innerRoundness );
+ p3.setY( m_innerRadius * sin( nextInnerAngle ) +
+ sin( angle + inAngle + VGlobal::twopi / m_edges * ( i + 0.5 ) ) * innerRoundness );
+
+ if( m_type == gear )
+ {
+ lineTo( p2 );
+ lineTo( p3 );
+ lineTo( p );
+ }
+ else
+ curveTo( p2, p3, p );
+ }
+ }
+
+ p.setX( m_outerRadius * cos( nextOuterAngle ) );
+ p.setY( m_outerRadius * sin( nextOuterAngle ) );
+
+ if( m_roundness == 0.0 )
+ lineTo( p );
+ else
+ {
+ p2.setX( m_innerRadius * cos( nextInnerAngle ) -
+ cos( angle + inAngle + VGlobal::twopi / m_edges * ( i + 0.5 ) ) * innerRoundness );
+ p2.setY( m_innerRadius * sin( nextInnerAngle ) -
+ sin( angle + inAngle + VGlobal::twopi / m_edges * ( i + 0.5 ) ) * innerRoundness );
+
+ p3.setX( m_outerRadius * cos( nextOuterAngle ) +
+ cos( angle + VGlobal::twopi / m_edges * ( i + 1.0 ) ) * outerRoundness );
+ p3.setY( m_outerRadius * sin( nextOuterAngle ) +
+ sin( angle + VGlobal::twopi / m_edges * ( i + 1.0 ) ) * outerRoundness );
+
+ if( m_type == gear )
+ {
+ lineTo( p2 );
+ lineTo( p3 );
+ lineTo( p );
+ }
+ else
+ curveTo( p2, p3, p );
+ }
+ }
+ }
+ if( m_type == wheel || m_type == framed_star )
+ {
+ close();
+ for ( int i = m_edges - 1; i >= 0; --i )
+ {
+ double nextOuterAngle = angle + VGlobal::pi_2 + VGlobal::twopi / m_edges * ( i + 1.0 );
+ p.setX( m_outerRadius * cos( nextOuterAngle ) );
+ p.setY( m_outerRadius * sin( nextOuterAngle ) );
+ lineTo( p );
+ }
+ }
+ close();
+
+ // translate path to center:
+ QWMatrix m;
+ m.translate( m_center.x(), m_center.y() );
+
+ // only tranform the path data
+ VTransformCmd cmd( 0L, m );
+ cmd.VVisitor::visitVPath( *this );
+
+ setFillRule( evenOdd );
+
+ m_matrix.reset();
+}
+
+double
+VStar::getOptimalInnerRadius( uint edges, double outerRadius, uint /*innerAngle*/ )
+{
+ int j = (edges % 2 == 0 ) ? ( edges - 2 ) / 2 : ( edges - 1 ) / 2;
+
+ // get two well chosen lines of the star
+ KoPoint p1( outerRadius * cos( VGlobal::pi_2 ), outerRadius * sin( VGlobal::pi_2 ) );
+ int jumpto = ( j ) % edges;
+ double nextOuterAngle = VGlobal::pi_2 + VGlobal::twopi / edges * jumpto;
+ KoPoint p2( outerRadius * cos( nextOuterAngle ), outerRadius * sin( nextOuterAngle ) );
+
+ nextOuterAngle = VGlobal::pi_2 + VGlobal::twopi / edges;
+ KoPoint p3( outerRadius * cos( nextOuterAngle ),
+ outerRadius * sin( nextOuterAngle ) );
+ jumpto = ( edges - j + 1 ) % edges;
+ nextOuterAngle = VGlobal::pi_2 + VGlobal::twopi / edges * jumpto;
+ KoPoint p4( outerRadius * cos( nextOuterAngle ), outerRadius * sin( nextOuterAngle ) );
+
+ // calc (x, y) -> intersection point
+ double b1 = ( p2.y() - p1.y() ) / ( p2.x() - p1.x() );
+ double b2 = ( p4.y() - p3.y() ) / ( p4.x() - p3.x() );
+ double a1 = p1.y() - b1 * p1.x();
+ double a2 = p3.y() - b2 * p3.x();
+ double x = -( a1 - a2 ) / ( b1 - b2 );
+ double y = a1 + b1 * x;
+ // calc inner radius from intersection point and center
+ return sqrt( x * x + y * y );
+}
+
+QString
+VStar::name() const
+{
+ QString result = VObject::name();
+ return !result.isEmpty() ? result : i18n( "Star" );
+}
+
+void
+VStar::save( QDomElement& element ) const
+{
+ VDocument *doc = document();
+ if( doc && doc->saveAsPath() )
+ {
+ VPath::save( element );
+ return;
+ }
+
+ if( state() != deleted )
+ {
+ QDomElement me = element.ownerDocument().createElement( "STAR" );
+ 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( "outerradius", m_outerRadius );
+ me.setAttribute( "innerradius", m_innerRadius );
+ me.setAttribute( "edges", m_edges );
+
+ me.setAttribute( "angle", m_angle );
+ me.setAttribute( "innerangle", m_innerAngle );
+
+ me.setAttribute( "roundness", m_roundness );
+
+ me.setAttribute( "type", m_type );
+
+ QString transform = buildSvgTransform();
+ if( !transform.isEmpty() )
+ me.setAttribute( "transform", transform );
+ }
+}
+
+void
+VStar::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_center.setX( KoUnit::parseValue( element.attribute( "cx" ) ) );
+ m_center.setY( KoUnit::parseValue( element.attribute( "cy" ) ) );
+
+ m_outerRadius = KoUnit::parseValue( element.attribute( "outerradius" ) );
+ m_innerRadius = KoUnit::parseValue( element.attribute( "innerradius" ) );
+ m_edges = element.attribute( "edges" ).toUInt();
+
+ m_innerAngle = element.attribute( "innerangle" ).toUInt();
+ m_angle = element.attribute( "angle" ).toDouble();
+
+ m_roundness = element.attribute( "roundness" ).toDouble();
+
+ m_type =(VStar::VStarType) element.attribute( "type" ).toInt();
+
+ init();
+
+ QString trafo = element.attribute( "transform" );
+ if( !trafo.isEmpty() )
+ transform( trafo );
+}
+
+VPath*
+VStar::clone() const
+{
+ return new VStar( *this );
+}
diff --git a/karbon/shapes/vstar.h b/karbon/shapes/vstar.h
new file mode 100644
index 00000000..7b7ec098
--- /dev/null
+++ b/karbon/shapes/vstar.h
@@ -0,0 +1,91 @@
+/* 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.
+*/
+
+#ifndef __VSTAR_H__
+#define __VSTAR_H__
+
+#include "vcomposite.h"
+#include <koffice_export.h>
+/**
+ * This shape offers star-like shapes with a lot of parameters :
+ *
+ * Types :
+ *
+ * Star - fully connected star shape.
+ * Star outline - like star but without the cross connections.
+ * Framed star - like star outline but with an enclosing path.
+ * Spoke - basically a star outline with inner radius of zero.
+ * Wheel - like spoke but with enclosing path.
+ * Polygon - like VPolygon.
+ * Gear - variant on star outline, resembling the KDE gear.
+ *
+ * Parameters :
+ *
+ * Edges - number of edges, which must be greater or equal to 3.
+ * Outer radius - radius amount of circumcircle of the star.
+ * Inner radius - inner radius where star has to connect to. This value
+ * doesn't apply to polygon, spoke and wheel.
+ * Inner angle - extra radius amount for inner radius.
+ * Roundness - uses curves instead of lines for the star shape.
+ */
+class KARBONBASE_EXPORT VStar : public VPath
+{
+public:
+ enum VStarType
+ {
+ star_outline,
+ spoke,
+ wheel,
+ polygon,
+ framed_star,
+ star,
+ gear
+ };
+ VStar( VObject* parent, VState state = edit );
+ VStar( VObject* parent,
+ const KoPoint& center, double outerRadius, double innerRadius,
+ uint edges, double angle = 0.0, uint innerAngle = 0,
+ double roundness = 0.0, VStarType type = star_outline );
+
+ static double getOptimalInnerRadius( uint edges, double outerRadius, uint innerAngle );
+
+ virtual QString name() const;
+
+
+ virtual void save( QDomElement& element ) const;
+ virtual void load( const QDomElement& element );
+
+ virtual VPath* clone() const;
+
+protected:
+ void init();
+
+private:
+ KoPoint m_center;
+ double m_outerRadius;
+ double m_innerRadius;
+ uint m_edges;
+ double m_angle;
+ double m_innerAngle;
+ double m_roundness;
+ VStarType m_type;
+};
+
+#endif
+