diff options
Diffstat (limited to 'lib/kofficecore/KoPictureShared.cpp')
-rw-r--r-- | lib/kofficecore/KoPictureShared.cpp | 535 |
1 files changed, 535 insertions, 0 deletions
diff --git a/lib/kofficecore/KoPictureShared.cpp b/lib/kofficecore/KoPictureShared.cpp new file mode 100644 index 000000000..5c2ff2a2b --- /dev/null +++ b/lib/kofficecore/KoPictureShared.cpp @@ -0,0 +1,535 @@ +/* This file is part of the KDE project + Copyright (c) 2001 Simon Hausmann <hausmann@kde.org> + Copyright (C) 2002, 2003, 2004 Nicolas GOUTTE <goutte@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include <qpainter.h> +#include <qfile.h> + +#include <kdebug.h> +#include <kurl.h> +#include <kfilterdev.h> +#include <kio/netaccess.h> + +#include "KoPictureKey.h" +#include "KoPictureBase.h" +#include "KoPictureImage.h" +#include "KoPictureEps.h" +#include "KoPictureClipart.h" +#include "KoPictureWmf.h" +#include "KoPictureShared.h" +#include <kmdcodec.h> + + +KoPictureShared::KoPictureShared(void) : m_base(NULL) +{ +} + +void KoPictureShared::assignPictureId( uint _id) +{ + m_pictureId = _id; +} + +QString KoPictureShared::uniquePictureId() const +{ + return "Pictures"+ QString::number(m_pictureId); +} + +KoPictureShared::~KoPictureShared(void) +{ + delete m_base; +} + +KoPictureShared::KoPictureShared(const KoPictureShared &other) + : QShared() // Some compilers want it explicitly! +{ + // We need to use newCopy, because we want a real copy, not just a copy of the part of KoPictureBase + if (other.m_base) + m_base=other.m_base->newCopy(); + else + m_base=NULL; +} + +KoPictureShared& KoPictureShared::operator=( const KoPictureShared &other ) +{ + clear(); + kdDebug(30003) << "KoPictureShared::= before" << endl; + if (other.m_base) + m_base=other.m_base->newCopy(); + kdDebug(30003) << "KoPictureShared::= after" << endl; + return *this; +} + +KoPictureType::Type KoPictureShared::getType(void) const +{ + if (m_base) + return m_base->getType(); + return KoPictureType::TypeUnknown; +} + +bool KoPictureShared::isNull(void) const +{ + if (m_base) + return m_base->isNull(); + return true; +} + +void KoPictureShared::draw(QPainter& painter, int x, int y, int width, int height, int sx, int sy, int sw, int sh, bool fastMode) +{ + if (m_base) + m_base->draw(painter, x, y, width, height, sx, sy, sw, sh, fastMode); + else + { + // Draw a red box (easier DEBUG) + kdWarning(30003) << "Drawing red rectangle! (KoPictureShared::draw)" << endl; + painter.save(); + painter.setBrush(QColor(255,0,0)); + painter.drawRect(x,y,width,height); + painter.restore(); + } +} + +bool KoPictureShared::loadWmf(QIODevice* io) +{ + kdDebug(30003) << "KoPictureShared::loadWmf" << endl; + if (!io) + { + kdError(30003) << "No QIODevice!" << endl; + return false; + } + + clear(); + + // The extension .wmf was used (KOffice 1.1.x) for QPicture files + // For an extern file or in the storage, .wmf can mean a real Windows Meta File. + + QByteArray array ( io->readAll() ); + + if ((array[0]=='Q') && (array[1]=='P') &&(array[2]=='I') && (array[3]=='C')) + { + m_base=new KoPictureClipart(); + setExtension("qpic"); + } + else + { + m_base=new KoPictureWmf(); + setExtension("wmf"); + } + return m_base->loadData(array, m_extension); +} + +bool KoPictureShared::loadTmp(QIODevice* io) +// We have a temp file, probably from a downloaded file +// We must check the file type +{ + kdDebug(30003) << "KoPictureShared::loadTmp" << endl; + if (!io) + { + kdError(30003) << "No QIODevice!" << endl; + return false; + } + + // The extension .wmf was used (KOffice 1.1.x) for QPicture files + // For an extern file or in the storage, .wmf can mean a real Windows Meta File. + + QByteArray array ( io->readAll() ); + return identifyAndLoad( array ); +} + +bool KoPictureShared::identifyAndLoad( QByteArray array ) +{ + if ( array.size() < 5 ) + { + kdError(30003) << "Picture is less than 5 bytes long!" << endl; + return false; + } + + QString strExtension; + bool flag=false; + + // Try to find the file type by comparing magic on the first few bytes! + // ### TODO: could not QImageIO::imageFormat do it too? (At least most of them?) + if ((array[0]==char(0x89)) && (array[1]=='P') &&(array[2]=='N') && (array[3]=='G')) + { + strExtension="png"; + } + else if ((array[0]==char(0xff)) && (array[1]==char(0xd8)) &&(array[2]==char(0xff)) && (array[3]==char(0xe0))) + { + strExtension="jpeg"; + } + else if ((array[0]=='B') && (array[1]=='M')) + { + strExtension="bmp"; + } + else if ((array[0]==char(0xd7)) && (array[1]==char(0xcd)) &&(array[2]==char(0xc6)) && (array[3]==char(0x9a))) + { + strExtension="wmf"; + } + else if ((array[0]=='<') && (array[1]=='?') && ( array[2]=='x' ) && (array[3]=='m') && ( array[4]=='l' ) ) + { + strExtension="svg"; + } + else if ((array[0]=='Q') && (array[1]=='P') &&(array[2]=='I') && (array[3]=='C')) + { + strExtension="qpic"; + } + else if ((array[0]=='%') && (array[1]=='!') &&(array[2]=='P') && (array[3]=='S')) + { + strExtension="eps"; + } + else if ((array[0]==char(0xc5)) && (array[1]==char(0xd0)) && (array[2]==char(0xd3)) && (array[3]==char(0xc6))) + { + // So called "MS-DOS EPS file" + strExtension="eps"; + } + else if ((array[0]=='G') && (array[1]=='I') && (array[2]=='F') && (array[3]=='8')) + { + // GIF (87a or 89a) + strExtension="gif"; + } + else if ( ( array[0] == char( 0037 ) ) && ( array[1] == char( 0213 ) ) ) + { + // Gzip + QBuffer buffer(array); + buffer.open(IO_ReadOnly); + + const bool flag = loadCompressed( &buffer, "application/x-gzip", "tmp" ); + buffer.close(); + return flag; + } + else if ( ( array[0] == 'B' ) && ( array[1] == 'Z' ) && ( array[2] == 'h') ) + { + // BZip2 + QBuffer buffer(array); + buffer.open(IO_ReadOnly); + const bool flag = loadCompressed( &buffer, "application/x-bzip2", "tmp" ); + buffer.close(); + return flag; + } + else + { + kdDebug(30003) << "Cannot identify the type of temp file!" + << " Trying to convert to PNG! (in KoPictureShared::loadTmp" << endl; + + // Do not trust QBuffer and do not work directly on the QByteArray array + // DF: It would be faster to work on array here, and to create a completely + // different QBuffer for the writing code! + QBuffer buf( array.copy() ); + if (!buf.open(IO_ReadOnly)) + { + kdError(30003) << "Could not open read buffer!" << endl; + return false; + } + + QImageIO imageIO(&buf,NULL); + + if (!imageIO.read()) + { + kdError(30003) << "Could not read image!" << endl; + return false; + } + + buf.close(); + + if ( !buf.open( IO_WriteOnly | IO_Truncate ) ) + { + kdError(30003) << "Could not open write buffer!" << endl; + return false; + } + + imageIO.setIODevice(&buf); + imageIO.setFormat("PNG"); + + if (!imageIO.write()) + { + kdError(30003) << "Could not write converted image!" << endl; + return false; + } + buf.close(); + + array = buf.buffer(); + + strExtension="png"; + } + + kdDebug(30003) << "Temp file considered to be " << strExtension << endl; + + clearAndSetMode(strExtension); + if (m_base) + flag = m_base->loadData(array,strExtension); + setExtension(strExtension); + + return flag; +} + + + +bool KoPictureShared::loadXpm(QIODevice* io) +{ + kdDebug(30003) << "KoPictureShared::loadXpm" << endl; + if (!io) + { + kdError(30003) << "No QIODevice!" << endl; + return false; + } + + clear(); + + // Old KPresenter XPM files have char(1) instead of some " + // Therefore we need to treat XPM separately + + QByteArray array=io->readAll(); + + // As XPM files are normally only ASCII files, we can replace it without problems + + int pos=0; + + while ((pos=array.find(char(1),pos))!=-1) + { + array[pos]='"'; + } + + // Now that the XPM file is corrected, we need to load it. + + m_base=new KoPictureImage(); + + QBuffer buffer(array); + bool check = m_base->load(&buffer,"xpm"); + setExtension("xpm"); + return check; +} + +bool KoPictureShared::save(QIODevice* io) const +{ + if (!io) + return false; + if (m_base) + return m_base->save(io); + return false; +} + +bool KoPictureShared::saveAsBase64( KoXmlWriter& writer ) const +{ + if ( m_base ) + m_base->saveAsBase64( writer ); + return false; +} + +void KoPictureShared::clear(void) +{ + // Clear does not reset the key m_key! + delete m_base; + m_base=NULL; +} + +void KoPictureShared::clearAndSetMode(const QString& newMode) +{ + delete m_base; + m_base=NULL; + + const QString mode=newMode.lower(); + + if ((mode=="svg") || (mode=="qpic")) + { + m_base=new KoPictureClipart(); + } + else if (mode=="wmf") + { + m_base=new KoPictureWmf(); + } + else if ( (mode=="eps") || (mode=="epsi") || (mode=="epsf") ) + { + m_base=new KoPictureEps(); + } + else + { // TODO: test if QImageIO really knows the file format + m_base=new KoPictureImage(); + } +} + +QString KoPictureShared::getExtension(void) const +{ + return m_extension; +} + +void KoPictureShared::setExtension(const QString& extension) +{ + m_extension = extension; +} + +QString KoPictureShared::getMimeType(void) const +{ + if (m_base) + return m_base->getMimeType(m_extension); + return QString(NULL_MIME_TYPE); +} + + +bool KoPictureShared::loadFromBase64( const QCString& str ) +{ + clear(); + QByteArray data; + KCodecs::base64Decode( str, data ); + return identifyAndLoad( data ); +} + +bool KoPictureShared::load(QIODevice* io, const QString& extension) +{ + kdDebug(30003) << "KoPictureShared::load(QIODevice*, const QString&) " << extension << endl; + bool flag=false; + QString ext(extension.lower()); + if (ext=="wmf") + flag=loadWmf(io); + else if (ext=="tmp") // ### TODO: also remote scripts need this, don't they? + flag=loadTmp(io); + else if ( ext == "bz2" ) + { + flag = loadCompressed( io, "application/x-bzip2", "tmp" ); + } + else if ( ext == "gz" ) + { + flag = loadCompressed( io, "application/x-gzip", "tmp" ); + } + else if ( ext == "svgz" ) + { + flag = loadCompressed( io, "application/x-gzip", "svg" ); + } + else + { + clearAndSetMode(ext); + if (m_base) + flag = m_base->load(io, ext); + setExtension(ext); + } + if (!flag) + { + kdError(30003) << "File was not loaded! (KoPictureShared::load)" << endl; + } + return flag; +} + +bool KoPictureShared::loadFromFile(const QString& fileName) +{ + kdDebug(30003) << "KoPictureShared::loadFromFile " << fileName << endl; + if ( fileName.isEmpty() ) + { + kdError(30003) << "Cannot load file with empty name!" << endl; + return false; + } + QFile file(fileName); + if (!file.open(IO_ReadOnly)) + return false; + + bool flag = false; + const int pos=fileName.findRev('.'); + if (pos==-1) + { + kdDebug(30003) << "File with no extension!" << endl; + // As we have no extension, consider it like a temporary file + flag = loadTmp( &file ); + } + else + { + const QString extension( fileName.mid( pos+1 ) ); + // ### TODO: check if the extension if gz or bz2 and find the previous extension + flag = load( &file, extension ); + } + file.close(); + return flag; +} + +QSize KoPictureShared::getOriginalSize(void) const +{ + if (m_base) + return m_base->getOriginalSize(); + return QSize(0,0); +} + +QPixmap KoPictureShared::generatePixmap(const QSize& size, bool smoothScale) +{ + if (m_base) + return m_base->generatePixmap(size, smoothScale); + return QPixmap(); +} + +QDragObject* KoPictureShared::dragObject( QWidget *dragSource, const char *name ) +{ + if (m_base) + return m_base->dragObject( dragSource, name ); + return 0L; +} + +QImage KoPictureShared::generateImage(const QSize& size) +{ + if (m_base) + return m_base->generateImage( size ); + return QImage(); +} + +bool KoPictureShared::hasAlphaBuffer() const +{ + if (m_base) + return m_base->hasAlphaBuffer(); + return false; +} + +void KoPictureShared::setAlphaBuffer(bool enable) +{ + if (m_base) + m_base->setAlphaBuffer(enable); +} + +QImage KoPictureShared::createAlphaMask(int conversion_flags) const +{ + if (m_base) + return m_base->createAlphaMask(conversion_flags); + return QImage(); +} + +void KoPictureShared::clearCache(void) +{ + if (m_base) + m_base->clearCache(); +} + +bool KoPictureShared::loadCompressed( QIODevice* io, const QString& mimeType, const QString& extension ) +{ + // ### TODO: check that we do not have an endless recursion + QIODevice* in = KFilterDev::device( io, mimeType, false); + + if ( !in ) + { + kdError(30003) << "Cannot create device for uncompressing! Aborting!" << endl; + return false; + } + + + if ( !in->open( IO_ReadOnly ) ) + { + kdError(30003) << "Cannot open file for uncompressing! Aborting!" << endl; + delete in; + return false; + } + + const bool flag = load( in, extension ); + + in->close(); + delete in; + + return flag; +} |