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