Subversion Repositories Scribus

Rev

Rev 14509 | Rev 14720 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
13951 fschmid 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
7
 
8
/* Code inspired by KOffice libwmf and adapted for Scribus by Jean Ghali */
9
 
10
#include "scconfig.h"
11
#include "wmfimport.h"
12
 
13
#include <QCursor>
14
#include <QDrag>
15
#include <QBuffer>
16
#include <QDataStream>
17
#include <QFile>
18
#include <QMimeData>
19
#include <QPainterPath>
20
#include <QRegExp>
21
 
14170 jghali 22
#include "commonstrings.h"
13951 fschmid 23
#include "scribus.h"
24
#include "scribusXml.h"
14170 jghali 25
#include "fonts/scfontmetrics.h"
13951 fschmid 26
#include "fpointarray.h"
14509 cbradney 27
#include "ui/scmwmenumanager.h"
13951 fschmid 28
#include "prefsmanager.h"
29
#include "pageitem.h"
14170 jghali 30
#include "prefsfile.h"
13951 fschmid 31
#include "scmimedata.h"
32
#include "scraction.h"
33
#include "scribuscore.h"
34
#include "scribusdoc.h"
35
#include "selection.h"
14170 jghali 36
#include "ui/customfdialog.h"
37
#include "ui/propertiespalette.h"
13951 fschmid 38
#include "undomanager.h"
39
#include "loadsaveplugin.h"
40
#include "util.h"
41
#include "util_icon.h"
42
#include "util_math.h"
43
 
14170 jghali 44
 
13951 fschmid 45
using namespace std;
46
 
47
#include "wmfstruct.h"
48
#include "wmfcmd.h"
49
#include "wmfcontext.h"
50
#include "wmfhandle.h"
51
#include "metafuncs.h"
52
 
53
#define WMFIMPORT_DEBUG 0
54
#define MAX_OBJHANDLE   128
55
 
56
#define ANSI_CHARSET                    0               // ANSI charset (Windows-1252)
57
#define DEFAULT_CHARSET                 1
58
#define SYMBOL_CHARSET                  2
59
#define MAC_CHARSET                             77
60
#define SHIFTJIS_CHARSET                128             // Shift JIS charset    (Windows-932)
61
#define HANGEUL_CHARSET                 129             // Hangeul charset      (Windows-949)
62
#define JOHAB_CHARSET                   130             // Johab charset        (Windows-1361)
63
#define GB2312_CHARSET                  134             // GB2312 charset       (Windows-936)
64
#define CHINESEBIG5_CHARSET             136             // Chinese Big5 charset (Windows-950)
65
#define GREEK_CHARSET                   161             // Greek charset        (Windows-1253)
66
#define TURKISH_CHARSET                 162             // Turkish charset      (Windows-1254)
67
#define VIETNAMESE_CHARSET              163             // Vietnamese charset   (Windows-1258)
68
#define HEBREW_CHARSET                  177             // Hebrew charset       (Windows-1255)
69
#define ARABIC_CHARSET                  178             // Arabic charset       (Windows-1256)
70
#define BALTIC_CHARSET                  186             // Baltic charset       (Windows-1257)
71
#define RUSSIAN_CHARSET                 204             // Cyrillic charset     (Windows-1251)
72
#define THAI_CHARSET                    222             // Thai charset         (Windows-874)
73
#define EASTEUROPE_CHARSET              238             // Eastern european charset (Windows-1250)
74
#define OEM_CHARSET                             255
75
 
76
/* Symbol to unicode conversion table copied from http://root.cern.ch/viewvc/trunk/qt/src/TQtSymbolCodec.cxx
77
This code is placed under GPL licence (http://root.cern.ch/viewvc/trunk/LICENSE) */
78
static const ushort greek_symbol_to_unicode[64] = {
79
//
80
//  upper case letters:
81
//  ----------------
82
//   Alpha   Beta     Chi   Delta   Epsilon   Phi    Gamma    Eta
83
        0x0391, 0x0392, 0x03A7, 0x0394, 0x0395, 0x03A6, 0x0393, 0x0397,
84
//   Iota   Theta(S) Kappa  Lambda    Mu      Nu    Omicron   Pi
85
        0x0399, 0x03D1, 0x039A, 0x039B, 0x039C, 0x039D, 0x039F, 0x03A0,
86
//  Theta    Rho    Sigma    Tau    Upsilon Stigma   Omega     Xi
87
        0x0398, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03DB, 0x03A9, 0x039E,
88
//   Psi     Zeta   Sigma    Tau    Upsilon  ????   Omega     Xi
89
        0x03A8, 0x0396, 0x03EA, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
90
//
91
//  lower case letters:
92
//  ----------------
93
//   Alpha   Beta    Chi    Delta   Epsilon   Phi    Gamma    Eta
94
        0x03B1, 0x03B2, 0x03C7, 0x03B4, 0x03B5, 0x03D5, 0x03B3, 0x03B7,
95
//   Iota   Phi (2) Kappa   Lambda    Mu      Nu    Omicron   Pi
96
        0x03B9, 0x03C6, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BF, 0x03C0,
97
//  Theta    Rho    Sigma    Tau    Upsilon OmegaPi Omega     Xi
98
        0x03B8, 0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03D6, 0x03B9, 0x03BE,
99
//   Psi     Zeta   Sigma    Tau    Upsilon  ????   Omega     Xi
100
        0x03C8, 0x03B6, 0x03EA, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD
101
};
102
 
103
/* Symbol to unicode conversion table copied from http://root.cern.ch/viewvc/trunk/qt/src/TQtSymbolCodec.cxx
104
This code is placed under GPL licence (http://root.cern.ch/viewvc/trunk/LICENSE) */
105
static const ushort symbol_to_unicode[96] = {
106
//
107
//  upper case letters:
108
//  ----------------
109
// UPSILON  NUMBER  LessEq   Div   INFINITY ???????  CLUB   DIAMOND     
110
        0x03D2, 0x0374, 0x2264, 0x2215, 0x221E, 0x0395, 0x2663, 0x2666,
111
//   HEART  SPADE   <--->   <---             -->             RING
112
        0x2665, 0x2660, 0x2194, 0x2190, 0x2191, 0x2192, 0x2193, 0x2218,
113
//  Theta    Rho    Great    ????   Propor  diff    bullet   ????
114
        0x0398, 0x03A1, 0x2265, 0x03A4, 0x221D, 0x2202, 0x2219, 0x03A8,
115
//   NonEq  Ident    ????   ellips   div     minus  ?????   aleph
116
        0x2260, 0x2261, 0xFFFD, 0x22EF, 0x2223, 0x2212, 0xFFFD, 0xFFFD,
117
//
118
//  lower case letters:
119
//  ----------------
120
//   Alpha   Beta    Chi    Delta   Epsilon   Phi    Gamma    Eta
121
        0x03B1, 0x03B2, 0x03C7, 0x03B4, 0x03B5, 0x03D5, 0x03B3, 0x03B7,
122
//   Iota   Phi (2) Kappa   Lambda    Mu      Nu    Omicron   Pi
123
        0x03B9, 0x03C6, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BF, 0x03C0,
124
//  Theta    Rho    Sigma    Tau    Upsilon OmegaPi Omega     Xi
125
        0x03B8, 0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03D6, 0x03B9, 0x03BE,
126
//   Psi     Zeta   arrow    Tau    Upsilon  ????   Omega     Xi
127
        0x03C8, 0x03B6, 0x21D4, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD,
128
//  lower case letters:
129
//  ----------------
130
//   Alpha   Beta    Chi    Delta   Sigma     Phi    Gamma    Eta
131
        0x03B1, 0x03B2, 0x03C7, 0x03B4, 0x2211, 0x03D5, 0x03B3, 0x03B7,
132
//   Iota   Phi (2) Kappa   Lambda    Mu      Nu    Omicron   Pi
133
        0x03B9, 0x03C6, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BF, 0x03C0,
134
//  Theta   Integr  Sigma    Tau    Upsilon OmegaPi Omega     Xi
135
        0x03B8, 0x222b, 0x03C3, 0x03C4, 0x03C5, 0x03D6, 0x03B9, 0x03BE,
136
//   Psi     Zeta   Sigma    Tau    Upsilon  ????   Omega     Xi
137
        0x03C8, 0x03B6, 0x03EA, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD
138
};
139
 
14710 fschmid 140
WMFImport::WMFImport( ScribusDoc* doc, int flags )
13951 fschmid 141
{      
142
        m_tmpSel = new Selection(this, false);
14710 fschmid 143
        m_Doc    = doc;
13951 fschmid 144
        unsupported = false;
145
        importFailed = false;
146
        importCanceled = true;
147
        importedColors.clear();
148
        m_docDesc = "";
149
        m_docTitle = "";
150
        interactive = (flags & LoadSavePlugin::lfInteractive);
151
 
152
        m_Valid        = false;
153
        m_ObjHandleTab = NULL;
154
        m_Dpi          = 1440;
155
}
156
 
157
WMFImport::~WMFImport()
158
{
159
        qDeleteAll(m_commands);
160
        m_commands.clear();
161
        if ( m_tmpSel) delete m_tmpSel;
162
        if ( m_ObjHandleTab )
163
        {
164
                for (int i = 0; i < MAX_OBJHANDLE; ++i)
165
                {
166
                        if (m_ObjHandleTab[i])
167
                                delete m_ObjHandleTab[i];
168
                }
169
                delete[] m_ObjHandleTab;
170
        }
171
}
172
 
173
QString WMFImport::importColor(const QColor& color)
174
{
175
        bool found = false;
176
        int r, g, b;
177
        QColor  tmpColor;
178
        QString retColorName;
179
        ColorList::Iterator it;
180
        for (it = m_Doc->PageColors.begin(); it != m_Doc->PageColors.end(); ++it)
181
        {
182
                if (it.value().getColorModel() == colorModelRGB)
183
                {
184
                        it.value().getRGB(&r, &g, &b);
185
                        tmpColor.setRgb(r, g, b);
186
                        if (color == tmpColor)
187
                        {
188
                                retColorName = it.key();
189
                                found = true;
190
                                break;
191
                        }
192
                }
193
        }
194
        if (!found)
195
        {
196
                ScColor tmp;
197
                tmp.fromQColor(color);
198
                tmp.setSpotColor(false);
199
                tmp.setRegistrationColor(false);
200
                m_Doc->PageColors.insert("FromWMF"+color.name(), tmp);
201
                importedColors.append("FromWMF"+color.name());
202
                retColorName = "FromWMF"+color.name();
203
        }
204
        return retColorName;
205
}
206
 
207
QColor WMFImport::colorFromParam( short* params )
208
{
209
        unsigned int colorRef;
210
        int red, green, blue;
211
 
212
        colorRef = toDWord( params ) & 0xffffff;
213
        red      = colorRef & 255;
214
        green    = ( colorRef>>8 ) & 255;
215
        blue     = ( colorRef>>16 ) & 255;
216
 
217
        return QColor( red, green, blue );
218
}
219
 
220
QTextCodec* WMFImport::codecFromCharset( int charset )
221
{
222
        QTextCodec* codec = NULL;
223
        if (charset == DEFAULT_CHARSET || charset == OEM_CHARSET)
224
                codec = QTextCodec::codecForLocale();
225
        else if (charset == ANSI_CHARSET)
226
                codec = QTextCodec::codecForName("windows-1252");
227
        /*else if (charset == SYMBOL_CHARSET)
228
                codec = QTextCodec::codecForLocale();// Not supported yet*/
229
        else if (charset == MAC_CHARSET)
230
                codec = QTextCodec::codecForName("Apple Roman");
231
        else if (charset == SHIFTJIS_CHARSET)
232
                codec = QTextCodec::codecForName("Shift-JIS");
233
        else if (charset == HANGEUL_CHARSET)
234
                codec = QTextCodec::codecForName("CP949");
235
        else if (charset == GB2312_CHARSET)
236
                codec = QTextCodec::codecForName("CP936");
237
        else if (charset == CHINESEBIG5_CHARSET)
238
                codec = QTextCodec::codecForName("Big5");
239
        else if (charset == GREEK_CHARSET)
240
                codec = QTextCodec::codecForName("windows-1253");
241
        else if (charset == TURKISH_CHARSET)
242
                codec = QTextCodec::codecForName("windows-1254");
243
        else if (charset == VIETNAMESE_CHARSET)
244
                codec = QTextCodec::codecForName("windows-1258");
245
        else if (charset == HEBREW_CHARSET)
246
                codec = QTextCodec::codecForName("windows-1255");
247
        else if (charset == ARABIC_CHARSET)
248
                codec = QTextCodec::codecForName("windows-1256");
249
        else if (charset == BALTIC_CHARSET)
250
                codec = QTextCodec::codecForName("windows-1257");
251
        else if (charset == RUSSIAN_CHARSET)
252
                codec = QTextCodec::codecForName("windows-1251");
253
        else if (charset == THAI_CHARSET)
254
                codec = QTextCodec::codecForName("CP874");
255
        else if (charset == EASTEUROPE_CHARSET)
256
                codec = QTextCodec::codecForName("windows-1250");
257
        return codec;
258
}
259
 
260
QString WMFImport::symbolToUnicode ( const QByteArray& chars )
261
{
262
        /*Code under GPL licence (http://root.cern.ch/viewvc/trunk/LICENSE)
263
        taken from http://root.cern.ch/viewvc/trunk/qt/src/TQtSymbolCodec.cxx*/
264
        QString r;
265
        const unsigned char * c = (const unsigned char *) chars.data();
266
 
267
        if( chars.size() == 0 ) return r;
268
 
269
        for (int i = 0; i < chars.size(); ++i)
270
        {
271
                if ( 64 < c[i] && c[i] <= 64+32 )
272
                        r.append( QChar(greek_symbol_to_unicode[c[i]-65]) );
273
                else if (64+32+1 <= c[i] && c[i] < 64+32+32+1)
274
                        r.append( QChar(greek_symbol_to_unicode[c[i]-65-32]+32) );
275
                else if (161 <= c[i] )
276
                        r.append(  QChar(symbol_to_unicode[c[i]-161]) );
277
                else
278
                        r.append( QChar(c[i]) );
279
        }
280
        return r;
281
}
282
 
283
FPointArray WMFImport::pointsFromParam( short num, short* params )
284
{
285
        FPointArray points;
286
        points.resize( num );
287
 
288
        for ( int i = 0; i < num; i++, params += 2 )
289
                points.setPoint( i, params[ 0 ], params[ 1 ] );
290
 
291
        return points;
292
}
293
 
294
FPointArray WMFImport::pointsToPolyline( const FPointArray& points, bool closePath )
295
{
296
        bool bFirst = true;
297
        double x = 0.0, y = 0.0;
298
        FPointArray polyline;
299
        polyline.svgInit();
300
        for( uint i = 0; i < points.size(); ++i )
301
        {
302
                FPoint point = points.point(i);
303
                if( bFirst )
304
                {
305
                        x = point.x();
306
                        y = point.y();
307
                        polyline.svgMoveTo(x, y);
308
                        bFirst = false;
309
                }
310
                else
311
                {
312
                        x = point.x();
313
                        y = point.y();
314
                        polyline.svgLineTo(x, y);
315
                }
316
        }
317
        if (closePath && (points.size() > 4))
318
                polyline.svgClosePath();
319
        return polyline;
320
}
321
 
322
void WMFImport::pointsToAngle( double xStart, double yStart, double xEnd, double yEnd, double& angleStart, double& angleLength )
323
{
324
        double aStart  = atan2( yStart,  xStart );
325
        double aLength = atan2( yEnd, xEnd ) - aStart;
326
 
327
        angleStart  = (int)(aStart * 180.0 / 3.14166);
328
        angleLength = (int)(aLength * 180.0 / 3.14166);
329
        if ( angleLength < 0 ) angleLength = 360.0 + angleLength;
330
}
331
 
14710 fschmid 332
QImage WMFImport::readThumbnail(QString fname)
333
{
334
        if (!loadWMF(fname))
335
        {
336
                importFailed = true;
337
                return QImage();
338
        }
339
        QString CurDirP = QDir::currentPath();
340
        QFileInfo efp(fname);
341
        QDir::setCurrent(efp.path());
342
        double scale  = (m_Dpi > 0) ? 72.0 / m_Dpi : 0.05;
343
        double width  = m_BBox.width() * scale;
344
        double height = m_BBox.height() * scale;
345
        m_Doc = new ScribusDoc();
346
        m_Doc->setup(0, 1, 1, 1, 1, "Custom", "Custom");
347
        m_Doc->setPage(width, height, 0, 0, 0, 0, 0, 0, false, false);
348
        m_Doc->addPage(0);
349
        m_Doc->setGUI(false, ScCore->primaryMainWindow(), 0);
350
        m_Doc->setLoading(true);
351
        m_Doc->DoDrawing = false;
352
        m_Doc->scMW()->ScriptRunning = true;
353
        m_Doc->PageColors.ensureBlackAndWhite();
354
        QList<PageItem*> Elements = parseWmfCommands();
355
        m_tmpSel->clear();
356
        if (Elements.count() > 0)
357
        {
358
                bool isGroup = true;
359
                int firstElem = -1;
360
                if (Elements.at(0)->Groups.count() != 0)
361
                        firstElem = Elements.at(0)->Groups.top();
362
                for (int bx = 0; bx < Elements.count(); ++bx)
363
                {
364
                        PageItem* bxi = Elements.at(bx);
365
                        if (bxi->Groups.count() != 0)
366
                        {
367
                                if (bxi->Groups.top() != firstElem)
368
                                        isGroup = false;
369
                        }
370
                        else
371
                                isGroup = false;
372
                }
373
                if (!isGroup)
374
                {
375
                        double minx = 99999.9;
376
                        double miny = 99999.9;
377
                        double maxx = -99999.9;
378
                        double maxy = -99999.9;
379
                        uint lowestItem = 999999;
380
                        uint highestItem = 0;
381
                        for (int a = 0; a < Elements.count(); ++a)
382
                        {
383
                                Elements.at(a)->Groups.push(m_Doc->GroupCounter);
384
                                PageItem* currItem = Elements.at(a);
385
                                lowestItem = qMin(lowestItem, currItem->ItemNr);
386
                                highestItem = qMax(highestItem, currItem->ItemNr);
387
                                double x1, x2, y1, y2;
388
                                currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
389
                                minx = qMin(minx, x1);
390
                                miny = qMin(miny, y1);
391
                                maxx = qMax(maxx, x2);
392
                                maxy = qMax(maxy, y2);
393
                        }
394
                        double gx = minx;
395
                        double gy = miny;
396
                        double gw = maxx - minx;
397
                        double gh = maxy - miny;
398
                        PageItem *high = m_Doc->Items->at(highestItem);
399
                        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, gx, gy, gw, gh, 0, m_Doc->itemToolPrefs.shapeFillColor, m_Doc->itemToolPrefs.shapeLineColor, true);
400
                        PageItem *neu = m_Doc->Items->takeAt(z);
401
                        m_Doc->Items->insert(lowestItem, neu);
402
                        neu->Groups.push(m_Doc->GroupCounter);
403
                        neu->setItemName( tr("Group%1").arg(neu->Groups.top()));
404
                        neu->AutoName = false;
405
                        neu->isGroupControl = true;
406
                        neu->groupsLastItem = high;
407
                        for (int a = 0; a < m_Doc->Items->count(); ++a)
408
                        {
409
                                m_Doc->Items->at(a)->ItemNr = a;
410
                        }
411
                        neu->setRedrawBounding();
412
                        neu->setTextFlowMode(PageItem::TextFlowDisabled);
413
                        Elements.prepend(neu);
414
                        m_Doc->GroupCounter++;
415
                }
416
        }
417
        m_Doc->DoDrawing = true;
418
        m_Doc->m_Selection->delaySignalsOn();
419
        for (int dre=0; dre<Elements.count(); ++dre)
420
        {
421
                m_tmpSel->addItem(Elements.at(dre), true);
422
        }
423
        m_tmpSel->setGroupRect();
424
        double xs = m_tmpSel->width();
425
        double ys = m_tmpSel->height();
426
        double sc = 500.0 / qMax(xs, ys);
427
        m_Doc->scaleGroup(sc, sc, true, m_tmpSel);
428
        QImage tmpImage = Elements.at(0)->DrawObj_toImage();
429
        tmpImage.setText("XSize", QString("%1").arg(xs));
430
        tmpImage.setText("YSize", QString("%1").arg(ys));
431
        m_Doc->m_Selection->delaySignalsOff();
432
        m_Doc->scMW()->ScriptRunning = false;
433
        m_Doc->setLoading(false);
434
        delete m_Doc;
435
        QDir::setCurrent(CurDirP);
436
        return tmpImage;
437
}
438
 
13951 fschmid 439
bool WMFImport::import(QString fname, const TransactionSettings& trSettings, int flags)
440
{
441
        if (!loadWMF(fname))
442
        {
443
                importFailed = true;
444
                return false;
445
        }
446
        QString CurDirP = QDir::currentPath();
447
        QFileInfo efp(fname);
448
        QDir::setCurrent(efp.path());
449
        bool success = importWMF(trSettings, flags);
450
        QDir::setCurrent(CurDirP);
451
        return success;
452
}
453
 
454
bool WMFImport::loadWMF( const QString &fileName )
455
{
456
        QFile file( fileName );
457
 
458
        if ( !file.exists() )
459
        {
460
                cerr << "File " << QFile::encodeName(fileName).data() << " does not exist" << endl;
461
                return false;
462
        }
463
 
464
        if ( !file.open( QIODevice::ReadOnly ) )
465
        {
466
                cerr << "Cannot open file " << QFile::encodeName(fileName).data() << endl;
467
                return false;
468
        }
469
 
470
        QByteArray ba = file.readAll();
471
        file.close();
472
 
473
        QBuffer buffer( &ba );
474
        buffer.open( QIODevice::ReadOnly );
475
        return loadWMF( buffer );
476
}
477
 
478
bool WMFImport::loadWMF( QBuffer &buffer )
479
{
480
        QDataStream st;
481
        WmfEnhMetaHeader eheader;
482
        WmfMetaHeader header;
483
        WmfPlaceableHeader pheader;
484
        WORD16 checksum;
485
        int filePos, idx, i;
486
        WmfCmd *cmd;
487
        WORD32 rdSize;
488
        WORD16 rdFunc;
489
 
490
        header.mtSize = 0;
491
        header.mtHeaderSize = 0;
492
        header.mtNoParameters = 0;
493
 
494
        qDeleteAll(m_commands);
495
        m_commands.clear();
496
 
497
        st.setDevice( &buffer );
498
        st.setByteOrder( QDataStream::LittleEndian ); // Great, I love Qt !
499
 
500
        //----- Read placeable metafile header
501
        st >> pheader.key;
502
        m_IsPlaceable = (pheader.key == (WORD32) APMHEADER_KEY);
503
        if ( m_IsPlaceable )
504
        {
505
                st >> pheader.hmf;
506
                st >> pheader.bbox.left;
507
                st >> pheader.bbox.top;
508
                st >> pheader.bbox.right;
509
                st >> pheader.bbox.bottom;
510
                st >> pheader.inch;
511
                st >> pheader.reserved;
512
                st >> pheader.checksum;
513
                checksum = calcCheckSum( &pheader );
514
                if ( pheader.checksum!=checksum ) m_IsPlaceable = false;
515
 
516
                m_Dpi = pheader.inch;
517
                m_BBox.setLeft( pheader.bbox.left );
518
                m_BBox.setTop( pheader.bbox.top );
519
                m_BBox.setRight( pheader.bbox.right );
520
                m_BBox.setBottom( pheader.bbox.bottom );
521
                m_HeaderBoundingBox = m_BBox;
522
                if ( WMFIMPORT_DEBUG )
523
                {
524
                        cerr << endl << "-------------------------------------------------" << endl;
525
                        cerr << "WMF Placeable Header ( " << static_cast<int>(sizeof( pheader ) ) << "):" << endl;
526
                        cerr << "  bbox=( " << m_BBox.left() << "; " << m_BBox.top() << "; " << m_BBox.width() << "; " << m_BBox.height() << ")" << endl;
527
                        cerr << "  inch=" << pheader.inch << endl;
528
                        cerr << "  checksum=" << pheader.checksum << "( " << (pheader.checksum==checksum?"ok":"wrong") << " )" << endl;
529
                }
530
        }
531
        else buffer.seek( 0 );
532
 
533
        //----- Read as enhanced metafile header
534
        filePos = buffer.pos();
535
        st >> eheader.iType;
536
        st >> eheader.nSize;
537
        st >> eheader.rclBounds.left;
538
        st >> eheader.rclBounds.top;
539
        st >> eheader.rclBounds.right;
540
        st >> eheader.rclBounds.bottom;
541
        st >> eheader.rclFrame.left;
542
        st >> eheader.rclFrame.top;
543
        st >> eheader.rclFrame.right;
544
        st >> eheader.rclFrame.bottom;
545
        st >> eheader.dSignature;
546
        m_IsEnhanced = ( eheader.dSignature==ENHMETA_SIGNATURE );
547
        if ( m_IsEnhanced ) // is it really enhanced ?
548
        {
549
                st >> eheader.nVersion;
550
                st >> eheader.nBytes;
551
                st >> eheader.nRecords;
552
                st >> eheader.nHandles;
553
                st >> eheader.sReserved;
554
                st >> eheader.nDescription;
555
                st >> eheader.offDescription;
556
                st >> eheader.nPalEntries;
557
                st >> eheader.szlDevice.width;
558
                st >> eheader.szlDevice.height;
559
                st >> eheader.szlMillimeters.width;
560
                st >> eheader.szlMillimeters.height;
561
 
562
                if ( WMFIMPORT_DEBUG )
563
                {
564
                        cerr << endl << "-------------------------------------------------" << endl;
565
                        cerr << "WMF Extended Header:" << endl;
566
                        cerr << "  iType=" << eheader.iType << endl;
567
                        cerr << "  nSize=" << eheader.nSize << endl;
568
                        cerr << "  rclBounds=( " << eheader.rclBounds.left << "; " << eheader.rclBounds.top << "; "
569
                                          << eheader.rclBounds.right << "; " << eheader.rclBounds.bottom << ")" << endl;
570
                        cerr << "  rclFrame=( " << eheader.rclFrame.left << "; " << eheader.rclFrame.top << "; "
571
                                          << eheader.rclFrame.right << "; " << eheader.rclFrame.bottom << ")" << endl;
572
                        cerr << "  nBytes=" << eheader.nBytes << endl;
573
                        cerr << "\nNOT YET IMPLEMENTED, SORRY." << endl;
574
                }
575
        }
576
        else // no, not enhanced
577
        {
578
                //----- Read as standard metafile header
579
                buffer.seek( filePos );
580
                st >> header.mtType;
581
                st >> header.mtHeaderSize;
582
                st >> header.mtVersion;
583
                st >> header.mtSize;
584
                st >> header.mtNoObjects;
585
                st >> header.mtMaxRecord;
586
                st >> header.mtNoParameters;
587
                if ( WMFIMPORT_DEBUG ) {
588
                        cerr << "WMF Header: " <<  "mtSize=" << header.mtSize << endl;
589
                }
590
        }
591
 
592
        //----- Test header validity
593
        m_Valid = ((header.mtHeaderSize == 9) && (header.mtNoParameters == 0)) || m_IsEnhanced || m_IsPlaceable;
594
        if ( m_Valid )
595
        {
596
                //----- Read Metafile Records
597
                rdFunc = -1;
598
                while ( !st.atEnd() && (rdFunc != 0) )
599
                {
600
                        st >> rdSize;
601
                        st >> rdFunc;
602
                        idx = findFunc( rdFunc );
603
                        rdSize -= 3;
604
 
605
                        cmd = new WmfCmd;
606
                        m_commands.append(cmd);
607
 
608
                        cmd->funcIndex = idx;
609
                        cmd->numParam = rdSize;
610
                        cmd->params = new WORD16[ rdSize ];
611
 
612
                        for ( i=0; i<rdSize && !st.atEnd(); i++ )
613
                                st >> cmd->params[ i ];
614
 
615
 
616
                        if ( rdFunc == 0x020B && !m_IsPlaceable) {         // SETWINDOWORG: dimensions
617
                                m_BBox.setLeft( qMin((int) cmd->params[ 1 ], m_BBox.left()) );
618
                                m_BBox.setTop ( qMin((int) cmd->params[ 0 ], m_BBox.top()) );
619
                        }
620
                        if ( rdFunc == 0x020C && !m_IsPlaceable ) {         // SETWINDOWEXT: dimensions
621
                                m_BBox.setWidth ( qMax((int) cmd->params[ 1 ], m_BBox.width()) );
622
                                m_BBox.setHeight( qMax((int) cmd->params[ 0 ], m_BBox.height()));
623
                        }
624
 
625
                        if ( i<rdSize )
626
                        {
627
                                cerr << "WMF : file truncated !" << endl;
628
                                return false;
629
                        }
630
                }
631
                //----- Test records validities
632
                m_Valid = (rdFunc == 0) && (m_BBox.width() != 0) && (m_BBox.height() != 0);
633
                if ( !m_Valid ) {
634
                        cerr << "WMF : incorrect file format !" << endl;
635
                }
636
        }
637
        else {
638
                cerr << "WMF Header : incorrect header !" << endl;
639
        }
640
 
641
        buffer.close();
642
        return m_Valid;
643
}
644
 
645
bool WMFImport::importWMF(const TransactionSettings& trSettings, int flags)
646
{
647
        bool ret = false;
648
        //double scale = (m_Dpi > 288) ? 288.0 / m_Dpi : 1.0;
649
        double scale  = (m_Dpi > 0) ? 72.0 / m_Dpi : 0.05;
650
        double width  = m_BBox.width() * scale;
651
        double height = m_BBox.height() * scale;
652
        if (!interactive || (flags & LoadSavePlugin::lfInsertPage))
653
        {
654
                m_Doc->setPage(fabs(width), fabs(height), 0, 0, 0, 0, 0, 0, false, false);
655
                m_Doc->addPage(0);
656
                m_Doc->view()->addPage(0);
657
        }
658
        else
659
        {
660
                if (!m_Doc || (flags & LoadSavePlugin::lfCreateDoc))
661
                {
662
                        m_Doc=ScCore->primaryMainWindow()->doFileNew(fabs(width), fabs(height), 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom", true);
663
                        ScCore->primaryMainWindow()->HaveNewDoc();
664
                        ret = true;
665
                }
666
        }
667
        if ((ret) || (!interactive))
668
        {
669
                if (width > height)
670
                        m_Doc->PageOri = 1;
671
                else
672
                        m_Doc->PageOri = 0;
673
                m_Doc->m_pageSize = "Custom";
674
        }
675
        FPoint minSize = m_Doc->minCanvasCoordinate;
676
        FPoint maxSize = m_Doc->maxCanvasCoordinate;
677
        FPoint cOrigin = m_Doc->view()->canvasOrigin();
678
        m_Doc->view()->Deselect();
679
        m_Doc->setLoading(true);
680
        m_Doc->DoDrawing = false;
681
        m_Doc->view()->updatesOn(false);
682
        m_Doc->scMW()->ScriptRunning = true;
683
        qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
13996 cbradney 684
        //gc->Family = m_Doc->toolSettings.textFont;
13951 fschmid 685
        m_Doc->PageColors.ensureBlackAndWhite();
686
        //m_gc.push( gc );
687
        QList<PageItem*> Elements = parseWmfCommands();
688
        if (flags & LoadSavePlugin::lfCreateDoc)
689
        {
690
                m_Doc->documentInfo.setTitle(m_docTitle);
691
                m_Doc->documentInfo.setComments(m_docDesc);
692
        }
693
        m_tmpSel->clear();
694
        if (Elements.count() == 0)
695
        {
696
                importFailed = true;
697
                if (importedColors.count() != 0)
698
                {
699
                        for (int cd = 0; cd < importedColors.count(); cd++)
700
                        {
701
                                m_Doc->PageColors.remove(importedColors[cd]);
702
                        }
703
                }
704
        }
705
        if (Elements.count() > 1)
706
        {
707
                bool isGroup = true;
708
                int firstElem = -1;
709
                if (Elements.at(0)->Groups.count() != 0)
710
                        firstElem = Elements.at(0)->Groups.top();
711
                for (int bx = 0; bx < Elements.count(); ++bx)
712
                {
713
                        PageItem* bxi = Elements.at(bx);
714
                        if (bxi->Groups.count() != 0)
715
                        {
716
                                if (bxi->Groups.top() != firstElem)
717
                                        isGroup = false;
718
                        }
719
                        else
720
                                isGroup = false;
721
                }
722
                if (!isGroup)
723
                {
724
                        double minx = 99999.9;
725
                        double miny = 99999.9;
726
                        double maxx = -99999.9;
727
                        double maxy = -99999.9;
728
                        uint lowestItem = 999999;
729
                        uint highestItem = 0;
730
                        for (int a = 0; a < Elements.count(); ++a)
731
                        {
732
                                Elements.at(a)->Groups.push(m_Doc->GroupCounter);
733
                                PageItem* currItem = Elements.at(a);
734
                                lowestItem = qMin(lowestItem, currItem->ItemNr);
735
                                highestItem = qMax(highestItem, currItem->ItemNr);
736
                                double x1, x2, y1, y2;
737
                                currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
738
                                minx = qMin(minx, x1);
739
                                miny = qMin(miny, y1);
740
                                maxx = qMax(maxx, x2);
741
                                maxy = qMax(maxy, y2);
742
                        }
743
                        double gx = minx;
744
                        double gy = miny;
745
                        double gw = maxx - minx;
746
                        double gh = maxy - miny;
747
                        PageItem *high = m_Doc->Items->at(highestItem);
14014 cbradney 748
                        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, gx, gy, gw, gh, 0, m_Doc->itemToolPrefs.shapeFillColor, m_Doc->itemToolPrefs.shapeLineColor, true);
13951 fschmid 749
                        PageItem *neu = m_Doc->Items->takeAt(z);
750
                        m_Doc->Items->insert(lowestItem, neu);
751
                        neu->Groups.push(m_Doc->GroupCounter);
752
                        neu->setItemName( tr("Group%1").arg(neu->Groups.top()));
753
                        neu->AutoName = false;
754
                        neu->isGroupControl = true;
755
                        neu->groupsLastItem = high;
756
                        for (int a = 0; a < m_Doc->Items->count(); ++a)
757
                        {
758
                                m_Doc->Items->at(a)->ItemNr = a;
759
                        }
760
                        neu->setRedrawBounding();
761
                        neu->setTextFlowMode(PageItem::TextFlowDisabled);
762
                        Elements.prepend(neu);
763
                        m_Doc->GroupCounter++;
764
                }
765
        }
766
        m_Doc->DoDrawing = true;
767
        m_Doc->scMW()->ScriptRunning = false;
768
        if (interactive)
769
                m_Doc->setLoading(false);
770
        qApp->setOverrideCursor(QCursor(Qt::ArrowCursor));
771
        if ((Elements.count() > 0) && (!ret) && (interactive))
772
        {
773
                if (flags & LoadSavePlugin::lfScripted)
774
                {
775
                        bool loadF = m_Doc->isLoading();
776
                        m_Doc->setLoading(false);
777
                        m_Doc->changed();
778
                        m_Doc->setLoading(loadF);
779
                        m_Doc->m_Selection->delaySignalsOn();
780
                        for (int dre=0; dre<Elements.count(); ++dre)
781
                        {
782
                                m_Doc->m_Selection->addItem(Elements.at(dre), true);
783
                        }
784
                        m_Doc->m_Selection->delaySignalsOff();
785
                        m_Doc->m_Selection->setGroupRect();
786
                        m_Doc->view()->updatesOn(true);
787
                        importCanceled = false;
788
                }
789
                else
790
                {
791
                        m_Doc->DragP = true;
792
                        m_Doc->DraggedElem = 0;
793
                        m_Doc->DragElements.clear();
794
                        m_Doc->m_Selection->delaySignalsOn();
795
                        for (int dre=0; dre<Elements.count(); ++dre)
796
                        {
797
                                m_Doc->DragElements.append(Elements.at(dre)->ItemNr);
798
                                m_tmpSel->addItem(Elements.at(dre), true);
799
                        }
800
                        ScriXmlDoc *ss = new ScriXmlDoc();
801
                        m_tmpSel->setGroupRect();
802
                        ScElemMimeData* md = new ScElemMimeData();
803
                        md->setScribusElem(ss->WriteElem(m_Doc, m_Doc->view(), m_tmpSel));
804
                        delete ss;
805
/*#ifndef QT_MAC*/
806
// see #2526
807
                        m_Doc->itemSelection_DeleteItem(m_tmpSel);
808
/*#endif*/
809
                        m_Doc->view()->updatesOn(true);
810
                        m_Doc->m_Selection->delaySignalsOff();
811
                        // We must copy the TransationSettings object as it is owned
812
                        // by handleObjectImport method afterwards
813
                        TransactionSettings* transacSettings = new TransactionSettings(trSettings);
814
                        m_Doc->view()->handleObjectImport(md, transacSettings);
815
                        m_Doc->DragP = false;
816
                        m_Doc->DraggedElem = 0;
817
                        m_Doc->DragElements.clear();
818
                }
819
        }
820
        else
821
        {
822
                bool loadF = m_Doc->isLoading();
823
                m_Doc->setLoading(false);
824
                m_Doc->changed();
825
                m_Doc->reformPages();
826
                m_Doc->view()->updatesOn(true);
827
                m_Doc->setLoading(loadF);
828
        }
829
        return true;
830
}
831
 
832
QList<PageItem*> WMFImport::parseWmfCommands(void)
833
{
834
        int idx, i;
835
        const WmfCmd* cmd;
836
        QList<PageItem*> elements;
837
 
838
        m_context.reset();
839
 
840
        if ( !m_Valid )  return elements;
841
 
842
        if ( m_ObjHandleTab ) delete[] m_ObjHandleTab;
843
        m_ObjHandleTab = new WmfObjHandle* [ MAX_OBJHANDLE ];
844
        for ( i = MAX_OBJHANDLE-1; i >= 0; i-- )
845
                m_ObjHandleTab[ i ] = NULL;
846
 
847
        if ( WMFIMPORT_DEBUG )  {
848
                cerr << "Bounding box : " << m_BBox.left() << " " << m_BBox.top() << " " << m_BBox.right() << " " << m_BBox.bottom() << endl;
849
        }
850
 
851
        double scale  = (m_Dpi > 0) ? 72.0 / m_Dpi : 0.05;
852
        m_context.setViewportOrg( 0, 0 );
853
        m_context.setViewportExt( m_BBox.width() * scale, m_BBox.height() * scale );
854
        m_context.setWindowOrg( m_BBox.left(), m_BBox.bottom() );
855
        m_context.setWindowExt( m_BBox.width(), m_BBox.height() );
856
 
857
        for (int index = 0; index < m_commands.count(); ++index)
858
        {
859
                cmd = m_commands.at(index);
860
                idx = cmd->funcIndex;
861
                ( this->*metaFuncTab[ idx ].method )( elements, cmd->numParam, cmd->params );
862
 
863
                if ( WMFIMPORT_DEBUG )  {
864
                        QString str = "", param;
865
                        if ( metaFuncTab[ idx ].name == NULL ) {
866
                                str += "UNKNOWN ";
867
                        }
868
                        if ( metaFuncTab[ idx ].method == &WMFImport::noop ) {
869
                                str += "UNIMPLEMENTED ";
870
                        }
871
                        str += metaFuncTab[ idx ].name;
872
                        str += " : ";
873
 
874
                        for ( i=0 ; i < cmd->numParam ; i++ ) {
875
                                param.setNum( cmd->params[ i ] );
876
                                str += param;
877
                                str += " ";
878
                        }
879
                        cerr << str.toAscii().data() << endl;
880
                }
881
        }
882
        return elements;
883
}
884
 
885
void WMFImport::finishCmdParsing( PageItem* item )
886
{
887
        QTransform gcm  = m_context.worldMatrix();
888
        double coeff1 = sqrt(gcm.m11() * gcm.m11() + gcm.m12() * gcm.m12());
889
        double coeff2 = sqrt(gcm.m21() * gcm.m21() + gcm.m22() * gcm.m22());
890
        if( item->asImageFrame() )
891
        {
892
                item->moveBy(gcm.dx(), gcm.dy());
893
                item->setWidthHeight(item->width() * gcm.m11(), item->height() * gcm.m22());
894
                item->setLineWidth(qMax(item->lineWidth() * (coeff1 + coeff2) / 2.0, 0.25));
895
                if (item->PictureIsAvailable)
896
                        item->setImageXYScale(item->width() / item->pixm.width(), item->height() / item->pixm.height());
897
        }
898
        else if( item->asTextFrame() )
899
        {
900
                item->setLineWidth(qMax(item->lineWidth() * (coeff1 + coeff2) / 2.0, 0.25));
901
        }
902
        else
903
        {
904
                item->ClipEdited = true;
905
                item->FrameType = 3;
906
                item->PoLine.map(gcm);
907
                item->setLineWidth(qMax(item->lineWidth() * (coeff1 + coeff2) / 2.0, 0.25));
908
                FPoint wh = getMaxClipF(&item->PoLine);
909
                item->setWidthHeight(wh.x(), wh.y());
910
                m_Doc->AdjustItemSize(item);
911
        }
912
        item->setRedrawBounding();
913
        item->OwnPage   = m_Doc->OnPage(item);
914
        item->PLineEnd  = m_context.pen().capStyle();
915
        item->PLineJoin = m_context.pen().joinStyle();
916
        item->setTextFlowMode(PageItem::TextFlowDisabled);
917
        //item->DashOffset = gc->dashOffset;
918
        //item->DashValues = gc->dashArray;
919
}
920
 
921
void WMFImport::setWindowOrg( QList<PageItem*>& /*items*/, long, short* params )
922
{
923
        m_context.setWindowOrg( params[ 1 ], params[ 0 ] );
924
}
925
 
926
void WMFImport::setWindowExt( QList<PageItem*>& /*items*/, long, short* params )
927
{
928
        m_context.setWindowExt( params[ 1 ], params[ 0 ] );
929
}
930
 
931
void WMFImport::lineTo( QList<PageItem*>& items, long, short* params )
932
{
933
        double BaseX = m_Doc->currentPage()->xOffset();
934
        double BaseY = m_Doc->currentPage()->yOffset();
935
        QPoint currentPos = m_context.position();
936
        bool   doStroke = (m_context.pen().style() != Qt::NoPen);
937
        if (doStroke)
938
        {
939
                double x1 = currentPos.x();
940
                double y1 = currentPos.y();
941
                double x2 = params[1];
942
                double y2 = params[0];
943
                double  lineWidth = m_context.pen().width();
944
                QString lineColor = importColor(m_context.pen().color());
945
                int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, BaseX, BaseY, 10, 10, lineWidth, CommonStrings::None, lineColor, true);
946
                PageItem* ite = m_Doc->Items->at(z);
947
                ite->PoLine.resize(4);
948
                ite->PoLine.setPoint(0, FPoint(x1, y1));
949
                ite->PoLine.setPoint(1, FPoint(x1, y1));
950
                ite->PoLine.setPoint(2, FPoint(x2, y2));
951
                ite->PoLine.setPoint(3, FPoint(x2, y2));
952
                finishCmdParsing(ite);
953
                items.append(ite);
954
        }
955
        m_context.setPosition( QPoint(params[1], params[0]) );
956
}
957
 
958
void WMFImport::moveTo( QList<PageItem*>& /*items*/, long, short* params )
959
{
960
        m_context.setPosition( QPoint(params[1], params[0]) );
961
}
962
 
963
void WMFImport::ellipse( QList<PageItem*>& items, long, short* params )
964
{
965
        double BaseX = m_Doc->currentPage()->xOffset();
966
        double BaseY = m_Doc->currentPage()->yOffset();
967
        double rx = (params[ 1 ] - params[ 3 ]) / 2.0;
968
        double ry = (params[ 0 ] - params[ 2 ]) / 2.0;
969
        double px = (params[ 1 ] + params[ 3 ]) / 2.0 - rx;
970
        double py = (params[ 0 ] + params[ 2 ]) / 2.0 - ry;
971
        bool   doFill = m_context.brush().style() != Qt::NoBrush;
972
        bool   doStroke = m_context.pen().style() != Qt::NoPen;
973
        QString fillColor   = doFill ? importColor( m_context.brush().color() ) : CommonStrings::None;
974
        QString strokeColor = doStroke ? importColor( m_context.pen().color() ) : CommonStrings::None;
975
        double  lineWidth   = m_context.pen().width();
976
        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, BaseX, BaseY, rx * 2.0, ry * 2.0, lineWidth, fillColor, strokeColor, true);
977
        PageItem* ite = m_Doc->Items->at(z);
978
        QTransform mm(1.0, 0.0, 0.0, 1.0, px, py);
979
        ite->PoLine.map(mm);
980
        finishCmdParsing(ite);
981
        items.append(ite);
982
}
983
 
984
void WMFImport::polygon( QList<PageItem*>& items, long, short* params )
985
{
986
        //cerr << "WMFImport::polygon unimplemented" << endl;
987
        double  BaseX = m_Doc->currentPage()->xOffset();
988
        double  BaseY = m_Doc->currentPage()->yOffset();
989
        bool    doFill = m_context.brush().style() != Qt::NoBrush;
990
        bool    doStroke = m_context.pen().style() != Qt::NoPen;
991
        QString fillColor   = doFill ? importColor( m_context.brush().color() ) : CommonStrings::None;
992
        QString strokeColor = doStroke ? importColor( m_context.pen().color() ) : CommonStrings::None;
993
        double  lineWidth   = m_context.pen().width();
994
        if (doStroke && lineWidth <= 0.0 )
995
                lineWidth = 1.0;
996
        FPointArray paramPoints = pointsFromParam( params[0], &params[1] );
997
        FPointArray points      = pointsToPolyline( paramPoints, true );
998
        if( paramPoints.size() > 0 )
999
        {
1000
                int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, lineWidth, fillColor, strokeColor, true);
1001
                PageItem* ite = m_Doc->Items->at(z);
1002
                ite->PoLine = points;
1003
                ite->fillRule = !m_context.windingFill();
1004
                finishCmdParsing(ite);
1005
                items.append(ite);
1006
        }
1007
}
1008
 
1009
void WMFImport::polyPolygon( QList<PageItem*>& items, long num, short* params )
1010
{
1011
        int numPolys   = params[0];
1012
        int pointIndex = params[0] + 1;
1013
        for (int i = 0; i < numPolys; ++i)
1014
        {
1015
                short  numPoints  = params[i + 1];
1016
                short* paramArray = new short[1 + 2 * numPoints];
1017
                paramArray[0] = numPoints;
1018
                memcpy(&paramArray[1], &params[pointIndex], 2 * numPoints * sizeof(short));
1019
                polygon(items, num, paramArray);
1020
                delete[] paramArray;
1021
                pointIndex += (2 * numPoints);
1022
        }
1023
}
1024
 
1025
void WMFImport::polyline( QList<PageItem*>& items, long, short* params )
1026
{
1027
        //cerr << "WMFImport::polyline unimplemented" << endl;
1028
        double  BaseX = m_Doc->currentPage()->xOffset();
1029
        double  BaseY = m_Doc->currentPage()->yOffset();
1030
        bool    doStroke = m_context.pen().style() != Qt::NoPen;
1031
        QString fillColor   = CommonStrings::None;
1032
        QString strokeColor = doStroke ? importColor( m_context.pen().color() ) : CommonStrings::None;
1033
        double  lineWidth   = m_context.pen().width();
1034
        if (doStroke && lineWidth <= 0.0 )
1035
                lineWidth = 1.0;
1036
        FPointArray paramPoints = pointsFromParam( params[0], &params[1] );
1037
        FPointArray points      = pointsToPolyline( paramPoints, false );
1038
        if( paramPoints.size() > 0 )
1039
        {
1040
                int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, BaseX, BaseY, 10, 10, lineWidth, fillColor, strokeColor, true);
1041
                PageItem* ite = m_Doc->Items->at(z);
1042
                ite->PoLine = points;
1043
                finishCmdParsing(ite);
1044
                items.append(ite);
1045
        }
1046
}
1047
 
1048
void WMFImport::rectangle( QList<PageItem*>& items, long, short* params )
1049
{
1050
        //cerr << "WMFImport::rectangle unimplemented" << endl;
1051
        double  BaseX = m_Doc->currentPage()->xOffset();
1052
        double  BaseY = m_Doc->currentPage()->yOffset();
1053
        bool    doFill = m_context.brush().style() != Qt::NoBrush;
1054
        bool    doStroke = m_context.pen().style() != Qt::NoPen;
1055
        QString fillColor   = doFill ? importColor( m_context.brush().color() ) : CommonStrings::None;
1056
        QString strokeColor = doStroke ? importColor( m_context.pen().color() ) : CommonStrings::None;
1057
        double  lineWidth   = m_context.pen().width();
1058
        if (doStroke && lineWidth <= 0.0 )
1059
                lineWidth = 1.0;
1060
        double x = ((params[3] - params[1]) > 0) ? params[1] : params[3];
1061
        double y = ((params[2] - params[0]) > 0) ? params[0] : params[2];
1062
        double width  = fabs((double) params[3] - params[1]);
1063
        double height = fabs((double) params[2] - params[0]);
1064
        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, BaseX, BaseY, width, height, lineWidth, fillColor, strokeColor, true);
1065
        PageItem* ite = m_Doc->Items->at(z);
1066
        QTransform mm(1.0, 0.0, 0.0, 1.0, x, y);
1067
        ite->PoLine.map(mm);
1068
        finishCmdParsing(ite);
1069
        items.append(ite);
1070
}
1071
 
1072
void WMFImport::roundRect( QList<PageItem*>& items, long, short* params )
1073
{
1074
        //cerr << "WMFImport::roundRect unimplemented" << endl;
1075
        double  BaseX = m_Doc->currentPage()->xOffset();
1076
        double  BaseY = m_Doc->currentPage()->yOffset();
1077
        bool    doFill = m_context.brush().style() != Qt::NoBrush;
1078
        bool    doStroke = m_context.pen().style() != Qt::NoPen;
1079
        QString fillColor   = doFill ? importColor( m_context.brush().color() ) : CommonStrings::None;
1080
        QString strokeColor = doStroke ? importColor( m_context.pen().color() ) : CommonStrings::None;
1081
        double  lineWidth   = m_context.pen().width();
1082
        if (doStroke && lineWidth <= 0.0 )
1083
                lineWidth = 1.0;
1084
        double x = ((params[5] - params[3]) > 0) ? params[3] : params[5];
1085
        double y = ((params[4] - params[2]) > 0) ? params[2] : params[4];
1086
        double width  = fabs((double) params[5] - params[3]);
1087
        double height = fabs((double) params[4] - params[2]);
1088
        double rx     = params[1] / 2.0;
1089
        double ry     = params[0] / 2.0;
1090
        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, BaseX, BaseY, width, height, lineWidth, fillColor, strokeColor, true);
1091
        PageItem* ite = m_Doc->Items->at(z);
1092
        if ((rx != 0.0) || (ry != 0.0))
1093
        {
1094
                ite->setCornerRadius(qMax(rx, ry));
1095
                ite->SetFrameRound();
1096
                m_Doc->setRedrawBounding(ite);
1097
        }
1098
        QTransform mm(1.0, 0.0, 0.0, 1.0, x, y);
1099
        ite->PoLine.map(mm);
1100
        finishCmdParsing(ite);
1101
        items.append(ite);
1102
}
1103
 
1104
void WMFImport::arc( QList<PageItem*>& items, long, short* params )
1105
{
1106
        FPointArray  pointArray;
1107
        QPainterPath painterPath;
1108
        double  BaseX = m_Doc->currentPage()->xOffset();
1109
        double  BaseY = m_Doc->currentPage()->yOffset();
1110
        bool    doStroke = m_context.pen().style() != Qt::NoPen;
1111
        QString fillColor   = CommonStrings::None;
1112
        QString strokeColor = doStroke ? importColor( m_context.pen().color() ) : CommonStrings::None;
1113
        double  lineWidth   = m_context.pen().width();
1114
        if (doStroke && lineWidth <= 0.0 )
1115
                lineWidth = 1.0;
1116
        double  angleStart, angleLength;
1117
        double  x = ((params[7] - params[5]) > 0) ? params[5] : params[7];
1118
        double  y = ((params[6] - params[4]) > 0) ? params[4] : params[6];
1119
        double  xCenter = (params[5] + params[7]) / 2.0;
1120
        double  yCenter = (params[4] + params[6]) / 2.0;
1121
        double  xWidth  =  fabs((double) params[5] - params[7]);
1122
        double  yHeight =  fabs((double) params[4] - params[6]);
1123
        pointsToAngle(params[3] - xCenter, yCenter - params[2], params[1] - xCenter, yCenter - params[0], angleStart, angleLength);
1124
        painterPath.arcMoveTo(x, y, xWidth, yHeight, angleStart);
1125
        painterPath.arcTo(x, y, xWidth, yHeight, angleStart, angleLength);
1126
        pointArray.fromQPainterPath(painterPath);
1127
        if( pointArray.size() > 0 )
1128
        {
1129
                int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, BaseX, BaseY, 10, 10, lineWidth, fillColor, strokeColor, true);
1130
                PageItem* ite = m_Doc->Items->at(z);
1131
                ite->PoLine = pointArray;
1132
                finishCmdParsing(ite);
1133
                items.append(ite);
1134
        }
1135
}
1136
 
1137
void WMFImport::chord( QList<PageItem*>& items, long, short* params )
1138
{
1139
        QPointF      firstPoint;
1140
        FPointArray  pointArray;
1141
        QPainterPath painterPath;
1142
        double  BaseX = m_Doc->currentPage()->xOffset();
1143
        double  BaseY = m_Doc->currentPage()->yOffset();
1144
        bool    doFill   = m_context.brush().style() != Qt::NoBrush;
1145
        bool    doStroke = m_context.pen().style() != Qt::NoPen;
1146
        QString fillColor   = doFill ? importColor( m_context.brush().color() ) : CommonStrings::None;
1147
        QString strokeColor = doStroke ? importColor( m_context.pen().color() ) : CommonStrings::None;
1148
        double  lineWidth   = m_context.pen().width();
1149
        if (doStroke && lineWidth <= 0.0 )
1150
                lineWidth = 1.0;
1151
        double  angleStart, angleLength;
1152
        double  x = ((params[7] - params[5]) > 0) ? params[5] : params[7];
1153
        double  y = ((params[6] - params[4]) > 0) ? params[4] : params[6];
1154
        double  xCenter = (params[5] + params[7]) / 2.0;
1155
        double  yCenter = (params[4] + params[6]) / 2.0;
1156
        double  xWidth  =  fabs((double) params[5] - params[7]);
1157
        double  yHeight =  fabs((double) params[4] - params[6]);
1158
        pointsToAngle(params[3] - xCenter, yCenter - params[2], params[1] - xCenter, yCenter - params[0], angleStart, angleLength);
1159
        painterPath.arcMoveTo(x, y, xWidth, yHeight, angleStart);
1160
        firstPoint = painterPath.currentPosition();
1161
        painterPath.arcTo (x, y, xWidth, yHeight, angleStart, angleLength);
1162
        painterPath.lineTo(firstPoint);
1163
        pointArray.fromQPainterPath(painterPath);
1164
        if( pointArray.size() > 0 )
1165
        {
1166
                int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, lineWidth, fillColor, strokeColor, true);
1167
                PageItem* ite = m_Doc->Items->at(z);
1168
                ite->PoLine = pointArray;
1169
                finishCmdParsing(ite);
1170
                items.append(ite);
1171
        }
1172
}
1173
 
1174
void WMFImport::pie( QList<PageItem*>& items, long, short* params )
1175
{
1176
        QPointF      firstPoint;
1177
        FPointArray  pointArray;
1178
        QPainterPath painterPath;
1179
        double  BaseX = m_Doc->currentPage()->xOffset();
1180
        double  BaseY = m_Doc->currentPage()->yOffset();
1181
        bool    doFill   = m_context.brush().style() != Qt::NoBrush;
1182
        bool    doStroke = m_context.pen().style() != Qt::NoPen;
1183
        QString fillColor   = doFill ? importColor( m_context.brush().color() ) : CommonStrings::None;
1184
        QString strokeColor = doStroke ? importColor( m_context.pen().color() ) : CommonStrings::None;
1185
        double  lineWidth   = m_context.pen().width();
1186
        if (doStroke && lineWidth <= 0.0 )
1187
                lineWidth = 1.0;
1188
        double  angleStart, angleLength;
1189
        double  x = ((params[7] - params[5]) > 0) ? params[5] : params[7];
1190
        double  y = ((params[6] - params[4]) > 0) ? params[4] : params[6];
1191
        double  xCenter = (params[5] + params[7]) / 2.0;
1192
        double  yCenter = (params[4] + params[6]) / 2.0;
1193
        double  xWidth  =  fabs((double) params[5] - params[7]);
1194
        double  yHeight =  fabs((double) params[4] - params[6]);
1195
        pointsToAngle(params[3] - xCenter, yCenter - params[2], params[1] - xCenter, yCenter - params[0], angleStart, angleLength);
1196
        painterPath.arcMoveTo(x,y, xWidth, yHeight, angleStart);
1197
        firstPoint = painterPath.currentPosition();
1198
        painterPath.arcTo (x, y, xWidth, yHeight, angleStart, angleLength);
1199
        painterPath.lineTo(xCenter, yCenter);
1200
        painterPath.lineTo(firstPoint);
1201
        pointArray.fromQPainterPath(painterPath);
1202
        if( pointArray.size() > 0 )
1203
        {
1204
                int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, lineWidth, fillColor, strokeColor, true);
1205
                PageItem* ite = m_Doc->Items->at(z);
1206
                ite->PoLine = pointArray;
1207
                finishCmdParsing(ite);
1208
                items.append(ite);
1209
        }
1210
}
1211
 
1212
void WMFImport::setPolyFillMode( QList<PageItem*>& /*items*/, long, short* params )
1213
{
1214
        m_context.setWindingFill( params[0] );
1215
}
1216
 
1217
void WMFImport::setBkColor( QList<PageItem*>& /*items*/, long, short* params )
1218
{
1219
        m_context.setBackgroundColor( colorFromParam( params ) );
1220
}
1221
 
1222
void WMFImport::setBkMode( QList<PageItem*>& /*items*/, long, short* params )
1223
{
1224
        if ( params[ 0 ]==1 )
1225
                m_context.setBackgroundMode( Qt::TransparentMode );
1226
        else
1227
                m_context.setBackgroundMode( Qt::OpaqueMode );
1228
}
1229
 
1230
void WMFImport::saveDC( QList<PageItem*>& /*items*/, long, short* )
1231
{
1232
        m_context.save();
1233
}
1234
 
1235
void WMFImport::restoreDC( QList<PageItem*>& /*items*/, long, short *params )
1236
{
1237
        for ( int i=0; i > params[ 0 ] ; i-- )
1238
                m_context.restore();
1239
}
1240
 
1241
void WMFImport::intersectClipRect( QList<PageItem*>& /*items*/, long, short* /*params*/ )
1242
{
1243
        cerr << "WMFImport::intersectClipRect unimplemented" << endl;
1244
}
1245
 
1246
void WMFImport::excludeClipRect( QList<PageItem*>& /*items*/, long, short* /*params*/ )
1247
{
1248
        cerr << "WMFImport::excludeClipRect unimplemented" << endl;
1249
}
1250
 
1251
void WMFImport::setTextColor( QList<PageItem*>& /*items*/, long, short* params )
1252
{
1253
        m_context.setTextColor( colorFromParam(params) );
1254
}
1255
 
1256
void WMFImport::setTextAlign( QList<PageItem*>& /*items*/, long, short* params )
1257
{
1258
        m_context.setTextAlign(params[ 0 ]);
1259
}
1260
 
1261
void WMFImport::textOut( QList<PageItem*>& items, long num, short* params )
1262
{
1263
        short *copyParm = new short[num + 1];
1264
 
1265
        // re-order parameters
1266
        int idxOffset = (params[0] / 2) + 1 + (params[0] & 1);
1267
        copyParm[0] = params[idxOffset];
1268
        copyParm[1] = params[idxOffset + 1];
1269
        copyParm[2] = params[0];
1270
        copyParm[3] = 0;
1271
        memcpy( &copyParm[4], &params[1], params[0] );
1272
 
1273
        extTextOut(items, num + 1, copyParm );
1274
        delete [] copyParm;
1275
}
1276
 
1277
void WMFImport::extTextOut( QList<PageItem*>& items, long num, short* params )
1278
{
1279
        QString    textString;
1280
        double  BaseX = m_Doc->currentPage()->xOffset();
1281
        double  BaseY = m_Doc->currentPage()->yOffset();
1282
 
1283
        if (params[3] & 0x0010) // ETO_GLYPH_INDEX
1284
        {
1285
                cerr << "WMFImport::extTextOut: ETO_GLYPH_INDEX option not supported " << endl;
1286
                unsupported = true;
1287
                return;
1288
        }
1289
 
1290
        // ETO_CLIPPED flag add 4 parameters
1291
        char* ptStr = (params[3] & 0x0004) ? ((char*)&params[8]) : ((char*)&params[4]);
1292
        QByteArray textArray( ptStr, params[2] );
1293
 
1294
        QTextCodec* codec = codecFromCharset( m_context.textCharSet() );
1295
        if (codec)
1296
                textString = codec->toUnicode(textArray);
1297
        else if ( m_context.textCharSet() == SYMBOL_CHARSET )
1298
                textString = symbolToUnicode(textArray);
1299
        else
1300
                textString = QString::fromLocal8Bit(textArray.data());
1301
 
1302
        QFontMetrics fm( m_context.font() );
1303
        int width  = fm.width(textString) + fm.descent();  // because fm.width(text) isn't rigth with Italic text
1304
        /*int height = fm.height();
1305
        int ascent = fm.ascent();*/
1306
 
1307
        double startX = params[1], startY = params[0];
1308
        int    textAlign    = m_context.textAlign();
1309
        double textRotation = m_context.textRotation();
1310
        if ( textAlign & 0x01 ) {       // (left, top) position = current logical position
1311
                QPoint pos = m_context.position();
1312
                startX = pos.x();
1313
                startY = pos.y();
1314
        }
1315
 
1316
        m_context.save();
1317
        // A bit hacky but should be sufficient to have text not flipped
1318
        // top down in some wmfs (see cell.wmf sample from libwmf)
1319
        if ( m_context.worldMatrix().m22() < 0.0)
1320
        {
1321
                m_context.translate(startX, startY);
1322
                m_context.scale (1.0, -1.0);
1323
                m_context.translate( -startX, -startY);
1324
        }
1325
        if ( textRotation != 0.0) {
1326
                m_context.translate(startX, startY);
1327
                m_context.rotate ( textRotation );
1328
                m_context.translate( -startX, -startY);
1329
        }
1330
 
1331
        if ( (textAlign & 0x04) && (textAlign & 0x02) ) // TA_CENTER 0x06
1332
                startX -= (width / 2);
1333
        else if ( textAlign & 0x02 ) // TA_RIGHT 0x02
1334
                startX -= width;
1335
        if ( textAlign == 0 ) // TA_TOP                       
1336
                startY += fm.ascent();
1337
 
1338
        bool eto_empty = (params[3] == 0);
1339
        bool eto_clipped_set = (params[3] & 0x0004);
1340
        bool eto_pdy_set     = (params[3] & 0x2000);
1341
 
1342
        int  idxOffset = (params[ 2 ] / 2) + 4 + (params[ 2 ] & 1) + (eto_clipped_set ? 4 : 0);
1343
        int  minParams = eto_pdy_set ? (idxOffset + 2 * (params[2] - 1)) : (idxOffset + params[2]);
1344
        bool useCharInterdistances = (num >= minParams) && (eto_empty || eto_pdy_set);
1345
        if ((params[2] > 1) && useCharInterdistances)
1346
        {
1347
                double xpos  = startX;
1348
                double ypos  = startY;
1349
                double lineWidth = 0.0;
1350
                FPointArray textPath;
1351
                QString textColor = importColor( m_context.textColor() );
1352
                for (int index = 0; (index < params[2] && index < textString.length()); ++index)
1353
                {
1354
                        QPainterPath painterPath;
1355
                        if (index > 0 && eto_pdy_set)
1356
                        {
1357
                                xpos += params[idxOffset + index * 2 - 1];
1358
                                ypos += params[idxOffset + index * 2];
1359
                        }
1360
                        else if (index > 0)
1361
                                xpos += params[idxOffset + index - 1];
1362
                        painterPath.addText(xpos, ypos, m_context.font(), textString.at(index));
1363
                        textPath.fromQPainterPath(painterPath);
1364
                        if (textPath.size() > 0)
1365
                        {
1366
                                int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, lineWidth, textColor, CommonStrings::None, true);
1367
                                PageItem* ite = m_Doc->Items->at(z);
1368
                                ite->PoLine = textPath;
1369
                                finishCmdParsing(ite);
1370
                                items.append(ite);
1371
                        }
1372
                }
1373
        }
1374
        else
1375
        {
1376
                FPointArray textPath;
1377
                QString textColor = importColor( m_context.textColor() );
1378
                QPainterPath painterPath;
1379
                painterPath.addText( startX, startY, m_context.font(), textString );
1380
                textPath.fromQPainterPath(painterPath);
1381
                if (textPath.size() > 0)
1382
                {
1383
                        double  lineWidth = 0.0;
1384
                        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, lineWidth, textColor, CommonStrings::None, true);
1385
                        PageItem* ite = m_Doc->Items->at(z);
1386
                        ite->PoLine = textPath;
1387
                        finishCmdParsing(ite);
1388
                        items.append(ite);
1389
                }
1390
        }
1391
        m_context.restore();
1392
}
1393
 
1394
void WMFImport::selectObject( QList<PageItem*>& /*items*/, long, short* params )
1395
{
1396
        int idx = params[ 0 ];
1397
        if ( idx >= 0 && idx < MAX_OBJHANDLE && m_ObjHandleTab[ idx ] )
1398
                m_ObjHandleTab[ idx ]->apply( m_context );
1399
}
1400
 
1401
void WMFImport::deleteObject( QList<PageItem*>& /*items*/, long, short* params )
1402
{
1403
        deleteHandle( params[ 0 ] );
1404
}
1405
 
1406
void WMFImport::createEmptyObject( QList<PageItem*>& /*items*/, long, short* )
1407
{
1408
        // allocation of an empty object (to keep object counting in sync)
1409
        WmfObjPenHandle* handle = new WmfObjPenHandle();
1410
        addHandle( handle );
1411
        cerr << "WMFImport: unimplemented createObject " << endl;
1412
}
1413
 
1414
void WMFImport::createBrushIndirect( QList<PageItem*>& /*items*/, long, short* params )
1415
{
1416
        static Qt::BrushStyle hatchedStyleTab[] =
1417
        {
1418
                Qt::HorPattern,
1419
                Qt::FDiagPattern,
1420
                Qt::BDiagPattern,
1421
                Qt::CrossPattern,
1422
                Qt::DiagCrossPattern
1423
        };
1424
        static Qt::BrushStyle styleTab[] =
1425
        { Qt::SolidPattern,
1426
          Qt::NoBrush,
1427
          Qt::FDiagPattern,   /* hatched */
1428
          Qt::Dense4Pattern,  /* should be custom bitmap pattern */
1429
          Qt::HorPattern,     /* should be BS_INDEXED (?) */
1430
          Qt::VerPattern,     /* should be device-independent bitmap */
1431
          Qt::Dense6Pattern,  /* should be device-independent packed-bitmap */
1432
          Qt::Dense2Pattern,  /* should be BS_PATTERN8x8 */
1433
          Qt::Dense3Pattern   /* should be device-independent BS_DIBPATTERN8x8 */
1434
        };
1435
        Qt::BrushStyle style;
1436
        short arg;
1437
        WmfObjBrushHandle* handle = new WmfObjBrushHandle();
1438
        addHandle( handle );
1439
 
1440
        arg = params[0];
1441
        if ( arg == 2 )
1442
        {
1443
                arg = params[3];
1444
                if ( arg >= 0 && arg < 5 )
1445
                        style = hatchedStyleTab[ arg ];
1446
                else
1447
                {
1448
                        cerr << "WMFImport::createBrushIndirect: invalid hatched brush " << arg << endl;
1449
                        style = Qt::SolidPattern;
1450
                }
1451
        }
1452
        else if ( arg >= 0 && arg < 9 )
1453
                style = styleTab[arg];
1454
        else
1455
        {
1456
                cerr << "WMFImport::createBrushIndirect: invalid brush " << arg << endl;
1457
                style = Qt::SolidPattern;
1458
        }
1459
        handle->brush.setStyle( style );
1460
        handle->brush.setColor( colorFromParam( params+1 ) );
1461
}
1462
 
1463
void WMFImport::createPenIndirect( QList<PageItem*>& /*items*/, long, short* params )
1464
{
1465
        static Qt::PenStyle styleTab[] = { Qt::SolidLine, Qt::DashLine, Qt::DotLine, Qt::DashDotLine, Qt::DashDotDotLine,
1466
          Qt::NoPen, Qt::SolidLine };
1467
        Qt::PenStyle style;
1468
        WmfObjPenHandle* handle = new WmfObjPenHandle();
1469
        addHandle( handle );
1470
 
1471
        if ( params[0] >= 0 && params[0] < 6 )
1472
                style = styleTab[ params[0] ];
1473
        else
1474
        {
1475
                cerr << "WMFImport::createPenIndirect: invalid pen " << params[ 0 ] << endl;
1476
                style = Qt::SolidLine;
1477
        }
1478
 
1479
        handle->pen.setStyle( style );
1480
        handle->pen.setWidth( params[1] );
1481
        handle->pen.setColor( colorFromParam( params+3 ) );
1482
        handle->pen.setCapStyle( Qt::RoundCap );
1483
}
1484
 
1485
void WMFImport::createFontIndirect( QList<PageItem*>& /*items*/, long , short* params)
1486
{
1487
        WmfObjFontHandle* handle = new WmfObjFontHandle();
1488
        addHandle( handle );
1489
 
1490
        QString family( (const char*)&params[ 9 ] );
1491
 
1492
        handle->rotation = -params[ 2 ]  / 10; // text rotation (in 1/10 degree)
1493
        handle->font.setFamily( family );
1494
        handle->font.setStyleStrategy( QFont::PreferOutline );
1495
        handle->font.setFixedPitch( ((params[ 8 ] & 0x01) == 0) );
1496
        // TODO: investigation why some test case need -2. (size of font in logical point)
1497
        int fontSize = (params[0] != 0) ? (qAbs(params[0]) - 2) : 12;
1498
        handle->font.setPixelSize( fontSize );
1499
        handle->font.setWeight( (params[ 4 ] >> 3) );
1500
        handle->font.setItalic( (params[ 5 ] & 0x01) );
1501
        handle->font.setUnderline( (params[ 5 ] & 0x100) );
1502
        handle->font.setStrikeOut( (params[ 6 ] & 0x01) );
1503
        handle->charset = (params[ 6 ] & 0xFF00) >> 8;
1504
}
1505
 
1506
void WMFImport::noop( QList<PageItem*>& /*items*/, long, short* )
1507
{
1508
}
1509
 
1510
void WMFImport::end( QList<PageItem*>& /*items*/, long, short* )
1511
{
1512
        //cerr << "WMFImport::end unimplemented" << endl;
1513
}
1514
 
1515
void WMFImport::addHandle( WmfObjHandle* handle )
1516
{
1517
        int idx;
1518
 
1519
        for ( idx =0; idx < MAX_OBJHANDLE ; idx++ )
1520
                if ( m_ObjHandleTab[ idx ] == NULL )  break;
1521
 
1522
        if ( idx < MAX_OBJHANDLE )
1523
                m_ObjHandleTab[ idx ] = handle;
1524
        else
1525
                cerr << "WMFImport error: handle table full !" << endl;
1526
}
1527
 
1528
void WMFImport::deleteHandle( int idx )
1529
{
1530
        if ( idx >= 0 && idx < MAX_OBJHANDLE && m_ObjHandleTab[ idx ] )
1531
        {
1532
                delete m_ObjHandleTab[ idx ];
1533
                m_ObjHandleTab[ idx ] = NULL;
1534
        }
1535
}
1536
 
1537
unsigned short WMFImport::calcCheckSum( WmfPlaceableHeader* apmfh )
1538
{
1539
        WORD16*  lpWord;
1540
        WORD16   wResult, i;
1541
 
1542
        // Start with the first word
1543
        wResult = *( lpWord = ( WORD16* )( apmfh ) );
1544
        // XOR in each of the other 9 words
1545
        for( i=1; i<=9; i++ )
1546
        {
1547
                wResult ^= lpWord[ i ];
1548
        }
1549
        return wResult;
1550
}
1551
 
1552
int WMFImport::findFunc( unsigned short aFunc ) const
1553
{
1554
        int i = 0;
1555
 
1556
        for ( i=0; metaFuncTab[ i ].name; i++ )
1557
                if ( metaFuncTab[ i ].func == aFunc ) return i;
1558
 
1559
        // here : unknown function
1560
        return i;
1561
}
1562
 
1563
unsigned int WMFImport::toDWord( short* params )
1564
{
1565
        unsigned int l;
1566
#if !defined( WORDS_BIGENDIAN )
1567
        l = *( unsigned int* )( params );
1568
#else
1569
        char *bytes;
1570
        char swap[ 4 ];
1571
        bytes = ( char* )params;
1572
        swap[ 0 ] = bytes[ 2 ];
1573
        swap[ 1 ] = bytes[ 3 ];
1574
        swap[ 2 ] = bytes[ 0 ];
1575
        swap[ 3 ] = bytes[ 1 ];
1576
        l = *( unsigned int* )( swap );
1577
#endif
1578
        return l;
1579
}