00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <math.h>
00021 #include <assert.h>
00022 #include <qfileinfo.h>
00023 #include <qpixmap.h>
00024 #include <qpainter.h>
00025 #include <qdatastream.h>
00026 #include <qapplication.h>
00027 #include <qbuffer.h>
00028 #include <kdebug.h>
00029
00030 bool qwmfDebug = false;
00031
00032 #include "qwmf.h"
00033 #include "wmfstruct.h"
00034 #include "metafuncs.h"
00035
00036 #define QWMF_DEBUG 0
00037
00038
00039 class WmfCmd
00040 {
00041 public:
00042 ~WmfCmd() { if ( next ) delete next; }
00043 WmfCmd* next;
00044 unsigned short funcIndex;
00045 long numParm;
00046 short* parm;
00047 };
00048
00049
00050 class WinObjHandle
00051 {
00052 public:
00053 virtual void apply( QPainter& p ) = 0;
00054 };
00055
00056 class WinObjBrushHandle: public WinObjHandle
00057 {
00058 public:
00059 virtual void apply( QPainter& p );
00060 QBrush brush;
00061 virtual ~WinObjBrushHandle() {};
00062 };
00063
00064 class WinObjPenHandle: public WinObjHandle
00065 {
00066 public:
00067 virtual void apply( QPainter& p );
00068 QPen pen;
00069 virtual ~WinObjPenHandle() {};
00070 };
00071
00072 class WinObjPatternBrushHandle: public WinObjHandle
00073 {
00074 public:
00075 virtual void apply( QPainter& p );
00076 QBrush brush;
00077 QPixmap image;
00078 virtual ~WinObjPatternBrushHandle() {};
00079 };
00080
00081 class WinObjFontHandle: public WinObjHandle
00082 {
00083 public:
00084 virtual void apply( QPainter& p );
00085 QFont font;
00086 int rotation;
00087 virtual ~WinObjFontHandle() {};
00088 };
00089
00090 void WinObjBrushHandle::apply( QPainter& p )
00091 {
00092 p.setBrush( brush );
00093 }
00094
00095 void WinObjPenHandle::apply( QPainter& p )
00096 {
00097 p.setPen( pen );
00098 }
00099
00100 void WinObjPatternBrushHandle::apply( QPainter& p )
00101 {
00102 p.setBrush( brush );
00103 }
00104
00105 void WinObjFontHandle::apply( QPainter& p )
00106 {
00107 p.setFont( font );
00108 }
00109
00110 #define MAX_OBJHANDLE 64
00111
00112
00113
00114
00115 QWinMetaFile::QWinMetaFile()
00116 {
00117 mValid = false;
00118 mFirstCmd = NULL;
00119 mObjHandleTab = NULL;
00120 mDpi = 1000;
00121 }
00122
00123
00124
00125 QWinMetaFile::~QWinMetaFile()
00126 {
00127 if ( mFirstCmd ) delete mFirstCmd;
00128 if ( mObjHandleTab ) delete[] mObjHandleTab;
00129 }
00130
00131
00132
00133 bool QWinMetaFile::load( const QString &filename )
00134 {
00135 QFile file( filename );
00136
00137 if ( !file.exists() )
00138 {
00139 kdDebug() << "File " << QFile::encodeName(filename) << " does not exist" << endl;
00140 return false;
00141 }
00142
00143 if ( !file.open( IO_ReadOnly ) )
00144 {
00145 kdDebug() << "Cannot open file " << QFile::encodeName(filename) << endl;
00146 return false;
00147 }
00148
00149 QByteArray ba = file.readAll();
00150 file.close();
00151
00152 QBuffer buffer( ba );
00153 buffer.open( IO_ReadOnly );
00154 return load( buffer );
00155 }
00156
00157
00158 bool QWinMetaFile::load( QBuffer &buffer )
00159 {
00160 QDataStream st;
00161 WmfEnhMetaHeader eheader;
00162 WmfMetaHeader header;
00163 WmfPlaceableHeader pheader;
00164 WORD checksum;
00165 int filePos, idx, i;
00166 WmfCmd *cmd, *last;
00167 DWORD rdSize;
00168 WORD rdFunc;
00169
00170 mTextAlign = 0;
00171 mRotation = 0;
00172 mTextColor = Qt::black;
00173 if ( mFirstCmd ) delete mFirstCmd;
00174 mFirstCmd = NULL;
00175
00176 st.setDevice( &buffer );
00177 st.setByteOrder( QDataStream::LittleEndian );
00178
00179
00180 st >> pheader.key;
00181 mIsPlaceable = ( pheader.key==( DWORD )APMHEADER_KEY );
00182 if ( mIsPlaceable )
00183 {
00184 st >> pheader.hmf;
00185 st >> pheader.bbox.left;
00186 st >> pheader.bbox.top;
00187 st >> pheader.bbox.right;
00188 st >> pheader.bbox.bottom;
00189 st >> pheader.inch;
00190 st >> pheader.reserved;
00191 st >> pheader.checksum;
00192 checksum = calcCheckSum( &pheader );
00193 if ( pheader.checksum!=checksum ) mIsPlaceable = false;
00194
00195 mDpi = pheader.inch;
00196 mBBox.setLeft( pheader.bbox.left );
00197 mBBox.setTop( pheader.bbox.top );
00198 mBBox.setRight( pheader.bbox.right );
00199 mBBox.setBottom( pheader.bbox.bottom );
00200 mHeaderBoundingBox = mBBox;
00201 if ( QWMF_DEBUG )
00202 {
00203 kdDebug() << endl << "-------------------------------------------------" << endl;
00204 kdDebug() << "WMF Placeable Header ( " << static_cast<int>(sizeof( pheader ) ) << "):" << endl;
00205 kdDebug() << " bbox=( " << mBBox.left() << "; " << mBBox.top() << "; " << mBBox.width()
00206 << "; " << mBBox.height() << ")" << endl;
00207 kdDebug() << " inch=" << pheader.inch << endl;
00208 kdDebug() << " checksum=" << pheader.checksum << "( "
00209 << (pheader.checksum==checksum?"ok":"wrong") << " )" << endl;
00210 }
00211 }
00212 else buffer.at( 0 );
00213
00214
00215 filePos = buffer.at();
00216 st >> eheader.iType;
00217 st >> eheader.nSize;
00218 st >> eheader.rclBounds.left;
00219 st >> eheader.rclBounds.top;
00220 st >> eheader.rclBounds.right;
00221 st >> eheader.rclBounds.bottom;
00222 st >> eheader.rclFrame.left;
00223 st >> eheader.rclFrame.top;
00224 st >> eheader.rclFrame.right;
00225 st >> eheader.rclFrame.bottom;
00226 st >> eheader.dSignature;
00227 mIsEnhanced = ( eheader.dSignature==ENHMETA_SIGNATURE );
00228 if ( mIsEnhanced )
00229 {
00230 st >> eheader.nVersion;
00231 st >> eheader.nBytes;
00232 st >> eheader.nRecords;
00233 st >> eheader.nHandles;
00234 st >> eheader.sReserved;
00235 st >> eheader.nDescription;
00236 st >> eheader.offDescription;
00237 st >> eheader.nPalEntries;
00238 st >> eheader.szlDevice.width;
00239 st >> eheader.szlDevice.height;
00240 st >> eheader.szlMillimeters.width;
00241 st >> eheader.szlMillimeters.height;
00242
00243 if ( QWMF_DEBUG )
00244 {
00245 kdDebug() << endl << "-------------------------------------------------" << endl;
00246 kdDebug() << "WMF Extended Header:" << endl;
00247 kdDebug() << " iType=" << eheader.iType << endl;
00248 kdDebug() << " nSize=" << eheader.nSize << endl;
00249 kdDebug() << " rclBounds=( " << eheader.rclBounds.left << "; " << eheader.rclBounds.top << "; "
00250 << eheader.rclBounds.right << "; " << eheader.rclBounds.bottom << ")" << endl;
00251 kdDebug() << " rclFrame=( " << eheader.rclFrame.left << "; " << eheader.rclFrame.top << "; "
00252 << eheader.rclFrame.right << "; " << eheader.rclFrame.bottom << ")" << endl;
00253 kdDebug() << " nBytes=" << eheader.nBytes << endl;
00254 kdDebug() << "\nNOT YET IMPLEMENTED, SORRY." << endl;
00255 }
00256 }
00257 else
00258 {
00259
00260 buffer.at( filePos );
00261 st >> header.mtType;
00262 st >> header.mtHeaderSize;
00263 st >> header.mtVersion;
00264 st >> header.mtSize;
00265 st >> header.mtNoObjects;
00266 st >> header.mtMaxRecord;
00267 st >> header.mtNoParameters;
00268 if ( QWMF_DEBUG ) {
00269 kdDebug() << "WMF Header: " << "mtSize=" << header.mtSize << endl;
00270 }
00271 }
00272
00273
00274 mValid = ((header.mtHeaderSize == 9) && (header.mtNoParameters == 0)) || mIsEnhanced || mIsPlaceable;
00275 if ( mValid )
00276 {
00277
00278 last = NULL;
00279 rdFunc = -1;
00280 while ( !st.eof() && (rdFunc != 0) )
00281 {
00282 st >> rdSize;
00283 st >> rdFunc;
00284 idx = findFunc( rdFunc );
00285 rdSize -= 3;
00286
00287 cmd = new WmfCmd;
00288 cmd->next = NULL;
00289 if ( last ) last->next = cmd;
00290 else mFirstCmd = cmd;
00291
00292 cmd->funcIndex = idx;
00293 cmd->numParm = rdSize;
00294 cmd->parm = new WORD[ rdSize ];
00295 last = cmd;
00296
00297 for ( i=0; i<rdSize && !st.eof(); i++ )
00298 st >> cmd->parm[ i ];
00299
00300
00301 if ( rdFunc == 0x020B ) {
00302 mBBox.setLeft( cmd->parm[ 1 ] );
00303 mBBox.setTop( cmd->parm[ 0 ] );
00304 }
00305 if ( rdFunc == 0x020C ) {
00306 mBBox.setWidth( cmd->parm[ 1 ] );
00307 mBBox.setHeight( cmd->parm[ 0 ] );
00308 }
00309
00310 if ( i<rdSize )
00311 {
00312 kdDebug() << "WMF : file truncated !" << endl;
00313 return false;
00314 }
00315 }
00316
00317 mValid = (rdFunc == 0) && (mBBox.width() != 0) && (mBBox.height() != 0);
00318 if ( !mValid ) {
00319 kdDebug() << "WMF : incorrect file format !" << endl;
00320 }
00321 }
00322 else {
00323 kdDebug() << "WMF Header : incorrect header !" << endl;
00324 }
00325
00326 buffer.close();
00327 return mValid;
00328 }
00329
00330
00331
00332 bool QWinMetaFile::paint( const QPaintDevice* aTarget, bool absolute )
00333 {
00334 int idx, i;
00335 WmfCmd* cmd;
00336
00337 if ( !mValid ) return false;
00338
00339 assert( aTarget!=NULL );
00340 if ( mPainter.isActive() ) return false;
00341
00342 if ( mObjHandleTab ) delete[] mObjHandleTab;
00343 mObjHandleTab = new WinObjHandle* [ MAX_OBJHANDLE ];
00344 for ( i=MAX_OBJHANDLE-1; i>=0; i-- )
00345 mObjHandleTab[ i ] = NULL;
00346
00347 mPainter.resetXForm();
00348 mWinding = false;
00349 mAbsoluteCoord = absolute;
00350
00351 mPainter.begin( aTarget );
00352 if ( QWMF_DEBUG ) {
00353 kdDebug() << "Bounding box : " << mBBox.left()
00354 << " " << mBBox.top() << " " << mBBox.right() << " " << mBBox.bottom() << endl;
00355 }
00356
00357 if ( mAbsoluteCoord ) {
00358 mPainter.setWindow( mBBox.top(), mBBox.left(), mBBox.width(), mBBox.height() );
00359 }
00360 mInternalWorldMatrix.reset();
00361
00362 for ( cmd=mFirstCmd; cmd; cmd=cmd->next )
00363 {
00364 idx = cmd->funcIndex;
00365 ( this->*metaFuncTab[ idx ].method )( cmd->numParm, cmd->parm );
00366
00367 if ( QWMF_DEBUG ) {
00368 QString str = "", param;
00369 if ( metaFuncTab[ idx ].name == NULL ) {
00370 str += "UNKNOWN ";
00371 }
00372 if ( metaFuncTab[ idx ].method == &QWinMetaFile::noop ) {
00373 str += "UNIMPLEMENTED ";
00374 }
00375 str += metaFuncTab[ idx ].name;
00376 str += " : ";
00377
00378 for ( i=0 ; i < cmd->numParm ; i++ ) {
00379 param.setNum( cmd->parm[ i ] );
00380 str += param;
00381 str += " ";
00382 }
00383 kdDebug() << str << endl;
00384 }
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397 mPainter.end();
00398 return true;
00399 }
00400
00401
00402
00403
00404
00405 void QWinMetaFile::setWindowOrg( long, short* parm )
00406 {
00407 if ( mAbsoluteCoord ) {
00408 QRect r = mPainter.window();
00409 mPainter.setWindow( parm[ 1 ], parm[ 0 ], r.width(), r.height() );
00410 }
00411 else {
00412 double dx = mInternalWorldMatrix.dx();
00413 double dy = mInternalWorldMatrix.dy();
00414
00415 mInternalWorldMatrix.translate( -dx, -dy );
00416 mInternalWorldMatrix.translate( -parm[ 1 ], -parm[ 0 ] );
00417 mPainter.translate( -dx, -dy );
00418 mPainter.translate( -parm[ 1 ], -parm[ 0 ] );
00419 }
00420 }
00421
00422
00423
00424 void QWinMetaFile::setWindowExt( long, short* parm )
00425 {
00426
00427 if ( mAbsoluteCoord ) {
00428 QRect r = mPainter.window();
00429 mPainter.setWindow( r.left(), r.top(), parm[ 1 ], parm[ 0 ] );
00430 }
00431 else {
00432 if ( (parm[ 0 ] != 0) && (parm[ 1 ] != 0) ) {
00433 QRect r = mPainter.window();
00434 double dx = mInternalWorldMatrix.dx();
00435 double dy = mInternalWorldMatrix.dy();
00436 double sx = mInternalWorldMatrix.m11();
00437 double sy = mInternalWorldMatrix.m22();
00438
00439 mInternalWorldMatrix.translate( -dx, -dy );
00440 mInternalWorldMatrix.scale( 1/sx, 1/sy );
00441 mPainter.translate( -dx, -dy );
00442 mPainter.scale( 1/sx, 1/sy );
00443
00444 sx = (double)r.width() / (double)parm[ 1 ];
00445 sy = (double)r.height() / (double)parm[ 0 ];
00446
00447 mInternalWorldMatrix.scale( sx, sy );
00448 mInternalWorldMatrix.translate( dx, dy );
00449 mPainter.scale( sx, sy );
00450 mPainter.translate( dx, dy );
00451 }
00452 }
00453 }
00454
00455
00456
00457
00458
00459 void QWinMetaFile::lineTo( long, short* parm )
00460 {
00461 mPainter.lineTo( parm[ 1 ], parm[ 0 ] );
00462 }
00463
00464
00465
00466 void QWinMetaFile::moveTo( long, short* parm )
00467 {
00468 mPainter.moveTo( parm[ 1 ], parm[ 0 ] );
00469 }
00470
00471
00472
00473 void QWinMetaFile::ellipse( long, short* parm )
00474 {
00475 mPainter.drawEllipse( parm[ 3 ], parm[ 2 ], parm[ 1 ]-parm[ 3 ], parm[ 0 ]-parm[ 2 ] );
00476 }
00477
00478
00479
00480 void QWinMetaFile::polygon( long, short* parm )
00481 {
00482 QPointArray* pa;
00483
00484 pa = pointArray( parm[ 0 ], &parm[ 1 ] );
00485 mPainter.drawPolygon( *pa, mWinding );
00486 }
00487
00488
00489
00490 void QWinMetaFile::polyPolygon( long, short* parm )
00491 {
00492 QRegion region;
00493 int i, j, startPolygon;
00494
00495 mPainter.save();
00496
00497
00498 QRect win = bbox();
00499 startPolygon = 1+parm[ 0 ];
00500 for ( i=0 ; i < parm[ 0 ] ; i++ ) {
00501 QPointArray pa1( parm[ 1+i ] );
00502 for ( j=0 ; j < parm[ 1+i ] ; j++) {
00503 pa1.setPoint ( j, parm[ startPolygon ], parm[ startPolygon+1 ] );
00504 startPolygon += 2;
00505 }
00506 QRegion r( pa1 );
00507 region = region.eor( r );
00508 }
00509 mPainter.setClipRegion( region, QPainter::CoordPainter );
00510
00511
00512 mPainter.fillRect( win.left(), win.top(), win.width(), win.height(), mPainter.brush() );
00513
00514
00515 if ( mPainter.pen().style() != Qt::NoPen ) {
00516 mPainter.setClipping( false );
00517 mPainter.setBrush( Qt::NoBrush );
00518
00519 QPointArray* pa;
00520 int idxPolygon = 1 + parm[ 0 ];
00521 for ( i=0 ; i < parm[ 0 ] ; i++ ) {
00522 pa = pointArray( parm[ 1+i ], &parm[ idxPolygon ] );
00523 mPainter.drawPolygon( *pa );
00524 idxPolygon += parm[ 1+i ] * 2;
00525 }
00526 }
00527
00528 mPainter.restore();
00529 }
00530
00531
00532
00533 void QWinMetaFile::polyline( long, short* parm )
00534 {
00535 QPointArray* pa;
00536
00537 pa = pointArray( parm[ 0 ], &parm[ 1 ] );
00538 mPainter.drawPolyline( *pa );
00539 }
00540
00541
00542
00543 void QWinMetaFile::rectangle( long, short* parm )
00544 {
00545 mPainter.drawRect( parm[ 3 ], parm[ 2 ], parm[ 1 ]-parm[ 3 ], parm[ 0 ]-parm[ 2 ] );
00546 }
00547
00548
00549
00550 void QWinMetaFile::roundRect( long, short* parm )
00551 {
00552 int xRnd = 0, yRnd = 0;
00553
00554
00555 if ( (parm[ 3 ] - parm[ 5 ]) != 0 )
00556 xRnd = (parm[ 1 ] * 100) / (parm[ 3 ] - parm[ 5 ]) ;
00557 if ( (parm[ 2 ] - parm[ 4 ]) != 0 )
00558 yRnd = (parm[ 0 ] * 100) / (parm[ 2 ] - parm[ 4 ]) ;
00559
00560 mPainter.drawRoundRect( parm[ 5 ], parm[ 4 ], parm[ 3 ]-parm[ 5 ], parm[ 2 ]-parm[ 4 ], xRnd, yRnd );
00561 }
00562
00563
00564
00565 void QWinMetaFile::arc( long, short* parm )
00566 {
00567 int xCenter, yCenter, angleStart, aLength;
00568
00569 xCenter = parm[ 7 ] + ((parm[ 5 ] - parm[ 7 ]) / 2);
00570 yCenter = parm[ 6 ] + ((parm[ 4 ] - parm[ 6 ]) / 2);
00571
00572 xyToAngle ( parm[ 3 ] - xCenter, yCenter - parm[ 2 ], parm[ 1 ] - xCenter, yCenter - parm[ 0 ], angleStart, aLength );
00573
00574 mPainter.drawArc( parm[ 7 ], parm[ 6 ], parm[ 5 ]-parm[ 7 ], parm[ 4 ]-parm[ 6 ], angleStart, aLength);
00575 }
00576
00577
00578
00579 void QWinMetaFile::chord( long, short* parm )
00580 {
00581 int xCenter, yCenter, angleStart, aLength;
00582
00583 xCenter = parm[ 7 ] + ((parm[ 5 ] - parm[ 7 ]) / 2);
00584 yCenter = parm[ 6 ] + ((parm[ 4 ] - parm[ 6 ]) / 2);
00585
00586 xyToAngle ( parm[ 3 ] - xCenter, yCenter - parm[ 2 ], parm[ 1 ] - xCenter, yCenter - parm[ 0 ], angleStart, aLength );
00587
00588 mPainter.drawChord( parm[ 7 ], parm[ 6 ], parm[ 5 ]-parm[ 7 ], parm[ 4 ]-parm[ 6 ], angleStart, aLength);
00589 }
00590
00591
00592
00593 void QWinMetaFile::pie( long, short* parm )
00594 {
00595 int xCenter, yCenter, angleStart, aLength;
00596
00597 xCenter = parm[ 7 ] + ((parm[ 5 ] - parm[ 7 ]) / 2);
00598 yCenter = parm[ 6 ] + ((parm[ 4 ] - parm[ 6 ]) / 2);
00599
00600 xyToAngle ( parm[ 3 ] - xCenter, yCenter - parm[ 2 ], parm[ 1 ] - xCenter, yCenter - parm[ 0 ], angleStart, aLength );
00601
00602 mPainter.drawPie( parm[ 7 ], parm[ 6 ], parm[ 5 ]-parm[ 7 ], parm[ 4 ]-parm[ 6 ], angleStart, aLength);
00603 }
00604
00605
00606
00607 void QWinMetaFile::setPolyFillMode( long, short* parm )
00608 {
00609 mWinding = parm[ 0 ];
00610 }
00611
00612
00613
00614 void QWinMetaFile::setBkColor( long, short* parm )
00615 {
00616 mPainter.setBackgroundColor( color( parm ) );
00617 }
00618
00619
00620
00621 void QWinMetaFile::setBkMode( long, short* parm )
00622 {
00623 if ( parm[ 0 ]==1 ) mPainter.setBackgroundMode( Qt::TransparentMode );
00624 else mPainter.setBackgroundMode( Qt::OpaqueMode );
00625 }
00626
00627
00628
00629 void QWinMetaFile::setPixel( long, short* parm )
00630 {
00631 QPen pen = mPainter.pen();
00632 mPainter.setPen( color( parm ) );
00633 mPainter.drawPoint( parm[ 3 ], parm[ 2 ] );
00634 mPainter.setPen( pen );
00635 }
00636
00637
00638
00639 void QWinMetaFile::setRop( long, short* parm )
00640 {
00641 mPainter.setRasterOp( winToQtRaster( parm[ 0 ] ) );
00642 }
00643
00644
00645
00646 void QWinMetaFile::saveDC( long, short* )
00647 {
00648 mPainter.save();
00649 }
00650
00651
00652
00653 void QWinMetaFile::restoreDC( long, short *parm )
00654 {
00655 for ( int i=0; i > parm[ 0 ] ; i-- )
00656 mPainter.restore();
00657 }
00658
00659
00660
00661 void QWinMetaFile::intersectClipRect( long, short* parm )
00662 {
00663
00664
00665
00666
00667
00668 QRegion region( bbox() );
00669
00670 QRegion newRegion( parm[ 3 ], parm[ 2 ], parm[ 1 ] - parm[ 3 ], parm[ 0 ] - parm[ 2 ] );
00671 region = region.intersect( newRegion );
00672
00673 mPainter.setClipRegion( region, QPainter::CoordPainter );
00674 }
00675
00676
00677
00678 void QWinMetaFile::excludeClipRect( long, short* parm )
00679 {
00680
00681
00682
00683
00684
00685 QRegion region( bbox() );
00686
00687 QRegion newRegion( parm[ 3 ], parm[ 2 ], parm[ 1 ] - parm[ 3 ], parm[ 0 ] - parm[ 2 ] );
00688 region = region.subtract( newRegion );
00689
00690 mPainter.setClipRegion( region, QPainter::CoordPainter );
00691 }
00692
00693
00694
00695
00696
00697 void QWinMetaFile::setTextColor( long, short* parm )
00698 {
00699 mTextColor = color( parm );
00700 }
00701
00702
00703
00704 void QWinMetaFile::setTextAlign( long, short* parm )
00705 {
00706 mTextAlign = parm[ 0 ];
00707 }
00708
00709
00710
00711 void QWinMetaFile::textOut( long num, short* parm )
00712 {
00713
00714 short *copyParm = new short[ num + 1 ];
00715
00716
00717 int idxOffset = (parm[ 0 ] / 2) + 1 + (parm[ 0 ] & 1);
00718 copyParm[ 0 ] = parm[ idxOffset ];
00719 copyParm[ 1 ] = parm[ idxOffset + 1 ];
00720 copyParm[ 2 ] = parm[ 0 ];
00721 copyParm[ 3 ] = 0;
00722 memcpy( ©Parm[ 4 ], &parm[ 1 ], parm[ 0 ] );
00723
00724 extTextOut( num + 1, copyParm );
00725 delete [] copyParm;
00726 }
00727
00728
00729
00730 void QWinMetaFile::extTextOut( long num, short* parm )
00731 {
00732 char* ptStr;
00733 int x, y, width, height;
00734 int idxOffset;
00735
00736 if ( parm[ 3 ] != 0 )
00737 ptStr = (char*)&parm[ 8 ];
00738 else
00739 ptStr = (char*)&parm[ 4 ];
00740
00741 QCString text( ptStr, parm[ 2 ] + 1 );
00742
00743 QFontMetrics fm( mPainter.font() );
00744 width = fm.width( text ) + fm.descent();
00745 height = fm.height();
00746
00747 mPainter.save();
00748
00749 if ( mTextAlign & 0x01 ) {
00750 QPoint pos = mPainter.pos();
00751 x = pos.x();
00752 y = pos.y();
00753 }
00754 else {
00755 x = parm[ 1 ];
00756 y = parm[ 0 ];
00757 }
00758
00759 if ( mRotation ) {
00760 mPainter.translate( parm[ 1 ], parm[ 0 ]);
00761 mPainter.rotate ( mRotation );
00762 mPainter.translate( -parm[ 1 ], -parm[ 0 ] );
00763 }
00764
00765
00766 if ( mTextAlign & 0x06 )
00767 x -= ( width / 2 );
00768 if ( mTextAlign & 0x08 )
00769 y -= (height - fm.descent());
00770
00771 mPainter.setPen( mTextColor );
00772 idxOffset = (parm[ 2 ] / 2) + 4 + (parm[ 2 ] & 1);
00773 if ( ( parm[ 2 ] > 1 ) && ( num >= (idxOffset + parm[ 2 ]) ) && ( parm[ 3 ] == 0 ) ) {
00774
00775 int left = x;
00776 mPainter.drawText( left, y, width, height, Qt::AlignLeft | Qt::AlignTop, text.mid(0, 1) );
00777 for ( int i = 1; i < parm[ 2 ] ; i++ ) {
00778 left += parm[ idxOffset + i - 1 ];
00779 mPainter.drawText( left, y, width, height, Qt::AlignLeft | Qt::AlignTop, text.mid(i, 1) );
00780 }
00781 }
00782 else {
00783 mPainter.drawText( x, y, width, height, Qt::AlignLeft | Qt::AlignTop, text );
00784 }
00785
00786 mPainter.restore();
00787
00788 }
00789
00790
00791
00792
00793
00794
00795 void QWinMetaFile::dibBitBlt( long num, short* parm )
00796 {
00797 if ( num > 9 ) {
00798 QImage bmpSrc;
00799
00800 if ( dibToBmp( bmpSrc, (char*)&parm[ 8 ], (num - 8) * 2 ) ) {
00801 long raster = toDWord( parm );
00802
00803 mPainter.setRasterOp( winToQtRaster( raster ) );
00804
00805
00806 mPainter.save();
00807 if ( parm[ 5 ] < 0 ) {
00808 QWMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
00809 mPainter.setWorldMatrix( m, true );
00810 }
00811 if ( parm[ 4 ] < 0 ) {
00812 QWMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
00813 mPainter.setWorldMatrix( m, true );
00814 }
00815 mPainter.drawImage( parm[ 7 ], parm[ 6 ], bmpSrc, parm[ 3 ], parm[ 2 ], parm[ 5 ], parm[ 4 ] );
00816 mPainter.restore();
00817 }
00818 }
00819 else {
00820 kdDebug() << "QWinMetaFile::dibBitBlt without image: not implemented " << endl;
00821 }
00822 }
00823
00824
00825
00826 void QWinMetaFile::dibStretchBlt( long num, short* parm )
00827 {
00828 QImage bmpSrc;
00829
00830 if ( dibToBmp( bmpSrc, (char*)&parm[ 10 ], (num - 10) * 2 ) ) {
00831 long raster = toDWord( parm );
00832
00833 mPainter.setRasterOp( winToQtRaster( raster ) );
00834
00835
00836 mPainter.save();
00837 if ( parm[ 7 ] < 0 ) {
00838 QWMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
00839 mPainter.setWorldMatrix( m, true );
00840 }
00841 if ( parm[ 6 ] < 0 ) {
00842 QWMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
00843 mPainter.setWorldMatrix( m, true );
00844 }
00845 bmpSrc = bmpSrc.copy( parm[ 5 ], parm[ 4 ], parm[ 3 ], parm[ 2 ] );
00846
00847
00848 mPainter.drawImage( parm[ 9 ], parm[ 8 ], bmpSrc );
00849 mPainter.restore();
00850 }
00851 }
00852
00853
00854
00855 void QWinMetaFile::stretchDib( long num, short* parm )
00856 {
00857 QImage bmpSrc;
00858
00859 if ( dibToBmp( bmpSrc, (char*)&parm[ 11 ], (num - 11) * 2 ) ) {
00860 long raster = toDWord( parm );
00861
00862 mPainter.setRasterOp( winToQtRaster( raster ) );
00863
00864
00865 mPainter.save();
00866 if ( parm[ 8 ] < 0 ) {
00867 QWMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
00868 mPainter.setWorldMatrix( m, true );
00869 }
00870 if ( parm[ 7 ] < 0 ) {
00871 QWMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
00872 mPainter.setWorldMatrix( m, true );
00873 }
00874 bmpSrc = bmpSrc.copy( parm[ 6 ], parm[ 5 ], parm[ 4 ], parm[ 3 ] );
00875
00876
00877 mPainter.drawImage( parm[ 10 ], parm[ 9 ], bmpSrc );
00878 mPainter.restore();
00879 }
00880 }
00881
00882
00883
00884 void QWinMetaFile::dibCreatePatternBrush( long num, short* parm )
00885 {
00886 WinObjPatternBrushHandle* handle = new WinObjPatternBrushHandle;
00887 addHandle( handle );
00888 QImage bmpSrc;
00889
00890 if ( dibToBmp( bmpSrc, (char*)&parm[ 2 ], (num - 2) * 2 ) ) {
00891 handle->image = bmpSrc;
00892 handle->brush.setPixmap( handle->image );
00893 }
00894 }
00895
00896
00897
00898
00899
00900 void QWinMetaFile::selectObject( long, short* parm )
00901 {
00902 int idx = parm[ 0 ];
00903 if ( idx>=0 && idx < MAX_OBJHANDLE && mObjHandleTab[ idx ] )
00904 mObjHandleTab[ idx ]->apply( mPainter );
00905 }
00906
00907
00908
00909 void QWinMetaFile::deleteObject( long, short* parm )
00910 {
00911 deleteHandle( parm[ 0 ] );
00912 }
00913
00914
00915
00916 void QWinMetaFile::createEmptyObject( long, short* )
00917 {
00918
00919 WinObjPenHandle* handle = new WinObjPenHandle;
00920 addHandle( handle );
00921 kdDebug() << "QWinMetaFile: unimplemented createObject " << endl;
00922 }
00923
00924
00925
00926 void QWinMetaFile::createBrushIndirect( long, short* parm )
00927 {
00928 static Qt::BrushStyle hatchedStyleTab[] =
00929 {
00930 Qt::HorPattern,
00931 Qt::FDiagPattern,
00932 Qt::BDiagPattern,
00933 Qt::CrossPattern,
00934 Qt::DiagCrossPattern
00935 };
00936 static Qt::BrushStyle styleTab[] =
00937 { Qt::SolidPattern,
00938 Qt::NoBrush,
00939 Qt::FDiagPattern,
00940 Qt::Dense4Pattern,
00941 Qt::HorPattern,
00942 Qt::VerPattern,
00943 Qt::Dense6Pattern,
00944 Qt::Dense2Pattern,
00945 Qt::Dense3Pattern
00946 };
00947 Qt::BrushStyle style;
00948 short arg;
00949 WinObjBrushHandle* handle = new WinObjBrushHandle;
00950 addHandle( handle );
00951
00952 arg = parm[ 0 ];
00953 if ( arg==2 )
00954 {
00955 arg = parm[ 3 ];
00956 if ( arg>=0 && arg<5 ) style = hatchedStyleTab[ arg ];
00957 else
00958 {
00959 kdDebug() << "QWinMetaFile::createBrushIndirect: invalid hatched brush " << arg << endl;
00960 style = Qt::SolidPattern;
00961 }
00962 }
00963 else if ( arg>=0 && arg<9 )
00964 style = styleTab[ arg ];
00965 else
00966 {
00967 kdDebug() << "QWinMetaFile::createBrushIndirect: invalid brush " << arg << endl;
00968 style = Qt::SolidPattern;
00969 }
00970 handle->brush.setStyle( style );
00971 handle->brush.setColor( color( parm+1 ) );
00972 }
00973
00974
00975
00976 void QWinMetaFile::createPenIndirect( long, short* parm )
00977 {
00978 static Qt::PenStyle styleTab[] =
00979 { Qt::SolidLine, Qt::DashLine, Qt::DotLine, Qt::DashDotLine, Qt::DashDotDotLine,
00980 Qt::NoPen, Qt::SolidLine };
00981 Qt::PenStyle style;
00982 WinObjPenHandle* handle = new WinObjPenHandle;
00983 addHandle( handle );
00984
00985 if ( parm[ 0 ]>=0 && parm[ 0 ]<6 ) style=styleTab[ parm[ 0 ] ];
00986 else
00987 {
00988 kdDebug() << "QWinMetaFile::createPenIndirect: invalid pen " << parm[ 0 ] << endl;
00989 style = Qt::SolidLine;
00990 }
00991
00992 handle->pen.setStyle( style );
00993 handle->pen.setColor( color( parm+3 ) );
00994 handle->pen.setCapStyle( Qt::RoundCap );
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009 }
01010
01011
01012
01013 void QWinMetaFile::createFontIndirect( long , short* parm)
01014 {
01015 WinObjFontHandle* handle = new WinObjFontHandle;
01016 addHandle( handle );
01017
01018 QString family( (const char*)&parm[ 9 ] );
01019
01020 mRotation = -parm[ 2 ] / 10;
01021
01022 handle->font.setFamily( family );
01023 handle->font.setFixedPitch( ((parm[ 8 ] & 0x01) == 0) );
01024
01025 handle->font.setPointSize( QABS(parm[ 0 ]) - 2 );
01026 handle->font.setWeight( (parm[ 4 ] >> 3) );
01027 handle->font.setItalic( (parm[ 5 ] & 0x01) );
01028 handle->font.setUnderline( (parm[ 5 ] & 0x100) );
01029 }
01030
01031
01032
01033
01034
01035 void QWinMetaFile::noop( long, short* )
01036 {
01037 }
01038
01039
01040 void QWinMetaFile::end( long, short* )
01041 {
01042
01043
01044 }
01045
01046
01047
01048 unsigned short QWinMetaFile::calcCheckSum( WmfPlaceableHeader* apmfh )
01049 {
01050 WORD* lpWord;
01051 WORD wResult, i;
01052
01053
01054 wResult = *( lpWord = ( WORD* )( apmfh ) );
01055
01056 for( i=1; i<=9; i++ )
01057 {
01058 wResult ^= lpWord[ i ];
01059 }
01060 return wResult;
01061 }
01062
01063
01064
01065 int QWinMetaFile::findFunc( unsigned short aFunc ) const
01066 {
01067 int i;
01068
01069 for ( i=0; metaFuncTab[ i ].name; i++ )
01070 if ( metaFuncTab[ i ].func == aFunc ) return i;
01071
01072
01073 return i;
01074 }
01075
01076
01077 QPointArray* QWinMetaFile::pointArray( short num, short* parm )
01078 {
01079 int i;
01080
01081 mPoints.resize( num );
01082
01083 for ( i=0; i<num; i++, parm+=2 )
01084 mPoints.setPoint( i, parm[ 0 ], parm[ 1 ] );
01085
01086 return &mPoints;
01087 }
01088
01089
01090 unsigned int QWinMetaFile::toDWord( short* parm )
01091 {
01092 unsigned int l;
01093
01094 #if !defined( WORDS_BIGENDIAN )
01095 l = *( unsigned int* )( parm );
01096 #else
01097 char *bytes;
01098 char swap[ 4 ];
01099 bytes = ( char* )parm;
01100 swap[ 0 ] = bytes[ 2 ];
01101 swap[ 1 ] = bytes[ 3 ];
01102 swap[ 2 ] = bytes[ 0 ];
01103 swap[ 3 ] = bytes[ 1 ];
01104 l = *( unsigned int* )( swap );
01105 #endif
01106
01107 return l;
01108 }
01109
01110
01111
01112 QColor QWinMetaFile::color( short* parm )
01113 {
01114 unsigned int colorRef;
01115 int red, green, blue;
01116
01117 colorRef = toDWord( parm ) & 0xffffff;
01118 red = colorRef & 255;
01119 green = ( colorRef>>8 ) & 255;
01120 blue = ( colorRef>>16 ) & 255;
01121
01122 return QColor( red, green, blue );
01123 }
01124
01125
01126
01127 void QWinMetaFile::xyToAngle( int xStart, int yStart, int xEnd, int yEnd, int& angleStart, int& angleLength )
01128 {
01129 float aStart, aLength;
01130
01131 aStart = atan2( yStart, xStart );
01132 aLength = atan2( yEnd, xEnd ) - aStart;
01133
01134 angleStart = (int)(aStart * 2880 / 3.14166);
01135 angleLength = (int)(aLength * 2880 / 3.14166);
01136 if ( angleLength < 0 ) angleLength = 5760 + angleLength;
01137 }
01138
01139
01140
01141 void QWinMetaFile::addHandle( WinObjHandle* handle )
01142 {
01143 int idx;
01144
01145 for ( idx=0; idx < MAX_OBJHANDLE ; idx++ )
01146 if ( mObjHandleTab[ idx ] == NULL ) break;
01147
01148 if ( idx < MAX_OBJHANDLE )
01149 mObjHandleTab[ idx ] = handle;
01150 else
01151 kdDebug() << "QWinMetaFile error: handle table full !" << endl;
01152 }
01153
01154
01155 void QWinMetaFile::deleteHandle( int idx )
01156 {
01157 if ( idx >= 0 && idx < MAX_OBJHANDLE && mObjHandleTab[ idx ] )
01158 {
01159 delete mObjHandleTab[ idx ];
01160 mObjHandleTab[ idx ] = NULL;
01161 }
01162 }
01163
01164
01165 Qt::RasterOp QWinMetaFile::winToQtRaster( short parm ) const
01166 {
01167 static const Qt::RasterOp opTab[] =
01168 {
01169 Qt::CopyROP,
01170 Qt::ClearROP, Qt::NandROP, Qt::NotAndROP, Qt::NotCopyROP,
01171 Qt::AndNotROP, Qt::NotROP, Qt::XorROP, Qt::NorROP,
01172 Qt::AndROP, Qt::NotXorROP, Qt::NopROP, Qt::NotOrROP,
01173 Qt::CopyROP, Qt::OrNotROP, Qt::OrROP, Qt::SetROP
01174 };
01175
01176 if ( parm > 0 && parm <= 16 )
01177 return opTab[ parm ];
01178 else
01179 return Qt::CopyROP;
01180 }
01181
01182
01183 Qt::RasterOp QWinMetaFile::winToQtRaster( long parm ) const
01184 {
01185
01186
01187
01188
01189
01190 static const struct OpTab
01191 {
01192 long winRasterOp;
01193 Qt::RasterOp qtRasterOp;
01194 } opTab[] =
01195 {
01196 { 0x00CC0020, Qt::CopyROP },
01197 { 0x00EE0086, Qt::OrROP },
01198 { 0x008800C6, Qt::AndROP },
01199 { 0x00660046, Qt::XorROP },
01200 { 0x00440328, Qt::AndNotROP },
01201 { 0x00330008, Qt::NotCopyROP },
01202 { 0x001100A6, Qt::NandROP },
01203 { 0x00C000CA, Qt::CopyROP },
01204 { 0x00BB0226, Qt::NotOrROP },
01205 { 0x00F00021, Qt::CopyROP },
01206 { 0x00FB0A09, Qt::CopyROP },
01207 { 0x005A0049, Qt::CopyROP },
01208 { 0x00550009, Qt::NotROP },
01209 { 0x00000042, Qt::ClearROP },
01210 { 0x00FF0062, Qt::SetROP }
01211 };
01212
01213 int i;
01214 for ( i=0 ; i < 15 ; i++ )
01215 if ( opTab[ i ].winRasterOp == parm )
01216 break;
01217
01218 if ( i < 15 )
01219 return opTab[ i ].qtRasterOp;
01220 else
01221 return Qt::CopyROP;
01222 }
01223
01224
01225 bool QWinMetaFile::dibToBmp( QImage& bmp, const char* dib, long size )
01226 {
01227 typedef struct _BMPFILEHEADER {
01228 WORD bmType;
01229 DWORD bmSize;
01230 WORD bmReserved1;
01231 WORD bmReserved2;
01232 DWORD bmOffBits;
01233 } BMPFILEHEADER;
01234
01235 int sizeBmp = size + 14;
01236
01237 QByteArray pattern( sizeBmp );
01238 pattern.fill(0);
01239 memcpy( &pattern[ 14 ], dib, size );
01240
01241
01242 BMPFILEHEADER* bmpHeader;
01243 bmpHeader = (BMPFILEHEADER*)((const char*)pattern);
01244 bmpHeader->bmType = 0x4D42;
01245 bmpHeader->bmSize = sizeBmp;
01246
01247 if ( !bmp.loadFromData( (const uchar*)bmpHeader, pattern.size(), "BMP" ) ) {
01248 kdDebug() << "QWinMetaFile::dibToBmp: invalid bitmap " << endl;
01249 return false;
01250 }
01251 else {
01252
01253
01254
01255 return true;
01256 }
01257 }
01258