kpresenter

KPrAutoformObject.cpp

00001 // -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*-
00002 /* This file is part of the KDE project
00003    Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
00004    Copyright (C) 2005-2006 Thorsten Zachmann <zachmann@kde.org>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include "KPrAutoformObject.h"
00023 #include "KPrAutoFormObjectIface.h"
00024 #include "KPrUtils.h"
00025 #include "KPrGradient.h"
00026 
00027 #include <qbitmap.h>
00028 #include <qpointarray.h>
00029 #include <qptrlist.h>
00030 #include <qregion.h>
00031 #include <qdom.h>
00032 #include <qpainter.h>
00033 #include <qwmatrix.h>
00034 #include <kstandarddirs.h>
00035 #include <kdebug.h>
00036 #include <KoTextZoomHandler.h>
00037 #include <math.h>
00038 using namespace std;
00039 
00040 KPrAutoformObject::KPrAutoformObject()
00041 : KPr2DObject()
00042 , KPrStartEndLine( L_NORMAL, L_NORMAL )
00043 , atfInterp()
00044 {
00045 }
00046 
00047 KPrAutoformObject::KPrAutoformObject( const KoPen & _pen, const QBrush &_brush, const QString & _filename,
00048                                     LineEnd _lineBegin, LineEnd _lineEnd,
00049                                     FillType _fillType, const QColor &_gColor1,
00050                                     const QColor &_gColor2, BCType _gType,
00051                                     bool _unbalanced, int _xfactor, int _yfactor)
00052 : KPr2DObject( _pen, _brush, _fillType, _gColor1, _gColor2, _gType, _unbalanced, _xfactor, _yfactor )
00053 , KPrStartEndLine( _lineBegin, _lineEnd )
00054 , filename( _filename ), atfInterp()
00055 {
00056     atfInterp.load( filename );
00057 }
00058 
00059 KPrAutoformObject &KPrAutoformObject::operator=( const KPrAutoformObject & )
00060 {
00061     return *this;
00062 }
00063 
00064 DCOPObject* KPrAutoformObject::dcopObject()
00065 {
00066     if ( !dcop )
00067         dcop = new KPrAutoFormObjectIface( this );
00068     return dcop;
00069 }
00070 
00071 void KPrAutoformObject::setFileName( const QString & _filename )
00072 {
00073     filename = _filename;
00074     atfInterp.load( filename );
00075 }
00076 
00077 
00078 bool KPrAutoformObject::saveOasisObjectAttributes( KPOasisSaveContext &sc ) const
00079 {
00080     kdDebug(33001) << "bool KPrAutoformObject::saveOasisObjectAttributes()" << endl;
00081     QSize size( int( ext.width() * 100 ), int( ext.height() * 100 )  );
00082 
00083     sc.xmlWriter.addAttribute( "svg:viewBox", QString( "0 0 %1 %2" ).arg( size.width() )
00084                                                                     .arg( size.height() ) );
00085 
00086     QPointArray points = const_cast<ATFInterpreter &>( atfInterp ).getPointArray( size.width(), size.height() );
00087 
00088     unsigned int pointCount = points.size();
00089     unsigned int pos = 0;
00090     bool closed = points.at( 0 ) == points.at( pointCount - 1 );
00091 
00092     if ( closed )
00093         --pointCount;
00094 
00095     QString d;
00096     d += QString( "M%1 %2" ).arg( points.at(pos).x() )
00097                             .arg( points.at(pos).y() );
00098     ++pos;
00099 
00100     while ( pos < pointCount )
00101     {
00102         d += QString( "L%1 %2" ).arg( points.at( pos ).x() )
00103                                 .arg( points.at( pos ).y() );
00104         ++pos;
00105     }
00106 
00107     if ( closed )
00108         d += "Z";
00109 
00110     sc.xmlWriter.addAttribute( "svg:d", d );
00111 
00112     return true;
00113 }
00114 
00115 void KPrAutoformObject::fillStyle( KoGenStyle& styleObjectAuto, KoGenStyles& mainStyles ) const
00116 {
00117     kdDebug(33001) << "KPr2DObject::fillStyle" << endl;
00118     KPrShadowObject::fillStyle( styleObjectAuto, mainStyles );
00119 
00120     QPointArray points = const_cast<ATFInterpreter &>( atfInterp ).getPointArray( int( ext.width() * 100 ),
00121                                                                                   int( ext.height() * 100 ) );
00122 
00123     // if it is a closed object save the background
00124     if ( points.at( 0 ) == points.at( points.size() - 1 ) )
00125     {
00126         m_brush.saveOasisFillStyle( styleObjectAuto, mainStyles );
00127     }
00128     else
00129     {
00130         saveOasisMarkerElement( mainStyles, styleObjectAuto );
00131     }
00132 }
00133 
00134 const char * KPrAutoformObject::getOasisElementName() const
00135 {
00136     return "draw:path";
00137 }
00138 
00139 QDomDocumentFragment KPrAutoformObject::save( QDomDocument& doc, double offset )
00140 {
00141     QDomDocumentFragment fragment=KPr2DObject::save(doc, offset);
00142     KPrStartEndLine::save( fragment, doc );
00143 
00144     // The filename contains the absolute path to the autoform. This is
00145     // bad, so we simply remove everything but the last dir and the name.
00146     // e.g. /my/local/path/to/kpresenter/Arrow/.source/Arrow1.atf -> Arrow/.source/Arrow1.atf
00147     QStringList afDirs = KPrFactory::global()->dirs()->resourceDirs("autoforms");
00148     QValueList<QString>::ConstIterator it=afDirs.begin();
00149     QString str;
00150     for( ; it!=afDirs.end(); ++it) {
00151         if(filename.startsWith(*it)) {
00152             str=filename.mid((*it).length());
00153             break;
00154         }
00155     }
00156     QDomElement elem=doc.createElement("FILENAME");
00157     elem.setAttribute("value", str);
00158     fragment.appendChild(elem);
00159     return fragment;
00160 }
00161 
00162 double KPrAutoformObject::load(const QDomElement &element)
00163 {
00164     double offset=KPr2DObject::load(element);
00165     KPrStartEndLine::load( element );
00166     QDomElement e=element.namedItem("FILENAME").toElement();
00167     if(!e.isNull()) {
00168         if(e.hasAttribute("value"))
00169             filename=e.attribute("value");
00170         // don't crash on invalid files, better insert something
00171         if(filename.isEmpty())
00172             filename="Connections/.source/Connection1.atf";
00173         // workaround for a bug in the (very) old file format
00174         if(filename[0]=='/') {
00175             kdDebug(33001) << "rubbish ahead! cleaning up..." << endl;
00176             // remove the leading absolute path (i.e. to create Arrow/Arrow1.atf)
00177             filename=filename.mid(filename.findRev('/', filename.findRev('/')-1)+1);
00178         }
00179         // okay... we changed the file format again and now the autoforms
00180         // are stored in .../kpresenter/autoforms/.source/foo.atf (note: we didn't have .source
00181         // before. Therefore we have to add this dir if it's not already there to make it
00182         // work with old files
00183         if(filename.find(".source")==-1) {
00184             // okay, old file -- add the .source dir
00185             filename=filename.insert(filename.find('/'), "/.source");
00186         }
00187         filename = locate("autoforms", filename, KPrFactory::global());
00188         atfInterp.load( filename );
00189     }
00190     return offset;
00191 }
00192 
00193 void KPrAutoformObject::paint( QPainter* _painter, KoTextZoomHandler *_zoomHandler,
00194                               int /* pageNum */, bool drawingShadow, bool drawContour )
00195 {
00196     unsigned int pw = 0, pwOrig = 0, px, py;
00197     QPen pen2;
00198     QSize size( _zoomHandler->zoomSize( ext ) );
00199 
00200     if ( drawContour )
00201         pen2 = QPen( Qt::black, 1, Qt::DotLine );
00202     else {
00203         pen2 = pen.zoomedPen( _zoomHandler );
00204     }
00205 
00206     _painter->setPen( pen2 );
00207     pwOrig = ( pen2.style() == Qt::NoPen ) ? 1 : pen2.width();
00208     if ( !drawContour )
00209         _painter->setBrush( getBrush() );
00210 
00211     QPointArray pntArray = atfInterp.getPointArray( _zoomHandler->zoomItX( ext.width()),
00212                                                     _zoomHandler->zoomItY( ext.height() ) );
00213     QPtrList<ATFInterpreter::AttribList> atrLs = atfInterp.getAttribList();
00214     QPointArray pntArray2( pntArray.size() );
00215     int ex = _zoomHandler->zoomItX(ext.width());
00216     int ey = _zoomHandler->zoomItY(ext.height());
00217     for ( unsigned int i = 0; i < pntArray.size(); i++ )
00218     {
00219         px = pntArray.at( i ).x();
00220         py = pntArray.at( i ).y();
00221         if ( atrLs.at( i )->pwDiv > 0 )
00222         {
00223             pw = pwOrig / atrLs.at( i )->pwDiv;
00224             px = (int)((double)(ex - pw) / (double)ex * px + pw / 2);
00225             py = (int)((double)(ey - pw) / (double)ey * py + pw / 2);
00226         }
00227         pntArray2.setPoint( i, px, py );
00228     }
00229 
00230     if ( pntArray2.size() > 0 )
00231     {
00232         if ( pntArray2.at( 0 ) == pntArray2.at( pntArray2.size() - 1 ) )
00233         {
00234             if ( drawContour || (drawingShadow || getFillType() == FT_BRUSH || !gradient) )
00235                 _painter->drawPolygon( pntArray2 );
00236             else
00237             {
00238                 if ( angle == 0 || angle==360 )
00239                 {
00240                     //int ox = _painter->viewport().x() + static_cast<int>( _painter->worldMatrix().dx() );
00241                     //int oy = _painter->viewport().y() + static_cast<int>( _painter->worldMatrix().dy() );
00242 
00243                     QPointArray pntArray3 = pntArray2.copy();
00244                     _painter->save();
00245 
00246                     QRegion clipregion( pntArray3 );
00247 
00248                     // Intersect with current clipregion (whereas setupClipRegion unites)
00249                     if ( _painter->hasClipping() )
00250                         clipregion = _painter->clipRegion(QPainter::CoordPainter).intersect( clipregion );
00251 
00252                     _painter->setClipRegion( clipregion, QPainter::CoordPainter );
00253 
00254                     gradient->setSize( size );
00255                     _painter->drawPixmap( 0, 0, gradient->pixmap() );
00256 
00257                     _painter->restore();
00258                 }
00259                 else
00260                 {
00261                     if ( m_redrawGradientPix || gradient->size() != size )
00262                     {
00263                         kdDebug(33001) << "KPrAutoformObject::draw redrawPix" << endl;
00264                         gradient->setSize( size );
00265                         m_redrawGradientPix = false;
00266                         QRegion clipregion( pntArray2 );
00267                         m_gradientPix.resize ( _zoomHandler->zoomItX(ext.width()),_zoomHandler->zoomItY(ext.height()) );
00268                         m_gradientPix.fill( Qt::white );
00269 
00270 
00271                         QPainter p;
00272                         p.begin( &m_gradientPix );
00273                         p.setClipRegion( clipregion , QPainter::CoordPainter);
00274                         p.drawPixmap( 0, 0, gradient->pixmap() );
00275                         p.end();
00276 
00277                         m_gradientPix.setMask( m_gradientPix.createHeuristicMask() );
00278                     }
00279 
00280                     _painter->drawPixmap( 0, 0, m_gradientPix );
00281                 }
00282 
00283                 _painter->setPen( pen2 );
00284                 _painter->setBrush( Qt::NoBrush );
00285                 _painter->drawPolygon( pntArray2 );
00286             }
00287         }
00288         else
00289         {
00290             KoSize diff1( 0, 0 ), diff2( 0, 0 );
00291             int _w = int( pen.pointWidth() );
00292 
00293             if ( lineBegin != L_NORMAL )
00294                 diff1 = getBoundingSize( lineBegin, _w, _zoomHandler );
00295 
00296             if ( lineEnd != L_NORMAL )
00297                 diff2 = getBoundingSize( lineEnd, _w, _zoomHandler );
00298 
00299             if ( pntArray.size() > 1 )
00300             {
00301                 if ( lineBegin != L_NORMAL && !drawContour )
00302                 {
00303                     QPoint pnt1( pntArray2.at( 0 ) ), pnt2( pntArray2.at( 1 ) );
00304                     QPoint pnt3, pnt4( pntArray.at( 0 ) );
00305                     float _angle = KoPoint::getAngle( KoPoint( pnt1 ), KoPoint( pnt2 ) );
00306 
00307                     switch ( static_cast<int>( _angle ) )
00308                     {
00309                     case 0:
00310                     {
00311                         pnt3.setX( pnt4.x() - (int)diff1.width() / 2 );
00312                         pnt3.setY( pnt1.y() );
00313                     } break;
00314                     case 180:
00315                     {
00316                         pnt3.setX( pnt4.x() + (int)diff1.width() / 2 );
00317                         pnt3.setY( pnt1.y() );
00318                     } break;
00319                     case 90:
00320                     {
00321                         pnt3.setX( pnt1.x() );
00322                         pnt3.setY( pnt4.y() - (int)diff1.width() / 2 );
00323                     } break;
00324                     case 270:
00325                     {
00326                         pnt3.setX( pnt1.x() );
00327                         pnt3.setY( pnt4.y() + (int)diff1.width() / 2 );
00328                     } break;
00329                     default:
00330                         pnt3 = pnt1;
00331                         break;
00332                     }
00333 
00334                     drawFigure( lineBegin, _painter, _zoomHandler->unzoomPoint( pnt3 ), pen2.color(), _w, _angle, _zoomHandler );
00335                 }
00336 
00337                 if ( lineEnd != L_NORMAL && !drawContour )
00338                 {
00339                     QPoint pnt1( pntArray2.at( pntArray2.size() - 1 ) ), pnt2( pntArray2.at( pntArray2.size() - 2 ) );
00340                     QPoint  pnt3, pnt4( pntArray.at( pntArray.size() - 1 ) );
00341                     float _angle = KoPoint::getAngle( KoPoint( pnt1 ), KoPoint( pnt2 ) );
00342 
00343                     switch ( ( int )_angle )
00344                     {
00345                     case 0:
00346                     {
00347                         pnt3.setX( pnt4.x() - (int)diff2.width() / 2 );
00348                         pnt3.setY( pnt1.y() );
00349                     } break;
00350                     case 180:
00351                     {
00352                         pnt3.setX( pnt4.x() + (int)diff2.width() / 2 );
00353                         pnt3.setY( pnt1.y() );
00354                     } break;
00355                     case 90:
00356                     {
00357                         pnt3.setX( pnt1.x() );
00358                         pnt3.setY( pnt4.y() - (int)diff2.width() / 2 );
00359                     } break;
00360                     case 270:
00361                     {
00362                         pnt3.setX( pnt1.x() );
00363                         pnt3.setY( pnt4.y() + (int)diff2.width() / 2 );
00364                     } break;
00365                     default:
00366                         pnt3 = pnt1;
00367                         break;
00368                     }
00369 
00370                     drawFigure( lineEnd, _painter, _zoomHandler->unzoomPoint( pnt3 ), pen2.color(), _w, _angle,_zoomHandler );
00371                 }
00372             }
00373 
00374             _painter->setPen( pen2 );
00375             _painter->drawPolyline( pntArray2 );
00376         }
00377     }
00378 }
KDE Home | KDE Accessibility Home | Description of Access Keys