00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <math.h>
00022
00023 #include <QFileInfo>
00024 #include <QImage>
00025 #include <QMatrix>
00026 #include <q3ptrlist.h>
00027 #include <q3pointarray.h>
00028 #include <QPainter>
00029 #include <QDataStream>
00030 #include <QByteArray>
00031 #include <kdebug.h>
00032
00033 #include "kowmfreadprivate.h"
00034 #include "kowmfread.h"
00035
00036
00037 KoWmfReadPrivate::KoWmfReadPrivate()
00038 {
00039 mNbrFunc = 0;
00040 mValid = false;
00041 mStandard = false;
00042 mPlaceable = false;
00043 mEnhanced = false;
00044 mBuffer = 0;
00045 mObjHandleTab = 0;
00046 }
00047
00048
00049 KoWmfReadPrivate::~KoWmfReadPrivate()
00050 {
00051 if ( mObjHandleTab != 0 ) {
00052 for ( int i=0 ; i < mNbrObject ; i++ ) {
00053 if ( mObjHandleTab[i] != 0 )
00054 delete mObjHandleTab[i];
00055 }
00056 delete[] mObjHandleTab;
00057 }
00058 if ( mBuffer != 0 ) {
00059 mBuffer->close();
00060 delete mBuffer;
00061 }
00062 }
00063
00064
00065 bool KoWmfReadPrivate::load( const QByteArray& array )
00066 {
00067
00068 if ( mBuffer != 0 ) {
00069 mBuffer->close();
00070 delete mBuffer;
00071 }
00072
00073
00074 QByteArray nonConstArray( array );
00075 mBuffer = new QBuffer( &nonConstArray );
00076 mBuffer->open( QIODevice::ReadOnly );
00077
00078
00079 WmfEnhMetaHeader eheader;
00080 WmfMetaHeader header;
00081 WmfPlaceableHeader pheader;
00082 unsigned short checksum;
00083 int filePos;
00084
00085 QDataStream st( mBuffer );
00086 st.setByteOrder( QDataStream::LittleEndian );
00087 mStackOverflow = mWinding = false;
00088 mTextAlign = mTextRotation = 0;
00089 mTextColor = Qt::black;
00090 mValid = false;
00091 mStandard = false;
00092 mPlaceable = false;
00093 mEnhanced = false;
00094
00095
00096 st >> pheader.key;
00097 if ( pheader.key==( quint32 )APMHEADER_KEY ) {
00098 mPlaceable = true;
00099 st >> pheader.handle;
00100 st >> pheader.left;
00101 st >> pheader.top;
00102 st >> pheader.right;
00103 st >> pheader.bottom;
00104 st >> pheader.inch;
00105 st >> pheader.reserved;
00106 st >> pheader.checksum;
00107 checksum = calcCheckSum( &pheader );
00108 if ( pheader.checksum!=checksum ) {
00109 return false;
00110 }
00111 st >> header.fileType;
00112 st >> header.headerSize;
00113 st >> header.version;
00114 st >> header.fileSize;
00115 st >> header.numOfObjects;
00116 st >> header.maxRecordSize;
00117 st >> header.numOfParameters;
00118 mNbrObject = header.numOfObjects;
00119 mBBox.setLeft( pheader.left );
00120 mBBox.setTop( pheader.top );
00121 mBBox.setRight( pheader.right );
00122 mBBox.setBottom( pheader.bottom );
00123 mDpi = pheader.inch;
00124 }
00125 else {
00126 mBuffer->reset();
00127
00128 filePos = mBuffer->pos();
00129 st >> eheader.recordType;
00130 st >> eheader.recordSize;
00131 st >> eheader.boundsLeft;
00132 st >> eheader.boundsTop;
00133 st >> eheader.boundsRight;
00134 st >> eheader.boundsBottom;
00135 st >> eheader.frameLeft;
00136 st >> eheader.frameTop;
00137 st >> eheader.frameRight;
00138 st >> eheader.frameBottom;
00139 st >> eheader.signature;
00140 if ( eheader.signature==ENHMETA_SIGNATURE ) {
00141 mEnhanced = true;
00142 st >> eheader.version;
00143 st >> eheader.size;
00144 st >> eheader.numOfRecords;
00145 st >> eheader.numHandles;
00146 st >> eheader.reserved;
00147 st >> eheader.sizeOfDescription;
00148 st >> eheader.offsetOfDescription;
00149 st >> eheader.numPaletteEntries;
00150 st >> eheader.widthDevicePixels;
00151 st >> eheader.heightDevicePixels;
00152 st >> eheader.widthDeviceMM;
00153 st >> eheader.heightDeviceMM;
00154 }
00155 else {
00156
00157 mStandard = true;
00158 mBuffer->seek( filePos );
00159 st >> header.fileType;
00160 st >> header.headerSize;
00161 st >> header.version;
00162 st >> header.fileSize;
00163 st >> header.numOfObjects;
00164 st >> header.maxRecordSize;
00165 st >> header.numOfParameters;
00166 mNbrObject = header.numOfObjects;
00167 }
00168 }
00169 mOffsetFirstRecord = mBuffer->pos();
00170
00171
00172 if ( ((header.headerSize == 9) && (header.numOfParameters == 0)) || (mPlaceable) ) {
00173
00174 mValid = true;
00175 }
00176 else {
00177 kDebug() << "KoWmfReadPrivate : incorrect file format !" << endl;
00178 }
00179
00180
00181 if ( (mValid) && (mStandard) ) {
00182 quint16 numFunction = 1;
00183 quint32 size;
00184 bool firstOrg=true, firstExt=true;
00185
00186
00187 while ( numFunction ) {
00188 filePos = mBuffer->pos();
00189 st >> size >> numFunction;
00190
00191 if ( size == 0 ) {
00192 kDebug() << "KoWmfReadPrivate : incorrect file!" << endl;
00193 mValid = 0;
00194 break;
00195 }
00196
00197 numFunction &= 0xFF;
00198 if ( numFunction == 11 ) {
00199 qint16 top, left;
00200
00201 st >> top >> left;
00202 if ( firstOrg ) {
00203 firstOrg = false;
00204 mBBox.setLeft( left );
00205 mBBox.setTop( top );
00206 }
00207 else {
00208 if ( left < mBBox.left() ) mBBox.setLeft( left );
00209 if ( top < mBBox.top() ) mBBox.setTop( top );
00210 }
00211 }
00212 if ( numFunction == 12 ) {
00213 qint16 width, height;
00214
00215 st >> height >> width;
00216 if ( width < 0 ) width = -width;
00217 if ( height < 0 ) height = -height;
00218 if ( firstExt ) {
00219 firstExt = false;
00220 mBBox.setWidth( width );
00221 mBBox.setHeight( height );
00222 }
00223 else {
00224 if ( width > mBBox.width() ) mBBox.setWidth( width );
00225 if ( height > mBBox.height() ) mBBox.setHeight( height );
00226 }
00227 }
00228 mBuffer->seek( filePos + (size<<1) );
00229
00230 }
00231 }
00232
00233 return (mValid);
00234 }
00235
00236
00237 bool KoWmfReadPrivate::play( KoWmfRead* readWmf )
00238 {
00239 if ( !(mValid) ) {
00240 kDebug() << "KoWmfReadPrivate::play : invalid WMF file" << endl;
00241 return false;
00242 }
00243
00244 if ( mNbrFunc ) {
00245 if ( (mStandard) ) {
00246 kDebug() << "Standard : " << mBBox.left() << " " << mBBox.top() << " " << mBBox.width() << " " << mBBox.height() << endl;
00247 }
00248 else {
00249 kDebug() << "DPI : " << mDpi << " : " << mBBox.left() << " " << mBBox.top() << " " << mBBox.width() << " " << mBBox.height() << endl;
00250 kDebug() << "inch : " << mBBox.width()/mDpi << " " << mBBox.height()/mDpi << endl;
00251 kDebug() << "mm : " << mBBox.width()*25.4/mDpi << " " << mBBox.height()*25.4/mDpi << endl;
00252 }
00253 kDebug() << mValid << " " << mStandard << " " << mPlaceable << endl;
00254 }
00255
00256
00257 mObjHandleTab = new KoWmfHandle* [ mNbrObject ];
00258 for ( int i=0; i < mNbrObject ; i++ ) {
00259 mObjHandleTab[ i ] = 0;
00260 }
00261
00262 quint16 numFunction;
00263 quint32 size;
00264 int bufferOffset, j;
00265
00266
00267 QDataStream st( mBuffer );
00268 st.setByteOrder( QDataStream::LittleEndian );
00269
00270 mReadWmf = readWmf;
00271 mWindow = mBBox;
00272 if ( mReadWmf->begin() ) {
00273
00274 mBuffer->seek( mOffsetFirstRecord );
00275 numFunction = j = 1;
00276 mWinding = false;
00277
00278 while ( ( numFunction ) && ( !mStackOverflow ) ) {
00279 bufferOffset = mBuffer->pos();
00280 st >> size >> numFunction;
00281
00286 numFunction &= 0xFF;
00287 if ( numFunction > 0x5F ) {
00288 numFunction -= 0x90;
00289 }
00290 if ( (numFunction > 111) || (koWmfFunc[ numFunction ].method == 0) ) {
00291
00292 kDebug() << "KoWmfReadPrivate::paint : BROKEN WMF file" << endl;
00293 mValid = false;
00294 break;
00295 }
00296
00297 if ( mNbrFunc ) {
00298
00299 if ( (j+12) > mNbrFunc ) {
00300
00301 int offBuff = mBuffer->pos();
00302 quint16 param;
00303
00304 kDebug() << j << " : " << numFunction << " : ";
00305 for ( quint16 i=0 ; i < (size-3) ; i++ ) {
00306 st >> param;
00307 kDebug() << param << " ";
00308 }
00309 kDebug() << endl;
00310 mBuffer->seek( offBuff );
00311 }
00312 if ( j >= mNbrFunc ) {
00313 break;
00314 }
00315 j++;
00316 }
00317
00318
00319 (this->*koWmfFunc[ numFunction ].method)( size, st );
00320
00321 mBuffer->seek( bufferOffset + (size<<1) );
00322 }
00323
00324 mReadWmf->end();
00325 }
00326
00327 for ( int i=0 ; i < mNbrObject ; i++ ) {
00328 if ( mObjHandleTab[ i ] != 0 )
00329 delete mObjHandleTab[ i ];
00330 }
00331 delete[] mObjHandleTab;
00332 mObjHandleTab = 0;
00333
00334 return true;
00335 }
00336
00337
00338
00339
00340
00341 void KoWmfReadPrivate::setWindowOrg( quint32, QDataStream& stream )
00342 {
00343 qint16 top, left;
00344
00345 stream >> top >> left;
00346 mReadWmf->setWindowOrg( left, top );
00347 mWindow.setLeft( left );
00348 mWindow.setTop( top );
00349
00350 }
00351
00352
00353
00354
00355 void KoWmfReadPrivate::setWindowExt( quint32, QDataStream& stream )
00356 {
00357 qint16 width, height;
00358
00359
00360 stream >> height >> width;
00361 mReadWmf->setWindowExt( width, height );
00362 mWindow.setWidth( width );
00363 mWindow.setHeight( height );
00364
00365 }
00366
00367
00368 void KoWmfReadPrivate::OffsetWindowOrg( quint32, QDataStream &stream )
00369 {
00370 qint16 offTop, offLeft;
00371
00372 stream >> offTop >> offLeft;
00373 mReadWmf->setWindowOrg( mWindow.left() + offLeft, mWindow.top() + offTop );
00374 mWindow.setLeft( mWindow.left() + offLeft );
00375 mWindow.setTop( mWindow.top() + offTop );
00376 }
00377
00378
00379 void KoWmfReadPrivate::ScaleWindowExt( quint32, QDataStream &stream )
00380 {
00381 qint16 width, height;
00382 qint16 heightDenom, heightNum, widthDenom, widthNum;
00383
00384 stream >> heightDenom >> heightNum >> widthDenom >> widthNum;
00385
00386 if ( ( widthDenom != 0 ) && ( heightDenom != 0 ) ) {
00387 width = (mWindow.width() * widthNum) / widthDenom;
00388 height = (mWindow.height() * heightNum) / heightDenom;
00389 mReadWmf->setWindowExt( width, height );
00390 mWindow.setWidth( width );
00391 mWindow.setHeight( height );
00392 }
00393
00394 }
00395
00396
00397
00398
00399
00400 void KoWmfReadPrivate::lineTo( quint32, QDataStream& stream )
00401 {
00402 qint16 top, left;
00403
00404 stream >> top >> left;
00405 mReadWmf->lineTo( left, top );
00406 }
00407
00408
00409 void KoWmfReadPrivate::moveTo( quint32, QDataStream& stream )
00410 {
00411 qint16 top, left;
00412
00413 stream >> top >> left;
00414 mReadWmf->moveTo( left, top );
00415 }
00416
00417
00418 void KoWmfReadPrivate::ellipse( quint32, QDataStream& stream )
00419 {
00420 qint16 top, left, right, bottom;
00421
00422 stream >> bottom >> right >> top >> left;
00423 mReadWmf->drawEllipse( left, top, right-left, bottom-top );
00424 }
00425
00426
00427 void KoWmfReadPrivate::polygon( quint32, QDataStream& stream )
00428 {
00429 quint16 num;
00430
00431 stream >> num;
00432
00433 QPolygon pa( num );
00434
00435 pointArray( stream, pa );
00436 mReadWmf->drawPolygon( pa, mWinding );
00437 }
00438
00439
00440 void KoWmfReadPrivate::polyPolygon( quint32, QDataStream& stream )
00441 {
00442 quint16 numberPoly;
00443 quint16 sizePoly;
00444 Q3PtrList<QPolygon> listPa;
00445
00446 stream >> numberPoly;
00447
00448 listPa.setAutoDelete( true );
00449 for ( int i=0 ; i < numberPoly ; i++ ) {
00450 stream >> sizePoly;
00451 listPa.append( new QPolygon( sizePoly ) );
00452 }
00453
00454
00455 QPolygon *pa;
00456 for ( pa = listPa.first() ; pa ; pa = listPa.next() ) {
00457 pointArray( stream, *pa );
00458 }
00459
00460
00461 mReadWmf->drawPolyPolygon( listPa, mWinding );
00462 listPa.clear();
00463 }
00464
00465
00466 void KoWmfReadPrivate::polyline( quint32, QDataStream& stream )
00467 {
00468 quint16 num;
00469
00470 stream >> num;
00471 QPolygon pa( num );
00472
00473 pointArray( stream, pa );
00474 mReadWmf->drawPolyline( pa );
00475 }
00476
00477
00478 void KoWmfReadPrivate::rectangle( quint32, QDataStream& stream )
00479 {
00480 qint16 top, left, right, bottom;
00481
00482 stream >> bottom >> right >> top >> left;
00483 mReadWmf->drawRect( left, top, right-left, bottom-top );
00484 }
00485
00486
00487 void KoWmfReadPrivate::roundRect( quint32, QDataStream& stream )
00488 {
00489 int xRnd = 0, yRnd = 0;
00490 quint16 widthCorner, heightCorner;
00491 qint16 top, left, right, bottom;
00492
00493 stream >> heightCorner >> widthCorner;
00494 stream >> bottom >> right >> top >> left;
00495
00496
00497 if ( (right - left) != 0 )
00498 xRnd = (widthCorner * 100) / (right - left);
00499 if ( (bottom - top) != 0 )
00500 yRnd = (heightCorner * 100) / (bottom - top);
00501
00502 mReadWmf->drawRoundRect( left, top, right-left, bottom-top, xRnd, yRnd );
00503 }
00504
00505
00506 void KoWmfReadPrivate::arc( quint32, QDataStream& stream )
00507 {
00508 int xCenter, yCenter, angleStart, aLength;
00509 qint16 topEnd, leftEnd, topStart, leftStart;
00510 qint16 top, left, right, bottom;
00511
00512 stream >> topEnd >> leftEnd >> topStart >> leftStart;
00513 stream >> bottom >> right >> top >> left;
00514
00515 xCenter = left + ((right-left) / 2);
00516 yCenter = top + ((bottom-top) / 2);
00517 xyToAngle ( leftStart-xCenter, yCenter-topStart, leftEnd-xCenter, yCenter-topEnd, angleStart, aLength );
00518
00519 mReadWmf->drawArc( left, top, right-left, bottom-top, angleStart, aLength);
00520 }
00521
00522
00523 void KoWmfReadPrivate::chord( quint32, QDataStream& stream )
00524 {
00525 int xCenter, yCenter, angleStart, aLength;
00526 qint16 topEnd, leftEnd, topStart, leftStart;
00527 qint16 top, left, right, bottom;
00528
00529 stream >> topEnd >> leftEnd >> topStart >> leftStart;
00530 stream >> bottom >> right >> top >> left;
00531
00532 xCenter = left + ((right-left) / 2);
00533 yCenter = top + ((bottom-top) / 2);
00534 xyToAngle ( leftStart-xCenter, yCenter-topStart, leftEnd-xCenter, yCenter-topEnd, angleStart, aLength );
00535
00536 mReadWmf->drawChord( left, top, right-left, bottom-top, angleStart, aLength);
00537 }
00538
00539
00540 void KoWmfReadPrivate::pie( quint32, QDataStream& stream )
00541 {
00542 int xCenter, yCenter, angleStart, aLength;
00543 qint16 topEnd, leftEnd, topStart, leftStart;
00544 qint16 top, left, right, bottom;
00545
00546 stream >> topEnd >> leftEnd >> topStart >> leftStart;
00547 stream >> bottom >> right >> top >> left;
00548
00549 xCenter = left + ((right-left) / 2);
00550 yCenter = top + ((bottom-top) / 2);
00551 xyToAngle ( leftStart-xCenter, yCenter-topStart, leftEnd-xCenter, yCenter-topEnd, angleStart, aLength );
00552
00553 mReadWmf->drawPie( left, top, right-left, bottom-top, angleStart, aLength);
00554 }
00555
00556
00557 void KoWmfReadPrivate::setPolyFillMode( quint32, QDataStream& stream )
00558 {
00559 quint16 winding;
00560
00561 stream >> winding;
00562 mWinding = (winding != 0);
00563 }
00564
00565
00566 void KoWmfReadPrivate::setBkColor( quint32, QDataStream& stream )
00567 {
00568 quint32 color;
00569
00570 stream >> color;
00571 mReadWmf->setBackgroundColor( qtColor( color ) );
00572 }
00573
00574
00575 void KoWmfReadPrivate::setBkMode( quint32, QDataStream& stream )
00576 {
00577 quint16 bkMode;
00578
00579 stream >> bkMode;
00580 if ( bkMode == 1 )
00581 mReadWmf->setBackgroundMode( Qt::TransparentMode );
00582 else
00583 mReadWmf->setBackgroundMode( Qt::OpaqueMode );
00584 }
00585
00586
00587 void KoWmfReadPrivate::setPixel( quint32, QDataStream& stream )
00588 {
00589 qint16 top, left;
00590 quint32 color;
00591
00592 stream >> color >> top >> left;
00593
00594 QPen oldPen = mReadWmf->pen();
00595 QPen pen = oldPen;
00596 pen.setColor( qtColor( color ) );
00597 mReadWmf->setPen( pen );
00598 mReadWmf->moveTo( left, top );
00599 mReadWmf->lineTo( left, top );
00600 mReadWmf->setPen( oldPen );
00601 }
00602
00603
00604 void KoWmfReadPrivate::setRop( quint32, QDataStream& stream )
00605 {
00606 quint16 rop;
00607
00608 stream >> rop;
00609 mReadWmf->setCompositionMode( winToQtComposition( rop ) );
00610 }
00611
00612
00613 void KoWmfReadPrivate::saveDC( quint32, QDataStream& )
00614 {
00615 mReadWmf->save();
00616 }
00617
00618
00619 void KoWmfReadPrivate::restoreDC( quint32, QDataStream& stream )
00620 {
00621 qint16 num;
00622
00623 stream >> num;
00624 for ( int i=0; i > num ; i-- )
00625 mReadWmf->restore();
00626 }
00627
00628
00629 void KoWmfReadPrivate::intersectClipRect( quint32, QDataStream& stream )
00630 {
00631 qint16 top, left, right, bottom;
00632
00633 stream >> bottom >> right >> top >> left;
00634
00635 QRegion region = mReadWmf->clipRegion();
00636 QRegion newRegion( left, top, right-left, bottom-top );
00637 if ( region.isEmpty() ) {
00638 region = newRegion;
00639 }
00640 else {
00641 region = region.intersect( newRegion );
00642 }
00643
00644 mReadWmf->setClipRegion( region );
00645 }
00646
00647
00648 void KoWmfReadPrivate::excludeClipRect( quint32, QDataStream& stream )
00649 {
00650 qint16 top, left, right, bottom;
00651
00652 stream >> bottom >> right >> top >> left;
00653
00654 QRegion region = mReadWmf->clipRegion();
00655 QRegion newRegion( left, top, right-left, bottom-top );
00656 if ( region.isEmpty() ) {
00657 region = newRegion;
00658 }
00659 else {
00660 region = region.subtract( newRegion );
00661 }
00662
00663 mReadWmf->setClipRegion( region );
00664 }
00665
00666
00667
00668
00669
00670 void KoWmfReadPrivate::setTextColor( quint32, QDataStream& stream )
00671 {
00672 quint32 color;
00673
00674 stream >> color;
00675 mTextColor = qtColor( color );
00676 }
00677
00678
00679 void KoWmfReadPrivate::setTextAlign( quint32, QDataStream& stream )
00680 {
00681 stream >> mTextAlign;
00682 }
00683
00684
00685 void KoWmfReadPrivate::textOut( quint32, QDataStream& )
00686 {
00687 if ( mNbrFunc ) {
00688 kDebug() << "textOut : unimplemented " << endl;
00689 }
00690 }
00691
00692
00693 void KoWmfReadPrivate::extTextOut( quint32 , QDataStream& )
00694 {
00695 if ( mNbrFunc ) {
00696 kDebug() << "extTextOut : unimplemented " << endl;
00697 }
00698 }
00699
00700
00701
00702
00703
00704
00705 void KoWmfReadPrivate::SetStretchBltMode( quint32, QDataStream& )
00706 {
00707 if ( mNbrFunc ) {
00708 kDebug() << "SetStretchBltMode : unimplemented " << endl;
00709 }
00710 }
00711
00712
00713 void KoWmfReadPrivate::dibBitBlt( quint32 size, QDataStream& stream )
00714 {
00715 quint32 raster;
00716 qint16 topSrc, leftSrc, widthSrc, heightSrc;
00717 qint16 topDst, leftDst;
00718
00719 stream >> raster;
00720 stream >> topSrc >> leftSrc >> heightSrc >> widthSrc;
00721 stream >> topDst >> leftDst;
00722
00723 if ( size > 11 ) {
00724 QImage bmpSrc;
00725
00726 if ( dibToBmp( bmpSrc, stream, (size - 11) * 2 ) ) {
00727 mReadWmf->setCompositionMode( winToQtComposition( raster ) );
00728
00729 mReadWmf->save();
00730 if ( widthSrc < 0 ) {
00731
00732 QMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
00733 mReadWmf->setMatrix( m, true );
00734 }
00735 if ( heightSrc < 0 ) {
00736
00737 QMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
00738 mReadWmf->setMatrix( m, true );
00739 }
00740 mReadWmf->drawImage( leftDst, topDst, bmpSrc, leftSrc, topSrc, widthSrc, heightSrc );
00741 mReadWmf->restore();
00742 }
00743 }
00744 else {
00745 kDebug() << "KoWmfReadPrivate::dibBitBlt without image not implemented " << endl;
00746 }
00747 }
00748
00749
00750 void KoWmfReadPrivate::dibStretchBlt( quint32 size, QDataStream& stream )
00751 {
00752 quint32 raster;
00753 qint16 topSrc, leftSrc, widthSrc, heightSrc;
00754 qint16 topDst, leftDst, widthDst, heightDst;
00755 QImage bmpSrc;
00756
00757 stream >> raster;
00758 stream >> heightSrc >> widthSrc >> topSrc >> leftSrc;
00759 stream >> heightDst >> widthDst >> topDst >> leftDst;
00760
00761 if ( dibToBmp( bmpSrc, stream, (size - 13) * 2 ) ) {
00762 mReadWmf->setCompositionMode( winToQtComposition( raster ) );
00763
00764 mReadWmf->save();
00765 if ( widthDst < 0 ) {
00766
00767 QMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
00768 mReadWmf->setMatrix( m, true );
00769 }
00770 if ( heightDst < 0 ) {
00771
00772 QMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
00773 mReadWmf->setMatrix( m, true );
00774 }
00775 bmpSrc = bmpSrc.copy( leftSrc, topSrc, widthSrc, heightSrc );
00776
00777
00778
00779 mReadWmf->drawImage( leftDst, topDst, bmpSrc );
00780 mReadWmf->restore();
00781 }
00782 }
00783
00784
00785 void KoWmfReadPrivate::stretchDib( quint32 size, QDataStream& stream )
00786 {
00787 quint32 raster;
00788 qint16 arg, topSrc, leftSrc, widthSrc, heightSrc;
00789 qint16 topDst, leftDst, widthDst, heightDst;
00790 QImage bmpSrc;
00791
00792 stream >> raster >> arg;
00793 stream >> heightSrc >> widthSrc >> topSrc >> leftSrc;
00794 stream >> heightDst >> widthDst >> topDst >> leftDst;
00795
00796 if ( dibToBmp( bmpSrc, stream, (size - 14) * 2 ) ) {
00797 mReadWmf->setCompositionMode( winToQtComposition( raster ) );
00798
00799 mReadWmf->save();
00800 if ( widthDst < 0 ) {
00801
00802 QMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
00803 mReadWmf->setMatrix( m, true );
00804 }
00805 if ( heightDst < 0 ) {
00806
00807 QMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
00808 mReadWmf->setMatrix( m, true );
00809 }
00810 bmpSrc = bmpSrc.copy( leftSrc, topSrc, widthSrc, heightSrc );
00811
00812
00813 mReadWmf->drawImage( leftDst, topDst, bmpSrc );
00814 mReadWmf->restore();
00815 }
00816 }
00817
00818
00819 void KoWmfReadPrivate::dibCreatePatternBrush( quint32 size, QDataStream& stream )
00820 {
00821 KoWmfPatternBrushHandle* handle = new KoWmfPatternBrushHandle;
00822
00823 if ( addHandle( handle ) ) {
00824 quint32 arg;
00825 QImage bmpSrc;
00826
00827 stream >> arg;
00828 if ( dibToBmp( bmpSrc, stream, (size - 5) * 2 ) ) {
00829 handle->image = QPixmap::fromImage( bmpSrc );
00830 handle->brush.setTexture( handle->image );
00831 }
00832 else {
00833 kDebug() << "KoWmfReadPrivate::dibCreatePatternBrush : incorrect DIB image" << endl;
00834 }
00835 }
00836 }
00837
00838
00839
00840
00841
00842 void KoWmfReadPrivate::selectObject( quint32, QDataStream& stream )
00843 {
00844 quint16 idx;
00845
00846 stream >> idx;
00847 if ( (idx < mNbrObject) && (mObjHandleTab[ idx ] != 0) )
00848 mObjHandleTab[ idx ]->apply( mReadWmf );
00849 else
00850 kDebug() << "KoWmfReadPrivate::selectObject : selection of an empty object" << endl;
00851 }
00852
00853
00854 void KoWmfReadPrivate::deleteObject( quint32, QDataStream& stream )
00855 {
00856 quint16 idx;
00857
00858 stream >> idx;
00859 deleteHandle( idx );
00860 }
00861
00862
00863 void KoWmfReadPrivate::createEmptyObject()
00864 {
00865
00866 KoWmfPenHandle* handle = new KoWmfPenHandle;
00867
00868 addHandle( handle );
00869 }
00870
00871
00872 void KoWmfReadPrivate::createBrushIndirect( quint32, QDataStream& stream )
00873 {
00874 Qt::BrushStyle style;
00875 quint16 sty, arg2;
00876 quint32 color;
00877 KoWmfBrushHandle* handle = new KoWmfBrushHandle;
00878
00879 if ( addHandle( handle ) ) {
00880 stream >> sty >> color >> arg2;
00881
00882 if ( sty == 2 ) {
00883 if ( arg2 < 6 )
00884 style = koWmfHatchedStyleBrush[ arg2 ];
00885 else
00886 {
00887 kDebug() << "KoWmfReadPrivate::createBrushIndirect: invalid hatched brush " << arg2 << endl;
00888 style = Qt::SolidPattern;
00889 }
00890 }
00891 else {
00892 if ( sty < 9 )
00893 style = koWmfStyleBrush[ sty ];
00894 else {
00895 kDebug() << "KoWmfReadPrivate::createBrushIndirect: invalid brush " << sty << endl;
00896 style = Qt::SolidPattern;
00897 }
00898 }
00899 handle->brush.setStyle( style );
00900 handle->brush.setColor( qtColor( color ) );
00901 }
00902 }
00903
00904
00905 void KoWmfReadPrivate::createPenIndirect( quint32, QDataStream& stream )
00906 {
00907
00908 Qt::PenStyle penStyle;
00909 quint32 color;
00910 quint16 style, width, arg;
00911
00912 KoWmfPenHandle* handle = new KoWmfPenHandle;
00913
00914 if ( addHandle( handle ) ) {
00915 stream >> style >> width >> arg >> color;
00916
00917 if ( style < 7 )
00918 penStyle=koWmfStylePen[ style ];
00919 else {
00920 kDebug() << "KoWmfReadPrivate::createPenIndirect: invalid pen " << style << endl;
00921 penStyle = Qt::SolidLine;
00922 }
00923
00924 handle->pen.setStyle( penStyle );
00925 handle->pen.setColor( qtColor( color ) );
00926 handle->pen.setCapStyle( Qt::RoundCap );
00927 handle->pen.setWidth( width );
00928 }
00929 }
00930
00931
00932 void KoWmfReadPrivate::createFontIndirect( quint32 size, QDataStream& stream )
00933 {
00934 qint16 pointSize, rotation;
00935 quint16 weight, property, fixedPitch, arg;
00936
00937 KoWmfFontHandle* handle = new KoWmfFontHandle;
00938
00939 if ( addHandle( handle ) ) {
00940 stream >> pointSize >> arg;
00941 stream >> rotation >> arg;
00942 stream >> weight >> property >> arg >> arg;
00943 stream >> fixedPitch;
00944
00945
00946
00947 mTextRotation = -rotation / 10;
00948 handle->font.setFixedPitch( ((fixedPitch & 0x01) == 0) );
00949
00950
00951 handle->font.setPointSize( qAbs(pointSize) - 2 );
00952 handle->font.setWeight( (weight >> 3) );
00953 handle->font.setItalic( (property & 0x01) );
00954 handle->font.setUnderline( (property & 0x100) );
00955
00956
00957 int maxChar = (size-12) * 2;
00958 char* nameFont = new char[maxChar];
00959 stream.readRawData( nameFont, maxChar );
00960 handle->font.setFamily( nameFont );
00961 delete[] nameFont;
00962 }
00963 }
00964
00965
00966
00967
00968
00969 void KoWmfReadPrivate::end( quint32, QDataStream& )
00970 {
00971 }
00972
00973 quint16 KoWmfReadPrivate::calcCheckSum( WmfPlaceableHeader* apmfh )
00974 {
00975 quint16* lpWord;
00976 quint16 wResult, i;
00977
00978
00979 wResult = *( lpWord = ( quint16* )( apmfh ) );
00980
00981 for( i=1; i<=9; i++ )
00982 {
00983 wResult ^= lpWord[ i ];
00984 }
00985 return wResult;
00986 }
00987
00988
00989 void KoWmfReadPrivate::notyet( quint32, QDataStream& )
00990 {
00991 if ( mNbrFunc ) {
00992 kDebug() << "unimplemented " << endl;
00993 }
00994 }
00995
00996 void KoWmfReadPrivate::region( quint32, QDataStream& )
00997 {
00998 if ( mNbrFunc ) {
00999 kDebug() << "region : unimplemented " << endl;
01000 }
01001 }
01002
01003 void KoWmfReadPrivate::palette( quint32, QDataStream& )
01004 {
01005 if ( mNbrFunc ) {
01006 kDebug() << "palette : unimplemented " << endl;
01007 }
01008 }
01009
01010 void KoWmfReadPrivate::escape( quint32, QDataStream& )
01011 {
01012 if ( mNbrFunc ) {
01013 kDebug() << "escape : unimplemented " << endl;
01014 }
01015 }
01016
01017 void KoWmfReadPrivate::setRelAbs( quint32, QDataStream& )
01018 {
01019 if ( mNbrFunc ) {
01020 kDebug() << "setRelAbs : unimplemented " << endl;
01021 }
01022 }
01023
01024 void KoWmfReadPrivate::setMapMode( quint32, QDataStream& )
01025 {
01026 if ( mNbrFunc ) {
01027 kDebug() << "setMapMode : unimplemented " << endl;
01028 }
01029 }
01030
01031 void KoWmfReadPrivate::extFloodFill( quint32, QDataStream& )
01032 {
01033 if ( mNbrFunc ) {
01034 kDebug() << "extFloodFill : unimplemented " << endl;
01035 }
01036 }
01037
01038 void KoWmfReadPrivate::startDoc( quint32, QDataStream& )
01039 {
01040 if ( mNbrFunc ) {
01041 kDebug() << "startDoc : unimplemented " << endl;
01042 }
01043 }
01044
01045 void KoWmfReadPrivate::startPage( quint32, QDataStream& )
01046 {
01047 if ( mNbrFunc ) {
01048 kDebug() << "startPage : unimplemented " << endl;
01049 }
01050 }
01051
01052 void KoWmfReadPrivate::endDoc( quint32, QDataStream& )
01053 {
01054 if ( mNbrFunc ) {
01055 kDebug() << "endDoc : unimplemented " << endl;
01056 }
01057 }
01058
01059 void KoWmfReadPrivate::endPage( quint32, QDataStream& )
01060 {
01061 if ( mNbrFunc ) {
01062 kDebug() << "endPage : unimplemented " << endl;
01063 }
01064 }
01065
01066 void KoWmfReadPrivate::resetDC( quint32, QDataStream& )
01067 {
01068 if ( mNbrFunc ) {
01069 kDebug() << "resetDC : unimplemented " << endl;
01070 }
01071 }
01072
01073 void KoWmfReadPrivate::bitBlt( quint32, QDataStream& )
01074 {
01075 if ( mNbrFunc ) {
01076 kDebug() << "bitBlt : unimplemented " << endl;
01077 }
01078 }
01079
01080 void KoWmfReadPrivate::setDibToDev( quint32, QDataStream& )
01081 {
01082 if ( mNbrFunc ) {
01083 kDebug() << "setDibToDev : unimplemented " << endl;
01084 }
01085 }
01086
01087 void KoWmfReadPrivate::createBrush( quint32, QDataStream& )
01088 {
01089 if ( mNbrFunc ) {
01090 kDebug() << "createBrush : unimplemented " << endl;
01091 }
01092 }
01093
01094 void KoWmfReadPrivate::createPatternBrush( quint32, QDataStream& )
01095 {
01096 if ( mNbrFunc ) {
01097 kDebug() << "createPatternBrush : unimplemented " << endl;
01098 }
01099 }
01100
01101 void KoWmfReadPrivate::createBitmap( quint32, QDataStream& )
01102 {
01103 if ( mNbrFunc ) {
01104 kDebug() << "createBitmap : unimplemented " << endl;
01105 }
01106 }
01107
01108 void KoWmfReadPrivate::createBitmapIndirect( quint32, QDataStream& )
01109 {
01110 createEmptyObject();
01111 if ( mNbrFunc ) {
01112 kDebug() << "createBitmapIndirect : unimplemented " << endl;
01113 }
01114 }
01115
01116 void KoWmfReadPrivate::createPalette( quint32, QDataStream& )
01117 {
01118 createEmptyObject();
01119 if ( mNbrFunc ) {
01120 kDebug() << "createPalette : unimplemented " << endl;
01121 }
01122 }
01123
01124 void KoWmfReadPrivate::createRegion( quint32, QDataStream& )
01125 {
01126 createEmptyObject();
01127 if ( mNbrFunc ) {
01128 kDebug() << "createRegion : unimplemented " << endl;
01129 }
01130 }
01131
01132
01133
01134
01135
01136
01137 bool KoWmfReadPrivate::addHandle( KoWmfHandle* handle )
01138 {
01139 int idx;
01140
01141 for ( idx=0; idx < mNbrObject ; idx++ ) {
01142 if ( mObjHandleTab[ idx ] == 0 ) break;
01143 }
01144
01145 if ( idx < mNbrObject ) {
01146 mObjHandleTab[ idx ] = handle;
01147 return true;
01148 }
01149 else {
01150 delete handle;
01151 mStackOverflow = true;
01152 kDebug() << "KoWmfReadPrivate::addHandle : stack overflow = broken file !" << endl;
01153 return false;
01154 }
01155 }
01156
01157
01158 void KoWmfReadPrivate::deleteHandle( int idx )
01159 {
01160 if ( (idx < mNbrObject) && (mObjHandleTab[idx] != 0) ) {
01161 delete mObjHandleTab[ idx ];
01162 mObjHandleTab[ idx ] = 0;
01163 }
01164 else {
01165 kDebug() << "KoWmfReadPrivate::deletehandle() : bad index number" << endl;
01166 }
01167 }
01168
01169
01170 void KoWmfReadPrivate::pointArray( QDataStream& stream, QPolygon& pa )
01171 {
01172 qint16 left, top;
01173 int i, max;
01174
01175 for ( i=0, max=pa.size() ; i < max ; i++ ) {
01176 stream >> left >> top;
01177 pa.setPoint( i, left, top );
01178 }
01179 }
01180
01181
01182 void KoWmfReadPrivate::xyToAngle( int xStart, int yStart, int xEnd, int yEnd, int& angleStart, int& angleLength )
01183 {
01184 double aStart, aLength;
01185
01186 aStart = atan2( yStart, xStart );
01187 aLength = atan2( yEnd, xEnd ) - aStart;
01188
01189 angleStart = (int)((aStart * 2880) / 3.14166);
01190 angleLength = (int)((aLength * 2880) / 3.14166);
01191 if ( angleLength < 0 ) angleLength = 5760 + angleLength;
01192 }
01193
01194
01195 QPainter::CompositionMode KoWmfReadPrivate::winToQtComposition( quint16 param ) const
01196 {
01197 if ( param < 17 )
01198 return koWmfOpTab16[ param ];
01199 else
01200 return QPainter::CompositionMode_Source;
01201 }
01202
01203
01204 QPainter::CompositionMode KoWmfReadPrivate::winToQtComposition( quint32 param ) const
01205 {
01206
01207
01208
01209
01210
01211 int i;
01212
01213 for ( i=0 ; i < 15 ; i++ ) {
01214 if ( koWmfOpTab32[ i ].winRasterOp == param ) break;
01215 }
01216
01217 if ( i < 15 )
01218 return koWmfOpTab32[ i ].qtRasterOp;
01219 else
01220 return QPainter::CompositionMode_SourceOver;
01221 }
01222
01223
01224 bool KoWmfReadPrivate::dibToBmp( QImage& bmp, QDataStream& stream, quint32 size )
01225 {
01226 typedef struct _BMPFILEHEADER {
01227 quint16 bmType;
01228 quint32 bmSize;
01229 quint16 bmReserved1;
01230 quint16 bmReserved2;
01231 quint32 bmOffBits;
01232 } BMPFILEHEADER;
01233
01234 int sizeBmp = size + 14;
01235
01236 QByteArray pattern;
01237 pattern.resize( sizeBmp );
01238 pattern.fill(0);
01239 stream.readRawData( pattern.data() + 14, size );
01240
01241
01242 BMPFILEHEADER* bmpHeader;
01243 bmpHeader = (BMPFILEHEADER*)(pattern.data());
01244 bmpHeader->bmType = 0x4D42;
01245 bmpHeader->bmSize = sizeBmp;
01246
01247
01248 if ( !bmp.loadFromData( pattern, "BMP" ) ) {
01249 kDebug() << "KoWmfReadPrivate::dibToBmp: invalid bitmap " << endl;
01250 return false;
01251 }
01252 else {
01253 return true;
01254 }
01255 }
01256