22#include "vtransformcmd.h"
26#include <KoXmlWriter.h>
31#include <core/vfill.h>
33VEllipse::VEllipse(
VObject* parent, VState state ) :
VPath( parent, state )
37VEllipse::VEllipse(
VObject* parent,
38 const KoPoint& topLeft,
double width,
double height,
39 VEllipseType type,
double startAngle,
double endAngle )
40 :
VPath( parent ), m_type( type ), m_startAngle( startAngle ), m_endAngle( endAngle )
46 m_center.setX( topLeft.x() + m_rx );
47 m_center.setY( topLeft.y() + m_ry );
57 if( m_startAngle < m_endAngle )
58 nsegs = int( floor( ( m_endAngle - m_startAngle ) / 90.0 ) );
60 nsegs = 4 - int( ceil( ( m_startAngle - m_endAngle ) / 90.0 ) );
61 double startAngle = m_startAngle - 90.0;
62 if( startAngle < 0 ) startAngle += 360.0;
63 startAngle = VGlobal::pi_2 * ( startAngle / 90.0 );
64 double endAngle = m_endAngle - 90.0;
65 if( endAngle < 0 ) endAngle += 360.0;
66 endAngle = VGlobal::pi_2 * ( endAngle / 90.0 );
68 double currentAngle = -startAngle - VGlobal::pi_2;
69 KoPoint start( 0.5 * sin( -startAngle ), 0.5 * cos( -startAngle ) );
70 moveTo( KoPoint( start.x(), start.y() ) );
71 double midAngle = currentAngle + VGlobal::pi_2 / 2.0;
72 double midAmount = 0.5 / sin( VGlobal::pi_2 / 2.0 );
73 for(
int i = 0;i < nsegs;i++ )
75 midAngle -= VGlobal::pi_2;
76 arcTo( KoPoint( cos( midAngle ) * midAmount, -sin( midAngle ) * midAmount ),
77 KoPoint( 0.5 * sin( currentAngle ), 0.5 * cos( currentAngle ) ), 0.5 );
78 currentAngle -= VGlobal::pi_2;
80 double rest = ( -endAngle - VGlobal::pi_2 - currentAngle ) * 90.0 / VGlobal::pi_2;
85 midAngle = currentAngle - ( -rest / 360.0 ) * VGlobal::pi;
86 midAmount = 0.5 / cos( currentAngle - midAngle );
87 KoPoint end( 0.5 * sin( -endAngle ), 0.5 * cos( -endAngle ) );
88 arcTo( KoPoint( cos( midAngle ) * midAmount, -sin( midAngle ) * midAmount ),
89 KoPoint( 0.5 * sin( -endAngle ), 0.5 * cos( -endAngle ) ), 0.5 );
92 lineTo( KoPoint( 0.0, 0.0 ) );
98 m.translate( m_center.x(), m_center.y() );
99 m.scale( 2.0 * m_rx, 2.0 * m_ry );
102 VTransformCmd cmd( 0L, m );
103 cmd.VVisitor::visitVPath( *
this );
112 return !result.isEmpty() ? result : i18n(
"Ellipse" );
116VEllipse::save( TQDomElement& element )
const
119 if( doc && doc->saveAsPath() )
127 TQDomElement me = element.ownerDocument().createElement(
"ELLIPSE" );
128 element.appendChild( me );
132 VTransformCmd cmd( 0L, m_matrix.invert() );
134 path.VObject::save( me );
137 me.setAttribute(
"cx", m_center.x() );
138 me.setAttribute(
"cy", m_center.y() );
140 me.setAttribute(
"rx", m_rx );
141 me.setAttribute(
"ry", m_ry );
143 me.setAttribute(
"start-angle", m_startAngle );
144 me.setAttribute(
"end-angle", m_endAngle );
147 me.setAttribute(
"kind",
"cut" );
148 else if( m_type == section )
149 me.setAttribute(
"kind",
"section" );
150 else if( m_type == arc )
151 me.setAttribute(
"kind",
"arc" );
153 me.setAttribute(
"kind",
"full" );
155 TQString transform = buildSvgTransform();
156 if( !transform.isEmpty() )
157 me.setAttribute(
"transform", transform );
162VEllipse::saveOasis( KoStore *store, KoXmlWriter *docWriter, KoGenStyles &mainStyles,
int &index )
const
168 docWriter->startElement(
"draw:ellipse" );
171 docWriter->addAttributePt(
"svg:cx", m_center.x() );
172 docWriter->addAttributePt(
"svg:cy", m_center.y() );
173 docWriter->addAttributePt(
"svg:rx", m_rx );
174 docWriter->addAttributePt(
"svg:ry", m_ry );
177 docWriter->addAttribute(
"draw:kind",
"full" );
182 if( m_type == section )
183 docWriter->addAttribute(
"draw:kind",
"cut" );
184 else if( m_type == cut )
185 docWriter->addAttribute(
"draw:kind",
"section" );
187 docWriter->addAttribute(
"draw:kind",
"arc" );
189 docWriter->addAttribute(
"draw:start-angle", m_startAngle );
190 docWriter->addAttribute(
"draw:end-angle", m_endAngle );
196 tmpMat.scale( 1, -1 );
197 tmpMat.translate( 0, -
document()->height() );
199 TQString transform = buildOasisTransform( m_matrix*tmpMat );
200 if( !transform.isEmpty() )
201 docWriter->addAttribute(
"draw:transform", transform );
203 docWriter->endElement();
207VEllipse::loadOasis(
const TQDomElement &element, KoOasisLoadingContext &context )
211 if( element.tagName() ==
"ellipse" )
213 if( element.hasAttributeNS( KoXmlNS::svg,
"rx" ) )
214 m_rx = KoUnit::parseValue( element.attributeNS( KoXmlNS::svg,
"rx", TQString() ) );
216 m_rx = 0.5 * KoUnit::parseValue( element.attributeNS( KoXmlNS::svg,
"width", TQString() ) );
218 if( element.hasAttributeNS( KoXmlNS::svg,
"ry" ) )
219 m_ry = KoUnit::parseValue( element.attributeNS( KoXmlNS::svg,
"ry", TQString() ) );
221 m_ry = 0.5 * KoUnit::parseValue( element.attributeNS( KoXmlNS::svg,
"height", TQString() ) );
224 else if( element.tagName() ==
"circle" )
226 if( element.hasAttributeNS( KoXmlNS::svg,
"r" ) )
227 m_rx = m_ry = KoUnit::parseValue( element.attributeNS( KoXmlNS::svg,
"r", TQString() ) );
229 m_rx = m_ry = 0.5 * KoUnit::parseValue( element.attributeNS( KoXmlNS::svg,
"width", TQString() ) );
232 if( element.hasAttributeNS( KoXmlNS::svg,
"cx" ) )
233 m_center.setX( KoUnit::parseValue( element.attributeNS( KoXmlNS::svg,
"cx", TQString() ) ) );
235 m_center.setX( m_rx + KoUnit::parseValue( element.attributeNS( KoXmlNS::svg,
"x", TQString() ) ) );
237 if( element.hasAttributeNS( KoXmlNS::svg,
"cy" ) )
238 m_center.setY( KoUnit::parseValue( element.attributeNS( KoXmlNS::svg,
"cy", TQString() ) ) );
240 m_center.setY( m_ry + KoUnit::parseValue( element.attributeNS( KoXmlNS::svg,
"y", TQString() ) ) );
244 TQString kind = element.attributeNS( KoXmlNS::draw,
"kind", TQString() );
247 else if( kind ==
"section" )
249 else if( kind ==
"arc" )
254 double startAngle = element.attributeNS( KoXmlNS::draw,
"start-angle", TQString() ).toDouble();
255 double endAngle = element.attributeNS( KoXmlNS::draw,
"end-angle", TQString() ).toDouble();
259 m_startAngle = 360.0 - endAngle;
260 m_endAngle = 360.0 - startAngle;
265 m_startAngle = startAngle;
266 m_endAngle = endAngle;
268 transformByViewbox( element, element.attributeNS( KoXmlNS::svg,
"viewBox", TQString() ) );
270 TQString trafo = element.attributeNS( KoXmlNS::draw,
"transform", TQString() );
271 if( !trafo.isEmpty() )
272 transformOasis( trafo );
278VEllipse::load(
const TQDomElement& element )
282 TQDomNodeList list = element.childNodes();
283 for( uint i = 0; i < list.count(); ++i )
284 if( list.item( i ).isElement() )
287 m_rx = KoUnit::parseValue( element.attribute(
"rx" ) );
288 m_ry = KoUnit::parseValue( element.attribute(
"ry" ) );
290 m_center.setX( KoUnit::parseValue( element.attribute(
"cx" ) ) );
291 m_center.setY( KoUnit::parseValue( element.attribute(
"cy" ) ) );
293 m_startAngle = element.attribute(
"start-angle" ).toDouble();
294 m_endAngle = element.attribute(
"end-angle" ).toDouble();
296 if( element.attribute(
"kind" ) ==
"cut" )
298 else if( element.attribute(
"kind" ) ==
"section" )
300 else if( element.attribute(
"kind" ) ==
"arc" )
307 TQString trafo = element.attribute(
"transform" );
308 if( !trafo.isEmpty() )
315 return new VEllipse( *
this );
The base class for all karbon objects.
virtual void setState(const VState state)
Sets the state to a specified new state.
virtual void saveOasis(KoStore *store, KoXmlWriter *docWriter, KoGenStyles &mainStyles, int &index) const
Save this object's state to OpenDocument.
@ deleted
deleted, nearly dead
@ normal
visible, not active
virtual TQString name() const
Returns the name of the object.
virtual void load(const TQDomElement &element)
Load this object's state from xml and initialize this object accordingly.
VDocument * document() const
Return document the object belongs to.
virtual bool loadOasis(const TQDomElement &element, KoOasisLoadingContext &context)
Load this object's state from OpenDocument and initialize this object accordingly.
VState state() const
Get the state the object is in.
A composite path consists of one or many subpaths.
void close()
Closes the current subpath.
bool arcTo(const KoPoint &p1, const KoPoint &p2, double r)
A convenience function to aproximate a circular arc with a bezier curve.
virtual void save(TQDomElement &element) const
Save this object's state to xml.
virtual VPath * clone() const
Create an exact copy of this object.