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