|
|
|
/* Windows Meta File Loader/Painter Class Implementation
|
|
|
|
*
|
|
|
|
* Copyright ( C ) 1998 Stefan Taferner
|
|
|
|
* Modified 2002 thierry lorthiois
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License as published by the
|
|
|
|
* Free Software Foundation; either version 2 of the License, or ( at your
|
|
|
|
* option ) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABLILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details. You should have received a copy
|
|
|
|
* of the GNU General Public License along with this program; if not, write
|
|
|
|
* to the Free Software Foundation, Inc, 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <tqfileinfo.h>
|
|
|
|
#include <tqpixmap.h>
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <tqdatastream.h>
|
|
|
|
#include <tqapplication.h>
|
|
|
|
#include <tqbuffer.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
|
|
|
|
bool qwmfDebug = false;
|
|
|
|
|
|
|
|
#include "qwmf.h"
|
|
|
|
#include "wmfstruct.h"
|
|
|
|
#include "metafuncs.h"
|
|
|
|
|
|
|
|
#define TQWMF_DEBUG 0
|
|
|
|
|
|
|
|
|
|
|
|
class WmfCmd
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
~WmfCmd() { if ( next ) delete next; }
|
|
|
|
WmfCmd* next;
|
|
|
|
unsigned short funcIndex;
|
|
|
|
long numParm;
|
|
|
|
short* parm;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class WinObjHandle
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual void apply( TQPainter& p ) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
class WinObjBrushHandle: public WinObjHandle
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual void apply( TQPainter& p );
|
|
|
|
TQBrush brush;
|
|
|
|
virtual ~WinObjBrushHandle() {};
|
|
|
|
};
|
|
|
|
|
|
|
|
class WinObjPenHandle: public WinObjHandle
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual void apply( TQPainter& p );
|
|
|
|
TQPen pen;
|
|
|
|
virtual ~WinObjPenHandle() {};
|
|
|
|
};
|
|
|
|
|
|
|
|
class WinObjPatternBrushHandle: public WinObjHandle
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual void apply( TQPainter& p );
|
|
|
|
TQBrush brush;
|
|
|
|
TQPixmap image;
|
|
|
|
virtual ~WinObjPatternBrushHandle() {};
|
|
|
|
};
|
|
|
|
|
|
|
|
class WinObjFontHandle: public WinObjHandle
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual void apply( TQPainter& p );
|
|
|
|
TQFont font;
|
|
|
|
int rotation;
|
|
|
|
virtual ~WinObjFontHandle() {};
|
|
|
|
};
|
|
|
|
|
|
|
|
void WinObjBrushHandle::apply( TQPainter& p )
|
|
|
|
{
|
|
|
|
p.setBrush( brush );
|
|
|
|
}
|
|
|
|
|
|
|
|
void WinObjPenHandle::apply( TQPainter& p )
|
|
|
|
{
|
|
|
|
p.setPen( pen );
|
|
|
|
}
|
|
|
|
|
|
|
|
void WinObjPatternBrushHandle::apply( TQPainter& p )
|
|
|
|
{
|
|
|
|
p.setBrush( brush );
|
|
|
|
}
|
|
|
|
|
|
|
|
void WinObjFontHandle::apply( TQPainter& p )
|
|
|
|
{
|
|
|
|
p.setFont( font );
|
|
|
|
}
|
|
|
|
|
|
|
|
#define MAX_OBJHANDLE 64
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
QWinMetaFile::QWinMetaFile()
|
|
|
|
{
|
|
|
|
mValid = false;
|
|
|
|
mFirstCmd = NULL;
|
|
|
|
mObjHandleTab = NULL;
|
|
|
|
mDpi = 1000;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
QWinMetaFile::~QWinMetaFile()
|
|
|
|
{
|
|
|
|
if ( mFirstCmd ) delete mFirstCmd;
|
|
|
|
if ( mObjHandleTab ) delete[] mObjHandleTab;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool QWinMetaFile::load( const TQString &filename )
|
|
|
|
{
|
|
|
|
TQFile file( filename );
|
|
|
|
|
|
|
|
if ( !file.exists() )
|
|
|
|
{
|
|
|
|
kdDebug() << "File " << TQString(TQFile::encodeName(filename)) << " does not exist" << endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !file.open( IO_ReadOnly ) )
|
|
|
|
{
|
|
|
|
kdDebug() << "Cannot open file " << TQString(TQFile::encodeName(filename)) << endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQByteArray ba = file.readAll();
|
|
|
|
file.close();
|
|
|
|
|
|
|
|
TQBuffer buffer( ba );
|
|
|
|
buffer.open( IO_ReadOnly );
|
|
|
|
return load( buffer );
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool QWinMetaFile::load( TQBuffer &buffer )
|
|
|
|
{
|
|
|
|
TQDataStream st;
|
|
|
|
WmfEnhMetaHeader eheader;
|
|
|
|
WmfMetaHeader header;
|
|
|
|
WmfPlaceableHeader pheader;
|
|
|
|
WORD checksum;
|
|
|
|
int filePos, idx, i;
|
|
|
|
WmfCmd *cmd, *last;
|
|
|
|
DWORD rdSize;
|
|
|
|
WORD rdFunc;
|
|
|
|
|
|
|
|
mTextAlign = 0;
|
|
|
|
mRotation = 0;
|
|
|
|
mTextColor = TQt::black;
|
|
|
|
if ( mFirstCmd ) delete mFirstCmd;
|
|
|
|
mFirstCmd = NULL;
|
|
|
|
|
|
|
|
st.setDevice( &buffer );
|
|
|
|
st.setByteOrder( TQDataStream::LittleEndian ); // Great, I love TQt !
|
|
|
|
|
|
|
|
//----- Read placeable metafile header
|
|
|
|
st >> pheader.key;
|
|
|
|
mIsPlaceable = ( pheader.key==( DWORD )APMHEADER_KEY );
|
|
|
|
if ( mIsPlaceable )
|
|
|
|
{
|
|
|
|
st >> pheader.hmf;
|
|
|
|
st >> pheader.bbox.left;
|
|
|
|
st >> pheader.bbox.top;
|
|
|
|
st >> pheader.bbox.right;
|
|
|
|
st >> pheader.bbox.bottom;
|
|
|
|
st >> pheader.inch;
|
|
|
|
st >> pheader.reserved;
|
|
|
|
st >> pheader.checksum;
|
|
|
|
checksum = calcCheckSum( &pheader );
|
|
|
|
if ( pheader.checksum!=checksum ) mIsPlaceable = false;
|
|
|
|
|
|
|
|
mDpi = pheader.inch;
|
|
|
|
mBBox.setLeft( pheader.bbox.left );
|
|
|
|
mBBox.setTop( pheader.bbox.top );
|
|
|
|
mBBox.setRight( pheader.bbox.right );
|
|
|
|
mBBox.setBottom( pheader.bbox.bottom );
|
|
|
|
mHeaderBoundingBox = mBBox;
|
|
|
|
if ( TQWMF_DEBUG )
|
|
|
|
{
|
|
|
|
kdDebug() << endl << "-------------------------------------------------" << endl;
|
|
|
|
kdDebug() << "WMF Placeable Header ( " << static_cast<int>(sizeof( pheader ) ) << "):" << endl;
|
|
|
|
kdDebug() << " bbox=( " << mBBox.left() << "; " << mBBox.top() << "; " << mBBox.width()
|
|
|
|
<< "; " << mBBox.height() << ")" << endl;
|
|
|
|
kdDebug() << " inch=" << pheader.inch << endl;
|
|
|
|
kdDebug() << " checksum=" << pheader.checksum << "( "
|
|
|
|
<< (pheader.checksum==checksum?"ok":"wrong") << " )" << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else buffer.at( 0 );
|
|
|
|
|
|
|
|
//----- Read as enhanced metafile header
|
|
|
|
filePos = buffer.at();
|
|
|
|
st >> eheader.iType;
|
|
|
|
st >> eheader.nSize;
|
|
|
|
st >> eheader.rclBounds.left;
|
|
|
|
st >> eheader.rclBounds.top;
|
|
|
|
st >> eheader.rclBounds.right;
|
|
|
|
st >> eheader.rclBounds.bottom;
|
|
|
|
st >> eheader.rclFrame.left;
|
|
|
|
st >> eheader.rclFrame.top;
|
|
|
|
st >> eheader.rclFrame.right;
|
|
|
|
st >> eheader.rclFrame.bottom;
|
|
|
|
st >> eheader.dSignature;
|
|
|
|
mIsEnhanced = ( eheader.dSignature==ENHMETA_SIGNATURE );
|
|
|
|
if ( mIsEnhanced ) // is it really enhanced ?
|
|
|
|
{
|
|
|
|
st >> eheader.nVersion;
|
|
|
|
st >> eheader.nBytes;
|
|
|
|
st >> eheader.nRecords;
|
|
|
|
st >> eheader.nHandles;
|
|
|
|
st >> eheader.sReserved;
|
|
|
|
st >> eheader.nDescription;
|
|
|
|
st >> eheader.offDescription;
|
|
|
|
st >> eheader.nPalEntries;
|
|
|
|
st >> eheader.szlDevice.width;
|
|
|
|
st >> eheader.szlDevice.height;
|
|
|
|
st >> eheader.szlMillimeters.width;
|
|
|
|
st >> eheader.szlMillimeters.height;
|
|
|
|
|
|
|
|
if ( TQWMF_DEBUG )
|
|
|
|
{
|
|
|
|
kdDebug() << endl << "-------------------------------------------------" << endl;
|
|
|
|
kdDebug() << "WMF Extended Header:" << endl;
|
|
|
|
kdDebug() << " iType=" << eheader.iType << endl;
|
|
|
|
kdDebug() << " nSize=" << eheader.nSize << endl;
|
|
|
|
kdDebug() << " rclBounds=( " << eheader.rclBounds.left << "; " << eheader.rclBounds.top << "; "
|
|
|
|
<< eheader.rclBounds.right << "; " << eheader.rclBounds.bottom << ")" << endl;
|
|
|
|
kdDebug() << " rclFrame=( " << eheader.rclFrame.left << "; " << eheader.rclFrame.top << "; "
|
|
|
|
<< eheader.rclFrame.right << "; " << eheader.rclFrame.bottom << ")" << endl;
|
|
|
|
kdDebug() << " nBytes=" << eheader.nBytes << endl;
|
|
|
|
kdDebug() << "\nNOT YET IMPLEMENTED, SORRY." << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else // no, not enhanced
|
|
|
|
{
|
|
|
|
//----- Read as standard metafile header
|
|
|
|
buffer.at( filePos );
|
|
|
|
st >> header.mtType;
|
|
|
|
st >> header.mtHeaderSize;
|
|
|
|
st >> header.mtVersion;
|
|
|
|
st >> header.mtSize;
|
|
|
|
st >> header.mtNoObjects;
|
|
|
|
st >> header.mtMaxRecord;
|
|
|
|
st >> header.mtNoParameters;
|
|
|
|
if ( TQWMF_DEBUG ) {
|
|
|
|
kdDebug() << "WMF Header: " << "mtSize=" << header.mtSize << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----- Test header validity
|
|
|
|
mValid = ((header.mtHeaderSize == 9) && (header.mtNoParameters == 0)) || mIsEnhanced || mIsPlaceable;
|
|
|
|
if ( mValid )
|
|
|
|
{
|
|
|
|
//----- Read Metafile Records
|
|
|
|
last = NULL;
|
|
|
|
rdFunc = -1;
|
|
|
|
while ( !st.eof() && (rdFunc != 0) )
|
|
|
|
{
|
|
|
|
st >> rdSize;
|
|
|
|
st >> rdFunc;
|
|
|
|
idx = findFunc( rdFunc );
|
|
|
|
rdSize -= 3;
|
|
|
|
|
|
|
|
cmd = new WmfCmd;
|
|
|
|
cmd->next = NULL;
|
|
|
|
if ( last ) last->next = cmd;
|
|
|
|
else mFirstCmd = cmd;
|
|
|
|
|
|
|
|
cmd->funcIndex = idx;
|
|
|
|
cmd->numParm = rdSize;
|
|
|
|
cmd->parm = new WORD[ rdSize ];
|
|
|
|
last = cmd;
|
|
|
|
|
|
|
|
for ( i=0; i<rdSize && !st.eof(); i++ )
|
|
|
|
st >> cmd->parm[ i ];
|
|
|
|
|
|
|
|
|
|
|
|
if ( rdFunc == 0x020B ) { // SETWINDOWORG: dimensions
|
|
|
|
mBBox.setLeft( cmd->parm[ 1 ] );
|
|
|
|
mBBox.setTop( cmd->parm[ 0 ] );
|
|
|
|
}
|
|
|
|
if ( rdFunc == 0x020C ) { // SETWINDOWEXT: dimensions
|
|
|
|
mBBox.setWidth( cmd->parm[ 1 ] );
|
|
|
|
mBBox.setHeight( cmd->parm[ 0 ] );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( i<rdSize )
|
|
|
|
{
|
|
|
|
kdDebug() << "WMF : file truncated !" << endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//----- Test records validities
|
|
|
|
mValid = (rdFunc == 0) && (mBBox.width() != 0) && (mBBox.height() != 0);
|
|
|
|
if ( !mValid ) {
|
|
|
|
kdDebug() << "WMF : incorrect file format !" << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
kdDebug() << "WMF Header : incorrect header !" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer.close();
|
|
|
|
return mValid;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool QWinMetaFile::paint( const TQPaintDevice* aTarget, bool absolute )
|
|
|
|
{
|
|
|
|
int idx, i;
|
|
|
|
WmfCmd* cmd;
|
|
|
|
|
|
|
|
if ( !mValid ) return false;
|
|
|
|
|
|
|
|
assert( aTarget!=NULL );
|
|
|
|
if ( mPainter.isActive() ) return false;
|
|
|
|
|
|
|
|
if ( mObjHandleTab ) delete[] mObjHandleTab;
|
|
|
|
mObjHandleTab = new WinObjHandle* [ MAX_OBJHANDLE ];
|
|
|
|
for ( i=MAX_OBJHANDLE-1; i>=0; i-- )
|
|
|
|
mObjHandleTab[ i ] = NULL;
|
|
|
|
|
|
|
|
mPainter.resetXForm();
|
|
|
|
mWinding = false;
|
|
|
|
mAbsoluteCoord = absolute;
|
|
|
|
|
|
|
|
mPainter.tqbegin( const_cast<TQPaintDevice*>(aTarget) );
|
|
|
|
if ( TQWMF_DEBUG ) {
|
|
|
|
kdDebug() << "Bounding box : " << mBBox.left()
|
|
|
|
<< " " << mBBox.top() << " " << mBBox.right() << " " << mBBox.bottom() << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( mAbsoluteCoord ) {
|
|
|
|
mPainter.setWindow( mBBox.top(), mBBox.left(), mBBox.width(), mBBox.height() );
|
|
|
|
}
|
|
|
|
mInternalWorldMatrix.reset();
|
|
|
|
|
|
|
|
for ( cmd=mFirstCmd; cmd; cmd=cmd->next )
|
|
|
|
{
|
|
|
|
idx = cmd->funcIndex;
|
|
|
|
( this->*metaFuncTab[ idx ].method )( cmd->numParm, cmd->parm );
|
|
|
|
|
|
|
|
if ( TQWMF_DEBUG ) {
|
|
|
|
TQString str = "", param;
|
|
|
|
if ( metaFuncTab[ idx ].name == NULL ) {
|
|
|
|
str += "UNKNOWN ";
|
|
|
|
}
|
|
|
|
if ( metaFuncTab[ idx ].method == &QWinMetaFile::noop ) {
|
|
|
|
str += "UNIMPLEMENTED ";
|
|
|
|
}
|
|
|
|
str += metaFuncTab[ idx ].name;
|
|
|
|
str += " : ";
|
|
|
|
|
|
|
|
for ( i=0 ; i < cmd->numParm ; i++ ) {
|
|
|
|
param.setNum( cmd->parm[ i ] );
|
|
|
|
str += param;
|
|
|
|
str += " ";
|
|
|
|
}
|
|
|
|
kdDebug() << str << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
// TODO: cleanup this code when TQPicture::setBoundingBox() is possible in KOClipart (QT31)
|
|
|
|
// because actually TQPicture::boundingBox() != mBBox()
|
|
|
|
mWindowsCoord += 1;
|
|
|
|
if ( mWindowsCoord == 2 ) {
|
|
|
|
kdDebug() << "DRAW ANGLES " << endl;
|
|
|
|
mPainter.setPen( TQt::white );
|
|
|
|
mPainter.drawPoint( mBBox.left(), mBBox.top() );
|
|
|
|
mPainter.drawPoint( mBBox.right(), mBBox.bottom() );
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
mPainter.end();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//----------------s-------------------------------------------------------------
|
|
|
|
// Metafile painter methods
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::setWindowOrg( long, short* parm )
|
|
|
|
{
|
|
|
|
if ( mAbsoluteCoord ) {
|
|
|
|
TQRect r = mPainter.window();
|
|
|
|
mPainter.setWindow( parm[ 1 ], parm[ 0 ], r.width(), r.height() );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
double dx = mInternalWorldMatrix.dx();
|
|
|
|
double dy = mInternalWorldMatrix.dy();
|
|
|
|
|
|
|
|
mInternalWorldMatrix.translate( -dx, -dy );
|
|
|
|
mInternalWorldMatrix.translate( -parm[ 1 ], -parm[ 0 ] );
|
|
|
|
mPainter.translate( -dx, -dy );
|
|
|
|
mPainter.translate( -parm[ 1 ], -parm[ 0 ] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::setWindowExt( long, short* parm )
|
|
|
|
{
|
|
|
|
// negative value allowed for width and height : TQABS() forbidden
|
|
|
|
if ( mAbsoluteCoord ) {
|
|
|
|
TQRect r = mPainter.window();
|
|
|
|
mPainter.setWindow( r.left(), r.top(), parm[ 1 ], parm[ 0 ] );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if ( (parm[ 0 ] != 0) && (parm[ 1 ] != 0) ) {
|
|
|
|
TQRect r = mPainter.window();
|
|
|
|
double dx = mInternalWorldMatrix.dx();
|
|
|
|
double dy = mInternalWorldMatrix.dy();
|
|
|
|
double sx = mInternalWorldMatrix.m11();
|
|
|
|
double sy = mInternalWorldMatrix.m22();
|
|
|
|
|
|
|
|
mInternalWorldMatrix.translate( -dx, -dy );
|
|
|
|
mInternalWorldMatrix.scale( 1/sx, 1/sy );
|
|
|
|
mPainter.translate( -dx, -dy );
|
|
|
|
mPainter.scale( 1/sx, 1/sy );
|
|
|
|
|
|
|
|
sx = (double)r.width() / (double)parm[ 1 ];
|
|
|
|
sy = (double)r.height() / (double)parm[ 0 ];
|
|
|
|
|
|
|
|
mInternalWorldMatrix.scale( sx, sy );
|
|
|
|
mInternalWorldMatrix.translate( dx, dy );
|
|
|
|
mPainter.scale( sx, sy );
|
|
|
|
mPainter.translate( dx, dy );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Drawing
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::lineTo( long, short* parm )
|
|
|
|
{
|
|
|
|
mPainter.lineTo( parm[ 1 ], parm[ 0 ] );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::moveTo( long, short* parm )
|
|
|
|
{
|
|
|
|
mPainter.moveTo( parm[ 1 ], parm[ 0 ] );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::ellipse( long, short* parm )
|
|
|
|
{
|
|
|
|
mPainter.drawEllipse( parm[ 3 ], parm[ 2 ], parm[ 1 ]-parm[ 3 ], parm[ 0 ]-parm[ 2 ] );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::polygon( long, short* parm )
|
|
|
|
{
|
|
|
|
TQPointArray* pa;
|
|
|
|
|
|
|
|
pa = pointArray( parm[ 0 ], &parm[ 1 ] );
|
|
|
|
mPainter.tqdrawPolygon( *pa, mWinding );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::polyPolygon( long, short* parm )
|
|
|
|
{
|
|
|
|
TQRegion region;
|
|
|
|
int i, j, startPolygon;
|
|
|
|
|
|
|
|
mPainter.save();
|
|
|
|
|
|
|
|
// define clipping region
|
|
|
|
TQRect win = bbox();
|
|
|
|
startPolygon = 1+parm[ 0 ];
|
|
|
|
for ( i=0 ; i < parm[ 0 ] ; i++ ) {
|
|
|
|
TQPointArray pa1( parm[ 1+i ] );
|
|
|
|
for ( j=0 ; j < parm[ 1+i ] ; j++) {
|
|
|
|
pa1.setPoint ( j, parm[ startPolygon ], parm[ startPolygon+1 ] );
|
|
|
|
startPolygon += 2;
|
|
|
|
}
|
|
|
|
TQRegion r( pa1 );
|
|
|
|
region = region.eor( r );
|
|
|
|
}
|
|
|
|
mPainter.setClipRegion( region, TQPainter::CoordPainter );
|
|
|
|
|
|
|
|
// fill polygons
|
|
|
|
mPainter.fillRect( win.left(), win.top(), win.width(), win.height(), mPainter.brush() );
|
|
|
|
|
|
|
|
// draw polygon's border if necessary
|
|
|
|
if ( mPainter.pen().style() != TQt::NoPen ) {
|
|
|
|
mPainter.setClipping( false );
|
|
|
|
mPainter.setBrush( TQt::NoBrush );
|
|
|
|
|
|
|
|
TQPointArray* pa;
|
|
|
|
int idxPolygon = 1 + parm[ 0 ];
|
|
|
|
for ( i=0 ; i < parm[ 0 ] ; i++ ) {
|
|
|
|
pa = pointArray( parm[ 1+i ], &parm[ idxPolygon ] );
|
|
|
|
mPainter.drawPolygon( *pa );
|
|
|
|
idxPolygon += parm[ 1+i ] * 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mPainter.restore();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::polyline( long, short* parm )
|
|
|
|
{
|
|
|
|
TQPointArray* pa;
|
|
|
|
|
|
|
|
pa = pointArray( parm[ 0 ], &parm[ 1 ] );
|
|
|
|
mPainter.drawPolyline( *pa );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::rectangle( long, short* parm )
|
|
|
|
{
|
|
|
|
mPainter.drawRect( parm[ 3 ], parm[ 2 ], parm[ 1 ]-parm[ 3 ], parm[ 0 ]-parm[ 2 ] );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::roundRect( long, short* parm )
|
|
|
|
{
|
|
|
|
int xRnd = 0, yRnd = 0;
|
|
|
|
|
|
|
|
// convert (xRound, yRound) in percentage
|
|
|
|
if ( (parm[ 3 ] - parm[ 5 ]) != 0 )
|
|
|
|
xRnd = (parm[ 1 ] * 100) / (parm[ 3 ] - parm[ 5 ]) ;
|
|
|
|
if ( (parm[ 2 ] - parm[ 4 ]) != 0 )
|
|
|
|
yRnd = (parm[ 0 ] * 100) / (parm[ 2 ] - parm[ 4 ]) ;
|
|
|
|
|
|
|
|
mPainter.drawRoundRect( parm[ 5 ], parm[ 4 ], parm[ 3 ]-parm[ 5 ], parm[ 2 ]-parm[ 4 ], xRnd, yRnd );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::arc( long, short* parm )
|
|
|
|
{
|
|
|
|
int xCenter, yCenter, angleStart, aLength;
|
|
|
|
|
|
|
|
xCenter = parm[ 7 ] + ((parm[ 5 ] - parm[ 7 ]) / 2);
|
|
|
|
yCenter = parm[ 6 ] + ((parm[ 4 ] - parm[ 6 ]) / 2);
|
|
|
|
|
|
|
|
xyToAngle ( parm[ 3 ] - xCenter, yCenter - parm[ 2 ], parm[ 1 ] - xCenter, yCenter - parm[ 0 ], angleStart, aLength );
|
|
|
|
|
|
|
|
mPainter.drawArc( parm[ 7 ], parm[ 6 ], parm[ 5 ]-parm[ 7 ], parm[ 4 ]-parm[ 6 ], angleStart, aLength);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::chord( long, short* parm )
|
|
|
|
{
|
|
|
|
int xCenter, yCenter, angleStart, aLength;
|
|
|
|
|
|
|
|
xCenter = parm[ 7 ] + ((parm[ 5 ] - parm[ 7 ]) / 2);
|
|
|
|
yCenter = parm[ 6 ] + ((parm[ 4 ] - parm[ 6 ]) / 2);
|
|
|
|
|
|
|
|
xyToAngle ( parm[ 3 ] - xCenter, yCenter - parm[ 2 ], parm[ 1 ] - xCenter, yCenter - parm[ 0 ], angleStart, aLength );
|
|
|
|
|
|
|
|
mPainter.drawChord( parm[ 7 ], parm[ 6 ], parm[ 5 ]-parm[ 7 ], parm[ 4 ]-parm[ 6 ], angleStart, aLength);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::pie( long, short* parm )
|
|
|
|
{
|
|
|
|
int xCenter, yCenter, angleStart, aLength;
|
|
|
|
|
|
|
|
xCenter = parm[ 7 ] + ((parm[ 5 ] - parm[ 7 ]) / 2);
|
|
|
|
yCenter = parm[ 6 ] + ((parm[ 4 ] - parm[ 6 ]) / 2);
|
|
|
|
|
|
|
|
xyToAngle ( parm[ 3 ] - xCenter, yCenter - parm[ 2 ], parm[ 1 ] - xCenter, yCenter - parm[ 0 ], angleStart, aLength );
|
|
|
|
|
|
|
|
mPainter.drawPie( parm[ 7 ], parm[ 6 ], parm[ 5 ]-parm[ 7 ], parm[ 4 ]-parm[ 6 ], angleStart, aLength);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::setPolyFillMode( long, short* parm )
|
|
|
|
{
|
|
|
|
mWinding = parm[ 0 ];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::setBkColor( long, short* parm )
|
|
|
|
{
|
|
|
|
mPainter.setBackgroundColor( color( parm ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::setBkMode( long, short* parm )
|
|
|
|
{
|
|
|
|
if ( parm[ 0 ]==1 ) mPainter.setBackgroundMode( Qt::TransparentMode );
|
|
|
|
else mPainter.setBackgroundMode( Qt::OpaqueMode );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::setPixel( long, short* parm )
|
|
|
|
{
|
|
|
|
TQPen pen = mPainter.pen();
|
|
|
|
mPainter.setPen( color( parm ) );
|
|
|
|
mPainter.drawPoint( parm[ 3 ], parm[ 2 ] );
|
|
|
|
mPainter.setPen( pen );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::setRop( long, short* parm )
|
|
|
|
{
|
|
|
|
mPainter.setRasterOp( winToTQtRaster( parm[ 0 ] ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::saveDC( long, short* )
|
|
|
|
{
|
|
|
|
mPainter.save();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::restoreDC( long, short *parm )
|
|
|
|
{
|
|
|
|
for ( int i=0; i > parm[ 0 ] ; i-- )
|
|
|
|
mPainter.restore();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::intersectClipRect( long, short* parm )
|
|
|
|
{
|
|
|
|
/* TODO: better implementation : need QT 3.0.2
|
|
|
|
TQRegion region = mPainter.clipRegion();
|
|
|
|
if ( region.isEmpty() )
|
|
|
|
region = bbox();
|
|
|
|
*/
|
|
|
|
TQRegion region( bbox() );
|
|
|
|
|
|
|
|
TQRegion newRegion( parm[ 3 ], parm[ 2 ], parm[ 1 ] - parm[ 3 ], parm[ 0 ] - parm[ 2 ] );
|
|
|
|
region = region.intersect( newRegion );
|
|
|
|
|
|
|
|
mPainter.setClipRegion( region, TQPainter::CoordPainter );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::excludeClipRect( long, short* parm )
|
|
|
|
{
|
|
|
|
/* TODO: better implementation : need QT 3.0.2
|
|
|
|
TQRegion region = mPainter.clipRegion();
|
|
|
|
if ( region.isEmpty() )
|
|
|
|
region = bbox();
|
|
|
|
*/
|
|
|
|
TQRegion region( bbox() );
|
|
|
|
|
|
|
|
TQRegion newRegion( parm[ 3 ], parm[ 2 ], parm[ 1 ] - parm[ 3 ], parm[ 0 ] - parm[ 2 ] );
|
|
|
|
region = region.subtract( newRegion );
|
|
|
|
|
|
|
|
mPainter.setClipRegion( region, TQPainter::CoordPainter );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Text
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::setTextColor( long, short* parm )
|
|
|
|
{
|
|
|
|
mTextColor = color( parm );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::setTextAlign( long, short* parm )
|
|
|
|
{
|
|
|
|
mTextAlign = parm[ 0 ];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::textOut( long num, short* parm )
|
|
|
|
{
|
|
|
|
|
|
|
|
short *copyParm = new short[ num + 1 ];
|
|
|
|
|
|
|
|
// re-order parameters
|
|
|
|
int idxOffset = (parm[ 0 ] / 2) + 1 + (parm[ 0 ] & 1);
|
|
|
|
copyParm[ 0 ] = parm[ idxOffset ];
|
|
|
|
copyParm[ 1 ] = parm[ idxOffset + 1 ];
|
|
|
|
copyParm[ 2 ] = parm[ 0 ];
|
|
|
|
copyParm[ 3 ] = 0;
|
|
|
|
memcpy( ©Parm[ 4 ], &parm[ 1 ], parm[ 0 ] );
|
|
|
|
|
|
|
|
extTextOut( num + 1, copyParm );
|
|
|
|
delete [] copyParm;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::extTextOut( long num, short* parm )
|
|
|
|
{
|
|
|
|
char* ptStr;
|
|
|
|
int x, y, width, height;
|
|
|
|
int idxOffset;
|
|
|
|
|
|
|
|
if ( parm[ 3 ] != 0 ) // ETO_CLIPPED flag add 4 parameters
|
|
|
|
ptStr = (char*)&parm[ 8 ];
|
|
|
|
else
|
|
|
|
ptStr = (char*)&parm[ 4 ];
|
|
|
|
|
|
|
|
TQCString text( ptStr, parm[ 2 ] + 1 );
|
|
|
|
|
|
|
|
TQFontMetrics fm( mPainter.font() );
|
|
|
|
width = fm.width( text ) + fm.descent(); // because fm.width(text) isn't rigth with Italic text
|
|
|
|
height = fm.height();
|
|
|
|
|
|
|
|
mPainter.save();
|
|
|
|
|
|
|
|
if ( mTextAlign & 0x01 ) { // (left, top) position = current logical position
|
|
|
|
TQPoint pos = mPainter.pos();
|
|
|
|
x = pos.x();
|
|
|
|
y = pos.y();
|
|
|
|
}
|
|
|
|
else { // (left, top) position = parameters
|
|
|
|
x = parm[ 1 ];
|
|
|
|
y = parm[ 0 ];
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( mRotation ) {
|
|
|
|
mPainter.translate( parm[ 1 ], parm[ 0 ]);
|
|
|
|
mPainter.rotate ( mRotation );
|
|
|
|
mPainter.translate( -parm[ 1 ], -parm[ 0 ] );
|
|
|
|
}
|
|
|
|
|
|
|
|
// tqalignment
|
|
|
|
if ( mTextAlign & 0x06 )
|
|
|
|
x -= ( width / 2 );
|
|
|
|
if ( mTextAlign & 0x08 )
|
|
|
|
y -= (height - fm.descent());
|
|
|
|
|
|
|
|
mPainter.setPen( mTextColor );
|
|
|
|
idxOffset = (parm[ 2 ] / 2) + 4 + (parm[ 2 ] & 1);
|
|
|
|
if ( ( parm[ 2 ] > 1 ) && ( num >= (idxOffset + parm[ 2 ]) ) && ( parm[ 3 ] == 0 ) ) {
|
|
|
|
// offset for each char
|
|
|
|
int left = x;
|
|
|
|
mPainter.drawText( left, y, width, height, TQt::AlignLeft | TQt::AlignTop, text.mid(0, 1) );
|
|
|
|
for ( int i = 1; i < parm[ 2 ] ; i++ ) {
|
|
|
|
left += parm[ idxOffset + i - 1 ];
|
|
|
|
mPainter.drawText( left, y, width, height, TQt::AlignLeft | TQt::AlignTop, text.mid(i, 1) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mPainter.drawText( x, y, width, height, TQt::AlignLeft | TQt::AlignTop, text );
|
|
|
|
}
|
|
|
|
|
|
|
|
mPainter.restore();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Bitmap
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::dibBitBlt( long num, short* parm )
|
|
|
|
{
|
|
|
|
if ( num > 9 ) { // DIB image
|
|
|
|
TQImage bmpSrc;
|
|
|
|
|
|
|
|
if ( dibToBmp( bmpSrc, (char*)&parm[ 8 ], (num - 8) * 2 ) ) {
|
|
|
|
long raster = toDWord( parm );
|
|
|
|
|
|
|
|
mPainter.setRasterOp( winToTQtRaster( raster ) );
|
|
|
|
|
|
|
|
// wmf file allow negative width or height
|
|
|
|
mPainter.save();
|
|
|
|
if ( parm[ 5 ] < 0 ) { // width < 0 => horizontal flip
|
|
|
|
TQWMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
|
|
|
|
mPainter.setWorldMatrix( m, true );
|
|
|
|
}
|
|
|
|
if ( parm[ 4 ] < 0 ) { // height < 0 => vertical flip
|
|
|
|
TQWMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
|
|
|
|
mPainter.setWorldMatrix( m, true );
|
|
|
|
}
|
|
|
|
mPainter.drawImage( parm[ 7 ], parm[ 6 ], bmpSrc, parm[ 3 ], parm[ 2 ], parm[ 5 ], parm[ 4 ] );
|
|
|
|
mPainter.restore();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
kdDebug() << "QWinMetaFile::dibBitBlt without image: not implemented " << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::dibStretchBlt( long num, short* parm )
|
|
|
|
{
|
|
|
|
TQImage bmpSrc;
|
|
|
|
|
|
|
|
if ( dibToBmp( bmpSrc, (char*)&parm[ 10 ], (num - 10) * 2 ) ) {
|
|
|
|
long raster = toDWord( parm );
|
|
|
|
|
|
|
|
mPainter.setRasterOp( winToTQtRaster( raster ) );
|
|
|
|
|
|
|
|
// wmf file allow negative width or height
|
|
|
|
mPainter.save();
|
|
|
|
if ( parm[ 7 ] < 0 ) { // width < 0 => horizontal flip
|
|
|
|
TQWMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
|
|
|
|
mPainter.setWorldMatrix( m, true );
|
|
|
|
}
|
|
|
|
if ( parm[ 6 ] < 0 ) { // height < 0 => vertical flip
|
|
|
|
TQWMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
|
|
|
|
mPainter.setWorldMatrix( m, true );
|
|
|
|
}
|
|
|
|
bmpSrc = bmpSrc.copy( parm[ 5 ], parm[ 4 ], parm[ 3 ], parm[ 2 ] );
|
|
|
|
// TODO: scale the bitmap ( TQImage::scale(parm[ 7 ], parm[ 6 ]) is actually too slow )
|
|
|
|
|
|
|
|
mPainter.drawImage( parm[ 9 ], parm[ 8 ], bmpSrc );
|
|
|
|
mPainter.restore();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::stretchDib( long num, short* parm )
|
|
|
|
{
|
|
|
|
TQImage bmpSrc;
|
|
|
|
|
|
|
|
if ( dibToBmp( bmpSrc, (char*)&parm[ 11 ], (num - 11) * 2 ) ) {
|
|
|
|
long raster = toDWord( parm );
|
|
|
|
|
|
|
|
mPainter.setRasterOp( winToTQtRaster( raster ) );
|
|
|
|
|
|
|
|
// wmf file allow negative width or height
|
|
|
|
mPainter.save();
|
|
|
|
if ( parm[ 8 ] < 0 ) { // width < 0 => horizontal flip
|
|
|
|
TQWMatrix m( -1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F );
|
|
|
|
mPainter.setWorldMatrix( m, true );
|
|
|
|
}
|
|
|
|
if ( parm[ 7 ] < 0 ) { // height < 0 => vertical flip
|
|
|
|
TQWMatrix m( 1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F );
|
|
|
|
mPainter.setWorldMatrix( m, true );
|
|
|
|
}
|
|
|
|
bmpSrc = bmpSrc.copy( parm[ 6 ], parm[ 5 ], parm[ 4 ], parm[ 3 ] );
|
|
|
|
// TODO: scale the bitmap ( TQImage::scale(parm[ 8 ], parm[ 7 ]) is actually too slow )
|
|
|
|
|
|
|
|
mPainter.drawImage( parm[ 10 ], parm[ 9 ], bmpSrc );
|
|
|
|
mPainter.restore();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::dibCreatePatternBrush( long num, short* parm )
|
|
|
|
{
|
|
|
|
WinObjPatternBrushHandle* handle = new WinObjPatternBrushHandle;
|
|
|
|
addHandle( handle );
|
|
|
|
TQImage bmpSrc;
|
|
|
|
|
|
|
|
if ( dibToBmp( bmpSrc, (char*)&parm[ 2 ], (num - 2) * 2 ) ) {
|
|
|
|
handle->image = bmpSrc;
|
|
|
|
handle->brush.setPixmap( handle->image );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Object handle
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::selectObject( long, short* parm )
|
|
|
|
{
|
|
|
|
int idx = parm[ 0 ];
|
|
|
|
if ( idx>=0 && idx < MAX_OBJHANDLE && mObjHandleTab[ idx ] )
|
|
|
|
mObjHandleTab[ idx ]->apply( mPainter );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::deleteObject( long, short* parm )
|
|
|
|
{
|
|
|
|
deleteHandle( parm[ 0 ] );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::createEmptyObject( long, short* )
|
|
|
|
{
|
|
|
|
// allocation of an empty object (to keep object counting in sync)
|
|
|
|
WinObjPenHandle* handle = new WinObjPenHandle;
|
|
|
|
addHandle( handle );
|
|
|
|
kdDebug() << "QWinMetaFile: unimplemented createObject " << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::createBrushIndirect( long, short* parm )
|
|
|
|
{
|
|
|
|
static Qt::BrushStyle hatchedStyleTab[] =
|
|
|
|
{
|
|
|
|
Qt::HorPattern,
|
|
|
|
Qt::FDiagPattern,
|
|
|
|
Qt::BDiagPattern,
|
|
|
|
Qt::CrossPattern,
|
|
|
|
Qt::DiagCrossPattern
|
|
|
|
};
|
|
|
|
static Qt::BrushStyle styleTab[] =
|
|
|
|
{ Qt::SolidPattern,
|
|
|
|
Qt::NoBrush,
|
|
|
|
Qt::FDiagPattern, /* hatched */
|
|
|
|
Qt::Dense4Pattern, /* should be custom bitmap pattern */
|
|
|
|
Qt::HorPattern, /* should be BS_INDEXED (?) */
|
|
|
|
Qt::VerPattern, /* should be device-independent bitmap */
|
|
|
|
Qt::Dense6Pattern, /* should be device-independent packed-bitmap */
|
|
|
|
Qt::Dense2Pattern, /* should be BS_PATTERN8x8 */
|
|
|
|
Qt::Dense3Pattern /* should be device-independent BS_DIBPATTERN8x8 */
|
|
|
|
};
|
|
|
|
Qt::BrushStyle style;
|
|
|
|
short arg;
|
|
|
|
WinObjBrushHandle* handle = new WinObjBrushHandle;
|
|
|
|
addHandle( handle );
|
|
|
|
|
|
|
|
arg = parm[ 0 ];
|
|
|
|
if ( arg==2 )
|
|
|
|
{
|
|
|
|
arg = parm[ 3 ];
|
|
|
|
if ( arg>=0 && arg<5 ) style = hatchedStyleTab[ arg ];
|
|
|
|
else
|
|
|
|
{
|
|
|
|
kdDebug() << "QWinMetaFile::createBrushIndirect: invalid hatched brush " << arg << endl;
|
|
|
|
style = Qt::SolidPattern;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( arg>=0 && arg<9 )
|
|
|
|
style = styleTab[ arg ];
|
|
|
|
else
|
|
|
|
{
|
|
|
|
kdDebug() << "QWinMetaFile::createBrushIndirect: invalid brush " << arg << endl;
|
|
|
|
style = Qt::SolidPattern;
|
|
|
|
}
|
|
|
|
handle->brush.setStyle( style );
|
|
|
|
handle->brush.setColor( color( parm+1 ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::createPenIndirect( long, short* parm )
|
|
|
|
{
|
|
|
|
static Qt::PenStyle styleTab[] =
|
|
|
|
{ Qt::SolidLine, Qt::DashLine, Qt::DotLine, Qt::DashDotLine, Qt::DashDotDotLine,
|
|
|
|
Qt::NoPen, Qt::SolidLine };
|
|
|
|
Qt::PenStyle style;
|
|
|
|
WinObjPenHandle* handle = new WinObjPenHandle;
|
|
|
|
addHandle( handle );
|
|
|
|
|
|
|
|
if ( parm[ 0 ]>=0 && parm[ 0 ]<6 ) style=styleTab[ parm[ 0 ] ];
|
|
|
|
else
|
|
|
|
{
|
|
|
|
kdDebug() << "QWinMetaFile::createPenIndirect: invalid pen " << parm[ 0 ] << endl;
|
|
|
|
style = Qt::SolidLine;
|
|
|
|
}
|
|
|
|
|
|
|
|
handle->pen.setStyle( style );
|
|
|
|
handle->pen.setColor( color( parm+3 ) );
|
|
|
|
handle->pen.setCapStyle( Qt::RoundCap );
|
|
|
|
|
|
|
|
//int width = 0;
|
|
|
|
// TODO : width of pen proportional to device context width
|
|
|
|
// DOESN'T WORK
|
|
|
|
/*
|
|
|
|
TQRect devRec;
|
|
|
|
devRec = mPainter.xForm( mBBox );
|
|
|
|
width = ( parm[ 0 ] * devRec.width() ) / mBBox.width() ;
|
|
|
|
kdDebug() << "CreatePenIndirect: " << endl;
|
|
|
|
kdDebug() << " log coord. : " << mBBox.width() << " " << mBBox.height() << endl;
|
|
|
|
kdDebug() << " log. pen : " << parm[ 1 ] << " " << parm[ 2 ] << endl;
|
|
|
|
kdDebug() << " dev. pen : " << width << endl;
|
|
|
|
handle->pen.setWidth( width );
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::createFontIndirect( long , short* parm)
|
|
|
|
{
|
|
|
|
WinObjFontHandle* handle = new WinObjFontHandle;
|
|
|
|
addHandle( handle );
|
|
|
|
|
|
|
|
TQString family( (const char*)&parm[ 9 ] );
|
|
|
|
|
|
|
|
mRotation = -parm[ 2 ] / 10; // text rotation (in 1/10 degree)
|
|
|
|
// TODO: memorisation of rotation in object Font
|
|
|
|
handle->font.setFamily( family );
|
|
|
|
handle->font.setFixedPitch( ((parm[ 8 ] & 0x01) == 0) );
|
|
|
|
// TODO: investigation why some test case need -2. (size of font in logical point)
|
|
|
|
handle->font.setPointSize( TQABS(parm[ 0 ]) - 2 );
|
|
|
|
handle->font.setWeight( (parm[ 4 ] >> 3) );
|
|
|
|
handle->font.setItalic( (parm[ 5 ] & 0x01) );
|
|
|
|
handle->font.setUnderline( (parm[ 5 ] & 0x100) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Misc
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::noop( long, short* )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void QWinMetaFile::end( long, short* )
|
|
|
|
{
|
|
|
|
// end of file :
|
|
|
|
// kdDebug() << "END bbox=( " << mBBox.left() << "; " << mBBox.top() << "; " << mBBox.width() << "; " << mBBox.height() << ")" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
unsigned short QWinMetaFile::calcCheckSum( WmfPlaceableHeader* apmfh )
|
|
|
|
{
|
|
|
|
WORD* lpWord;
|
|
|
|
WORD wResult, i;
|
|
|
|
|
|
|
|
// Start with the first word
|
|
|
|
wResult = *( lpWord = ( WORD* )( apmfh ) );
|
|
|
|
// XOR in each of the other 9 words
|
|
|
|
for( i=1; i<=9; i++ )
|
|
|
|
{
|
|
|
|
wResult ^= lpWord[ i ];
|
|
|
|
}
|
|
|
|
return wResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
int QWinMetaFile::findFunc( unsigned short aFunc ) const
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for ( i=0; metaFuncTab[ i ].name; i++ )
|
|
|
|
if ( metaFuncTab[ i ].func == aFunc ) return i;
|
|
|
|
|
|
|
|
// here : unknown function
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
TQPointArray* QWinMetaFile::pointArray( short num, short* parm )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
mPoints.resize( num );
|
|
|
|
|
|
|
|
for ( i=0; i<num; i++, parm+=2 )
|
|
|
|
mPoints.setPoint( i, parm[ 0 ], parm[ 1 ] );
|
|
|
|
|
|
|
|
return &mPoints;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
unsigned int QWinMetaFile::toDWord( short* parm )
|
|
|
|
{
|
|
|
|
unsigned int l;
|
|
|
|
|
|
|
|
#if !defined( WORDS_BIGENDIAN )
|
|
|
|
l = *( unsigned int* )( parm );
|
|
|
|
#else
|
|
|
|
char *bytes;
|
|
|
|
char swap[ 4 ];
|
|
|
|
bytes = ( char* )parm;
|
|
|
|
swap[ 0 ] = bytes[ 2 ];
|
|
|
|
swap[ 1 ] = bytes[ 3 ];
|
|
|
|
swap[ 2 ] = bytes[ 0 ];
|
|
|
|
swap[ 3 ] = bytes[ 1 ];
|
|
|
|
l = *( unsigned int* )( swap );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
TQColor QWinMetaFile::color( short* parm )
|
|
|
|
{
|
|
|
|
unsigned int colorRef;
|
|
|
|
int red, green, blue;
|
|
|
|
|
|
|
|
colorRef = toDWord( parm ) & 0xffffff;
|
|
|
|
red = colorRef & 255;
|
|
|
|
green = ( colorRef>>8 ) & 255;
|
|
|
|
blue = ( colorRef>>16 ) & 255;
|
|
|
|
|
|
|
|
return TQColor( red, green, blue );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::xyToAngle( int xStart, int yStart, int xEnd, int yEnd, int& angleStart, int& angleLength )
|
|
|
|
{
|
|
|
|
float aStart, aLength;
|
|
|
|
|
|
|
|
aStart = atan2( yStart, xStart );
|
|
|
|
aLength = atan2( yEnd, xEnd ) - aStart;
|
|
|
|
|
|
|
|
angleStart = (int)(aStart * 2880 / 3.14166);
|
|
|
|
angleLength = (int)(aLength * 2880 / 3.14166);
|
|
|
|
if ( angleLength < 0 ) angleLength = 5760 + angleLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::addHandle( WinObjHandle* handle )
|
|
|
|
{
|
|
|
|
int idx;
|
|
|
|
|
|
|
|
for ( idx=0; idx < MAX_OBJHANDLE ; idx++ )
|
|
|
|
if ( mObjHandleTab[ idx ] == NULL ) break;
|
|
|
|
|
|
|
|
if ( idx < MAX_OBJHANDLE )
|
|
|
|
mObjHandleTab[ idx ] = handle;
|
|
|
|
else
|
|
|
|
kdDebug() << "QWinMetaFile error: handle table full !" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void QWinMetaFile::deleteHandle( int idx )
|
|
|
|
{
|
|
|
|
if ( idx >= 0 && idx < MAX_OBJHANDLE && mObjHandleTab[ idx ] )
|
|
|
|
{
|
|
|
|
delete mObjHandleTab[ idx ];
|
|
|
|
mObjHandleTab[ idx ] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
TQt::RasterOp QWinMetaFile::winToTQtRaster( short parm ) const
|
|
|
|
{
|
|
|
|
static const TQt::RasterOp opTab[] =
|
|
|
|
{
|
|
|
|
TQt::CopyROP,
|
|
|
|
TQt::ClearROP, TQt::NandROP, TQt::NotAndROP, TQt::NotCopyROP,
|
|
|
|
TQt::AndNotROP, TQt::NotROP, TQt::XorROP, TQt::NorROP,
|
|
|
|
TQt::AndROP, TQt::NotXorROP, TQt::NopROP, TQt::NotOrROP,
|
|
|
|
TQt::CopyROP, TQt::OrNotROP, TQt::OrROP, TQt::SetROP
|
|
|
|
};
|
|
|
|
|
|
|
|
if ( parm > 0 && parm <= 16 )
|
|
|
|
return opTab[ parm ];
|
|
|
|
else
|
|
|
|
return TQt::CopyROP;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
TQt::RasterOp QWinMetaFile::winToTQtRaster( long parm ) const
|
|
|
|
{
|
|
|
|
/* TODO: Ternary raster operations
|
|
|
|
0x00C000CA dest = (source AND pattern)
|
|
|
|
0x00F00021 dest = pattern
|
|
|
|
0x00FB0A09 dest = DPSnoo
|
|
|
|
0x005A0049 dest = pattern XOR dest */
|
|
|
|
static const struct OpTab
|
|
|
|
{
|
|
|
|
long winRasterOp;
|
|
|
|
TQt::RasterOp qtRasterOp;
|
|
|
|
} opTab[] =
|
|
|
|
{
|
|
|
|
{ 0x00CC0020, TQt::CopyROP },
|
|
|
|
{ 0x00EE0086, TQt::OrROP },
|
|
|
|
{ 0x008800C6, TQt::AndROP },
|
|
|
|
{ 0x00660046, TQt::XorROP },
|
|
|
|
{ 0x00440328, TQt::AndNotROP },
|
|
|
|
{ 0x00330008, TQt::NotCopyROP },
|
|
|
|
{ 0x001100A6, TQt::NandROP },
|
|
|
|
{ 0x00C000CA, TQt::CopyROP },
|
|
|
|
{ 0x00BB0226, TQt::NotOrROP },
|
|
|
|
{ 0x00F00021, TQt::CopyROP },
|
|
|
|
{ 0x00FB0A09, TQt::CopyROP },
|
|
|
|
{ 0x005A0049, TQt::CopyROP },
|
|
|
|
{ 0x00550009, TQt::NotROP },
|
|
|
|
{ 0x00000042, TQt::ClearROP },
|
|
|
|
{ 0x00FF0062, TQt::SetROP }
|
|
|
|
};
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for ( i=0 ; i < 15 ; i++ )
|
|
|
|
if ( opTab[ i ].winRasterOp == parm )
|
|
|
|
break;
|
|
|
|
|
|
|
|
if ( i < 15 )
|
|
|
|
return opTab[ i ].qtRasterOp;
|
|
|
|
else
|
|
|
|
return TQt::CopyROP;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool QWinMetaFile::dibToBmp( TQImage& bmp, const char* dib, long size )
|
|
|
|
{
|
|
|
|
typedef struct _BMPFILEHEADER {
|
|
|
|
WORD bmType;
|
|
|
|
DWORD bmSize;
|
|
|
|
WORD bmReserved1;
|
|
|
|
WORD bmReserved2;
|
|
|
|
DWORD bmOffBits;
|
|
|
|
} BMPFILEHEADER;
|
|
|
|
|
|
|
|
int sizeBmp = size + 14;
|
|
|
|
|
|
|
|
TQByteArray pattern( sizeBmp ); // BMP header and DIB data
|
|
|
|
pattern.fill(0);
|
|
|
|
memcpy( &pattern[ 14 ], dib, size );
|
|
|
|
|
|
|
|
// add BMP header
|
|
|
|
BMPFILEHEADER* bmpHeader;
|
|
|
|
bmpHeader = (BMPFILEHEADER*)((const char*)pattern);
|
|
|
|
bmpHeader->bmType = 0x4D42;
|
|
|
|
bmpHeader->bmSize = sizeBmp;
|
|
|
|
|
|
|
|
if ( !bmp.loadFromData( (const uchar*)bmpHeader, pattern.size(), "BMP" ) ) {
|
|
|
|
kdDebug() << "QWinMetaFile::dibToBmp: invalid bitmap " << endl;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// if ( bmp.save("/home/software/kde-cvs/qt/examples/wmf/test.bmp", "BMP") )
|
|
|
|
// if ( bmp.load( "/home/software/kde-cvs/qt/examples/wmf/test.bmp", "BMP" ) )
|
|
|
|
// fprintf(stderr, "Bitmap ok \n");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|