00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "vellipse.h"
00022 #include "vtransformcmd.h"
00023 #include <klocale.h>
00024 #include <KoUnit.h>
00025 #include <KoStore.h>
00026 #include <KoXmlWriter.h>
00027 #include <KoXmlNS.h>
00028 #include <vglobal.h>
00029 #include <vdocument.h>
00030 #include <qdom.h>
00031 #include <core/vfill.h>
00032
00033 VEllipse::VEllipse( VObject* parent, VState state ) : VPath( parent, state )
00034 {
00035 }
00036
00037 VEllipse::VEllipse( VObject* parent,
00038 const KoPoint& topLeft, double width, double height,
00039 VEllipseType type, double startAngle, double endAngle )
00040 : VPath( parent ), m_type( type ), m_startAngle( startAngle ), m_endAngle( endAngle )
00041 {
00042 setDrawCenterNode();
00043
00044 m_rx = width / 2.0;
00045 m_ry = height / 2.0;
00046 m_center.setX( topLeft.x() + m_rx );
00047 m_center.setY( topLeft.y() + m_ry );
00048
00049 init();
00050 }
00051
00052 void
00053 VEllipse::init()
00054 {
00055
00056 int nsegs;
00057 if( m_startAngle < m_endAngle )
00058 nsegs = int( floor( ( m_endAngle - m_startAngle ) / 90.0 ) );
00059 else
00060 nsegs = 4 - int( ceil( ( m_startAngle - m_endAngle ) / 90.0 ) );
00061 double startAngle = m_startAngle - 90.0;
00062 if( startAngle < 0 ) startAngle += 360.0;
00063 startAngle = VGlobal::pi_2 * ( startAngle / 90.0 );
00064 double endAngle = m_endAngle - 90.0;
00065 if( endAngle < 0 ) endAngle += 360.0;
00066 endAngle = VGlobal::pi_2 * ( endAngle / 90.0 );
00067
00068 double currentAngle = -startAngle - VGlobal::pi_2;
00069 KoPoint start( 0.5 * sin( -startAngle ), 0.5 * cos( -startAngle ) );
00070 moveTo( KoPoint( start.x(), start.y() ) );
00071 double midAngle = currentAngle + VGlobal::pi_2 / 2.0;
00072 double midAmount = 0.5 / sin( VGlobal::pi_2 / 2.0 );
00073 for( int i = 0;i < nsegs;i++ )
00074 {
00075 midAngle -= VGlobal::pi_2;
00076 arcTo( KoPoint( cos( midAngle ) * midAmount, -sin( midAngle ) * midAmount ),
00077 KoPoint( 0.5 * sin( currentAngle ), 0.5 * cos( currentAngle ) ), 0.5 );
00078 currentAngle -= VGlobal::pi_2;
00079 }
00080 double rest = ( -endAngle - VGlobal::pi_2 - currentAngle ) * 90.0 / VGlobal::pi_2;
00081 if( rest > 0 )
00082 rest -= 360.0;
00083 if( rest != 0 )
00084 {
00085 midAngle = currentAngle - ( -rest / 360.0 ) * VGlobal::pi;
00086 midAmount = 0.5 / cos( currentAngle - midAngle );
00087 KoPoint end( 0.5 * sin( -endAngle ), 0.5 * cos( -endAngle ) );
00088 arcTo( KoPoint( cos( midAngle ) * midAmount, -sin( midAngle ) * midAmount ),
00089 KoPoint( 0.5 * sin( -endAngle ), 0.5 * cos( -endAngle ) ), 0.5 );
00090 }
00091 if( m_type == cut )
00092 lineTo( KoPoint( 0.0, 0.0 ) );
00093 if( m_type != arc )
00094 close();
00095
00096
00097 QWMatrix m;
00098 m.translate( m_center.x(), m_center.y() );
00099 m.scale( 2.0 * m_rx, 2.0 * m_ry );
00100
00101
00102 VTransformCmd cmd( 0L, m );
00103 cmd.VVisitor::visitVPath( *this );
00104
00105 m_matrix.reset();
00106 }
00107
00108 QString
00109 VEllipse::name() const
00110 {
00111 QString result = VObject::name();
00112 return !result.isEmpty() ? result : i18n( "Ellipse" );
00113 }
00114
00115 void
00116 VEllipse::save( QDomElement& element ) const
00117 {
00118 VDocument *doc = document();
00119 if( doc && doc->saveAsPath() )
00120 {
00121 VPath::save( element );
00122 return;
00123 }
00124
00125 if( state() != deleted )
00126 {
00127 QDomElement me = element.ownerDocument().createElement( "ELLIPSE" );
00128 element.appendChild( me );
00129
00130
00131 VPath path( *this );
00132 VTransformCmd cmd( 0L, m_matrix.invert() );
00133 cmd.visit( path );
00134 path.VObject::save( me );
00135
00136
00137 me.setAttribute( "cx", m_center.x() );
00138 me.setAttribute( "cy", m_center.y() );
00139
00140 me.setAttribute( "rx", m_rx );
00141 me.setAttribute( "ry", m_ry );
00142
00143 me.setAttribute( "start-angle", m_startAngle );
00144 me.setAttribute( "end-angle", m_endAngle );
00145
00146 if( m_type == cut )
00147 me.setAttribute( "kind", "cut" );
00148 else if( m_type == section )
00149 me.setAttribute( "kind", "section" );
00150 else if( m_type == arc )
00151 me.setAttribute( "kind", "arc" );
00152 else
00153 me.setAttribute( "kind", "full" );
00154
00155 QString transform = buildSvgTransform();
00156 if( !transform.isEmpty() )
00157 me.setAttribute( "transform", transform );
00158 }
00159 }
00160
00161 void
00162 VEllipse::saveOasis( KoStore *store, KoXmlWriter *docWriter, KoGenStyles &mainStyles, int &index ) const
00163 {
00164 docWriter->startElement( "draw:ellipse" );
00165
00166
00167 docWriter->addAttributePt( "svg:cx", m_center.x() );
00168 docWriter->addAttributePt( "svg:cy", m_center.y() );
00169 docWriter->addAttributePt( "svg:rx", m_rx );
00170 docWriter->addAttributePt( "svg:ry", m_ry );
00171
00172 if( m_type == full )
00173 docWriter->addAttribute( "draw:kind", "full" );
00174 else
00175 {
00176 if( m_type == cut )
00177 docWriter->addAttribute( "draw:kind", "cut" );
00178 else if( m_type == section )
00179 docWriter->addAttribute( "draw:kind", "section" );
00180 else
00181 docWriter->addAttribute( "draw:kind", "arc" );
00182
00183 docWriter->addAttribute( "draw:start-angle", m_startAngle );
00184 docWriter->addAttribute( "draw:end-angle", m_endAngle );
00185 }
00186
00187 VObject::saveOasis( store, docWriter, mainStyles, index );
00188
00189 QWMatrix tmpMat;
00190 tmpMat.scale( 1, -1 );
00191 tmpMat.translate( 0, -document()->height() );
00192
00193 QString transform = buildOasisTransform( m_matrix*tmpMat );
00194 if( !transform.isEmpty() )
00195 docWriter->addAttribute( "draw:transform", transform );
00196
00197 docWriter->endElement();
00198 }
00199
00200 bool
00201 VEllipse::loadOasis( const QDomElement &element, KoOasisLoadingContext &context )
00202 {
00203 setState( normal );
00204
00205 if( element.tagName() == "ellipse" )
00206 {
00207 if( element.hasAttributeNS( KoXmlNS::svg, "rx" ) )
00208 m_rx = KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "rx", QString::null ) );
00209 else
00210 m_rx = 0.5 * KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "width", QString::null ) );
00211
00212 if( element.hasAttributeNS( KoXmlNS::svg, "ry" ) )
00213 m_ry = KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "ry", QString::null ) );
00214 else
00215 m_ry = 0.5 * KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "height", QString::null ) );
00216
00217 }
00218 else if( element.tagName() == "circle" )
00219 {
00220 if( element.hasAttributeNS( KoXmlNS::svg, "r" ) )
00221 m_rx = m_ry = KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "r", QString::null ) );
00222 else
00223 m_rx = m_ry = 0.5 * KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "width", QString::null ) );
00224 }
00225
00226 if( element.hasAttributeNS( KoXmlNS::svg, "cx" ) )
00227 m_center.setX( KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "cx", QString::null ) ) );
00228 else
00229 m_center.setX( m_rx + KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "x", QString::null ) ) );
00230
00231 if( element.hasAttributeNS( KoXmlNS::svg, "cy" ) )
00232 m_center.setY( KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "cy", QString::null ) ) );
00233 else
00234 m_center.setY( m_ry + KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "y", QString::null ) ) );
00235
00236 m_startAngle = element.attributeNS( KoXmlNS::draw, "start-angle", QString::null ).toDouble();
00237 m_endAngle = element.attributeNS( KoXmlNS::draw, "end-angle", QString::null ).toDouble();
00238
00239 QString kind = element.attributeNS( KoXmlNS::draw, "kind", QString::null );
00240 if( kind == "cut" )
00241 m_type = cut;
00242 else if( kind == "section" )
00243 m_type = section;
00244 else if( kind == "arc" )
00245 m_type = arc;
00246 else
00247 m_type = full;
00248
00249 init();
00250
00251 transformByViewbox( element, element.attributeNS( KoXmlNS::svg, "viewBox", QString::null ) );
00252
00253 QString trafo = element.attributeNS( KoXmlNS::draw, "transform", QString::null );
00254 if( !trafo.isEmpty() )
00255 transformOasis( trafo );
00256
00257 return VObject::loadOasis( element, context );
00258 }
00259
00260 void
00261 VEllipse::load( const QDomElement& element )
00262 {
00263 setState( normal );
00264
00265 QDomNodeList list = element.childNodes();
00266 for( uint i = 0; i < list.count(); ++i )
00267 if( list.item( i ).isElement() )
00268 VObject::load( list.item( i ).toElement() );
00269
00270 m_rx = KoUnit::parseValue( element.attribute( "rx" ) );
00271 m_ry = KoUnit::parseValue( element.attribute( "ry" ) );
00272
00273 m_center.setX( KoUnit::parseValue( element.attribute( "cx" ) ) );
00274 m_center.setY( KoUnit::parseValue( element.attribute( "cy" ) ) );
00275
00276 m_startAngle = element.attribute( "start-angle" ).toDouble();
00277 m_endAngle = element.attribute( "end-angle" ).toDouble();
00278
00279 if( element.attribute( "kind" ) == "cut" )
00280 m_type = cut;
00281 else if( element.attribute( "kind" ) == "section" )
00282 m_type = section;
00283 else if( element.attribute( "kind" ) == "arc" )
00284 m_type = arc;
00285 else
00286 m_type = full;
00287
00288 init();
00289
00290 QString trafo = element.attribute( "transform" );
00291 if( !trafo.isEmpty() )
00292 transform( trafo );
00293 }
00294
00295 VPath*
00296 VEllipse::clone() const
00297 {
00298 return new VEllipse( *this );
00299 }