1
/* This file is part of the KDE project
2
Copyright (C) 2002, The Karbon Developers
4
This library is free software; you can redistribute it and/or
5
modify it under the terms of the GNU Library General Public
6
License as published by the Free Software Foundation; either
7
version 2 of the License, or (at your option) any later version.
9
This library is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
Library General Public License for more details.
14
You should have received a copy of the GNU Library General Public License
15
along with this library; see the file COPYING.LIB. If not, write to
16
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17
Boston, MA 02111-1307, USA.
21
#include <qdatastream.h>
25
#include <qvaluelist.h>
27
#include <kgenericfactory.h>
29
#include <koFilterChain.h>
32
#include "vdocument.h"
34
#include "xcfexport.h"
39
// Tile size constants.
40
const unsigned XcfExport::m_tileWidth = 64;
41
const unsigned XcfExport::m_tileHeight = 64;
44
typedef KGenericFactory<XcfExport, KoFilter> XcfExportFactory;
45
K_EXPORT_COMPONENT_FACTORY( libkarbonxcfexport, XcfExportFactory( "karbonxcfexport" ) )
48
XcfExport::XcfExport( KoFilter*, const char*, const QStringList& )
55
KoFilter::ConversionStatus
56
XcfExport::convert( const QCString& from, const QCString& to )
58
if( to != "image/x-xcf-gimp" || from != "application/x-karbon" )
60
return KoFilter::NotImplemented;
64
KoStoreDevice* storeIn = m_chain->storageFile( "root", KoStore::Read );
67
return KoFilter::StupidError;
70
QFile fileOut( m_chain->outputFile() );
72
if( !fileOut.open( IO_WriteOnly ) )
73
return KoFilter::StupidError;
77
domIn.setContent( storeIn );
78
QDomElement docNode = domIn.documentElement();
80
m_stream = new QDataStream( &fileOut );
87
// Process the document.
98
XcfExport::visitVDocument( VDocument& document )
101
QIODevice::Offset current = 0;
102
QIODevice::Offset start = 0;
103
QIODevice::Offset end = 0;
105
// Save width and height for layer saving.
106
m_width = static_cast<unsigned>( document.width() * m_zoomX );
107
m_height = static_cast<unsigned>( document.height() * m_zoomY );
110
// Header tag (size 14 bytes).
111
m_stream->writeRawBytes( "gimp xcf file", 14 );
114
*m_stream << static_cast<Q_UINT32>( m_width );
117
*m_stream << static_cast<Q_UINT32>( m_height );
120
*m_stream << static_cast<Q_UINT32>( 0 );
122
// Do not save any properties currently.
125
<< static_cast<Q_UINT32>( 0 )
126
// Property size in bytes.
127
<< static_cast<Q_UINT32>( 0 );
130
// Save current offset.
131
current = m_stream->device()->at();
133
// Leave space for layer and channel offsets.
134
m_stream->device()->at(
135
// current position + (number layers + number channels + 2) * 4.
136
current + ( document.layers().count() + 3 + 2 ) * 4 );
139
// Iterate over layers.
140
VLayerListIterator itr( document.layers() );
142
for( ; itr.current(); ++itr )
144
// Save start offset.
145
start = m_stream->device()->at();
149
itr.current()->accept( *this );
153
end = m_stream->device()->at();
155
// Return to current offset.
156
m_stream->device()->at( current );
158
// Save layer offset.
162
current = m_stream->device()->at();
164
// Return to end offset.
165
m_stream->device()->at( end );
169
// Return to current offset.
170
m_stream->device()->at( current );
172
// Append a zero offset to indicate end of layer offsets.
173
*m_stream << static_cast<Q_UINT32>( 0 );
176
// Return to end offset.
177
m_stream->device()->at( end );
179
// Append a zero offset to indicate end of channel offsets.
180
*m_stream << static_cast<Q_UINT32>( 0 );
184
XcfExport::visitVLayer( VLayer& layer )
186
// Layer width = image width.
187
*m_stream << static_cast<Q_UINT32>( m_width );
189
// Layer height = image height.
190
*m_stream << static_cast<Q_UINT32>( m_height );
192
// Layer type = RGBA.
193
*m_stream << static_cast<Q_UINT32>( 1 );
196
*m_stream << layer.name().latin1();
199
*m_stream << static_cast<Q_UINT32>( 6 );
200
// Property size in bytes.
201
*m_stream << static_cast<Q_UINT32>( 4 );
202
// Fully opaque = 255.
203
*m_stream << static_cast<Q_UINT32>( 255 );
206
*m_stream << static_cast<Q_UINT32>( 8 );
207
// Property size in bytes.
208
*m_stream << static_cast<Q_UINT32>( 4 );
210
*m_stream << static_cast<Q_UINT32>( 1 );
213
*m_stream << static_cast<Q_UINT32>( 9 );
214
// Property size in bytes.
215
*m_stream << static_cast<Q_UINT32>( 4 );
217
*m_stream << static_cast<Q_UINT32>( 0 );
219
// Preserve transparency?
220
*m_stream << static_cast<Q_UINT32>( 10 );
221
// Property size in bytes.
222
*m_stream << static_cast<Q_UINT32>( 4 );
224
*m_stream << static_cast<Q_UINT32>( 0 );
227
*m_stream << static_cast<Q_UINT32>( 11 );
228
// Property size in bytes.
229
*m_stream << static_cast<Q_UINT32>( 4 );
231
*m_stream << static_cast<Q_UINT32>( 0 );
234
*m_stream << static_cast<Q_UINT32>( 12 );
235
// Property size in bytes.
236
*m_stream << static_cast<Q_UINT32>( 4 );
238
*m_stream << static_cast<Q_UINT32>( 0 );
241
*m_stream << static_cast<Q_UINT32>( 13 );
242
// Property size in bytes.
243
*m_stream << static_cast<Q_UINT32>( 4 );
245
*m_stream << static_cast<Q_UINT32>( 0 );
248
*m_stream << static_cast<Q_UINT32>( 15 );
249
// Property size in bytes.
250
*m_stream << static_cast<Q_UINT32>( 8 );
252
*m_stream << static_cast<Q_UINT32>( 0 );
254
*m_stream << static_cast<Q_UINT32>( 0 );
257
*m_stream << static_cast<Q_UINT32>( 7 );
258
// Property size in bytes.
259
*m_stream << static_cast<Q_UINT32>( 4 );
261
*m_stream << static_cast<Q_UINT32>( 0 );
264
*m_stream << static_cast<Q_UINT32>( 20 );
265
// Property size in bytes.
266
*m_stream << static_cast<Q_UINT32>( 4 );
268
*m_stream << static_cast<Q_UINT32>( 0 );
270
// Layer properties end.
271
*m_stream << static_cast<Q_UINT32>( 0 );
272
// Property size in bytes.
273
*m_stream << static_cast<Q_UINT32>( 0 );
277
QIODevice::Offset current = 0;
278
QIODevice::Offset start = 0;
279
QIODevice::Offset end = 0;
281
// Save current offset.
282
current = m_stream->device()->at();
284
// Leave space for hierarchy offsets.
285
m_stream->device()->at( current + 8 );
287
// Save start offset.
288
start = m_stream->device()->at();
296
end = m_stream->device()->at();
298
// Return to current offset.
299
m_stream->device()->at( current );
301
// Save hierarchy offset.
305
// Append a zero offset to indicate end of layer mask offsets.
306
*m_stream << static_cast<Q_UINT32>( 0 );
310
XcfExport::writeHierarchy()
313
QIODevice::Offset current = 0;
314
QIODevice::Offset start = 0;
315
QIODevice::Offset end = 0;
318
*m_stream << m_width;
321
*m_stream << m_height;
324
*m_stream << static_cast<Q_UINT32>( 3 );
327
// Calculate level number.
328
int levX = levels( m_width, m_tileWidth );
329
int levY = levels( m_height, m_tileHeight );
330
int levels = QMAX( levX, levY );
333
int height = m_height;
335
// Save current offset.
336
current = m_stream->device()->at();
338
// Leave space for level offsets.
339
m_stream->device()->at( current + ( levels + 1 ) * 4 );
341
for( int i = 0; i < levels; ++i )
343
// Save start offset.
344
start = m_stream->device()->at();
353
// Fake an empty level.
357
*m_stream << static_cast<Q_UINT32>( width );
358
*m_stream << static_cast<Q_UINT32>( height );
359
*m_stream << static_cast<Q_UINT32>( 0 );
363
end = m_stream->device()->at();
365
// Return to current offset.
366
m_stream->device()->at( current );
368
// Save level offset.
372
current = m_stream->device()->at();
374
// Return to end offset.
375
m_stream->device()->at( end );
378
// Return to current offset.
379
m_stream->device()->at( current );
381
// Append a zero offset to indicate end of level offsets.
382
*m_stream << static_cast<Q_UINT32>( 0 );
386
XcfExport::writeLevel()
389
QIODevice::Offset current = 0;
390
QIODevice::Offset start = 0;
391
QIODevice::Offset end = 0;
393
*m_stream << static_cast<Q_UINT32>( m_width );
394
*m_stream << static_cast<Q_UINT32>( m_height );
396
int rows = ( m_height + m_tileHeight - 1 ) / m_tileHeight;
397
int cols = ( m_width + m_tileWidth - 1 ) / m_tileWidth;
398
int tiles = rows * cols;
400
// Save current offset.
401
current = m_stream->device()->at();
403
// Leave space for tile offsets.
404
m_stream->device()->at( current + ( tiles + 1 ) * 4 );
406
for( int i = 0; i < tiles; ++i )
408
// Save start offset.
409
start = m_stream->device()->at();
413
*m_stream << static_cast<Q_UINT8>( 1 );
414
*m_stream << static_cast<Q_UINT8>( 1 );
415
*m_stream << static_cast<Q_UINT8>( 1 );
416
*m_stream << static_cast<Q_UINT8>( 1 );
417
*m_stream << static_cast<Q_UINT8>( 1 );
418
*m_stream << static_cast<Q_UINT8>( 1 );
419
*m_stream << static_cast<Q_UINT8>( 1 );
420
*m_stream << static_cast<Q_UINT8>( 1 );
421
*m_stream << static_cast<Q_UINT8>( 1 );
422
*m_stream << static_cast<Q_UINT8>( 1 );
423
*m_stream << static_cast<Q_UINT8>( 1 );
424
*m_stream << static_cast<Q_UINT8>( 1 );
428
end = m_stream->device()->at();
430
// Return to current offset.
431
m_stream->device()->at( current );
437
current = m_stream->device()->at();
439
// Return to end offset.
440
m_stream->device()->at( end );
445
XcfExport::levels( int layerSize, int tileSize )
449
while( layerSize > tileSize )
458
#include "xcfexport.moc"