lib Library API Documentation

koPictureShared.cc

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