kpresenter

KPrAutoformObject.cpp
1/* This file is part of the KDE project
2 Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
3 Copyright (C) 2005-2006 Thorsten Zachmann <zachmann@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#include "KPrAutoformObject.h"
22#include "KPrAutoFormObjectIface.h"
23#include "KPrUtils.h"
24#include "KPrGradient.h"
25
26#include <tqbitmap.h>
27#include <tqpointarray.h>
28#include <tqptrlist.h>
29#include <tqregion.h>
30#include <tqdom.h>
31#include <tqpainter.h>
32#include <tqwmatrix.h>
33#include <kstandarddirs.h>
34#include <kdebug.h>
35#include <KoTextZoomHandler.h>
36#include <math.h>
37using namespace std;
38
39KPrAutoformObject::KPrAutoformObject()
40: KPr2DObject()
41, KPrStartEndLine( L_NORMAL, L_NORMAL )
42, atfInterp()
43{
44}
45
46KPrAutoformObject::KPrAutoformObject( const KoPen & _pen, const TQBrush &_brush, const TQString & _filename,
47 LineEnd _lineBegin, LineEnd _lineEnd,
48 FillType _fillType, const TQColor &_gColor1,
49 const TQColor &_gColor2, BCType _gType,
50 bool _unbalanced, int _xfactor, int _yfactor)
51: KPr2DObject( _pen, _brush, _fillType, _gColor1, _gColor2, _gType, _unbalanced, _xfactor, _yfactor )
52, KPrStartEndLine( _lineBegin, _lineEnd )
53, filename( _filename ), atfInterp()
54{
55 atfInterp.load( filename );
56}
57
58KPrAutoformObject &KPrAutoformObject::operator=( const KPrAutoformObject & )
59{
60 return *this;
61}
62
63DCOPObject* KPrAutoformObject::dcopObject()
64{
65 if ( !dcop )
66 dcop = new KPrAutoFormObjectIface( this );
67 return dcop;
68}
69
70void KPrAutoformObject::setFileName( const TQString & _filename )
71{
72 filename = _filename;
73 atfInterp.load( filename );
74}
75
76
77bool KPrAutoformObject::saveOasisObjectAttributes( KPOasisSaveContext &sc ) const
78{
79 kdDebug(33001) << "bool KPrAutoformObject::saveOasisObjectAttributes()" << endl;
80 TQSize size( int( ext.width() * 100 ), int( ext.height() * 100 ) );
81
82 sc.xmlWriter.addAttribute( "svg:viewBox", TQString( "0 0 %1 %2" ).arg( size.width() )
83 .arg( size.height() ) );
84
85 TQPointArray points = const_cast<ATFInterpreter &>( atfInterp ).getPointArray( size.width(), size.height() );
86
87 unsigned int pointCount = points.size();
88 unsigned int pos = 0;
89 bool closed = points.at( 0 ) == points.at( pointCount - 1 );
90
91 if ( closed )
92 --pointCount;
93
94 TQString d;
95 d += TQString( "M%1 %2" ).arg( points.at(pos).x() )
96 .arg( points.at(pos).y() );
97 ++pos;
98
99 while ( pos < pointCount )
100 {
101 d += TQString( "L%1 %2" ).arg( points.at( pos ).x() )
102 .arg( points.at( pos ).y() );
103 ++pos;
104 }
105
106 if ( closed )
107 d += "Z";
108
109 sc.xmlWriter.addAttribute( "svg:d", d );
110
111 return true;
112}
113
114void KPrAutoformObject::fillStyle( KoGenStyle& styleObjectAuto, KoGenStyles& mainStyles ) const
115{
116 kdDebug(33001) << "KPr2DObject::fillStyle" << endl;
117 KPrShadowObject::fillStyle( styleObjectAuto, mainStyles );
118
119 TQPointArray points = const_cast<ATFInterpreter &>( atfInterp ).getPointArray( int( ext.width() * 100 ),
120 int( ext.height() * 100 ) );
121
122 // if it is a closed object save the background
123 if ( points.at( 0 ) == points.at( points.size() - 1 ) )
124 {
125 m_brush.saveOasisFillStyle( styleObjectAuto, mainStyles );
126 }
127 else
128 {
129 saveOasisMarkerElement( mainStyles, styleObjectAuto );
130 }
131}
132
133const char * KPrAutoformObject::getOasisElementName() const
134{
135 return "draw:path";
136}
137
138TQDomDocumentFragment KPrAutoformObject::save( TQDomDocument& doc, double offset )
139{
140 TQDomDocumentFragment fragment=KPr2DObject::save(doc, offset);
141 KPrStartEndLine::save( fragment, doc );
142
143 // The filename contains the absolute path to the autoform. This is
144 // bad, so we simply remove everything but the last dir and the name.
145 // e.g. /my/local/path/to/kpresenter/Arrow/.source/Arrow1.atf -> Arrow/.source/Arrow1.atf
146 TQStringList afDirs = KPrFactory::global()->dirs()->resourceDirs("autoforms");
147 TQValueList<TQString>::ConstIterator it=afDirs.begin();
148 TQString str;
149 for( ; it!=afDirs.end(); ++it) {
150 if(filename.startsWith(*it)) {
151 str=filename.mid((*it).length());
152 break;
153 }
154 }
155 TQDomElement elem=doc.createElement("FILENAME");
156 elem.setAttribute("value", str);
157 fragment.appendChild(elem);
158 return fragment;
159}
160
161double KPrAutoformObject::load(const TQDomElement &element)
162{
163 double offset=KPr2DObject::load(element);
164 KPrStartEndLine::load( element );
165 TQDomElement e=element.namedItem("FILENAME").toElement();
166 if(!e.isNull()) {
167 if(e.hasAttribute("value"))
168 filename=e.attribute("value");
169 // don't crash on invalid files, better insert something
170 if(filename.isEmpty())
171 filename="Connections/.source/Connection1.atf";
172 // workaround for a bug in the (very) old file format
173 if(filename[0]=='/') {
174 kdDebug(33001) << "rubbish ahead! cleaning up..." << endl;
175 // remove the leading absolute path (i.e. to create Arrow/Arrow1.atf)
176 filename=filename.mid(filename.findRev('/', filename.findRev('/')-1)+1);
177 }
178 // okay... we changed the file format again and now the autoforms
179 // are stored in .../kpresenter/autoforms/.source/foo.atf (note: we didn't have .source
180 // before. Therefore we have to add this dir if it's not already there to make it
181 // work with old files
182 if(filename.find(".source")==-1) {
183 // okay, old file -- add the .source dir
184 filename=filename.insert(filename.find('/'), "/.source");
185 }
186 filename = locate("autoforms", filename, KPrFactory::global());
187 atfInterp.load( filename );
188 }
189 return offset;
190}
191
192void KPrAutoformObject::paint( TQPainter* _painter, KoTextZoomHandler *_zoomHandler,
193 int /* pageNum */, bool drawingShadow, bool drawContour )
194{
195 unsigned int pw = 0, pwOrig = 0, px, py;
196 TQPen pen2;
197 TQSize size( _zoomHandler->zoomSize( ext ) );
198
199 if ( drawContour )
200 pen2 = TQPen( TQt::black, 1, TQt::DotLine );
201 else {
202 pen2 = pen.zoomedPen( _zoomHandler );
203 }
204
205 _painter->setPen( pen2 );
206 pwOrig = ( pen2.style() == TQt::NoPen ) ? 1 : pen2.width();
207 if ( !drawContour )
208 _painter->setBrush( getBrush() );
209
210 TQPointArray pntArray = atfInterp.getPointArray( _zoomHandler->zoomItX( ext.width()),
211 _zoomHandler->zoomItY( ext.height() ) );
212 TQPtrList<ATFInterpreter::AttribList> atrLs = atfInterp.getAttribList();
213 TQPointArray pntArray2( pntArray.size() );
214 int ex = _zoomHandler->zoomItX(ext.width());
215 int ey = _zoomHandler->zoomItY(ext.height());
216 for ( unsigned int i = 0; i < pntArray.size(); i++ )
217 {
218 px = pntArray.at( i ).x();
219 py = pntArray.at( i ).y();
220 if ( atrLs.at( i )->pwDiv > 0 )
221 {
222 pw = pwOrig / atrLs.at( i )->pwDiv;
223 px = (int)((double)(ex - pw) / (double)ex * px + pw / 2);
224 py = (int)((double)(ey - pw) / (double)ey * py + pw / 2);
225 }
226 pntArray2.setPoint( i, px, py );
227 }
228
229 if ( pntArray2.size() > 0 )
230 {
231 if ( pntArray2.at( 0 ) == pntArray2.at( pntArray2.size() - 1 ) )
232 {
233 if ( drawContour || (drawingShadow || getFillType() == FT_BRUSH || !gradient) )
234 _painter->drawPolygon( pntArray2 );
235 else
236 {
237 if ( angle == 0 || angle==360 )
238 {
239 //int ox = _painter->viewport().x() + static_cast<int>( _painter->worldMatrix().dx() );
240 //int oy = _painter->viewport().y() + static_cast<int>( _painter->worldMatrix().dy() );
241
242 TQPointArray pntArray3 = pntArray2.copy();
243 _painter->save();
244
245 TQRegion clipregion( pntArray3 );
246
247 // Intersect with current clipregion (whereas setupClipRegion unites)
248 if ( _painter->hasClipping() )
249 clipregion = _painter->clipRegion(TQPainter::CoordPainter).intersect( clipregion );
250
251 _painter->setClipRegion( clipregion, TQPainter::CoordPainter );
252
253 gradient->setSize( size );
254 _painter->drawPixmap( 0, 0, gradient->pixmap() );
255
256 _painter->restore();
257 }
258 else
259 {
260 if ( m_redrawGradientPix || gradient->size() != size )
261 {
262 kdDebug(33001) << "KPrAutoformObject::draw redrawPix" << endl;
263 gradient->setSize( size );
264 m_redrawGradientPix = false;
265 TQRegion clipregion( pntArray2 );
266 m_gradientPix.resize ( _zoomHandler->zoomItX(ext.width()),_zoomHandler->zoomItY(ext.height()) );
267 m_gradientPix.fill( TQt::white );
268
269
270 TQPainter p;
271 p.begin( &m_gradientPix );
272 p.setClipRegion( clipregion , TQPainter::CoordPainter);
273 p.drawPixmap( 0, 0, gradient->pixmap() );
274 p.end();
275
276 m_gradientPix.setMask( m_gradientPix.createHeuristicMask() );
277 }
278
279 _painter->drawPixmap( 0, 0, m_gradientPix );
280 }
281
282 _painter->setPen( pen2 );
283 _painter->setBrush( TQt::NoBrush );
284 _painter->drawPolygon( pntArray2 );
285 }
286 }
287 else
288 {
289 KoSize diff1( 0, 0 ), diff2( 0, 0 );
290 int _w = int( pen.pointWidth() );
291
292 if ( lineBegin != L_NORMAL )
293 diff1 = getBoundingSize( lineBegin, _w, _zoomHandler );
294
295 if ( lineEnd != L_NORMAL )
296 diff2 = getBoundingSize( lineEnd, _w, _zoomHandler );
297
298 if ( pntArray.size() > 1 )
299 {
300 if ( lineBegin != L_NORMAL && !drawContour )
301 {
302 TQPoint pnt1( pntArray2.at( 0 ) ), pnt2( pntArray2.at( 1 ) );
303 TQPoint pnt3, pnt4( pntArray.at( 0 ) );
304 float _angle = KoPoint::getAngle( KoPoint( pnt1 ), KoPoint( pnt2 ) );
305
306 switch ( static_cast<int>( _angle ) )
307 {
308 case 0:
309 {
310 pnt3.setX( pnt4.x() - (int)diff1.width() / 2 );
311 pnt3.setY( pnt1.y() );
312 } break;
313 case 180:
314 {
315 pnt3.setX( pnt4.x() + (int)diff1.width() / 2 );
316 pnt3.setY( pnt1.y() );
317 } break;
318 case 90:
319 {
320 pnt3.setX( pnt1.x() );
321 pnt3.setY( pnt4.y() - (int)diff1.width() / 2 );
322 } break;
323 case 270:
324 {
325 pnt3.setX( pnt1.x() );
326 pnt3.setY( pnt4.y() + (int)diff1.width() / 2 );
327 } break;
328 default:
329 pnt3 = pnt1;
330 break;
331 }
332
333 drawFigure( lineBegin, _painter, _zoomHandler->unzoomPoint( pnt3 ), pen2.color(), _w, _angle, _zoomHandler );
334 }
335
336 if ( lineEnd != L_NORMAL && !drawContour )
337 {
338 TQPoint pnt1( pntArray2.at( pntArray2.size() - 1 ) ), pnt2( pntArray2.at( pntArray2.size() - 2 ) );
339 TQPoint pnt3, pnt4( pntArray.at( pntArray.size() - 1 ) );
340 float _angle = KoPoint::getAngle( KoPoint( pnt1 ), KoPoint( pnt2 ) );
341
342 switch ( ( int )_angle )
343 {
344 case 0:
345 {
346 pnt3.setX( pnt4.x() - (int)diff2.width() / 2 );
347 pnt3.setY( pnt1.y() );
348 } break;
349 case 180:
350 {
351 pnt3.setX( pnt4.x() + (int)diff2.width() / 2 );
352 pnt3.setY( pnt1.y() );
353 } break;
354 case 90:
355 {
356 pnt3.setX( pnt1.x() );
357 pnt3.setY( pnt4.y() - (int)diff2.width() / 2 );
358 } break;
359 case 270:
360 {
361 pnt3.setX( pnt1.x() );
362 pnt3.setY( pnt4.y() + (int)diff2.width() / 2 );
363 } break;
364 default:
365 pnt3 = pnt1;
366 break;
367 }
368
369 drawFigure( lineEnd, _painter, _zoomHandler->unzoomPoint( pnt3 ), pen2.color(), _w, _angle,_zoomHandler );
370 }
371 }
372
373 _painter->setPen( pen2 );
374 _painter->drawPolyline( pntArray2 );
375 }
376 }
377}