filters

xcfexport.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2002, The Karbon Developers
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include <qcstring.h>
00021 #include <qdatastream.h>
00022 #include <qdom.h>
00023 #include <qfile.h>
00024 #include <qstring.h>
00025 #include <qvaluelist.h>
00026 
00027 #include <kgenericfactory.h>
00028 #include <KoFilter.h>
00029 #include <KoFilterChain.h>
00030 #include <KoStore.h>
00031 
00032 #include "vdocument.h"
00033 #include "vlayer.h"
00034 #include "xcfexport.h"
00035 
00036 #include <kdebug.h>
00037 
00038 
00039 // Tile size constants.
00040 const unsigned XcfExport::m_tileWidth  = 64;
00041 const unsigned XcfExport::m_tileHeight = 64;
00042 
00043 
00044 typedef KGenericFactory<XcfExport, KoFilter> XcfExportFactory;
00045 K_EXPORT_COMPONENT_FACTORY( libkarbonxcfexport, XcfExportFactory( "kofficefilters" ) )
00046 
00047 
00048 XcfExport::XcfExport( KoFilter*, const char*, const QStringList& )
00049     : KoFilter()
00050 {
00051     m_zoomX = 1.0;
00052     m_zoomY = 1.0;
00053 }
00054 
00055 KoFilter::ConversionStatus
00056 XcfExport::convert( const QCString& from, const QCString& to )
00057 {
00058     if( to != "image/x-xcf-gimp" || from != "application/x-karbon" )
00059     {
00060         return KoFilter::NotImplemented;
00061     }
00062 
00063 
00064     KoStoreDevice* storeIn = m_chain->storageFile( "root", KoStore::Read );
00065 
00066     if( !storeIn )
00067         return KoFilter::StupidError;
00068 
00069 
00070     QFile fileOut( m_chain->outputFile() );
00071 
00072     if( !fileOut.open( IO_WriteOnly ) )
00073         return KoFilter::StupidError;
00074 
00075 
00076     QDomDocument domIn;
00077     domIn.setContent( storeIn );
00078     QDomElement docNode = domIn.documentElement();
00079 
00080     m_stream = new QDataStream( &fileOut );
00081 
00082 
00083     // Load the document.
00084     VDocument doc;
00085     doc.load( docNode );
00086 
00087     // Process the document.
00088     doc.accept( *this );
00089 
00090 
00091     delete m_stream;
00092     fileOut.close();
00093 
00094     return KoFilter::OK;
00095 }
00096 
00097 void
00098 XcfExport::visitVDocument( VDocument& document )
00099 {
00100     // Offsets.
00101     QIODevice::Offset current = 0;
00102     QIODevice::Offset start = 0;
00103     QIODevice::Offset end = 0;
00104 
00105     // Save width and height for layer saving.
00106     m_width  = static_cast<unsigned>( document.width()  * m_zoomX );
00107     m_height = static_cast<unsigned>( document.height() * m_zoomY );
00108 
00109 
00110     // Header tag (size 14 bytes).
00111     m_stream->writeRawBytes( "gimp xcf file", 14 );
00112 
00113     // Image width.
00114     *m_stream << static_cast<Q_UINT32>( m_width );
00115 
00116     // Image height.
00117     *m_stream << static_cast<Q_UINT32>( m_height );
00118 
00119     // Image type = RGB.
00120     *m_stream << static_cast<Q_UINT32>( 0 );
00121 
00122     // Do not save any properties currently.
00123     *m_stream
00124         // "END".
00125         << static_cast<Q_UINT32>( 0 )
00126         // Property size in bytes.
00127         << static_cast<Q_UINT32>( 0 );
00128 
00129 
00130     // Save current offset.
00131     current = m_stream->device()->at();
00132 
00133     // Leave space for layer and channel offsets.
00134     m_stream->device()->at(
00135         // current position + (number layers + number channels + 2) * 4.
00136         current + ( document.layers().count() + 3 + 2 ) * 4 );
00137 
00138 
00139     // Iterate over layers.
00140     VLayerListIterator itr( document.layers() );
00141 
00142     for( ; itr.current(); ++itr )
00143     {
00144         // Save start offset.
00145         start = m_stream->device()->at();
00146 
00147 
00148         // Write layer.
00149         itr.current()->accept( *this );
00150 
00151 
00152         // Save end offset.
00153         end = m_stream->device()->at();
00154 
00155         // Return to current offset.
00156         m_stream->device()->at( current );
00157 
00158         // Save layer offset.
00159         *m_stream << start;
00160 
00161         // Increment offset.
00162         current = m_stream->device()->at();
00163 
00164         // Return to end offset.
00165         m_stream->device()->at( end );
00166     }
00167 
00168 
00169     // Return to current offset.
00170     m_stream->device()->at( current );
00171 
00172     // Append a zero offset to indicate end of layer offsets.
00173     *m_stream << static_cast<Q_UINT32>( 0 );
00174 
00175 
00176     // Return to end offset.
00177     m_stream->device()->at( end );
00178 
00179     // Append a zero offset to indicate end of channel offsets.
00180     *m_stream << static_cast<Q_UINT32>( 0 );
00181 }
00182 
00183 void
00184 XcfExport::visitVLayer( VLayer& layer )
00185 {
00186     // Layer width = image width.
00187     *m_stream << static_cast<Q_UINT32>( m_width );
00188 
00189     // Layer height = image height.
00190     *m_stream << static_cast<Q_UINT32>( m_height );
00191 
00192     // Layer type = RGBA.
00193     *m_stream << static_cast<Q_UINT32>( 1 );
00194 
00195     // Layer name.
00196     *m_stream << layer.name().latin1();
00197 
00198     // Layer opacity.
00199     *m_stream << static_cast<Q_UINT32>( 6 );
00200     // Property size in bytes.
00201     *m_stream << static_cast<Q_UINT32>( 4 );
00202     // Fully opaque = 255.
00203     *m_stream << static_cast<Q_UINT32>( 255 );
00204 
00205     // Layer visible?
00206     *m_stream << static_cast<Q_UINT32>( 8 );
00207     // Property size in bytes.
00208     *m_stream << static_cast<Q_UINT32>( 4 );
00209     // True.
00210     *m_stream << static_cast<Q_UINT32>( 1 );
00211 
00212     // Layer linked?
00213     *m_stream << static_cast<Q_UINT32>( 9 );
00214     // Property size in bytes.
00215     *m_stream << static_cast<Q_UINT32>( 4 );
00216     // False.
00217     *m_stream << static_cast<Q_UINT32>( 0 );
00218 
00219     // Preserve transparency?
00220     *m_stream << static_cast<Q_UINT32>( 10 );
00221     // Property size in bytes.
00222     *m_stream << static_cast<Q_UINT32>( 4 );
00223     // False.
00224     *m_stream << static_cast<Q_UINT32>( 0 );
00225 
00226     // Apply mask?
00227     *m_stream << static_cast<Q_UINT32>( 11 );
00228     // Property size in bytes.
00229     *m_stream << static_cast<Q_UINT32>( 4 );
00230     // False.
00231     *m_stream << static_cast<Q_UINT32>( 0 );
00232 
00233     // Edit mask?
00234     *m_stream << static_cast<Q_UINT32>( 12 );
00235     // Property size in bytes.
00236     *m_stream << static_cast<Q_UINT32>( 4 );
00237     // False.
00238     *m_stream << static_cast<Q_UINT32>( 0 );
00239 
00240     // Show mask?
00241     *m_stream << static_cast<Q_UINT32>( 13 );
00242     // Property size in bytes.
00243     *m_stream << static_cast<Q_UINT32>( 4 );
00244     // False.
00245     *m_stream << static_cast<Q_UINT32>( 0 );
00246 
00247     // Layer offsets.
00248     *m_stream << static_cast<Q_UINT32>( 15 );
00249     // Property size in bytes.
00250     *m_stream << static_cast<Q_UINT32>( 8 );
00251     // X-Offset.
00252     *m_stream << static_cast<Q_UINT32>( 0 );
00253     // Y-Offset.
00254     *m_stream << static_cast<Q_UINT32>( 0 );
00255 
00256     // Layer mode.
00257     *m_stream << static_cast<Q_UINT32>( 7 );
00258     // Property size in bytes.
00259     *m_stream << static_cast<Q_UINT32>( 4 );
00260     // Normal mode.
00261     *m_stream << static_cast<Q_UINT32>( 0 );
00262 
00263     // TODO: Tattoo.
00264     *m_stream << static_cast<Q_UINT32>( 20 );
00265     // Property size in bytes.
00266     *m_stream << static_cast<Q_UINT32>( 4 );
00267     // False.
00268     *m_stream << static_cast<Q_UINT32>( 0 );
00269 
00270     // Layer properties end.
00271     *m_stream << static_cast<Q_UINT32>( 0 );
00272     // Property size in bytes.
00273     *m_stream << static_cast<Q_UINT32>( 0 );
00274 
00275 
00276     // Offsets.
00277     QIODevice::Offset current = 0;
00278     QIODevice::Offset start = 0;
00279     QIODevice::Offset end = 0;
00280 
00281     // Save current offset.
00282     current = m_stream->device()->at();
00283 
00284     // Leave space for hierarchy offsets.
00285     m_stream->device()->at( current + 8 );
00286 
00287     // Save start offset.
00288     start = m_stream->device()->at();
00289 
00290 
00291     // Write hierarchy.
00292     writeHierarchy();
00293 
00294 
00295     // Save end offset.
00296     end = m_stream->device()->at();
00297 
00298     // Return to current offset.
00299     m_stream->device()->at( current );
00300 
00301     // Save hierarchy offset.
00302     *m_stream << start;
00303 
00304 
00305     // Append a zero offset to indicate end of layer mask offsets.
00306     *m_stream << static_cast<Q_UINT32>( 0 );
00307 }
00308 
00309 void
00310 XcfExport::writeHierarchy()
00311 {
00312     // Offsets.
00313     QIODevice::Offset current = 0;
00314     QIODevice::Offset start = 0;
00315     QIODevice::Offset end = 0;
00316 
00317     // Width (again?).
00318     *m_stream << m_width;
00319 
00320     // Height (again?).
00321     *m_stream << m_height;
00322 
00323     // Color depth.
00324     *m_stream << static_cast<Q_UINT32>( 3 );
00325 
00326 
00327     // Calculate level number.
00328     int levX = levels( m_width, m_tileWidth );
00329     int levY = levels( m_height, m_tileHeight );
00330     int levels = QMAX( levX, levY );
00331 
00332     int width = m_width;
00333     int height = m_height;
00334 
00335     // Save current offset.
00336     current = m_stream->device()->at();
00337 
00338     // Leave space for level offsets.
00339     m_stream->device()->at( current + ( levels + 1 ) * 4 );
00340 
00341     for( int i = 0; i < levels; ++i )
00342     {
00343         // Save start offset.
00344         start = m_stream->device()->at();
00345 
00346         if( i == 0 )
00347         {
00348             // Write level.
00349             writeLevel();
00350         }
00351         else
00352         {
00353             // Fake an empty level.
00354             width  /= 2;
00355             height /= 2;
00356 
00357             *m_stream << static_cast<Q_UINT32>( width );
00358             *m_stream << static_cast<Q_UINT32>( height );
00359             *m_stream << static_cast<Q_UINT32>( 0 );
00360         }
00361 
00362         // Save end offset.
00363         end = m_stream->device()->at();
00364 
00365         // Return to current offset.
00366         m_stream->device()->at( current );
00367 
00368         // Save level offset.
00369         *m_stream << start;
00370 
00371         // Increment offset.
00372         current = m_stream->device()->at();
00373 
00374         // Return to end offset.
00375         m_stream->device()->at( end );
00376     }
00377 
00378     // Return to current offset.
00379     m_stream->device()->at( current );
00380 
00381     // Append a zero offset to indicate end of level offsets.
00382     *m_stream << static_cast<Q_UINT32>( 0 );
00383 }
00384 
00385 void
00386 XcfExport::writeLevel()
00387 {
00388     // Offsets.
00389     QIODevice::Offset current = 0;
00390     QIODevice::Offset start = 0;
00391     QIODevice::Offset end = 0;
00392 
00393     *m_stream << static_cast<Q_UINT32>( m_width );
00394     *m_stream << static_cast<Q_UINT32>( m_height );
00395 
00396     int rows = ( m_height + m_tileHeight - 1 ) / m_tileHeight;
00397     int cols = ( m_width  + m_tileWidth  - 1 ) / m_tileWidth;
00398     int tiles = rows * cols;
00399 
00400     // Save current offset.
00401     current = m_stream->device()->at();
00402 
00403     // Leave space for tile offsets.
00404     m_stream->device()->at( current + ( tiles + 1 ) * 4 );
00405 
00406     for( int i = 0; i < tiles; ++i )
00407     {
00408         // Save start offset.
00409         start = m_stream->device()->at();
00410 
00411 
00412         // TODO: Save tile.
00413         *m_stream << static_cast<Q_UINT8>( 1 );
00414         *m_stream << static_cast<Q_UINT8>( 1 );
00415         *m_stream << static_cast<Q_UINT8>( 1 );
00416         *m_stream << static_cast<Q_UINT8>( 1 );
00417         *m_stream << static_cast<Q_UINT8>( 1 );
00418         *m_stream << static_cast<Q_UINT8>( 1 );
00419         *m_stream << static_cast<Q_UINT8>( 1 );
00420         *m_stream << static_cast<Q_UINT8>( 1 );
00421         *m_stream << static_cast<Q_UINT8>( 1 );
00422         *m_stream << static_cast<Q_UINT8>( 1 );
00423         *m_stream << static_cast<Q_UINT8>( 1 );
00424         *m_stream << static_cast<Q_UINT8>( 1 );
00425 
00426 
00427         // Save end offset.
00428         end = m_stream->device()->at();
00429 
00430         // Return to current offset.
00431         m_stream->device()->at( current );
00432 
00433         // Save tile offset.
00434         *m_stream << start;
00435 
00436         // Increment offset.
00437         current = m_stream->device()->at();
00438 
00439         // Return to end offset.
00440         m_stream->device()->at( end );
00441     }
00442 }
00443 
00444 int
00445 XcfExport::levels( int layerSize, int tileSize )
00446 {
00447     int l = 1;
00448 
00449     while( layerSize > tileSize )
00450     {
00451         layerSize /= 2;
00452         l += 1;
00453     }
00454 
00455     return l;
00456 }
00457 
00458 #include "xcfexport.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys