diff options
Diffstat (limited to 'filters/karbon/xcf/xcfexport.cpp')
-rw-r--r-- | filters/karbon/xcf/xcfexport.cpp | 458 |
1 files changed, 458 insertions, 0 deletions
diff --git a/filters/karbon/xcf/xcfexport.cpp b/filters/karbon/xcf/xcfexport.cpp new file mode 100644 index 000000000..215c4f018 --- /dev/null +++ b/filters/karbon/xcf/xcfexport.cpp @@ -0,0 +1,458 @@ +/* This file is part of the KDE project + Copyright (C) 2002, The Karbon Developers + + 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 <tqcstring.h> +#include <tqdatastream.h> +#include <tqdom.h> +#include <tqfile.h> +#include <tqstring.h> +#include <tqvaluelist.h> + +#include <kgenericfactory.h> +#include <KoFilter.h> +#include <KoFilterChain.h> +#include <KoStore.h> + +#include "vdocument.h" +#include "vlayer.h" +#include "xcfexport.h" + +#include <kdebug.h> + + +// Tile size constants. +const unsigned XcfExport::m_tileWidth = 64; +const unsigned XcfExport::m_tileHeight = 64; + + +typedef KGenericFactory<XcfExport, KoFilter> XcfExportFactory; +K_EXPORT_COMPONENT_FACTORY( libkarbonxcfexport, XcfExportFactory( "kofficefilters" ) ) + + +XcfExport::XcfExport( KoFilter*, const char*, const TQStringList& ) + : KoFilter() +{ + m_zoomX = 1.0; + m_zoomY = 1.0; +} + +KoFilter::ConversionStatus +XcfExport::convert( const TQCString& from, const TQCString& to ) +{ + if( to != "image/x-xcf-gimp" || from != "application/x-karbon" ) + { + return KoFilter::NotImplemented; + } + + + KoStoreDevice* storeIn = m_chain->storageFile( "root", KoStore::Read ); + + if( !storeIn ) + return KoFilter::StupidError; + + + TQFile fileOut( m_chain->outputFile() ); + + if( !fileOut.open( IO_WriteOnly ) ) + return KoFilter::StupidError; + + + TQDomDocument domIn; + domIn.setContent( storeIn ); + TQDomElement docNode = domIn.documentElement(); + + m_stream = new TQDataStream( &fileOut ); + + + // Load the document. + VDocument doc; + doc.load( docNode ); + + // Process the document. + doc.accept( *this ); + + + delete m_stream; + fileOut.close(); + + return KoFilter::OK; +} + +void +XcfExport::visitVDocument( VDocument& document ) +{ + // Offsets. + TQIODevice::Offset current = 0; + TQIODevice::Offset start = 0; + TQIODevice::Offset end = 0; + + // Save width and height for layer saving. + m_width = static_cast<unsigned>( document.width() * m_zoomX ); + m_height = static_cast<unsigned>( document.height() * m_zoomY ); + + + // Header tag (size 14 bytes). + m_stream->writeRawBytes( "gimp xcf file", 14 ); + + // Image width. + *m_stream << static_cast<TQ_UINT32>( m_width ); + + // Image height. + *m_stream << static_cast<TQ_UINT32>( m_height ); + + // Image type = RGB. + *m_stream << static_cast<TQ_UINT32>( 0 ); + + // Do not save any properties currently. + *m_stream + // "END". + << static_cast<TQ_UINT32>( 0 ) + // Property size in bytes. + << static_cast<TQ_UINT32>( 0 ); + + + // Save current offset. + current = m_stream->device()->at(); + + // Leave space for layer and channel offsets. + m_stream->device()->at( + // current position + (number layers + number channels + 2) * 4. + current + ( document.layers().count() + 3 + 2 ) * 4 ); + + + // Iterate over layers. + VLayerListIterator itr( document.layers() ); + + for( ; itr.current(); ++itr ) + { + // Save start offset. + start = m_stream->device()->at(); + + + // Write layer. + itr.current()->accept( *this ); + + + // Save end offset. + end = m_stream->device()->at(); + + // Return to current offset. + m_stream->device()->at( current ); + + // Save layer offset. + *m_stream << start; + + // Increment offset. + current = m_stream->device()->at(); + + // Return to end offset. + m_stream->device()->at( end ); + } + + + // Return to current offset. + m_stream->device()->at( current ); + + // Append a zero offset to indicate end of layer offsets. + *m_stream << static_cast<TQ_UINT32>( 0 ); + + + // Return to end offset. + m_stream->device()->at( end ); + + // Append a zero offset to indicate end of channel offsets. + *m_stream << static_cast<TQ_UINT32>( 0 ); +} + +void +XcfExport::visitVLayer( VLayer& layer ) +{ + // Layer width = image width. + *m_stream << static_cast<TQ_UINT32>( m_width ); + + // Layer height = image height. + *m_stream << static_cast<TQ_UINT32>( m_height ); + + // Layer type = RGBA. + *m_stream << static_cast<TQ_UINT32>( 1 ); + + // Layer name. + *m_stream << layer.name().latin1(); + + // Layer opacity. + *m_stream << static_cast<TQ_UINT32>( 6 ); + // Property size in bytes. + *m_stream << static_cast<TQ_UINT32>( 4 ); + // Fully opaque = 255. + *m_stream << static_cast<TQ_UINT32>( 255 ); + + // Layer visible? + *m_stream << static_cast<TQ_UINT32>( 8 ); + // Property size in bytes. + *m_stream << static_cast<TQ_UINT32>( 4 ); + // True. + *m_stream << static_cast<TQ_UINT32>( 1 ); + + // Layer linked? + *m_stream << static_cast<TQ_UINT32>( 9 ); + // Property size in bytes. + *m_stream << static_cast<TQ_UINT32>( 4 ); + // False. + *m_stream << static_cast<TQ_UINT32>( 0 ); + + // Preserve transparency? + *m_stream << static_cast<TQ_UINT32>( 10 ); + // Property size in bytes. + *m_stream << static_cast<TQ_UINT32>( 4 ); + // False. + *m_stream << static_cast<TQ_UINT32>( 0 ); + + // Apply mask? + *m_stream << static_cast<TQ_UINT32>( 11 ); + // Property size in bytes. + *m_stream << static_cast<TQ_UINT32>( 4 ); + // False. + *m_stream << static_cast<TQ_UINT32>( 0 ); + + // Edit mask? + *m_stream << static_cast<TQ_UINT32>( 12 ); + // Property size in bytes. + *m_stream << static_cast<TQ_UINT32>( 4 ); + // False. + *m_stream << static_cast<TQ_UINT32>( 0 ); + + // Show mask? + *m_stream << static_cast<TQ_UINT32>( 13 ); + // Property size in bytes. + *m_stream << static_cast<TQ_UINT32>( 4 ); + // False. + *m_stream << static_cast<TQ_UINT32>( 0 ); + + // Layer offsets. + *m_stream << static_cast<TQ_UINT32>( 15 ); + // Property size in bytes. + *m_stream << static_cast<TQ_UINT32>( 8 ); + // X-Offset. + *m_stream << static_cast<TQ_UINT32>( 0 ); + // Y-Offset. + *m_stream << static_cast<TQ_UINT32>( 0 ); + + // Layer mode. + *m_stream << static_cast<TQ_UINT32>( 7 ); + // Property size in bytes. + *m_stream << static_cast<TQ_UINT32>( 4 ); + // Normal mode. + *m_stream << static_cast<TQ_UINT32>( 0 ); + + // TODO: Tattoo. + *m_stream << static_cast<TQ_UINT32>( 20 ); + // Property size in bytes. + *m_stream << static_cast<TQ_UINT32>( 4 ); + // False. + *m_stream << static_cast<TQ_UINT32>( 0 ); + + // Layer properties end. + *m_stream << static_cast<TQ_UINT32>( 0 ); + // Property size in bytes. + *m_stream << static_cast<TQ_UINT32>( 0 ); + + + // Offsets. + TQIODevice::Offset current = 0; + TQIODevice::Offset start = 0; + TQIODevice::Offset end = 0; + + // Save current offset. + current = m_stream->device()->at(); + + // Leave space for hierarchy offsets. + m_stream->device()->at( current + 8 ); + + // Save start offset. + start = m_stream->device()->at(); + + + // Write hierarchy. + writeHierarchy(); + + + // Save end offset. + end = m_stream->device()->at(); + + // Return to current offset. + m_stream->device()->at( current ); + + // Save hierarchy offset. + *m_stream << start; + + + // Append a zero offset to indicate end of layer mask offsets. + *m_stream << static_cast<TQ_UINT32>( 0 ); +} + +void +XcfExport::writeHierarchy() +{ + // Offsets. + TQIODevice::Offset current = 0; + TQIODevice::Offset start = 0; + TQIODevice::Offset end = 0; + + // Width (again?). + *m_stream << m_width; + + // Height (again?). + *m_stream << m_height; + + // Color depth. + *m_stream << static_cast<TQ_UINT32>( 3 ); + + + // Calculate level number. + int levX = levels( m_width, m_tileWidth ); + int levY = levels( m_height, m_tileHeight ); + int levels = TQMAX( levX, levY ); + + int width = m_width; + int height = m_height; + + // Save current offset. + current = m_stream->device()->at(); + + // Leave space for level offsets. + m_stream->device()->at( current + ( levels + 1 ) * 4 ); + + for( int i = 0; i < levels; ++i ) + { + // Save start offset. + start = m_stream->device()->at(); + + if( i == 0 ) + { + // Write level. + writeLevel(); + } + else + { + // Fake an empty level. + width /= 2; + height /= 2; + + *m_stream << static_cast<TQ_UINT32>( width ); + *m_stream << static_cast<TQ_UINT32>( height ); + *m_stream << static_cast<TQ_UINT32>( 0 ); + } + + // Save end offset. + end = m_stream->device()->at(); + + // Return to current offset. + m_stream->device()->at( current ); + + // Save level offset. + *m_stream << start; + + // Increment offset. + current = m_stream->device()->at(); + + // Return to end offset. + m_stream->device()->at( end ); + } + + // Return to current offset. + m_stream->device()->at( current ); + + // Append a zero offset to indicate end of level offsets. + *m_stream << static_cast<TQ_UINT32>( 0 ); +} + +void +XcfExport::writeLevel() +{ + // Offsets. + TQIODevice::Offset current = 0; + TQIODevice::Offset start = 0; + TQIODevice::Offset end = 0; + + *m_stream << static_cast<TQ_UINT32>( m_width ); + *m_stream << static_cast<TQ_UINT32>( m_height ); + + int rows = ( m_height + m_tileHeight - 1 ) / m_tileHeight; + int cols = ( m_width + m_tileWidth - 1 ) / m_tileWidth; + int tiles = rows * cols; + + // Save current offset. + current = m_stream->device()->at(); + + // Leave space for tile offsets. + m_stream->device()->at( current + ( tiles + 1 ) * 4 ); + + for( int i = 0; i < tiles; ++i ) + { + // Save start offset. + start = m_stream->device()->at(); + + + // TODO: Save tile. + *m_stream << static_cast<TQ_UINT8>( 1 ); + *m_stream << static_cast<TQ_UINT8>( 1 ); + *m_stream << static_cast<TQ_UINT8>( 1 ); + *m_stream << static_cast<TQ_UINT8>( 1 ); + *m_stream << static_cast<TQ_UINT8>( 1 ); + *m_stream << static_cast<TQ_UINT8>( 1 ); + *m_stream << static_cast<TQ_UINT8>( 1 ); + *m_stream << static_cast<TQ_UINT8>( 1 ); + *m_stream << static_cast<TQ_UINT8>( 1 ); + *m_stream << static_cast<TQ_UINT8>( 1 ); + *m_stream << static_cast<TQ_UINT8>( 1 ); + *m_stream << static_cast<TQ_UINT8>( 1 ); + + + // Save end offset. + end = m_stream->device()->at(); + + // Return to current offset. + m_stream->device()->at( current ); + + // Save tile offset. + *m_stream << start; + + // Increment offset. + current = m_stream->device()->at(); + + // Return to end offset. + m_stream->device()->at( end ); + } +} + +int +XcfExport::levels( int layerSize, int tileSize ) +{ + int l = 1; + + while( layerSize > tileSize ) + { + layerSize /= 2; + l += 1; + } + + return l; +} + +#include "xcfexport.moc" |