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
00165 if( state() == deleted )
00166 return;
00167
00168 docWriter->startElement( "draw:ellipse" );
00169
00170
00171 docWriter->addAttributePt( "svg:cx", m_center.x() );
00172 docWriter->addAttributePt( "svg:cy", m_center.y() );
00173 docWriter->addAttributePt( "svg:rx", m_rx );
00174 docWriter->addAttributePt( "svg:ry", m_ry );
00175
00176 if( m_type == full )
00177 docWriter->addAttribute( "draw:kind", "full" );
00178 else
00179 {
00180 if( m_type == cut )
00181 docWriter->addAttribute( "draw:kind", "cut" );
00182 else if( m_type == section )
00183 docWriter->addAttribute( "draw:kind", "section" );
00184 else
00185 docWriter->addAttribute( "draw:kind", "arc" );
00186
00187 docWriter->addAttribute( "draw:start-angle", m_startAngle );
00188 docWriter->addAttribute( "draw:end-angle", m_endAngle );
00189 }
00190
00191 VObject::saveOasis( store, docWriter, mainStyles, index );
00192
00193 QWMatrix tmpMat;
00194 tmpMat.scale( 1, -1 );
00195 tmpMat.translate( 0, -document()->height() );
00196
00197 QString transform = buildOasisTransform( m_matrix*tmpMat );
00198 if( !transform.isEmpty() )
00199 docWriter->addAttribute( "draw:transform", transform );
00200
00201 docWriter->endElement();
00202 }
00203
00204 bool
00205 VEllipse::loadOasis( const QDomElement &element, KoOasisLoadingContext &context )
00206 {
00207 setState( normal );
00208
00209 if( element.tagName() == "ellipse" )
00210 {
00211 if( element.hasAttributeNS( KoXmlNS::svg, "rx" ) )
00212 m_rx = KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "rx", QString::null ) );
00213 else
00214 m_rx = 0.5 * KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "width", QString::null ) );
00215
00216 if( element.hasAttributeNS( KoXmlNS::svg, "ry" ) )
00217 m_ry = KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "ry", QString::null ) );
00218 else
00219 m_ry = 0.5 * KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "height", QString::null ) );
00220
00221 }
00222 else if( element.tagName() == "circle" )
00223 {
00224 if( element.hasAttributeNS( KoXmlNS::svg, "r" ) )
00225 m_rx = m_ry = KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "r", QString::null ) );
00226 else
00227 m_rx = m_ry = 0.5 * KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "width", QString::null ) );
00228 }
00229
00230 if( element.hasAttributeNS( KoXmlNS::svg, "cx" ) )
00231 m_center.setX( KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "cx", QString::null ) ) );
00232 else
00233 m_center.setX( m_rx + KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "x", QString::null ) ) );
00234
00235 if( element.hasAttributeNS( KoXmlNS::svg, "cy" ) )
00236 m_center.setY( KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "cy", QString::null ) ) );
00237 else
00238 m_center.setY( m_ry + KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "y", QString::null ) ) );
00239
00240 m_startAngle = element.attributeNS( KoXmlNS::draw, "start-angle", QString::null ).toDouble();
00241 m_endAngle = element.attributeNS( KoXmlNS::draw, "end-angle", QString::null ).toDouble();
00242
00243 QString kind = element.attributeNS( KoXmlNS::draw, "kind", QString::null );
00244 if( kind == "cut" )
00245 m_type = cut;
00246 else if( kind == "section" )
00247 m_type = section;
00248 else if( kind == "arc" )
00249 m_type = arc;
00250 else
00251 m_type = full;
00252
00253 init();
00254
00255 transformByViewbox( element, element.attributeNS( KoXmlNS::svg, "viewBox", QString::null ) );
00256
00257 QString trafo = element.attributeNS( KoXmlNS::draw, "transform", QString::null );
00258 if( !trafo.isEmpty() )
00259 transformOasis( trafo );
00260
00261 return VObject::loadOasis( element, context );
00262 }
00263
00264 void
00265 VEllipse::load( const QDomElement& element )
00266 {
00267 setState( normal );
00268
00269 QDomNodeList list = element.childNodes();
00270 for( uint i = 0; i < list.count(); ++i )
00271 if( list.item( i ).isElement() )
00272 VObject::load( list.item( i ).toElement() );
00273
00274 m_rx = KoUnit::parseValue( element.attribute( "rx" ) );
00275 m_ry = KoUnit::parseValue( element.attribute( "ry" ) );
00276
00277 m_center.setX( KoUnit::parseValue( element.attribute( "cx" ) ) );
00278 m_center.setY( KoUnit::parseValue( element.attribute( "cy" ) ) );
00279
00280 m_startAngle = element.attribute( "start-angle" ).toDouble();
00281 m_endAngle = element.attribute( "end-angle" ).toDouble();
00282
00283 if( element.attribute( "kind" ) == "cut" )
00284 m_type = cut;
00285 else if( element.attribute( "kind" ) == "section" )
00286 m_type = section;
00287 else if( element.attribute( "kind" ) == "arc" )
00288 m_type = arc;
00289 else
00290 m_type = full;
00291
00292 init();
00293
00294 QString trafo = element.attribute( "transform" );
00295 if( !trafo.isEmpty() )
00296 transform( trafo );
00297 }
00298
00299 VPath*
00300 VEllipse::clone() const
00301 {
00302 return new VEllipse( *this );
00303 }