~ubuntu-branches/ubuntu/precise/koffice/precise

« back to all changes in this revision

Viewing changes to plugins/vectorshape/libemf/EmfRecords.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2010-09-21 15:36:35 UTC
  • mfrom: (1.4.1 upstream) (60.2.11 maverick)
  • Revision ID: james.westby@ubuntu.com-20100921153635-6tejqkiro2u21ydi
Tags: 1:2.2.2-0ubuntu3
Add kubuntu_03_fix-crash-on-closing-sqlite-connection-2.2.2.diff and
kubuntu_04_support-large-memo-values-for-msaccess-2.2.2.diff as
recommended by upstream http://kexi-
project.org/wiki/wikiview/index.php@Kexi2.2_Patches.html#sqlite_stab
ility

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright 2008 Brad Hards <bradh@frogmouth.net>
 
3
  Copyright 2009 Inge Wallin <inge@lysator.liu.se>
 
4
 
 
5
  This library is free software; you can redistribute it and/or
 
6
  modify it under the terms of the GNU Lesser General Public
 
7
  License as published by the Free Software Foundation; either 
 
8
  version 2.1 of the License, or (at your option) any later version.
 
9
  
 
10
  This library is distributed in the hope that it will be useful,
 
11
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
  Lesser General Public License for more details.
 
14
 
 
15
  You should have received a copy of the GNU Lesser General Public 
 
16
  License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 
17
*/
 
18
 
 
19
#include "EmfEnums.h"
 
20
#include "EmfRecords.h"
 
21
 
 
22
#include <KDebug>
 
23
 
 
24
namespace Libemf
 
25
{
 
26
 
 
27
/*****************************************************************************/
 
28
 
 
29
BitmapInfoHeader::BitmapInfoHeader( QDataStream &stream )
 
30
{
 
31
    stream >> m_headerSize;
 
32
    stream >> m_width;
 
33
    //kDebug(31000) << "Width:" << m_width;
 
34
    stream >> m_height;
 
35
    //kDebug(31000) << "Height:" << m_height;
 
36
    stream >> m_planes;
 
37
    // kDebug(33100) << "planes:" << m_planes;
 
38
    stream >> m_bitCount;
 
39
    // kDebug(33100) << "BitCount:" << m_bitCount;
 
40
    stream >> m_compression;
 
41
    //kDebug(31000) << "Compression:" << m_compression;
 
42
    stream >> m_imageSize;
 
43
    // kDebug(33100) << "ImageSize:" << m_imageSize;
 
44
    stream >> m_xPelsPerMeter;
 
45
    stream >> m_yPelsPerMeter;
 
46
    stream >> m_colorUsed;
 
47
    stream >> m_colorImportant;
 
48
}
 
49
 
 
50
BitmapInfoHeader::~BitmapInfoHeader()
 
51
{
 
52
}
 
53
 
 
54
 
 
55
/*****************************************************************************/
 
56
BitBltRecord::BitBltRecord( QDataStream &stream )
 
57
{
 
58
#if 0
 
59
    qint32 x, y, width, height;
 
60
    stream >> x >> y >> width >> height;
 
61
    kDebug(31000) << "Bounds" << x << y << width << height;
 
62
    m_Bounds = QRect( QPoint(x, y), QSize(width, height));
 
63
#else
 
64
    stream >> m_Bounds;
 
65
#endif
 
66
    stream >> m_xDest;
 
67
    stream >> m_yDest;
 
68
    stream >> m_cxDest;
 
69
    stream >> m_cyDest;
 
70
    //kDebug(31000) << "Destination" << m_xDest << m_yDest << m_cxDest << m_cyDest;
 
71
 
 
72
    stream >> m_BitBltRasterOperation;
 
73
    //kDebug(31000) << "bitblt raster operation:" << m_BitBltRasterOperation;
 
74
    stream >> m_xSrc;
 
75
    stream >> m_ySrc;
 
76
    //kDebug(31000) << "Sourcd" << m_xSrc << m_ySrc;
 
77
 
 
78
    float M11, M12, M21, M22, Dx, Dy;
 
79
    stream >> M11;
 
80
    stream >> M12;
 
81
    stream >> M21;
 
82
    stream >> M22;
 
83
    stream >> Dx;
 
84
    stream >> Dy;
 
85
    m_XFormSrc = QMatrix( M11, M12, M21, M22, Dx, Dy );
 
86
    //kDebug(31000) << m_XFormSrc;
 
87
 
 
88
    stream >> m_red >> m_green >> m_blue >> m_reserved;
 
89
    stream >> m_UsageSrc;
 
90
    stream >> m_offBmiSrc;
 
91
    stream >> m_cbBmiSrc;
 
92
    stream >> m_offBitsSrc;
 
93
    stream >> m_cbBitsSrc;
 
94
    if ( ( m_cbBmiSrc == 0 ) && ( m_cbBmiSrc == 0 ) ) {
 
95
        return;
 
96
    }
 
97
    if ( m_cbBmiSrc == 40 ) {
 
98
        m_BmiSrc = new BitmapInfoHeader( stream );
 
99
    } else {
 
100
        //kDebug(31000) << "m_cbBmiSrc:" << m_cbBmiSrc;
 
101
        Q_ASSERT( 0 );
 
102
    }
 
103
 
 
104
    m_imageData.resize( m_cbBitsSrc );
 
105
    stream.readRawData( m_imageData.data(), m_cbBitsSrc );
 
106
}
 
107
 
 
108
BitBltRecord::~BitBltRecord()
 
109
{
 
110
}
 
111
 
 
112
bool BitBltRecord::hasImage() const
 
113
{
 
114
    return ( ( m_cbBmiSrc != 0 ) && ( m_cbBmiSrc != 0 ) );
 
115
}
 
116
 
 
117
QImage* BitBltRecord::image() 
 
118
{
 
119
 
 
120
    if ( ! hasImage() ) {
 
121
        return 0;
 
122
    }
 
123
 
 
124
    if ( m_image != 0 ) {
 
125
        return m_image;
 
126
    }
 
127
 
 
128
    QImage::Format format = QImage::Format_Invalid;
 
129
    if ( m_BmiSrc->bitCount() == BI_BITCOUNT_4 ) {
 
130
        if ( m_BmiSrc->compression() == 0x00 ) {
 
131
            format = QImage::Format_RGB555;
 
132
        } else {
 
133
            kDebug(33100) << "Unexpected compression format for BI_BITCOUNT_4:"
 
134
                     << m_BmiSrc->compression();
 
135
            Q_ASSERT( 0 );
 
136
        }
 
137
    } else if ( m_BmiSrc->bitCount() == BI_BITCOUNT_5 ) {
 
138
        format = QImage::Format_RGB888;
 
139
    } else {
 
140
        kDebug(33100) << "Unexpected format:" << m_BmiSrc->bitCount();
 
141
        Q_ASSERT( 0 );
 
142
    }
 
143
    m_image = new QImage( (const uchar*)m_imageData.constData(),
 
144
                          m_BmiSrc->width(), m_BmiSrc->height(), format );
 
145
 
 
146
    return m_image;
 
147
}
 
148
 
 
149
/*****************************************************************************/
 
150
StretchDiBitsRecord::StretchDiBitsRecord( QDataStream &stream )
 
151
    : m_BmiSrc(0)
 
152
    , m_image(0)
 
153
{
 
154
    stream >> m_Bounds;
 
155
    stream >> m_xDest;
 
156
    stream >> m_yDest;
 
157
    stream >> m_xSrc;
 
158
    stream >> m_ySrc;
 
159
    stream >> m_cxSrc;
 
160
    stream >> m_cySrc;
 
161
    stream >> m_offBmiSrc;
 
162
    stream >> m_cbBmiSrc;
 
163
    stream >> m_offBitsSrc;
 
164
    stream >> m_cbBitsSrc;
 
165
    stream >> m_UsageSrc;
 
166
    stream >> m_BitBltRasterOperation;
 
167
    stream >> m_cxDest;
 
168
    stream >> m_cyDest;
 
169
 
 
170
#if 0
 
171
    kDebug(31000) << "m_cbBmiSrc =" << m_cbBmiSrc;
 
172
    kDebug(31000) << "m_offBmiSrc =" << m_offBmiSrc;
 
173
    kDebug(31000) << "m_cbBitsSrc  =" << m_cbBitsSrc;
 
174
    kDebug(31000) << "m_offBitsSrc =" << m_offBitsSrc;
 
175
    //kDebug(31000) << "m_BitBltRasterOperation =" << hex << m_BitBltRasterOperation << dec;
 
176
#endif
 
177
 
 
178
    // Read away those bytes that preceed the header.  These are undefined
 
179
    // according to the spec.  80 is the size of the record above.
 
180
    qint32 dummy;
 
181
    int    padding = 0;
 
182
    while (m_offBmiSrc - padding > 80) {
 
183
        stream >> dummy;
 
184
        padding += 4;
 
185
    }
 
186
    m_BmiSrc = new BitmapInfoHeader( stream );
 
187
 
 
188
    // 40 is the size of the header record.
 
189
    while (m_offBitsSrc - padding > 80 + 40) {
 
190
        stream >> dummy;
 
191
        padding += 4;
 
192
    }
 
193
    m_imageData.resize( m_cbBitsSrc );
 
194
    stream.readRawData( m_imageData.data(), m_cbBitsSrc );
 
195
}
 
196
 
 
197
StretchDiBitsRecord::~StretchDiBitsRecord()
 
198
{
 
199
    delete m_image;
 
200
    // delete m_BmiSrc;
 
201
}
 
202
 
 
203
QRect StretchDiBitsRecord::bounds() const
 
204
{
 
205
    return m_Bounds;
 
206
}
 
207
 
 
208
QImage* StretchDiBitsRecord::image() 
 
209
{
 
210
    if ( m_image != 0 ) {
 
211
        return m_image;
 
212
    }
 
213
 
 
214
    QImage::Format format = QImage::Format_Invalid;
 
215
    if (m_BmiSrc->bitCount() == BI_BITCOUNT_1) {
 
216
        format = QImage::Format_Mono;
 
217
    } else if ( m_BmiSrc->bitCount() == BI_BITCOUNT_4 ) {
 
218
        if ( m_BmiSrc->compression() == BI_RGB ) {
 
219
            format = QImage::Format_RGB555;
 
220
        } else {
 
221
            kDebug(33100) << "Unexpected compression format for BI_BITCOUNT_4:"
 
222
                          << m_BmiSrc->compression();
 
223
            Q_ASSERT( 0 );
 
224
        }
 
225
    } else if ( m_BmiSrc->bitCount() == BI_BITCOUNT_5 ) {
 
226
        format = QImage::Format_RGB888;
 
227
    } else {
 
228
        kDebug(31000) << "Unexpected format:" << m_BmiSrc->bitCount();
 
229
        //Q_ASSERT(0);
 
230
    }
 
231
 
 
232
    // According to MS-WMF 2.2.2.3, the sign of the height decides if
 
233
    // this is a compressed bitmap or not.
 
234
    if (m_BmiSrc->height() > 0) {
 
235
        // This bitmap is a top-down bitmap without compression.
 
236
        m_image = new QImage( (const uchar*)m_imageData.constData(),
 
237
                              m_BmiSrc->width(), m_BmiSrc->height(), format );
 
238
        // we have to mirror this bitmap in the X axis.
 
239
        *m_image = m_image->mirrored(false, true);
 
240
    } else {
 
241
        // This bitmap is a bottom-up bitmap which uses compression.
 
242
        switch (m_BmiSrc->compression()) {
 
243
        case BI_RGB:
 
244
            m_image = new QImage( (const uchar*)m_imageData.constData(),
 
245
                                  m_BmiSrc->width(), -m_BmiSrc->height(), format );
 
246
            break;
 
247
 
 
248
        // These compressions are not yet supported, so return an empty image.
 
249
        case BI_RLE8:
 
250
        case BI_RLE4:
 
251
        case BI_BITFIELDS:
 
252
        case BI_JPEG:
 
253
        case BI_PNG:
 
254
        case BI_CMYK:
 
255
        case BI_CMYKRLE8:
 
256
        case BI_CMYKRLE4:
 
257
        default:
 
258
            m_image = new QImage(m_BmiSrc->width(), m_BmiSrc->height(), format);
 
259
            break;
 
260
        }
 
261
    }
 
262
 
 
263
    return m_image;
 
264
}
 
265
 
 
266
/*****************************************************************************/
 
267
ExtCreateFontIndirectWRecord::ExtCreateFontIndirectWRecord( QDataStream &stream, quint32 size )
 
268
{
 
269
    stream >> m_ihFonts;
 
270
    size -= 12;
 
271
 
 
272
    // TODO: Check size, we might need to do a LogFontExDv parse
 
273
    stream >> m_height;
 
274
    stream >> m_width;
 
275
    size -= 8;
 
276
 
 
277
    stream >> m_escapement;
 
278
    size -= 4;
 
279
 
 
280
    stream >> m_orientation;
 
281
    size -= 4;
 
282
 
 
283
    stream >> m_weight;
 
284
    size -= 4;
 
285
 
 
286
    stream >> m_italic;
 
287
    stream >> m_underline;
 
288
    stream >> m_strikeout;
 
289
    stream >> m_charSet;
 
290
    size -= 4;
 
291
 
 
292
    stream >> m_outPrecision;
 
293
    stream >> m_clipPrecision;
 
294
    stream >> m_quality;
 
295
    stream >> m_pitchAndFamily;
 
296
    size -= 4;
 
297
 
 
298
    QChar myChar[64];
 
299
    for ( int i = 0; i < 32; ++i ) {
 
300
        stream >> myChar[i];
 
301
    }
 
302
    size -= 64;
 
303
 
 
304
    for ( int i = 0; i < 32; ++i ) {
 
305
        if ( ! myChar[i].isNull() ) {
 
306
            m_facename.append( myChar[i] );
 
307
        }
 
308
    }
 
309
 
 
310
#if 0
 
311
    for ( int i = 0; i < 64; ++i ) {
 
312
        stream >> myChar[i];
 
313
    }
 
314
    size -= 128;
 
315
 
 
316
    for ( int i = 0; i < 64; ++i ) {
 
317
        if ( ! myChar[i].isNull() ) {
 
318
            m_fullName.append( myChar[i] );
 
319
        }
 
320
    }
 
321
    kDebug(33100) << "fullName:" << m_fullName;
 
322
 
 
323
    for ( int i = 0; i < 32; ++i ) {
 
324
        stream >> myChar[i];
 
325
    }
 
326
    size -= 64;
 
327
    for ( int i = 0; i < 32; ++i ) {
 
328
        if ( ! myChar[i].isNull() ) {
 
329
            m_style.append( myChar[i] );
 
330
        }
 
331
    }
 
332
    kDebug(33100) << "style:" << m_style;
 
333
 
 
334
    for ( int i = 0; i < 32; ++i ) {
 
335
        stream >> myChar[i];
 
336
    }
 
337
    size -= 64;
 
338
    for ( int i = 0; i < 32; ++i ) {
 
339
        if ( ! myChar[i].isNull() ) {
 
340
            m_script.append( myChar[i] );
 
341
        }
 
342
    }
 
343
    kDebug(33100) << "script:" << m_script;
 
344
#endif
 
345
    soakBytes( stream, size ); // rest of the record.
 
346
}
 
347
 
 
348
ExtCreateFontIndirectWRecord::~ExtCreateFontIndirectWRecord()
 
349
{
 
350
}
 
351
 
 
352
void ExtCreateFontIndirectWRecord::soakBytes( QDataStream &stream, int numBytes )
 
353
{
 
354
    quint8 scratch;
 
355
    for ( int i = 0; i < numBytes; ++i ) {
 
356
        stream >> scratch;
 
357
    }
 
358
}
 
359
 
 
360
/*****************************************************************************/
 
361
EmrTextObject::EmrTextObject( QDataStream &stream, quint32 size, TextType textType )
 
362
{
 
363
    stream >> m_referencePoint;
 
364
    size -= 8;
 
365
 
 
366
    stream >> m_charCount;
 
367
    size -= 4;
 
368
 
 
369
    stream >> m_offString;
 
370
    size -= 4;
 
371
    // 36 bytes for the body of the parent structure (EMR_EXTTEXTOUTA or EMR_EXTTEXTOUTW)
 
372
    // then parts of the EmrText structure
 
373
    quint32 offString = m_offString - 36 - 8 - 4 - 4; 
 
374
 
 
375
    stream >> m_options;
 
376
    size -= 4;
 
377
    offString -= 4;
 
378
 
 
379
    stream >> m_rectangle;
 
380
    size -= 16;
 
381
    offString -= 16;
 
382
 
 
383
    stream >> m_offDx;
 
384
    size -= 4;
 
385
    offString -= 4;
 
386
    // as for offString. 36 bytes for parent, then the earlier parts of EmrText
 
387
    quint32 offDx = m_offDx - 36 - 8 - 4 - 4 - 4 - 16 - 4;
 
388
 
 
389
    soakBytes( stream, offString ); // skips over UndefinedSpace1.
 
390
    size -= offString;
 
391
    offDx -= offString;
 
392
 
 
393
    if ( textType ==  SixteenBitChars ) {
 
394
        m_textString = recordWChars( stream, m_charCount );
 
395
        size -= 2 * m_charCount;
 
396
        offDx -= 2 * m_charCount;
 
397
    } else {
 
398
        m_textString = recordChars( stream, m_charCount );
 
399
        size -= m_charCount;
 
400
        offDx -= m_charCount;
 
401
    }
 
402
    // TODO: parse the spacing array
 
403
    soakBytes( stream, size );
 
404
}
 
405
 
 
406
EmrTextObject::~EmrTextObject()
 
407
{
 
408
}
 
409
 
 
410
QPoint EmrTextObject::referencePoint() const
 
411
{
 
412
    return m_referencePoint;
 
413
}
 
414
 
 
415
QString EmrTextObject::textString() const
 
416
{
 
417
    return m_textString;
 
418
}
 
419
 
 
420
QString EmrTextObject::recordWChars( QDataStream &stream, int numChars )
 
421
{
 
422
    QString text;
 
423
    QChar myChar;
 
424
    for ( int i = 0; i < numChars; ++i ) {
 
425
        stream >> myChar;
 
426
        text.append( myChar );
 
427
    }
 
428
    return text;
 
429
}
 
430
 
 
431
QString EmrTextObject::recordChars( QDataStream &stream, int numChars )
 
432
{
 
433
    QString text;
 
434
    quint8 myChar;
 
435
    for ( int i = 0; i < numChars; ++i ) {
 
436
        stream >> myChar;
 
437
        text.append( QChar( myChar ) );
 
438
    }
 
439
    return text;
 
440
}
 
441
 
 
442
void EmrTextObject::soakBytes( QDataStream &stream, int numBytes )
 
443
{
 
444
    quint8 scratch;
 
445
    for ( int i = 0; i < numBytes; ++i ) {
 
446
        stream >> scratch;
 
447
    }
 
448
}
 
449
 
 
450
/*****************************************************************************/
 
451
 
 
452
ExtTextOutARecord::ExtTextOutARecord( QDataStream &stream, quint32 size )
 
453
{
 
454
    size -= 8;
 
455
    stream >> m_bounds;
 
456
    size -= 16;
 
457
    stream >> m_iGraphicsMode;
 
458
    size -= 4;
 
459
    stream >> m_exScale;
 
460
    size -= 4;
 
461
    stream >> m_eyScale;
 
462
    size -= 4;
 
463
    m_emrText = new EmrTextObject( stream, size, EmrTextObject::EightBitChars );
 
464
}
 
465
 
 
466
ExtTextOutARecord::~ExtTextOutARecord()
 
467
{
 
468
   delete m_emrText;
 
469
}
 
470
 
 
471
QPoint ExtTextOutARecord::referencePoint() const
 
472
{
 
473
    return m_emrText->referencePoint();
 
474
}
 
475
 
 
476
QString ExtTextOutARecord::textString() const
 
477
{
 
478
    return m_emrText->textString();
 
479
}
 
480
 
 
481
}