~ubuntu-branches/ubuntu/breezy/koffice/breezy

« back to all changes in this revision

Viewing changes to filters/karbon/xcf/xcfexport.cc

  • Committer: Bazaar Package Importer
  • Author(s): Ben Burton
  • Date: 2004-05-09 11:33:00 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040509113300-vfrdadqsvjfuhn3b
Tags: 1:1.3.1-1
* New upstream bugfix release.
* Built against newer imagemagick (closes: #246623).
* Made koffice-libs/kformula recommend/depend on latex-xft-fonts, which
  provides mathematical fonts that the formula editor can use.  Also
  patched the kformula part to make these fonts the default.
* Changed kword menu hint from "WordProcessors" to "Word processors"
  (closes: #246209).
* Spellchecker configuration is now fixed (closes: #221256, #227568).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file is part of the KDE project
 
2
   Copyright (C) 2002, The Karbon Developers
 
3
 
 
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.
 
8
 
 
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.
 
13
 
 
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.
 
18
*/
 
19
 
 
20
#include <qcstring.h>
 
21
#include <qdatastream.h>
 
22
#include <qdom.h>
 
23
#include <qfile.h>
 
24
#include <qstring.h>
 
25
#include <qvaluelist.h>
 
26
 
 
27
#include <kgenericfactory.h>
 
28
#include <koFilter.h>
 
29
#include <koFilterChain.h>
 
30
#include <koStore.h>
 
31
 
 
32
#include "vdocument.h"
 
33
#include "vlayer.h"
 
34
#include "xcfexport.h"
 
35
 
 
36
#include <kdebug.h>
 
37
 
 
38
 
 
39
// Tile size constants.
 
40
const unsigned XcfExport::m_tileWidth  = 64;
 
41
const unsigned XcfExport::m_tileHeight = 64;
 
42
 
 
43
 
 
44
typedef KGenericFactory<XcfExport, KoFilter> XcfExportFactory;
 
45
K_EXPORT_COMPONENT_FACTORY( libkarbonxcfexport, XcfExportFactory( "karbonxcfexport" ) )
 
46
 
 
47
 
 
48
XcfExport::XcfExport( KoFilter*, const char*, const QStringList& )
 
49
        : KoFilter()
 
50
{
 
51
        m_zoomX = 1.0;
 
52
        m_zoomY = 1.0;
 
53
}
 
54
 
 
55
KoFilter::ConversionStatus
 
56
XcfExport::convert( const QCString& from, const QCString& to )
 
57
{
 
58
        if( to != "image/x-xcf-gimp" || from != "application/x-karbon" )
 
59
        {
 
60
                return KoFilter::NotImplemented;
 
61
        }
 
62
 
 
63
 
 
64
        KoStoreDevice* storeIn = m_chain->storageFile( "root", KoStore::Read );
 
65
 
 
66
        if( !storeIn )
 
67
                return KoFilter::StupidError;
 
68
 
 
69
 
 
70
        QFile fileOut( m_chain->outputFile() );
 
71
 
 
72
        if( !fileOut.open( IO_WriteOnly ) )
 
73
                return KoFilter::StupidError;
 
74
 
 
75
 
 
76
        QDomDocument domIn;
 
77
        domIn.setContent( storeIn );
 
78
        QDomElement docNode = domIn.documentElement();
 
79
 
 
80
        m_stream = new QDataStream( &fileOut );
 
81
 
 
82
 
 
83
        // Load the document.
 
84
        VDocument doc;
 
85
        doc.load( docNode );
 
86
 
 
87
        // Process the document.
 
88
        doc.accept( *this );
 
89
 
 
90
 
 
91
        delete m_stream;
 
92
        fileOut.close();
 
93
 
 
94
        return KoFilter::OK;
 
95
}
 
96
 
 
97
void
 
98
XcfExport::visitVDocument( VDocument& document )
 
99
{
 
100
        // Offsets.
 
101
        QIODevice::Offset current = 0;
 
102
        QIODevice::Offset start = 0;
 
103
        QIODevice::Offset end = 0;
 
104
 
 
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 );
 
108
 
 
109
 
 
110
        // Header tag (size 14 bytes).
 
111
        m_stream->writeRawBytes( "gimp xcf file", 14 );
 
112
 
 
113
        // Image width.
 
114
        *m_stream << static_cast<Q_UINT32>( m_width );
 
115
 
 
116
        // Image height.
 
117
        *m_stream << static_cast<Q_UINT32>( m_height );
 
118
 
 
119
        // Image type = RGB.
 
120
        *m_stream << static_cast<Q_UINT32>( 0 );
 
121
 
 
122
        // Do not save any properties currently.
 
123
        *m_stream
 
124
                // "END".
 
125
                << static_cast<Q_UINT32>( 0 )
 
126
                // Property size in bytes.
 
127
                << static_cast<Q_UINT32>( 0 );
 
128
 
 
129
 
 
130
        // Save current offset.
 
131
        current = m_stream->device()->at();
 
132
 
 
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 );
 
137
 
 
138
 
 
139
        // Iterate over layers.
 
140
        VLayerListIterator itr( document.layers() );
 
141
 
 
142
        for( ; itr.current(); ++itr )
 
143
        {
 
144
                // Save start offset.
 
145
                start = m_stream->device()->at();
 
146
 
 
147
 
 
148
                // Write layer.
 
149
                itr.current()->accept( *this );
 
150
 
 
151
 
 
152
                // Save end offset.
 
153
                end = m_stream->device()->at();
 
154
 
 
155
                // Return to current offset.
 
156
                m_stream->device()->at( current );
 
157
 
 
158
                // Save layer offset.
 
159
                *m_stream << start;
 
160
 
 
161
                // Increment offset.
 
162
                current = m_stream->device()->at();
 
163
 
 
164
                // Return to end offset.
 
165
                m_stream->device()->at( end );
 
166
        }
 
167
 
 
168
 
 
169
        // Return to current offset.
 
170
        m_stream->device()->at( current );
 
171
 
 
172
        // Append a zero offset to indicate end of layer offsets.
 
173
        *m_stream << static_cast<Q_UINT32>( 0 );
 
174
 
 
175
 
 
176
        // Return to end offset.
 
177
        m_stream->device()->at( end );
 
178
 
 
179
        // Append a zero offset to indicate end of channel offsets.
 
180
        *m_stream << static_cast<Q_UINT32>( 0 );
 
181
}
 
182
 
 
183
void
 
184
XcfExport::visitVLayer( VLayer& layer )
 
185
{
 
186
        // Layer width = image width.
 
187
        *m_stream << static_cast<Q_UINT32>( m_width );
 
188
 
 
189
        // Layer height = image height.
 
190
        *m_stream << static_cast<Q_UINT32>( m_height );
 
191
 
 
192
        // Layer type = RGBA.
 
193
        *m_stream << static_cast<Q_UINT32>( 1 );
 
194
 
 
195
        // Layer name.
 
196
        *m_stream << layer.name().latin1();
 
197
        
 
198
        // Layer opacity.
 
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 );
 
204
 
 
205
        // Layer visible?
 
206
        *m_stream << static_cast<Q_UINT32>( 8 );
 
207
        // Property size in bytes.
 
208
        *m_stream << static_cast<Q_UINT32>( 4 );
 
209
        // True.
 
210
        *m_stream << static_cast<Q_UINT32>( 1 );
 
211
 
 
212
        // Layer linked?
 
213
        *m_stream << static_cast<Q_UINT32>( 9 );
 
214
        // Property size in bytes.
 
215
        *m_stream << static_cast<Q_UINT32>( 4 );
 
216
        // False.
 
217
        *m_stream << static_cast<Q_UINT32>( 0 );
 
218
 
 
219
        // Preserve transparency?
 
220
        *m_stream << static_cast<Q_UINT32>( 10 );
 
221
        // Property size in bytes.
 
222
        *m_stream << static_cast<Q_UINT32>( 4 );
 
223
        // False.
 
224
        *m_stream << static_cast<Q_UINT32>( 0 );
 
225
 
 
226
        // Apply mask?
 
227
        *m_stream << static_cast<Q_UINT32>( 11 );
 
228
        // Property size in bytes.
 
229
        *m_stream << static_cast<Q_UINT32>( 4 );
 
230
        // False.
 
231
        *m_stream << static_cast<Q_UINT32>( 0 );
 
232
 
 
233
        // Edit mask?
 
234
        *m_stream << static_cast<Q_UINT32>( 12 );
 
235
        // Property size in bytes.
 
236
        *m_stream << static_cast<Q_UINT32>( 4 );
 
237
        // False.
 
238
        *m_stream << static_cast<Q_UINT32>( 0 );
 
239
 
 
240
        // Show mask?
 
241
        *m_stream << static_cast<Q_UINT32>( 13 );
 
242
        // Property size in bytes.
 
243
        *m_stream << static_cast<Q_UINT32>( 4 );
 
244
        // False.
 
245
        *m_stream << static_cast<Q_UINT32>( 0 );
 
246
 
 
247
        // Layer offsets.
 
248
        *m_stream << static_cast<Q_UINT32>( 15 );
 
249
        // Property size in bytes.
 
250
        *m_stream << static_cast<Q_UINT32>( 8 );
 
251
        // X-Offset.
 
252
        *m_stream << static_cast<Q_UINT32>( 0 );
 
253
        // Y-Offset.
 
254
        *m_stream << static_cast<Q_UINT32>( 0 );
 
255
 
 
256
        // Layer mode.
 
257
        *m_stream << static_cast<Q_UINT32>( 7 );
 
258
        // Property size in bytes.
 
259
        *m_stream << static_cast<Q_UINT32>( 4 );
 
260
        // Normal mode.
 
261
        *m_stream << static_cast<Q_UINT32>( 0 );
 
262
 
 
263
        // TODO: Tattoo.
 
264
        *m_stream << static_cast<Q_UINT32>( 20 );
 
265
        // Property size in bytes.
 
266
        *m_stream << static_cast<Q_UINT32>( 4 );
 
267
        // False.
 
268
        *m_stream << static_cast<Q_UINT32>( 0 );
 
269
 
 
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 );
 
274
 
 
275
 
 
276
        // Offsets.
 
277
        QIODevice::Offset current = 0;
 
278
        QIODevice::Offset start = 0;
 
279
        QIODevice::Offset end = 0;
 
280
 
 
281
        // Save current offset.
 
282
        current = m_stream->device()->at();
 
283
 
 
284
        // Leave space for hierarchy offsets.
 
285
        m_stream->device()->at( current + 8 );
 
286
 
 
287
        // Save start offset.
 
288
        start = m_stream->device()->at();
 
289
 
 
290
 
 
291
        // Write hierarchy.
 
292
        writeHierarchy();
 
293
 
 
294
 
 
295
        // Save end offset.
 
296
        end = m_stream->device()->at();
 
297
 
 
298
        // Return to current offset.
 
299
        m_stream->device()->at( current );
 
300
 
 
301
        // Save hierarchy offset.
 
302
        *m_stream << start;
 
303
 
 
304
 
 
305
        // Append a zero offset to indicate end of layer mask offsets.
 
306
        *m_stream << static_cast<Q_UINT32>( 0 );
 
307
}
 
308
 
 
309
void
 
310
XcfExport::writeHierarchy()
 
311
{
 
312
        // Offsets.
 
313
        QIODevice::Offset current = 0;
 
314
        QIODevice::Offset start = 0;
 
315
        QIODevice::Offset end = 0;
 
316
 
 
317
        // Width (again?).
 
318
        *m_stream << m_width;
 
319
 
 
320
        // Height (again?).
 
321
        *m_stream << m_height;
 
322
 
 
323
        // Color depth.
 
324
        *m_stream << static_cast<Q_UINT32>( 3 );
 
325
 
 
326
        
 
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 );
 
331
 
 
332
        int width = m_width;
 
333
        int height = m_height;
 
334
 
 
335
        // Save current offset.
 
336
        current = m_stream->device()->at();
 
337
 
 
338
        // Leave space for level offsets.
 
339
        m_stream->device()->at( current + ( levels + 1 ) * 4 );
 
340
 
 
341
        for( int i = 0; i < levels; ++i ) 
 
342
        {
 
343
                // Save start offset.
 
344
                start = m_stream->device()->at();
 
345
 
 
346
                if( i == 0 ) 
 
347
                {
 
348
                        // Write level.
 
349
                        writeLevel();
 
350
                } 
 
351
                else 
 
352
                {
 
353
                        // Fake an empty level.
 
354
                        width  /= 2;
 
355
                        height /= 2;
 
356
 
 
357
                        *m_stream << static_cast<Q_UINT32>( width );
 
358
                        *m_stream << static_cast<Q_UINT32>( height );
 
359
                        *m_stream << static_cast<Q_UINT32>( 0 );
 
360
                }
 
361
 
 
362
                // Save end offset.
 
363
                end = m_stream->device()->at();
 
364
 
 
365
                // Return to current offset.
 
366
                m_stream->device()->at( current );
 
367
 
 
368
                // Save level offset.
 
369
                *m_stream << start;
 
370
 
 
371
                // Increment offset.
 
372
                current = m_stream->device()->at();
 
373
 
 
374
                // Return to end offset.
 
375
                m_stream->device()->at( end );
 
376
        }
 
377
 
 
378
        // Return to current offset.
 
379
        m_stream->device()->at( current );
 
380
 
 
381
        // Append a zero offset to indicate end of level offsets.
 
382
        *m_stream << static_cast<Q_UINT32>( 0 );
 
383
}
 
384
 
 
385
void
 
386
XcfExport::writeLevel()
 
387
{
 
388
        // Offsets.
 
389
        QIODevice::Offset current = 0;
 
390
        QIODevice::Offset start = 0;
 
391
        QIODevice::Offset end = 0;
 
392
 
 
393
        *m_stream << static_cast<Q_UINT32>( m_width );
 
394
        *m_stream << static_cast<Q_UINT32>( m_height );
 
395
 
 
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;        
 
399
 
 
400
        // Save current offset.
 
401
        current = m_stream->device()->at();
 
402
 
 
403
        // Leave space for tile offsets.
 
404
        m_stream->device()->at( current + ( tiles + 1 ) * 4 );
 
405
 
 
406
        for( int i = 0; i < tiles; ++i )
 
407
        {
 
408
                // Save start offset.
 
409
                start = m_stream->device()->at();
 
410
 
 
411
 
 
412
                // TODO: Save tile.
 
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 );
 
425
 
 
426
 
 
427
                // Save end offset.
 
428
                end = m_stream->device()->at();
 
429
 
 
430
                // Return to current offset.
 
431
                m_stream->device()->at( current );
 
432
 
 
433
                // Save tile offset.
 
434
                *m_stream << start;
 
435
 
 
436
                // Increment offset.
 
437
                current = m_stream->device()->at();
 
438
 
 
439
                // Return to end offset.
 
440
                m_stream->device()->at( end );
 
441
        }
 
442
}
 
443
 
 
444
int
 
445
XcfExport::levels( int layerSize, int tileSize )
 
446
{
 
447
        int l = 1;
 
448
 
 
449
        while( layerSize > tileSize )
 
450
        {
 
451
                layerSize /= 2;
 
452
                l += 1;
 
453
        }
 
454
 
 
455
        return l;
 
456
}
 
457
 
 
458
#include "xcfexport.moc"