F:/KPlato/koffice/libs/kofficecore/KoPictureShared.cpp

Aller à la documentation de ce fichier.
00001 /* This file is part of the KDE project
00002    Copyright (c) 2001 Simon Hausmann <hausmann@kde.org>
00003    Copyright (C) 2002, 2003, 2004 Nicolas GOUTTE <goutte@kde.org>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include <QFile>
00022 #include <QImageReader>
00023 #include <QImageWriter>
00024 #include <QPainter>
00025 //Added by qt3to4:
00026 #include <QPixmap>
00027 
00028 #include <kdebug.h>
00029 #include <kurl.h>
00030 #include <kfilterdev.h>
00031 #include <kio/netaccess.h>
00032 #include <QBuffer>
00033 #include "KoPictureKey.h"
00034 #include "KoPictureBase.h"
00035 #include "KoPictureImage.h"
00036 #include "KoPictureEps.h"
00037 #include "KoPictureClipart.h"
00038 #include "KoPictureWmf.h"
00039 #include "KoPictureShared.h"
00040 #include <kcodecs.h>
00041 
00042 
00043 KoPictureShared::KoPictureShared(void) : m_base(NULL)
00044 {
00045 }
00046 
00047 void KoPictureShared::assignPictureId( uint _id)
00048 {
00049     m_pictureId = _id;
00050 }
00051 
00052 QString KoPictureShared::uniquePictureId() const
00053 {
00054     return "Pictures"+ QString::number(m_pictureId);
00055 }
00056 
00057 KoPictureShared::~KoPictureShared(void)
00058 {
00059     delete m_base;
00060 }
00061 
00062 KoPictureShared::KoPictureShared(const KoPictureShared &other)
00063     : Q3Shared() // Some compilers want it explicitly!
00064 {
00065     // We need to use newCopy, because we want a real copy, not just a copy of the part of KoPictureBase
00066     if (other.m_base)
00067         m_base=other.m_base->newCopy();
00068     else
00069         m_base=NULL;
00070 }
00071 
00072 KoPictureShared& KoPictureShared::operator=( const KoPictureShared &other )
00073 {
00074     clear();
00075     kDebug(30003) << "KoPictureShared::= before" << endl;
00076     if (other.m_base)
00077         m_base=other.m_base->newCopy();
00078     kDebug(30003) << "KoPictureShared::= after" << endl;
00079     return *this;
00080 }
00081 
00082 KoPictureType::Type KoPictureShared::getType(void) const
00083 {
00084     if (m_base)
00085         return m_base->getType();
00086     return KoPictureType::TypeUnknown;
00087 }
00088 
00089 bool KoPictureShared::isNull(void) const
00090 {
00091     if (m_base)
00092         return m_base->isNull();
00093     return true;
00094 }
00095 
00096 void KoPictureShared::draw(QPainter& painter, int x, int y, int width, int height, int sx, int sy, int sw, int sh, bool fastMode)
00097 {
00098     if (m_base)
00099         m_base->draw(painter, x, y, width, height, sx, sy, sw, sh, fastMode);
00100     else
00101     {
00102         // Draw a red box (easier DEBUG)
00103         kWarning(30003) << "Drawing red rectangle! (KoPictureShared::draw)" << endl;
00104         painter.save();
00105         painter.setBrush(QColor(255,0,0));
00106         painter.drawRect(x,y,width,height);
00107         painter.restore();
00108     }
00109 }
00110 
00111 bool KoPictureShared::loadWmf(QIODevice* io)
00112 {
00113     kDebug(30003) << "KoPictureShared::loadWmf" << endl;
00114     if (!io)
00115     {
00116         kError(30003) << "No QIODevice!" << endl;
00117         return false;
00118     }
00119 
00120     clear();
00121 
00122     // The extension .wmf was used (KOffice 1.1.x) for QPicture files
00123     // For an extern file or in the storage, .wmf can mean a real Windows Meta File.
00124 
00125     QByteArray array ( io->readAll() );
00126 
00127     if ((array[0]=='Q') && (array[1]=='P') &&(array[2]=='I') && (array[3]=='C'))
00128     {
00129         m_base=new KoPictureClipart();
00130         setExtension("qpic");
00131     }
00132     else
00133     {
00134         m_base=new KoPictureWmf();
00135         setExtension("wmf");
00136     }
00137     return m_base->loadData(array, m_extension);
00138 }
00139 
00140 bool KoPictureShared::loadTmp(QIODevice* io)
00141 // We have a temp file, probably from a downloaded file
00142 //   We must check the file type
00143 {
00144     kDebug(30003) << "KoPictureShared::loadTmp" << endl;
00145     if (!io)
00146     {
00147         kError(30003) << "No QIODevice!" << endl;
00148         return false;
00149     }
00150 
00151     // The extension .wmf was used (KOffice 1.1.x) for QPicture files
00152     // For an extern file or in the storage, .wmf can mean a real Windows Meta File.
00153 
00154     QByteArray array ( io->readAll() );
00155     return identifyAndLoad( array );
00156 }
00157 
00158 bool KoPictureShared::identifyAndLoad( QByteArray array )
00159 {
00160     if ( array.size() < 5 )
00161     {
00162         kError(30003) << "Picture is less than 5 bytes long!" << endl;
00163         return false;
00164     }
00165 
00166     QString strExtension;
00167     bool flag=false;
00168 
00169     // Try to find the file type by comparing magic on the first few bytes!
00170     // ### TODO: could not QImageIO::imageFormat do it too? (At least most of them?)
00171     if ((array[0]==char(0x89)) && (array[1]=='P') &&(array[2]=='N') && (array[3]=='G'))
00172     {
00173         strExtension="png";
00174     }
00175     else if ((array[0]==char(0xff)) && (array[1]==char(0xd8)) &&(array[2]==char(0xff)) && (array[3]==char(0xe0)))
00176     {
00177         strExtension="jpeg";
00178     }
00179     else if ((array[0]=='B') && (array[1]=='M'))
00180     {
00181         strExtension="bmp";
00182     }
00183     else if ((array[0]==char(0xd7)) && (array[1]==char(0xcd)) &&(array[2]==char(0xc6)) && (array[3]==char(0x9a)))
00184     {
00185         strExtension="wmf";
00186     }
00187     else if ((array[0]=='<') && (array[1]=='?') && ( array[2]=='x' ) && (array[3]=='m') && ( array[4]=='l' ) )
00188     {
00189         strExtension="svg";
00190     }
00191     else if ((array[0]=='Q') && (array[1]=='P') &&(array[2]=='I') && (array[3]=='C'))
00192     {
00193         strExtension="qpic";
00194     }
00195     else if ((array[0]=='%') && (array[1]=='!') &&(array[2]=='P') && (array[3]=='S'))
00196     {
00197         strExtension="eps";
00198     }
00199     else if ((array[0]==char(0xc5)) && (array[1]==char(0xd0)) && (array[2]==char(0xd3)) && (array[3]==char(0xc6)))
00200     {
00201         // So called "MS-DOS EPS file"
00202         strExtension="eps";
00203     }
00204     else if ((array[0]=='G') && (array[1]=='I') && (array[2]=='F') && (array[3]=='8'))
00205     {
00206         // GIF (87a or 89a)
00207         strExtension="gif";
00208     }
00209     else if ( ( array[0] == char( 0037 ) ) && ( array[1] == char( 0213 ) ) )
00210     {
00211         // Gzip
00212         QBuffer buffer(&array);
00213         buffer.open(QIODevice::ReadOnly);
00214 
00215         const bool flag = loadCompressed( &buffer, "application/x-gzip", "tmp" );
00216         buffer.close();
00217         return flag;
00218     }
00219     else if ( ( array[0] == 'B' ) && ( array[1] == 'Z' ) && ( array[2] == 'h') )
00220     {
00221         // BZip2
00222         QBuffer buffer(&array);
00223         buffer.open(QIODevice::ReadOnly);
00224         const bool flag = loadCompressed( &buffer, "application/x-bzip2", "tmp" );
00225         buffer.close();
00226         return flag;
00227     }
00228     else
00229     {
00230         kDebug(30003) << "Cannot identify the type of temp file!"
00231             << " Trying to convert to PNG! (in KoPictureShared::loadTmp" << endl;
00232 
00233         // Do not trust QBuffer and do not work directly on the QByteArray array
00234         // DF: It would be faster to work on array here, and to create a completely
00235         // different QBuffer for the writing code!
00236         QBuffer buf( &array );
00237         if (!buf.open(QIODevice::ReadOnly))
00238         {
00239             kError(30003) << "Could not open read buffer!" << endl;
00240             return false;
00241         }
00242 
00243         QImageReader imageReader( &buf );
00244         QImage image = imageReader.read();
00245         if ( image.isNull() )
00246         {
00247             kError(30003) << "Could not read image!" << endl;
00248             return false;
00249         }
00250         buf.close();
00251 
00252         if ( !buf.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
00253         {
00254             kError(30003) << "Could not open write buffer!" << endl;
00255             return false;
00256         }
00257 
00258         QImageWriter imageWriter( &buf, "PNG" );
00259 
00260         if ( !imageWriter.write( image ) )
00261         {
00262             kError(30003) << "Could not write converted image!" << endl;
00263             return false;
00264         }
00265         buf.close();
00266 
00267         array = buf.buffer();
00268 
00269         strExtension="png";
00270     }
00271 
00272     kDebug(30003) << "Temp file considered to be " << strExtension << endl;
00273 
00274     clearAndSetMode(strExtension);
00275     if (m_base)
00276         flag = m_base->loadData(array,strExtension);
00277     setExtension(strExtension);
00278 
00279     return flag;
00280 }
00281 
00282 
00283 
00284 bool KoPictureShared::loadXpm(QIODevice* io)
00285 {
00286     kDebug(30003) << "KoPictureShared::loadXpm" << endl;
00287     if (!io)
00288     {
00289         kError(30003) << "No QIODevice!" << endl;
00290         return false;
00291     }
00292 
00293     clear();
00294 
00295     // Old KPresenter XPM files have char(1) instead of some "
00296     // Therefore we need to treat XPM separately
00297 
00298     QByteArray array = io->readAll();
00299 
00300     // As XPM files are normally only ASCII files, we can replace it without problems
00301 
00302     int pos=0;
00303 
00304     while ( (pos = array.indexOf( char(1), pos ) )!=-1)
00305     {
00306         array[pos]='"';
00307     }
00308 
00309     // Now that the XPM file is corrected, we need to load it.
00310 
00311     m_base=new KoPictureImage();
00312 
00313     QBuffer buffer(&array);
00314     bool check = m_base->load(&buffer,"xpm");
00315     setExtension("xpm");
00316     return check;
00317 }
00318 
00319 bool KoPictureShared::save(QIODevice* io) const
00320 {
00321     if (!io)
00322         return false;
00323     if (m_base)
00324         return m_base->save(io);
00325     return false;
00326 }
00327 
00328 bool KoPictureShared::saveAsBase64( KoXmlWriter& writer ) const
00329 {
00330     if ( m_base )
00331         m_base->saveAsBase64( writer );
00332     return false;
00333 }
00334 
00335 void KoPictureShared::clear(void)
00336 {
00337     // Clear does not reset the key m_key!
00338     delete m_base;
00339     m_base=NULL;
00340 }
00341 
00342 void KoPictureShared::clearAndSetMode(const QString& newMode)
00343 {
00344     delete m_base;
00345     m_base=NULL;
00346 
00347     const QString mode = newMode.toLower();
00348 
00349     if ((mode=="svg") || (mode=="qpic"))
00350     {
00351         m_base=new KoPictureClipart();
00352     }
00353     else if (mode=="wmf")
00354     {
00355         m_base=new KoPictureWmf();
00356     }
00357     else if ( (mode=="eps") || (mode=="epsi") || (mode=="epsf") )
00358     {
00359         m_base=new KoPictureEps();
00360     }
00361     else
00362     {   // TODO: test if QImageIO really knows the file format
00363         m_base=new KoPictureImage();
00364     }
00365 }
00366 
00367 QString KoPictureShared::getExtension(void) const
00368 {
00369     return m_extension;
00370 }
00371 
00372 void KoPictureShared::setExtension(const QString& extension)
00373 {
00374     m_extension = extension;
00375 }
00376 
00377 QString KoPictureShared::getMimeType(void) const
00378 {
00379    if (m_base)
00380         return m_base->getMimeType(m_extension);
00381     return QString(NULL_MIME_TYPE);
00382 }
00383 
00384 
00385 bool KoPictureShared::loadFromBase64( const QByteArray& str )
00386 {
00387     clear();
00388     QByteArray data;
00389     KCodecs::base64Decode( str, data );
00390     return identifyAndLoad( data );
00391 }
00392 
00393 bool KoPictureShared::load(QIODevice* io, const QString& extension)
00394 {
00395     kDebug(30003) << "KoPictureShared::load(QIODevice*, const QString&) " << extension << endl;
00396     bool flag=false;
00397     QString ext( extension.toLower() );
00398     if (ext=="wmf")
00399         flag=loadWmf(io);
00400     else if (ext=="tmp") // ### TODO: also remote scripts need this, don't they?
00401         flag=loadTmp(io);
00402     else if ( ext == "bz2" )
00403     {
00404         flag = loadCompressed( io, "application/x-bzip2", "tmp" );
00405     }
00406     else if ( ext == "gz" )
00407     {
00408         flag = loadCompressed( io, "application/x-gzip", "tmp" );
00409     }
00410     else if ( ext == "svgz" )
00411     {
00412         flag = loadCompressed( io, "application/x-gzip", "svg" );
00413     }
00414     else
00415     {
00416         clearAndSetMode(ext);
00417         if (m_base)
00418             flag = m_base->load(io, ext);
00419         setExtension(ext);
00420     }
00421     if (!flag)
00422     {
00423         kError(30003) << "File was not loaded! (KoPictureShared::load)" << endl;
00424     }
00425     return flag;
00426 }
00427 
00428 bool KoPictureShared::loadFromFile(const QString& fileName)
00429 {
00430     kDebug(30003) << "KoPictureShared::loadFromFile " << fileName << endl;
00431     if ( fileName.isEmpty() )
00432     {
00433         kError(30003) << "Cannot load file with empty name!" << endl;
00434         return false;
00435     }
00436     QFile file(fileName);
00437     if (!file.open(QIODevice::ReadOnly))
00438         return false;
00439 
00440     bool flag = false;
00441     const int pos = fileName.lastIndexOf('.');
00442     if (pos==-1)
00443     {
00444         kDebug(30003) << "File with no extension!" << endl;
00445         // As we have no extension, consider it like a temporary file
00446         flag = loadTmp( &file );
00447     }
00448     else
00449     {
00450         const QString extension( fileName.mid( pos+1 ) );
00451         // ### TODO: check if the extension if gz or bz2 and find the previous extension
00452         flag = load( &file, extension );
00453     }
00454     file.close();
00455     return flag;
00456 }
00457 
00458 QSize KoPictureShared::getOriginalSize(void) const
00459 {
00460     if (m_base)
00461         return m_base->getOriginalSize();
00462     return QSize(0,0);
00463 }
00464 
00465 QPixmap KoPictureShared::generatePixmap(const QSize& size, bool smoothScale)
00466 {
00467     if (m_base)
00468         return m_base->generatePixmap(size, smoothScale);
00469     return QPixmap();
00470 }
00471 
00472 Q3DragObject* KoPictureShared::dragObject( QWidget *dragSource, const char *name )
00473 {
00474     if (m_base)
00475         return m_base->dragObject( dragSource, name );
00476     return 0L;
00477 }
00478 
00479 QImage KoPictureShared::generateImage(const QSize& size)
00480 {
00481     if (m_base)
00482         return m_base->generateImage( size );
00483     return QImage();
00484 }
00485 
00486 bool KoPictureShared::hasAlphaBuffer() const
00487 {
00488    if (m_base)
00489        return m_base->hasAlphaBuffer();
00490    return false;
00491 }
00492 
00493 void KoPictureShared::setAlphaBuffer(bool enable)
00494 {
00495     if (m_base)
00496         m_base->setAlphaBuffer(enable);
00497 }
00498 
00499 QImage KoPictureShared::createAlphaMask(Qt::ImageConversionFlags flags) const
00500 {
00501     if (m_base)
00502         return m_base->createAlphaMask(flags);
00503     return QImage();
00504 }
00505 
00506 void KoPictureShared::clearCache(void)
00507 {
00508     if (m_base)
00509         m_base->clearCache();
00510 }
00511 
00512 bool KoPictureShared::loadCompressed( QIODevice* io, const QString& mimeType, const QString& extension )
00513 {
00514     // ### TODO: check that we do not have an endless recursion
00515     QIODevice* in = KFilterDev::device( io, mimeType, false);
00516 
00517     if ( !in )
00518     {
00519         kError(30003) << "Cannot create device for uncompressing! Aborting!" << endl;
00520         return false;
00521     }
00522 
00523 
00524     if ( !in->open( QIODevice::ReadOnly ) )
00525     {
00526         kError(30003) << "Cannot open file for uncompressing! Aborting!" << endl;
00527         delete in;
00528         return false;
00529     }
00530 
00531     const bool flag = load( in, extension );
00532 
00533     in->close();
00534     delete in;
00535 
00536     return flag;
00537 }

Généré le Wed Nov 22 23:41:03 2006 pour KPlato par  doxygen 1.5.1-p1