karbon

vrectangle.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2001, 2002, 2003 The Karbon Developers
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20
21#include "vrectangle.h"
22#include <tdelocale.h>
23#include <KoUnit.h>
24#include <KoStore.h>
25#include <KoXmlWriter.h>
26#include <KoXmlNS.h>
27#include <tqdom.h>
28#include <kdebug.h>
29#include "vglobal.h"
30#include <vdocument.h>
31#include "vtransformcmd.h"
32
33VRectangle::VRectangle( VObject* parent, VState state )
34 : VPath( parent, state )
35{
36}
37
38VRectangle::VRectangle( VObject* parent,
39 const KoPoint& topLeft, double width, double height, double rx, double ry )
40 : VPath( parent ), m_topLeft( topLeft ), m_width( width), m_height( height ), m_rx( rx ), m_ry( ry )
41{
42 setDrawCenterNode();
43
44 if( m_rx < 0.0 ) m_rx = 0.0;
45 if( m_ry < 0.0 ) m_ry = 0.0;
46 // Catch case, when radius is larger than width or height:
47 if( m_rx > m_width * 0.5 )
48 m_rx = m_width * 0.5;
49 if( m_ry > m_height * 0.5 )
50 m_ry = m_height * 0.5;
51
52 init();
53}
54
55void
56VRectangle::init()
57{
58 if( m_rx == 0 && m_ry == 0 )
59 {
60 moveTo( m_topLeft );
61 lineTo( KoPoint( m_topLeft.x(), m_topLeft.y() - m_height ) );
62 lineTo( KoPoint( m_topLeft.x() + m_width, m_topLeft.y() - m_height ) );
63 lineTo( KoPoint( m_topLeft.x() + m_width, m_topLeft.y() ) );
64 }
65 else
66 {
67 double rx = m_rx;
68 double ry = m_ry;
69 double x = m_topLeft.x();
70 double y = m_topLeft.y();
71 moveTo( KoPoint( x + rx, y ) );
72 curveTo( KoPoint( x + rx * ( 1 - 0.552 ), y ),
73 KoPoint( x, y - ry * ( 1 - 0.552 ) ),
74 KoPoint( x, y - ry ) );
75 if( ry < m_height / 2 )
76 lineTo( KoPoint( x, y - m_height + ry ) );
77 curveTo( KoPoint( x, y - m_height + ry * ( 1 - 0.552 ) ),
78 KoPoint( x + rx * ( 1 - 0.552 ), y - m_height ),
79 KoPoint( x + rx, y - m_height ) );
80 if( rx < m_width / 2 )
81 lineTo( KoPoint( x + m_width - rx, y - m_height ) );
82 curveTo( KoPoint( x + m_width - rx * ( 1 - 0.552 ), y - m_height ),
83 KoPoint( x + m_width, y - m_height + ry * ( 1 - 0.552 ) ),
84 KoPoint( x + m_width, y - m_height + ry ) );
85 if( ry < m_height / 2 )
86 lineTo( KoPoint( x + m_width, y - ry ) );
87 curveTo( KoPoint( x + m_width, y - ry * ( 1 - 0.552 ) ),
88 KoPoint( x + m_width - rx * ( 1 - 0.552 ), y ),
89 KoPoint( x + m_width - rx, y ) );
90 if( rx < m_width / 2 )
91 lineTo( KoPoint( x + rx, y ) );
92 }
93 close();
94}
95
96TQString
97VRectangle::name() const
98{
99 TQString result = VObject::name();
100 return !result.isEmpty() ? result : i18n( "Rectangle" );
101}
102
103void
104VRectangle::save( TQDomElement& element ) const
105{
106 VDocument *doc = document();
107 if( doc && doc->saveAsPath() )
108 {
109 VPath::save( element );
110 return;
111 }
112
113 if( state() != deleted )
114 {
115 TQDomElement me = element.ownerDocument().createElement( "RECT" );
116 element.appendChild( me );
117
118 // save fill/stroke untransformed
119 VPath path( *this );
120 VTransformCmd cmd( 0L, m_matrix.invert() );
121 cmd.visit( path );
122 path.VObject::save( me );
123 //VObject::save( me );
124
125 me.setAttribute( "x", m_topLeft.x() );
126 me.setAttribute( "y", m_topLeft.y() );
127
128 me.setAttribute( "width", TQString("%1pt").arg( m_width ) );
129 me.setAttribute( "height", TQString("%1pt").arg( m_height ) );
130
131 me.setAttribute( "rx", m_rx );
132 me.setAttribute( "ry", m_ry );
133
134 TQString transform = buildSvgTransform();
135 if( !transform.isEmpty() )
136 me.setAttribute( "transform", transform );
137 }
138}
139
140void
141VRectangle::saveOasis( KoStore *store, KoXmlWriter *docWriter, KoGenStyles &mainStyles, int &index ) const
142{
143 // do not save deleted objects
144 if( state() == deleted )
145 return;
146
147 // different rx/ry is not supported by oasis, so act like it is a normal path
148 if( m_rx != 0. && m_ry != 0. && m_rx != m_ry )
149 return VPath::saveOasis( store, docWriter, mainStyles, index );
150
151 docWriter->startElement( "draw:rect" );
152
153 //save all into pt
154 docWriter->addAttributePt( "svg:x", m_topLeft.x() );
155 docWriter->addAttributePt( "svg:y", m_topLeft.y()-m_height );
156 docWriter->addAttributePt( "svg:width", m_width );
157 docWriter->addAttributePt( "svg:height", m_height );
158
159 if( m_rx != 0. && m_ry != 0. && m_rx == m_ry )
160 docWriter->addAttributePt( "draw:corner-radius", m_rx );
161
162 VObject::saveOasis( store, docWriter, mainStyles, index );
163
164 TQWMatrix tmpMat;
165 tmpMat.scale( 1, -1 );
166 tmpMat.translate( 0, -document()->height() );
167
168 TQString transform = buildOasisTransform( m_matrix*tmpMat );
169 if( !transform.isEmpty() )
170 docWriter->addAttribute( "draw:transform", transform );
171
172 docWriter->endElement();
173}
174
175bool
176VRectangle::loadOasis( const TQDomElement &element, KoOasisLoadingContext &context )
177{
178 setState( normal );
179
180 m_width = KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "width", TQString() ), 10.0 );
181 m_height = KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "height", TQString() ), 10.0 );
182
183 m_topLeft.setX( KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "x", TQString() ) ) );
184 m_topLeft.setY( m_height + KoUnit::parseValue( element.attributeNS( KoXmlNS::svg, "y", TQString() ) ) );
185
186 m_rx = m_ry = KoUnit::parseValue( element.attributeNS( KoXmlNS::draw, "corner-radius", TQString() ) );
187
188 init();
189
190 transformByViewbox( element, element.attributeNS( KoXmlNS::svg, "viewBox", TQString() ) );
191
192 TQString trafo = element.attributeNS( KoXmlNS::draw, "transform", TQString() );
193 if( !trafo.isEmpty() )
194 transformOasis( trafo );
195
196 return VObject::loadOasis( element, context );
197}
198
199void
200VRectangle::load( const TQDomElement& element )
201{
202 setState( normal );
203
204 TQDomNodeList list = element.childNodes();
205 for( uint i = 0; i < list.count(); ++i )
206 if( list.item( i ).isElement() )
207 VObject::load( list.item( i ).toElement() );
208
209 m_width = KoUnit::parseValue( element.attribute( "width" ), 10.0 );
210 m_height = KoUnit::parseValue( element.attribute( "height" ), 10.0 );
211
212 m_topLeft.setX( KoUnit::parseValue( element.attribute( "x" ) ) );
213 m_topLeft.setY( KoUnit::parseValue( element.attribute( "y" ) ) );
214
215 m_rx = KoUnit::parseValue( element.attribute( "rx" ) );
216 m_ry = KoUnit::parseValue( element.attribute( "ry" ) );
217
218 init();
219
220 TQString trafo = element.attribute( "transform" );
221 if( !trafo.isEmpty() )
222 transform( trafo );
223}
224
225VPath*
226VRectangle::clone() const
227{
228 return new VRectangle( *this );
229}
The base class for all karbon objects.
Definition vobject.h:50
virtual void setState(const VState state)
Sets the state to a specified new state.
Definition vobject.h:163
virtual void saveOasis(KoStore *store, KoXmlWriter *docWriter, KoGenStyles &mainStyles, int &index) const
Save this object's state to OpenDocument.
Definition vobject.cpp:116
@ deleted
deleted, nearly dead
Definition vobject.h:58
@ normal
visible, not active
Definition vobject.h:54
virtual TQString name() const
Returns the name of the object.
Definition vobject.cpp:225
virtual void load(const TQDomElement &element)
Load this object's state from xml and initialize this object accordingly.
Definition vobject.cpp:157
VDocument * document() const
Return document the object belongs to.
Definition vobject.cpp:216
virtual bool loadOasis(const TQDomElement &element, KoOasisLoadingContext &context)
Load this object's state from OpenDocument and initialize this object accordingly.
Definition vobject.cpp:181
VState state() const
Get the state the object is in.
Definition vobject.h:154
A composite path consists of one or many subpaths.
Definition vcomposite.h:48
virtual void saveOasis(KoStore *store, KoXmlWriter *docWriter, KoGenStyles &mainStyles, int &index) const
Save this object's state to OpenDocument.
void close()
Closes the current subpath.
virtual void save(TQDomElement &element) const
Save this object's state to xml.
virtual VPath * clone() const
Create an exact copy of this object.